저번에 Uncrackable3를 도전했었는데 당시에 다운받았던 앱이 오류가 있었던 건지 실행하면 바로 종료가 되어 분석을 하지 못했는데


며칠전 다시 다운받아 설치해보니 이번엔 잘돌아가네요 :) (당시에 앱 자체의 오류가 맞았을까요....)



앱 실행 시 위와 같이 루팅감지되어 바로 종료가 됩니다


디컴파일 후에 소스코드를 보면



MainActivity의 onCreate부분에서 루팅체크하는걸 볼 수 있습니다 


루팅체크로직을 따라가 보면



다음과 같은걸 볼 수 있는데 저는 Supersu를 사용해서 위 로직에서 탐지가 된듯합니다


간단하게 Frida를 이용해서 우회해 보겠습니다.


jscode = """

    Java.perform(function() {

        console.log("[*] Hooking calls to System.exit");

        root1 = Java.use("sg.vantagepoint.util.RootDetection");

        root1.checkRoot1.implementation = function() {

            console.log("[*] checkRoot1 Hook");

            return false;

        }

        root1.checkRoot2.implementation = function() {

            console.log("[*] checkRoot2 Hook");

            return false;

        }

        root1.checkRoot3.implementation = function() {

            console.log("[*] checkRoot3 Hook");

            return false;

        }

    });

"""


후킹 스크립트는 위와 같이 간단하게 탐지가 되어도 false를 리턴하게 작성하였습니다


실행해보면...



다음과 같이 에러가 나는데요 여기서 왜 에러가 나는지 몰라 한동안 깊은 삽질을 했네요 :(


결론은 MainActivity에서 libfoo.so파일을 호출해서 native코드를 실행하는데 .so파일의 경우 로드될때 .init_array가 먼저 실행된다고 합니다


그럼 .so파일의 .init_array를 살펴보겠습니다 ida에서 Control + S를 눌러 확인이 가능합니다



Ctrl + S를 이용하여 .init_array를 확인해 보면

아래 그림과 같이 offset sub_8D50을 호출하는 것을 알 수 있습니다

 


sub_8D50으로 들어가면 pthread_create를 이용한 anti-debugging 기법같은데요 thread가 생성되며 호출되는 함수(sub_8BC0)를 살펴보겠습니다



이 함수안에보면 메모리를 읽어 frida와 xposed를 확인하는 루틴이 존재하네요 ㅠㅠㅠ

frida를 이용해서 후킹하려고 하면 여기서 탐지되어 강제로 종료되는 것을 확인할 수 있습니다



android_log_print를 보면 37942자리에 있는 값을 ddms에 로그로 띄워주는 것 같네요 

37942 = 0x9436이므로 해당 주소로 가보면



탐지될 경우 UnCrackable3에 Tampering dtected! Terminating...이라고 출력될 것 같네요



ddms로 로그를 확인해보면 프리다로 실행시켰을 경우, 다음과 같이 탐지되는 것을 볼 수 있습니다



하나로 끝내려고 했는데 너무 길어져서 다음에 이어 작성해야겠네요 ;)

Uncrackable3-2로 끝내겠습니다 :)


문제 풀이(3-2)는 아래에서 확인하시면 됩니다~

https://taesun1114.tistory.com/entry/Uncrackable3-2

'Mobile' 카테고리의 다른 글

apktool first type is not attr  (0) 2018.10.04
Android Proxy Burp 인증서 설치  (2) 2018.09.15
APK IDA로 동적디버깅  (0) 2018.02.22
welcome to droid (codegate2018)  (2) 2018.02.11
INSTALL FAILED TEST_ONLY  (1) 2018.02.06

