상세 컨텐츠

본문 제목

[Android] 프리다를 이용한 안드로이드 앱 후킹 (Level3)

기술보안/Mobile:Android

by about_SC 2019. 1. 17. 09:54

본문

아래의 경로에서 문제를 받아볼 수 있었다.
https://github.com/OWASP/owasp-mstg/tree/master/Crackmes

(도구 설치 방법론은 다루지 않는다)


환경분석
:
OS : Win7
TOOL : Frida, Frida-server, adb, Python2.7, Nox

1) 후킹할 APP을 설치한다.


2) 루팅된 단말기에서 앱 실행시 루팅검증 로직이 존재하여 APP 시작과 동시에 강제종료됨을 확인할 수 있다.


3) JEB를 통해 APP을 디컴파일 하여 자바코드로 분석 시 루팅체크 로직을 확인할 수 있다.


4) 또한, 문자열 검증 로직을 확인할 수 있다.
문자열 검증 과정을 거치는 분기의 check_code(v4) 메소드를 타고 들어가보자.


5) 문자열 검증 메소드 중 native 메소드를 확인할 수 있다.


6) 이전 과정으로 돌아와 Mainactivity에서 코드를 살펴보면 libfoo.so 파일이 loadlibrary()에 의해 포함되는 것을 확인할 수 있다.


7) 먼저, 이전 실습(LEVEL2)와 같이 루팅탐지를 우회하는 후킹코드를 작성하여 루팅탐지를 우회해보자.


8) 위의 후킹 코드로 앱 후킹 시 앱이 강제종료됨을 확인할 수 있다.
후킹을 진행하며 로그캣을 통해 로그 확인 시 Tempering detected! Terminating... 메시지를 확인할 수 있다.
이를 통해, Frida로 앱 후킹 시 탐지하여 강제종료하는 로직이 있다는 것을 추측할 수 있다.

자바 코드 상에서 Frida 후킹을 방지하는 안티디버깅이 존재하지 않음을 확인함에 따라 
해당 로직은 포함했던 libfoo.so C/C++ 모듈에 존재함을 추측할 수 있다.


9) IDA를 통해 libfoo.so 모듈을 분석해보자.
해당 문자를 이용해 프로세스를 확인하여 종료하는 로직이 있을거라 추측해보았다.
해당 파일을 IDA로 열고 String 검색을 통해 frida 문자를 검색해보자.
검색 시 검색 결과로 나타난 frida를 타고들어가보자.


10) 해당 문자열이 호출되는 클래스 확인 시 sub_38A0 클래스에서 해당 문자열이 사용되는 것을 확인할 수 있다.
해당 클래스로 이동해보자.



11) 위의 과정을 통해 sub_38A0 클래스 내부의 start_routine 함수에서 frida 문자열이 사용되는 것을 확인할 수 있었다. 
start_routine 함수 내부를 타고 들어가보자.


12) 메모리를 읽어서 메모리가 읽히지 않을 시 앱을 강제종료 하는 분기와 메모리를 읽어서
frida 프로세스와 xposed 프로세스가 존재하는지 확인하여 존재 시 앱을 강제종료하는 분기가 있는 것을 확인할 수 있다.


13) 해당 코드를 디컴파일 시 C 코드로 확인할 수 있다.
strstr 함수를 통해 frida와 xposed 문자열 여부를 확인하는 로직이 존재함을 알 수 있다.
이를 통해, strstr 함수를 후킹함으로 C 모듈 내 안티디버깅을 우회하고,
자바코드 내 루팅탐지를 우회하는 후킹코드를 작성하면 모든 과정이 우회 가능할 것을 알 수 있다.


14) 후킹 코드를 작성해보자.
아래와 같은 후킹코드를 통해 native 단의 안티디버깅과 java 단의 루팅탐지 로직이 우회가 가능하게 된다.

FRIDA API에 대한 정보는 FRIDA 공식 홈페이지를 참조하도록 하자. API의 종류와 사용방법이 자세히 나와있다.
(https://www.frida.re/docs/javascript-api/)

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
import frida, sys
 
def on_message(message, data):
    if message['type'== 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)
 
  
PACKAGE_NAME = "owasp.mstg.uncrackable3"
 
jscode= """
send("Start script....");
Interceptor.attach(Module.findExportByName("libc.so","strstr"), {
  
      onEnter: function (args) {
        this.haystack = args[0];
        this.needle = args[1];
        this.frida = Boolean(0);
        haystack = Memory.readUtf8String(this.haystack);
        needle = Memory.readUtf8String(this.needle);
        if ( haystack.indexOf("frida") !== -1 || haystack.indexOf("xposed") != -1) {
            this.frida = Boolean(1);
        }
    },
    onLeave: function (retval) {
        if (this.frida) {
            var fakeRet = ptr(0);
            retval.replace(0);
        }
    return retval;
    }
});
send("Done with native hooks.");
    
Java.perform(function() {
    send("Start java hooks....");
    var sys = Java.use("java.lang.System");
    sys.exit.overload("int").implementation = function(var_0) {
        send("System.exit called");
    };
    send("Done java hooks installed.");
});
"""
 
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME])  
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Hook')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)
 
 
cs



15) 후킹 코드를 실행하여 앱 후킹 시 앱이 종료되지 않고 후킹 코드가 실행되며,
앱의 루팅 탐지 로직이 정상적으로 우회되는 것을 확인할 수 있다.
패스워드를 획득하는 후킹 코드는 이전 포스팅된 LEVEL2와 동일하니 생략하도록 하겠다.


지금까지 uncrack3.apk 샘플 파일을 통해 프리다를 이용한 안드로이드 앱 후킹을 알아보았다.
참고한 사이트는 아래에 기재하였다.

참고 : 
https://www.frida.re/docs/javascript-api/
https://gflow-security.tistory.com/entry/Android-App-Hooking-with-Frida3?category=278801

관련글 더보기