Raw Network Manipulation

 < Day Day Up > 

When using a kernel rootkit, you will typically have access to the device drivers that control the network card. This means you can read and write raw frames from and to the network. With a raw frame, you can control all parts of the protocol in other words, the parts of the communication that control routing and identification. For example, with raw frames you can control your Ethernet address (MAC address), TCP source port, and source IP address. With raw frames, you are not dependent on the infected host's TCP/IP stack. This can be useful, enabling you to better hide the source of communication. More importantly, it can allow you to bypass firewalls and IDS systems.

To get started, we cover raw packet manipulation from a user-mode program. Although this book is about kernel rootkits, we felt it would be easier for you to learn about and practice with raw packets and protocol manipulation in a user-mode program. We cover raw packet manipulation in the kernel later in the chapter.

Implementing Raw Sockets on Windows XP

For a long time, Microsoft didn't offer a raw sockets interface. This forced developers to use driver-level technology to do anything "cute" (for example, spoofing packets) with the TCP/IP stack. Now that raw sockets have been made available in Windows, rootkit authors can forge packets from user mode.

If a system is running XP service pack 2 (SP2), the functionality of raw sockets is limited. Probably in response to Internet worms, Microsoft chose to limit the power of raw sockets with SP2. If SP2 is installed, you cannot craft raw TCP frames (for example, you cannot run a SYN Scan). You can write raw UDP frames, but you cannot spoof the source address. And, SP2 makes it difficult to create a port scanner: If you attempt a full TCP-connection scan, you will be rate-limited.

Raw sockets are opened the same way ordinary sockets are they just function a bit differently. As with all sockets programs for Windows, the first step is to initialize Winsock using WSAStartup():

 WSAData wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)    {       printf("WSAStartup() failed.\n");       exit(-1);    } 

Next, you must open a socket using the socket() function. Note the use of the constant, SOCK_RAW. If this succeeds, you will now have a raw socket you can use to sniff packets and send raw packets.

 SOCKET mySocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);    if (mySocket == INVALID_SOCKET)    {       printf("socket() failed.\n");       exit(-1);    } 

Binding to an Interface

A raw socket is not operational until it has been bound to an interface. To bind, you must specify the IP address of the local interface you wish to bind to. In most cases you will want to determine the local IP address dynamically. The following code obtains the local IP address and stores it within the in_addr structure:

 // Discover Hostname/IP.    char ac[255];    struct in_addr addr;    if (gethostname(ac, sizeof(ac)) != SOCKET_ERROR)    {       struct hostent *phe = gethostbyname(ac);       if(phe != NULL)       {          memcpy(&addr,                 phe->h_addr_list[0],                 sizeof(struct in_addr));       }    } 