테스트 중에 칼리 리눅스에서 Wine32를 설치해야 하는데, 자꾸 에러가 뜨네요 :(


보통 sources.list의 문제인 경우가 많습니다


Kali linux 공홈에 가면 sources.list에 들어갈 내용이 나오네요 


https://docs.kali.org/general-use/kali-linux-sources-list-repositories



위 내용을 입력해주고 


apt-get update 명령어를 실행해주면 잘됩니다

라고 공홈에서는 말하지만 저는 계속 에러가 나네요 ㅠ

The following signatures were invalid: EXPKEYSIG ~~~라는 에러가 계속납니다


위와 같은 에러가 계속되는데 signature가 문제라고 하네요 


다음 사이트에서 해결책을 찾을 수 있었습니다

https://unix.stackexchange.com/questions/421821/invalid-signature-for-kali-linux-repositories-the-following-signatures-were-i


key를 넣어준후에 update를 실행하면 드디어 실행되는것을 확인할 수 있습니다



apt list --upgradeable 명령어까지 실행하고 난 후에 apt-get install wine32를 실행하면 설치가 되는것을 볼 수 있습니다 :)




'System > Linux' 카테고리의 다른 글

리눅스 네트워크 인터페이스 안잡힐때(no eth)  (0) 2019.03.11
CentOs 7.x 네트워크 설정  (0) 2018.10.31
Linux에서 Hex edit 쓰기  (0) 2013.03.28
리눅스 core file  (0) 2013.03.18
nohup  (0) 2013.03.18

APK를 IDA로 동적디버깅하는 방법을 포스팅하겠습니다


인터넷에 Netbeans를 이용해서 디버깅하는 자료가 나와 있는데 안드로이드 6.0부터는 Netbeans가 지원이 안되는 것 같네요 ( 확실하진 않지만 제가 해봤을때는 안되네요 :/ )


디버깅 하고자 했던 원래 의도는 무결성을 훼손하지 않으면서 디버깅을 하고 싶었는데, 그건 아마 안되는 것 같습니다


예시를 위해 기존에 포스팅했던 Uncrackable1 앱을 이용하겠습니다


일단 APK파일의 AndroidManifest.xml 파일에 debuggable속성을 넣어줘서 리패키징을 해야 합니다



리패키징된 APK파일을 단말기에 설치한 후, APK파일을 IDA에서 로드합니다



APK파일이 zip파일이므로 로드하게 되면 내부 파일을 선택하라는 창이 나오는데 여기서 calsses.dex를 선택합니다



로드하면 classes.dex의 smali코드가 출력됩니다



smali코드의 원하는 지점에 브레이크포인트를 설정합니다


F2 혹은 smali코드 라인에서 우클릭하면 브레이크포인트를 설정할 수 있습니다



브레이크 포인트를 설정하고 나면 설정한 위치에 빨간 라인이 생깁니다



앱을 실행시켜주기전에 한가지 설정을 해줘야 합니다 


[Debugger] - [Debugger options]



생성되는 창에서 [Set sepecific options]로 들어가 줍니다



Package name 및 Activity에 알맞은 값을 설정해 줍니다



설정이 완료되면 Debugger의 Start Process 혹은 attach를 시켜주면 됩니다



그럼 시간이 좀 걸린 후에 브레이크포인트에 실행지점이 도달하게 되면 다음과 같이 디버깅 창을 확인하실 수 있습니다



[Debugger] - [Debugger windows] - [Locals]에서 변수값들 확인도 가능합니다 :)



IDA에서 Dex와 so를 같이 디버깅 하는 방법은 다음 포스팅에 있습니다.

https://taesun1114.tistory.com/entry/IDA-DEXSO-동적디버깅?category=729990




'Mobile' 카테고리의 다른 글

Android Proxy Burp 인증서 설치  (2) 2018.09.15
Uncrackable3-1  (2) 2018.06.14
welcome to droid (codegate2018)  (2) 2018.02.11
INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable3 - frida  (0) 2018.01.30

Welcome to Droid 


codegate 2018이 열렸는데요 


참가는 안했지만 모바일 문제가 하나 출제되었다길래 풀어봤습니다


일단 앱을 실행시켜 보겠습니다


    


에뮬레이터로 실행하면 처음에 ID를 입력받고 PW를 입력받습니다 


ID/PW를 임의의값으로 입력하니 PW입력 직후에 wrong! try again이라는 문구가 출력되네요


디컴파일 후에 소스를 분석해 보겠습니다



처음에 ID 입력부분에서 입력값의 길이가 10이상 26자리 이하여야만 통과가 되었네요 임의의 값이 우연찮게 10자리여서 통과가 되었나 봅니다



