龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课 9 [已完结] C++零基础开发DXF内存脚本辅助教程 32课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 4449|回复: 0

代码注入和CALL游戏中的功能函数一点技巧

[复制链接]

10

主题

2

回帖

15

积分

编程入门

Rank: 1

龙马币
30

获得目标进程句柄就从略了。直接从注射开始:

  1. HANDLE CRemoteCodeDlg::InjetionCode(HANDLE hProcess, LPVOID pCode, LPVOID pParam)
  2. {
  3.     HANDLE RemoteThand;
  4.     LPVOID CodeAddress = NULL;
  5.     LPVOID DataAddress = NULL;
  6.     DWORD  RetByte,Tid,CodeSize,AllRemoteMemSize;

  7.     if(! hProcess || INVALID_HANDLE_VALUE == hProcess)
  8.     {
  9.         return HANDLE(0);
  10.     }
  11.      
  12.     CodeSize = DWORD(PCHAR(GETVCPROC_ADDRESS(GetVCProcAddress)) - PCHAR(GETVCPROC_ADDRESS(ISee)));
  13.     AllRemoteMemSize = CodeSize +  MEMCODEPARAM_SIZE + sizeof(DWORD);

  14.     CodeAddress = VirtualAllocEx(hProcess,NULL,AllRemoteMemSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  15.     if(! CodeAddress)
  16.     {         
  17.         return HANDLE(0);
  18.     }
  19.      
  20.     if(! WriteProcessMemory(hProcess,CodeAddress,pCode,CodeSize,&RetByte))
  21.     {         
  22.         VirtualFreeEx(hProcess,CodeAddress,AllRemoteMemSize,MEM_DECOMMIT);
  23.         CodeAddress = NULL;
  24.         return HANDLE(0);
  25.     }
  26.     DataAddress = LPVOID(DWORD(CodeAddress) + sizeof(DWORD) & ~3);

  27.     if(! WriteProcessMemory(hProcess,DataAddress,pParam,MEMCODEPARAM_SIZE,&RetByte))
  28.     {         
  29.         VirtualFreeEx(hProcess,CodeAddress,AllRemoteMemSize,MEM_DECOMMIT);
  30.         CodeAddress = NULL;
  31.         return HANDLE(0);
  32.     }

  33.     RemoteThand = CreateRemoteThread(hProcess,NULL,0,LPTHREAD_START_ROUTINE(CodeAddress),
  34.         DataAddress,CREATE_SUSPENDED,&Tid);

  35.     m_pRemoteAllocMem = CodeAddress;
  36.     m_RemoteMemSize = AllRemoteMemSize;

  37.     return RemoteThand;
  38. }
复制代码


        首先说说这个被注射代码的大小问题,这个问题我在很多论坛上看到过。但是回答的人都是用估计值作答。实际上这个难题也很好理解,因为你写得不是机器代码,自然无法计算最后生成的执行的机器代码字节数。(玩笑话,编译器知道,但他不会告诉你。呵呵)。

    汇编语言可以很轻松的获得这个值,原因同上。

    难道我们就无法确定了吗?NO,让编译器告诉我们,不要吃惊,方法如下:
int Func1(void)
{
  -------------------------------
  --------------------------------
}

void Func2(void)
{

}

    假设Func1是要注射的代码,要求的Func1编译后的代码大小:Func1Size = Func2 - Func2;

原理:
   
  实际上如果你对编译器比较熟悉的话,就会知道实际上函数名就是编译过程中的一个地址标号。因此用高地址标号减去低的就是我们想要得。有人要问:你怎末知道编译器一定会把Func2放在Func1之后哪?我的回答是:可能有反向的。但目前我见到的VC \ BC \ BCB \ SC(赛门铁克)都是这末做的。

我的码如下:

CodeSize = DWORD(PCHAR(GETVCPROC_ADDRESS(GetVCProcAddress)) - PCHAR(GETVCPROC_ADDRESS(ISee)));

这个GETVCPROC_ADDRESS是一个宏,定义如下:

#ifdef _DEBUG     
    #define GETVCPROC_ADDRESS(Fn)  GetVCProcAddress(Fn)
#else
    #define GETVCPROC_ADDRESS(Fn)  Fn
#endif

    为什莫定义这个?直接用Fn2 - Fn1不就好了吗?NO,这又引出了一个概念:VC的编译器有个特点从6.0到现在的9.0都是如此。在你选择Debug版本编译时,所有的函数调用都会被编译为一个间接的调转指令。就像调用系统API一样。在编译器内部型如:

JMP @IAT_Fn1@ 这个鬼样子。

而在Release版本时就变成了直接调用。所以为了调试方便就定义了此宏。Debug宏实现如下:

  1. LPVOID GetVCProcAddress(LPVOID pFn)
  2. {
  3.     PCHAR pAddRess = (PCHAR)pFn;

  4.     pAddRess ++;        //跳过@IAT的第一个指令jmp

  5.     pAddRess +=  *(DWORD *)pAddRess;
  6.     pAddRess += 4;        //修正指针类型偏移

  7.     return pAddRess;
  8. }
复制代码


好了,再看看这个:

AllRemoteMemSize = CodeSize +  MEMCODEPARAM_SIZE + sizeof(DWORD);

        全部分配的内存大小为什用代码尺寸大小(CodeSize) + 参数块大小(MEMCODEPARAM_SIZE)还要再加一个sizeof(DWORD)哪?我只说是为了数据对齐,如何保证后拷贝的数据块能正好放在一个4字节对齐的开始地址哪?看看下面这行代码你就明白了。

DataAddress = LPVOID(DWORD(CodeAddress) + sizeof(DWORD) & ~3);

        至于经常有人说直接注射的代码无法调用API的问题,我觉得更加荒谬。他们的理由无非是,本地进程的API地址跟目标进程的API地址不一致。是的,这个我也承认。但是你可以用LoadLibRary和GetProcAddress来获取目标进程中的API地址。你不用跟我说这两个地址怎末来?实际上 Kernel32.dll在每个进程中的加载地址都一样。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表