如何使用python通过LLDB读写一个寄存器?

How to use python to read and write a register via LLDB?

我正在尝试使用 python 到 read/write 一个寄存器,当它到达断点时。

我能够在触发断点时执行一个简单的 python 脚本。

我遇到的问题是读写单个寄存器。我可以获得寄存器列表,但不是寄存器。

* thread #1, stop reason = signal SIGSTOP
    frame #0: 0x000000010521562c dyld` ImageLoaderMachO::usablePrebinding(ImageLoader::LinkContext const&) const  + 56
dyld`ImageLoaderMachO::usablePrebinding:
->  0x10521562c <+56>: ldrb   w8, [x19, #0x76]
    0x105215630 <+60>: ldrh   w9, [x19, #0x74]
    0x105215634 <+64>: bfi    w9, w8, #16, #8
    0x105215638 <+68>: tbz    w9, #0x9, 0x105215694     ; <+160>
    0x10521563c <+72>: ldr    x8, [x19]
    0x105215640 <+76>: ldr    x8, [x8, #0x378]
    0x105215644 <+80>: mov    x0, x19
    0x105215648 <+84>: blr    x8
Target 0: (BBM) stopped.
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> print lldb.frame.registers

任何人都可以帮我 python api 我可以用来更改 x1 寄存器值吗?

SBFrames 上的 registers 属性 是一个 SBValueList,用于存储寄存器组(GPR 等)。每个寄存器集都是一个 SBValue,各个寄存器表示为寄存器集的子项,子项名称是寄存器名称。 x1 是 GPR,GPR 始终是 registers 中设置的第一个寄存器。 SBValueListGetFirstValueByName 按名称获取元素,因此您还可以通过编程方式查找 "General Purpose Register"。

所以你会做这样的事情:

error = lldb.SBError()
did_change = lldb.frame.registers[0].GetChildMemberWithName('x1').SetValueFromCString("0x12345",error)

SetValueFromCString returns True 如果能够更改值,如果不能,原因将存储在 error 参数中.

请注意,像 x1 这样的易失性寄存器不会跨函数调用存储,因此您只能在当前执行的帧中访问或更改它们的值。

SBValues 描述如下:

https://lldb.llvm.org/python_reference/lldb.SBValue-class.html

如果您想知道您还可以用它们做什么。

registers 属性 的替代方法是 register 属性。通过名称访问寄存器很方便。例如:

(lldb) script print lldb.frame.register["x1"].value
(lldb) script lldb.frame.register["x1"].value = "0"

@Dave Lee 的回答在 lldbscript 界面有效。

当我在完整脚本中尝试相同操作时,我得到的是空寄存器值。

文档https://lldb.llvm.org/use/python-reference.html 解释了所有内容。您需要传入 exe_ctx 才能获得正确的 context。这是 lldb.SBExecutionContext.

def YDFooBarFunction(debugger, command, exe_ctx, result, internal_dict):
    """
        Reads and writes a register.
    """
    frame = exe_ctx.frame
    error = lldb.SBError()
    disposition = frame.FindRegister("rsi")
    print("[*]Original register: " + str(disposition))

    if disposition.unsigned == 2:
        print "[!]found 2 in the register"
        result = frame.registers[0].GetChildMemberWithName('rsi').SetValueFromCString("0x1", error)
        messages = {None: 'error', True: 'pass', False: 'fail'}
        print ("[*]PATCHING result: " + messages[result])

    thread = frame.GetThread()
    process = thread.GetProcess()
    process.Continue()

我希望这可以节省人们打猎的时间。

请注意,我使用了伟人 (@Jim Ingham) 的部分答案来编写寄存器。