代码转载自:https://github.com/Dvd848/CTFs/blob/master/2021_picoCTF/Hurry_up_Wait.md 添加了部分备注。
下面这部分代码在 Ghidra - Window - Python 中运行:
import sys
# 给出 offset,得到地址
def getAddress(offset):
return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset)
listing = currentProgram.getListing()
functionManager = currentProgram.getFunctionManager()
# getGlobalFunctions 会返回 [FUN_0010298a] 这个 list
main_func = getGlobalFunctions("FUN_0010298a")[0]
# listing.getCodeUnits() 可以得到提供的地址范围内的所有 code/instructions,codeUnit 就是一条指令
# main_func.getBody() 会得到这个函数的 body 的地址范围:[[0010298a, 00102a26] ]
# Iterate the instructions that FUN_0010298a() is composed of
for codeUnit in listing.getCodeUnits(main_func.getBody(), True):
if not codeUnit.toString().startswith("CALL"):
# Ignore anything that isn't a "call"
continue
# codeUnit.getAddress(0) 得到指令中的地址(一般是 offset 而非真正的地址)
# functionManager.getFunctionAt(address) 获取指定 address 的函数,注意 getAddress 函数是自定义的
callee = functionManager.getFunctionAt(getAddress(str(codeUnit.getAddress(0))))
if not callee.getName().startswith("FUN_"):
# In practice - skip ada__calendar__delays__delay_for()
continue
for cu in listing.getCodeUnits(callee.getBody(), True):
# Iterate the instructions that the callee is composed of
if not cu.toString().startswith("LEA RAX"):
# Ignore anything that isn't LEA RAX, [addr]
# since that's the instruction that loads the flag character to be printed
continue
# cu.getScalar(1) 获取指令中的第1个(实际是第2个)标量,前面应该还有第0个标量
# Check what's at "addr" and print it
sys.stdout.write(chr(getByte(getAddress(str(cu.getScalar(1))))))
print("")