本文最后更新于 2025年3月27日 晚上
下午看 SWDD 的 Frida操作方法总结 文章时被激起兴趣了,所以开干!
项目地址:Frida-Labs
第一个还是很简单的,整体流程:jeb 反编译 -> 简单代码审计 -> hook 关键函数
准备工作
Frida
frida
和 frida-tools
的版本要对应上,不然可能会报错,可以在 https://github.com/frida/frida/releases 找对应版本下载

Frida-server
启动 frida-server
1 2 3 4 5 6
| adb shell su cd data/local/tmp ls chmod 777 frida~ ./frida~
|

分析
先丢进模拟器看看长什么样
当什么都不输入值为空时会直接退出程序
当输入 111
的时候,提示了 【Try again】

Jeb 反编译
使用 jeb 反编译后进行代码审计
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package com.ad2001.frida0x1;
import android.os.Bundle; import android.text.TextUtils; import android.view.View.OnClickListener; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.util.Random;
public class MainActivity extends AppCompatActivity { TextView t1;
void check(int v, int v1) { if(v * 2 + 4 == v1) { Toast.makeText(this.getApplicationContext(), "Yey you guessed it right", 1).show(); StringBuilder stringBuilder0 = new StringBuilder(); for(int v2 = 0; v2 < 20; ++v2) { int v3 = "AMDYV{WVWT_CJJF_0s1}".charAt(v2); if(v3 >= 97 && v3 <= 0x7A) { v3 = (char)(v3 - 21); if(v3 < 97) { v3 = (char)(v3 + 26); } } else if(v3 >= 65 && v3 <= 90) { v3 = (char)(v3 - 21); if(v3 < 65) { v3 = (char)(v3 + 26); } }
stringBuilder0.append(((char)v3)); }
this.t1.setText(stringBuilder0.toString()); return; }
Toast.makeText(this.getApplicationContext(), "Try again", 1).show(); }
int get_random() { return new Random().nextInt(100); }
@Override protected void onCreate(Bundle bundle0) { super.onCreate(bundle0); this.setContentView(layout.activity_main); EditText editText0 = (EditText)this.findViewById(id.editTextTextPassword); Button button0 = (Button)this.findViewById(id.button); this.t1 = (TextView)this.findViewById(id.textview1); button0.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view0) { String s = editText0.getText().toString(); if(TextUtils.isDigitsOnly(s)) { int v = Integer.parseInt(s); MainActivity.this.check(this.get_random(), v); return; }
Toast.makeText(MainActivity.this.getApplicationContext(), "Enter a valid number !!", 1).show(); } }); } }
|
Oncreate() 方法
在 onCreate()
方法中添加了一个事件监听器 Button
,当被点击的时候会调用 onClick()
方法,onClick()
方法中获取输入的文本,验证是否是数字,如果是数字就调用 check()
方法进行验证

check() 方法
get_random()
方法为了找随机数,check()
方法检查输入是否能够满足 v*2 + 4 == v1
,如果满足则将 flag 输出

所以现在明白流程:输入一个数字,如果与随机数符合则输出 flag
Hook
hook get_random() 方法
最简单的就是去 hook 这个随机数的值,hook 代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function hook1(){ var MainActivity=Java.use("com.ad2001.frida0x1.MainActivity"); MainActivity.get_random.implementation=function (){
var num=this.get_random(); console.log("value:",num); return num; }; }
function main(){ Java.perform(function (){ hook1(); }) }
setImmediate(main);
|
保存好后运行,因为 get_random()
方法在程序启动时就已经加载完了,所以我们要在它加载之前就注入进去,加上 --no-pause
确保应用启动后不会暂停
1
| frida -U -f com.ad2001.frida0x1 -l .\hook1.js --no-pause
|
返回值为 33,则应该输入 33*2 + 4 =70

hook get_random() 方法指定值
hook get_random()
方法然后指定随机数的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function hook1(){ var MainActivity=Java.use("com.ad2001.frida0x1.MainActivity"); MainActivity.get_random.implementation=function (){
return 6; }; }
function main(){ Java.perform(function (){ hook1(); }) }
setImmediate(main);
|
直接输入 16 能得出结果

hook check() 方法
命令可以不用加上 --no-pause
,因为 check()
函数是在程序初始化之后才运行的,不需要在加载时注入了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function hook1(){ var MainActivity=Java.use("com.ad2001.frida0x1.MainActivity"); MainActivity.check.overload('int','int').implementation=function (a,b){ this.check(a,a*2+4); return; }; }
function main(){ Java.perform(function (){ hook1(); }) }
setImmediate(main);
|
这个时候随便输入一个范围内的数字都能得出结果

Challenge 0x1 over ^__^~