LyScript 实现对内存堆栈扫描
LyScript插件中提供了三种基本的堆栈操作方法,其中push_stack用于入栈,pop_stack用于出栈,而最有用的是peek_stack函数,该函数可用于检查指定堆栈位置处的内存参数,利用这个特性就可以实现,对堆栈地址的检测,或对堆栈的扫描等。
LyScript项目地址:https://github.com/lyshark/LyScript
peek_stack命令传入的是堆栈下标位置默认从0开始,并输出一个十进制有符号长整数,首先实现有符号与无符号数之间的转换操作,为后续堆栈扫描做准备。
from LyScript32 import MyDebug
# 有符号整数转无符号数
def long_to_ulong(inter,is_64 = False):
if is_64 == False:
return inter & ((1 << 32) - 1)
else:
return inter & ((1 << 64) - 1)
# 无符号整数转有符号数
def ulong_to_long(inter,is_64 = False):
if is_64 == False:
return (inter & ((1 << 31) - 1)) - (inter & (1 << 31))
else:
return (inter & ((1 << 63) - 1)) - (inter & (1 << 63))
if __name__ == "__main__":
dbg = MyDebug()
connect_flag = dbg.connect()
print("连接状态: {}".format(connect_flag))
for index in range(0,10):
# 默认返回有符号数
stack_address = dbg.peek_stack(index)
# 使用转换
print("默认有符号数: {:15} --> 转为无符号数: {:15} --> 转为有符号数: {:15}".
format(stack_address, long_to_ulong(stack_address),ulong_to_long(long_to_ulong(stack_address))))
dbg.close()
通过上述封装函数,即可实现对有符号和无符号数的转换。

继续完善该功能,我们使用get_disasm_one_code()函数,扫描堆栈地址并得到该地址处的反汇编代码。
from LyScript32 import MyDebug
# 有符号整数转无符号数
def long_to_ulong(inter,is_64 = False):
if is_64 == False:
return inter & ((1 << 32) - 1)
else:
return inter & ((1 << 64) - 1)
# 无符号整数转有符号数
def ulong_to_long(inter,is_64 = False):
if is_64 == False:
return (inter & ((1 << 31) - 1)) - (inter & (1 << 31))
else:
return (inter & ((1 << 63) - 1)) - (inter & (1 << 63))
if __name__ == "__main__":
dbg = MyDebug()
connect_flag = dbg.connect()
print("连接状态: {}".format(connect_flag))
for index in range(0,10):
# 默认返回有符号数
stack_address = dbg.peek_stack(index)
# 反汇编一行
dasm = dbg.get_disasm_one_code(stack_address)
# 根据地址得到模块基址
if stack_address <= 0:
mod_base = 0
else:
mod_base = dbg.get_base_from_address(long_to_ulong(stack_address))
print("stack => [{}] addr = {:10} base = {:10} dasm = {}".format(index, hex(long_to_ulong(stack_address)),hex(mod_base), dasm))
dbg.close()
得到的堆栈参数如下:

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

其实很简单,首先我们需要得到程序全局状态下的所有加载模块的基地址,然后得到当前堆栈内存地址内的实际地址,并通过实际内存地址得到模块基地址,对比全局表即可拿到当前模块是返回到了哪里。
from LyScript32 import MyDebug
# 有符号整数转无符号数
def long_to_ulong(inter,is_64 = False):
if is_64 == False:
return inter & ((1 << 32) - 1)
else:
return inter & ((1 << 64) - 1)
# 无符号整数转有符号数
def ulong_to_long(inter,is_64 = False):
if is_64 == False:
return (inter & ((1 << 31) - 1)) - (inter & (1 << 31))
else:
return (inter & ((1 << 63) - 1)) - (inter & (1 << 63))
if __name__ == "__main__":
dbg = MyDebug()
connect_flag = dbg.connect()
print("连接状态: {}".format(connect_flag))
# 得到程序加载过的所有模块信息
module_list = dbg.get_all_module()
# 向下扫描堆栈
for index in range(0,10):
# 默认返回有符号数
stack_address = dbg.peek_stack(index)
# 反汇编一行
dasm = dbg.get_disasm_one_code(stack_address)
# 根据地址得到模块基址
if stack_address <= 0:
mod_base = 0
else:
mod_base = dbg.get_base_from_address(long_to_ulong(stack_address))
# print("stack => [{}] addr = {:10} base = {:10} dasm = {}".format(index, hex(long_to_ulong(stack_address)),hex(mod_base), dasm))
if mod_base > 0:
for x in module_list:
if mod_base == x.get("base"):
print("stack => [{}] addr = {:10} base = {:10} dasm = {:15} return = {:10}"
.format(index,hex(long_to_ulong(stack_address)),hex(mod_base), dasm,
x.get("name")))
dbg.close()
运行后,即可扫描到堆栈内的所有返回模块的位置。

