Runtime Manipulation

옥영진·2023년 1월 29일
0

DVIA-v2

목록 보기
5/7

Login Method 1


입력한 계정 정보 입력 후 Login Method 1을 클릭하면 이를 확인 후 잘못된 계정을 입력하면 위와 같은 메시지를 출력한다.


출력되는 메시지를 검색하여 어느 로직에서 사용되고 있는 지 확인한다.

...loginMethod1Tapped... 메소드에서 사용하고 있는 것을 알 수 있다.


해당 메소드의 로직을 살펴 보면 TBZ 지시어에 따라 분기하여 결과를 보여주는데, 그 위에 isLoginValidated 메소드를 사용하여 해당 메소드의 리턴값에 따라 분기하는 것으로 예상할 수 있다.


그래서 isLoginValidated 메소드의 시작 주소를 확인한다.

if(ObjC.available){
    try{
        var base_address = Module.findBaseAddress('DVIA-v2');
        var target_address = base_address.add('0x15E38C'); 

         Interceptor.attach(target_address, {   
            onEnter: function (args) {
				console.log("");
				console.log("베이스 주소 : " + base_address);
				console.log("후킹 타겟 주소 : " + target_address);
                console.log("[+] 타겟 실행");
            },
            onLeave: function (retval) {
				console.log("리턴 값 : " + retval);
            }
        });
    }
    catch(err){
        console.log("[!] Error: " + err.message);
    }
}
else {
    console.log("Objective-C Runtime is not available!");
}

그리고 위 frida 코드를 작성하여 실행한다.


실행했을 때 해당 메소드의 리턴값이 0x0 인것을 확인할수 있었다.

if(ObjC.available){
    try{
        var base_address = Module.findBaseAddress('DVIA-v2');
        var target_address = base_address.add('0x15E38C');

         Interceptor.attach(target_address, {   
            onEnter: function (args) {
				console.log("");
				console.log("베이스 주소 : " + base_address);
				console.log("후킹 타겟 주소 : " + target_address);
                console.log("[+] 타겟 명령어 실행");
            },
            onLeave: function (retval) {
				console.log("리턴 값 : " + retval);
				retval.replace(ptr("0x1"));
				console.log("변환된 리턴 값 : " + retval);
            }
        });
    }
    catch(err){
        console.log("[!] Error: " + err.message);
    }
}
else {
    console.log("Objective-C Runtime is not available!");
}

리턴값을 변경하는 코드를 추가하여 재 실행한다.

앱에서 Login Method 1을 터치하면 성공적으로 인증을 우회할 수 있었다.

Login Method 2


다음으로 ...loginMethod2Tapped... 메소드를 확인해보면 조금 다른 모습을 확인할 수가 있다.

이번에는 Login Method 1 처럼 isLoginValidated 와 같이 검증 후 리턴되는 값을 확인하는 로직이 보이지 않아, 분기할 때 레지스터 값을 변경하는 방식으로 우회해보았다.

var module_base = Module.findBaseAddress('DVIA-v2');
console.log("베이스 주소 : " + module_base);
		
var offset = "0x1bded4";
var jailbreak_address = module_base.add(offset);
console.log("후킹 타겟 주소 : " + jailbreak_address);

Interceptor.attach(jailbreak_address, {   
            onEnter: function (args) {
				console.log("");
				console.log("베이스주소:" + module_base);
				console.log("서브루틴 주소:" + jailbreak_address);
                console.log("[+] 사용자함수 호출");
				
				this.context.x8 = 0x1;
            },
            onLeave: function (retval) {            
            }
        });

TBZ 지시어가 사용하는 w8(x8) 레지스터 값을 확인했을 때 0이었기 때문에 이를 1로 변경하는 frida 코드를 생성하여 실행해준다.


Login Method 2를 터치하면 성공적으로 우회할 수 있었다.

Validate code


4자리 코드 입력 후 인증하는 로직인데, 잘못된 코드 입력 시 출력되는 메시지를 확인한다.


해당 메시지를 사용하는 로직을 찾아보니 CMP 지시어의 결과에 따라 분기해서 메시지를 출력하는 것을 알 수 있다.

var module_base = Module.findBaseAddress('DVIA-v2');
console.log("베이스 주소 : " + module_base);
		
var offset = "0x15E3E0";
var jailbreak_address = module_base.add(offset);
console.log("후킹 타겟 주소 : " + jailbreak_address);

Interceptor.attach(jailbreak_address, {   
		onEnter: function (args) {
			console.log("");
			console.log("베이스주소:" + module_base);
			console.log("서브루틴 주소:" + jailbreak_address);
			console.log("[+] 타겟 호출");
			
			console.log("x9 : " + this.context.x9);
			console.log("x8 : " + this.context.x8);
		},
		onLeave: function (retval) {            
		}
	});

CMP 지시어에서 x8, x9 레지스터의 값을 서로 비교하는 것으로 보아 둘 중 하나는 정답 코드일 것으로 예상되므로 이를 출력하는 frida 코드를 작성한다.


frida 코드를 실행하면 Validate code를 터치했을 때 x8, x9의 값이 출력된다.


0x457의 값이 바로 입력했던 1111이므로, 0x2290이 바로 맞는 코드인 것을 알 수 있다.

그렇다면 x9의 값을 0x2290으로 바꿔도 되고, x8, x9 둘 다 같은 값으로 변경하는 방법이 있을 수 있는데, 후자의 방법으로 코드를 작성해보았다.

var module_base = Module.findBaseAddress('DVIA-v2');
console.log("베이스 주소 : " + module_base);
		
var offset = "0x15E3E0";
var jailbreak_address = module_base.add(offset);
console.log("후킹 타겟 주소 : " + jailbreak_address);

Interceptor.attach(jailbreak_address, {   
		onEnter: function (args) {
			console.log("");
			console.log("베이스주소:" + module_base);
			console.log("서브루틴 주소:" + jailbreak_address);
			console.log("[+] 타겟 호출");
			
			this.context.x8 = 0x1;
			this.context.x9 = 0x1;
		},
		onLeave: function (retval) {            
		}
	});

x8, x9 레지스터의 값을 0x1로 똑같이 변경하는 코드를 작성후 실행한다.


다시 무작위 코드 입력 후 validate code를 터치하면 성공적으로 인증할 수 있었다.

profile
안녕하세요 함께 공부합시다

0개의 댓글