Once the local address has been obtained, the sockaddr structure must be initialized and the bind() call performed:

 struct sockaddr_in SockAddr; memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = addr.s_addr;    SockAddr.sin_family = AF_INET;    SockAddr.sin_port = 0;    if (bind(   mySocket, (sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)    {       printf("bind failed.\n");       exit(-1);    } 

Sniffing with Raw Sockets

To sniff, all you must do is to begin reading packets from the wire using a call to recvfrom(). In this example code, we read a maximum of 12,000 bytes into a packet. The read loop continues until the program breaks or an error occurs.

 struct sockaddr_in fromAddr;    int numBytesRecv;    int fromAddrLen = sizeof(fromAddr); for(;;) {        memset(&fromAddr, 0, fromAddrLen);        numBytesRecv = recvfrom(                                mySocket,                                myRecvBuffer,                                12000,                                0,                                (struct sockaddr *)&fromAddr, &fromAddrLen);       if (numBytesRecv > 0)       {          // Do something with the packet.       }       else       {          // recvfrom failed          break;       } } free(myRecvBuffer); 

Promiscuous Sniffing with Raw Sockets

Raw sockets will not automatically sniff all packets on the network. By default, they sniff only those packets destined for the local host. Engaging in promiscuous sniffing requires the use of an IOCTL call. Such a call can be made using WSAIoctl():

 int input_buffer; DWORD numBytesReturned; if ( WSAIoctl(mySocket,               SIO_RCVALL,               &input_buffer,               sizeof(input_buffer),               NULL,               NULL,               &numBytesReturned,               NULL,               NULL) == SOCKET_ERROR)    {       printf("WSAIoctl() failed.\n");       exit(-1);    } 

After this call, the raw socket will sniff all packets on the network, regardless of destination address. Keep in mind that on switched networks, only broadcast packets and packets destined for the local host are available. The use of a hub makes all packets available. Another option is to configure a spanned port[13] on the switch.

[13] A spanned port is a special port on a switch that can be used to sniff traffic.

In a real-world deployment of a rootkit, however, these options might not be available. If you require sniffing of a remote host on the same subnet, then ARP hijacking[14] may be one of your few options. "Etherleak" sniffing may be another.[15]

[14] ARP hijacking allows you to capture traffic over a switched network, and cause packets to be routed through a middleman host. The topic is well covered in the public domain.

[15] See O. Arkin and J. Anderson, "Etherleak: Ethernet Frame Padding Information Leakage" ( www.atstake.com/research/advisories/2003/atstake_etherleak_report.pdf

Sending Packets with Raw Sockets

Sending a raw packet is very easy using the sendto function:

 sendto(theSocket,        (char *)packet,        sizeof(struct iphdr)+sizeof(struct tcphdr)+datasize,        0,        (struct sockaddr *)theAddressP,        sizeof(struct sockaddr)); 

Now we have all the tools required to send and receive raw packets. Let's explore some of the things we can do with them.

Forging the Source

Controlling the source port can be important for firewalls. Many firewalls have special rules that allow communication if the source port is DNS, SMTP, or WWW (53, 25, or 80, respectively). Bypass rules such as these may be useful for getting data out of any network. In some cases, certain source IP addresses must be used. For example, a firewall may allow all outbound traffic from the Web server, source ports 80 and 443. Knowing this, a rootkit can be designed to forge packets with a false identity: that of the Web server. Using the correct source port and source IP, the traffic will be allowed over the firewall and out of the network.

Bouncing Packets

The last method of raw network manipulation we'll cover is that of bouncing packets, an interesting effect that can be obtained by controlling the source IP address. The rootkit can forge a source IP address that refers to an external machine one outside of the network. The forged source address can belong to a real computer controlled by a hacker somewhere on the Internet. The rootkit can send these source-forged packets to some innocent third party, such as a popular Web server. The third-party Web server then sends response packets to the forged source address the computer controlled by the hacker. This is a complicated form of bounce attack that allows a rootkit to send traffic in one direction without revealing its location.[16]

[16] Of course, sending two-way traffic would reveal the hacker's location. The target address of the one-way method is revealed by simply looking at the forged source address.

For example, a rootkit could send a TCP SYN packet with a forged source IP. The TCP SYN packet could contain covert data encoded in the initial sequence number. The third-party Web server would respond to the SYN with a SYN-ACK, placing the initial sequence number (plus one) in the response packet. Thus, a one-way communication mechanism is born.

Another effect of using bounced traffic is that you might be able to bypass firewalls. If a rootkit is installed in a very sensitive network that allows traffic from only certain trusted hosts, commands could be sent to the rootkit by bouncing off of these trusted hosts. The use of a bounce host should be managed carefully, though: Sometimes DNS will resolve to a farm of hosts, and you will unwittingly be using a whole set of bounce hosts. To avoid this problem, either use only IP addresses for your bounce host, or make sure your rootkit is aware that any of these hosts might provide bounced data. Another gotcha is that some routers and firewalls use stateful inspection, and as a result will not allow the bounce packets in or out.

In most cases, these issues will not be problems. Many so-called stateful inspection firewalls, upon detecting a bounced SYN-ACK packet, assume that a valid connection is established.

     < Day Day Up > 


    Rootkits(c) Subverting the Windows Kernel
    Rootkits: Subverting the Windows Kernel
    ISBN: 0321294319
    EAN: 2147483647
    Year: 2006
    Pages: 111

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net