pyd逆向处理

一,初查:

1.查版本

先用die或者ida或者010查看pyd对应的版本号

假如版本不对的话是不能运行的

2.查函数和参数

可以使用 python自带的help()dir()函数,查看里面有什么函数或者参数

二,静态分析

通过查字符串可以找到这样函数的结构:
image

PyLong_FromLong()是固定数据

后面那个基地址加偏移是函数的位置

可以先像这样记录下来,以便以后查询或者猜测数据

29:0
30:1
31:2
32:4
33:5
.......

通过查字符串还能找到这样的结构

image

最底下的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
    }
    
}

posted @ 2025-10-26 17:53  漫宿骄盛  阅读(70)  评论(0)    收藏  举报