Last active
June 29, 2023 12:05
-
-
Save ngn999/c611758be295b7056f26dcd115a48528 to your computer and use it in GitHub Desktop.
parsing bitcoin transaction script in lldb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lldb | |
import shlex | |
# push value | |
OP_PUSHDATA1 = 0x4c | |
OP_PUSHDATA2 = 0x4d | |
OP_PUSHDATA4 = 0x4e | |
def print_script(debugger, command, result, internal_dict): | |
target = lldb.debugger.GetSelectedTarget() | |
thread = target.GetProcess().GetSelectedThread() | |
frame = thread.GetSelectedFrame() | |
args = shlex.split(command) | |
if len(args) == 0: | |
print('please input a variable') | |
return | |
size = frame.EvaluateExpression("(int)%s.size()" % args[0]) | |
script_size = int(size.GetValue()) | |
pc = 0 | |
readable_script = [] | |
while pc < script_size: | |
opcode = frame.EvaluateExpression("%s[%d]" % (args[0], pc)) | |
opcode.SetFormat(lldb.eFormatUnsigned) | |
currentpc = pc | |
pc += 1 | |
# push data | |
if int(opcode.GetValue()) <= OP_PUSHDATA4: | |
nsize = 0 | |
if int(opcode.GetValue()) < OP_PUSHDATA1: | |
nsize = int(opcode.GetValue()) | |
readable_script.append("%d" % nsize) | |
elif int(opcode.GetValue()) == OP_PUSHDATA1: | |
pcvalue = frame.EvaluateExpression("%s[%d]" % (args[0], currentpc)) | |
pc += 1 | |
pcvalue.SetFormat(lldb.eBasicTypeUnsignedShort) | |
nsize = int(pcvalue.GetValue()) | |
readable_script.append("OP_PUSHDATA1") | |
elif int(opcode.GetValue()) == OP_PUSHDATA2: | |
readable_script.append("OP_PUSHDATA2") | |
elif int(opcode.GetValue()) == OP_PUSHDATA4: | |
readable_script.append("OP_PUSHDATA4") | |
# push data | |
index = pc | |
c = 0 | |
data_hex_string = "0x" | |
while index < script_size and c < nsize: | |
data = frame.EvaluateExpression("%s[%d]" % (args[0], index)) | |
data.SetFormat(lldb.eFormatHex) | |
data_hex_string = data_hex_string + data.GetValue()[2:] | |
index += 1 | |
c += 1 | |
pc += nsize | |
readable_script.append(data_hex_string) | |
continue | |
else: | |
# other opcode | |
opname = frame.EvaluateExpression("GetOpName((opcodetype)%s[%d])" % (args[0], currentpc)) | |
opname.SetFormat(lldb.eFormatCString) | |
readable_script.append(opname.GetValue()) | |
print(' '.join(readable_script).replace('"', '')) | |
# register this command | |
def __lldb_init_module(debugger, internal_dict): | |
debugger.HandleCommand('command script add --help "print bitcoin script" -f print_script.print_script print_script') | |
print('The "print_script" python command has been installed and is ready for use.') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment