Veloideu - IT∽보안∽프로그래밍
article thumbnail
Published 2022. 9. 19. 10:45
[FRIDA] - Anti Debugging Bypass 🤖Android

문제 개요


안티 디버깅 우회 방법

1. Pthread_create

ㄴ Interceptor.replace

2. Fopen, Open, Access, Strstr, Strcmp, Strtok, System, Opendir, Scandir

ㄴ String값 및 경로 Interceptor.replace

3. Sprintf Hook

ㄴ String값 및 경로 Interceptor.replace

4. GetPid hook

ㄴ Retval Replace

5. IsDebuggerPresent() check

 

Frida_Hook

Pthread_create

Pthread_create와 동일한 Fake 함수를 만든 뒤, pthread_create를 fake 함수로 바꾼다.

fake 함수는 frida 검사를 위해 실행된 pthread_create 일 경우에 0을 반환시킨다.

// int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
var p_pthread_create = Module.findExportByName("libc.so", "pthread_create");
var pthread_create = new NativeFunction( p_pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"]);
send("NativeFunction pthread_create() replaced @ " + pthread_create);

Interceptor.replace( p_pthread_create, new NativeCallback(function (ptr0, ptr1, ptr2, ptr3) {
    send("pthread_create() overloaded");
    var ret = ptr(0);
    if (ptr1.isNull() && ptr3.isNull()) {
        send("loading fake pthread_create because ptr1 and ptr3 are equal to 0!");
    } else {
        send("loading real pthread_create()");
        ret = pthread_create(ptr0,ptr1,ptr2,ptr3);
    }

    do_native_hooks_libfoo();

    send("ret: " + ret);

}, "int", ["pointer", "pointer", "pointer", "pointer"]));


Fopen, Open, Access, Strstr, Strcmp, Strtok, System, Opendir, Scandir

StrStr Hook 탐색하려는 문자열('frida') 검색될 경우 해당 인덱스를 반환 하기

 [+] javascript exit hook

console.log("[*] Starting script");
Interceptor.attach(Module.findExportByName("libc.so", "strstr"), {
onEnter: function (args) {
var haystack = Memory.readUtf8String(args[0]);
if(haystack.indexOf('frida')!==-1 || haystack.indexOf('xposed')!==-1)
    this.frida = Boolean(1);
},
onLeave: function (retval) {
if(this.frida)
    retval.replace(0);
return retval;
}
});
send("Done with native hooks....");
Java.perform(function () {
    send("Hooking calls to System.exit");
    var sys = Java.use("java.lang.System");
    sys.exit.implementation = function() {
        send("System.exit called");
    };
    send("Done Java hooks installed.");
});

Sprintf hook

Java.perform(function() {
	console.error('\n[!] Let\'s Koo00 !\n')
	
	Interceptor.attach(Module.findExportByName(null, 'sprintf'), {
		onEnter: function(args) {
			// console.warn("[*] sprintf() called !")
			var str = args[1].readUtf8String();
			// console.log("\t[+] sprintf : " + str)			
			if(str.indexOf('/proc/') !== -1 && str.indexOf('/status') !== -1) {
				console.warn("[!] Debug Detection Pattern Found !")
				console.log("\t[+] sprintf str : " + str)
				console.log('[+] sprintf format : ' + args[2]);
				args[2] = ptr('0x0');
				console.log('[!] New sprintf format : ' + args[2]);
			}
		},
		onLeave: function(retval) {
		}
	})
})

 

sprintf 가 호출될 때 /proc/%d/status 에서 포맷을 바꾸었다.

adb에서 확인한 결과 자식 프로세스가 생성되지 않았다. 당연히 attach가 된다! (IDA 화면은 생략)


Getpid Hook

Java.perform(function() {
	console.error('\n[!] Let\'s Koo00 !\n')	
	
	Interceptor.attach(Module.findExportByName(null, 'getpid'), {
		onEnter: function(args) {
		},
		onLeave: function(retval) {
			console.log('\t[-] getpid retval : ' + retval);
			retval.replace(ptr('0x0'));
			console.log('\t[!] New getpid retval : ' + retval);
		}
	})
})

실행 결과를 먼저 확인해보자. getpid가 여러번 호출되었는데, 항상 0을 리턴하도록 만들었다.

adb에서 프로세스를 확인해보면 자식 프로세스가 생성되었다.

부모 프로세스의 pid는 사진에서도 알 수 있듯이 5739 이다. 하지만 TracerPid 값을 확인해보면 0이다.

IDA에서 해당 프로세스(5739)에 attach 해본다.

짜잔


IsDebuggerPresent() check

BOOL WINAPI IsDebuggerPresent();

function antidebugbypass(){
Interceptor.attach(Module.findExportByName(null, 'IsDebuggerPresent'), {
	
    onEnter: function(args) {
       	console.log("IsDebuggerPresent() is called");
    },
    onLeave: function(ret) {
       ret.replace(0);
	   console.log("bypass antidebug!");
   	},
});
}

console.log("[*]going silver!!!!")
antidebugbypass()
// frida .\target.exe .\poc1.js

FIRDA을 사용해 hooking후 안티 디버깅 우회

먼저 hooking code 없이 frida로 target.exe를 spawn하고나면 frida는 entrypoint 지점에 멈춘다. 그러면 프로그램을 실행하기 위해 %resume 명령을 주면 디버깅을 부착하지 않았으므로 [*]PASS를 출력하고 끝낸다.

(1) IsDebuggerPresent()을 후킹하기 위해 작성한 poc1.js 스크립트를 로드해 target.exe를 실행한다.

[출처] [AOS][FRIDA] Anti Debugging Bypass|작성자 Koo00

[출처] https://velog.io/@silver35/Anti-Anti-Debug-Fridabypassing-IsDebuggerPresent-check

'🤖Android' 카테고리의 다른 글

딥링크 취약점 진단 방법  (0) 2024.05.07
Droidx / Samsung App 솔루션 우회  (0) 2022.10.14
[AOS] Flutter Proxy Bypass / SSL Pinning  (0) 2022.10.14
〽APK 분석툴 제작 0.1V  (0) 2020.09.21
profile

Veloideu - IT∽보안∽프로그래밍

@Veloideu

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!