Jailbreak Detection

justugi·2024년 7월 7일
0

DVIA

목록 보기
2/11

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

Jailbreak Detection 방법

1. 파일 기반 체크 (File-based Checks)

: 탈옥되지 않은 기기에서는 존재할 수 없는 파일 또는 디렉터리 존재여부로 탈옥 여부를 판단하는 방법

  • 파일기반 탈옥 탐지 체크리스트의 파일 또는 디렉터리가 존재하는지 확인하고, 존재한다면 탈옥된 기기라고 판단한다.

2. 파일 권한 기반 체크 (Checking File Peremissions)

: 앱 샌드박스 외부의 위치에 파일 생성을 시도하는 것으로 탈옥 여부를 판단하는 방법

  • 탈옥된 기기가 아니라면 앱이 샌드박스 외부에 파일을 생성하는 것은 불가능함을 이용한다.
  • /private 디렉터리에 파일을 생성하도록 하여 성공적으로 생성된다면 디바이스가 탈옥된 것으로 판단한다.

3. 프로토콜 핸들러 기반 체크 (Checking Protocol Handlers)

: 프로토콜 핸들러 사용여부를 기반으로 탈옥 여부를 판단하는 방법

  • 프로토콜 핸들러란 특별한 URL을 처리하는 프로그램으로 "cydia://설치할 패키지 이름" 과 같이 사용할 수 있다.
  • 탈옥된 기기에 거의 모두 설치되어 있는 cydia 앱을 이용한 프로토콜 핸들러가 가능할 경우 탈옥된 기기라 판단한다.

4. 시스템 API 호출 기반 체크 (Calling System APIs)

: 시스템 API를 호출하는 것으로 탈옥 여부를 판단하는 방법

5. OpenSSH 서비스 기반 체크 (OpenSSH Service Detection)

:OpenSSH 서비스가 동작중인지를 확인하는 것으로 탈옥 여부를 판단하는 방법

  • 탈옥되지 않은 기기에서는 OpenSSH 서비스를 실행할 수 없음을 이용한다.
  • SSH 연결 시간이 초과될때까지 기다려야하므로 이 탐지 기법은 매우 느릴 수 있다.
  • OpenSSH 서비스용 포트를 변경하여 해당 탐지기법을 쉽게 우회할 수 있으므로 추천되지 않는다.

현재 탈옥된 기기 (Dopamine)

  • 3uTools 에선 Jailbroken 에 Yes 라고 뜨나,

  • Dopamine 을 통한 rootless Jailbreak 을 완료했으며, Dopamine 이 탈옥 탐지 우회가 기본적으로 적용되어있어서 모든 Test들에서 탈옥되지 않았다고 뜬다.
  • DVIA 는 주로 파일 기반 검사, 디렉토리 권한 확인, Cydia 앱 존재 여부 등의 방법을 사용하여 탈옥을 탐지한다.

이하 Test 들의 탐지 우회에서 탈옥되었다고 변경하겠다.


Jailbreak Detection Bypass

: 탈옥 탐지 우회는 두 단계로 나눠서 진행

  1. Ghidra 로 탈옥 탐지 로직 파악

  2. 파악된 로직을 Ghidra 또는 Frida 를 이용하여 탈옥 탐지 기능 우회


Test 1

  1. 바이너리 파일 추출
  • /var/mobile/Containers/Data/Application/$uuid/DVIA-v2.app 경로의 파일 크기가 가장 큰 DVIA-v2 파일(바이너리 파일)을 컴퓨터로 복사
  1. Ghidra 프로젝트 생성
  • Ghidra - File - New Project - Non-Shared Project - Next - Project Directory, Project Name - Finish
  1. 바이너리 파일 열기
  • File - Import File - DVIA-v2 파일 Select File To Import - 설정 그대로 OK - OK
  • DVIA-v2 더블클릭 - Yes - 설정 그대로 Analyze
  1. 바이너리 파일 분석

  • Search - For Strings - Filter 에 Jailbreak Test1 결과 문구 중 일부인 Jailbroken 입력 - 원하는 행 더블클릭 - 검색창을 닫거나 내림

  • XREF[1]: __T07DVIA_v213DVIAUtilitiesC9sho... 더블클릭

  • 더블클릭 시 음영처리된 행 선택 - Window - Function Graph - 노란색 부분 확대

  • 1001cc17c 더블클릭 시 해당위치로 이동

  • 레지스터 w0 의 값이 0x0 일 때와 아닐 때의 결과가 달라진다.

    • 1001cc17c : 탈옥되지 않은 기기 일 때 실행
    • 1001cbdd4 : 탈옥된 기기 일 때 실행

  • Function Graph 에서 분기 명령문 클릭 - Listing 창에서 해당 명령문 위치로 커서 이동됨 - 분기 명령문의 주소값 (1001cbdd0) 확인
  1. 코드 작성 및 설명
