远程代码注入及DLL注入教程(InlineHook)---植物大战僵尸为例
远程代码注入及DLL注入教程
说明
本人刚开始学习逆向,不知道有没有动力学下深去,这一块也没有详细的实战教学,学多少就上传多少,希望能给想学的朋友一点帮助吧,本教程想通过植物大战僵尸这一经典游戏来抛砖引玉,教大家如何编写一个单机辅助。
CE找数据的过程本教程不提供,本文着重讲述如何根据找到的数据实现无限阳光,无冷却,其他诸如秒杀僵尸,后台运行等均大同小异。
所需基础
CE找关键数据基址(网上教程很多)、基本汇编命令
涉及工具
VS、CheatEngine(CE,网上很多)、汇编转机器码工具(我在用的https://www.jb51.net/softs/629217.html)、DLL注入工具(网上很多)
开始
无限冷却
假设第一个植物栏的冷却地址已找到,如图:
此时种下植物后暂停游戏,切到CE,选中冷却地址,右键-找出什么改写了这个地址,然后继续游戏,发现改写的代码:
点击显示汇编代码:
经过分析发现:如果还在冷却,那么在②处判断会跳走,把②处代码nop掉,让代码无论如何也会去Call③,发现植物已经实现无冷却(有很多种方法,比如把①修改为cmp eax,0),那么只需要如下代码即可实现:
BYTE noCD[2] = {0};
memset(noCD, 0x90, 2);//nop硬编码为0x90
WriteProcessMemory(hProcess, (LPVOID)(0x487296), noCD, 2, NULL);
无限阳光
像前面这种替换指令所用空间小于当前代码的方式,实现起来非常简单,但如果替换的汇编指令超过当前代码长度,将会导致后面指令被覆盖,引起崩溃,此时需要用到代码注入。
选中找到的阳光值地址,右键-找出什么访问了这个地址
可以看到有两处频繁访问,我们选择访问次数较少的第二条-显示反汇编程序。
那就在这里注入吧,前面已经知道,阳光值的地址为[[[基址006A9EC0]->偏移768]->偏移5560],所以要注入的汇编代码可以写成:
push eax
mov eax,[006A9EC0]
mov eax,[eax+768]
mov [eax+5560],0xFFF // 0xFFF为阳光值,别太小就行
pop eax
mov eax,[esi+00005560] //恢复被覆盖掉的代码
而在注入处发现eax被赋值,所以push eax 及 pop eax可以删掉(实际情况实际分析)。
因此,运行流程为:
代码到达"PlantsVsZombies.exe"+89825(0x489825)处时,JMP到空闲空间,执行我们注入的汇编代码,JMP到"PlantsVsZombies.exe"+8982B处继续向后执行,两种方法的示意图:
远程代码注入
我们需要计算0x489825处 JMP的偏移,推导过程如下:
起跳地址(0x489825) + 5(JMP远跳占用固定5字节,0xE9 + 4字节偏移量) + 偏移量 = 目标地址
因此
偏移量 = 目标地址 - (起跳地址 + 5)
目标地址需要我们手动申请,代码如下:
//第三个参数为申请大小
LPVOID virAddr = VirtualAllocEx(hProcess, NULL, 64, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
那么偏移jmpOffset为:
DWORD jmpOffset = (DWORD)(0x489825) - ((DWORD)virAddr + 5);
接下来组合0x489825处代码:
BYTE ByteOffset[4];
IntTo4Bytes(jmpOffset , ByteOffset); //int转4字节byte[]
BYTE JmpToNewCode[6] = {0};
JmpToNewCode[0] = 0xE9; //jmp指令
memcpy(JmpToNewCode + 1, ByteOffset, 4);
JmpToNewCode[5] = 0x90; //空余的1个字节用nop填充
到这一步时,我们先不要着急WriteProcessMemory写入,因为我们申请的virAddr中还没有写入我们的汇编代码,这时需要使用汇编代码转机器码工具(文中有下载地址),转成机器码,然后写入到virAddr中,如图:
BYTE machinecode[32] = { 161,192,158,106,0,139,128,104,7,0,0,199,128,96,85,0,0,255,15,0,0,139,134,96,85,0,0 };//27
为什么是32字节呢,因为我们的汇编代码还没有JMP跳回0x48982B,需要再加上5字节的JMP 偏移量,计算方法和上面思路一样:
//起跳地址:virAddr + 27 目标地址:0x48982B
DWORD returnoffset = (DWORD)(0x48982B) - ((DWORD)virAddr + 27 + 5);
组合注入的机器码:
BYTE ByteOffset[4];
IntTo4Bytes(returnoffset, ByteOffset);
BYTE ReturnCode[5] = { 0 };
ReturnCode[0] = 0xE9; //jmp指令
memcpy(ReturnCode + 1, ByteOffset, 4); //组合jmp
memcpy(machinecode + 27, ReturnCode, 5);//组合完整机器码
在注入前,先把原来汇编指令保存下来,方便还原代码。
BYTE OldCode[6] = { 0 };
ReadProcessMemory(hProcess, (LPVOID)0x489825, OldCode, 6, NULL)
OK,把machinecode写入到virAddr中:
WriteProcessMemory(hProcess, virAddr, machinecode, 32, NULL);
最后再修改注入点(0x489825):
WriteProcessMemory(hProcess, (LPVOID)0x489825, JmpToNewCode, 6, NULL);
至此,代码注入功能基本完毕,编译,运行,测试完美无限阳光。
恢复原来功能只需要:
WriteProcessMemory(hProcess, (LPVOID)0x489825, OldCode, 6, NULL);
DLL注入
DLL注入相比代码注入少了手动开辟内存以及计算跳回偏移的过程,更加简单,步骤如下:
VS创建DLL工程,在DLL_PROCESS_ATTACH中码功能:
内联代码:
BYTE OldJmp[6] = { 0 };
DWORD JmpBack = 0x48982B;__declspec(naked) void InfinateSunshine()
{ // 不加 dword ptr ss 编译器会翻译成单字赋值,原因不明(求大佬解释)__asm{mov eax, dword ptr ss: [0x006A9EC0]mov eax, dword ptr ss : [eax + 0x00000768]mov dword ptr ss : [eax + 0x00005560], 0x00000FFFmov eax, dword ptr ss : [esi + 0x5560]jmp JmpBack}
}
计算偏移方法和上面一致:
//计算偏移,InfinateSunshine 即为目标函数
DWORD offset = (DWORD)InfinateSunshine - (0x489825 + 5);
BYTE NewJmp[6] = {0};
NewJmp[0] = 0xE9;
BYTE ByteOffset[4];
IntTo4Bytes(offset, ByteOffset);
memcpy(NewJmp + 1, ByteOffset, 4);
NewJmp[5] = 0x90;nRet = WriteProcessMemory(hProcess, (LPVOID)0x489825, NewJmp, 6, NULL);
编译后,用注入工具注入:
成功。
但是,如果你再卸载掉DLL,会发现游戏崩溃,原因为在卸载DLL时不会自动还原0x489825 处的代码,因此需要再添加逻辑,卸载时复原代码。
再分析
后来经过分析,发现无限阳光插入处的代码还可以再优化,因为插入处的代码只有阳光访问时才会到达,如何判断呢,可以先用CE代码注入写一个判断代码,和当前的阳光地址做对比,加入一段没有意义的代码并设置断点,看能否断下,如果没有断下,那说明注入处只会被阳光访问,如图:
故[esi+00005560]一定为阳光地址,因此可以省掉使用基址加偏移的方式,注入处代码可以修改为更简单的:
mov [esi+00005560],0xffff //确定为阳光唯一,直接赋值
mov eax,[esi+00005560] //恢复被覆盖掉的代码
总结
代码注入及DLL注入的关键为
1、注入代码中不要破坏原先堆栈平衡,如果不确定寄存器里的值在我们使用之前是不是有用,最好先pushad再写自己的注入代码,最后popad
2、注入处的JMP偏移及返回的JMP偏移一定要计算准确,否则必出错,可以配合OD和CE进行调试检查。
远程代码注入及DLL注入教程(InlineHook)---植物大战僵尸为例相关推荐
- 进程注入之DLL注入
前言 DLL注入是我在大一的时候接触的一种技术,那时候还不懂,最近结合小程序详细的理解了一下. DLL注入是将代码注入到一个远程进程中,并让远程进程调用LoadLibrary()函数,从而强制远程进程 ...
- python注入_Python——dll注入
dll攻击原理分析 什么是dll 动态链接库,是在微软Windows操作系统中实现共享函数库概念的一种方式. 这些库函数的扩展名是 ".dll".".ocx"( ...
- 【网络杂烩 ---> 网络安全】DLL 注入 --- c/c++ 代码实现(超 · 详细)
麻了,之前写的博客全是收藏,没人点赞,来点赞行不行! GitHub同步更新(已分类):DLL_Injection Gitee同步更新(已分类)DLL_Injection 公众号:URLeisure 的 ...
- 实战dll注入(原理, 踩坑及排雷)
摘要 使用vs2019编写注入器程序, 在生成的注入器可用前, 踩了不少坑, 因此记录一下. 本文涉及三种恶意代码注入方法: 直接dll注入, 反射式dll注入, 镂空注入. 之所以选这三种注入方法, ...
- 1.DLL注入相关概念
DLL注入相关概念 DLL注入与DLL劫持的比较: DLL劫持相当于一个定时的炸弹,只等待可执行文件双击运行,拔出导火线,而DLL注入,目标必须处于运行状态,而且DLL注入很容易被拦截. DLL注入需 ...
- C++远程dll注入到QQ聊天工具
远程dll注入到QQ 逻辑: 1.获取QQ的进程ID: 2.打开进程获取进程句柄,从而对进程进行操作: 3.对进程句柄进行操作,开辟一块空间,让目标进程进行调用我们所写的东西: 4.往开辟好的内存中写 ...
- DLL注入_远程线程注入
什么是线程注入? 线程注入,是通过开启远程线程的方式,将DLL加载到目标宿主进程中的常用方式. 什么是动态链接库? 首先Windows中链接库分为两种:动态链接库DLL.静态链接库LIB. ① 静态链 ...
- DLL注入:远程线程注入
Dll 代码: #include "stdafx.h" #include <iostream> #include <Windows.h> #include ...
- (二) 使用Detours调试远程线程注入的dll
远程线程注入是指一个进程在另一个进程中创建线程的技术.该技术可以用于:API Hook,破解软件所谓的"内存补丁"等. 将DLL注入到其它进程并不是难事,问题是这个被注入的DLL不 ...
最新文章
- 独家 | 人工神经网络中发现了人类大脑拥有的多模态神经元(附链接)
- linux检查socekt是否断开,如何在C语言中判断socket是否已经断开
- 查看HTML代码却被当黑客,记者好心报告漏洞,反遭美国州长起诉
- input python2.7_python 中的input
- Servlet映射路径中的通配符
- java下拉文本框_java swing 下拉框与文本框
- Google Mock启蒙篇 [2] (Google C++ Mocking Framework for Dummies 翻译)
- C++编程练习:设计一个银行账户类,包含户名、帐号以及当前余额属性,并且能完成开户、存款、取款和查询余额等行为。
- 思想已经高过行动好多了
- 【转载保存】Lucene7.1.0超详细的使用文档
- Web开发如何实现Tomcat等服务器热部署不用重启
- mysql 重要维护工具 图解
- 【python】59个Python使用技巧,从此你的Python与众不同(二)
- 8Manage革新多项目管理的沟通方式
- 如何让插入PPT的音乐跨幻灯片后同时播放
- visio2010安装
- 毕业论文排版(六)-三线表
- 从没想过从上帝视角看地球,竟美得如此震撼!
- 如何找回电脑回收站删除的文件, 10种恢复工具方法!
- 自动浇花系统的电路分析
热门文章
- NBU 异机恢复Oracle操作步骤
- 2019年5月新出Dart Flutter入门实战视频教程网盘下载地址
- 计算机考研推荐的专业课视频链接(408)
- Autodesk Mudbox 2019 for Mac(三维雕刻软件)
- 12864液晶模块驱动
- Camtasia Studio8如何提高视频画质和清晰度
- java Post ,Get 调用Http Https
- 广东人除了敢吃,原来还“最敢生”!数据可视化带你了解我国人口出生率!
- PHP自学笔记 ---李炎恢老师PHP第一季 TestGuest0.6
- 【历史上的今天】8 月 23 日:计算机先驱诞生日;万维网面世 30 周年