您现在的位置是:首页 > 编程语言学习 > 前端编程语言 > 文章正文 前端编程语言

LyScript实现对内存堆栈扫描的方法详解

2022-08-04 09:52:22 前端编程语言

简介LyScript插件中提供了三种基本的堆栈操作方法,其中push_stack用于入栈,pop_stack用于出栈,而最有用的是peek_stack函数,该函数可用于检...

LyScript插件中提供了三种基本的堆栈操作方法,其中push_stack用于入栈,pop_stack用于出栈,而最有用的是peek_stack函数,该函数可用于检查指定堆栈位置处的内存参数,利用这个特性就可以实现,对堆栈地址的检测,或对堆栈的扫描等。

LyScript项目地址:https://github.com/lyshark/LyScript

peek_stack命令传入的是堆栈下标位置默认从0开始,并输出一个十进制有符号长整数,首先实现有符号与无符号数之间的转换操作,为后续堆栈扫描做准备。

  1. from LyScript32 import MyDebug 
  2.  
  3. # 有符号整数转无符号数 
  4. def long_to_ulong(inter,is_64 = False): 
  5. if is_64 == False: 
  6. return inter & ((1 << 32) - 1) 
  7. else
  8. return inter & ((1 << 64) - 1) 
  9.  
  10. # 无符号整数转有符号数 
  11. def ulong_to_long(inter,is_64 = False): 
  12. if is_64 == False: 
  13. return (inter & ((1 << 31) - 1)) - (inter & (1 << 31)) 
  14. else
  15. return (inter & ((1 << 63) - 1)) - (inter & (1 << 63)) 
  16.  
  17. if __name__ == "__main__"
  18. dbg = MyDebug() 
  19.  
  20. connect_flag = dbg.connect() 
  21. print("连接状态: {}".format(connect_flag)) 
  22.  
  23. for index in range(0,10): 
  24.  
  25. # 默认返回有符号数 
  26. stack_address = dbg.peek_stack(index) 
  27.  
  28. # 使用转换 
  29. print("默认有符号数: {:15} --> 转为无符号数: {:15} --> 转为有符号数: {:15}"
  30.   format(stack_address, long_to_ulong(stack_address),ulong_to_long(long_to_ulong(stack_address)))) 
  31.  
  32. dbg.close() 

通过上述封装函数,即可实现对有符号和无符号数的转换。

继续完善该功能,我们使用get_disasm_one_code()函数,扫描堆栈地址并得到该地址处的反汇编代码。

  1. from LyScript32 import MyDebug 
  2.  
  3. # 有符号整数转无符号数 
  4. def long_to_ulong(inter,is_64 = False): 
  5. if is_64 == False: 
  6. return inter & ((1 << 32) - 1) 
  7. else
  8. return inter & ((1 << 64) - 1) 
  9.  
  10. # 无符号整数转有符号数 
  11. def ulong_to_long(inter,is_64 = False): 
  12. if is_64 == False: 
  13. return (inter & ((1 << 31) - 1)) - (inter & (1 << 31)) 
  14. else
  15. return (inter & ((1 << 63) - 1)) - (inter & (1 << 63)) 
  16.  
  17. if __name__ == "__main__"
  18. dbg = MyDebug() 
  19.  
  20. connect_flag = dbg.connect() 
  21. print("连接状态: {}".format(connect_flag)) 
  22.  
  23. for index in range(0,10): 
  24.  
  25. # 默认返回有符号数 
  26. stack_address = dbg.peek_stack(index) 
  27.  
  28. # 反汇编一行 
  29. dasm = dbg.get_disasm_one_code(stack_address) 
  30.  
  31. # 根据地址得到模块基址 
  32. if stack_address <= 0: 
  33. mod_base = 0 
  34. else
  35. mod_base = dbg.get_base_from_address(long_to_ulong(stack_address)) 
  36.  
  37. print("stack => [{}] addr = {:10} base = {:10} dasm = {}".format(index, hex(long_to_ulong(stack_address)),hex(mod_base), dasm)) 
  38.  
  39. dbg.close() 

得到的堆栈参数如下:

由此我们可以得到堆栈处的反汇编参数,但如果我们需要检索堆栈特定区域内是否存在返回到模块的地址,该如何实现呢?

其实很简单,首先我们需要得到程序全局状态下的所有加载模块的基地址,然后得到当前堆栈内存地址内的实际地址,并通过实际内存地址得到模块基地址,对比全局表即可拿到当前模块是返回到了哪里。

  1. from LyScript32 import MyDebug 
  2.  
  3. # 有符号整数转无符号数 
  4. def long_to_ulong(inter,is_64 = False): 
  5. if is_64 == False: 
  6. return inter & ((1 << 32) - 1) 
  7. else
  8. return inter & ((1 << 64) - 1) 
  9.  
  10. # 无符号整数转有符号数 
  11. def ulong_to_long(inter,is_64 = False): 
  12. if is_64 == False: 
  13. return (inter & ((1 << 31) - 1)) - (inter & (1 << 31)) 
  14. else
  15. return (inter & ((1 << 63) - 1)) - (inter & (1 << 63)) 
  16.  
  17. if __name__ == "__main__"
  18. dbg = MyDebug() 
  19.  
  20. connect_flag = dbg.connect() 
  21. print("连接状态: {}".format(connect_flag)) 
  22.  
  23. # 得到程序加载过的所有模块信息 
  24. module_list = dbg.get_all_module() 
  25.  
  26. # 向下扫描堆栈 
  27. for index in range(0,10): 
  28.  
  29. # 默认返回有符号数 
  30. stack_address = dbg.peek_stack(index) 
  31.  
  32. # 反汇编一行 
  33. dasm = dbg.get_disasm_one_code(stack_address) 
  34.  
  35. # 根据地址得到模块基址 
  36. if stack_address <= 0: 
  37. mod_base = 0 
  38. else
  39. mod_base = dbg.get_base_from_address(long_to_ulong(stack_address)) 
  40.  
  41. # print("stack => [{}] addr = {:10} base = {:10} dasm = {}".format(index, hex(long_to_ulong(stack_address)),hex(mod_base), dasm)) 
  42. if mod_base > 0: 
  43. for x in module_list: 
  44. if mod_base == x.get("base"): 
  45. print("stack => [{}] addr = {:10} base = {:10} dasm = {:15} return = {:10}" 
  46.   .format(index,hex(long_to_ulong(stack_address)),hex(mod_base), dasm, 
  47.   x.get("name"))) 
  48.  
  49. dbg.close() 

运行后,即可扫描到堆栈内的所有返回模块的位置。

相关文章

站点信息