frida for windows

frida for windows

参考

Frida-Windows 夏洛魂的个人博客

JavaScript API | Frida • A world-class dynamic instrumentation toolkit

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
#include<stdint.h>


int add(int a,int b){
return a+b;
}

int main(){
int a=6;
int b=7;
printf("%d",add(a,b));
}

很简单的测试脚本 挨个把官方文档的api都试一试

image

搞一个开发环境

1
2
3
git clone https://github.com/oleavr/frida-agent-example.git
cd frida-agent-example/
npm install

网速慢就直接

1
git config --global http.proxy http://127.0.0.1:7897

image

Process

image

image

先给出常见类的几个基础的属性

获取id

1
frida -f  test.exe -l .\exp\hook.js

1
2
var baseaddres =Process.id
console.log(baseaddres)

image

当面对多线程的时候即可使用

1
2
Process.getCurrentThreadId()
Process.enumerateThreads()

进行查看

获取地址

1
2
3
4
5
6
7
8

var baseaddress = Process.mainModule;
console.log("Main module:", baseaddress);
console.log("Base address:", baseaddress.base);
console.log("Name:", baseaddress.name);
console.log("Path:", baseaddress.path);
console.log("Size:", baseaddress.size);

image

获取到目前加载的模块

1
2
3
4
5
6
7
8
9
10
// 获取目标模块的符号表
var symbols = Process.enumerateModules()

// 遍历并打印符号信息
symbols.forEach(symbols =>{
console.log('Name:', symbols.name,
'Type:', symbols.size,
'Module:', symbols.base,
'Address:', symbols.path)
})

image

获取模块地址

Process.findModuleByAddress(address)

Process.getModuleByAddress(address)

Process.findModuleByName(name)

Process.getModuleByName(name)

其实功能都差不多 就是弹不弹异常的区别 get失败返回null find失败直接异常

1
2
3
4
5
6
7
8
9
10
// 获取目标模块的符号表
var symbols = Process.findModuleByAddress(0x7ffedc230000)
console.log(symbols)
// 遍历并打印符号信息

console.log('Name:', symbols.name,
'Type:', symbols.size,
'Module:', symbols.base,
'Address:', symbols.path);

获取module内存的信息

1
2
3
4
5
var Moduleaddres = Process.findModuleByName("msvcrt.dll")

var address=Process.findRangeByAddress(ptr(Moduleaddres.base))

console.log(address.base,address.size,address.file,address.protection)

image

Module

hook函数

1
2
3
4
5
6
7
8
9
10
var addres =Module.findBaseAddress("test.exe").add(0x1550)
console.log(addres)
Interceptor.attach(addres,{
onEnter(args){
console.log("yes")
},
onLeave(reda){
console.log(reda)
}
})

image

获取到参数 修改返回值

1
2
3
4
5
6
7
8
9
10
var addres =Module.findBaseAddress("test.exe").add(0x1550)
console.log(addres)
Interceptor.attach(addres,{
onEnter(args){
console.log(args[0],args[1])
},
onLeave(reda){
reda.replace(1000)
}
})

image

获取到导入module信息 返回列表

1
2
3
4
5
6
7
8
9
10
// 获取目标模块的导入函数列表
const imports = Module.enumerateImports("test.exe");

// 遍历并打印所有导入函数
imports.forEach(imp => {
console.log('Name:', imp.name,
'Type:', imp.type,
'Module:', imp.module,
'Address:', imp.address);
});

image

获取导出信息 返回列表

1
2
3
4
5
6
7
8
9
// 获取目标模块的导出函数列表
const exports = Module.enumerateExports("msvcrt.dll");
console.log("yes")
// 遍历并打印所有导出函数
exports.forEach(exp => {
console.log('Name:', exp.name,
'Type:', exp.type,
'Address:', exp.address);
});

image

获取目标模块的符号表