/* (1) 사전 준비
 (1-1) DVIA-v2 바이너리가 메모리에 올라갔을때 실제 할당된 주소를 변수(realBase)에 담는다
var realBase = Module.findBaseAddress('DVIA-v2')  <-- 실제 바이너리 이름 또는 프로세스 이름

 (1-2) 주소 출력하여 확인
console.log(realBase) 

 (1-3) 주소값을 더한다
var Jailbreak_address = realBase.add('0x1cbdd0') 

 (2) 변조 시도 (interceptor - 반환값 또는 특정 무언가를 변조시 타겟 선언하여 사용)
Interceptor.attach(Jailbreak_address, {     target 설정은 첫 번째 인자, 다음으로 콜백 지정
  onEnter:function(args){      콜백은 onEnter:function(args) <-- 기본 구조, onLeave:(반환값 변조시 사용) 여기서는 사용 안함
     console.log(this.context)   context는 할당된 레지스터 값을 받는다 
    console.log(JSON.stringify(this.context))   JSON 형태로 출력 - 앱 실행 시 레지스터 값 확인 가능
 }
}) */

-------------------------------------

// jailBreak_test1.js

var realBase = Module.findBaseAddress('DVIA-v2')
console.log(realBase)

var jailBreak_address = realBase.add('0x1cbdd0')
console.log(jailBreak_address)

Interceptor.attach(jailBreak_address, {
	onEnter:function(args){
		console.log(JSON.stringify(this.context))
	}
})
  1. 아이폰 pc 연결 후 프리다 실행
  • 아나콘다 프롬프트에서 파이썬 환경 활성화

  • frida -U -l [코드 파일 경로][프리다 코드를 적용할 실행 중인 앱] 명령어 실행 (아이폰에서 DVIA 를 실행중이며, 화면도 켜놓은 상태여야 함)

0x104a18000 : DVIA-v2 바이너리가 실제 할당된 주소
0x104be3dd0 : DVIA-v2 바이너리 내의 변조할 주소

  • 아이폰에서 Jailbreak Test 1 터치 시 레지스터 값이 출력된다.
  • x0 : 0x0 → x0 레지스터 값이 0 이다. 여기서의 x0 레지스터가 Grida 에서의 w0 레지스터이다.
  1. 코드 추가 작성 및 프리다 실행
// jailBreak_test1.js

var realBase = Module.findBaseAddress('DVIA-v2')
console.log(realBase)

var jailBreak_address = realBase.add('0x1cbdd0')
console.log(jailBreak_address)

Interceptor.attach(jailBreak_address, {
	onEnter:function(args){
		console.log(JSON.stringify(this.context))
     // 아래부터 추가
     // 레지스터 값 변조 (레지스터 받을 때는 this.context)
        this.context.x0 = 0x1   // 현재 코드 블럭내 레지스터 값은 x0 : 0x0 인데 이를 강제 변경
        console.log(JSON.stringify(this.context)) // 출력
     	}
})
  • x0 값을 0x0 에서 0x1 으로 변조

  • x0 레지스터의 값이 0x1 로 변조되었으며, Jailbreak Test 1 터치 시 탈옥되었다고 뜰 것이다.


Test 2

  1. 프리다로 DVIA 의 프로세스 아이디 (PID), 앱 이름 (번들 ID), 식별자 확인

  • 4353 / DVIA-v2 / com.highaltitudehacks.DVIAswiftv2.DJT9Y4JM75
  1. 클래스 출력 코드 작성
// jailBreak_test2.js

if(ObjC.available){     // 해당 코드가 실행 가능한 환경이라면,
	for(var classname in ObjC.classes) // ObjC.classes > 메모리에 올라와 있는 오브젝트 맵핑 클래스를 가져온다.
		console.log(classname) //가져온 클래스의 이름을 출력
}

3, 프리다로 파일 로드 후 클래스 조회

frida -U -l "js 파일 경로" DVIA-v2 > classes.txt

  • DVIA 의 클래스 명을 classes.txt 로 저장

  • 탈옥 관련 클래스라고 추측되는 JailbreakDetection 클래스 존재 확인
  1. 클래스의 메소드 출력 코드 작성 후 프리다 실행
// jailBreak_test2_2.js

if(ObjC.available){
	var classname = "JailbreakDetection" //분석하고자 하는 클래스 이름을 지정
	var methods = ObjC.classes[classname].$ownMethods //클래스가 가지고 있는 기본 메소드를 배열 형식으로 가져온다
	console.log(methods) //가져온 메소드정보 출력
}

  • isJailbroken 메소드 출력
  • 는 클래스에 대한 메소드, - 는 인스턴스에 대한 메소드
  1. 메소드 반환값 출력 코드 작성 후 프리다 실행
// jailBreak_test2_3.js

