Richor 发表于 2019-6-26 10:16

Frida HOOK入门之剪刀石头布破解

本帖最后由 Richor 于 2019-6-26 10:18 编辑

个人觉得Frida是比Xpose更牛逼一丢丢的框架,今天用一个剪刀石头布的apk来说明一下frida HOOK
目标:让程序直接输出获胜1000次
第一步:搭建环境
(1)Python及其IDE
    1.1安装python2.7或者python3.6      进入官网:https://www.python.org/   选择Downloads>Windows下载相应版本   安装
    1.2 Python IDE:我是使用pycharm,其他的IDE当然也可以
    1.3模拟器选用雷电模拟器

(2)Frida环境搭建
    2.1模拟器端环境
       下载https://github.com/frida/frida/releases/download/12.0.8/frida-server-12.0.8-android-x86.xz即可并改名为Frida-server
      打开CMD输入下面的指令
       adb pushFrida-server/data/local/tmp/      adb shell "chmod 755 /data/local/tmp/Frida-server"
      adb shell"/data/local/tmp/Frida-server &"
   不要关闭此窗口,否则frida-server会掉
   2.2Python端环境
       打开pycharm,新建工程,打开新的CMD,输入以下指令
       pip install frida
      安装完成后查看进程
    firda-ps -U
   
(3)程序分析
我们先用ak反编译看看代码
.class public Lcom/example/seccon2015/rock_paper_scissors/MainActivity;
.super Landroid/app/Activity;
.source "MainActivity.java"

# interfaces
.implements Landroid/view/View$OnClickListener;


# instance fields
.field P:Landroid/widget/Button;

.field S:Landroid/widget/Button;

.field cnt:I

.field flag:I

.field private final handler:Landroid/os/Handler;

.field m:I

.field n:I

.field r:Landroid/widget/Button;

.field private final showMessageTask:Ljava/lang/Runnable;


# direct methods
.method static constructor <clinit>()V
    .locals 1

    .prologue
    .line 22
    const-string v0, "calc"

    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    .line 23
    return-void
.end method

.method public constructor <init>()V
    .locals 1

    .prologue
    .line 13
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V

    .line 15
    const/4 v0, 0x0

    iput v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->cnt:I

    .line 25
    new-instance v0, Landroid/os/Handler;

    invoke-direct {v0}, Landroid/os/Handler;-><init>()V

    iput-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->handler:Landroid/os/Handler;

    .line 26
    new-instance v0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity$1;

    invoke-direct {v0, p0}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity$1;-><init>(Lcom/example/seccon2015/rock_paper_scissors/MainActivity;)V

    iput-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->showMessageTask:Ljava/lang/Runnable;

    return-void
.end method


# virtual methods
.method public native calc()I
.end method