1
2
3
4
5
6
7
8
9
10
// 获取目标模块的符号表
const symbols = Module.enumerateSymbols("msvcrt.dll");

// 遍历并打印符号信息
symbols.forEach(sym => {
console.log('Name:', sym.name,
'Type:', sym.type,
'Address:', sym.address,
'Size:', sym.size);
});

image

字符串读取api

API 说明
{NativePointer}.readCString() 读取C风格字符串
{NativePointer}.readAnsiString() 读取Ansi字符串
{NativePointer}.readUtf8String() 读取UTF8字符串
{NativePointer}.readUtf16String() 读取UTF16字符串

Frida提供的读取数值API

API 说明
{}.readInt() 从给定地址读取整数
{}.readUInt() 从给定地址读取无符号整数
{}.readS8() 从指定地址读取带符号的8位、16位、32位或64位整数
{}.readShort() 从给定地址读取短整数
{}.readFloat() 从给定地址读取浮点数
{}.readDouble() 从给定地址读取双浮点数
{}.readLong() 从给定地址读取长数字
{}.readULong() 从给定地址读取无符号长数字
{}.readUShort() 从给定地址读取无符号短数
{}.readUS8() 从给定地址读取无符号整数

Frida提供的数值写入API

API 说明
{}.writeInt() 向给定地址写入整数
{}.writeUInt() 向给定地址写入无符号整数
{}.writeS8() 向给定地址写入带符号的8位、16位、32位或64位整数
{}.writeShort() 向给定地址写入短整数
{}.writeFloat() 向给定地址写入浮点数
{}.writeDouble() 向给定地址写入双浮点数
{}.writeLong() 向给定地址写入长数字
{}.writeULong() 向给定地址写入无符号长数字
{}.writeUShort() 向给定地址写入无符号短数
{}.writeUS8() 向给定地址写入无符号整数

Hexdump

1
2
3
4
var baseaddres = Process.mainModule
console.log(baseaddres.base)

console.log(hexdump(baseaddres.base, {offset: 0,length: 16,header: false,ansi: true}))

创建本地函数

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
new NativeFunction(address, returnType, argTypes[, abi])

//TYPES 可选如下:
void
pointer
int
uint
long
ulong
char
uchar
size_t
ssize_t
float
double
int8
uint8
int16
uint16
int32
uint32
int64
uint64
bool

//ABIS 可选如下:
default
Windows 32-bit:
sysv
stdcall
thiscall
fastcall
mscdecl
Windows 64-bit:
win64
UNIX x86:
sysv
unix64
UNIX ARM:
sysv
vfp
1
2
3
4
5
6
var baseaddres =Process.mainModule
console.log(baseaddres.base)

var myfunction =new NativeFunction(baseaddres.base.add(0x1550),"int",["int","int"])

console.log(myfunction(1000,1200))

image

函数替换

使用nterceptor.replace()进行操作

1
2
3
4
5
6
var baseaddres =Process.mainModule
console.log(baseaddres.base)

Interceptor.replace(baseaddres.base.add(0x1550),new NativeCallback(function(a,b){
return a*b
},'int', ['int', 'int']))

image

内存扫描

1
2
3
//pattern的格式为由空格分隔的16进制字符串
Memory.scan(address, size, pattern, callbacks)
Memory.scanSync(address, size, pattern)

寄存器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var addPtr = Process.mainModule.base.add(0x16F8F0)

Interceptor.attach(addPtr, {
onEnter (args) {
// console.log('args0:' + args[0]);
// console.log('args1:' + args[1]);

console.log('args1:' + this.context.rcx.toInt32());
console.log('args2:' + this.context.rdx.toInt32());
}
});

//修改寄存器
// Memory.patchCode(addPtr, Process.pointerSize, function (code) {
// const cw = new X86Writer(code, { pc: addPtr });
// cw.putMovRegU32('eax', 1234);
// cw.putRet();
// cw.flush();
// });