ndis 修改

场景:NDIS 修改数据包,拦截URL解决方法

NDIS 修改数据包,拦截URL
想实现:本机输入www.baidu.com 拦截后显示,This page is restricted by xiaoc!


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

C/C++ code

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);
    }

}



------解决方案--------------------
无法找到该页:TCP的SYN/ACK包没有收到。是不是根据IP过滤的?
------解决方案--------------------
用抓包工具等查看一下你过滤的数据包等是否正确
------解决方案--------------------
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,释放控制块。也够烦的。

------解决方案--------------------
处理的时候把原来的包放过去,如果需要过滤再多发一个你的修改包,这样TCP应该能连接上。
------解决方案--------------------
重定向到本地不是那么容易的