NDIS 修改数据包,拦截URL

见习学术士 2011-07-12 03:18:24
想实现:本机输入www.baidu.com 拦截后显示,This page is restricted by xiaoc!


下面这个函数就是在MPSend 和 MPSendOnePacket 调用后修改数据包的。
修改完后就会调用NdisSend发送,运行结果是输入www.baidu.com 后无法找到该页
不知道错在哪里?还有如何知道效验值check的正确性?


void FilterHttpRequest(PUCHAR p)
{
__u32 u32temp;
__u16 u16temp;
struct psdhdr ph; /* pseudo header declaration */


//////////////////////////SENDING BLOCK PAGE TO CLIENT//////////////////////////

// Use the first 40 bytes of m_pBlockBuffer for future TCP control packet transmission.
char* pBlockBuffer;
struct iphdr* respIpHdr;
struct tcphdr* respTcpHdr;
char* pTcpData;
unsigned int dsize;
//DbgBreakPoint();

respIpHdr = (struct iphdr*)(p + sizeof(struct ethhdr));
respTcpHdr = ((struct tcphdr*)((char*)respIpHdr + sizeof (struct iphdr)));
pTcpData = (char*)respIpHdr + sizeof(struct iphdr) + sizeof(struct tcphdr);

NdisAllocateMemoryWithTag(&pBlockBuffer, 512, TAG);
NdisZeroMemory(pBlockBuffer, 512);
sprintf(pBlockBuffer,
"%s",
"<html>"
"<head>"
"<title>HTTPFilter block page</title></head><body><TABLE height=\"100%\" width=\"100%\">"
"<TR>"
"<TD align=\"center\"><h1>This page is restricted by xiaoc!</h1>"
"</TD>"
"</TR>"
"</TABLE>"
"</body>"
"</html>\n\n\n"
);

dsize = Xc_strlen(pBlockBuffer, '\0');

NdisZeroMemory(pBlockBuffer, 512);


sprintf(pBlockBuffer,
"HTTP/1.1 200 OK\r\n"
"Content-Type: Text/HTML\r\n"
"Connection: close\r\n"
"Content-Lenght: %d"
"\r\n\r\n"
"%s",
dsize,
"<html>"
"<head>"
"<title>HTTPFilter block page</title></head><body><TABLE height=\"100%\" width=\"100%\">"
"<TR>"
"<TD align=\"center\"><h1>This page is restricted by xiaoc!</h1>"
"</TD>"
"</TR>"
"</TABLE>"
"</body>"
"</html>\n\n\n"
);

dsize = Xc_strlen(pBlockBuffer, '\0');
DbgPrint("[xiaoc httpfiter] block info : %s", pBlockBuffer);

NdisZeroMemory(pTcpData, XC_ntohs(respIpHdr->tot_len) - sizeof(struct iphdr) - sizeof(struct tcphdr));
NdisMoveMemory(pTcpData, pBlockBuffer, dsize);


DbgPrint("[xiaoc httpfilter] FilterHttpRequest debug 1");


respIpHdr->check = 0;

u32temp = respIpHdr->daddr;
respIpHdr->daddr = respIpHdr->saddr;
respIpHdr->saddr = u32temp;
respIpHdr->tot_len = XC_htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + dsize);

respIpHdr->id = XC_htons((__u16)2);
respIpHdr->frag_off = 0;
respIpHdr->protocol = 0x06;

respIpHdr->check =
CalcIPSum((__u16*) respIpHdr, sizeof(struct iphdr));



u32temp = respTcpHdr->ack_seq;
respTcpHdr->ack_seq = XC_htonl (XC_htonl (respTcpHdr->seq) + dsize);
respTcpHdr->seq = u32temp;
u16temp = respTcpHdr->source;
respTcpHdr->source = respTcpHdr->dest;
respTcpHdr->dest = u16temp;
respTcpHdr->ack = 1;
respTcpHdr->fin = 1;
//SET_TCP_OFFSET(respTcpHdr, 0x5);
//SET_TCP_X2(respTcpHdr, 0x0);
respTcpHdr->urg = 0;


ph.sourceip = respIpHdr->saddr;
ph.destip = respIpHdr->daddr;
ph.mbz = 0;
ph.ptcl = 0x06;
ph.plen = XC_htons((__u16)(sizeof (struct tcphdr) + dsize));
respTcpHdr->check = 0;

respTcpHdr->check =
CalcTCPSum((__u16 *)&ph,
(__u16 *)respTcpHdr,
sizeof(struct tcphdr) + dsize);

if( pBlockBuffer )
{
NdisFreeMemory(pBlockBuffer, 512, 0);
}

}
...全文
1655 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
见习学术士 2011-07-14
  • 打赏
  • 举报
回复
还是没有成功,结了吧。
见习学术士 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ndy_w 的回复:]
处理的时候把原来的包放过去,如果需要过滤再多发一个你的修改包,这样TCP应该能连接上。
[/Quote]
试试。


[Quote=引用 9 楼 vincent_1011 的回复:]
重定向到本地不是那么容易的
[/Quote]
有什么好办法?
vincent_1011 2011-07-13
  • 打赏
  • 举报
回复
重定向到本地不是那么容易的
ndy_w 2011-07-13
  • 打赏
  • 举报
