凡心所向,素履所往

frida理解与学习

字数统计: 2k阅读时长: 9 min
2019/01/22 Share

【1】pip install frida

【2】sudo pip install frida-tools

【3】我这里使用的测试机cpuinfo是

Processor    : ARMv7 Processor rev 0 (v7l)

所以下载的对应的server版本是frida-server-12.2.29-android-arm

在启动对应的sever后,可以不用端口转发直接测试链接

frida-ps -U:在另一个终端的常规操作系统shell中检测frida中进程

frida-trace : 跟踪由对应应用使用的特定调用

如 跟踪chrome使用的open应用

frida-trace -i "open" -U com.android.chrome

内心os(不知道特么是什么玄学问题,直接用的现目前最新版29,死活有问题,都快怀疑人生了,换了下24低版本,可以正常使用)

测试功能

python 枚举android手机所有的进程

import frida
rdev = frida.get_remote_device()
processes = rdev.enumerate_processes()
for process in processes:
    print (process)

js 测试

setTimeout(function(){
  Java.perform(function(){
      console.log("hello world!");
    });
});

frida ssl unpinning(待细看)

Java.perform(function() {                
    var array_list = Java.use("java.util.ArrayList");
    var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');
    // console.log('Start ssl bypass.');

    ApiClient.checkTrustedRecursive.implementation = function(a1,a2,a3,a4,a5,a6) {
        console.log('Bypassing SSL Pinning');
        var k = array_list.$new(); 
        return k;
    }
},0);

在进行后面初学测试后,回头看 才发现这个并不是之前以为的通用版,是hook了com.android.org.conscrypt.TrustManagerImpl类的checkTrustedRecursive函数,猜测是作者在对应应用的校验函数。

初学

功能模块

访问进程内存

read_bytes(address, n)

write_bytes(address, data)

案例
  1. 利用Frida从TeamViewer内存中提取密码(暂未复现)

在应用程序运行时覆盖函数

implementation 覆盖了原函数,进行重执行

从导入的类调用函数

这个也是默认的功能,可以直接调用java.use的导入需求的类,然后通过 this.a 调用原函数,调用情况在下面例子中有。

当需要打印成员数据时,可以调用.value属性来访问

var ah = Java.use("com/miui/virtualsim/utils/ah");
console.log("To Log: " + ah.a.value);
ah.a.value = true; 

在堆上查找对象实例并使用他们

Hook、追踪和拦截函数

https://blog.csdn.net/u011337769/article/details/82855818
https://www.52pojie.cn/thread-848126-1-1.html
https://blog.csdn.net/qingemengyue/article/details/79871926

crack 学习

ex1

因为不知道的什么原因,我这里的frida在使用-f(spawn)的时候就会报错,not connection,所以不能spwan模式在重启程序时调试。只能着眼于已进入mainActivity程序后续进行hook

