无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
- 无dll注入游戏拦截函数截取封包
- 无DLL注入(函数直接注入)
- 无DLL注入(函数直接注入)
- 无DLL注入(函数直接注入)
- SPI拦截网络封包(DLL篇)
- 游戏封包的截取(1)-
- 游戏封包的截取(2)
- WIN32注入(无dll)
- vc 无dll注入
- DLL注入和API 拦截
- DLL注入和API拦截
- DLL注入和API拦截
- dll注入与API拦截
- DLL注入和API拦截
- 转贴:利用VB远线程注入技术实现键盘拦截的例子(无DLL)
- 利用VB远线程注入技术实现键盘拦截的例子(无DLL)
- 函数钩子-Dll注入
- CreateProcess启动游戏注入DLL
- 安装虚拟机报错解决办法 TheVMware Authorization Service is not running
- 关于热血传奇actor绘制的分析与思考
- linux yum命令详解
- 五彩趣味运动会的起源与发展
- Struts2+Hibernate+Spring整合
- 无dll注入游戏拦截函数截取封包
- HashSet和TreeSet的相关总结和整理
- 项目启动时报错:Unsupported major.minor version 51.0
- Oracle获取系统时间及格式化
- Karp的21个NPC问题及其规约
- LA 3027 Corporative Network
- 关于Linq使用过程中遇见的一些小问题的总结
- java堆栈获取后缀表达式
- memcached完全剖析–1. memcached的基础