回复
处理的时候把原来的包放过去,如果需要过滤再多发一个你的修改包,这样TCP应该能连接上。
见习学术士 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ndy_w 的回复:]
Dns完成后,client发syn包连接,server回复的syn/ack/psh应该不满足你的过滤条件;不过client再ack/psh就被滤了,三次握手没完成。
如果简单地根据IP/PORT滤包,TCP连不上,过滤可以实现,你自己的html内容也就不能被上层收到。
你的条件是目的端口=HTTP,这个时候过滤会把HTTP请求替换,这个有点问题。
感觉你想做的是TCP欺骗,要允许TCP连接上……
[/Quote]

要这么麻烦吗,我是这样做的:
检测到发送http数据包包含我指定的URL(我先内定了baidu),那就将IP包中的源、目的地址互换:
u32temp = respIpHdr->daddr;
respIpHdr->daddr = respIpHdr->saddr;
respIpHdr->saddr = u32temp;
respIpHdr->tot_len = XC_htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + dsize);

TCP包的 ack_seq 和 seq 替换, 源端口目的端口替换
respTcpHdr->ack_seq = XC_htonl (XC_htonl (respTcpHdr->seq) + dsize);
respTcpHdr->seq = u32temp;
u16temp = respTcpHdr->source;
respTcpHdr->source = respTcpHdr->dest;
respTcpHdr->dest = u16temp;

再替换TCP的数据内容(既我要返回的HTTP数据包内容),计算IP->check tcp->check
再发送出去。。



我是根据这个应用层的例子来挪到NDIS层来的
HTTPFilter_src.zip



ndy_w 2011-07-13
  • 打赏
  • 举报
回复
Dns完成后,client发syn包连接,server回复的syn/ack/psh应该不满足你的过滤条件;不过client再ack/psh就被滤了,三次握手没完成。
如果简单地根据IP/PORT滤包,TCP连不上,过滤可以实现,你自己的html内容也就不能被上层收到。
你的条件是目的端口=HTTP,这个时候过滤会把HTTP请求替换,这个有点问题。
感觉你想做的是TCP欺骗,要允许TCP连接上,但是要伪造服务器返回的内容。这样的话,你要自己写类似TCP控制块的东西,记录要欺骗的连接,并修改内容,要注意!sequence number需要伪造不能错!
简单一点,判断是HTTP请求指定站点,记录TCP控制块;一旦该连接建立,就冒充服务器生成一个包(包含HTTP头和HTML),然后断开TCP,释放控制块。也够烦的。
见习学术士 2011-07-13
  • 打赏
  • 举报
回复
packet1


packet2


packet3
见习学术士 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 oyljerry 的回复:]
用抓包工具等查看一下你过滤的数据包等是否正确
[/Quote]

图packet1是 我输入www.baidu.com 后发送出去的IP包列表


图packet2是 包含发送出去的IP包详情


图packet3是 我修改后的数据包


在图packet1中可以看到一直再重发数据包,不知道是哪里错了,还有列表那里显示的数据包长度修改前和修改后是一样的。。郁闷

见习学术士 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ndy_w 的回复:]
无法找到该页:TCP的SYN/ACK包没有收到。是不是根据IP过滤的?
[/Quote]
是的,检测到HTTP包就进行过滤



FILTER_STATUS DecodeTCP(PUCHAR pData)
{
struct tcphdr* pTCPHead;
struct iphdr* pIpHead;
char* pTCPData = NULL;
int datalen = 0;
int tcphdrlen = 0;
__u16 nSrcPort;
__u16 nDesPort;
struct psdhdr psd_header;
pIpHead = (struct iphdr*)(pData + sizeof(struct ethhdr));
pTCPHead = (struct tcphdr*)((char*)pIpHead + pIpHead->ihl*4);
nSrcPort = XC_ntohs(pTCPHead->source);
nDesPort = XC_ntohs(pTCPHead->dest);
tcphdrlen = XC_ntohs(pIpHead->tot_len) - sizeof(struct iphdr);
pTCPData = (char*)pIpHead + sizeof(struct iphdr) + sizeof(struct tcphdr);
DbgPrint("[xiaoc httpfilter] sport = %u, dport = %u, psh = %d, ack = %d",
nSrcPort, nDesPort, pTCPHead->psh, pTCPHead->ack);
if( pTCPHead->psh == 1 && pTCPHead->ack == 1 )
{
DbgPrint("[xiaoc httpfilter] DecodeTCP psh | ack");
if( nDesPort != 80 && nDesPort != 8080 )
{
return STATUS_PASS;
}
return DecodeHTTP(pTCPData, tcphdrlen, pData);
}
return STATUS_PASS;
}

FILTER_STATUS DecodeHTTP(__u8 * pkt, const __u32 len, PUCHAR p)
{
DbgPrint("[xiaoc httpfilter] DecodeHTTP");
if (CheckHttpState(pkt, len) == CLIENT_REQUEST)
{
int matched_idx = 0;
if (CheckPattern(pkt, len, &matched_idx))
{
DbgPrint("[xiaoc httpfilter] ban page");
/* packet caught, Filter it */
FilterHttpRequest(p);
DbgPrint("[xiaoc httpfilter exec FilterHttpRequest finished!" );
return STATUS_MODIFY;
}

}
return STATUS_PASS;
}
oyljerry 2011-07-13
  • 打赏
  • 举报
回复
用抓包工具等查看一下你过滤的数据包等是否正确
ndy_w 2011-07-13
  • 打赏
  • 举报
回复
无法找到该页:TCP的SYN/ACK包没有收到。是不是根据IP过滤的?

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