无dll注入游戏拦截函数截取封包

呵呵, 都是老代码了, 我怕发霉, 现在拿出来分享下吧, 这些都只是在我的技术爱好范围内的,不汲及其它的 以前了解到的都是dll注入到游戏中才能进行函数的拦截, 后来我想这个麻烦了, 就自己琢磨了一番, 终于经过自己的努力写出来了

下面是某游戏的一个无dll注入拦的源码, 发源码前先说说他的原理吧, 其实和dll注入差不别不大, 首先我们要写一个函数用来替换要拦截的函数, 而这个函数最终只能是汇编的, 呵呵, 这里我不多作解释了, 我的作法是写成函数, 然后导出, 再利用od反汇编这到一堆的机器码

复制出来整理成一个常量数组, 用od是比较方便, 难不成自己一个对照去翻译啊, 当然也可以利用现成的反汇编引擎搞定, 呵呵, 那个不在我这次的讨论范围了

看下面,这个是一个hook函数, 其中 call push jmp几个指令后面我都以0填充了, 主要是后面动态写入的

  //最终需要跳转的代码
  JmpHookCode : array[0..35] of Byte = ($6A, $FF,                    //push -1
                                        $60,                         //pushad
                                        $8B, $44, $24, $2C,          //mov eax, dword ptr[esp + 2c]
                                        $8B, $74, $24, $28,          //mov esi, dword ptr[esp + 28]
                                        $50,                         //push eax
                                        $56,                         //push esi
                                        $E8, $00, $00, $00, $00,     //call xxxx
                                        $61,                         //popad
                                        $64, $A1, $00, $00, $00, $00,//mov eax, dword fs:[0]
                                        $68, $00, $00, $00, $00,     //push xxxx
                                        $E9, $00, $00, $00, $00,     //jmp  xxxxx
                                        $C3);                        //retn
  00401019      6A FF                push    -1  
  0040101B      60                   pushad  
  00401015      8B4424 2C            mov     eax, [dword esp+2C]  
  00401019      8B7424 28            mov     esi, [dword esp+28]  //11  
  0040101D      50                   push    eax  
  0040101E      56                   push    esi
  00401024      E8 0B240408          call    08443434             //18
  00401029      61                   popad
  0040102A      64:A1 00000000       mov     eax, [dword fs:0]    //25
  00401030      68 5840A700          push    0A74058
  00401035    - E9 0980E402          jmp     03249043             //35               

好了,下面就要下那个 call的函数, 同理写好后编译导出,然后用od打开复制机器码再整理, 照着上面的将一个指定后面时行填0

SendDataCode : array[0..51] of Byte = ($55,                       //push ebp
                                       $8B, $EC,                  //mov  ebp, esp                 ;保存堆栈
                                       $83, $C4, $F4,             //add  esp, -0C                 ;开辟 0C 大小栈空间
                                       $8B, $45, $0C,             //mov  eax, dword ptr [ebp+C]   ;将第二个参数放入eax
                                       $83, $F8, $01,             //cmp  eax, 1                   ;比较 if DataLen > 1 then
                                       $76, $20,                  //jbe  short 004AE342           ;不等于跳到结束位置
                                       $33, $D2,                  //xor  edx, edx                 ;初始化edx寄存器
                                       $89, $55, $F4,             //mov  dword ptr [ebp-C], edx   ;Data.dwData := 0;
                                       $89, $45, $F8,             //mov  dword ptr [ebp-8], eax   ;Data.cbData := DataLen
                                       $8B, $45, $08,             //mov  eax, dword ptr [ebp+8]   ;将第一个参数放入eax
                                       $89, $45, $FC,             //mov  dword ptr[ebp-4], eax    ;Data.lpData := DataPoint
                                       $8D, $45, $F4,             //lea  eax, dword ptr[ebp-c]    ;@Data
                                       $50,                       //push eax                      ;lParam
                                       $6A, $00,                  //push 0                        ;wParam
                                       $6A, $4A,                  //push 4A                       ;Msg = WM_COPYDATA
                                       $68, $00, $00, $00, $00,   //push xxxx                     ;Handle
                                       $E8, $00, $00, $00, $00,   //call SendMessageA             ;SendMessage
                                       $8B, $E5,                  //mov  esp, ebp                 ;恢复堆栈
                                       $5D,                       //pop  ebp
                                       $C2, $08, $00);            //retn 8
  004AE314 >  55              push    ebp
  004AE315    8BEC            mov     ebp, esp
  004AE317    83C4 F4         add     esp, -0C
  004AE31A    8B45 0C         mov     eax, dword ptr [ebp+C]
  004AE31D    83F8 01         cmp     eax, 1
  004AE320    76 20           jbe     short 004AE342
  004AE322    33D2            xor     edx, edx
  004AE324    8955 F4         mov     dword ptr [ebp-C], edx
  004AE327    8945 F8         mov     dword ptr [ebp-8], eax           
  004AE32A    8B45 08         mov     eax, dword ptr [ebp+8]           
  004AE32D    8945 FC         mov     dword ptr [ebp-4], eax
  004AE330    8D45 F4         lea     eax, dword ptr [ebp-C]
  004AE333    50              push    eax
  004AE334    6A 00           push    0
  004AE336    6A 4A           push    4A                               
  004AE338    68 A4000100     push    100A4                            
  004AE33D    E8 A693F5FF     call    <jmp.&user32.SendMessageA>
  004AE342    8BE5            mov     esp, ebp
  004AE344    5D              pop     ebp
  004AE345    C2 0800         retn    8
  //第37个字节开始写入四字节的句柄
  //第42个字节开始写入四字节的SendMessage函数地址 SendMessage - SendData- 42

  //汇编代码还原后的函数
  procedure SendData(DataPoint: Pointer; DataLen: DWORD);stdcall;
  var
    Data: TWMCopyDataStruct;
  begin
    if DataLen > 1 then
    begin
      Data.dwData := 0;
      Data.cbData := DataLen;
      Data.lpData := DataPoint;
      SendMessage(Handle, WM_COPYDATA, 0, Integer(@Data));
    end;
  end;

