用HOOK方法获取MSN收发的数据包.已经成功获得了正常聊天时的所有控制信息与MSG信息.但是当对方发送过来的数据包超过512字节时候,只能获得512字节长度的数据.然而我们在平时MSN聊天的时候,是可以接收到超过512字节的信息的.  程序大致实现如下:
 
  HOOK_SEND(SOCKET s, char* buf, int len, int flag)
{
    WaitForSingleObject(g_hSendEvent, INFINITE);
    WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)g_pSend,(void*)        g_dwOldBytesSend[0], sizeof(DWORD)*2, NULL);    /*.......将buf内容写到文件的代码,省略.........*/
    send(s, buf, len, flag);
}// 没有任何问题,在MSN客户端发送信息允许长度范围内的信息全部可以正确捕获HOOK_RECV(SOCKET s, char* buf, int len, int flag)
{
    WaitForSingleObject(g_hRecvEvent, INFINITE);
    WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)g_pRecv, (void*)g_dwOldBytesRecv[0], sizeof(DWORD)*2, NULL);

    memset(buf, 0, len);
    nRet = recv(s, buf, len, flags);    /*.......将buf中的内容写到文件的代码,省略........*/
}// 当MSN客户端接收的信息长度(包括消息头)超过512字节的时候,超过512字节的内容全被丢弃了.小于512字节的内容正确捕获我跟踪了两个函数中参数LEN的大小,发现SEND中LEN的大小随发送信息的长度变化,而RECV中LEN的值一直是512.不理解MSN的客户端在处理超过512字节的信息时是怎样做的,MSN的协议中似乎也没有讲到.有知道的高手请指点一下迷津,多谢.