LyScript 实现对内存堆栈扫描的更多相关文章
- STM32/GD32上内存堆栈溢出探测研究
无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!主要溢出情况如下:1,一般RAM最后两块空间是堆Heap和栈Stack,堆从下往上用,栈从上往下用,任意一个用完,都会进入对方的空间2, ...
- 关于掌握C#的内存堆栈概念
很多时候,我们使用C#语言书写业务逻辑时,并不会太多地主动考虑到内存的占用和分配问题,但编的程序多了,就总会遇到一些性能问题.提到"性能"二字,就不得不考虑CPU和内存,而提到内存 ...
- arcgis engine 中出现的内存堆栈溢出问题。
两种解决方案: 1.循环加载mxd文档的时候出现的堆栈溢出,解决办法是每次循环结束时清空FeatureLayer,感觉并不好,但是确实可以实现功能. 2.循环调取featureclass的search ...
- PHP对象在内存堆栈中的分配
对象在PHP里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上说大体上是分为4段,栈空间段.堆空间段. ...
- JAVA对象及属性的内存堆栈管理(通过小程序简单说明)
JAVA在执行过程中会划分4个内存区域(heap.stack.data segment.code segment)代码区(codesegment):java开始执行会把代码加载到code segmen ...
- eclipse JVM Tomcat 内存堆栈大小设置
1, 设置Eclipse内存使用情况 修改eclipse根目录下的eclipse.ini文件 -vmargs //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn ...
- openjdk-alpine镜像无法打印线程堆栈和内存堆栈问题
基于openjdk:8u171-alpine构建的java镜像,使用jstack命令打印线程的时候会提示以下错误: /opt # ps -ef PID USER TIME COMMAND 1 root ...
- C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例
一个奇怪的C语言问题,涉及到指针.数组.堆栈.以及printf.以下实现: 整数向字符串的转换,返回字符串指针,并在main函数中调用printf显示. #include<stdio.h> ...
- AJ整理问题之:内存堆栈
内存 数据在内存中的存放 在计算机中,运行的应用程序的数据都是保存在内存中的. 不同类型的数据,保存的内存区域不同,其中包括: 1:栈区(stack)由编译器自动分配并释放,一半存放函数的参数值,局部 ...
随机推荐
- 23. Merge k Sorted Lists - LeetCode
Question 23. Merge k Sorted Lists Solution 题目大意:合并链表数组(每个链表中的元素是有序的),要求合并后的链表也是有序的 思路:遍历链表数组,每次取最小节点 ...
- Android源码环境生成Android SDK并导入Adnroid Studio
1.发现问题 之前使用Repo同步Android源码使用的是下面这条指令,即同步的是分支android-7.1.2_r18的代码 repo init -u https://mirrors.tuna.t ...
- 【Axure】母版引发事件
引发事件是指你将母版中某一元件的事件从母版中提升出来,以使其在页面的级别可用. 通过引发事件,可以对在不同页面上母版实例的同一个元件设置不同的交互. 设置引发事件 打开一个母版: 选择其中一个组件: ...
- 使用 Vite 插件开发构建 Tampermonkey 用户脚本
起因 一直以来,我都是直接在浏览器 Tampermonkey 扩展页面直接新建用户脚本来开发的: 对于一些简单的脚本,这没有什么问题,即改即看.但当代码多了以后问题就来了,自带编辑器开发体验确实不太舒 ...
- CF1681F Unique Occurrences
题意:一棵树,问每条路径上只出现一次的值的个数的和. 思路: 显然想到考虑边贡献.每条边权下放到下面的哪个点.\(up_i\)为上面第一个点权等于它的点.我们需要一个子树内点权等于它的点(如果满足祖孙 ...
- DAST 黑盒漏洞扫描器 第二篇:规则篇
0X01 前言 怎么衡量一个扫描器的好坏,扫描覆盖率高.扫描快.扫描过程安全 而最直接的效果就是扫描覆盖率高(扫的全) 怎么扫描全面,1 流量全面 2 规则漏报低 流量方面上篇已经讲过,这篇主要讲扫描 ...
- Spring Ioc源码分析系列--自动注入循环依赖的处理
Spring Ioc源码分析系列--自动注入循环依赖的处理 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到Spring创建bean出现循环依赖的时候并没有深入去分 ...
- 定制.NET 6.0的依赖注入
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本章中,我们将学习ASP.NET Core的依赖项注入(DI)以及如何自定义它. ...
- Markdown的使用指南
# Markdown学习 ------ 以下符号均是英文输入法下的 ## 1.标题 几级标题就写 几个#号 加 空格 加 标题内容 就可以 例如: ###加空格加三级标题效果如下 ### 三级标题 # ...
- Camunda定时器事件示例Demo(Timer Events)
Camunda定时器事件(Timer Events)是由定义的计时器触发的事件.它们可以用作启动事件.中间事件或边界事件.边界事件可以中断,也可以不中断. Camunda定时器事件包括:Timer ...