LyScript實(shí)現(xiàn)對內(nèi)存堆棧掃描的方法詳解
LyScript插件中提供了三種基本的堆棧操作方法,其中push_stack
用于入棧,pop_stack
用于出棧,而最有用的是peek_stack
函數(shù),該函數(shù)可用于檢查指定堆棧位置處的內(nèi)存參數(shù),利用這個(gè)特性就可以實(shí)現(xiàn),對堆棧地址的檢測,或?qū)Χ褩5膾呙璧取?/p>
LyScript項(xiàng)目地址:https://github.com/lyshark/LyScript
peek_stack命令傳入的是堆棧下標(biāo)位置默認(rèn)從0開始,并輸出一個(gè)十進(jìn)制有符號(hào)長整數(shù),首先實(shí)現(xiàn)有符號(hào)與無符號(hào)數(shù)之間的轉(zhuǎn)換操作,為后續(xù)堆棧掃描做準(zhǔn)備。
from LyScript32 import MyDebug # 有符號(hào)整數(shù)轉(zhuǎn)無符號(hào)數(shù) def long_to_ulong(inter,is_64 = False): if is_64 == False: return inter & ((1 << 32) - 1) else: return inter & ((1 << 64) - 1) # 無符號(hào)整數(shù)轉(zhuǎn)有符號(hào)數(shù) 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("連接狀態(tài): {}".format(connect_flag)) for index in range(0,10): # 默認(rèn)返回有符號(hào)數(shù) stack_address = dbg.peek_stack(index) # 使用轉(zhuǎn)換 print("默認(rèn)有符號(hào)數(shù): {:15} --> 轉(zhuǎn)為無符號(hào)數(shù): {:15} --> 轉(zhuǎn)為有符號(hào)數(shù): {:15}". format(stack_address, long_to_ulong(stack_address),ulong_to_long(long_to_ulong(stack_address)))) dbg.close()
通過上述封裝函數(shù),即可實(shí)現(xiàn)對有符號(hào)和無符號(hào)數(shù)的轉(zhuǎn)換。
繼續(xù)完善該功能,我們使用get_disasm_one_code()
函數(shù),掃描堆棧地址并得到該地址處的反匯編代碼。
from LyScript32 import MyDebug # 有符號(hào)整數(shù)轉(zhuǎn)無符號(hào)數(shù) def long_to_ulong(inter,is_64 = False): if is_64 == False: return inter & ((1 << 32) - 1) else: return inter & ((1 << 64) - 1) # 無符號(hào)整數(shù)轉(zhuǎn)有符號(hào)數(shù) 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("連接狀態(tài): {}".format(connect_flag)) for index in range(0,10): # 默認(rèn)返回有符號(hào)數(shù) stack_address = dbg.peek_stack(index) # 反匯編一行 dasm = dbg.get_disasm_one_code(stack_address) # 根據(jù)地址得到模塊基址 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()
得到的堆棧參數(shù)如下:
由此我們可以得到堆棧處的反匯編參數(shù),但如果我們需要檢索堆棧特定區(qū)域內(nèi)是否存在返回到模塊的地址,該如何實(shí)現(xiàn)呢?
其實(shí)很簡單,首先我們需要得到程序全局狀態(tài)下的所有加載模塊的基地址,然后得到當(dāng)前堆棧內(nèi)存地址內(nèi)的實(shí)際地址,并通過實(shí)際內(nèi)存地址得到模塊基地址,對比全局表即可拿到當(dāng)前模塊是返回到了哪里。
from LyScript32 import MyDebug # 有符號(hào)整數(shù)轉(zhuǎn)無符號(hào)數(shù) def long_to_ulong(inter,is_64 = False): if is_64 == False: return inter & ((1 << 32) - 1) else: return inter & ((1 << 64) - 1) # 無符號(hào)整數(shù)轉(zhuǎn)有符號(hào)數(shù) 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("連接狀態(tài): {}".format(connect_flag)) # 得到程序加載過的所有模塊信息 module_list = dbg.get_all_module() # 向下掃描堆棧 for index in range(0,10): # 默認(rèn)返回有符號(hào)數(shù) stack_address = dbg.peek_stack(index) # 反匯編一行 dasm = dbg.get_disasm_one_code(stack_address) # 根據(jù)地址得到模塊基址 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()
運(yùn)行后,即可掃描到堆棧內(nèi)的所有返回模塊的位置。
到此這篇關(guān)于LyScript實(shí)現(xiàn)對內(nèi)存堆棧掃描的方法詳解的文章就介紹到這了,更多相關(guān)LyScript內(nèi)存堆棧掃描內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中使用zip函數(shù)出現(xiàn)<zip object at 0x02A9E418>錯(cuò)誤的原因
這篇文章主要介紹了python中使用zip函數(shù)出現(xiàn)<zip object at 0x02A9E418>錯(cuò)誤的原因分析及解決方法,需要的朋友可以參考下2018-09-09Python3操作Excel文件(讀寫)的簡單實(shí)例
這篇文章主要給大家介紹了關(guān)于Python3操作Excel文件(讀寫)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Python計(jì)算一個(gè)給定時(shí)間點(diǎn)前一個(gè)月和后一個(gè)月第一天的方法
這篇文章主要介紹了Python計(jì)算一個(gè)給定時(shí)間點(diǎn)前一個(gè)月和后一個(gè)月第一天的方法,涉及Python使用datetime模塊計(jì)算日期時(shí)間的相關(guān)操作技巧,需要的朋友可以參考下2018-05-05Python非單向遞歸函數(shù)如何返回全部結(jié)果
這篇文章主要介紹了Python非單向遞歸函數(shù)如何返回全部結(jié)果,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Pytorch evaluation每次運(yùn)行結(jié)果不同的解決
今天小編就為大家分享一篇Pytorch evaluation每次運(yùn)行結(jié)果不同的解決,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01Python callable內(nèi)置函數(shù)原理解析
這篇文章主要介紹了Python callable內(nèi)置函數(shù)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03