Frida使用和Hook代码整理
本帖最后由 藿香正气 于 2018-5-14 10:46 编辑0x0001 一些废话
最近学习Hook技术,一直使用的是substrate和xposed,这两种框架给我的感觉功能是非常强大的,但是有一些不稳定,有的时候安装模块软重启后机器就起不来了(也可能是我的代码写的不叫渣,总之遇到一些坑),只能进入recovery模式删除模块。最近找到了一个轻量级的hook框架这几天使用了一下感觉非常不错,她就是Firda,她的优点就是比较轻量级,使用python和javascrip进行hook模块的开发,缺点的话我感觉就是js我不太会,下面就上代码吧
0x0002 安装
安装很简单,需要python环境在linux、win的环境都可以,下面就是我在windwos下安装,
1.Python环境就不用多说了 安装后配置环境变量,我使用的是2.7.X的版本
2.安装piphttps://pypi.python.org/pypi/pip, 到这里下载pip-9.0.1.tar.gz (md5, pgp)的安装包,解压后,在命令行下进入这个目录,运行 python setup install 等一会安装就完成了
再讲pip所在的 python\Scripts 添加到命令行,pip就可以用了
3.安装frida 运行命令pip install frida 就好了
4.下载 服务端 https://github.com/frida/frida/releases 到这里找到frida-server-10.0.8-android-arm.xz这里根据自己手机的平台选择就可以了 大多数是android-arm
0x0003 使用
链接手机usb 打开调试模式
1.adb push frida-server-10.0.8-android-arm /data/local/tmp
然后使用root 启动就行了
2.打开另一个命令行
adb forward tcp:27042 tcp:27042
adb forward tcp 27043 tcp 27043
然后输入 frida-ps -R
就会看到手机里所有的进程
0x0004 开始测试
先是目标应用,分为两部分 java + ndk
package com.example.hooktest.jiami;
public class Jiami {
public int jiami(int i ,int j) {
return i*10 + j*11;
}
}
package com.example.hooktest;
import com.example.hooktest.jiami.Jiami;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
static {
System.loadLibrary("test");
}
private TextView tv;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(this);
}
native public String getString();
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Jiami mi = new Jiami();
tv.setText(getString() + mi.jiami(10, 20));
}
}
下面是ndk的
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#defineLOGI(...)__android_log_print(ANDROID_LOG_INFO, "hooktest", __VA_ARGS__)
int getInt(int i)
{
return i+99;
}
JNIEXPORT jstring JNICALL
Java_com_example_hooktest_MainActivity_getString(JNIEnv* env,jobject thiz)
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__mips__)
#define ABI "mips"
#else
#define ABI "unknown"
#endif
LOGI("[+] %d\n", getInt(1));
return (*env)->NewStringUTF(env, ABI);
}
测试是要对jiami这个函数进行hook,也可以对这个函数进行调用生成加密后的数据,第二个是对jni这个接口函数进行调用,也可以调用getInt这个 c函数 下面是代码
Hook_java_method.py
#coding=utf-8
import frida
import sys
session = frida.get_remote_device().attach("com.example.hooktest")
#print session.enumerate_modules()
jscode = """
Java.perform(function(){
send("Running Script");
var getString = undefined;
exports = Module.enumerateExportsSync("libtest.so");
for(i=0; i<exports.length; i++){
if(exports.name == "Java_com_example_hooktest_MainActivity_getString"){
getString = exports.address;
send("getInt is at " + getString);
break;
}
}
var getInt = undefined;
exports = Module.enumerateExportsSync("libtest.so");
for(i=0; i<exports.length; i++){
if(exports.name == "getInt"){
getInt = exports.address;
send("getInt is at " + getInt);
break;
}
}
var fungetInt = new NativeFunction(getInt, 'int', ['int']);
Interceptor.attach(getString,{
onEnter: function (args) {
send("onEnter");
var res = fungetInt(99999);
send(res);
},
onLeave: function (retval) {
send("onLeave");
}
});
});
"""
def on_message(message, data):
print message
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()
这个是调用jiami函数
call_java_method
#coding=utf-8
import frida
import sys
session = frida.get_remote_device().attach("com.example.hooktest")
#print session.enumerate_modules()
jscode = """
Java.perform(function () {
var jiami = Java.use("com.example.hooktest.jiami.Jiami");
var instance = jiami.$new();
var res = instance.jiami(100,200);
send(res);
});
"""
def on_message(message, data):
print message
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()
这个是调用getInt函数
#coding=utf-8
import frida
import sys
session = frida.get_remote_device().attach("com.example.hooktest")
#print session.enumerate_modules()
jscode = """
Java.perform(function(){
send("Running Script");
var getString = undefined;
exports = Module.enumerateExportsSync("libtest.so");
for(i=0; i<exports.length; i++){
if(exports.name == "Java_com_example_hooktest_MainActivity_getString"){
getString = exports.address;
send("getInt is at " + getString);
break;
}
}
var getInt = undefined;
exports = Module.enumerateExportsSync("libtest.so");
for(i=0; i<exports.length; i++){
if(exports.name == "getInt"){
getInt = exports.address;
send("getInt is at " + getInt);
break;
}
}
var fungetInt = new NativeFunction(getInt, 'int', ['int']);
Interceptor.attach(getString,{
onEnter: function (args) {
send("onEnter");
var res = fungetInt(99999);
send(res);
},
onLeave: function (retval) {
send("onLeave");
}
});
});
"""
def on_message(message, data):
print message
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()
先看一下正常结果
小弟最后一个问题就是 没法hook住 getInt这个函数,只能对他进行调用,不是哪位老大可以对这个很熟进行hook。
有不对的地方也请各位老大斧正
本帖最后由 kwing112 于 2017-9-19 15:43 编辑
Interceptor.attach(Module.findExportByName("libtest.so","Java_com_example_kwing_frdtest_MainActivity_getInt"),
{
onEnter:function(args)
{
console.log("inside ndk "+args.toInt32());//args2就是传进来的int参数,,直接修改是不行的
},
onLeave:function (retval)
{
retval.replace(1000);
}
});
""" 改成这样是可以hook到ndk函数的,,但是我修改参数还是不成功,有熟悉的指导下 kwing112 发表于 2017-9-19 15:40
Interceptor.attach(Module.findExportByName("libtest.so","Java_com_example_kwing_frdtest_MainActivity ...
我只有retval.replace(0)才能成功 不然都是读取已释放内存
不知现在有否解决方案? 怒抢一楼 高手啊11 厉害了我的哥, 感谢分享 楼主幸苦了谢谢分享 火钳刘明{:1_931:} 使用python和javascrip进行hook模块的开发
{:17_1083:}JavaScript你少打了一个t 楼主辛苦了 辛苦了谢谢分享 谢谢分享