PW입력 부분인데 Main2Activity class의 a 함수에서 PW를 확인하는 로직을 확인할 수 있습니다



a 함수를 살펴보면 codegate2018hurry!HAHAHALOL 이었나.. 확실하게 기억이 안나는데 해당 문자열을 이용하여 패스워드를 생성한후 최종적으로 paramString변수에 담아 리턴 후 입력받은 문자열과 비교하게 됩니다



다음 Main3Activity도 확인해 보니 시리얼키를 입력해야 하는 것 같습니다


이번에는 Main3Activity의 k함수에서 비교하네요



k함수에서는 ABCDEFG.....Z123....9의 문자을 가지고 시리얼을 생성하여 입력값과 비교합니다



마지막으로 Main4Acitivity에서는 native-lib.so에 파일에 저장된 flag를 출력하네요


풀이법으로는 여러방법이 있겠지만 smali코드의 분기문을 변조하여 거짓일때 실행되도록 변경하겠습니다



Main2Activity.smali파일에서 분기문을 확인합니다 Main2Activity.smali파일을 확인하니 $2파일에 setOnClickListener가 정의되어 있네요



Main2Activity$2.smali , Main3Activity$2.smali의 분기문을 변경한 후에 리패키징하여 에뮬레이터에 다시 설치해줍니다



임의의 값을 입력하고 계속 넘어가면 Main4Activity가 불리면서 Flag를 확인할 수 있습니다 :)



Try & Error


문제를 푸는 도중 smali코드를 변경하고 평소처럼 리패키징하는 경우, 다음과 같은 에러를 확인할 수 있었습니다


resource를 찾을 수 없다는 에러인데... 


삽질하다가 apktool의 옵션중 리소스 디컴파일을 하지 않는 옵션을 주고 해결했습니다.


java -jar apktool.jar d -r droid.apk


이렇게 디컴파일한 상태에서 smali를 변경하고 리패키징하면 정상적으로 리패키징되는 것을 확인할 수 있습니다



또한, apk파일 설치 시에 에러를 확인 할 수 있었는데 해당 내용은


http://taesun1114.tistory.com/entry/INSTALL-FAILED-TESTONLY?category=729990 과 같습니다


마지막으로 Frida를 통해 무결성을 훼손하지 않고 패스워드와 시리얼을 획득하여 문제를 풀어보려 했는데 실패했습니다


아직 Frida가 능숙하지 않아서 에러가 나면 한참 헤매게 되네요ㅠ 후에 Frida를 통해 문제를 해결하고 포스팅하도록 하겠습니다 :)


'Mobile' 카테고리의 다른 글

Uncrackable3-1  (2) 2018.06.14
APK IDA로 동적디버깅  (0) 2018.02.22
INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable3 - frida  (0) 2018.01.30
Uncrackable1 - frida  (4) 2018.01.30
APK 설치 시, 다음과 같은 에러를 확인 할 수 있었습니다


검색을 해보니, 에러가 다음과 같이 정의되어 있네요



INSTALL_FAILED_TEST_ONLY는 test-only로 명시되어 있어서 에러가 납니다


adb install 옵션중에 -t를 넣어 설치를 하거나 androidmanifest.xml파일에서 test-only옵션을 제거해 주시면 됩니다:)


adb install -t <apk_name>


출처


'Mobile' 카테고리의 다른 글

APK IDA로 동적디버깅  (0) 2018.02.22
welcome to droid (codegate2018)  (2) 2018.02.11
Uncrackable3 - frida  (0) 2018.01.30
Uncrackable1 - frida  (4) 2018.01.30
Android에서 호출한 Class/Method 확인하기 - with Frida  (0) 2018.01.26

frida를 이용해서 다른 스크립트 작성 중 검색을 통해 Uncrackable 실습앱을 발견하다보니, 순서가 뒤죽박죽이네요


Uncrackable 실습앱은 level3까지 나와있습니다

마지막인데.. 앱을 설치하고 실행하면 그냥 종료되네요 

처음엔 이것도 우회해야 하는 건가 싶어 한참을 헤맷으나 확인해보니 출제자 에러인 것 같습니다

DDMS를 통해 실행 후 로그를 확인해 봤습니다


