从WINDOWS VISITA开始以后,windows已经开始支持随机基址的关系,也就是说以前我们的进程基址都是从0x40000开始的,如果一个变量在我们第一次运行的时候地址为0x50000,那么以后也都会在这个位置
而VS2008后开始提供随机基址的功能,在WINDOWS VISITA后的版本也都支持这个功能,这样进程的基址将不会再固定从一个地方开始,变量的地址也会随着基址的不同而不同,加大了我们对一个进程修改的难度,我们每次修改一个变量不能再将变量写死,而是要根据基址+数据偏移量来算出数据的地址,那么,我们怎么去获得一个进程的基址呢??
在我们程序运行的时候,我们进程自己的HINSTANCE或者HMODULE就是我们这个进程的基址,当然,DLL的HMODULE或者HINSTANCE则是该DLL的基址,这样我们大概就知道怎么获取进程的基址了
1.GetModuleHandle
通过GetModuleHandle,我们可以获取一个进程的基址,我们可以直接传入一个NULL就可以直接拿到该进程的基址,但是这种方法我们只能拿到自己进程的基址,所以不是很方便
当然我还有一个想法就是可以把获取进程基址的代码注入到另外一个进程,然后通过其他方法传送出来,除了SOCKET,文件,管道等正常通讯外,我们还可以利用VirtualAllocEx,在对方内存开辟一块地址后,我们把代码复制进去(如同上一章的代码注入),记得,我们申请内存的大小除了需要放置代码,还需要放置我们计算完以后的结果,我们计算完了后把结果放在这块内存,就可以通过另外一个进程去取了
比如我们A进程向B进程申请了100字节的内存区域C,并且复制了50字节的代码到C,我们这50字节的代码执行了后,可以获取B进程的基地址,并且取得基地址后,他会把这个值放到区域C地址偏移为80的位置,这样我们A进程就可以通过读取区域C再往后面偏移80个,这个值就是进程的基址
这个方法也适用于注入代码与原进程的通讯,简单的来讲就是通过在对方内存开辟一块专门放置计算结果的内存,然后再由另外一个进程去取数据,有点类似于内存映射,后面将会有专门的一节讲这个
2. 给我们的进程拍加载模块的快照
windows有专门的TLHELP32这个库,就是给我们的电脑拍快照用的,比如DLL快照,比如电脑进程表的快照,CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,ProcessID),这样的话,第一个DLL将会是我们要查找的DLL
3.利用EnumProcessModules
psapi库里面也有提供一些进程状态的API,其中EnumProcessModules的库就可以枚举对应进程加载的所有模块,枚举的第一个就是我们要查看进程对应的地址
后面的两个方法都会比较简单,所以简单讲解一下,以上代码都在
https://github.com/linyilong3/hacker-tutorial
里面的ModuleBaseAddr我们这一章的代码,代码在WIN7 64位下也均可以通过编译和运行正确,本人水平所限,有不足之处希望大家指教