개발자가 C ++ 또는 C 언어로 코드를 개발하고 APK의 기능에 액세스 할 수있는 Android NDK를 사용하여 루팅 탐지와 같은 다양한 작업을 수행하는 경우에 Frida를 사용하여 C ++ 또는 C로 개발 된 함수를 동적으로 분석.
# Root Inpector 분석
- C ++로 작성된 원시 코드를 사용하여 루트 탐지에 대한 검사를 구현하는 Rootinspector라는 앱의 루팀 탐지 로직을 우회
1. rootinspector에 구현 된 루팅 탐지 로직은 두가지로 구성
java 함수 checkRootMethodNative12() 와 C++함수 checkifstream()
<그림 1. JAVA 메서드를 통한 Native 함수 호출>
<그림 2. 클래스 파일 내 선언된 Native 함수>
2. 네이티브 소스 코드 내 해당 함수는 Java_com_devadvance_rootinspector_Root_checkifstream로 작성되어 있음.
( _구분자로 된 패키지명 + 함수명)
<그림 3. C++로 작성된 Java_com_devadvance_rootinspector_Root_checkifstream 함수>
<그림 4. C++로 작성된 Java_com_devadvance_rootinspector_Root_checkfopen 함수>
3. 네이티브 코드 후킹을 위해 Frida의 Interceptor API 참조
- 링크 : https://www.frida.re/docs/javascript-api/#interceptor
- Interceptor를 이용하여 Low Memory나 지정된 라이브러리에 접근 가능
4. APK 파일 내 C++로 구현된 Target .so파일 확인
<그림 4. APK 내 C++로 구현된 네이티브 라이브러리 확인>
5. 후킹할 함수명 확인을 위해 디스어셈블러 사용
- Target : Java_com_devadvance_rootinspector_Root_checkfopen
6. 후킹 코드 작성
7. 로드 최초 실패 해결 및 전체우회코드
import frida
import sys
package_name = "com.devadvance.rootinspector"
def get_messages_from_js(message, data):
#print(message)
print (message['payload'])
def instrument_debugger_checks():
hook_code = """
var didHookApis = false;
Interceptor.attach(Module.findExportByName(null, 'dlopen'), {
onEnter: function (args) {
this.path = Memory.readUtf8String(args[0]);
console.log(this.path);
},
onLeave: function (retval) {
if(!retval.isNull() && this.path.indexOf('libnative2.so')!== -1 && !didHookApis) {
didHookApis = true;
console.log("File loaded hooking");
hooknative2();
}
}
});
function hooknative2(){
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_checkifstream"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_checkfopen"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_checkfopen"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_statfile"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_runsu"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_runls"), {
onLeave: function (retval) {
retval.replace(0);
}
});
Interceptor.attach (Module.findExportByName ( "libnative2.so", "Java_com_devadvance_rootinspector_Root_runpmlist"), {
onLeave: function (retval) {
retval.replace(0);
}
});
}
"""
return hook_code
device=frida.get_usb_device()
#run package
p1=device.spawn(["com.devadvance.rootinspector"])
process = device.attach(p1)
script = process.create_script(instrument_debugger_checks())
script.on('message',get_messages_from_js)
script.load()
#Extremely important to add this else the app would freeze
device.resume(p1)
sys.stdin.read()
'Android > Diagnostics' 카테고리의 다른 글
[Android Profiler] Method Trace (0) | 2018.07.25 |
---|---|
[Android] Smali Example (0) | 2017.04.27 |
[Android-Diagnostics] Android Decompile & Smali 수정(Toast) (0) | 2015.10.02 |
[Android-Diagnostics] ADB를 통한 현재 Activity 찾기 (0) | 2015.09.30 |
[Android-Diagnostics] Apktool (0) | 2015.06.11 |