iOS도 기본적으로 안드로이드와 동일한 방식으로 후킹한다.
둘 다 특정 함수가 호출되는 시점을 잡기 떄문이다.
Hooking 시 사용하는 JAVA API에 간략하게 설명하겠다.
setImmediate(fn): Hooking이나 함수 Holding으로 앱 실행이 늦어질 때 timeout으로 종료되는 것을 방지한다.
Java.Perform(fn): 스레드가 가상머신에 연결되었는지 확인하고 함수(fn)를 호출한다.
Java.androidVersion : 사용하고 있는 안드로이드 버전의 기기를 반환함
Java.enumerateLoadedClasses(callback):
- onMatch(이름, 핸들):에 지정된 개체가 자바스크립트 래퍼를 가져오기 위해 use()할 수 있는 이름을 가진 로드된 각
클래스에 대해 호출되는 클래스를 열거.
- onComplete(): 모든 클래스가 열거되면 호출
예시1 ➔ 안드로이드 내 고유 함수 후킹
Java.perform(function(){
const objS = Java.use("java.lang.String");
console.log("[*] Hooking Start");
objS.equals.overload('java.lang.String').implementation = function(arg0){
console.log(arg0);
var data = this.equals(arg0);
return data;
};
console.log("[*] Hooking End");
});
예시 2 ➔ 클래스 메소드 순차 후킹
setTimeout(function() { // avoid java.lang.ClassNotFoundException
Java.perform(function() {
var hook = Java.use("루팅 탐지 Class 명"); // 루팅 탐지 클래스
console.log("");
console.log("info: hooking target class");
// 아래에 메소드
hook.isEmulator.overload().implementation = function() {
console.log("info: entered target method");
// obtain old retval
var retval = this.isRooted.overload().call(this);
console.log("old ret value: " + retval);
// set new retval
var retnew = false;
console.log("new ret value: " + retnew);
return retnew;
}
});
}, 0);
예시 3 ➔ 해당 Class가 생성한 인스턴스가 생길 시 후킹
Java.perform(function() {
Java.choose("com.examplePackage.exampleClass",
{
/* when instance founded, 'onMatch` function will called */
onMatch: function(instance)
{
console.log("[+] Instance Found! Hook Start");
},
/* when their action is finished, 'onComplete' function will called */
onComplete: function()
{
console.log("[*] Instance Finished");
}
});
});
메모리 단 후킹 예시
libnative-lib.so 라이브러리 내에 있는 Jniint() 메소드 후킹하여 해당 메소드가 동작시 메모리 주소에 접근하여 변조한다.
후킹 메소드의 메소드만 알 경우 findExportByname(null , "fopen") 를 써도 된다.
Interceptor.attach(Module.getExportByName('libnative-lib.so', 'Jniint'),{
onEnter: function(args) {
this.first = args[0].toInt32();
console.log("on enter with : " + this.first)
},
onLeave : functin(retval){
const dstAddr = Java.vm.getEnv().newIntArray(117878);
console.log("dstAddr is : " + dstAddr.toInt32())
retval.replace(dstAddr)
}
});