로그를 확인하니 세그멘테이션 오류인 듯 합니다


디컴파일 후 소스를 확인해 보겠습니다



앱 분석 당시에는 그냥 출제자 에러인가 보다 하고 넘겼는데... 글을 작성하면서 소스를 보니 뭔가 verifyLibs에서 뭔가를 해주네요


일단 글작성후에 다시 분석을 해보도록 하겠습니다



분석할 당시에는 libfoo.so파일의 strncpy 함수를 호출할 때 인자로 NULL이 들어가서 세그멘테이션 에러가 발생한다고 생각했는데..


글 작성하면서 다시 보니, lib에 뭔가 조치를 해줘야 앱이 실행되는 걸까요? 조금 더 분석해 봐야 겠네요 :)



'Mobile' 카테고리의 다른 글

welcome to droid (codegate2018)  (2) 2018.02.11
INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable1 - frida  (4) 2018.01.30
Android에서 호출한 Class/Method 확인하기 - with Frida  (0) 2018.01.26
Uncrackable2 - Radare2  (0) 2018.01.23

Frida 자료를 찾던 중 좋은 실습앱이 있어 Frida를 통해 Uncrackable1 앱 우회를 하겠습니다



앱 실행 시, 루팅탐지 후 종료하게 됩니다


디컴파일 후에 루팅 탐지 로직을 확인하면 다음과 같습니다



sg.vantagepoint.a.c.class에서 루팅을 확인하는데 총 3번에 걸쳐서 탐지를 합니다


해당 실습앱이 올라와 있는 사이트에서는 exit 함수를 후킹하여 exit함수 호출 시 아무런 동작도 하지 않도록 하는데, activity가 떠있는 상태에서는 굳이 루팅체크로직을 일일히 후킹하지 않더라도 이런 방법으로도 우회가 가능하네요 :)


그럼 exit를 후킹하여 앱종료 명령 시, 무시하는 코드를 작성하도록 합니다


import sys
import frida

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


PACKAGE_NAME = "sg.vantagepoint.uncrackable1"

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호출 시 콘솔에 로그 출력만 하도록 후킹을 걸고 String을 입력 후 버튼을 눌러보겠습니다




문자열 비교 후 알람을 출력합니다 다시 디컴파일 된 소스코드를 확인해보면



분기문이 보입니다 sg.vantagepoint.a.a.class에서 문자열을 비교하는 것 같습니다



arrayOfByte2에 찾아야할 문자열이 암호화 후 저장되어 있고, sg.vantagepoint.a.a.a를 호출하여 arrayOfByte2를 복호화하여 입력값과 비교하는 것 같습니다


위 화면의 네모박스에 있는 스트링은 AES복호화할 때 사용하는 키값인 것 같네요


sg.vantagepoint.a.a.class를 확인해보니 맞는 것 같습니다 


이 class에서 복호화된 문자열을 return하므로 해당 함수를 후킹하여 복호화된 문자열을 추출하도록 하겠습니다


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

PACKAGE_NAME = "sg.vantagepoint.uncrackable1"
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");
        }
     
  a = Java.use("sg.vantagepoint.a.a");
        a.a.implementation = function(a,b){
            console.log("[*]Hooking in a.Class");
            retVal = this.a(a,b);
            passcode='';
            for(i=0;i<retVal.length;i++){
                passcode+=String.fromCharCode(retVal[i]);
            }
            console.log("Secret key :"+passcode);
            return retVal;
        }
    });
