Analysis
OS 변조 탐지 기능 적용 유무를 확인하기 위한 기능이다.
CHECK ROOT 버튼을 누르면 루팅 여부에 따라 "Device is rooted" or "Device is not rooted"라는 문자를 출력한다.
실제 테스트 하는 기기는 루팅 된 기기이기 때문에 다음과 같이 "Device is rooted"라는 문자열을 출력하는 것을 확인할 수 있다.
Code
RootDetectionActivity$onCreate$1
final class RootDetectionActivity$onCreate$1 implements View.OnClickListener {
final /* synthetic */ RootDetectionActivity this$0;
RootDetectionActivity$onCreate$1(RootDetectionActivity rootDetectionActivity) {
this.this$0 = rootDetectionActivity;
}
public final void onClick(View it) {
if (this.this$0.isRooted()) {
Toast.makeText(this.this$0.getApplicationContext(), "Device is rooted", 1).show();
} else {
Toast.makeText(this.this$0.getApplicationContext(), "Device is not rooted", 1).show();
}
}
}
버튼을 누를 경우 호출되는 함수이며, 이후 isRooted() 함수 결과값에 따라 "Device is rooted" 또는 "Device is not rooted" 둘 중 하나를 출력한다.
isRooted
public final boolean isRooted() {
boolean result = false;
for (String files : new String[]{"/system/app/Superuser/Superuser.apk", "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su", "re.robv.android.xposed.installer-1.apk", "/data/app/eu.chainfire.supersu-1/base.apk"}) {
result = new File(files).exists();
if (result) {
break;
}
}
return result;
}
해당 기기가 루트인지 아닌지 확인하는 함수로 문자열로 저장된 경로에 파일이 있는지 하나하나 exists() 함수를 통해 확인하여 result의 결괏값을 저장한다. (exists() 함수는 파일이 존재한다면 True 없다면 False를 반환한다)
이후 result 값을 반환하는 것으로 함수가 마무리 된다.
Exploit
Smali 변조
OS 변조 탐지 우회 중 한 가지 방법이다.
먼저 smali 변조할 코드를 찾기 위해 디컴파일을 진행한다.
디컴파일은 다음과 같이 APK Easy Tool을 이용하여 진행하면 쉽게 할 수 있다.
이후 smali → owasp → sat → goat 경로를 따라가면 RootDetectionAvtivity.smali 코드를 확인할 수 있다.
찾은 코드 파일을 열어준 후 isRooted() 함수 가장 마지막 return 이전에 "const v1, 0x0" 한 줄을 추가해준다. 결국에는 isRooted() 함수의 반환 값에 따라 루트인지 아닌지 판단하기 때문에 반환 값을 0으로 고정해 주는 것이다.
코드 수정 후 다음과 같이 APK Easy Tool로 돌아와서 컴파일을 진행한다.
컴파일 후 adb install을 사용하여 컴파일된 애플리케이션을 설치해준다.
설치 후 Root Detection을 확인해보면 루팅 된 기기임에도 불구하고 "Device is not rooted"라는 문자열이 출력된 것을 확인할 수 있다.
Frida
두 번째 방법은 Frida를 활용한 방법이다.
frida도 이전과 같이 isRooted() 함수를 후킹 하여 반환 값을 fasle로 반환하게 스크립트를 작성한다.
console.log("Script loaded successfully");
Java.perform(function x() {
console.log("java perform function");
var my_class = Java.use("owasp.sat.agoat.RootDetectionActivity");
my_class.isRooted.implementation = function (args) {
console.log("\n return false ");
return false;
};
});
스크립트를 실행한 다음 CHECK ROOT를 눌러주면 로그에 "return false"가 출력되고 애플리케이션에는 "Device is not rooted"가 출력되는 것을 확인할 수 있다.
Reference
'Android > Androgoat' 카테고리의 다른 글
Network Intercepting (0) | 2021.09.20 |
---|---|
Binary Patching (0) | 2021.09.20 |
Emulator Detection (0) | 2021.09.20 |