如何修改Java层的函数参数和返回值
  • apk解析 首先找mainActivity中的oncreate方法,这个是在activity创建时即执行的方法
  1. mainActivity
    `
    package sg.vantagepoint.uncrackable1;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import sg.vantagepoint.a.b;
import sg.vantagepoint.a.c;

public class MainActivity extends Activity {
private void a(String str) {
AlertDialog create = new Builder(this).create();
create.setTitle(str);
create.setMessage(“This in unacceptable. The app is now going to exit.”);
create.setButton(-3, “OK”, new b(this));
create.setCancelable(false);
create.show();
}

protected void onCreate(Bundle bundle) {
    if (c.a() || c.b() || c.c()) {
        a("Root detected!");
    }
    if (b.a(getApplicationContext())) {
        a("App is debuggable!");
    }
    super.onCreate(bundle);
    setContentView(R.layout.activity_main);
}

public void verify(View view) {
    String obj = ((EditText) findViewById(R.id.edit_text)).getText().toString();
    AlertDialog create = new Builder(this).create();
    if (a.a(obj)) {
        create.setTitle("Success!");
        create.setMessage("This is the correct secret.");
    } else {
        create.setTitle("Nope...");
        create.setMessage("That's not it. Try again.");
    }
    create.setButton(-3, "OK", new c(this));
    create.show();
}

}

在该apk调用中,在mainAc中onCreate- create.setButton(-3, "OK", new b(this));
2. b类

package sg.vantagepoint.uncrackable1;

import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;

class b implements OnClickListener {
final / synthetic / MainActivity a;

b(MainActivity mainActivity) {
    this.a = mainActivity;
}

public void onClick(DialogInterface dialogInterface, int i) {
    System.exit(0);
}

}

调用后退出应用。

- 注入js解析

setImmediate(function() { //prevent timeout
console.log(“[*] Starting script”);

Java.perform(function() {

  bClass = Java.use("sg.vantagepoint.uncrackable1.b");
  bClass.onClick.implementation = function(v) {
     console.log("[*] onClick called");
  }
  console.log("[*] onClick handler modified")

})

})

1. 在该js中 Java.perform相当于main函数;获取sg.vantagepoint.uncrackable1.b 类,然后调用onclick模拟点击事件,让本该退出的成为 调用后输出console.log
修改:

setImmediate(function() { //prevent timeout
console.log(“[*] Starting script”);

Java.perform(function() {

  bClass = Java.use("sg.vantagepoint.uncrackable1.b");
  aClass = Java.use("sg.vantagepoint.uncrackable1.c");
  bClass.onClick.implementation = function(v) {
     console.log("[*] onClick called bb");
  }
  aClass.onClick.implementation = function(v) {
     console.log("[*] onClick called aa");
  }
  console.log("[*] onClick handler modified")

})

})

2. 在该apk中,调用原aes加密函数 sg.vantagepoint.a.a函数,进行解密,将结果输出。

setImmediate(function() { //prevent timeout
console.log(“[*] Starting script”);

Java.perform(function() {

  bClass = Java.use("sg.vantagepoint.uncrackable1.b");
  bClass.onClick.implementation = function(v) {
     console.log("[*] onClick called");
  }
  aaclass = Java.use("sg.vantagepoint.a.a");
  aaclass.a.implementation = function (arg1, arg2) {
   pass = "";
   s = this.a(arg1, arg2); 
   for(i=0; i<s.length; i++) {
              pass += String.fromCharCode(s[i]);
          }
          console.log("[*] content: " + pass);

return s;}
console.log(“[*] onClick handler modified”)

})

})

3. 在该apk中,hook输出最后的校验函数 sg.vantagepoint.uncrackable1.a.a函数结果,使其一直返回true

setImmediate(function() { //prevent timeout
console.log(“[*] Starting script”);

Java.perform(function() {

  bClass = Java.use("sg.vantagepoint.uncrackable1.b");
  bClass.onClick.implementation = function(v) {
     console.log("[*] onClick called");
  }
  aaclass = Java.use("sg.vantagepoint.uncrackable1.a");
  aaclass.a.implementation = function (arg1) {

  return true;
}
  console.log("[*] onClick handler modified")

})

})

##### ex2
场景参考在这里:
https://bbs.pediy.com/thread-227232.htm

###### 源码分析
同上先看oncreate函数

protected 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;
}

菜鸟学android什么都的查emmmmm

**Bundle savedInstanceState:**
经常会出现用户按到home键,退出了界面,或者安卓系统意外回收了应用的进程,这种情况下,使用Bundle savedInstanceState就可以用户再次打开应用的时候恢复的原来的状态,剩下的声明了button控件和事件的监听

onClick函数

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);
TextView tv2 = (TextView) findViewById(R.id.textView2);
this.m = 0;
this.n = new Random().nextInt(3);
tv2.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);
}
}

postDelayed:创建多线程消息的函数,类似于定时器,每秒触发一下this.showMessageTask

private final Runnable showMessageTask = new Runnable() {
public void run() {
TextView tv3 = (TextView) MainActivity.this.findViewById(R.id.textView3);
MainActivity mainActivity;
if (MainActivity.this.n - MainActivity.this.m == 1) {
mainActivity = MainActivity.this;
mainActivity.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 = MainActivity.this;
mainActivity.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;
}
};

根据例子一以及源码分析,该问题需要hook com.example.seccon2015.rock_paper.scissors.MainActivity中的showMessageTask函数,使其直接执行

if (1000 == MainActivity.this.cnt) {
tv3.setText(“SECCON{“ + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + “}”);
}


构造js如下,hook掉对应的onclick函数-1:

setImmediate(function() { //prevent timeout
console.log(“[*] Starting script”);
Java.perform(function () {

var mClass = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
mClass.onClick.implementation = function () {
    console.log("Hook Start...");
    console.log("SECCON{" + (1000 + this.calc())*107 + "}")

    }
})

});

构造js如下,hook掉对应的onclick函数-2:

setImmediate(function() { //prevent timeout
console.log(“[] Starting script”);
Java.perform(function () {
//定义变量MainActivity,Java.use指定要使用的类
var MainActivity = Java.use(‘com.example.seccon2015.rock_paper_scissors.MainActivity’);
//hook该类下的onCreate方法,重新实现它
MainActivity.onClick.implementation = function () {
send(“Hook Start…”);
//调用calc()方法,获取返回值
var returnValue = this.calc();
send(“Return:”+returnValue);
var result = (1000+returnValue)
107;
//解出答案
send(“Flag:”+”SECCON{“+result.toString()+”}”);
}
})
});



##### 如何打印Java层的方法堆栈信息
枚举内存范围 enumerate_ranges(mask)
##### 如何拦截native层的函数参数和返回值



#### 需要理解的问题

##### java反射

##### 动态代码插桩DBI


#### 参考

https://www.52pojie.cn/thread-848126-1-1.html
https://blog.csdn.net/omnispace/article/details/70598829
https://codemetrix.net/hacking-android-apps-with-frida-2/
https://www.frida.re/docs/javascript-api/#java
https://github.com/iromise/AOS-Note/blob/42544f4635e6238e2d7ddbc6e4e1789c20d2c130/frida-exp/frida.md
https://bbs.pediy.com/thread-227232.htm
https://www.cnblogs.com/qwangxiao/p/9255328.html
`

CATALOG
  1. 1. 测试功能
    1. 1.1. python 枚举android手机所有的进程
    2. 1.2. js 测试
    3. 1.3. frida ssl unpinning(待细看)
  • 初学
    1. 1. 功能模块
      1. 1.1. 访问进程内存
        1. 1.1.1. 案例
      2. 1.2. 在应用程序运行时覆盖函数
      3. 1.3. 从导入的类调用函数
      4. 1.4. 在堆上查找对象实例并使用他们
      5. 1.5. Hook、追踪和拦截函数
      6. 1.6. crack 学习
        1. 1.6.1. ex1
          1. 1.6.1.1. 如何修改Java层的函数参数和返回值