运行环境

这里以winmine扫雷程序为例,加载的文件是info.js,运行环境从默认的QJS改为了V8。

frida -f winmine.exe -l info.js --runtime=v8
  • 1.

JavaScript代码函数:

// 运行时信息
function showRuntimeInfo() {
    console.log('Frida.version:', Frida.version);
    console.log('Frida.heapSize:', Frida.heapSize);
    console.log('Script.runtime:', Script.runtime);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_Memory

进程(Process)

// 进程(Process)
function showProcessInfo() {
    console.log("Process.id:\t\t", Process.id);
    console.log("Process.getCurrentThreadId():\t", Process.getCurrentThreadId());
    console.log("Process.arch:\t\t", Process.arch);
    console.log("Process.platform:\t", Process.platform);
    console.log("Process.pageSize:\t", Process.pageSize);
    console.log("Process.pointerSize:\t", Process.pointerSize);
    console.log("Process.codeSigningPolicy:\t", Process.codeSigningPolicy);
    console.log("Process.getCurrentDir():\t", Process.getCurrentDir());
    console.log("Process.getHomeDir():\t", Process.getHomeDir());
    console.log("Process.getTmpDir():\t", Process.getTmpDir());

    let threads = Process.enumerateThreads();
    for (const iterator of threads) {
        console.log(JSON.stringify(iterator));
    }

    let modules = Process.enumerateModules();
    for (const iterator of modules) {
        console.log(JSON.stringify(iterator));
    }

    let ranges = Process.enumerateRanges("rwx");
    for (const iterator of ranges) {
        console.log(JSON.stringify(iterator));
    }

    // let mallocRanges = Process.enumerateMallocRanges();
    // for (const iterator of mallocRanges) {
    //   console.log(JSON.stringify(iterator));
    // }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_汇编_02

Thread(线程)

// Thread(线程)
function showThreadInfo() {
    // Thread.backtrace
    // Thread.sleep
    console.log("Thread.sleep(1000) start...");
    // 单位:秒、seconds
    Thread.sleep(1)
    console.log("Thread.sleep(1000) finish...");
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_拦截器_03

Module(模块)

// Module(模块)
function showModuleInfo() {
    let module = Process.getModuleByName("winmine.exe");
    // let module = Process.getModuleByName("user32.dll");
    // module = Process.getModuleByName("Kernel32.dll");
    console.log("module", JSON.stringify(module, null, 4));

    for (const iterator of module.enumerateImports()) {
        console.log(JSON.stringify(iterator));
    }

    for (const iterator of module.enumerateExports()) {
        console.log(JSON.stringify(iterator));
    }

    for (const iterator of module.enumerateSymbols()) {
        console.log(JSON.stringify(iterator));
    }

    // enumerateRanges
    for (const iterator of module.enumerateRanges("r--")) {
        console.log(JSON.stringify(iterator));
    }

    // {"type":"function","name":"lstrlenW","address":"0x7630e0b0"}
    let p = module.findExportByName("lstrlenW");
    console.log(p);

    let p1 = Module.load("DBGHELP.DLL");
    console.log(JSON.stringify(p1));
    for (const iterator of p1.enumerateExports()) {
        console.log(JSON.stringify(iterator));
    }

    for (const iterator of p1.enumerateImports()) {
        console.log(JSON.stringify(iterator));
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_Memory_04

内存

function showMemory() {
    let module = Process.getModuleByName("winmine.exe");
    // Memory.scan(module.base, module.size, pattern, {
    Memory.scan(module.base, module.size, "04 ?? ?1 ?0", {
        onMatch: (address, size) => {
            console.log("onMatch", size, address, address.sub(module.base));
        },

        onError: (reason) => {
            console.log(reason);
        },

        onComplete: () => {
            console.log("Scan Complete!");
        }
    });
    // let matches = Memory.scanSync(module.base, module.size, pattern);
    let matches = Memory.scanSync(module.base, module.size, "04 ?? ?1 ?0");
    for (const iterator of matches) {
        console.log(JSON.stringify(iterator));
    }

    let m1 = Memory.alloc(Process.pageSize);
    console.log("protect", JSON.stringify(Process.getRangeByAddress(m1)));
    Memory.protect(m1, Process.pageSize, "r-x");
    console.log("protect", JSON.stringify(Process.getRangeByAddress(m1)));

    let lpText = Memory.allocUtf16String("This is a string!");
    let lpCaption = Memory.allocUtf16String("Caption");

    // WinApi.MessageBox(p, lpText, lpCaption, 0x00000001);

    let m2 = Memory.alloc(Process.pageSize);
    console.log("m2", m2);
    let address = Module.getExportByName("User32.dll", "MessageBoxW");

    Memory.patchCode(m2, Process.pageSize, (code) => {
        // console.log("code", code);
        let asm = new X86Writer(code);
        asm.putPushU32(0x00000001);
        asm.putPushU32(lpCaption.toUInt32());
        asm.putPushU32(lpText.toUInt32());
        // asm.putPushU32(p.toUInt32());
        asm.putPushU32(0);
        asm.putCallAddress(address);
        asm.putRet();
        asm.flush();
    });

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_javascript_05

拦截器

拦截器Interceptor用于在运行时拦截和修改函数调用, 一个入口函数onEnter,一个出口函数onLeave。通过Frida Interceptor,你可以监视并修改应用程序中特定函数的行为,比如修改函数的参数、返回值等。

// 拦截器
function showInterceptorInfo() {
    let address = Module.getExportByName("User32.dll", "DispatchMessageW");
    Interceptor.attach(address, {
        onEnter(args) {
            console.log(JSON.stringify(this.context));
            console.log(args[0]);
            console.log(args[1]);
            console.log(args[2]);
            console.log(args[3]);
            console.log(args[4]);
            console.log(args[5]);

            let msg = args[0];

            console.log("hwnd", msg.readPointer());
            console.log("message", msg.add(4).readPointer());
            console.log("wParam", msg.add(8).readPointer());
            console.log("lParam", msg.add(12).readPointer());
            console.log("pt", msg.add(20).readPointer());
            console.log("lPrivate", msg.add(24).readPointer());
        }
    });
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_JSON_06

function injectMessage(){
    // 获取MessageBoxA地址
    const funcAddr = Module.findExportByName('user32.dll', 'MessageBoxW')
    // hook MessageBoxA
    Interceptor.attach(funcAddr, {
      // 进入函数前打印第一个参数(从0开始计算,第0个参数为句柄)
      onEnter(args) {
        send("HOOK MessageBoxA args[1] = " + args[1].readUtf16String())
        send("HOOK MessageBoxA args[2] = " + args[2].readUtf16String())
        console.log("end");
      }
    });
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_JSON_07

汇编代码

// 显示汇编代码
function showAsm(start, length) {
    for (let index = 0; index < length; index++) {
        let inst = Instruction.parse(start);
        // console.log(JSON.stringify(inst));
        let byteArray = start.readByteArray(inst.size);
        let byteCode = Array.prototype.slice.call(new Uint8Array(byteArray));
        let mCode = byteCode.map(x => x.toString(16).padStart(2, "0")).join(" ").toUpperCase();
        console.log(inst.address.toString().toUpperCase().replace("0X", "0x"), mCode.padEnd(14, " "), "\t", inst.toString().toUpperCase().replace("0X", "0x"));

        start = inst.next;
        if (start.readU32() == 0) break;
    }
}

// 测试功能函数封装(snippets)
function testSnippets() {
    let address = Module.getExportByName("User32.dll", "MessageBoxW");
    console.log(address);
    showAsm(address, 10);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

Frida查看运行环境、进程、线程、模块、内存、拦截器、汇编代码_拦截器_08

相关链接

 https://frida.re/docs/examples/javascript/ https://frida.re/docs/javascript-api/