보안개구리
[DVIA-v2 실습] 2. Jailbreak Detection - test1 본문
[개요]
Jailbreak Detection란 탈옥된 기기 탐지로 기기를 탈옥할 경우 운영체제의 기본 보안 메커니즘을 우회하고 앱의 보안기능을 우회하여 정상적인 앱의 동작을 보장하지 못하기 때문에 탈옥된 기기에 대하여 탐지 로직이 존재하며 탈옥된 기기의 경우 앱의 이용에 있어 제한이 존재합니다. 진단자의 입장에서는 이러한 탈옥 검증 로직을 우회해야 되는데 이번 실습에서는 탈옥 탐지를 우회하는 실습을 진행하도록 하겠습니다.
[진단]
1) Jailbreak Detection Test1을 클릭합니다. 클릭하면 "Device is Jailbroken"이라는 메시지가 출력됩니다. 이번 실습에서는 이 메시지가 출력될 때 탈옥 검증 로직이 작동한다고 가정하고, "Device is Not Jailbroken" 메시지가 출력되면 탈옥 검증 로직을 우회한 것으로 간주하겠습니다.
(참고로 탈옥 후 Cydia가 아닌 Sileo가 설치된 상황에서 접속하면 "Device is Not Jailbroken"이라는 메시지가 출력되는데 아마 Cyida 설치 여부를 통해 "Device is Jailbroken" 라는 메시지를 출력하는 것 같습니다. /Applications/ 경로에 Cydia.app 생성 후 접속 시 "Device is Jailbroken"라는 메시지가 정상적으로 출력됩니다.)
2) Ghidra에서 "Device is Jailbroken" 문자열을 검색하여, 해당 문자열이 있는 위치로 이동합니다.
3) 이동 시 해당 문자열이 참조되는 곳이 나오는데 해당 부분을 더블클릭하여 이동합니다.
4) Device is Jailbroken라는 문자열이 보입니다. 보기 편하게 하기 위해 기드라 옵션 중 Windows > Function Graph를 클릭하여 그래프화 하여 확인해 보도록 하겠습니다.
5) 빨간 테두리 안에 부분을 먼저 살펴보겟습니다.
tbz: 지정된 레지스터의 특정 비트를 검사하여 그 비트가 0일 경우 분기
w0: tbz가 지정한 레지스터 대상
#0x0: 테스트할 비트의 번호
LAB_1001cc17c: 분기할 주소(레이블)
-> 요약하자면 tbz라는 명령어를 통해 w0 레지스터의 0번 비트를 검사하여 해당 비트가 0일 경우 1001cc17c 분기점으로 이동하라 정도로 해석하면 됩니다. 초록색 선이 비트가 0일 경우 분기점이고 빨간색 선이 0이 아닐 경우 분기입니다.
6) 아래 두 사진은 분기점을 보여줍니다. 왼쪽의 1001cbdd4는 0이 아닐 경우 탈옥된 기기로 인식되는 분기점이고, 오른쪽의 1001cc17c는 0일 경우 기기가 탈옥되지 않았다고 출력하는 분기점입니다.
7) 프리다를 통해 후킹 하기 앞서 먼저 한 가지를 확인해야 하는데 바로 앱에 대한 ASLR 여부입니다.
ASLR이란 스택, 힙, 라이브러리 등의 주소를 랜덤한 영역에 배치하여 메모리 손상 취약점 등의 공격을 예방할 수 있는 기술인데 이로 인해 프로그램의 모듈의 매번 임의의 메모리 주소에 로드되도록 합니다. 즉 실행 때마다 베이스 주소가 달라지는데 따라서 후킹이나 메모리 패치 시 고정된 주소가 아닌 베이스 주소를 찾아 그 주소를 기반으로 원하는 함수나 데이터에 접근해야 합니다.
8) 아래처럼 /var/containers/Bundle/Application/6EBDA404-0428-4E05-A391-2A6EA65E3778/DVIA-v2.app 해당 디렉터리로 이동해 준 후 otool을 명령어를 실행합니다. otool은 iOS에서 사용되는 바이너리 분석 도구로 여기서 봐야 할 점은 PIE부분입니다. PIE가 존재한다는 것은 ASLR을 지원한다는 것입니다. 즉 DVIA앱은 ASLR이 있음을 알 수 있습니다.
명령어: otool -Vh DVIA-v2
9) 이제 Frida 도구를 사용해 후킹을 시도해 보겠습니다. Module.findBaseAddress는 Frida 내장 함수로, 지정된 모듈의 베이스 주소를 찾는 역할을 합니다. 분기점의 시작 주소는 5번 과정에서 그래프의 마지막 부분을 클릭한 후 우클릭하여 Instruction Info를 선택하면 찾을 수 있습니다.
let Base_address = Module.findBaseAddress('DVIA-v2')
10) 앞에서 획득한 주소가 베이스 주소, 그러고 시작 주소가 오프셋 주소로 두 주소값을 더하면 절대 주소가 나옵니다. 즉 오프셋 주소를 사용해 베이스 주소에 더함으로써 프로그램 실행 중 실제로 사용할 수 있는 절대 주소를 계산하는 프리다 후킹을 위해선 해당 주소가 필요합니다. 이렇게 스크립트를 작성 후 실행하면 절대주소가 출력됨을 알 수 있습니다.
let Base_address = Module.findBaseAddress('DVIA-v2')
let Hooking_address = Base_address.add('0x1cbdd0')
console.log(Hooking_address)
11) 위에서 획득한 절대주소값을 통해 후킹을 시도합니다. Interceptor.attach는 특정 메모리 주소에 후킹을 설정하는 함수로 여기서는 절대주소가 해당합니다. onEnter를 통해 this.context 즉 CPU 컨텍스트 정보를 JSON문자열로 출력해 보여줍니다. 스크립트를 실행한 후 DVIA 앱에 접속하여 Jailbreak Test1을 다시 한번 클릭해 줍니다.
let Base_address = Module.findBaseAddress('DVIA-v2')
let Hooking_address = Base_address.add('0x1cbdd0')
Interceptor.attach(Hooking_address, {
onEnter: function(args){
console.log(JSON.stringify(this.context))
}
})
12) 여기서 중요한 부분은 아래 표시된 부분입니다. sp는 스택의 현재 위치를 가리키는 포인터이고, x0의 값은 이전에 검사했던 레지스터 w0의 값과 동일합니다. 즉, 현재 w0 레지스터의 값은 1비트입니다. 6번 과정에서 설명한 대로, 0비트가 아닐 경우 탈옥된 기기라는 메시지가 출력되므로, 이 값을 0으로 변경하는 것이 목표입니다.
13) this.context.x0 = 0x0을 통해 값을 0비트로 변경을 해서 전의 값과 변경 후의 값을 출력하여 비교해 보겠습니다. 변경 전에는 x0의 값이 0x1이었으나 변경 후 0x0으로 정상적으로 변경됐음을 확인하였습니다.
let Base_address = Module.findBaseAddress('DVIA-v2')
let Hooking_address = Base_address.add('0x1cbdd0')
Interceptor.attach(Hooking_address, {
onEnter: function(args){
console.log(JSON.stringify(this.context))
this.context.x0 = 0x0;
console.log(*************************************************************)
console.log(JSON.stringify(this.context))
}
})
14) 앱 역시 "Device is Not Jailbroken" 메시지를 출력하는 것을 보아 탈옥 검증 로직을 우회했음을 알 수 있습니다.
'앱 진단(iOS) > DVIA 실습' 카테고리의 다른 글
[DVIA-v2 실습] 1. Local Data Storage - Couchbase Lite (0) | 2024.08.16 |
---|---|
[DVIA-v2 실습] 1. Local Data Storage - Core Data (0) | 2024.08.16 |
[DVIA-v2 실습] 1. Local Data Storage - Keychain (0) | 2024.08.16 |
[DVIA-v2 실습] 1. Local Data Storage - UserDefault (0) | 2024.08.16 |
[DVIA-v2 실습] 1. Local Data Storage - Plist (0) | 2024.08.16 |