ANDITER 이라는 애플리케이션을 이용한 모바일 모의침투 테스트 학습 내용입니다.
해당 글은 그중에서 루팅 탐지 우회입니다.
https://github.com/naroSEC/Anditer
Bypass Package | Bypass Package 개요 |
---|---|
![]() | ![]() |
루팅을 하게 되면 사용할 수 있는 패키지들이 존재하는데 해당 문제는 루팅을 하게 되면 사용할 수 있는 패키지를 탐지하는 과정을 우회하는 문제이다.
apktool 을 이용하여 애플리케이션을 unpacking 하고 Java 코드를 보면 다음과 같이 특정 패키지들을 검사하고 있는 코드를 볼 수 있다.
해당 과정을 우회 하는 방법에는 크게 두가지 방법이 있다.
위의 스마일리 코드를 보면 if-ge 문을 확인할 수 있다.
스마일리 비교 연산문 종류는 다음과 같다.
명령어 | 문법 | 설명 | Java 동등 표현 |
---|---|---|---|
if-eq | if-eq vA, vB, :label | 두 값이 같으면 레이블로 분기 | a == b |
if-ne | if-ne vA, vB, :label | 두 값이 다르면 레이블로 분기 | a != b |
if-lt | if-lt vA, vB, :label | 첫 번째 값이 두 번째 값보다 작으면 분기 | a < b |
if-le | if-le vA, vB, :label | 첫 번째 값이 두 번째 값보다 작거나 같으면 분기 | a <= b |
if-gt | if-gt vA, vB, :label | 첫 번째 값이 두 번째 값보다 크면 분기 | a > b |
if-ge | if-ge vA, vB, :label | 첫 번째 값이 두 번째 값보다 크거나 같으면 분기 | a >= b |
명령어 | 문법 | 설명 | Java 동등 표현 |
---|---|---|---|
if-eqz | if-eqz vA, :label | 값이 0이면 레이블로 분기 | a == 0 |
if-nez | if-nez vA, :label | 값이 0이 아니면 레이블로 분기 | a != 0 |
if-ltz | if-ltz vA, :label | 값이 0보다 작으면(음수) 레이블로 분기 | a < 0 |
if-lez | if-lez vA, :label | 값이 0보다 작거나 같으면 레이블로 분기 | a <= 0 |
if-gtz | if-gtz vA, :label | 값이 0보다 크면(양수) 레이블로 분기 | a > 0 |
if-gez | if-gez vA, :label | 값이 0보다 크거나 같으면 레이블로 분기 | a >= 0 |
요소 | 설명 |
---|---|
vA, vB | 비교할 레지스터 변수 (4비트 또는 8비트) |
:label | 조건이 참일 때 이동할 레이블 |
분기 오프셋 | 16비트 크기의 점프 위치 정보 |
다음과 같이 if 문 조건을 ge -> le 로 바꾸어 주었다.
우회 성공
다음과 같이 js 코드를 만들었다.
Java.perform(function(){
var MainActivity = Java.use("com.playground.anditer.RootingDetector");
MainActivity.isCheckRootingInstalled.implementation = function(){
console.log("isCheckRootingInstalled 호출");
return false;
};
});
frida -D ce10171ab2e34c3f04 -f com.playground.anditer -l Bypass_Packages_frida.js
Java.perform(function(){
var MainActivity = Java.use("com.playground.anditer.RootingDetector");
MainActivity.isCheckRootingInstalled.implementation = function(){
console.log("isCheckRootingInstalled bypass");
return false;
};
MainActivity.isCheckRootingBinary.implementation = function(){
console.log("isCheckRootingBinary bypass");
return false;
};
MainActivity.isCheckRootingExec.implementation = function(){
console.log("isCheckRootingExec bypass");
return false;
};
MainActivity.isCheckRootingProcesses.implementation = function(){
console.log("isCheckRootingProcesses bypass");
return false;
};
});
이렇게 우회할 함수를 여러개 지정할 수 있다.
루팅을 하게되면 magiskd등의 프로그램들이 백그라운드에서 실행되게 된다.
다음과 같이 해당 프로그램들이 실행되고 있는지 확인할 수 있다.
Java 코드를 보면 ps -ef 명령어를 입력했을 때 magiskd 프로그램이 실행중인지 확인하게 된다.
위의 코드는 isRootCommand 함수이다. su 명령어를 사용해 ps -ef 결과값을 얻어내기 위한 코드이다.
==>>> su권한에서의 ps -ef 결과가 다르기 때문
해당 함수(isRootCommand) 함수에서는 ArrayList를 반환하지만 루팅이 되지 않은 환경에서는 su 명령어가 실행 되지 않으므로 su 명령어가 실행되는 것 만으로도 루팅이 되었는지 확인할 수 있다.
다음 js 코드로 우회할 수 있다. (ps -ef command 를 조작하는 방법)
Java.perform(function(){
var MainActivity = Java.use("com.playground.anditer.RootTools");
MainActivity.isRootCommand.implementation = function(command){
console.log("isRootCommand 함수 호출 : " + command);
if(command === "ps -ef"){
console.log("[*] ps -ef command detected => manipulate command");
var ArrayList = Java.use("java.util.ArrayList");
return ArrayList.$new();
}
return this.isRootCommand(command);
};
});