接下来我们要干嘛呢? 我们要修在目标进程中分配一埠同上面两个函数大小的内存
然后将代码写进去,,,,,,,,,, 其它的就看注释部分吧, 程序退出别记了释放先前分配的内存哦

      ReadMem(hProcess, Pointer(OldSendAddr), @Flags, 1);
      if Flags <> $E9 then  //检测当前位置标识是否为 jmp = $E9
      begin
          ReadMem(hProcess, Pointer(OldSendAddr), @OldHookCode, Length(OldHookCode));//备份代码
         //在目标进程中为自己的函数分配空间
          JmpHookFuncAddr := VirtualAllocEx(hProcess, nil, Length(JmpHookCode),  MEM_COMMIT, PAGE_READWRITE);
          MySendFuncAddr  := VirtualAllocEx(hProcess, nil, Length(SendDataCode), MEM_COMMIT, PAGE_READWRITE);
          //写入代码
          if Assigned(JmpHookFuncAddr) then
          begin
            //写入自己的处理跳转的代码
            WriteMem(hProcess, JmpHookFuncAddr, @JmpHookCode,  Length(JmpHookCode));
            //写入要CALL自己的函数地址, 并计算相对地址
            TEMP := DWORD(MySendFuncAddr) - DWORD(JmpHookFuncAddr) - 18;
            WriteMem(hProcess, Pointer(DWORD(JmpHookFuncAddr) + 14), @TEMP, 4);
            // 写入相对地址 
            ReadMem (hProcess, Pointer(OldSendAddr + 9), @TEMP, 4);
            WriteMem(hProcess, Pointer(DWORD(JmpHookFuncAddr) + 26), @TEMP, 4);

            //写入处理完成后要跳转的代码
            TEMP := (OldSendAddr - DWORD(JmpHookFuncAddr) - 35) + $D;
            WriteMem(hProcess, Pointer(DWORD(JmpHookFuncAddr) + 31), @TEMP, 4);
          end;
      
          if Assigned(MySendFuncAddr) then
          begin
            //写入自己的处理函数代码
            WriteMem(hProcess, MySendFuncAddr,  @SendDataCode, Length(SendDataCode));
            //写入当前句柄
            TEMP := Handle;
            WriteMem(hProcess, Pointer(DWORD(MySendFuncAddr) + 37), @TEMP, 4);
            //写入SendMessage函数地址
            SendMsg := GetFuncAddr('SendMessageA');
            TEMP := DWORD(SendMsg) - DWORD(MySendFuncAddr) - 46;
            WriteMem(hProcess, Pointer(DWORD(MySendFuncAddr) + 42), @TEMP, 4);
          end;

          //这里开始完成改写跳转代码让函数跳到我自己的函数内来
          //inline hook
          B := $E9;
          WriteMem(hProcess, Pointer(OldSendAddr), @B, 1);
          //写入自己的函数
          TEMP := DWORD(JmpHookFuncAddr) - OldSendAddr - 5;
          WriteMem(hProcess, Pointer(OldSendAddr + 1), @TEMP, 4);
          //写入nop
          B := $90;
          WriteMem(hProcess, Pointer(OldSendAddr + 5), @B, 1);

          IsHook := True;
      end;
 

至此我们就剩下使用wm_copydata接收发送过来的数据, 是不是很爽啊

转载于:https://my.oschina.net/ying33/blog/1575650

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值