naroSEC
article thumbnail

들어가기 앞서

 

TracerPid 검사를 통한 동적 디버깅 탐지 방안과 우회 기법

들어가기 앞서 디버깅 개요 및 동적 디버깅 사용을 위한 사전 조건 들어가기 앞서 '안드로이드/루팅 탐지 및 우회' 카테고리의 글 목록 모바일 분석 글을 주로 포스팅 합니다. naro-security.tistory.com

naro-security.tistory.com

이전 "TracerPid 검사를 통한 동적 디버깅 탐지 방안과 우회 기법" 포스팅에 이어서 안드로이드 OS의 시스템 속성인 ro.debuggable 값을 검사하여 동적 디버깅을 탐지하는 방법과 또 이를 우회하는 기법을 다뤄보도록 하겠다.

 

실습 진행에 사용되는 ANDITER 앱은 아래의 GitHub에서 다운로드 가능하다.

 

GitHub - naroSEC/Anditer

Contribute to naroSEC/Anditer development by creating an account on GitHub.

github.com


개요

[그림 1]

 

 

디버깅 개요 및 동적 디버깅 사용을 위한 사전 조건

들어가기 앞서 '안드로이드/루팅 탐지 및 우회' 카테고리의 글 목록 모바일 분석 글을 주로 포스팅 합니다. naro-security.tistory.com 루팅 탐지 및 우회 기법에 대한 주제에 이어서 이번 시간에는 디버

naro-security.tistory.com

이전 포스팅에서 안드로이드 애플리케이션에서 디버그 사용을 위해서는 두 가지 선택적 전제 조건이 필요하다고 설명했었다.

첫 번째는 AndroidManifest.xml 파일에 debuggable 속성이 true 설정되어 있을 때고, 두 번째는 Android 시스템 파일인 build.prop의 빌드 속성 중 ro.debuggable 값을 1로 변경해 사용할 경우이다.

 

Bypass Debuggable 탐지 항목은 두 번째 방법에서 사용되는 ro.debuggable 빌드 속성 값을 확인해 값이 1인 경우 애플리케이션이 디버그 모드로 동작 중인 것으로 판단해 탐지하게 된다.


실습 진행을 위한 사전 준비

[그림 2] ro.debuggable 값 확인

build.prop 파일은 Android OS 운영체제에서 사용되는 빌드 정보 및 시스템 속성이 포함된 파일로 디바이스 부팅 시 로드 된다. 파일은 /system 디렉터리 내에 위치하고 있으며 디바이스 콘솔에서 getprop 명령어를 통해 확인이 가능하다.

 

ANDITER를 활용한 시스템 속성 기반의 루팅 탐지 및 우회 방법

들어가기 앞서 2023.05.31 - [안드로이드] - ANDITER를 활용한 Writeable 기반의 루팅 탐지 및 우회 방법 ANDITER를 활용한 Writeable 기반의 루팅 탐지 및 우회 방법 들어가기 앞서 이전 포스팅에 이어 시스템

naro-security.tistory.com

추가로 ro.debuggable 빌드 속성은 사용자 임의 변경이 불가능하므로 실습 진행을 위해 값을 변경 하고자 하는 경우 위 "ANDITER를 활용한 시스템 속성 기반의 루팅 탐지 및 우회 방법" 포스팅에서 ro.adb.secure 속성 값 변경 시 사용했던 mgisk를 통해서 값을 변경하면 된다.


분석

[그림 3] isCheckDebuggable() 함수 소스코드

[그림 3]의 isCheckDebuggable() 함수는 Bypass Debuggable 탐지 결과를 반환해주는 역할을 한다. 코드를 보면 getSystemProperty 클래스의 prop() 함수가 사용됐으며, 해당 함수의 인자로 전달되는 시스템 속성 값을 반환한다.

그 후 equals() 함수를 통해 반환 받은 ro.debuggable 빌드 속성 값이 1인지 검증하게 되며 값이 1이라면 애플리케이션을 디버그 중인 것으로 판단해 탐지하게 된다.

 

Bypass Debuggable 탐지를 우회하기 위한 프리다 후킹 포인트는 세 가지가 있다.

첫 번째는 함수 결과와 상관없이 무조건 False를 반환하도록 isCheckDebuggable() 함수를 재 작성하는 방법이고 두 번째는 getSystemProperty 클래스의 prop() 함수로 전달되는 인자 값을 변조하는 방법이다. 그리고 세 번째는 속성 값 검증을 위해 equals() 함수의 인자로 전달되는 문자열을 변조하는 방법이다. 여기서는 세 번째 방법을 사용해 탐지를 우회해 보도록 하겠다.


우회 실습

[그림 4]  equals() 함수를 후킹하기 위한 Frida 스크립트

[그림 4]는 equals() 함수를 후킹하기 위해 필자가 작성한 Frida 스크립트이다. 코드를 보면 ①에서 equals() 함수 사용을 위해 StringsJVMKt 클래스 객체를 생성했고 isCheckDebuggable()에서 equals() 함수를 호출할 때 전달되는 인자의 데이터 타입에 맞춰 equals() 함수를 오버로딩으로 구현했다. ②에서는 두 번째 매개 변수(str2) 값이 1일 경우 더미 값으로 변조하고 변조한 더미 값을 인자로 원본 equals() 함수를 호출해 해당 결과 값을 반환하게 된다.

 

추가로 문자열 비교를 위해 equals() 함수로 들어오는 첫 번째 매개 변수(str1)가 getSystemProperty 클래스의 prop() 함수를 통해 반환 받은 ro.debuggable 속성 값이고, 두 번째 매개 변수(str2)가 첫 번째 매개 변수와 값 비교 시 사용되는 문자열이다.

 

[그림 5]  Bypass Debuggable 우회 성공

Frida를 통해 작성한 스크립트를 ADITER 애플리케이션에 어태치 하고 Bypass Debuggable 탐지 항목을 체크하면 Success! 가 출력되며 탐지가 우회된 것을 볼 수 있다.


마무리

지금까지 안드로이드 OS의 시스템 속성 중 하나인 ro.debuggable 값을 검사하여 동적 디버깅을 탐지하는 방법과 또 이를 공격자의 관점에서 어떻게 우회할 수 있는지 살펴봤다. 다음 포스팅에서는 안드로이드 앱을 동적 디버깅 시 사용하는 도구를 탐지하는 방안에 대해서 다뤄보도록 하겠다.

profile

naroSEC

@naroSEC

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

profile on loading

Loading...