LyScript插件提供了三种基本的栈操作方法,其中push_stack用于入栈,pop_stack用于出栈,最有用的是peek_stack函数,可以用于检查指定栈位置的内存参数,可以利用该特性实现栈地址的检测,或者栈的扫描等。插件地址:https://github.com/lyshark/Ly...peek_stack命令传入栈下标位置,默认从0开始,输出一个十进制有符号长整数。首先,实现有符号数和无符号数之间的转换操作,为后续的栈扫描做准备。fromLyScript32importMyDebug#将有符号整数转换为无符号数deflong_to_ulong(inter,is_64=False):ifis_64==False:returninter&((1<<32)-1)else:returninter&((1<<64)-1)#将无符号整数转换为有符号数defulong_to_long(inter,is_64=False):ifis_64==False:return(inter&((1<<31)-1))-(inter&(1<<31))否则:返回(inter&((1<<63)-1))-(inter&(1<<63))if__name__=="__main__":dbg=MyDebug()connect_flag=dbg.connect()print("Connectionstatus:{}".format(connect_flag))forindexinrange(0,10):#默认返回有符号数stack_address=dbg.peek_stack(index)#使用转换print("default有符号数:{: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()函数扫描栈地址,得到这个地址的反汇编代码。fromLyScript32importMyDebug#将有符号整数转换为无符号数deflong_to_ulong(inter,is_64=False):ifis_64==False:returninter&((1<<32)-1)else:returninter&((1<<64)-1)#将无符号整数转换为有符号数defulong_to_long(inter,is_64=False):ifis_64==False:return(inter&((1<<31)-1))-(inter&(1<<31))否则:返回(inter&((1<<63)-1))-(inter&(1<<63))if__name__=="__main__":dbg=MyDebug()connect_flag=dbg.connect()print("Connectionstatus:{}".format(connect_flag))forindexinrange(0,10):#默认返回有符号数stack_address=dbg.peek_stack(index)#反汇编一行dasm=dbg.get_disasm_one_code(stack_address)#根据地址获取模块的基地址ifstack_address<=0:mod_base=0else: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()得到的栈参数为如下:这样我们就可以在栈中获取反汇编参数了,但是如果我们需要检索栈的特定区域是否有返回给模块的地址,怎么实现呢?其实很简单,首先我们需要获取程序全局状态下所有加载模块的基地址,然后获取当前栈内存地址中的实际地址,通过实际内存地址获取模块基地址,对比全局表得到哪里当前模块返回到fromLyScript32importMyDebug#将有符号整数转换为无符号数deflong_to_ulong(inter,is_64=False):ifis_64==False:returninter&((1<<32)-1)else:returninter&((1<<64)-1)#将无符号整数转换为有符号数defulong_to_long(inter,is_64=False):ifis_64==False:return(inter&((1<<31)-1))-(inter&(1<<31))否则:返回(inter&((1<<63)-1))-(inter&(1<<63))if__name__=="__main__":dbg=MyDebug()connect_flag=dbg.connect()print("Connectionstatus:{}".format(connect_flag))#获取程序加载的所有模块信息module_list=dbg.get_all_module()#在range(0,10)中向下扫描堆栈索引:#默认返回一个有符号数stack_address=dbg.peek_stack(index)#反汇编一行dasm=dbg.get_disasm_one_code(stack_address)#根据地址获取模块基地址ifstack_address<=0:mod_base=0else:mod_base=dbg.get_base_from_addresss(long_to_ulong(stack_address))#print("stack=>[{}]addr={:10}base={:10}dasm={}".format(index,hex(long_to_ulong(stack_address)),hex(mod_base),dasm))ifmod_base>0:forxinmodule_list:ifmod_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()运行之后可以扫描到栈中所有返回模块的位置
