pyd逆向处理
一,初查:
1.查版本
先用die或者ida或者010查看pyd对应的版本号
假如版本不对的话是不能运行的
2.查函数和参数
可以使用 python自带的help()和dir()函数,查看里面有什么函数或者参数
二,静态分析
通过查字符串可以找到这样函数的结构:
PyLong_FromLong()是固定数据
后面那个基地址加偏移是函数的位置
可以先像这样记录下来,以便以后查询或者猜测数据
29:0
30:1
31:2
32:4
33:5
.......
通过查字符串还能找到这样的结构

最底下的return里的函数就是这个名字函数的具体逻辑
然后自己分析就行了
三,动调
首先我们要先写一个py脚本引入pyd
然后引入os和sys库
之后使用print(sys.executable) print(os.getpid()) 加载解释器和进程pid
再之后使用input暂停终端
在IDA中选择Local Windows debugger
再点击Debugger,选择attath to process
搜索你刚刚得到的pid,选择那个程序,就可以附加上,然后动调了
例如
import rand0m
import sys
import os
print(sys.executable)
print(os.getpid())
flag = input("Please input: ")
if(rand0m.check(flag)):
print("Congrats! Flag is: flag{"+flag+"}")
else: print("Wrong! Try again!")
rand0m就是pyd库
输出
PS D:\下载文件\ctf\cina_24> py -3.12 a.py
D:\app\python\python.exe
31628
Please input:
在此时打开IDA,依照上面的步骤,附加id搜索31628然后附加就能动调pyd了
四,frida
这里的代码来自于https://imconfident11.github.io/2025/07/15/pyd/
我们需要按照上面的流程获取pid
然后使用下面的模板来运行,里面的脚本名字和pid都需要自己手动改
import frida
import sys
import time
with open("a.js", encoding="utf-8") as f:#读取脚本的名字,需要自己改
jscode = f.read()
def on_message(message, data):
print("[*]", message)
def main():
try:
device = frida.get_local_device()
target = 40836#pid,需要自己改
try:
pid = int(target)
session = device.attach(pid)
except ValueError:
session = device.attach(target)
print(f"[*] Attached to {target}")
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
print("[*] Script loaded. Monitoring Python operations...")
print("[*] Press Ctrl+C to stop and analyze.\n")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n[*] Stopping trace and analyzing...")
try:
# 尝试调用 stop() 函数
script.exports.stop()
except Exception as e:
print(f"[!] Error during stop: {e}")
finally:
# 确保资源被清理
script.unload()
session.detach()
print("[*] Cleanup completed")
except KeyboardInterrupt:
print("\n[*] Exiting...")
except Exception as e:
print(f"[-] Error: {e}")
if __name__ == "__main__":
main()
js 脚本
一般都是hook cpython的库,例如python312.dll python311.dll,关于Cpython有什么数值
然后对里面的数值操作运算做hook,值得注意的是python长整型和大整数还有内部储存格式需要做处理
关于Cpython有什么数值操作函数可以看这个,Cpython:https://docs.python.org/zh-cn/3.12/c-api/number.html#c.PyNumber_Add
这是一个处理参考
function parsePyLong(addr) {
try {
if (!addr || addr.isNull()) {
return 0;
}
const ob_size = addr.add(0x10).readS64();
if (ob_size === 0) return 0;
const isNegative = ob_size < 0;
const numdigits = Math.abs(Number(ob_size));
if (numdigits > 0x1000) {
const digit = addr.add(0x18).readU32();
return isNegative ? -digit : digit;
}
if (numdigits > 2) {
let bigVal = 0n;
for (let i = 0; i < numdigits; i++) {
const digit = addr.add(0x18 + 4 * i).readU32();
bigVal += BigInt(digit) * (1n << (30n * BigInt(i)));
}
return isNegative ? -bigVal : bigVal;
}
let val = 0;
for (let i = 0; i < numdigits; i++) {
val += addr.add(0x18 + 4 * i).readU32() * Math.pow(2, 30 * i);
}
return isNegative ? -val : val;
} catch (e) {
return 0;
}
}
这是另一种,代码来自https://www.cnblogs.com/lordtianqiyi/p/18614184
function parseInt_python12(addr){
var ob_refcnt = addr.readU64()
var ob_type = addr.add(0x8).readU64()
var lv_tag = addr.add(0x10).readU64()
var sign = lv_tag & 3
var numdigits = lv_tag >> 3
let val = 0
for(var i=0;i<numdigits;i++){
val += addr.add(0x18 + 4*i).readU32() * (2 ** (30*i)) // counld not handle BigInt
}
return (1-sign) * val
}
function parseInt_python12(addr){
var ob_refcnt = addr.readU64()
var ob_type = addr.add(0x8).readU64()
var ob_size = addr.add(0x10).readS64() // not unsigned
var numdigits = ob_size
if(ob_size < 0){
numdigits = -numdigits;
}
let val = 0
if (numdigits > 0x10000){ // to big , maby not PyLong
val = addr.add(0x18).readU32()
console.log("unexpected data , " + "0x" + val.toString(16))
}else{
for(var i=0;i<numdigits;i++){
val += addr.add(0x18 + 4*i).readU32() * (2 ** (30*i)) // counld not handle BigInt
}
}
if(ob_size == 0){
return 0
}else if(ob_size >0){
return val
}else if(ob_size <0){
return -val
}
}
本文来自博客园,作者:漫宿骄盛,转载请注明原文链接:https://www.cnblogs.com/msjs/p/19167090
都是顺手发的,写的时候可能有错误,如果发现了,望各位指出。

浙公网安备 33010602011771号