FridaHook框架学习(1)
FridaHook框架学习(1)
前言
本次学习过程参考https://bbs.pediy.com/thread-227232.htm
Frida安装与使用
-
Windows端安装
pip install frida
pip install frida-tools
请Over the wall后安装,不然可能会报错。
frida-tools提供frida命令行工具
-
手机端安装
到https://github.com/frida/frida/releases下载对应的frida-server,推荐各个架构的都下完,这样以后就不用再下了
查看自己手机架构(abi),使用命令
adb shell getprop ro.product.cpu.abi
模拟器一般都是x86架构。
然后使用下面这个命令将fridaserver发送到手机
adb push frida-server-12.10.4-android-x86 ./data/local/tmp
进入adb shell,然后cd到./data/local/tmp,给fridaserver权限,命令:
chmod 777 frida-server-12.10.4-android-x86
然后运行fridaserver
新开一个Cmd窗口,使用以下命令执行端口转发
adb forward tcp:27042 tcp:27042 adb forward tcp:27043 tcp:27043
然后执行以下命令,查看fridaserver是否运行成功
frida-ps -U
若显示手机上的进程则说明运行成功。frida命令必须安装frida-tools才能使用。
逆向分析
将文中例子下载好拖入jadx分析。
package com.example.seccon2015.rock_paper_scissors;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.Random;
public class MainActivity extends Activity implements View.OnClickListener {
Button P;
Button S;
int cnt = 0;
int flag;
private final Handler handler = new Handler();
int m;
int n;
Button r;
private final Runnable showMessageTask = new Runnable() {
public void run() {
TextView tv3 = (TextView) MainActivity.this.findViewById(R.id.textView3);
if (MainActivity.this.n - MainActivity.this.m == 1) {
MainActivity.this.cnt++;
tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
} else if (MainActivity.this.m - MainActivity.this.n == 1) {
MainActivity.this.cnt = 0;
tv3.setText("LOSE +0");
} else if (MainActivity.this.m == MainActivity.this.n) {
tv3.setText("DRAW +" + String.valueOf(MainActivity.this.cnt));
} else if (MainActivity.this.m < MainActivity.this.n) {
MainActivity.this.cnt = 0;
tv3.setText("LOSE +0");
} else {
MainActivity.this.cnt++;
tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
}
if (1000 == MainActivity.this.cnt) {
tv3.setText("SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}");
}
MainActivity.this.flag = 0;
}
};
public native int calc();
static {
System.loadLibrary("calc");
}
/* access modifiers changed from: protected */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.P = (Button) findViewById(R.id.button);
this.S = (Button) findViewById(R.id.button3);
this.r = (Button) findViewById(R.id.buttonR);
this.P.setOnClickListener(this);
this.r.setOnClickListener(this);
this.S.setOnClickListener(this);
this.flag = 0;
}
public void onClick(View v) {
if (this.flag != 1) {
this.flag = 1;
((TextView) findViewById(R.id.textView3)).setText("");
TextView tv = (TextView) findViewById(R.id.textView);
this.m = 0;
this.n = new Random().nextInt(3);
((TextView) findViewById(R.id.textView2)).setText(new String[]{"CPU: Paper", "CPU: Rock", "CPU: Scissors"}[this.n]);
if (v == this.P) {
tv.setText("YOU: Paper");
this.m = 0;
}
if (v == this.r) {
tv.setText("YOU: Rock");
this.m = 1;
}
if (v == this.S) {
tv.setText("YOU: Scissors");
this.m = 2;
}
this.handler.postDelayed(this.showMessageTask, 1000);
}
}
}
这个例子是一个剪刀石头布游戏。
系统会随机出剪刀石头布,必须连续赢1000次才能获得flag,因为输一次计数器就会清零。
其中handler是Android中一种多线程实现方式,可以实现线程间通信。handler被实例化时就会绑定实例化时的线程,之后handler绑定的方法就可以对该线程数据进行修改。this.handler.postDelayed功能为延迟执行。本例子中意思为1秒后使用执行showMessageTask。我Android开发不太行,这些是查找网上资料后一些自己的理解。
Hook代码编写
要想得到flag
- 逆向分析cal方法得到结果
- 直接Hook onCrate方法修改计数器cnt的值使计数器为1000
- 直接Hook cal方法得到返回值
-
方法二,修改计数器
若直接修改cnt,一开始不能确定输赢。所以m和n的值也要修改。
showMessageTask是个匿名内部类,目前还不知道怎么Hook,故Hook onClick方法。
import frida import sys # 核心代码 jscode = """ // Java.perform开始执行js脚本 Java.perform(function () { // Java.use指定要使用的类 var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity'); // Hook这个类的onClick方法,注意该方法有一个参数,要写上 MainActivity.onClick.implementation = function (v) { //发送信息 send("Hook Start..."); //模拟点击事件 this.onClick(v); //修改值 this.n.value = 0; this.m.value = 2; this.cnt.value = 999; send("Success!") } }); """ #设置信息格式的方法 def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message) # 获取设备,attach内填完整包名 process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors') # 创建脚本对象 script = process.create_script(jscode) # 设置信息 script.on('message', on_message) # 执行脚本 script.load() sys.stdin.read()
-
方法三,直接获得cal的返回值
import frida import sys jscode = """ Java.perform(function () { var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity'); MainActivity.onCreate.implementation = function () { send("Hook Start..."); var returnValue = this.calc(); send("Return:"+returnValue); var result = (1000+returnValue)*107; send("Flag:"+"SECCON{"+result.toString()+"}"); } }); """ def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message) process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors') script = process.create_script(jscode) script.on('message', on_message) script.load() sys.stdin.read()
因为Hook的是onCreat方法,但要Hook又必须先启动程序,程序启动后onCreate方法已经执行完毕,所以Hook不到。所以要先打开程序,之后运行脚本,之后点击主页返回桌面,再点击一次应用图标打开,即可Hook。
Hook完成后APP会停止运行,不知道为什么。