if(ObjC.available){
	var classname = "JailbreakDetection"
	var methodname = "isJailbroken" // 메소드 이름을 변수에 저장
	var hook = ObjC.classes[classname][methodname] // 클래스명과, 메소드명을 배열형식으로 넣어준다.
    
	Interceptor.attach(hook.implementation,{ // 탈취하기위해 준비, implementation : 해당 메소드를 실행한다.
    	onLeave:function(retval){ // 반환값을 확인하기 위해 사용.
			console.log("[*] Class Name : " + classname) // 클래스명 출력
			console.log("[*] Method Name : " + methodname) // 메소드명 출력
			console.log("[*] Type of return value : " + hook.returnType) // 반환대는 값의 형식을 출력한다.
			console.log("[*] Return Value : " + retval) // 반환값을 출력한다.
		}
	})
}

  • 반환값 0x0 를 0x1 로 바꾸면 탈옥 탐지를 성공할 것이다.
  1. 메소드 반환값 변조 코드 작성 후 프리다 실행
// jailBreak_test2_4.js

if(ObjC.available){
	var classname = "JailbreakDetection"
	var methodname = "isJailbroken"
	var hook = ObjC.classes[classname][methodname]
    
	Interceptor.attach(hook.implementation,{
    	onLeave:function(retval){
			console.log("[*] Class Name : " + classname)
			console.log("[*] Method Name : " + methodname)
			console.log("[*] Type of return value : " + hook.returnType)
			console.log("[*] Return Value : " + retval)

			var new_retval = ptr("0x1") // 변조하고자 하는 값을 변수에 저장
			retval.replace(new_retval) // 변수에 저장한 값으로 반환값을 변조
			console.log("[*] New Return Value : " + retval) // 변조된 반환값을 출력
		}
	})
}

  • 반환값이 0x1 로 변조되었으며, Jailbreak Test 2 터치 시 탈옥되었다고 뜰 것이다.


Test 3

  1. Test 1 의 Grida 세팅에서 조회
  • search - For Strings - 탈옥 탐지됐을 때 나왔을 문구인 Device is Jailbroken, the application will now exit 검색 - 조회할 행 더블클릭

  • Listing 창 - XREF[1]: __T07DVIA_v232JailbreakDetection... 더블클릭 - 음영표시된 칸 선택 - Window - Function Graph - 노란색 부분 확대

  • w8 의 값이 0x0 일 때 / 아닐 때 로 나뉘어져 결과가 달라진다.
    • (0x0 일 때) 100195da8 : 탈옥되지 않은 기기일 때 실행되는 로직
    • (0x0 아닐 때) 1001959e0 : 탈옥된 기기를 사용할 때 실행되는 로직
  1. 분기점 확인

  • 분기점이 되는 곳의 오프셋을 알기 위해 w8, #0x0 행을 클릭 - 음영표시된 행의 분기점 오프셋 : 1001959dc
  1. 코드 작성 후 프리다 실행
// jailBreak_test3.js

var realbase_address = Module.findBaseAddress('DVIA-v2') // DVIA-v2 바이너리가 실행되어 메모리에 올라갔을때 할당된 주소를 realbase_address 에 저장
console.log('realbase address : ' + realbase_address) // realbase_address에 저장된 주소를 화면에 출력

var jailbreak_address = realbase_address.add('0x1959dc') // realbase_address에 분기점 오프셋을 더하면 실제 분기점 메모리 주소가 jailbreak_address 에 저장됨
console.log('jailbreak address : ' + jailbreak_address) // jailbreak_address에 저장된 주소를 화면에 출력

Interceptor.attach(jailbreak_address, { // jailbreak_address에서 호출되는 값을 가로채기 위해 준비
	onEnter: function(args){ // 호출되는 레지스터 값을 받아옴
		console.log(JSON.stringify(this.context)) // 받아온 레지스터 값을 JSON 형태로 화면에 출력
	}
})

  • Jailbreak Test 3 터치 - x8 의 값이 0x0 이다. → 탈옥이 탐지되지 않았을 때 100195da8 실행
  1. 분기 명령문 수정
  • w8, #0x0, 0x100195da8 우클릭 - Patch Instruction - 0x0 값을 0x1 로 수정 ( 조건문의 w8 의 값 #0x0 을 #0x1 로 수정하여 조건문이 반대가 되도록 만든다. )

  • File - Export Program - Format : Binary (Raw Bytes) - OK

  • 파일 명의 확장자를 삭제하여 DVIA-v2 로 수정 후 아이폰의 DVIA-v2 파일 교체

  • DVIA 앱 재실행 후 Jailbreak Test 3 터치 시 탈옥되었다고 뜰 것이다.


Test 4, 5 : Test 1, 3 과 동일한 방법으로 가능


대응방안

  • 디버깅 방지

    • 예방 (Preventive) 기술 : 디버거가 앱에 연결되는 것을 방지
    • 반응 (Reactive) 기술 : 디버거의 존재를 확인하고 앱을 종료
  • 디버깅 탐지

    • ptrace 사용 : 프로세스 디버거 연결 방지 (예방 기술)
    • sysctl 사용 : 연결된 디버거 탐지 (반응 기술)
    • 프리다 아티팩트 (Artefacts) 탐지

출처
https://hagsig.tistory.com/148
https://cybersecurity.asee.io/blog/what-is-jailbreaking/
https://takudaddy.tistory.com/592
https://takudaddy.tistory.com/594
https://takudaddy.tistory.com/595

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

0개의 댓글

관련 채용 정보