"""
   
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()함수 후킹 소스에 덧붙여 sg.vantagepoint.a.a.a를 후킹하는 스크립트를 추가합니다


단순하게 기존 함수의 리턴값을 받아 출력하는 함수입니다


실행시켜 보면 복호화된 문자열이 출력되는 것을 볼 수 있습니다 :)




'Mobile' 카테고리의 다른 글

INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable3 - frida  (0) 2018.01.30
Android에서 호출한 Class/Method 확인하기 - with Frida  (0) 2018.01.26
Uncrackable2 - Radare2  (0) 2018.01.23
Android Anti-Debugging  (1) 2018.01.23
Java에서 자신을 호출한 클래스나 함수는 Throwable의 getStackTrace를 이용하여 확인할 수 있습니다

Android에서도 Frida를 이용해 무결성을 훼손하지 않고 호출한 함수를 확인해 보겠습니다

예제로 작성한 APP 소스입니다

package com.example.gnsan.chfrida;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.button).setOnClickListener(Click);
}
Button.OnClickListener Click = new View.OnClickListener(){
public void onClick(View v){
chfrida();
}
};
void chfrida(){
chfrida2();
TextView textview = (TextView)findViewById(R.id.test);
textview.setText("Hello World!!!");
}
void chfrida2(){
}
}

간단하게 버튼을 클릭하여 텍스트를 변경하는 앱입니다. 호출 함수를 확인하기 위해 chfrida / chfrida2를 작성하였습니다


Frida 소스입니다


line:13에서 Throwable를 로드하고 line:16에서 instance 생성 및 line:17에서 getStackTrace를 호출합니다



실행하면 위에서 부터 차례로 호출했던 함수를 출력하네요 :)




'Mobile' 카테고리의 다른 글

Uncrackable3 - frida  (0) 2018.01.30
Uncrackable1 - frida  (4) 2018.01.30
Uncrackable2 - Radare2  (0) 2018.01.23
Android Anti-Debugging  (1) 2018.01.23
Instant Run(Split apk)  (1) 2018.01.10

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/

App 진단 중 간단한 Anti-Debugging 기법을 알게되었습니다.


ptrace를 이용한 기법인데 ptrace에 대한 자세한 내용은


http://research.hackerschool.org/temp/ptrace.txt


위 주소에 더 잘나와있네요. 해커스쿨에서 작성된 내용을 보자면 


/*


ptrace의 특징은, 다양한 기능들을 함수 인자로 처리한다는 점입니다.


ptrace(PTRACE_ATTACH, ... ); // 이렇게 하면 process를 attach하겠다는 것이고요


ptrace(PTRACE_GETREGS, ... ); // 이건 대상 process의 레지스터 목록을 받아오라는 거죠


ptrace(PTRACE_PEEKDATA, ... ); // 이처럼 데이터를 쓰거나


ptrace(PTRACE_POPEDATA, ... ); // 가져올 수 있습니다.

*/ 등등인데 유명한 GDB, Frida도 ptrace를 이용해서 동작한다고 하네요


1. Ptrace Anti-Debugging 


Android Anti-Debugging 기본 예제는 다음과 같습니다.


void anti_debug() {

    child_pid = fork();

    if (child_pid == 0)
    {
        int ppid = getppid();
        int status;

        if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0)
        {
            waitpid(ppid, &status, 0);

            ptrace(PTRACE_CONT, ppid, NULL, NULL);

            while (waitpid(ppid, &status, 0)) {

                if (WIFSTOPPED(status)) {
                    ptrace(PTRACE_CONT, ppid, NULL, NULL);
                } else {
                    // Process has exited for some reason
                    _exit(0);
                }
            }
        }
    }
}

출처 : www.vantagepoint.sg/blog/89-more-android-anti-debugging-fun



Anti-Debugging 기본 예제 소스는 위와 같습니다.


원리는 fork()를 이용해서 자식프로세스에서 부모프로세스를 ptrace하면 다른 프로세스에서 해당 프로세스로 ptrace 시도 시, 이미 점유되어 있어서 다른 디버거에서 attach가 불가능한 원리입니다.


2. Anti-Debugging 우회


2.1 With Frida

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

PACKAGE_NAME = sys.argv[1]
jscode = """
/// Inject_Jscode
"""
   
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)


Frida의 spawn을 이용하여 앱 실행 전에 프리다가 먼저 후킹을 시도하여 Anti-Debugging을 우회하는 방법과


frida -U -f <Package_Name> --no-pause


명령어를 입력하는 방법이 있습니다.


2.2 Integrity 


이건 뭐 별달리 설명드릴 부분은 아니지만.. 해당 로직 Smali를 변조하여 앱 리빌드 후에 실행시키는 방법인데, 이를 이용하려면 무결성 체크로직이 없거나 무결성 체크로직도 우회해야 합니다.



출처 : http://www.vantagepoint.sg/blog/89-more-android-anti-debugging-fun

+ Recent posts