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()
執行後,即可掃描到堆疊內的所有返回模組的位置。