들어가기 앞서
이전 포스팅에 이어 Binaries 기반 탐지는 어떻게 이뤄지고 또 이를 어떠한 방안을 통해 우회할 수 있는지 다뤄보겠다.
실습 진행에 사용되는 ANDITER 앱은 아래의 Github에서 다운로드 가능하다.
개요
모든 OS에는 운영체제가 어떤 프로세스를 실행시킬 때 경로를 참조할 수 있도록 PATH 환경 변수가 제공된다. 이는 리눅스 커널 기반인 Android OS도 동일하며 콘솔 단에서 명령어 사용 시 시스템 환경 변수에 등록된 PATH를 참조해 명령어를 찾고 실행시키게 된다. 그리고 디바이스 루팅 시 설치되는 su 명령어도 시스템 환경 변수에 등록되어 호출 위치와 상관없이 명령어 사용이 가능해진다.
Bypass Command Execution 탐지 항목에서는 이러한 특징을 이용해 which 명령어를 통해 PATH 변수에 등록된 디렉터리 경로에 su 명령어가 존재하는지 검사하고 명령어 존재 시 루팅 디바이스로 판단해 탐지하게 된다. 추가로 which 명령어는 특정 명령어를 찾아주는 기능을 한다.
분석
JEB 디컴파일러 도구를 사용해 ANDITER 앱의 dex 파일 코드를 디컴파일 했으며, 디컴파일 과정은 별도로 다루지 않겠다.
[그림 2]의 isCheckRootingExec() 함수는 Bypass Command Execution 탐지 결과를 반환해 주는 역할을 한다. 코드를 살펴보면 Runtime.getRuntime().exec() 함수가 사용된 것을 볼 수 있는데 Runtime.exec()는 Windows, Linux, Unix 등의 시스템 명령어를 Java를 통해 실행한 후 그 결과를 받아오는 기능을 가지고 있다. 위 코드에서는 which와 su 를 인수 값으로 실행 결과를 받아와 su 명령어가 해당 디바이스에 존재하는지 검사한다.
이번 포스팅부터는 별도의 언급이 없는 이상 Frida를 통해 탐지 우회를 진행한다. Bypass Module 탐지를 우회하기 위한 후킹 포인트는 두 가지가 있다. 첫 번째는 함수 결과 상관없이 무조건 false를 반환하도록 isCheckRootingExec() 함수를 재 작성하는 방법이고 두 번째는 Runtime 클래스의 exec() 함수 호출 시 전달되는 인수 값을 더미 값으로 변조하는 방법이다. 여기서는 두 번째 방법을 사용해 탐지를 우회해 보도록 하겠다.
우회 실습
[그림 3]은 Runtime클래스의 exec() 함수를 후킹하기 위해 필자가 작성한 Frida 스크립트이다. 코드를 보면 ① exec() 함수 사용을 위해 Runtime 클래스 객체를 반환받고 isCheckRootingExec()에서 exec() 함수 호출 시 전달되는 인수의 데이터 타입에 맞춰 exec() 함수를 오버로딩으로 구현했다. ②에서는 함수로 들어오는 매개 변수 중 su 문자열이 포함되어 있을 경우 더미 값으로 변조하고 ③ 변조한 더미 값을 인수로 원본 exec() 함수를 호출해 결과 값을 반환하게 된다.
Frida를 통해 작성한 스크립트를 ADITER 애플케이션에 어태치 한다. 그 후 Bypass Command Execution 탐지 항목을 체크하면 Success! 가 출력되며 탐지가 우회된 것을 볼 수 있다.
마무리
지금까지 which 명령어를 이용한 루팅 디바이스를 탐지하는 방법과 또 이를 어떻게 우회할 수 있는지 살펴보았다. 다음 포스팅에서는 안드로이드 OS가 부팅 시 시스템에서 참고하는 Build 속성 값을 검사해 루팅 디바이스를 탐지하는 방법을 다뤄보도록 하겠다.
'안드로이드 탐지 및 우회 > 루팅 탐지 및 우회' 카테고리의 다른 글
ANDITER를 활용한 시스템 속성 기반의 루팅 탐지 및 우회 방법 (0) | 2023.06.01 |
---|---|
ANDITER를 활용한 Writeable 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.31 |
ANDITER를 활용한 Build.prop 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.25 |
ANDITER를 활용한 Binary 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.24 |
ANDITER를 활용한 Package 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.21 |