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 实现对内存堆栈扫描的更多相关文章

  1. STM32/GD32上内存堆栈溢出探测研究

    无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找!主要溢出情况如下:1,一般RAM最后两块空间是堆Heap和栈Stack,堆从下往上用,栈从上往下用,任意一个用完,都会进入对方的空间2, ...

  2. 关于掌握C#的内存堆栈概念

    很多时候,我们使用C#语言书写业务逻辑时,并不会太多地主动考虑到内存的占用和分配问题,但编的程序多了,就总会遇到一些性能问题.提到"性能"二字,就不得不考虑CPU和内存,而提到内存 ...

  3. arcgis engine 中出现的内存堆栈溢出问题。

    两种解决方案: 1.循环加载mxd文档的时候出现的堆栈溢出,解决办法是每次循环结束时清空FeatureLayer,感觉并不好,但是确实可以实现功能. 2.循环调取featureclass的search ...

  4. PHP对象在内存堆栈中的分配

    对象在PHP里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上说大体上是分为4段,栈空间段.堆空间段. ...

  5. JAVA对象及属性的内存堆栈管理(通过小程序简单说明)

    JAVA在执行过程中会划分4个内存区域(heap.stack.data segment.code segment)代码区(codesegment):java开始执行会把代码加载到code segmen ...

  6. eclipse JVM Tomcat 内存堆栈大小设置

    1,  设置Eclipse内存使用情况 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn ...

  7. openjdk-alpine镜像无法打印线程堆栈和内存堆栈问题

    基于openjdk:8u171-alpine构建的java镜像,使用jstack命令打印线程的时候会提示以下错误: /opt # ps -ef PID USER TIME COMMAND 1 root ...

  8. C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例

    一个奇怪的C语言问题,涉及到指针.数组.堆栈.以及printf.以下实现: 整数向字符串的转换,返回字符串指针,并在main函数中调用printf显示. #include<stdio.h> ...

  9. AJ整理问题之:内存堆栈

    内存 数据在内存中的存放 在计算机中,运行的应用程序的数据都是保存在内存中的. 不同类型的数据,保存的内存区域不同,其中包括: 1:栈区(stack)由编译器自动分配并释放,一半存放函数的参数值,局部 ...

随机推荐

  1. OpenStack 安装 Keystone

    OpenStack 安装 Keystone 本篇主要记录一下 如何安装 openstack的 第一个组件 keystone 认证授权组件 openstack 版本 我选的是queens 版本 1.Op ...

  2. 企业应用架构研究系列二十六:信号量SemaphoreSlim与Semaphore

    在进行多线程程序的开发和设计的过程中,不可避免的需要引入semaphore信号量这个组件,这是.net框架提供的一个对多线程计数互斥的方案,就是允许指定的线程个数访问特定的资源而增加的 一个" ...

  3. VUE3 之 render 函数的使用 - 这个系列的教程通俗易懂,适合新手

    1. 概述 老话说的好:不用想的太多.太远,做好当天的事,知道明天要做什么就可以了. 言归正传,今天我们来聊聊 VUE 中 render 函数的使用. 2. render 函数 2.1 一个简单的例子 ...

  4. CSS的几种选择器

    选择器 目录 选择器 基础选择器 标签选择器 类选择器 id选择器 通配符选择器 复合选择器 后代选择器 子选择器 并集选择器 伪类选择器 基础选择器 标签选择器 标签选择器可以把一类标签全部选择出来 ...

  5. 用C语言实现井字棋(人人/AI人机)--完结版

    目录 用C语言实现井字棋(人人/AI人机)--完结版 BUG与优化3: 1. 修改了step的计算方法,每个玩家玩完就加一次step 2. 改变了电脑下棋的逻辑,每个玩家玩完之后都跳过这次循环 源码: ...

  6. C#.NET中的程序集版本

    更新记录 2022年4月16日:本文迁移自Panda666原博客,原发布时间:2021年8月22日. 在Visual Studio中查看程序集版本 在程序运行中获得程序集版本信息 除了在Visual ...

  7. 基于thinkphp6 layui的优秀极速后台开发框架推荐

    很多时候我们在做项目开发的时候,苦于没有好一点的轮子,自己动手开发的话,太耗费时间了,如果采用VUE的话,学习成本跟调试也比较麻烦, 而且有时候选用的东西甲方也不太容易接受,现在给大家介绍一款优秀的极 ...

  8. 国外价值10K+美金的Python面试题,珍藏已久,含泪放了出来

    兄弟们,没吹牛皮,一哥们在国外面试的时候,就是要他做的这个,直接给他说,做出来了给你15K(单位是刀),做不出来就拜拜~ 大兄弟当时就不服了,这不是看不起我么,分分钟就给整完了~ 我上我也行系列: 唠 ...

  9. 比我的脸还干的gan货——Python Flask Web 框架入门

    Flask是一个轻量级的基于Python的web框架. 本文适合有一定HTML.Python.网络基础的同学阅读. 1. 简介 这份文档中的代码使用 Python 3 运行.是的,所以读者需要自己在电 ...

  10. 使用Kind快速构建k8s

    什么是 KindKind(Kubernetes in Docker) 是一个 Kubernetes 孵化项目,Kind 是一套开箱即用的 Kubernetes 环境搭建方案.顾名思义,就是将 Kube ...