本帖最后由 |流年灬一逝| 于 2012-7-26 09:20 编辑
前言
第一章
第二章
第三章
第四章
第五章
第六章
既然来了,就坚持读下去吧,认真读下去,一定会有收获的!
************************************************************************************************
上一节我们知道了怎样在 OllyDBG 中 Hook 修改一个数据,然后转存。
这节课我们主要学习一下远程修改指定进程的代码来达到我们 Hook 的目的。
其实这节课也就是编写程序来实现 OD 中的修改代码的操作。
这节课我们需要认识几个 API 函数。
1、 OpenProcess 打开一个进程,返回进程句柄
2、 WriteProcessMemory 在一个进程中写入数据
3、 CloseHandle 关闭一个内核对象
4、 ReadProcessMemory 读取进程数据
5、 VirtualAllocEx 在目标进程中申请一段内存空间 (存放 Hook代码 )
6、 VirtualFreeEx 在目标进程中释放申请的内存空间
因为是要动态修改程序代码,所以这节课的原程序有所改变,是一个静态编译的 Windows 窗口程序。
代码和上节课的一样,但是换成了按钮事件:
今天这个目标程序的 Hook 位置比较不好找,我提前找好了:
Hook地址: 00401057 |. DB45 FC fild [local.1] 相加指令地址(c = a + b)
还原地址: 00401077 |. 6A 00 push 0x0 信息框地址
我们今天的这个 Hook 程序就是这样, 编辑框里输入目标进程 ID,点 Hook就修改指令,点还原就还原修改的Hook代码 。
我们先来看看这几个 API 函数的使用:
OpenProcess 根据进程 ID打开进程
参数
dwDesiredAccess 进程操作权限
bInheritHandle 是否被子进程所继承
dwProcessId 指定要打开的进程 ID
这里的操作权限我们一般给它完全操作权限,也就是 PROCESS_ALL_ACCESS 在 API 助手里查到的是 ( STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF ) 这个值,其实就是把 STANDARD_RIGHTS_REQUIRED 和 SYNCHRONIZE 和 FFF进行位或 。
STANDARD_RIGHTS_REQUIRED 的值是 F0000( 十六进制 ) , SYNCHRONIZE 的值是 100000 ( 十六进制 ) ,他们三个位或之后的结果是 2035711 ( 十进制 )
WriteProcessMemory 读取进程的数据
参数
hProcess 进程句柄
lpBaseAddress 写入数据的起始位置
lpBuffer 将要写入数据的缓冲区
nSize 缓冲区的长度
lpNumberOfBytesWritten 实际写入长度,如果不需要可以设置为 null(0)
ReadProcessMemory 和 WriteProcessMemory 的用法一样。
CloseHandle 关闭一个内核对象
参数
hObject 对象句柄
VirtualAllocEx 在指定的进程中分配内存空间,返回分配的内存地址
参数
lpAddress 分配起始地址,一般为 0则自动分配
dwSize 分配长度
flAllocationType 分配类型
flProtect 保护类型
VirtualFreeEx 释放分配的内存数据
参数
hProcess 进程句柄
lpAddress 释放起始地址
dwSize 释放长度,一般为 0
dwFreeType 释放类型
这是写好的代码,首先我们判断进程 ID 是否合法,接着根据提供的进程 ID 来使用 openprocess 函数来打开进程。 原数据 这个 程序集变量 中保存的是 Hook 前的数据代码,也就是 c=a+b转换成汇编代码的前五个字节 ,用来以后我们还原用。接下来就是我们 Hook 的主要代码了,先使用 VirtualAllocEx 函数申请一段内存空间,我们的 分配类型(第四个参数)使用的是 从内存中分配 ,保护类型(第五个参数)使用的是 应用程序可读可写 。
下面的那段汇编指令我们暂且不管。
接着构造 hook 代码,也就是:
mov dword [ebp-0x4],0x3
mov dword [ebp-0x8],0x4
mov eax,dword [ebp-0x4]
add eax,[ebp-0x8]
mov dword [ebp-0xc],eax
jmp 0x00401077 跳转到信息框的地址
这段代码我们应该很熟悉,就是上节课我们 Hook 的代码。
那个计算 jmp 指令机器码子程序待会我们会提到。
接着就是写入数据了,注释打的很清楚,我就不说了。
说一下这个常量 “ #Hook 代码 ” 吧。
我们 Hook 代码存储区有一段代码是固定不变的,也就是:
mov dword [ebp-0x4],0x3
mov dword [ebp-0x8],0x4
mov eax,dword [ebp-0x4]
add eax,[ebp-0x8]
mov dword [ebp-0xc],eax
这段代码既然固定不变,我们就可以把它设定为常量,用字节集形式来写入,这样也就是写入一段代码了。
注:jmp 0x00401077 跳转到信息框的地址 这条代码会随着申请Hook代码存储空间的位置变化而变化,原因我们待会会提到( 计算 jmp指令机器码子程序的实现 )
我们在云外归鸟写的易语言 置入代码工具中,写入这段汇编代码,然后编译成为二进制文件,添加在易语言的资源中,需要时进行调用写入目标程序就可以了。 关于这个工具也可以到易语言宝盒或者云外归鸟的官方去下载。
好了,再说一下计算 jmp 指令机器码 这个子程序的实现。
其实他只有这么几行代码,参数是源地址 ( 从哪里跳 ) ,和目标地址 ( 准备往哪里跳 ) 。
我们先要考虑 jmp 本身的代码长度,也就是 5 个字节,那么开始跳的地方也就是源地址 +5 ,从哪里跳,就把目标地址减去这个值就算出了跳转的距离, jmp 指令的机器码标志是 EB ,也就是 {232}, 把它和跳转距离合并起来就是整个 jmp 的机器码了。
我们的这句代码:
其实就是:
mov dword [ebp-0x4],0x3
mov dword [ebp-0x8],0x4
mov eax,dword [ebp-0x4]
add eax,[ebp-0x8]
mov dword [ebp-0xc],eax
jmp 0x00401077 跳转到信息框的地址
加红的这句是使用计算 jmp 指令机器码来实现的。
这句代码也一样,计算从 Hook 起始位置跳转到 Hook 代码储存区的机器码。
然后我们来看一下还原:
这个是还原的代码,首先从 Hook 起始地址把数据还原,也就是我们之前的原数据中保存的代码,接着我们释放已经申请的内存。最后,我们关闭这个进程句柄,以防进程泄露。
最后我们看一下运行效果:
没有 Hook 之前的:
Hook 之后的:
*****************************************************************************************
大家可能有疑问说怎样才能知道被Hook程序的进程ID。方法可以利用一些工具,比如说进程管理器把查看-选择列-PID(进程标识符)选上,点确定,就有了。
大家还有什么疑问可以跟帖提出来。
程序+代码在此下载
程序 代码.rar
(499.74 KB, 下载次数: 653)