frida-mod tutorial

This tutorial introduces how to use frida-mod.
Frida-mod is trying to make us access functions more easily using Frida. We can call functions, hook and unhook functions.
These functions can come from:

  • Existing modules, the process has loaded these modules after boot. I will call this is get mode.
  • Our modules, we can write these modules in C/C++, and it only supports 2 file formats. .so files and .dll files. I will call this is load mode.

Prepare C/C++ source codes.

get mode

For demonstraction, I wrote sprintf function prototype in file libc.h. For simplicity, we’d better make these source files not depend on other files.

load mode

In theory, we can use module source codes directly, but because we use llvm to parse source code for further process, this compiler may be different than the compiler you compile the actual module. So we may need to do some modifications on it.

Generate typescript wrapper code.

I wrote a python util to generate typescript wrapper code. It’s modinfo2ts.py. You can run modinfo2ts.py --help to get its help page.

get mode

1
./utils/modinfo2ts.py -m get -o modinfos/libc.ts source/libc.h

-m flag specifies mode, get mode is for the existing module;
-o flag specifies the output typescript file name;
the last argument is the source file, and it supports multiple source files;

load mode

1
./utils/modinfo2ts.py -m load -b c/bins/win64.dll -o modinfos/libwin64.ts c/mod_win.cc

-m flag specifies mode, load mode is for our own modules;
-b flag specifies compiled module binary file;
-o flag specifies the output typescript file name;
the last argument is the source file, and it supports multiple source files, I use module source code here;

The generated code exports a mod variable.

Test generated typescript module

I wrote index.ts to test generated TS module.
We need to import module as follows

1
2
3
4
5
6
7
import { mod as libcmodinfo } from './modinfos/libc'
import { mod as liblinux_x64info } from './modinfos/liblinux_x64'
import { mod as liblinux_x86info } from './modinfos/liblinux_x86'
import { mod as libarm64info } from './modinfos/libarm64'
import { mod as libarm32info } from './modinfos/libarm32'
import { mod as libwin64info } from './modinfos/libwin64'
import { mod as libwin32info } from './modinfos/libwin32'

We need to use the alias to avoid the dupulcation of mod names.

Get mode

Function testLibcSprintf calls sprintf function in libc module.

1
2
3
4
5
6
7
8
9
10
11
// we need to specify the actual module name in here. 
// use the following code to get the module containing `sprintf`
// let p = Module.getExportByName(null,'sprintf)
// let m = Process.getModuleByAddress(p);
// console.log(JSON.stringify(m))
let libc = libcmodinfo.get(modname);
let buff = Memory.alloc(Process.pageSize);
// use libc.functions.sprintf.call to call sprintf
libc.functions.sprintf.call(buff, Memory.allocUtf8String("%s %d"), Memory.allocUtf8String('1 + 2 ='), ptr(1+2));
let resStr = buff.readUtf8String();
console.log('result', resStr);

Load mode

Function testLibAdd call add function implemented in our module

load module

I try to explain how to load the module on arm64 platform here. The passed parameters are slightly different on every platform.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let lib = libarm64info.load(
[ // an array of depended libraries. load function will try to resolve symbols at these libraries.

],
{ // a map for symbols, the key is symbol name, the value is symbol address,
// we can pass our defined frida NativeCall to the loaded module,
// and we can set some never used symbols to null.

_frida_puts : _frida_puts,

_ITM_registerTMCloneTable : ptr(0),
_ITM_deregisterTMCloneTable : ptr(0),
__gmon_start__ : ptr(0),
});

Call functions in our module

1
2
3
4
5
6
let a = 2;
let b = 3;
lib.functions.add.hook(); // hook add function
let res = lib.functions.add.call(a,b); // call add function
lib.functions.add.unhook(); // unhook
console.log('res', res);

Conclusion

I introduced how to access functions in modules using frida-mod. Hope this util can help you write frida code easier.

Todo

  • Fix the bug on win64 platform
  • support variable access
  • support struct parsing
Author

Meng Xipeng

Posted on

2022-12-24

Updated on

2023-10-05

Licensed under

Comments