.method public onClick(Landroid/view/View;)V
    .locals 10
    .param p1, "v"    # Landroid/view/View;

    .prologue
    const/4 v9, 0x3

    const/4 v8, 0x2

    const/4 v7, 0x0

    const/4 v6, 0x1

    .line 78
    iget v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->flag:I

    if-ne v5, v6, :cond_0

    .line 109
    :goto_0
    return-void

    .line 80
    :cond_0
    iput v6, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->flag:I

    .line 82
    const v5, 0x7f0c0052

    invoke-virtual {p0, v5}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v4

    check-cast v4, Landroid/widget/TextView;

    .line 83
    .local v4, "tv3":Landroid/widget/TextView;
    const-string v5, ""

    invoke-virtual {v4, v5}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 85
    const v5, 0x7f0c0050

    invoke-virtual {p0, v5}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v2

    check-cast v2, Landroid/widget/TextView;

    .line 86
    .local v2, "tv":Landroid/widget/TextView;
    const v5, 0x7f0c0051

    invoke-virtual {p0, v5}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v3

    check-cast v3, Landroid/widget/TextView;

    .line 88
    .local v3, "tv2":Landroid/widget/TextView;
    iput v7, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->m:I

    .line 89
    new-instance v0, Ljava/util/Random;

    invoke-direct {v0}, Ljava/util/Random;-><init>()V

    .line 90
    .local v0, "rm":Ljava/util/Random;
    invoke-virtual {v0, v9}, Ljava/util/Random;->nextInt(I)I

    move-result v5

    iput v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->n:I

    .line 92
    new-array v1, v9, [Ljava/lang/String;

    const-string v5, "CPU: Paper"

    aput-object v5, v1, v7

    const-string v5, "CPU: Rock"

    aput-object v5, v1, v6

    const-string v5, "CPU: Scissors"

    aput-object v5, v1, v8

    .line 93
    .local v1, "ss":[Ljava/lang/String;
    iget v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->n:I

    aget-object v5, v1, v5

    invoke-virtual {v3, v5}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 95
    iget-object v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->P:Landroid/widget/Button;

    if-ne p1, v5, :cond_1

    .line 96
    const-string v5, "YOU: Paper"

    invoke-virtual {v2, v5}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 97
    iput v7, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->m:I

    .line 99
    :cond_1
    iget-object v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->r:Landroid/widget/Button;

    if-ne p1, v5, :cond_2

    .line 100
    const-string v5, "YOU: Rock"

    invoke-virtual {v2, v5}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 101
    iput v6, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->m:I

    .line 103
    :cond_2
    iget-object v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->S:Landroid/widget/Button;

    if-ne p1, v5, :cond_3

    .line 104
    const-string v5, "YOU: Scissors"

    invoke-virtual {v2, v5}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 105
    iput v8, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->m:I

    .line 108
    :cond_3
    iget-object v5, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->handler:Landroid/os/Handler;

    iget-object v6, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->showMessageTask:Ljava/lang/Runnable;

    const-wide/16 v8, 0x3e8

    invoke-virtual {v5, v6, v8, v9}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z

    goto :goto_0
.end method

.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;

    .prologue
    .line 60
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 61
    const v0, 0x7f040018

    invoke-virtual {p0, v0}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->setContentView(I)V

    .line 63
    const v0, 0x7f0c004d

    invoke-virtual {p0, v0}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->P:Landroid/widget/Button;

    .line 64
    const v0, 0x7f0c004f

    invoke-virtual {p0, v0}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->S:Landroid/widget/Button;

    .line 65
    const v0, 0x7f0c004e

    invoke-virtual {p0, v0}, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->r:Landroid/widget/Button;

    .line 67
    iget-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->P:Landroid/widget/Button;

    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 68
    iget-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->r:Landroid/widget/Button;

    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 69
    iget-object v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->S:Landroid/widget/Button;

    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 71
    const/4 v0, 0x0

    iput v0, p0, Lcom/example/seccon2015/rock_paper_scissors/MainActivity;->flag:I

    .line 72
    return-void
.end method

反编译成java看看
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import java.util.Random;

public class MainActivity extends Activity implements 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);
            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;
      }
    };

    public native int calc();

    static {
      System.loadLibrary("calc");
    }

    /* Access modifiers changed, original: 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);
            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"});
            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);
      }
    }
}
我们就可以得到CPU生成状态的位置在onclick
(4)Frida HOOK
我们得到目标的条件是
m=0 n=1cnt=999
我们开始编写python的代码
import frida, sys


def on_message(message, data):
    if message['type'] == 'send':
      print(" {0}".format(message['payload']))
    else:
      print(message)


jscode = """
Java.perform(function () {
    var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
//开始hook onClick方法需要注意这个function是传参数的所以我们hook时别忘了
//public void onClick(View paramView){}
MainActivity.onClick.implementation = function (v) {
      this.onClick(v);
//修改m,n的值
      this.m.value = 0;
      this.n.value = 1;
      this.cnt.value = 999;
      send("Success!")
    }
});
"""

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()
最终结果


   
       pip install frida-tools
      pip install frida-tools
      

jiang196771 发表于 2019-6-26 10:40

前排为大神鼓掌,可惜我看不懂啊,&#128557;&#128557;

ccraker 发表于 2019-6-26 11:12

如果能讲的更详细一点就好了,第三步贴了一段smali代码,结果还是靠反编译java来的

Richor 发表于 2019-6-26 13:42

ccraker 发表于 2019-6-26 11:12
如果能讲的更详细一点就好了,第三步贴了一段smali代码,结果还是靠反编译java来的

Smali代码和java代码一样的,Java更加直观一点

血色天空 发表于 2019-6-26 13:59

虽然没有看懂个,但是还是为楼主鼓掌

不苦小和尚 发表于 2019-6-26 20:19

为什么一运行,app就退出了

可还行丶 发表于 2019-6-26 20:21

懂这些是不是得先会英语?
{:1_926:}

xianyucoder 发表于 2019-7-18 15:00

第三步跳的有点快,有点&#128563;懵逼

pwpdc75 发表于 2019-7-21 14:41

学习一下,非常好,谢谢

jldwda8 发表于 2019-10-21 00:36

学习了!剪刀石头布
页: [1]
查看完整版本: Frida HOOK入门之剪刀石头布破解