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

来源:互联网 发布:matlab bp算法 编辑:程序博客网 时间:2024/06/16 23:47

呵呵, 都是老代码了, 我怕发霉, 现在拿出来分享下吧, 这些都只是在我的技术爱好范围内的,不汲及其它的

以前了解到的都是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接收发送过来的数据, 是不是很爽啊


0 0
原创粉丝点击