-
-
[分享]2026第二题wp
-
发表于: 2天前 68
-
技术方案:IDA动态调试子进程,断点打在python解释器input处,dump出PyObject进行反编译
基本流程
exe程序执行
生成临时文件python313解释器
python业务代码
分步骤拆解:
题目.ext => sub_7FF70DF940E0
主程序加载python解释器之后,发现C:目录下生成临时文件。断点不再阻塞,主逻辑进入子进程。
python313.dll => sub_7FF97F592350
IDA加载python313.dll,并attach到子进程后,断点往上追堆栈,找到python313相关segment。字符串输入发生在sub_7FF97F592350中
python313.dll => 7FF97F592A79
可以看到这里的v23 = PyUnicode_Decode(v49, v56, const_utf8, const_surrogateescape),是把输入的字符串转为python对象
python313.dll => 7FF97F597738
回答解释器层, PyEval_EvalFrameDefault中的v195 = v193(v194, v1024, v188);是在执行python的input
断点锚定在这个函数,IDAPython dump出 pyc文件:
import idc
import idaapi
def dump_pyc():
rdx = idc.get_reg_value("RDX")
print(f"[*] RDX (Args Array) at: {hex(rdx)}")
pycode_type = idc.get_name_ea_simple("PyCode_Type")
if pycode_type == idc.BADADDR:
print("[-] 找不到 PyCode_Type 符号,请确保 IDA 识别了 DLL 导出表")
return
code_obj = 0
for i in range(0, 0x1000, 8):
addr = rdx - i
try:
f_exec = idc.get_qword(addr)
if f_exec > 0x10000:
ob_type = idc.get_qword(f_exec + 8)
if ob_type == pycode_type:
print(f"[*] 找到 Frame Header: {hex(addr)}")
print(f"[*] 找到目标 PyCodeObject: {hex(f_exec)}")
code_obj = f_exec
break
except:
pass
if not code_obj:
print("[-] 未能在栈上找到 PyCodeObject")
return
marshal_func = idc.get_name_ea_simple("PyMarshal_WriteObjectToString")
idc.SetType(marshal_func, "void* __fastcall PyMarshal_WriteObjectToString(void* obj, int version);")
print("[*] 正在调用 PyMarshal_WriteObjectToString...")
bytes_ptr = idaapi.Appcall.PyMarshal_WriteObjectToString(code_obj, 4)
if not bytes_ptr:
print("[-] Marshal 序列化失败")
return
bytes_ea = bytes_ptr.value
ob_size = idc.get_qword(bytes_ea + 0x10)
print(f"[*] 序列化数据大小: {ob_size} bytes")
pyc_data = idc.get_bytes(bytes_ea + 0x20, ob_size)
header = b'\xcb\x0d\x0d\x0a' + (b'\x00' * 12)
with open("dump-biz.pyc", "wb") as f:
f.write(header + pyc_data)
dump_pyc()
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。