What is Frida?


Android

setting up your Android device

먼저, Frida를 사용하기 전에 사용자는 루팅된 단말기를 가지고 있어야 합니다. 공식 홈페이지에 따르면 안드로이드 버전 4.2 ~ 6.0 까지 지원 한다고 명시되어 있으며, Dalvik-powered ARM device 혹은 emulator에서 사용하는 것을 권고 하고 있습니다.(※ Nox에서 Frida-Server 실행 시 not executable: magic 7F45 에러와 함께 실행되지 않습니다.) 

  • Frida-Server를 설치 하기 전 adb(Android Debug Bridge)를 준비 합니다.

  • Android 전용 Frida-Server를 다운로드 합니다. 다운로드 한 Frida-Serve를 Android 단말기에 넣어 Frida-Server를 실행 시킵니다.
$ adb root # might be required
$ adb push frida-server /data/local/tmp/ 
$ adb shell "chmod 755 /data/local/tmp/frida-server"
$ adb shell "/data/local/tmp/frida-server &"

setting up your Desktop

  • Python - 3.x 버전
  • Windows, macOS, Linux 
윈도우즈 환경에서 Python 3.5버전을 이용하여 Frida 설치를 진행 했습니다.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
 
C:\Users\dj>pip install frida==9.0.0



공식 홈페이지에서 제공 하는 명령어(pip install frida)를 통해 설치 시 아래 그림과 같이 오류가 발생할 수 있습니다. 저랑 동일한 오류가 발생하는 분은 pip install frida==9.0.0 명령어를 이용하여 설치하시길 바랍니다.


A quick smoke-test

frida-ps -U 명령어를 통해 현재 Android 디바이스에서 실행 중인 Process 목록을 확인할 수 있습니다.

# Connect Frida to an iPad over USB and list running processes
$ frida-ps -U
 
# List running applications
$ frida-ps -Ua
 
# List installed applications
$ frida-ps -Uai
 




Example

ctf.py

공식 홈페이지에서 제공 하는 SECCON Quals CTF 2015 APK1 예제를 이용하여 Frida 실습을 진행 합니다. APK 다운로드 후 Android 디바이스에 설치 합니다. 

Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
 
C:\Users\dj>adb install rps.apk


해당 예제는 컴퓨터와 가위·바위·보 게임에서 1000번 승리 하는 게임 입니다. 아래 코드를 ctf.py로 저장 하여 실행 시킵니다.

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
import frida, sys
 
def on_message(message, data):
    if message['type'== 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)
 
jscode = """
Java.perform(function () {
    // Function to hook is defined here
    var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
    // Whenever button is clicked
    MainActivity.onClick.implementation = function (v) {
        // Show a message to know that the function got called
        send('onClick');
        // Call the original onClick handler
        this.onClick(v);
        // Set our values after running the original onClick handler
        this.m.value = 0;
        this.n.value = 1;
        this.cnt.value = 999;
        // Log to the console that it's done, and we should have the flag!
        console.log('Done:' + JSON.stringify(this.cnt));
    };
});
"""
 
process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()

rps.apk

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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");
    }
 
    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;
    }
 
    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);
        }
    }
}



Hooking을 통해 1000번 승리 시 우측 그림과 같은 화면을 확인할 수 있습니다.

  


참고

[1] https://www.frida.re


+ Recent posts