들어가기 앞서
이전 "ro.debuggable 값 검사를 통한 동적 디버깅 탐지 방안과 우회 기법" 포스팅에 이어서 디버깅 도구인 JEB Decompiler를 탐지하는 방안과 또 이를 우회하는 기법을 다뤄보도록 하겠다.
실습 진행에 사용되는 ANDITER 앱은 아래의 GitHub에서 다운로드 가능하다.
개요
모바일 애플리케이션 디버그 시 해당 운영체제 및 아키텍처를 지원하는 모바일 전용 디버그 도구를 사용한다. 대표적으로 디버그 모드를 지원하는 도구로는 JEB, IDA, GDA, Ghidra가 있으며 디버그 시 별도의 에이전트 파일을 이용해 대상 애플리케이션과 상호작용 하며 스레드 작업을 진행하게 된다.
그리고 이러한 도구 사용 방지를 위한 탐지 방안으로는 "ro.debuggable 값 검사를 통한 동적 디버깅 탐지 방안과 우회 기법"에서 살펴본 바와 같이 디버그 하고 있는 프로세스의 Pid를 표시하는 상태 필드인 TracerPid 값을 확인하거나 각 도구들이 사용하는 에이전트들의 특징을 캐치하는 방법이 있다. 다만, 위에서 언급한 도구들 중 JEB의 경우 디버그 시 에이전트를 사용해 통신하는 방식이 아닌 VM(Virtual Machine) 어태치 방식을 사용하기 때문에 기존의 알려진 방법으로는 탐지가 불가해 별도의 방법을 사용해야 한다.
Bypass Debug Tools 탐지 항목은 동작중인 애플리케이션의 프로세스 정보를 확인해 JEB에서 디버그 시 참조하는 특정 라이브러리 파일이 사용 중인지 확인한다. 해당 라이브러리 파일이 메모리에 올라와 있다면 애플리케이션이 디버그 모드로 동작 중인 것으로 판단해 탐지하게 된다.
JEB Decompiler와 다른 디버깅 도구의 차이점
[그림 2]는 IDA 도구를 이용한 동적 디버깅 사용 예시로 그림과 같이 애플리케이션의 상태 필드인 TracerPid 값이 디버그 하고 있는 에이전트의 프로세스 Pid 값으로 변경된 것을 확인할 수 있다.
반면, JEB를 이용한 디버그 모드 사용 시 [그림 3]과 같이 TracerPid 값이 디버그를 사용하지 않았을 때와 동일한 것을 볼 수 있다. 이는 각 도구가 디버그 모드를 지원하는 방식에 따른 차이점에서 나타나는 것으로 대다수의 도구가 별도의 에이전트와 통신을 이용한 디버그를 지원한다면 JEB의 경우 에이전트 없이 자체 기술인 VM 방식을 통한 디버그 모드를 사용하기 때문이다. 따라서, 앞서 언급한 것과 같이 기존의 TracerPid 값을 확인해 탐지하는 방법이 아닌 별도의 방식을 사용해야 하며 JEB 경우 디버그 시 ART 플러그인 파일인 libopenjdkjvmti 참조한다는 점을 이용해 애플리케이션 메모리 주소에 해당 라이브러리 파일이 올라와 있는지 검증하는 방법으로 탐지할 수 있다.
[그림 4]와 [그림 5]는 디버그 모드를 사용했을 때와 사용하지 않았을 때의 차이점을 보여주고 있으며, 디버그 사용 시에는 애플리케이션 메모리 주소에 ART 플러그인 libopenjdkjvmti.so 파일이 참조되고 있는 것을 알 수 있다.
분석
[그림 6]의 isCheckCallPPID() 함수는 Bypass Debug Tools 탐지 결과를 반환해주는 역할을 한다. 코드를 보면 ①에서 프로세스 참조 주소가 저장되어 있는 /proc/self/maps 파일을 객체로 생성하고 ② 해당 파일의 존재 유무를 확인한다. ③에서는 객체로 생성한 /proc/self/maps 파일 내용을 읽어와 파일 내용에 libopenjdkjvmti.so 문자열이 포함되어 있는지 검사하고 문자열 존재 시 디버그 모드가 동작 중인 것으로 판단해 탐지하게 된다.
Bypass Debug Tools 탐지를 우회하기 위한 후킹 포인트는 세 가지가 있다. 첫 번째는 File 클래스 생성자를 후킹해 파일 객체 생성 시 들어오는 인자 값이 /proc/self/maps일 경우 더미 값으로 변조하는 방법이고 두 번째는 파일이 존재하는 검사할 때 사용하는 exists() 함수의 결과 값을 변조하는 방법이다. 마지막 세 번째는 문자열 비교 시 사용한 contains() 함수를 후킹해 전달되는 인자 값이 libopenjdkjvmti.so일 경우 더미 값으로 변조하는 방법이다. 여기서는 첫 번재 방법을 사용해 탐지를 우회해 보도록 하겠다.
우회 실습
[그림 7]은 File 클래스 생성자를 후킹하기 위해 필자가 작성한 Frida 스크립트이다. 코드를 보면 ①에서 File 클래스 사용을 위해 객체를 생성하고 생성자를 오버로딩으로 구현한다. ②에서는 File 객체 생성 시 들어오는 매개 변수 값 중 /proc/self/maps일 경우 더미 값으로 변조하고 변조한 더미 값을 인자로 File 객체를 생성해 결과를 반환한다.
Frida를 통해 작성한 스크립트를 ADITER 애플리케이션에 어태치 하고 Bypass Debug Tools 탐지 항목을 체크하면 Success! 가 출력되며 탐지가 우회된 것을 볼 수 있다.
마무리
지금까지 동적 디버깅 시 사용되는 JEB Decompiler가 다른 디버깅 도구와 어떻게 다른지 알아보고 이를 탐지하는 방법과 또, 공격자의 관점에서 어떻게 우회할 수 있는지 살펴봤다. 다음 포스팅에서는 앱 디버깅 시 디바이스에서 설정되어야 하는 개발자 모드에 대해서 알아보고 또 이를 탐지 및 우회하는 방안에 대해서 다뤄보도록 하겠다.
'안드로이드 탐지 및 우회 > 디버깅 탐지 및 우회' 카테고리의 다른 글
USB 디버깅 옵션 검사를 통한 동적 디버깅 탐지 방안과 우회 기법 (0) | 2023.08.03 |
---|---|
개발자 모드 검사를 통한 동적 디버깅 탐지 방안과 우회 기법 (0) | 2023.08.02 |
ro.debuggable 값 검사를 통한 동적 디버깅 탐지 방안과 우회 기법 (0) | 2023.07.11 |
TracerPid 검사를 통한 동적 디버깅 탐지 방안과 우회 기법 (1) | 2023.07.10 |
디버깅 개요 및 동적 디버깅 사용을 위한 사전 조건 (0) | 2023.07.10 |