解决方案 »

  1.   

    另外,帖中贴出的代码做了很多简化,下面给出其中一些未做说明的宏和变量的说明
    g_hSendEvent = CreateEvent(NULL, FALSE, TRUE, NULL);//事务,解决send函数同步问题
    g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL);//事务,解决recv函数同步问题#define INFINITE                0xFFFFFFFF  // Infinite timeout
    #define INVALID_HANDLE_VALUE   (HANDLE)-1DWORD g_dwOldBytesSend[2][2] = {0x0, 0x0, 0x0, 0x0};//保存原MSN的API入口的8个字节
    DWORD g_dwOldBytesRecv[2][2] = {0x0, 0x0, 0x0, 0x0};//保存原MSN的API入口的8个字节DWORD g_pSend = 0; //MSN客户端API中send函数的地址
    DWORD g_pRecv = 0;                   //MSN客户端API中recv函数的地址所有的变量已经在DLL入口中正确赋值或初始化.功能已经基本实现,我相信唯一的问题来自与RECV的时候对512字节以上数据的处理,可惜我不知道MSN客户端程序是怎么处理的.望大侠们给予指教,不胜感激
      

  2.   

    这里的len应该是接受缓冲区的大小, 超过len应该就把剩余的data 放到下一次recv调用里去了
      

  3.   

    回AlanChenBoy(Alan) 问题是我在下一次的RECV调用里面的BUF中仍然找不到丢掉的数据,而是对方新发过来的数据.
      

  4.   

    感觉应该是有后续的包没有截到,如果说下一次的RECV调用是对方发来的新数据,那么很有可能一个RECV把大于512的数据分开大包传送了~
      

  5.   

    回 kofts(我自横刀向天笑,去留肝胆两昆仑)谢谢你的回复,我也一直有这种怀疑.但是我的程序应该HOOK到MSN客户端中每一次对RECV函数的调用,所以即使有分开的数据包,也不应该漏掉的啊.或者哪为高手知道MSN客户端在这种情况下的处理方法,或者能写一个简单的HOOK_RECV可以获得完整数据包的?先谢过了,公司任务逼得比较急.
      

  6.   

    DWORD g_dwOldBytesSend[2][2] = {0x0, 0x0, 0x0, 0x0};//保存原MSN的API入口的8个字节
    DWORD g_dwOldBytesRecv[2][2] = {0x0, 0x0, 0x0, 0x0};//保存原MSN的API入口的8个字节DWORD g_pSend = 0; //MSN客户端API中send函数的地址
    DWORD g_pRecv = 0;                   //MSN客户端API中recv函数的地址send()
    recv()
    你的HOOK程序中怎么是三套函数地址啊???它们什么关系?
    一般HOOK API只有新旧两套地址吧??
      

  7.   

    对不起,jovia() 上面的帖子写急了,忘了说明
    g_pSend = (DWORD)GetProcAddress(hWsockSend, "send");
    g_pRecv = (DWORD)GetProcAddress(hWsockRecv, "recv");呵呵,现在是两套了吧.
      

  8.   

    HOOK_RECV(SOCKET s, char* buf, int len, int flag)
    {
        WaitForSingleObject(g_hRecvEvent, INFINITE);
        WriteProcessMemory(INVALID_HANDLE_VALUE, (void*)g_pRecv, (void*)g_dwOldBytesRecv[0], sizeof(DWORD)*2, NULL);

        memset(buf, 0, len);
        nRet = recv(s, buf, len, flags);    /*.......将buf中的内容写到文件的代码,省略........*/
    }
    是不是在处理顺序上有点问题?
    HOOK_RECV(SOCKET s, char* buf, int len, int flag)的参数中是不是已经含有接收到的数据了?
    你跟踪一下buf中的内容吧,看看你接收到的内容是不是消息开头的512个字节?如果不是的话,就说明处理顺序可能有问题了。
      

  9.   

    其实重点不在于如何HOOK到,因为已经实现了,重点是RECV的长度,从跟踪的情况来看,MSN的API中一次也是接收512字节,可是却不知道剩下的字节到哪里去了
      

  10.   

    回jovia()可以明确保证BUF中的内容就是消息开头的512个字节.
      

  11.   

    哦 :)看来只能帮你乱顶一下了 。如果把 nRet = recv(s, buf, len, flags);
    中的len值人为设定为比512更大的数值,会如何呢?一样也接收不到更多的数据吗?
      

  12.   

    jovia() 那样会覆盖掉不可写的内存,造成MSN客户端崩溃,这个已经试验过多次了.......
      

  13.   

    不知道MSNSHELL这样的软件在处理这个问题的时候是怎么做的,对MSNSHELL调用的动态库进行分析,可以肯定他们也用了HOOK技术来捕获MSN的数据包
      

  14.   

    http://www.donews.net/zwell/archive/2004/08/31/84513.aspx
    //------------------------------------------------------------------------
    // 由于要截获两个库里面的函数,所以每个函数定义了两个HOOK结构
    // 在编程过程中因为没有考虑到这个问题,导致很多包没有截获到,
    // 后来想到了冰哥在模仿SOCKCAP的程序中每个函数截了两次才明白
    // 一个是wsock32.dll, 一个是ws2_32.dll
    //------------------------------------------------------------------------
     
    不知道MSN会不会也是这种情形,你把两个库都HOOK一下试试吧
    :)希望好运吧!
      

  15.   

    感谢jovia(),我将用你说的方法再试验一下.
      

  16.   

    http://www.donews.net/zwell/archive/2004/08/31/84513.aspx
    //------------------------------------------------------------------------
    // 由于要截获两个库里面的函数,所以每个函数定义了两个HOOK结构
    // 在编程过程中因为没有考虑到这个问题,导致很多包没有截获到,
    // 后来想到了冰哥在模仿SOCKCAP的程序中每个函数截了两次才明白
    // 一个是wsock32.dll, 一个是ws2_32.dll
    //------------------------------------------------------------------------
     
    不知道MSN会不会也是这种情形,你把两个库都HOOK一下试试吧
    :)希望好运吧!
    试过了,不行.MSN只调用wsock32.dll中的recv.
    还是感谢你!
      

  17.   

    这个缓冲是从MSN中HOOK过来的,不是我想弄大就弄大的.....而且我另申请大缓冲区来接收数据也只能接到512字节以下的数据包,一旦收到的数据超过512字节反而会让MSN客户端崩掉.....实在怪异.现在我是到处找也找不到丢掉的数据被放到哪里去了....但肯定接收到了...
      

  18.   

    先用Ethereal抓包看看能否成功
      

  19.   

    我做过用 底层 socket 抓所有的IP包,然后分析MSN协议 。  好象不存在这样的问题。
    如果数据太长, 根据MSN协议把数据并起来。  加上杂收, 就能在内网上所有MSN通信的
    内容。  这个比较变态。
      

  20.   

    恩,我试过如果抓取所有IP包再根据协议来分析MSN包的确不存在这样的问题.我现在主要目的是想弄清楚MSN的客户端程序里是怎么实现的.Ethereal我也用过了,超过512字节的包也是正常接收,没有分包,没有压缩,没进行任何处理.所以我肯定信息分包处理在客户端程序接收部分中实现的.真是变态的微软...既然发包的时候不分包,接收的时候干嘛要分成一块块的接....而且还让人找不到其余的包去哪了...
      

  21.   

    还是想用HOOK来做.....不然很憋气