Windows Examples

Frida Windows Examples

Monitor AES Encryption in jvm.dll (BB Simulator)

Target: fledge.exe (BB Simulator) — loads Jvm.dll which performs AES operations Goal: Intercept SetAesDecrypt0 to log plaintext input and encrypted/decrypted output Run: python.exe bb.py fledge.exe

How Address Resolution Works

JVM.dll loads at a different base address each run (ASLR). The intercept address must be rebased:

runtime_address = (runtime_base - ida_base) + function_offset_in_IDA

Where:

Full Script

 1import frida
 2import sys
 3
 4def on_message(message, data):
 5    print("[%s] => %s" % (message, data))
 6
 7def main(target_process):
 8    session = frida.attach(target_process)
 9
10    script = session.create_script("""
11
12    // Step 1: Get runtime base of jvm.dll
13    const baseAddr = Process.getModuleByName('Jvm.dll').base;
14    console.log('Jvm.dll baseAddr: ' + baseAddr);
15
16    // Step 2: Resolve function address from IDA-relative offset
17    const setAesDecrypt0 = resolveAddress('0x1FF44870');
18
19    // Step 3: Intercept the function
20    Interceptor.attach(setAesDecrypt0, {
21
22      onEnter(args) {
23        console.log('');
24        console.log('[+] Called SetAesDeCrypt0 @ ' + setAesDecrypt0);
25        console.log('[+] Ctx:    ' + args[0]);       // AES context pointer
26        console.log('[+] Input:  ' + args[1]);       // Plaintext buffer pointer
27        console.log('[+] Output: ' + args[2]);       // Output buffer pointer
28        console.log('[+] Len:    ' + args[3]);       // Data length
29
30        dumpAddr('Input',  args[1], args[3].toInt32());
31
32        // Save output pointer + length for onLeave
33        this.outptr  = args[2];
34        this.outsize = args[3].toInt32();
35      },
36
37      onLeave(retval) {
38        dumpAddr('Output', this.outptr, this.outsize);
39        console.log('[+] Returned from setAesDecrypt0: ' + retval);
40      }
41    });
42
43    // Dump memory region as hex+ASCII table
44    function dumpAddr(info, addr, size) {
45      if (addr.isNull()) return;
46
47      console.log('Data dump ' + info + ':');
48      const buf = addr.readByteArray(size);
49      console.log(hexdump(buf, {
50        offset: 0,
51        length: size,
52        header: true,
53        ansi: false    // set true for colored terminal output
54      }));
55    }
56
57    // Rebase an IDA address to the current runtime address
58    function resolveAddress(addr) {
59      const idaBase = ptr('0x1FEE0000');       // jvm.dll base in IDA
60      const offset  = ptr(addr).sub(idaBase);  // RVA
61      const result  = baseAddr.add(offset);    // runtime address
62      console.log('[+] Resolved addr=' + result);
63      return result;
64    }
65""")
66    script.on('message', on_message)
67    script.load()
68    print("[!] Ctrl+D on UNIX, Ctrl+Z on Windows/cmd.exe to detach from instrumented program.\n\n")
69    sys.stdin.read()
70    session.detach()
71
72if __name__ == '__main__':
73    if len(sys.argv) != 2:
74        print("Usage: %s <process name or PID>" % __file__)
75        sys.exit(1)
76
77    try:
78        target_process = int(sys.argv[1])
79    except ValueError:
80        target_process = sys.argv[1]
81    main(target_process)

Key APIs Used

APITypePurpose
Process.getModuleByName(name)JSGet module info; .base is the runtime load address
ptr(hexString)JSCreate a NativePointer from a hex string
ptr.sub(other)JSPointer subtraction (returns offset as NativePointer)
ptr.add(other)JSPointer addition (rebase offset to runtime address)
Interceptor.attach(addr, callbacks)JSHook a function by address
args[n]JSNativePointer to the nth argument in onEnter
args[n].toInt32()JSRead argument as 32-bit integer
this.outptr / this.outsizeJSStore state in onEnter for use in onLeave
addr.readByteArray(size)JSRead raw bytes from a pointer
hexdump(buf, opts)JSFormat an ArrayBuffer as a hex+ASCII dump
retvalJSReturn value in onLeave (modifiable via retval.replace(...))
frida.attach(target)PythonAttach to process by name (string) or PID (int)

Address Resolution Pattern (ASLR Rebase)

RVA    = ida_address - ida_base
runtime = module_base + RVA

This pattern applies to any function identified in a disassembler where the module is loaded with ASLR at a different base at runtime.


Running on Windows

 1rem Install frida-tools
 2pip install frida-tools
 3
 4rem List processes
 5frida-ps
 6
 7rem Run the bb.py script
 8python.exe bb.py fledge.exe
 9
10rem Or attach by PID
11python.exe bb.py 1234

Detach: Ctrl+Z then Enter (Windows cmd.exe) or Ctrl+D (Unix-like terminals / Git Bash).