日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

LyScript實現對內存堆棧掃描的方法詳解_python

作者:lyshark ? 更新時間: 2022-09-28 編程語言

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()

運行后,即可掃描到堆棧內的所有返回模塊的位置。

原文鏈接:https://www.cnblogs.com/LyShark/p/16545888.html

欄目分類
最近更新