들어가기 앞서
이전 포스팅에 이어 Binaries 기반 탐지는 어떻게 이뤄지고 또 이를 어떠한 방안을 통해 우회할 수 있는지 다뤄보겠다.
실습 진행에 사용되는 ANDITER 앱은 아래의 Github에서 다운로드 가능하다.
개요
디바이스 루팅 시 사용된 루팅 패치 프로그램에 따라서 상이할 수 있지만 관리자 권한을 획득하기 위한 명령어 파일인 su와 UNIX 명령행 도구들을 제공하는 busybox, 루팅 관리 매니저 등이 함께 설치된다. 대표적인 설치 파일들로는 su, busybox, magisk, supersu, daemonsu 등이 있다.
Bypass Binaries 항목은 이와 같이 루팅 시 설치되는 바이너리 파일들을 검사해 파일이 존재할 경우 루팅 디바이스로 판단해 탐지하게 된다.
이전 [Bypass Packages] 탐지 파트에서는 실제 런타임 코드를 수정하고 리패키징 과정을 거쳐 탐지를 우회했었다. 다만, 코드 변조 방법은 직접 코드를 수정하기 때문에 애플리케이션의 무결성을 해치게 된다. 실습하고 있는 ANDITER의 경우 애플리케이션 실행 시 별도의 무결성 변조 탐지가 동작하지 않아 문제없지만, 상용 애플리케이션의 경우 무결성 변조 탐지가 이루어지기 때문에 추가적인 탐지 우회가 필요하다. 하지만, 후킹 도구인 Frida를 사용한다면 무결성을 해치지 않고도 코드 수정이 가능하다. 이번 Bypass Packages 탐지 항목에서는 Frida 도구를 사용해 탐지를 우회해 보도록 하겠다.
Frida는 Windows, macOS, Linux, Android, iOS QNX 기반의 네이티브 애플리케이션을 후킹 할 수 있도록 기능을 제공하는 파이썬(Python) 라이브러리이다. 대표적으로 Android, iOS 모바일 플랫폼에서 많이 사용되며, Frida 스크립트 작성 시 Js, C, Swift 등 여러 언어에 대한 API를 지원한다. Frida에 대한 상세 기능과 사용법은 Frida 공식 문서(https://frida.re/)에 잘 설명되어 있어 해당 포싀팅에서는 이에 대해 별도로 다루지 않으며, 추후 따로 프리다 관련 자료를 준비해 포스팅하겠다.
분석
JEB 디컴파일러 도구를 사용해 ANDITER 앱의 dex 파일 코드를 디컴파일 했으며, 디컴파일 과정은 생략하겠다.
[그림 3]의 isCheckRootingBinary() 함수는 Bypass Binaries 탐지 결과를 반환해 주는 역할을 한다. 코드를 보면 ① rootingPath에서 시스템 디렉터리 목록을 가져오고 있으며 ②에서는 루팅 시 설치되는 파일 목록을 가져오고 있다. ③에서는 ①에서 가져온 디렉터리에 ② 루팅 시 설치되는 파일이 존재하는지 검사한다. 이때, 파일이 디바이스에 존재하는지 확인하는 함수가 File 클래스의 exists() 함수이며 파일이 존재할 경우 true를 반환하고 없을 경우 false를 반환한다.
대략적인 코드 분석이 끝이 났다면, Frida 도구를 통해 후킹 해야 할 공격포인트를 찾아야 한다. 해당 코드에서 탐지를 우회하기 위한 후킹 포인트는 세 가지가 있다. 첫 번째는 함수 결과와 상관없이 무조건 false를 반환하도록 isCheckRootingBinary() 함수를 재 작성하는 방법이고 두 번째는 File 클래스 객체 생성 시 전달되는 인수 값인 rootingPath, rootingBinaries를 더미 값으로 변조하는 방법이다. 그리고 세 번째는 File 클래스의 exists() 함수를 후킹해 반환 값을 변조하는 방법이다. 여기서는 세 번째 방법을 사용해 탐지를 우회해 하도록 하겠다.
우회 실습
[그림 4]는 exists() 함수를 후킹하기 위해 필자가 작성한 Frida 스크립트이다. 코드를 보면 ① isCheckRootingBinary() 함수에서 루팅 시 설치되는 파일 목록인 rootBinaries 값을 그대로 가지고 왔으며 ②에서는 exists() 사용을 위해 File 클래스 객체를 반환받고 Frida 자바 스크립트 API인 implementatio을 사용해 함수를 재 작성했다. ③에서는 exists() 함수 호출 시 호출되는 객체의 파일명을 가져와 ①의 rootBinaries 목록에 포함되어 있을 경우 false 반환하고 포함되어 있지 않다면 원본 exists() 함수를 호출해 해당 결괏값을 반환한다. 즉, ①에서 선언된 파일을 검사하려는 경우 무조건 false를 반환하고 그 외에는 정상 결과를 반환하게 된다. 추가로 더 다양한 Frida 코드를 보고 싶다면 Frida Code Share(https://codeshare.frida.re/)를 참고하기 바란다.
Frida를 통해 작성한 스크립트를 ADITER 애플케이션에 어태치 한다. 그 후 Bypass Binaries탐지 항목을 체크하면 Success! 가 출력되며 탐지가 우회된 것을 볼 수 있다.
마무리
지금까지 Binary 파일을 검사해 루팅 디바이스를 탐지하는 방법과 또 이를 어떻게 우회할 수 있는지 살펴보았다. 다음 포스팅에서는 루팅 탐지 시 가장 많이 사용하는 탐지 기법인 Which 명령어를 이용한 탐지 기법을 다뤄보겠다.
'안드로이드 탐지 및 우회 > 루팅 탐지 및 우회' 카테고리의 다른 글
ANDITER를 활용한 시스템 속성 기반의 루팅 탐지 및 우회 방법 (0) | 2023.06.01 |
---|---|
ANDITER를 활용한 Writeable 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.31 |
ANDITER를 활용한 Build.prop 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.25 |
ANDITER를 활용한 명령어(which) 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.25 |
ANDITER를 활용한 Package 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.21 |