Runtime Manipulation

justugi·2024년 7월 8일
0

DVIA

목록 보기
4/11

주의사항 : 이 포스팅은 개인 학습 및 교육적 목적으로 작성되었으며, 제공하는 정보를 악용하여 불법적인 행위를 하는 것은 엄격히 금지되어 있습니다. 타인의 시스템에 대한 접근 권한을 얻기 위해 명시적인 동의를 받아야 하며, 이러한 기술을 사용하여 발생하는 모든 결과에 대한 책임은 사용자에게 있습니다.

Runtime Manipulation

: 런타임 조작이란 디버깅 툴을 이용해 앱이 실행 중인 상태에서 흐름을 조작하여 보안 기능을 우회하는 것을 말한다.

  • 런타임 조작을 통해 인스턴스 변수를 수정, 로그인(인증) 검사 우회, 무차별 강제 핀 코드 등을 사용할 수 있다.
  • 인증 값이 맞을 때까지 무차별 대입 공격을 수행하는 것도 가능하다.

Login Method 1

  1. 로그인 시도

  • ID / Password 미입력 시 오류 메세지

  • ID / Password 미일치 시 오류 메세지
  1. 클래스 찾기
// RuntimeManipuation1.js
// 클래스 이름 출력

if(ObjC.available){    
	for(var classname in ObjC.classes) 
		console.log(classname)	
} 

  • 클래스 중 LoginValidate 클래스가 로그인 기능을 하는것으로 추정
  1. 메서드 찾기
// RuntimeManipuation1_2.js
// 메소드 이름 출력

if(ObjC.available){
	var classname = "LoginValidate"
	var methods = ObjC.classes[classname].$ownMethods
	for(var i=0; i<methods.length; i++){
		console.log(methods[i]) 
    }
}

  • isLoginValidated 메소드 하나 있다.
  1. 반환 값 확인
// RuntimeManipuation1_3.js

if(ObjC.available){
	var classname = "LoginValidate"
	var methodname = "isLoginValidated"
	var hook = ObjC.classes[classname][methodname]
	
	Interceptor.attach(hook.implementation,{
		onLeave:function(retval){
            console.log("Runtime 조작")
			console.log("[+] 클래스 명: " + classname)
			console.log("[+] 메소드 명: " + methodname)
			console.log("[+] 반환 값 타입: " + hook.returnType)
			console.log("[+] 반환 값: " + retval)
		}
	})
}
  • id / Password 입력 후 Login Method 1 터치

  • 반환 값: 0x0 이 출력된다.
  1. 반환 값 변조
// RuntimeManipuation1_4.js

if(ObjC.available){
	var classname = "LoginValidate"
	var methodname = "isLoginValidated"
	var hook = ObjC.classes[classname][methodname]
	
	Interceptor.attach(hook.implementation,{
		onLeave:function(retval){
			console.log("Runtime 조작")
			console.log("[+] 클래스 명: " + classname)
			console.log("[+] 메소드 명: " + methodname)
			console.log("[+] 반환 값 타입: " + hook.returnType)
			console.log("[+] 반환 값: " + retval)
			
			var new_retval = ptr("0x1")
			retval.replace(new_retval)
			console.log("[+] 변조 시킨 반환 값 : " + new_retval)
		}
	})
}
  • 반환 값 0x1 로 수정

  • Login Method 1 터치

Login Method 2

  1. 로그인 시도

  • ID / Password 미입력 시 오류 메세지

  • ID / Password 미일치 시 오류 메세지
  1. Ghidra
  • 오류 메세지인 Incorrect Username or Password 검색 후 세번째 참조값 더블클릭

  • 그래프 창에서 분기문 조회 : 1001bded4 → 0x1bded4 (메모리 16진수 표기)
  1. 코드 작성 후 프리다 실행
// RuntimeManipuation2.js

//(1) 실 주소 확인 후 변조
var realBase = Module.findBaseAddress('DVIA-v2')
console.log("[+] ASLR로 바뀐 바이너리 실제 메모리 주소 : " + realBase)

var jailBreak_address = realBase.add('0x1bded4')
console.log("[+] 분기점 실제 주소 : " + jailBreak_address)


