• LyScript 通过PEB结构解析堆基址


    LyScript中默认并没有提供获取进程堆基址的函数,不过却提供了获取PEB/TEB的函数,以PEB获取为例,可以调用dbg.get_peb_address(local_pid)用户传入当前进程的PID号,通常PID号可以使用dbg.get_process_id()函数得到,当得到了PEB进程环境块的基地址,那么获取堆基址就变得很简单了。

    首先以获取kernel32.dll模块基地址为例,如果使用汇编获取则代码是这样的,根据这段代码我们举一反三。

    1. _asm
    2. {
    3. push esi
    4. mov esi, dword ptr fs : [0x30] // PEB地址
    5. mov esi, [esi + 0x0C] // PEB_LDR_DATA
    6. mov esi, [esi + 0x1C] // InInitializationOrderModuleList
    7. mov esi, [esi] //
    8. mov eax, [esi + 0x08] // 模块基址
    9. pop esi
    10. }

    使用lyscript得到地址的代码就变得很简单了,只需要多次读取指针变量即可得到。

    1. from LyScript32 import MyDebug
    2. if __name__ == "__main__":
    3. dbg = MyDebug()
    4. conn = dbg.connect()
    5. # 内置函数得到进程PEB
    6. local_pid = dbg.get_process_id()
    7. peb = dbg.get_peb_address(local_pid)
    8. print("进程PEB: {}".format(hex(peb)))
    9. # esi = PEB_LDR_DATA结构体的地址
    10. ptr = peb + 0x0c
    11. # 读取内存指针
    12. PEB_LDR_DATA = dbg.read_memory_ptr(ptr)
    13. print("读入PEB_LDR_DATA里面的地址: {}".format(hex(PEB_LDR_DATA)))
    14. # esi = 模块链表指针InInitializationOrderModuleList
    15. ptr = PEB_LDR_DATA + 0x1c
    16. InInitializationOrderModuleList = dbg.read_memory_ptr(ptr)
    17. print("读入InInitializationOrderModuleList里面的地址: {}".format(hex(InInitializationOrderModuleList)))
    18. # 取出kernel32.dll模块基址
    19. ptr = InInitializationOrderModuleList + 0x08
    20. modbase = dbg.read_memory_ptr(ptr)
    21. print("kernel32.dll = {}".format(hex(modbase)))
    22. dbg.close()

    读取效果如下:

    如上kernel模块基地址的获取已经实现了,那么堆基址的获取也就非常简单了,我们只需要找到peb+0x90的位置,将其读取出来即可。

    1. 0:000> dt _peb @$peb
    2. ntdll!_PEB+0x090 ProcessHeaps
    3. 0:000> dd 7c99ffe0 l8
    4. 7c99ffe0 00150000 00250000 00260000 00000000
    5. 7c99fff0 00000000 00000000 00000000 00000000

    读取内存指针即可得到堆地址,将堆地址获取封装成getHeapsAddress()函数方便后续调用。

    1. from LyScript32 import MyDebug
    2. # 获取模块基址
    3. def getKernelModuleBase(dbg):
    4. # 内置函数得到进程PEB
    5. local_pid = dbg.get_process_id()
    6. peb = dbg.get_peb_address(local_pid)
    7. # print("进程PEB: {}".format(hex(peb)))
    8. # esi = PEB_LDR_DATA结构体的地址
    9. ptr = peb + 0x0c
    10. # 读取内存指针
    11. PEB_LDR_DATA = dbg.read_memory_ptr(ptr)
    12. # print("读入PEB_LDR_DATA里面的地址: {}".format(hex(PEB_LDR_DATA)))
    13. # esi = 模块链表指针InInitializationOrderModuleList
    14. ptr = PEB_LDR_DATA + 0x1c
    15. InInitializationOrderModuleList = dbg.read_memory_ptr(ptr)
    16. # print("读入InInitializationOrderModuleList里面的地址: {}".format(hex(InInitializationOrderModuleList)))
    17. # 取出kernel32.dll模块基址
    18. ptr = InInitializationOrderModuleList + 0x08
    19. modbase = dbg.read_memory_ptr(ptr)
    20. # print("kernel32.dll = {}".format(hex(modbase)))
    21. return modbase
    22. # 获取进程堆基址
    23. def getHeapsAddress(dbg):
    24. # 内置函数得到进程PEB
    25. local_pid = dbg.get_process_id()
    26. peb = dbg.get_peb_address(local_pid)
    27. # print("进程PEB: {}".format(hex(peb)))
    28. # 读取堆分配地址
    29. ptr = peb + 0x90
    30. peb_address = dbg.read_memory_ptr(ptr)
    31. # print("读取堆分配: {}".format(hex(peb_address)))
    32. heap_address = dbg.read_memory_ptr(peb_address)
    33. # print("当前进程堆基址: {}".format(hex(heap_address)))
    34. return heap_address
    35. if __name__ == "__main__":
    36. dbg = MyDebug()
    37. conn = dbg.connect()
    38. k32 = getKernelModuleBase(dbg)
    39. print("kernel32 = {}".format(hex(k32)))
    40. heap = getHeapsAddress(dbg)
    41. print("heap 堆地址: {}".format(hex(heap)))
    42. dbg.close()

    读取效果如下:

  • 相关阅读:
    虚拟机Linux+Ubuntu操作系统 如何在虚拟机上安装docker VMPro 2024在线激活资源
    趣味问题《寻人启事》的Python程序解决
    C语言编译与链接
    linux 内核中的pid和前缀树
    Elasticsearch集群部署及Head插件安装
    独立站运营优化方法
    spring事务失效场景
    SpringCloud(十)——ElasticSearch简单了解(一)初识ElasticSearch和RestClient
    Kafka生产者发送流程详解
    linux系统选择
  • 原文地址:https://blog.csdn.net/lyshark_csdn/article/details/126805435