의미없는 블로그

[Android] 루팅 탐지 기법 / 루팅 탐지 우회 기법 본문

# 나/nnobile (AOS, iOS)

[Android] 루팅 탐지 기법 / 루팅 탐지 우회 기법

SaltLee 2020. 10. 6. 09:24

[루팅 탐지 기법]

다양한 루팅 탐지 기법 있는데 거의 다 적용된 앱이 있어서 분석쓰

1) detectRootManagementApps : 루팅 관련 앱 탐지하는것 같다

2) detectPotentiallyDangerousApps : 루팅에서만 설치되는 Dangerous Apps 탐지인듯

3) checkForBinary("su") : su 바이너리 존재하는지

4) checkForBinary("busybox") : busybox 바이너리 존재하는지

5) checkForDangerousProps : default.prop 설정 관련임

6) checkForRWPaths : 시스템 디렉에 쓰기권한 탐지하는거

7) detectTestKeys : build.prop 설정 관련

8) checkSuExists : su 명령어 실행되는지

9) checkForRootNative : 이건 뭔지 모르겟다

10) checkForMagiskBinary : magisk 바이너리 존재하는지

 

1), 2) 루팅 관련 앱(패키지) 탐지

- 루팅 했을 때 설치 가능한 앱이 깔려있는지 확인하는거

- exists() 함수로 루팅 관련 패키지 등이 존재하는지 확인

- 대부분 탐지해야 하는 패키지가 배열에 선언되어 있고 반복문을 통해 해당 배열에 존재하는 모든 경우의 수를 확인함

패키지 예시

 

3), 4), 10) 루팅 관련 파일(바이너리) 확인

- 루팅 환경에서 사용하는 바이너리(/system/bin/su, /sbin/su, /system/xbin/busybox 등)가 존재하는지 확인하는 방법

- exists() 함수로 루팅 관련 바이너리 등이 존재하는지 확인

- 대부분 탐지해야 하는 바이너리가 배열에 선언되어 있고 반복문을 통해 해당 배열에 존재하는 모든 경우의 수를 확인함

CheckForBinary 예시

 

8) 루팅 관련 명령어 실행

- 루팅 환경에서 사용가능한 명령어(su, which 등)를 실행해보는 방법

- Rumtime.getRuntime().exec 이용하여 명령어 실행

- 거의 대부분의 코드가 try-catch 구문으로 되어 있음

- 특정 명령어 실행했을 때 에러 안나면 루팅 디바이스로 판단

- 실행되지 않는 경우는 해당 바이너리가 존재하지 않기 때문에 루팅 되지 않은 디바이스로 판단

- 또는 id 같은 명령을 실행해보고 결과값을 통해 판단 (ex. id가 0 이면 루팅 디바이스)

이건 다른 샘플 예시

 

5) build.prop(build TAG)

- 디폴트 안드로이드 이미지는 release-keys 태그를 가지나 커스텀된(루팅된) 이미지는 test-keys 태그를 가짐

- /system/build.prop 파일에 test-keys 값이 존재하는지 확인하는 방법

- ro.build.type, ro.build.tags, o.build.display.id, ro.build.description, ro.build.fingerprint 등의 값을 확인

 

6) 특정 디렉터리의 권한 확인(쓰기 권한)

일반적으로 안드로이드 디바이스는 특정 디렉터리에 쓰기 권한이 제한되어 있으나

루팅 시 이런 디렉터리에 쓰기 권한을 부여하는 경우가 있음 이를 탐지하는 케이스

ex) /system

 

7) default.prop

- /default.prop 의 설정값 확인

- ro.secure = 0 이면 루팅

- ro.debuggable = 1 이면 루팅

- service.adb.root = 1 이면 루팅 등

- 근데 루팅된 단말에서도 해당값 안바뀌는 듯 하다

- CVE 취약점으로 바꿀 수 있는듯 함 (참고 : https://securitynote.tistory.com/13)

 

기타) 프로세스 확인

ActivityManager.getRunningAppProcesses() 또는

ActivityManager.getRunningServices() 또는

Runtime.getRuntime.exec("ps") 명령 등을 통해 실행중인 프로세스 목록을 확인하고

루팅 관련 프로세스가 존재하면 탐지하는 형태

 

기타) 특정 디렉터리에 SetUID가 존재하는 파일 확인

일반적으로 루팅했을 때 사용하는 su와 같은 명령어는 백도어 파일의 일종임

일반 사용자 권한으로 root 권한을 획득해야 하기 때문에 이런 바이너리 파일에는 SetUID가 설정되어 있음

따라서 특정 디렉터리 하위에 SetUID를 가지고 있는 파일이 있는지 확인하는 방법

→ SetUID를 확인하는 로직을 구현하면 일반적인 파일명 변경 방식으로는 우회가 불가능함

 

참고

1) Xposed Framework를 이용한 루팅 탐지 우회 기법에 관한 연구

   oasis.dcollection.net/public_resource/pdf/000002221716_20201006093413.pdf

2) Root Detection in Android

   medium.com/@deekshithmoolyakavoor/root-detection-in-android-device-9144b7c2ae07

3) Root Detection in Android 번역본

   philosopher-chan.tistory.com/355

 

 

[루팅 탐지 우회]

1) 루팅 관련 파일이나 폴더를 직접 변경

- [루팅 관련 파일 탐지] 루팅 환경에서 사용하는 파일(/system/bin/su, /sbin/su, busybox )의 이름을 변경하여 우회

- [시스템 설정 확인] 시스템 설정 파일(build.prop, default.prop ) 내의 값들을 변경하여 우회

- [디렉터리 권한 확인] 특정 디렉터리(/system )의 권한을 확인하는 경우 해당 폴더의 이름을 변경하여 우회

 

2) API 후킹

- Frida 같은 도구를 사용하여 루팅 탐지 관련 API를 후킹해서 우회하는 방법

- [명령어 실행] 명령어 실행(Runtime.getRuntime().exec )으로 루팅 여부를 확인하는 경우 바이너리를 탐지하는

  명령을 후킹하여 su 대신 FAKE 등 의미없는 문자열로 우회

- [프로세스 탐지] 루팅 관련 프로세스를 확인하는 경우 관련 API(getRunningAppProcesses())를 후킹하여 우회

 

3) 소스코드를 직접 패치

- 소스코드에서 루팅 탐지 관련 로직을 직접 수정 후 리패키징하고 재서명하여 앱을 실행하는 것

- [명령어 실행], [루팅 관련 파일 탐지], [프로세스 탐지], [디렉터리 권한 확인], [시스템 설정 확인], [SetUID 확인]

  모든 루팅 탐지 기법을 우회 가능할 것으로 판단

 

# 소스코드 직접 패치 - 예시 1

isRooted, isRootedWithBusyBoxCheck 모두 각각 루팅탐지함수들에 대해 or 로 체크하고 있으므로

그냥 return 값이 false(0) 가 되게 만들면 된다

smali 에서 모든 조건(cond_0, cond_1)에서 return 값 false(0x0) 되게 수정해줌

 

# 소스코드 직접 패시 - 예시 2

루팅 탐지 로직 검색할 때 보통 su 로 검색하고

아래에 exists 함수로 su 관련 파일들 탐지하고 있어서 요기인 줄 알았는데 여기 바꿔도 안되었음

su 로 검색해서 나오는 부분들 다 고쳤는데도 안되가지고 뭐냐 했는데

아래처럼 getString() 으로 불러와서 검증하고 있음

exec 함수 있길래 이건가 싶어서 추측해봄..

Smali 에서 bool1 값 false 로 다 바꿔주면 우회됨

Comments