LyScript中默认并没有提供获取进程堆基址的函数,不过却提供了获取PEB/TEB的函数,以PEB获取为例,可以调用dbg.get_peb_address(local_pid)
用户传入当前进程的PID号,通常PID号可以使用dbg.get_process_id()
函数得到,当得到了PEB进程环境块的基地址,那么获取堆基址就变得很简单了。
首先以获取kernel32.dll
模块基地址为例,如果使用汇编获取则代码是这样的,根据这段代码我们举一反三。
- _asm
- {
- push esi
- mov esi, dword ptr fs : [0x30] // PEB地址
- mov esi, [esi + 0x0C] // PEB_LDR_DATA
- mov esi, [esi + 0x1C] // InInitializationOrderModuleList
- mov esi, [esi] //
- mov eax, [esi + 0x08] // 模块基址
- pop esi
- }
使用lyscript
得到地址的代码就变得很简单了,只需要多次读取指针变量即可得到。
- from LyScript32 import MyDebug
-
- if __name__ == "__main__":
- dbg = MyDebug()
- conn = dbg.connect()
-
- # 内置函数得到进程PEB
- local_pid = dbg.get_process_id()
- peb = dbg.get_peb_address(local_pid)
- print("进程PEB: {}".format(hex(peb)))
-
- # esi = PEB_LDR_DATA结构体的地址
- ptr = peb + 0x0c
-
- # 读取内存指针
- PEB_LDR_DATA = dbg.read_memory_ptr(ptr)
- print("读入PEB_LDR_DATA里面的地址: {}".format(hex(PEB_LDR_DATA)))
-
- # esi = 模块链表指针InInitializationOrderModuleList
- ptr = PEB_LDR_DATA + 0x1c
- InInitializationOrderModuleList = dbg.read_memory_ptr(ptr)
- print("读入InInitializationOrderModuleList里面的地址: {}".format(hex(InInitializationOrderModuleList)))
-
- # 取出kernel32.dll模块基址
- ptr = InInitializationOrderModuleList + 0x08
- modbase = dbg.read_memory_ptr(ptr)
- print("kernel32.dll = {}".format(hex(modbase)))
-
- dbg.close()
读取效果如下:
如上kernel模块基地址的获取已经实现了,那么堆基址的获取也就非常简单了,我们只需要找到peb+0x90
的位置,将其读取出来即可。
- 0:000> dt _peb @$peb
- ntdll!_PEB+0x090 ProcessHeaps
-
- 0:000> dd 7c99ffe0 l8
- 7c99ffe0 00150000 00250000 00260000 00000000
- 7c99fff0 00000000 00000000 00000000 00000000
读取内存指针即可得到堆地址,将堆地址获取封装成getHeapsAddress()
函数方便后续调用。
- from LyScript32 import MyDebug
-
- # 获取模块基址
- def getKernelModuleBase(dbg):
- # 内置函数得到进程PEB
- local_pid = dbg.get_process_id()
- peb = dbg.get_peb_address(local_pid)
- # print("进程PEB: {}".format(hex(peb)))
-
- # esi = PEB_LDR_DATA结构体的地址
- ptr = peb + 0x0c
-
- # 读取内存指针
- PEB_LDR_DATA = dbg.read_memory_ptr(ptr)
- # print("读入PEB_LDR_DATA里面的地址: {}".format(hex(PEB_LDR_DATA)))
-
- # esi = 模块链表指针InInitializationOrderModuleList
- ptr = PEB_LDR_DATA + 0x1c
- InInitializationOrderModuleList = dbg.read_memory_ptr(ptr)
- # print("读入InInitializationOrderModuleList里面的地址: {}".format(hex(InInitializationOrderModuleList)))
-
- # 取出kernel32.dll模块基址
- ptr = InInitializationOrderModuleList + 0x08
- modbase = dbg.read_memory_ptr(ptr)
- # print("kernel32.dll = {}".format(hex(modbase)))
- return modbase
-
- # 获取进程堆基址
- def getHeapsAddress(dbg):
- # 内置函数得到进程PEB
- local_pid = dbg.get_process_id()
- peb = dbg.get_peb_address(local_pid)
- # print("进程PEB: {}".format(hex(peb)))
-
- # 读取堆分配地址
- ptr = peb + 0x90
- peb_address = dbg.read_memory_ptr(ptr)
- # print("读取堆分配: {}".format(hex(peb_address)))
-
- heap_address = dbg.read_memory_ptr(peb_address)
- # print("当前进程堆基址: {}".format(hex(heap_address)))
- return heap_address
-
- if __name__ == "__main__":
- dbg = MyDebug()
- conn = dbg.connect()
-
- k32 = getKernelModuleBase(dbg)
- print("kernel32 = {}".format(hex(k32)))
-
- heap = getHeapsAddress(dbg)
- print("heap 堆地址: {}".format(hex(heap)))
-
- dbg.close()
读取效果如下: