Android hook 入门案例

  1. 用objection大致了看下,

    1.1 查看有哪些类

    1
    android hooking search classes  com.example.seccon2015

    返回结果,发现比较简单,就一个类:

    1
    2
    3
    com.example.seccon2015.rock_paper_scissors.MainActivity
    com.example.seccon2015.rock_paper_scissors.MainActivity$1
    Found 2 classes

    1.2 查看有该类中有哪些方法

    1
    2
    3
    4
    5
    6
    7
    8
    seccon2015.rock_paper_scissors on (google: 7.1.2) [usb] # android hooking list class_methods com.example.seccon2015.rock_paper_scissors.MainActivity

    # 返回结果
    protected void com.example.seccon2015.rock_paper_scissors.MainActivity.onCreate(android.os.Bundle)
    public native int com.example.seccon2015.rock_paper_scissors.MainActivity.calc()
    public void com.example.seccon2015.rock_paper_scissors.MainActivity.onClick(android.view.View)

    Found 3 method(s)

    发现仅3个方法,其中有一个native方法,

  2. 实现方法

    1. oncreate方法,声明了button控件以及对应的监听器

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      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;
      }
    2. onClick方法。

    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
    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; //玩家
    // 设置n为随机数0,1,2
    this.n = new Random().nextInt(3); //PC
    // 随机出 布/石头/剪刀
    ((TextView) findViewById(R.id.textView2)).setText(new String[]{"CPU: Paper", "CPU: Rock", "CPU: Scissors"}[this.n]);
    // 如果玩家出布,m置为0
    if (v == this.P) {
    tv.setText("YOU: Paper");
    this.m = 0;
    }
    // 如果玩家出石头,m置为1
    if (v == this.r) {
    tv.setText("YOU: Rock");
    this.m = 1;
    }
    // 如果玩家出剪刀,m置为2
    if (v == this.S) {
    tv.setText("YOU: Scissors");
    this.m = 2;
    }
    // 执行定时任务
    this.handler.postDelayed(this.showMessageTask, 1000);
    }
    }

    继续查看showMessageTask方法。

    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
    private final Runnable showMessageTask = new Runnable() {
    public void run() {
    TextView tv3 = (TextView) MainActivity.this.findViewById(R.id.textView3);
    // 如果玩家win
    if (MainActivity.this.n - MainActivity.this.m == 1) {
    MainActivity.this.cnt++;
    tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
    // 如果玩家lose
    } 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));
    // 如果玩家lose
    } else if (MainActivity.this.m < MainActivity.this.n) {
    MainActivity.this.cnt = 0;
    tv3.setText("LOSE +0");
    // 如果玩家win
    } else {
    MainActivity.this.cnt++;
    tv3.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
    }
    // 如果连胜1000次,弹出flag
    if (1000 == MainActivity.this.cnt) {
    tv3.setText("SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}");
    }
    MainActivity.this.flag = 0;
    }
    };
  3. 分析得到flag思路

    1. 修改返回值为1000,得到flag;
    2. hook到calc的返回值,得到flag;
    3. 看到弹出flag的语句,直接想到去分析native的calc方法,得到flag。

方法一:

修改返回值为1000,再点击按钮时,触发点击事件,可能会win,也可能会lose,此时对玩家和pc的值也控制一下,为相同的值,使得分不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function hook2() {
Java.perform(function () {
var useClass = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
//hook onClick方法,此处要注意的是onClick方法是传递了一个View参数v
useClass.onClick.implementation = function (arg) {
send("hook start--->");
send("cnt修改前, 当前值----->"+this.cnt.value);
//调用onClick,模拟点击事件
var calcVule=this.onClick(arg);
this.n.value = 1;
this.m.value = 1;
this.cnt.value = 1000;
send("cnt修改后, 当前值----->"+this.cnt.value);
send("hook success---->");
}
});
};
setImmediate(hook2, 0);

执行结果如下,发现cnt已经修改为1000,同时将flag显示在界面中。

1
2
3
4
message: {'type': 'send', 'payload': 'hook start--->'} data: None
message: {'type': 'send', 'payload': 'cnt修改前, 当前值----->0'} data: None
message: {'type': 'send', 'payload': 'cnt修改后, 当前值----->1000'} data: None
message: {'type': 'send', 'payload': 'hook success---->'} data: None

方法二:

calc方法在MainActivity类中,直接引用该类下的calc()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function hook1(){
Java.perform(function(){
var useClass=Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
useClass.onClick.implementation=function(){
send("hook start--->");
//调用calc()方法,获取返回值
var calcVule=this.calc();
send("calcVule---->" + calcVule);
var vule= (calcVule+1000)*107;
send ("flag---> {SECCON"+vule+"}");
}
});
};
setImmediate(hook2,0);

执行结果

1
2
3
4
[Nexus 5X::com.example.seccon2015.rock_paper_scissors]-> 
message: {'type': 'send', 'payload': 'hook start--->'} data: None
message: {'type': 'send', 'payload': 'calcVule---->7'} data: None
message: {'type': 'send', 'payload': 'flag---> {SECCON107749}'} data: None

方法三:

把so文件拉到反编译工具查看其算法,发现就简单的返回一个值,

那就简单多了,直接计算“{SECCON”+1007*107+“}”,得最终flag.