自己修改 WS2_32 中的send函数, (通过浩方平台联网)
具体方法是 修改前 5个字节跳到 自己的Mysend中。 用互斥来防止多线程出现的问题。 可以说里面什么都没做。
但只要已进入别人的房间,就崩溃。。
// 互斥信号量
HANDLE hMutex = NULL;
typedef int(*PFunSend)( SOCKET, const char FAR *, int , int);   // send 函数指针
PFunSend pSend;int MySend( SOCKET s, const char FAR *buf, int len, int flags )
{
// 进入缓冲区
WaitForSingleObject( hMutex, INFINITE ); // 改回源地址地址
int nTmp = 0;
for(nTmp = 0; nTmp < nSize; nTmp ++)
pFuncAddr[nTmp] = uszBuf[nTmp]; // 调用原函数
pSend = (PFunSend)pFuncAddr;
nTmp =  pSend(s, buf, len, flags ); // 改成本地地址
pFuncAddr[0] = 0xE9;
*(PDWORD)&pFuncAddr[1] = dwSrcOffset; ReleaseMutex(hMutex); return nTmp;
}我也很想自己解决这个问题, 但是 自己调试了好长时间, 而且自己写的多线程调用 + 更改IAT表的测试例子 一点问题都没有。故在此求救

解决方案 »

  1.   

    其中 dwSrcOffset ,uszBuf 是两个存储 jmp 相对偏移量的DWORD 和 send 地址中内容的UCHAR数组.通过加MessageBox 可以肯定 是能够进入 MySend中的。
      

  2.   

    将MessageBox放在 ReleaseMutex(hMutex); 后面时可以肯定的是 消息框弹出来 n次。。应该说我 hook成功了,  崩溃是怎么回事呢?
      

  3.   

    你试一下不用恢复原函数,弄一个stub的方法的inline hook
      

  4.   

    stub 不好意思不太懂 什么是stub 
      

  5.   


    之前就是这种方法, 在xp虚拟机下测试得好好的, 10个线程 调用 都没问题,回到win7下, 内存不可写。。
    今天请教了一下, 貌似win权限更强了,   好像是不允许EIP指向数据区, 得给数组加权限
    但是还面临一个问题。。 由于要占用5个字节, 难免会把 系统库中的 send函数 中某条执行给破坏掉,,而且E9 很有可能跟其他数据 结合成为其它指令,, 所以 今晚上回去时得好好调试一下
      

  6.   

    如果要运行时动态产生代码,应该分配PAGE_EXECUTE_READWRITE内存,把备份的代码放到那里,否则如果开了数据执行保护,PAGE_READONLY,PAGE_READWRITE等不可执行
    send的前五字节包含完整的指令,因此可以先把原来的指令备份,如果要调用原来的函数,先执行备份的,再跳回去e9只会和后面4字节结合,保证后面四字节是正确的偏移量即可
      

  7.   

    又调试了一晚上, 关键跳转还是不行。直接上代码吧。
    // 全局变量
    unsigned char uszBufStore_Send[20] = {0};
    int nByteSize_Send = 5;
    unsigned char* pFuncAddr_Send = NULL;
    typedef int (*PFunSend)(SOCKET, const char FAR *, int , int);
    PFunSend pSend;// 修改IAT表后的函数
    int WINAPI MySend( SOCKET s, const char FAR *buf, int len, int flags )
    {
    *(char*)(buf + 36) = 0x45; // TODO: 已经删除掉了互斥改回源send的代码 // 调用原函数
    return pSend(s, buf, len, flags );
    }
    dll开始的时候要执行下面程序: 对无关紧要的做出了删改 FARPROC fp = GetProcAddress(hLibrary, "send");
    pFuncAddr_Send = (unsigned char *)fp;

    // 复制一份副本到数组
    for (int i = 0; i < nByteSize_Send; i ++)
    uszBufStore_Send[i] = pFuncAddr_Send[i]; DWORD dwSrcAddr = (DWORD)(pFuncAddr_Send + 5);  // 源地址要加上五个字节
    DWORD dwDesAddr = (DWORD)MySend;
    dwSrcOffset = dwDesAddr - dwSrcAddr; // 获取原来进程的属性
    hProcess = ::GetCurrentProcess(); if (VirtualProtectEx(hProcess, (LPVOID)pFuncAddr_Send, nByteSize_Send + 2, PAGE_EXECUTE_READWRITE, &dwOldProtectCodeSeg))
    {
    fprintf(pFile, "代码段可写\r\n");
    pFuncAddr_Send[0] = 0xE9;
    *(PDWORD)&pFuncAddr_Send[1] = dwSrcOffset; if (!VirtualProtectEx(hProcess, (LPVOID)uszBufStore_Send, 20, PAGE_EXECUTE_READWRITE, &dwOldProtectDataSeg))
    {
    fprintf(pFile, "数据段不可执行可写 关闭程序, 改回原属性\r\n");
    EndCokeHouse(hModule);   // 关闭
    return;
    }
    else
    {
    fprintf(pFile, "数据段属性修改完毕,进行增加跳转到代码段代码\r\n");

    DWORD dwDataSegmentAddr = (DWORD)(uszBufStore_Send + nByteSize_Send + 6);
    DWORD dwDataSegmentOffset = dwSrcAddr - dwDataSegmentAddr; uszBufStore_Send[nByteSize_Send] = 0x90;  // 空操作
    uszBufStore_Send[nByteSize_Send + 1] = 0xe9; 
    *(PDWORD)&uszBufStore_Send[nByteSize_Send + 2] = dwDataSegmentOffset; pSend = (PFunSend)(void*)uszBufStore_Send;
    }
      

  8.   

    我有一个做好了的inline hook,对这些问题有专门处理,不过是delphi的,你是否需要?
      

  9.   

    上述代码用 OD  静态分析,  是能够正确跳转的, 但是 一旦加入别人的房间,就崩溃了貌似是堆栈不平衡,, 但是我实在想不出来该怎么搞了。。 上OD图片
      

  10.   

    每张图表示一个模块的跳转
    原始sendMySend中
    数据段数组中
      

  11.   

    少了一张hook的地址, 感觉完全都正确,  貌似就是堆栈平衡的问题
      

  12.   

    百度吃了你的图们 /:^]。这个怎么没加__stdcall?
    typedef int (__stdcall *PFunSend)(SOCKET, const char FAR *, int , int);而且想要在data段里执行代码时,也应该先修改下data段的属性为可执行吧。
    VirtualProtect ( (hProcess, (LPVOID)uszBufStore_Send, nByteSize_Send + 2, PAGE_EXECUTE_READWRITE, &dwOldProtectCodeSeg));//就好希望有帮助
      

  13.   

    楼上的哥们,  我有给数据区加上可读可写可执行的代码啊
    而且我已经排列组合试过 加过各种 WINAPI了,  考虑到堆栈平衡,又都给去掉了。。
    堆栈平衡,真是很难搞啊。。
    send api 应该是 __stdcall 自动清栈, 那么send后面一定有清栈的代码
    MySend 应该是 __stdcall 自动清栈,, 但是
    数组中 的调用也要自动清栈吗》?  数组中可是要跳回 send中去得。。 那么 就可以直接运行send的清栈代码了不对吗?
      

  14.   

    hook 找个类,用吧.方便,不出错. hook send. 就要注意自己的send和系统的send,别包搞混了.就行了.
      

  15.   

    奇怪了, 同样的代码,我拿到公司来, 都改成 __stdcall的情况, 我hook  腾讯的rtx上去了,而且没崩溃,,但是为什么在 war3?崩溃了??? 难道是浩方????难道是浩方????
      

  16.   

    你再钩一下其他的,或者检测一下浩方有没有进行hook
      

  17.   


    恐怕我得hook send后面几个字节了。 初步的想法,,,难度还真超过自己想象啊,   堆栈平衡一道大坎 要越过
      

  18.   


    是啊, 我在纸上一个一个push 一个一个pop, 的记录,  发现也是对的啊。 所以我开始怀疑我自己。于是 精神崩溃
      

  19.   

    唉。简直就是悲剧,, 今天一天都没干公司的活, 老大不在把同事一个聊天室 hook了一下, 所有东西都出来了没问题。。 在MySend中更改它的数据也可以把rtxhook一下, 数据也出来了, 但是无法解析  于是输入大量的1来填补测试 结果居然没发现有一个一样的数据。真悲剧。还有什么可以hook呢??
      

  20.   

    唉, 你们说浩方是不是也是 hook 来 把本地数据包改成远程数据包的, 所以我跳到浩方hook后的代码段了,,所以跳乱了。
    但是也不能啊,我在一开始写的代码
    互斥
    改回send的地址
    调用send
    改成MySend的地址
    互斥结束这个流程不会错啊,, 真的不知道浩方到底有没有改什么东东,,, 
      

  21.   

    把send的代码显示出来看一下不就知道了
      

  22.   

    用IAT HOOK,直接修改IAT里的send地址,你都写的是这个send的wapper了。
    IAT hook不更好 /;^]
      

  23.   


    我还以为我的这种方法 就是 修改IAT呢?? 难道不是吗??谢谢楼上哈, 这几天辛苦你了。。
      

  24.   

    你的方法叫inline hook,比iat hook有效,但稳定性差一些
      

  25.   


    哦,这样啊, 看来我得去查查啥叫 IAT hook, 我还以为我的方法就是呢。。
    我在外面有个先给你分的帖子, 你去恢复一下把
      

  26.   

    不知道是浩方问题还是多线程问题,, 总之就是崩溃。。 但是今天到家里 hook了一下  qq, 飞信。 都没问题  qq咋一看解析不了。。飞信居然都是明文。上图
      

  27.   

    顺便补上 上面被百度吞掉的4张图片。正常的send
    hook之后的send
    MySend中
    数组中
      

  28.   

    你试一下用scas指令搜索包含send地址的内存,然后改掉
      

  29.   

    要确保一个问题 hook操作发生在ws2_32.dll加载这后
    这是程序很可能正在执行你替换那5个字节 此时被换掉 可能会使程序崩溃
    尽量能让程序在联网直接完成hook操作
      

  30.   

    看了半天OD调试什么都是对的,那是什么地方堆栈不平衡了?带着OD跑一下试试,把出错的截图也发出来看下.另外把MySend改成naked调用约定然后直接跳到MySend上,执行完调回去试试另外int可能用的是两字节标准的形式,而非四字节,可以解释MySend中只恢复10字节
      

  31.   

    另外stonexing5说可能是执行时替换应该是不会的,因为只有在进入房间时才挂掉,之前已经替换好并且Send过很多次了.说到这里我觉得可能浩方再次inline了send,然后写的地方稍微偏着几个字节把lz你的指令给破坏了,有这个可能性,仔细跟踪下看看.
      

  32.   

    哈哈,你这个怎么会是IAT HOOK :P
    IAT HOOK是在内存中,自己解析PE头,然后通过PE头获得要HOOK的目标模块IAT表的里对应API指针的位置,接着在要HOOK的目标DLL的EAT表的位置,修改EAT表里API指针的值。不过你的问题是出在
    call [pSend]
    add esp, 0x10
    retn 0x10这个ws2_32.dll里的send,它自己的返回就是
    retn 0x10
    不是默认的__cdecl调用类型的,即不用你手动
    add esp, 0x10 平衡堆栈。
    定义pSend这个函数指针的类型为__stdcall就好 /:^}
      

  33.   

    嗯, 谢谢 解答,,, 刚看场电影, 这两天睡眠不足,  准备调试一次就睡了  我也是今天才知道, 原来已经启动的进程能够用od调试 所以尝试一下,, 也觉得是浩方inline hook了。。
    话说你们谁去 上海高速rpg砖房  建立一个 挂机地图去。?
      

  34.   

    你用调试器看一下运行后的send函数的代码是什么
      

  35.   

    这就是 我这段时间inline hook 失败的原因。。浩方啊, 浩方, 让我内牛满面啊。。
    当我的inline hook 上去后 直接 返回 int 3 了, 能不崩溃吗。
      

  36.   

    这下我是真的不知道该怎么做了
    hook 后面5个字节固然是可以的, 但是这样做未必会达到我的目的, 因为 浩方已经在 前5个字节把数据包发出去了,, 我后面再更改也没用了。
      

  37.   

    你的图的意思是 jmp FNWar3,100044D3是浩方的hook?如果是这样,你在备份浩方的指令时要调整e9后的位移。或者不使用inline hook,使用搜索并更改地址的hook方式。
      

  38.   

    哈哈。你可以HOOK的浩方的hook router啊 /;^]把 0xe9后面jmp过去的地址计算出来,然后过去修改浩方hook router的前5个字节。
      

  39.   


    你说的不失为一种方法, 但是我想尝试 hook  send的 父调用试试, 看看父调用中有没有发送的包数据。。
      

  40.   


    有点不太明白你的意思你指的是 hook 5到10 的字节吗?
    我觉得  在浩方上 send函数的作用只是 给 浩方自己的函数传递参数而已 而 hook 浩方自己的函数我无从下手。。 所以就考虑 hook 上一级函数。。
      

  41.   

    你先说为什么直接hook前5字节不行,我觉得问题出在备份的指令
      

  42.   


    整理了一下思路, 发现是这样的流程:
    1. 浩方启动war3  (send值正常)
    2. 我注入的dll更改 send 到达 Mysend( jmp到我的mysend)
    3. 进入房间, 调用send
    4. 浩方改掉 send , 改成它的 内容
    5. 跳转到int 3, 退出。。 
      

  43.   

    你先试试什么都不动看看浩方怎么hook的,然后才能找对策啊
      

  44.   


    呵呵, IAT 不会啊, 正在看 PE文件结构。我觉得我应该下载一个钩子库试一下, 不过我还是觉得一开始底层一点 好处多多。。你经验很丰富啊。。 经常做这个吗?
      

  45.   

    仅靠自己把所有的hook方式实现一遍,就熟了
      

  46.   

    魔兽3单机,没有开平台,hook send失败 进入别人房间或别人进入我的主机都会报错