好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 Juana111 于 2025-3-22 16:36 编辑
0x00 搞清楚Fri.da和Objection的区别
表格一 fri.da&objection
b1
表格中跨平台支持解释:FrIDA的跨平台支持中提到的Windows平台的使用,这里的Windows平台使用是可以通过Frida直接对Windows系统的程序进行调试,使用macOS和Windows作为例子来说有两个连接方式:1.在Windows上运行frida-server使用macOS进行连接。 - 运行frida-server
- 确保 Windows 和 macOS 在同一个网络中。
- 获取 Windows 的 IP 地址(在 Windows 上运行 ipconfig)。
- 在 macOS 上使用 Frida 客户端连接到 Windows:
- frida -H <Windows IP> -n <进程名>
- 连接成功后,在 macOS 上编写和加载 JavaScript 脚本,对 Windows 上的目标进程进行 Hook 和调试。
2.在windows上运行frida-server并调试本地进程- 运行frida-server
- frida -n <进程名>
- 连接成功后,直接在 Windows 上编写和加载 JavaScript 脚本,对本地进程进行 Hook 和调试。
表格二
b2
0x01 frida的JavaScript脚本
表格一中提到的javascript脚本,Frida可以通过javascript脚本hook应用程序的函数,拦截函数的输入参数、返回值以及执行流程。
1.hook函数- 修改函数行为(如绕过验证、修改返回值)。
- 监控函数的调用频率和参数值。
- 分析加密算法、网络请求等关键逻辑。
[JavaScript] 纯文本查看 复制代码 1 2 3 | Interceptor.attach(Module.findExportByName( "libc.so" , "strcmp" ), {onEnter: function (args) {
console.log( "strcmp called with:" , args[0].readCString(), args[1].readCString());},onLeave: function (retval) {
console.log( "strcmp returned:" , retval);}});
|
2. 动态修改内存
通过 JavaScript 脚本,Frida 可以读取和修改目标进程的内存数据。- 修改内存中的变量值或字符串。
- 绕过某些内存中的校验逻辑。
- 动态篡改应用的行为。
[JavaScript] 纯文本查看 复制代码 1 2 3 | var ptr = Module.findBaseAddress( "libnative.so" ).add(0x1234);Memory.writeUtf8String(ptr, "new_value" );
|
3. 调用函数
通过 JavaScript 脚本直接调用目标应用程序中的函数- 触发特定功能以测试其行为。
- 调用未导出的函数或私有方法。
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 6 | var func = new NativeFunction(Module.findExportByName( "libnative.so" , "my_function" ), 'int' , [ 'int' ]);
var result = func(123);
console.log( "Function returned:" , result);
|
4. 监控和拦截系统调用
Frida 可以监控目标应用程序与操作系统之间的交互,如文件读写、网络请求等。- 分析应用程序的文件操作行为。
- 拦截网络请求,查看或修改请求数据。
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 | var openPtr = Module.findExportByName( null , "open" );
Interceptor.attach(openPtr, {
onEnter: function (args) {
console.log( "Opening file:" , args[0].readCString());
},
onLeave: function (retval) {
console.log( "File opened with fd:" , retval);
}
});
|
open函数的原型int open(const char *pathname, int flags, mode_t mode);- args[0] 是第一个参数 pathname,表示要打开的文件路径。
- args[1] 是第二个参数 flags,表示打开文件的标志。
- args[2] 是第三个参数 mode,表示文件的权限模式(如果创建文件)
5.动态加载和卸载模块
Frida 可以在运行时加载或卸载目标应用程序中的模块(如 SO 文件)。[JavaScript] 纯文本查看 复制代码 1 2 | var module = Process.findModuleByName( "libnative.so" );[/font]
console.log( "Module base address:" , module.base);
|
这个功能对我来说比较抽象,具体的场景是在目标应用程序在运行时加载的某些模块(插件,广告SDK,加密库),例如一些恶意软件可能会在运行时动态加载加密模块来隐藏行为。 举例: 某个程序加密库在加载之后解密数据,此时就要hook掉解密函数来获取解密后的内容
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 | var module = Process.findModuleByName( "libcrypto.so" );
if (module) {
var decryptFunc = Module.findExportByName( "libcrypto.so" , "decrypt" );
Interceptor.attach(decryptFunc, {
onEnter: function (args) {
console.log( "Decrypting data:" , args[0].readCString());
},
onLeave: function (retval) {
console.log( "Decrypted data:" , retval.readCString());
}
});
}
|
其他功能:应用程序支持插件或扩展功能,通过动态模块来实现,就要分析插件的导出函数和调用逻辑;检测恶意行为,检测模块的加载行为,用户不知情的情况下加载恶意模块来窃取数据;加载大量模块,导致内存占用过高或启动速度变慢的情况。 6.调试和日志记录 Frida 的 JavaScript 脚本可以用于动态调试和记录应用程序的运行状态。 - 打印函数调用栈。
- 记录关键变量的值。
- 跟踪应用程序的执行流程。
[JavaScript] 纯文本查看 复制代码 1 2 | console.log( "Current thread ID:" , Process.getCurrentThreadId());
console.log( "Backtrace:" , Thread.backtrace( this .context, Backtracer.ACCURATE));
|
7.绕过反调试和检测
Frida 的 JavaScript 脚本可以用于绕过应用程序中的反调试机制。- 修改反调试标志位。
- Hook 反调试函数,使其失效。
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 | var ptracePtr = Module.findExportByName( null , "ptrace" );
Interceptor.replace(ptracePtr, new NativeCallback( function () {
console.log( "ptrace called, bypassing..." );
return 0;
}, 'int' , []));
|
8. 自动化测试和分析
Frida 的 JavaScript 脚本可以用于自动化测试和分析应用程序的行为。- 批量测试函数的输入输出。
- 自动化分析应用程序的逻辑。
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 6 7 8 | function testFunction(input) {
var func = new NativeFunction(Module.findExportByName( "libnative.so" , "my_function" ), 'int' , [ 'int' ]);
var result = func(input);
console.log( "Input:" , input, "Output:" , result);
}
for ( var i = 0; i < 10; i++) {
testFunction(i);
}
|
0x02 Hook脚本
先搞清楚的是frida的JavaScript脚本是指使用Frida的JavaScript API编写的脚本,实现的功能:hook函数、读取和修改内存、调用native函数、动态调试。
hook脚本是frida的javascript脚本的一个子集,专门hook目标函数:拦截函数调用、修改函数行为、监控函数调用。
b3
hook脚本经典结构
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | Java.perform( function () {
var TargetClass = Java.use( "com.example.app.TargetClass" );
TargetClass.targetMethod.implementation = function (arg1, arg2) {
console.log( "targetMethod called with:" , arg1, arg2);
var result = this .targetMethod(arg1, arg2);
return result + 1;
};
});
|
1.常见用途- 动态调试:打印函数参数和返回值;跟踪程序的执行流程。
- 绕过验证:修改函数的返回值,绕过登录验证、许可证检查等。
- 分析加密算法:拦截加密函数的输入和输出,分析其逻辑。
- 修改应用行为:替换函数的实现,改变应用的行为。
- 数据监控:记录敏感数据(如密码、密钥等)。
2.应用
应用验证许可证是否有效
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 6 7 | Java.perform( function () {
var LicenseManager = Java.use( "com.example.app.LicenseManager" );
LicenseManager.checkLicense.implementation = function () {
console.log( "Bypassing license check..." );
return true ;
};
});
|
3.hook脚本的难点
b4
4. 部分hook脚本
4.1.枚举已加载的类
为什么要枚举已加载的类? 已加载的类通过枚举类名,结合方法名、字段名、调用关系来定位目标,动态分析应用的行为。
目标类名被混淆,就可以先枚举已经加载的类
[JavaScript] 纯文本查看 复制代码 1 2 3 4 | Java.perform( function () {
Java.enumerateLoadedClasses({onMatch: function (className) {
console.log(className);},onComplete: function () {}});});
|
4.2.Hook目标方法
找到目标类com.example.app.MainActivity和方法login
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 6 7 8 | Java.perform( function () {
var MainActivity = Java.use( "com.example.app.MainActivity" );
MainActivity.login.implementation = function (username, password) {
console.log( "Login called with:" , username, password);
return true ;
};
});
|
4.3.监控网络请求
应用实现方式:
1.使用系统apiandroid应用使用系统api:HttpURLConnection、OkHttp、Retrofit 等ios应用使用系统api:NSURLSession、NSURLConnection 等。
2.发送请求:构建请求(url,请求头,请求体),发送请求服务器
3.接收响应,接收服务器返回的响应数据(状态码,响应头,响应体)。
Hook思路:
目标应用使用HttpURLConnection
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 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 | Java.perform( function () {
var URL = Java.use( "java.net.URL" );
var HttpURLConnection = Java.use( "java.net.HttpURLConnection" );
URL.openConnection.overload().implementation = function () {
var connection = this .openConnection();
console.log( "URL:" , this .toString());
if (connection.getClass().getName().indexOf( "HttpURLConnection" ) !== -1) {
var httpConnection = Java.cast(connection, HttpURLConnection);
httpConnection.getInputStream.implementation = function () {
console.log( "Request Headers:" , httpConnection.getRequestProperties());
var inputStream = this .getInputStream();
var response = readInputStream(inputStream);
console.log( "Response:" , response);
return inputStream;
};
}
return connection;
};
function readInputStream(inputStream) {
var BufferedReader = Java.use( "java.io.BufferedReader" );
var InputStreamReader = Java.use( "java.io.InputStreamReader" );
var StringBuilder = Java.use( "java.lang.StringBuilder" );
var reader = BufferedReader.$ new (InputStreamReader.$ new (inputStream));
var builder = StringBuilder.$ new ();
var line;
while ((line = reader.readLine()) !== null ) {
builder.append(line);
}
reader.close();
return builder.toString();
}
});
|
目标应用使用 OkHttp
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | Java.perform( function () {
var OkHttpClient = Java.use( "okhttp3.OkHttpClient" );
var Request = Java.use( "okhttp3.Request" );
var Response = Java.use( "okhttp3.Response" );
OkHttpClient.newCall.implementation = function (request) {
console.log( "Request URL:" , request.url().toString());
console.log( "Request Headers:" , request.headers().toString());
var response = this .newCall(request).execute();
console.log( "Response Code:" , response.code());
console.log( "Response Body:" , response.body().string());
return response;
};
});
|
4.4.绕过 SSL Pinning
SSL pinning (SSL 证书绑定)安全机制,防止中间人攻击,核心是将服务器的SSL\TLS证书或公钥硬编码到客户端应用中,客户端与特定的服务器通信,不是与拥有有效证书的服务器通信。
引入机制:
1.证书或公钥绑定,客户端在建立连接,检查服务器返回的证书或公钥是否与硬编码的值匹配
2.防止中间人攻击,攻击者的证书与硬编码值不匹配
实现方式:
1.证书绑定:将服务器的完整证书(通常是 DER 或 PEM 格式)硬编码到客户端应用中。
2.公钥绑定:将服务器的公钥(通常是公钥的哈希值)硬编码到客户端应用中3.证书链绑定:将服务器证书链中的某个中间证书或根证书硬编码到客户端应用中。
绕过方式:
1.修改客户端代码:反编译应用代码,删掉SSL Pinning的实现代码并修改删除
2.使用frida或者objection绕过:
Frida 使用脚本Hook SSL Pinning 相关的函数;
[JavaScript] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | Java.perform( function () {
var X509TrustManager = Java.use( "javax.net.ssl.X509TrustManager" );
var TrustManager = Java.registerClass({
name: "com.example.TrustManager" ,
implements : [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) {},
checkServerTrusted: function (chain, authType) {},
getAcceptedIssuers: function () {
return [];
}
}
});
var SSLContext = Java.use( "javax.net.ssl.SSLContext" );
SSLContext.init.implementation = function (keyManager, trustManager, secureRandom) {
this .init(keyManager, [TrustManager.$ new ()], secureRandom);
};
});
|
使用objection命令:
[JavaScript] 纯文本查看 复制代码 1 | android sslpinning disable
|
4.5.动态修改内存
[JavaScript] 纯文本查看 复制代码 1 2 | var ptr = Module.findBaseAddress( "libnative.so" ).add(0x1234);
Memory.writeUtf8String(ptr, "new_value" );
|
4.6. 处理反调试
目标应用检测Frida,可以hook反调试函数
[JavaScript] 纯文本查看 复制代码 1 2 3 4 5 6 7 8 9 | Java.perform( function () {
var System = Java.use( "java.lang.System" );
System.getProperty.implementation = function (key) {
if (key === "java.vm.name" ) {
return "Dalvik" ;
}
return this .getProperty(key);
};
});
|
|
免费评分
-
查看全部评分
|