들어가기 앞서
이전 포스팅에 이어 시스템 디렉터리 권한 검사를 통한 탐지 방법과 또 이를 어떠한 방안을 통해 우회할 수 있는지 다뤄보겠다.
실습 진행에 사용되는 ANDITER 앱은 아래의 Github에서 다운로드 가능하다.
개요
디바이스 루팅 시 설치된 루팅 관련 애플리케이션 또는 응용 프로그램을 통해서 디바이스의 주요 설정을 변경할 수 있게 되며, 설정 변경 시 디바이스 내부 저장소에 위치한 시스템 디렉터리에 일반 사용자 쓰기 권한을 부여하는 경우가 있다.
Bypass Writeable 탐지 항목은 디바이스의 시스템 디렉터리의 권한을 검사하고 일반 사용자 권한에 쓰기 권한이 부여되어 있을 경우 루팅 디바이스로 판단해 탐지하게 된다.
분석
디렉터리 | 설명 |
/system | 디바이스 시스템 설정 파일들이 위치해 있다. |
/vendor | 디바이스 벤더사 설정 파일들이 위치해 있다. |
[표 1] 시스템 설정 디렉터리
디바이스 벤더사와 Android OS의 Linux 커널 버전에 따라 설정 파일이 위치한 디렉터리가 상이할 수 있지만 일반적으로 디바이스 시스템 설정 파일들이 위치한 디렉터리는 [표 1]과 같다. 참고로 Bypass Writeable 탐지 항목의 경우 사용 디바이스에 따라 탐지되는 사람이 있고 탐지되지 않는 사람이 있을 것이다. 필자의 경우도 항목에 탐지되기 위해 별도의 애플리케이션을 통해서 설정을 변경했으며, 원활한 실습 진행을 위해 탐지를 원하는 경우 ADB(Android Debug Bridge)를 통해 설정 변경이 가능하다.
ADB(Android Debug Bridge)는 Android 디바이스와 통신하며, 디버깅 등의 작업과 애플리케이션 설치, 디바이스 설정 확인, 시스템 log 출력 등의 작업을 할 수 있도록 지원하는 다목적 명령줄 도구이다.
또한, 로컬 PC에서 디바이스 접속 기능을 지원해 USB만 연결되어 있다면 바로 사용이 가능하다. 여기서는 ADB의 shell 명령어 기능을 이용해 Bypass Writeable 항목에서 탐지하고 있는 /vender/bin 디렉터리 권한을 [그림 2]와 같이 변경해 주겠다. Android 디버그 브리지 파일은 아래의 링크에서 다운로드 가능하다.
설치가 되었다면, Android 디버그 브리지 파일이 위치한 곳으로 이동 후 아래와 같이 진행하면 된다.
① 콘솔 창에서 디바이스 진입을 위해 adb shell 명령어를 입력해 준다.
② 시스템 설정 파일들이 위치한 중요 디렉터리들은 일반 사용자에게 변경 권한이 존재하지 않아 관리자 권한이 필요하다. 따라서, su 명령어를 사용해 관리자 권한을 획득해 준다.
③ chmod 명령어를 사용해 /vendor/bin 디렉터리의 권한을 변경한다.
④ 권한 변경이 정상적으로 되었는지 ls 명령어를 통해 확인한다.
⑤ 권한 변경이 되었다면 위 [그림 2]와 같이 출력되며 앱으로 돌아가 Bypass Writeable 탐지 항목을 체크해보면 루팅 디바이스로 탐지될 것이다.
이제 Bypass Writeables 탐지 항목의 소스코드를 살펴보겠다. 우리가 먼저 눈여겨봐야 할 것은 writeAbleFiles 리스트 변수다. 해당 변수에는 시스템 설정 파일이 위치한 디렉터리 목록들이 저장되어 있다. 그중에는 우리가 ADB를 통해 권한을 변경한 /vendor/bin 디렉터리도 포함되어 있는 것을 알 수 있다.
[그림 5]의 isCheckRWFile() 함수는 Bypass Writeable 항목의 탐지 결과를 반환해주는 역할을 한다. 소스코드를 살펴보면 [그림 4의] writeAbleFiles 변수가 ①에서 사용되고 있는 것을 볼 수 있으며, 반복문을 통해서 writeAbleFiles 변수에 저장된 디렉터리를 하나씩 확인한다 . ②에서는 Files 클래스를 사용해 권한을 확인하는데 파일의 권한을 가져오는 함수가 바로 getPosixFile
permissions() 함수로 반환되는 권한 값에서 OTHERS_WRITE(일반 사용자 쓰기 권한) 문자열이 존재할 경우 루팅 디바이스로 판단해 탐지하게 된다.
Bypass Writeable 탐지를 우회하기 위한 후킹 포인트는 세 가지가 있다. 첫 번째는 함수 결과 상관없이 무조건 false를 반환하도록 isCheckRWFile() 함수를 재 작성하는 방법이고 두 번째는 getPosixFilePermissions() 함수 호출 시 전달되는 인자 값을 더미 값으로 변조하는 방법이다. 세 번째는 디렉터리 객체를 반환 받기 위해 사용되는 Paths 클래스의 get() 함수를 후킹해 함수로 들어오는 매개 변수 값을 더미 값으로 변조하는 방법이다. 여기서는 세 번째 방법을 사용해 탐지를 우회해 보도록 하겠다.
우회 실습
[그림 6]은 Paths 클래스의 get() 함수를 후킹하기 위해 필자가 작성한 Frida 스크립트이다. 코드를 보면 ①에서 Paths 클래스 사용을 위해 클래스 객체를 반환 받고 isCheckRWFile() 함수에서 get() 함수 호출 시 전달되는 인자의 데이터 타입에 맞춰 get() 함수를 오버로딩으로 구현한다. ②에서는 함수로 들어오는 매개 변수 값을 더미 값으로 변조하고 변조한 더미 값을 인자로 원본 get() 함수를 호출해 결과 값을 반환한다.
Frida를 통해 작성한 스크립트를 ADITER 애플케이션에 어태치 한다. 그 후 Bypass Writeable탐지 항목을 체크하면 Success! 가 출력되며 탐지가 우회된 것을 볼 수 있다.
마무리
지금까지 안드로이드의 시스템 디렉터리에 일반 사용자 쓰기 권한이 존재하는지 검사해 루팅 디바이스를 탐지하는 방법과 또 이를 어떻게 우회할 수 있는지 살펴보았다. 다음 포스팅에서는 Build.prop 파일에 정의되어 있는 시스템 속성인 ro.secure, ro.adb.secure의 값을 확인해 비정상 값일 경우 루팅으로 탐지하는 방법을 다뤄보도록 하겠다.
'안드로이드 탐지 및 우회 > 루팅 탐지 및 우회' 카테고리의 다른 글
ANDITER를 활용한 프로세스 기반의 루팅 탐지 및 우회 방법 (0) | 2023.06.11 |
---|---|
ANDITER를 활용한 시스템 속성 기반의 루팅 탐지 및 우회 방법 (0) | 2023.06.01 |
ANDITER를 활용한 Build.prop 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.25 |
ANDITER를 활용한 명령어(which) 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.25 |
ANDITER를 활용한 Binary 기반의 루팅 탐지 및 우회 방법 (0) | 2023.05.24 |