본문 바로가기

iOS 앱 점검(ObjC)/안티디버깅

ios) 안티디버깅 - sysctl

반응형

ios) 안티디버깅 - sysctl

ptrace와 비슷한 맥락이다.

다만 이번에는 ptrace flag가 설정됐는지 여부를 확인하는 것.

Is_debugger_present를 알고 있다면 동일하다고 생각하면 된다.

정보 : 디버거 아래에 자식으로 생성하던, 실행중인 프로세스에 attach를 했건 P_TRACED 플래그는 Set 된다.

 

아래 코드는 mobile-security-testing-guide의 ios-testing-guide에서 발췌함.

#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>

static bool AmIBeingDebugged(void)
    // Returns true if the current process is being debugged (either
    // running under the debugger or has a debugger attached post facto).
{
    int                 junk;
    int                 mib[4];
    struct kinfo_proc   info;
    size_t              size;

    // Initialize the flags so that, if sysctl fails for some bizarre
    // reason, we get a predictable result.

    info.kp_proc.p_flag = 0;

    // Initialize mib, which tells sysctl the info we want, in this case
    // we're looking for information about a specific process ID.

    mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_PID;
    mib[3] = getpid();

    // Call sysctl.

    size = sizeof(info);
    junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
    assert(junk == 0);

    // We're being debugged if the P_TRACED flag is set.

    return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}

배열 설정하고 sysctl를 호출하면 결과가 info에 담긴다.

결과로 얻은 info에 P_TRACED 플래그가 있는지 없는지 확인함으로써 디버깅 여부를 판단한다.

 

위 소스는 딱 봐도 우회하기 좋게 생겼다.

또한 sysctl을 호출한다는 사실로 앱이 디버깅 감지를 수행한다는 판단의 지표가 될 수도 있다.


[우회]

검증 함수 패치 혹은 후킹은 여태 하던대로 하면 된다.

디버거 상에서 실시간으로 우회할 때 편하게 접근하는 방법만 다룬다.

(gdb) break sysctl if $r1==4 && *(int *)$r0==1 && *(int *)($r0+4)==14 && *(int *)($r0+8)==1

특정 인자를 가진 sysctl에서 중단점을 설정하는 명령어이다.

 

 

ios에는 $r0~$r7가 인자 전달로 쓰이며 $r0부터 순서대로 들어간다고 보면 된다.

*(int *)$r0==1 (첫번째인자[0] == 1 : CTL_KERN)
*(int *)($r0+4)==14 (첫번째인자[1] == 14 : KERN_PROC)
*(int *)($r0+8)==1 (첫번째인자[2] == 1 : KERN_PROC_PID)
$r1==4 (두번째인자 == 4)

두번째 인자는 sizeof(mib)/sizeof(*mib)으로 배열의 총 크기를 한 요소의 크기로 나누는 것이므로 배열의 개수다.

    mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_PID;
    mib[3] = getpid();

이렇게 총 4개를 넘기므로, 두번째 인자에 4가 담겼는지를 확인하는 것.

 

(gdb) set $pinfo=$r2

우회하려면 결과로 받아온 플래그에서 P_TRACED 플래그를 제거해야하므로 세번째 인자인 kinfo_proc 구조체를 담아둔다.

 

(gdb) finish
(gdb) break *$pc if $pinfo!=-1

finish명령으로 sysctl 호출 끝까지 실행시키고, 받아온 info에 제대로 정보가 담겼다면 finish 위치에 bp를 건다.

정보를 담아온 다음이므로 잡아서 값을 바꾸면 됨.

 

(gdb) set $pflag = (*(int *)($pinfo+16))
(gdb) set *(int *)($pinfo+16) = $pflag & ~0x800

플래그 부분을 가져와서 0x800(P_TRACED) 플래그만 제거해서 다시 설정한다.

 

(gdb) print (*(int *)($pinfo+16) & 0x800)
(gdb) continue

print 출력 결과 0으로 나온다면 제대로 P_TRACED 플래그를 제거한 것.

끝.

 

[자동 우회 설정]

매번 bp 걸릴 때마다 저 짓을 하기는 번거로우니, commands 명령어로 bp걸렸을 때 수행될 명령어를 등록하자.

commands 1
silent
set $pinfo=$r2
continue
end
commands 2
silent
set $pflag = (*(int *)($pinfo+16))
set *(int *)($pinfo+16) = $pflag & ~0x800
set $pinfo=-1
continue
end
반응형

'iOS 앱 점검(ObjC) > 안티디버깅' 카테고리의 다른 글

ios) 안티디버깅 - getppid()  (0) 2020.07.27
ios) ptrace관련 안티디버깅 정리  (0) 2020.07.27