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번 승리 시 우측 그림과 같은 화면을 확인할 수 있습니다.
참고
'Hacking > Android Hacking' 카테고리의 다른 글
Android@ETC#How to get current foreground activity context in android? (0) | 2017.03.29 |
---|---|
Android@Frida#Rooting Bypass(1) (0) | 2017.02.27 |
Android@SSL Pinning# Android SSL Pinning Bypass (0) | 2017.01.27 |
Android@Dorzer# 취약한 컨텐트 프로바이더 (0) | 2016.08.13 |
Android@Drozer# Drozer 사용법 - 01 (0) | 2016.08.08 |