Android 분석 중, .so파일은 보통 IDA를 이용해서 분석했는데 좋은 툴이 있어 소개드립니다


Radare2라는 툴인데 IDA CLI버전 느낌이네요. 가볍기도 하고 GDB + IDA느낌입니다.(오늘 처음 사용해봐서 잘모르지만 느낌은)


http://radare.org/r/   -  Radare2공홈입니다


https://radare.gitbooks.io/radare2book/content/  - Radare2 가이드 페이지입니다


Windows 버전과 리눅스 버전이 있는데, 리눅스는 github에서 받으시면 됩니다


#git clone https://github.com/radare/radare2.git

#cd radare/sys

#./install.sh


설치가 완료되면 r2명령어를 이용하여 실행할 수 있습니다


OWASP의 uncrackable2 app을 이용하여 Radare2를 소개하겠습니다


앱 실행시 다음화면과 같습니다. 루팅 탐지 로직을 확인하기 위해 디컴파일 후에 소스코드를 확인하겠습니다


init()함수 후에 b.a , b.b , b.c함수를 이용해 루팅탐지를 합니다.

소스코드를 보니 init함수가 jni를 이용하여 작성된 so파일이니 r2를 이용해 분석하겠습니다


iE명령을 이용하여 Java_sg_vantagepoint_uncrackable2_CodeCheck_bar, Java_sg_vantagepoint_uncrackable2_MainActivity_init 함수를 확인하였습니다


[]>s 0x00000b0c
[]>pd $r @

명령어를 이용해 MainActivity_init함수를 확인할 수 있습니다


fork()함수를 이용하여 다른 작업을 하는 것 같습니다


[]>s 0x000008b8

[]>pd $r @



ptrace를 이용한 anti-debug 로직인 것 같네요


Anti-Debugging 및 루팅탐지를 우회하기 위해 Frida를 이용하기로 합니다.

import sys
import frida

def on_message(message,data):
    print "[%s] -> %s" % (message, data)


PACKAGE_NAME = "sg.vantagepoint.uncrackable2"

jscode = """
    Java.perform(function() {
        console.log("[*] Hooking calls to System.exit");
        exitClass = Java.use("java.lang.System");
        exitClass.exit.implementation = function() {
            console.log("[*] System.exit called");
        }
    });
"""
   
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME]) 
    print("App is starting ... pid : {}".format(pid))
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Frida')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)



exit() 함수를 후킹하여 앱 종료를 막는 스크립트입니다

스크립트 실행 시, 루팅탐지가 되지만 exit함수가 후킹되어 앱이 종료되지 않습니다 



다시 복호화된 소스를 확인합니다


위 캡처화면의 분기문에서 스트링을 검사한 후에 Alert창을 띄우는 것을 확인하였으며, this.m.a의 로직을 살펴보면 다음과 같습니다


jni파일의 bar함수에서 스트링 검사를 진행하여 결과값을 리턴받아 판별하는 소스입니다

상단의 radare2를 이용하여 libfoo.so파일을 살펴본 결과 CodeCheck_bar를 확인할 수 있었고 해당 함수를 디스어셈블하면 다음과 같은 화면이 출력됩니다


0x00000c88부분에 strncmp함수를 확인할 수 있습니다

조금더 올라가서 0x00000c74부분을 살펴보면


cmp w0,0x17

b.ne 0xc90


를 확인할 수 있고 0x17글자수를 검증한 후 기존의 문자열과 입력된 문자열을 비교합니다

Frida를 이용해서 strncmp를 후킹하여 파라미터를 출력하는 방법으로 secret key를 확인하겠습니다


import sys
import frida

def on_message(message,data):
    print "[%s] -> %s" % (message, data)


PACKAGE_NAME = "sg.vantagepoint.uncrackable2"

jscode = """
    Java.perform(function() {
        console.log("[*] Hooking calls to System.exit");
        exitClass = Java.use("java.lang.System");
        exitClass.exit.implementation = function() {
            console.log("[*] System.exit called");
        }
       
        var strcmp=undefined;
        module=Module.enumerateImportsSync("libfoo.so");
        for(i=0;i<module.length;i++){
            if(module[i].name=="strncmp"){
                strcmp=module[i].address;
                break;
            }
        }

        Interceptor.attach(strcmp, {
            onEnter: function (args) {
               if(args[2].toInt32() == 23 && Memory.readUtf8String(args[0],23) == "01234567890123456789012") {
                    console.log("[*] Secret string at " + args[1] + ": " + Memory.readUtf8String(args[1],23));
                }
             },
        });
    });
"""
   
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME]) 
    print("App is starting ... pid : {}".format(pid))
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Frida')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)


코드 실행 시, secret key를 확인할 수 있습니다


※Radare2에서 Ida와 동일하게 스페이스 바를 이용하여 그래프 모드가 가능합니다



출처 : https://www.codemetrix.net/hacking-android-apps-with-frida-2/

+ Recent posts