안드로이드 루팅 탐지 우회

KIM DO YOON·2025년 6월 7일
0

ANDITER 이라는 애플리케이션을 이용한 모바일 모의침투 테스트 학습 내용입니다.
해당 글은 그중에서 루팅 탐지 우회입니다.

https://github.com/naroSEC/Anditer

Bypass Packages

Bypass PackageBypass Package 개요

루팅을 하게 되면 사용할 수 있는 패키지들이 존재하는데 해당 문제는 루팅을 하게 되면 사용할 수 있는 패키지를 탐지하는 과정을 우회하는 문제이다.

과정

unpacking

apktool 을 이용하여 애플리케이션을 unpacking 하고 Java 코드를 보면 다음과 같이 특정 패키지들을 검사하고 있는 코드를 볼 수 있다.

해당 과정을 우회 하는 방법에는 크게 두가지 방법이 있다.

  • 스마일리 코드 변경 후 리패킹
  • Frida 를 이용한 우회

스마일리 코드 변경

위의 스마일리 코드를 보면 if-ge 문을 확인할 수 있다.

스마일리 비교 연산문 종류는 다음과 같다.


기본 비교 연산 if문

명령어문법설명Java 동등 표현
if-eqif-eq vA, vB, :label두 값이 같으면 레이블로 분기a == b
if-neif-ne vA, vB, :label두 값이 다르면 레이블로 분기a != b
if-ltif-lt vA, vB, :label첫 번째 값이 두 번째 값보다 작으면 분기a < b
if-leif-le vA, vB, :label첫 번째 값이 두 번째 값보다 작거나 같으면 분기a <= b
if-gtif-gt vA, vB, :label첫 번째 값이 두 번째 값보다 크면 분기a > b
if-geif-ge vA, vB, :label첫 번째 값이 두 번째 값보다 크거나 같으면 분기a >= b

Zero 비교 if문

명령어문법설명Java 동등 표현
if-eqzif-eqz vA, :label값이 0이면 레이블로 분기a == 0
if-nezif-nez vA, :label값이 0이 아니면 레이블로 분기a != 0
if-ltzif-ltz vA, :label값이 0보다 작으면(음수) 레이블로 분기a < 0
if-lezif-lez vA, :label값이 0보다 작거나 같으면 레이블로 분기a <= 0
if-gtzif-gtz vA, :label값이 0보다 크면(양수) 레이블로 분기a > 0
if-gezif-gez vA, :label값이 0보다 크거나 같으면 레이블로 분기a >= 0

명령어 구성 요소

요소설명
vA, vB비교할 레지스터 변수 (4비트 또는 8비트)
:label조건이 참일 때 이동할 레이블
분기 오프셋16비트 크기의 점프 위치 정보

다음과 같이 if 문 조건을 ge -> le 로 바꾸어 주었다.

앱 리패킹 후 재설치

우회 성공

Frida를 이용한 우회

다음과 같이 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;
    };
});

이렇게 우회할 함수를 여러개 지정할 수 있다.

Bypass Check Process

루팅을 하게되면 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);
     };
});

profile
안녕하세요 김도윤 입니다.

0개의 댓글