//(2) 반환 값 변조 
Interceptor.attach(jailBreak_address,{
	onEnter:function(args){
		console.log("[+] 변조 전 반환 값 : ")
		console.log(JSON.stringify(this.context))
		this.context.x8 = 0x1
		console.log("[+] 변조 후 반환 값 : ")
		console.log(JSON.stringify(this.context))
	}
})

  • x8 값 0x1 로 수정


Login Method 3_1

  1. 코드 입력 시도

  • 2222 입력 후 Validate code 터치 시 에러 메세지 Error 2222: Incorrect Code
  1. Ghidra
  • Incorrect Code 검색 후 참조값 더블클릭 후 이동한 행에서 참조값 더블클릭

  • 그래프창에서 분기 반대편 Congratulation 앞에 8848 4자리 번호가 평문으로 노출되어 있다.

Login Method 3_2

  1. Ghidra

  • 어셈블리 언어에서 cmp 명령어는 두 피연산자의 값을 차를 계산하여 두 개의 값을 비교한다.

A-1. x8 에는 0x2290 값을 고정으로 가지고, x9 에는 사용자 입력 값 local_28 을 가진다.

  • // 16 진수인 0x2290 을 10 진수로 변환하면 8848 이 나온다.

A-2. 주소 확인

  • cmp x9,x8 가 10015e3e0 에 위치한다.

A-3. Brute force 실행

// RuntimeManipuation3.js

var realBase = Module.findBaseAddress('DVIA-v2')
//console.log("[+] 앱 실제 메모리 주소 : " + realBase)

var runtime_address = realBase.add('0x15e3e0')
//console.log("[+] 분기점 실제 주소 : " + runtime_address)

// [+] 네 자릿수 맞춰주는 함수 정의
function padToFour(number){
	if(number<=9999){
		number = ("000" + number).slice(-4) // slice로 4자리 맞춰주면 됨
		return String(number)  // 위에서 "000"이 스트링으로 묶였는데 혹시 몰라 한번 더 형 변환을 해준다.
	}
}

Interceptor.attach(runtime_address,{
	onEnter:function(args){
		console.log("")
		console.log("[+] x8, x9 값 : ")
		console.log(JSON.stringify(this.context))
		console.log("x8 값 :" + this.context.x8)
		console.log("x9 값 :" + this.context.x9)
		
		// [+] 비교가 가능하도록 16진수 x8 값을 정수형(10진수)로 변환한다.
		var hex_pin = parseInt(this.context.x8, 16) // 데이터 형식 주의! 여기선 정수(Int)형으로 반환된다.
		hex_pin = String(hex_pin)  // padToFour 함수가 스트링 타입이기에 여기도 동일하게 형 변환시켜 줘야한다.

        // [+] Brute Force 반복문
     	for(var i=0;i<10000;i++){
			console.log("[+] Brute force attack : " + padToFour(i))
			if(hex_pin == padToFour(i)){
				this.context.x9 = padToFour(i)
                console.log("new x8 값 :" + this.context.x8)
				console.log("new x9 값 :" + this.context.x9)
				console.log("x8의 정수 코드는 : " + hex_pin)
				break
			}
		}
	}
})
  • x9 에 0000 부터 순서대로 대입

  • Brute Force 로 크랙 성공

B-1. x8 과 x9 에 같은 값을 넣어 준다.

B-2. 비교 값들에 동일한 값을 대입

// RuntimeManipuation3_2.js

var realBase = Module.findBaseAddress('DVIA-v2')
//console.log("[+] 앱 실제 메모리 주소 : " + realBase)

var runtime_address = realBase.add('0x15e3e0')
//console.log("[+] 분기점 실제 주소 : " + runtime_address)

Interceptor.attach(runtime_address,{
	onEnter:function(args){
		console.log("")
		console.log("x8 값 :" + this.context.x8)
		console.log("x9 값 :" + this.context.x9)
		
		this.context.x8 = 0x1
		this.context.x9 = 0x1

		// x9 를 x8 에 담아줘도 된다.
		
		console.log("new x8 값 :" + this.context.x8)
		console.log("new x9 값 :" + this.context.x9)
	}
})
  • x8 과 x9 에 같은 값인 0x1 (10진수로 1) 을 대입한다.



출처
https://takudaddy.tistory.com/600

profile
IT 보안, 관심 있는 것을 공부합니다.

0개의 댓글

관련 채용 정보