Written by reset + s0ngsari 최근 많은 연구들이 Windows 운영체제에 초점이 맞추어져 있지만, 보안적인 측면에서 아이폰과 맥북에 탑재되는 iOS와 macOS를 빼놓을 수 없다. 이번 블로그 시리즈를 통해서 OS X 커널에서의 버그 분석 및 익스플로잇 기법 등을 알아본다.
(1) 커널 버그 찾기 BSD, Mach와 IOKit 등 과 같은 커널 레벨에서 실행 가능한 버그를 퍼징, 소스코드 오디팅과 같은 방법을 통해 발견함. BSD : 커널의 BSD 부분은 대부분의 시스템 호출, 네트워킹 및 파일 시스템 기능을 제공함. FreeBSD 5에서 가져온 소스. Mach : Carnegie Mellon University에서 개발 된 Mach 3.0 마이크로 커널에서 파생되어짐. 메모리 맵 및 IPC 와 같은 기본 서비스를 구현함. 사용자 공간 프로그램은 마하 트랩을 통해 마하 서비스에 액세스 가능. IOKit : IOKit은 XNU용 드라이버를 작성하는 C++로 작성된 프레임워크이며, Apple은 libkern이라는 자체 런타임 시스템을 제공함. (2) Exploit Primitive(s) Arbitrary Read / Write를 이용해 취약점을 공략하는데에 있어서 필요한 데이터를 획득 하거나, 커널 영역에 임의의 데이터를 작성함. 이는 버그 별로 상이한 데이터이기 때문에, Read / Write 로 공격시 이용할 수 있는 데이터를 사용해야함. (3) 커널 권한 획득 & AAR / AAW in Kernel kernel_task(pid=0)의 권한을 위해 필요한 값 ipc object와 kernel task를 획득하기 위해 커널에 존재하는 모든 프로세스를 트레버싱 한 후 유저 영역에 데이터를 덤프 한다. 이를 이용해, 커널 레벨에서 Read / Write를 할 수 있다. (4) 루트 권한 획득 각각의 프로세스가 커널 메모리에 적재되어 있기 때문에, 타겟 프로세스를 잡아서 아래의 프로세스 권한 구조체의 CR_RUID(Credential Real UID)를 0으로 변경 [bsd/sys/ucred.h] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /* * In-kernel credential structure. * * Note that this structure should not be used outside the kernel, nor should * it or copies of it be exported outside. */ struct ucred { TAILQ_ENTRY ( ucred ) cr_link ; /* never modify this without KAUTH_CRED_HASH_LOCK */ u_long cr_ref ; /* reference count */ struct posix_cred { /* * The credential hash depends on everything from this point on * (see kauth_cred_get_hashkey) */ uid_t cr_uid ; /* effective user id */ uid_t cr_ruid ; /* real user id */ uid_t cr_svuid ; /* saved user id */ short cr_ngroups ; /* number of groups in advisory list */ gid_t cr_groups [ NGROUPS ]; /* advisory group list */ gid_t cr_rgid ; /* real group id */ gid_t cr_svgid ; /* saved group id */ uid_t cr_gmuid ; /* UID for group membership purposes */ int cr_flags ; /* flags on credential */ } cr_posix ; struct label * cr_label ; /* MAC label */ /* * NOTE: If anything else (besides the flags) * added after the label, you must change * kauth_cred_find(). */ struct au_session cr_audit ; /* user auditing data */ };
변경이 완료되면, 해당 프로세스는 root 권한으로 돌아가는 상태가 되어짐. 따라서, system(“/bin/bash”); 를 실행해 준다면 루트 권한의 쉘을 획득할 수 있음. (Local Privilege Escalation)
배경 지식 Kernel Zone OS X 의 커널에서는 힙이 할당되는 Zone이라는 구조를 사용하고 있음. Zone은 zalloc(zone), kalloc(size)를 이용해 할당되어지며, zfree(zone, ptr), kfree(ptr,size)를 이용해 해제 되어짐. kalloc 호출시, zalloc이 내부 호출 됨. 또한 kalloc zone은 sudo zprint kalloc
를 통해 확인 가능함. zone metadata : 페이지 첫번째에 들어가있는 zone의 정보로 size, page_count, alloc_element, free_element 등을 가지고 있다. OOL(Out-Of-Line) Port IPC 통신에서 발생하는 인라인이 아닌 패킷을 적재 OOL 데이터를 수신하기 전까지 커널에서 보존되어짐. 주로 OS X Kernel Exploit을 할 때, fakeport를 만들기 위해 OOL을 Leak 시킴으로써 공격을 함 따라서, OOL Leak을 완화시키기 위한 보안 패치가 자주 이루어짐.
OS X Kernel Mitigation kASLR 부팅에 따른 커널 메모리 주소 랜덤화 Kext(Kernel Extension)와 커널은 같은 슬라이드를 공유함 우회 : kslide 주소 계산 (kslide = kernel_base - kernel text base) kslide : 바이너리 상의 주소와 실제 주소의 차이 DEP SMEP / SMAP 인텔 CPU에서 제공하는 커널 메모리 보호 기법 SMEP(Supervisor Mode Execution Protection) : 유저 영역 주소 공간에서 커널 코드 실행 불가 SMAP(Supervisor Mode Access Protection) : 유저 영역 주소 공간에서 메모리 액세스를 허용하지 않음. 단, 지원되는 CPU 아키텍처에서만 사용 가능 우회 : 커널에서 우회 가능한 ROP 시행 vm_map_copy() 변화 OS X 10.11 El Capitan 이전의 커널 익스플로잇은, 오버플로우 취약점을 이용해 vm_map_copy의 kdata 포인터 및 size를 공략하여 임의 데이터 읽기를 시도했으나, 이는 구조가 변경됨으로써 보완 되었음. (osfmk/vm/vm_map.h) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // 변경 전 struct vm_map_copy { int type ; #define VM_MAP_COPY_ENTRY_LIST 1 #define VM_MAP_COPY_OBJECT 2 #define VMMAP_COPY_KERNEL_BUFFER 3 vm_object_offset_t offset ; vm_map_size_t size ; union { struct vm_map_header hdr ; vm_object_t object ; struct { // <<= Before Change void * kdata ; vm_size_t kalloc_size ; } c_k ; } c_u ; }; // 변경 후 struct vm_map_copy { int type ; #define VM_MAP_COPY_ENTRY_LIST 1 #define VM_MAP_COPY_OBJECT 2 #define VM_MAP_COPY_KERNEL_BUFFER 3 vm_object_offset_t offset ; vm_map_size_t size ; union { struct vm_map_header hdr ; vm_object_t object ; uint8_t kdata [ 0 ]; // <<= Changed } }
단, OS X 10.11 El capitan의 ipc_kmsg_copyout_ool_descriptor()에서 레이스 컨디션 기법을 이용해 우회한 사례가 있음. (현재 구조 패치 되었음.)
기타 iOS와 macOS의 구조 및 보안에 대한 패치가 상당히 비슷하므로, 보통 함께 공략 가능. 완벽한 오버플로우 버그가 아니라면 공격하기 까다로움. 많은 버그들이 리모트 공격으로부터 도달하기 어려워짐. (e.g., 사파리 취약점을 넘어서 커널 권한 획득 까지 가는데 있어서 도달 과정) 이전 버전의 OS X에서는 널 포인터에 데이터를 작성함으로써, 상대적으로 간단하게 LPE가 가능하였으나 (아래 소스 참조), 현재는 불가한 상태임. 1 2 3 4 5 6 7 8 9 10 11 12 void null_page (){ sync (); vm_address_t addr = 0 ; vm_deallocate ( mach_task_self (), 0x0 , 0x1000 ); vm_allocate ( mach_task_self (), & addr , 0x1000 , 0 ); uint64_t * np = 0 ; for ( int i = 1 ; i < 0x100 ; i ++ ) { np [ i ] = 0x4141414141414141 ; } }
iOS 9.2, macOS 10.11 이후부터 재 할당되는 메모리 위치를 쉽게 예측할 수 없음. (freelist randomization) iOS 10, macOS 10.12 의 버전에서 애플이 vm_map_size(vm_map_copy)를 변경하여 힙 공격하는 것도 보안 패치 됨.
KERNEL DEBUGGING Introduction 커널 크래쉬가 나면, OS가 멈추기때문에 하나의 로컬에서는 디버깅을 하지 못하고 VM으로 kdp를 사용하여 디버깅을 해야한다.때문에 하나이상의 VM은 무조건 설치해야 한다. OS X에서 ‘Parallels Desktop’을 사용 한다면 복구파티션을 이용해 OSX VM을 설치 할 수 있다. 원하는 OSX 버전이 있다면 이미지파일 혹은 VM을 검색을 통해 설치하는 방식으로 하면 된다.
Host에서 디버깅을 하기위해 여러가지 환경 구성을 해야하는데, 우선 Kernel Debug Kit 을 다운로드 해야한다. Kernel Debug Kit은 LLDB 혹은 GDB로 어떠한 커널을 디버깅할때 기본적으로 없는 심볼을 로드해 디버깅 할 수 있게 해준다. 커널 바이너리를 직접 분석해 1day를 구경하고싶다면, OSX 버전 업데이트없이 Kernel Debug Kit을 이용하여 바이너리를 분석하면 된다.
Host Setting https://developer.apple.com/download/more/?=Kernel Debug Kit
각 버전별로 공유되고있어, 분석하고있는 1-day의 버전에 맞춰 다운로드 받으면 된다. 다운로드한 dmg파일을 실행하여 설치하면 /Library/Developer/KDKs/ 경로에 디버그 킷이 존재한다.
OSX에서 실행되는 커널 바이너리는 /System/Library/Kernels/kernel 에 존재한다. 해당 바이너리를 디버거에 붙혀도 되지만 위 처럼 킷을 설치하는 환경구성은 Host와 Guest의 OSX버전이 달라도 커널디버깅을 할 수 있게 한다.
이제 Host에서 LLDB만 조금 손봐주면 Host의 환경구성은 끝난다.
LLDB에 바이너리를 붙혀 로드하게되면 위와 같은 에러메세지를 볼 수 있다. 해당 에러는 아래와 같이 쉽게 해결 가능하다.
( lldb) command script import "/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py" songsangjun-ui-MacBook-Pro:~ s0ngsari$ echo "settings set target.load-script-from-symbol-file true" > ~/.lldbinit
Host와 Guest 모두 System Integrity Protection(SIP)를 disable 해야한다.
Host에서의 환경 구성은 모두 끝났고, 이제 Guest의 환경만 구성하면 커널을 디버깅 할 수 있게된다.
Guest Setting OSX는 boot-args라는것을 nvram을 통해 건드릴 수 있다.
$ nvram boot-args
boot-args는 부팅될 때 설정한 값대로 OS에 적용된다. 하지만 우리가 해당 인자를 사용하는이유는 디버깅에 필요한 Interrupt와 Logging을 위한것이다. boot-args에도 인자가 많지만 우리는 debug라는것을 먼저 설정 할 것이다. 아래 차트를 보고 설정해주면 된다.
커널 디버깅을 할때에는 debug옵션의 인자를 0x144를 준다. DB_NMI플래그를 주게되면 NMI 를 사용하여 디버거가 디버기에 붙을수 있게끔 해준다. 옵션을 줄때는 아래와 같이 설정해 주면 된다.
$ sudo nvram boot-args= "debug=0x144 -v"
DB_LOG_PI_SCRN DB_ARP DB_NMI Boot Verbose mode $ sudo reboot
이후 boot-args가 설정되고, NMI 인터럽트를 발생시켜 debugger가 debuggee의 커널을 디버깅 할 수 있게 된다.
가끔 debuggee에서 NMI를 줘도 debugger에서 디버깅이 안될때가 있는데, 그때는 debugger에서 arp 테이블을 추가해줘야 한다.
$ arp -s
Host와 Guest모두 설정이 끝났으니 디버깅을 하면 된다.
Attach to debugger 해당 버전에 맞는 1day의 PoC를 예제 삼아 디버깅을 할것이다. 글에서 예제로 쓰이는 1day는 CVE-2017-2370 이다.
$ vi test.c $ clang -o test test.c
Guest에서 PoC를 컴파일 해주고 NMI를 발생시키면 된다 NMI는 Command + Alt + Control + Shift + Esc 로 발생 시킬수 있다. NMI를 발생시키면 OS가 멈추는게 정상이니 안심해도 된다.
디버거에서는 kdp-remote라는것을 사용하여 원격디버깅을 하면 되는데, 처음에 다운로드 받은 KDK의 kernel바이너리를 열어 주면된다.
songsangjun-ui-MacBook-Pro:~ s0ngsari$ lldb /Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel ( lldb) target create "/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel" Loading kernel debugging from /Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py LLDB version lldb-350.0.21.9 settings set target.process.python-os-plugin-path "/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/core/operating_system.py" settings set target.trap-handler-names hndl_allintrs hndl_alltraps trap_from_kernel hndl_double_fault hndl_machine_check _fleh_prefabt _ExceptionVectorsBase _ExceptionVectorsTable _fleh_undef _fleh_dataabt _fleh_irq _fleh_decirq _fleh_fiq_generic _fleh_dec command script import "/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/xnu.py" xnu debug macros loaded successfully. Run showlldbtypesummaries to enable type summaries. Current executable set to '/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel' ( x86_64) . ( lldb)
에러 없이 잘 열렸으면 kdp-remote 커맨드를 사용해서 디버기에 연결하면 된다.
( lldb) kdp-remote Version: Darwin Kernel Version 16.1.0: Wed Oct 19 20:31:56 PDT 2016; root:xnu-3789.21.4~4/RELEASE_X86_64; UUID = 75CA1C4D-7BF4-321B-B544-D8F1B6D60EF8; stext = 0xffffff8014200000 Kernel UUID: 75CA1C4D-7BF4-321B-B544-D8F1B6D60EF8 Load Address: 0xffffff8014200000 Kernel slid 0x14000000 in memory. Loaded kernel file /Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel Loading 94 kext modules warning: Can't find binary/dSYM for com.apple.kec.corecrypto (809FEC94-017C-307A-B099-A01EFF5485FB) .warning: Can' t find binary/dSYM for com.apple.kec.pthread ( 36567317-B854-3157-ABF3-CEAD0A3770BB) .warning: Can't find binary/dSYM for com.apple.kec.Libm (51D82C5F-0248-334D-ADC6-5861BBB83C97) .warning: Can' t find binary/dSYM for com.apple.iokit.IOACPIFamily ( 4F7FB6AD-2498-3F71-827C-ED7AA4BF2511) .Target arch : x86_64 Instantiating threads completely from saved state in memory. .warning: Can't find binary/dSYM for com.apple.driver.AppleACPIPlatform (249D7BA8-3FD5-3207-A482-0605CB898037) .warning: Can' t find binary/dSYM for com.apple.driver.AppleFDEKeyStore ( EA5D0966-E8EA-337A-98EB-195806E8F723) .warning: Can't find binary/dSYM for com.apple.iokit.IOReportFamily (B14DC3D3-7250-3DA3-BF50-C666EBEDAF4C) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.driver.DiskImages ( 05A729EF-20B8-3254-8F13-42DF42E0544B) .warning: Can't find binary/dSYM for com.apple.driver.AppleBusPowerController (DB526B45-1A45-3A81-A0C1-57F826CADEDF) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.driver.KernelRelayHost ( 3B58E6F0-DE92-3289-9D3B-3BF12208585F) .warning: Can't find binary/dSYM for com.apple.driver.AppleCredentialManager (54677B39-44B3-3AAA-BBEC-D78D0B5CC1A7) .warning: Can' t find binary/dSYM for com.apple.driver.AppleMobileFileIntegrity ( 0EFA4D2C-2271-3C43-B777-17D05716144A) .warning: Can't find binary/dSYM for com.apple.driver.AppleKeyStore (75515493-6D25-39F7-8F0B-B08B505CAB74) .warning: Can' t find binary/dSYM for com.apple.security.TMSafetyNet ( 1CB512A3-24BD-344A-BFB4-44A61F27AB03) .warning: Can't find binary/dSYM for com.apple.kext.AppleMatch (3B280DAB-903F-33DC-8110-525A1154B11E) .warning: Can' t find binary/dSYM for com.apple.security.sandbox ( 32039FC4-CA9B-3B74-B326-A2BF5CFE45E1) .warning: Can't find binary/dSYM for com.apple.security.quarantine (EC92F0F9-694E-3E22-8B2C-4A071D20C6BA) .warning: Can' t find binary/dSYM for com.apple.nke.applicationfirewall ( 2A0DC0EF-655C-3D4B-93FD-3AED72BEBBDC) .warning: Can't find binary/dSYM for com.apple.driver.AppleAPIC (BC2E6D01-BCBB-3525-BF38-BF99C3F1EC46) .warning: Can' t find binary/dSYM for com.apple.driver.AppleSMBIOS ( 9BB02681-4B47-3592-AD62-71FB0BF56965) .warning: Can't find binary/dSYM for com.apple.driver.AppleRTC (3FD1BCF4-8AFC-3CE6-A36E-26410544AD14) .warning: Can' t find binary/dSYM for com.apple.iokit.IOSMBusFamily ( 185F0EBF-0262-3370-BD47-8FE4C8AA726E) .warning: Can't find binary/dSYM for com.apple.driver.AppleACPIEC (BC227AE1-3CD5-3938-9C8C-009F1A966FBE) .warning: Can' t find binary/dSYM for com.apple.driver.AppleHPET ( 2CFB49B8-4CC2-320B-9C6E-99646DFD8571) .Target arch : x86_64 Instantiating threads completely from saved state in memory. .warning: Can't find binary/dSYM for com.apple.driver.AppleACPIButtons (4D5E51D6-8A6B-3B6A-A8F2-472D56C9D0C3) .warning: Can' t find binary/dSYM for com.apple.driver.AppleSmartBatteryManager ( 31670664-0EF0-39B5-A13F-15B8F9EC1283) .warning: Can't find binary/dSYM for com.apple.driver.AppleEFIRuntime (6B7A5B9A-C313-3F7F-B6E2-60EE54593BC8) .warning: Can' t find binary/dSYM for com.apple.driver.AppleEFINVRAM ( 6F4404D6-8625-35CA-AEB6-6ECD7B64FA52) .Target arch : x86_64 Instantiating threads completely from saved state in memory. .warning: Can't find binary/dSYM for com.apple.driver.usb.AppleUSBHostPacketFilter (9888F9CD-B7EE-3A9D-8530-6FA4C167B26C) .warning: Can' t find binary/dSYM for com.apple.driver.usb.AppleUSBEHCI ( BF6EF9A2-F090-3094-B3FA-F34351D946CF) .warning: Can't find binary/dSYM for com.apple.driver.usb.AppleUSBUHCI (4EF43593-FC11-31E6-8B27-E7A6B5703C15) .warning: Can' t find binary/dSYM for com.apple.driver.usb.AppleUSBUHCIPCI ( 4EC90565-DB48-3190-8608-1F6DA30B8691) .warning: Can't find binary/dSYM for com.apple.driver.usb.AppleUSBXHCI (E5F9850E-A1A1-305F-854D-48B46C08B2EC) .warning: Can' t find binary/dSYM for com.apple.driver.usb.AppleUSBXHCIPCI ( B4287428-23D9-3547-93B5-2FEB73A02EA6) .warning: Can't find binary/dSYM for com.apple.driver.usb.AppleUSBEHCIPCI (4FCE62CA-0477-34A2-9564-86F807CDBD4D) .warning: Can' t find binary/dSYM for com.apple.iokit.IOATAFamily ( BC25A382-3DA0-33C7-93C5-E8A823B50F98) .warning: Can't find binary/dSYM for com.apple.driver.AppleIntelPIIXATA (BDC5E432-B04E-3ACF-A213-672128140381) .warning: Can' t find binary/dSYM for com.apple.iokit.IOAHCIFamily ( 5C275B66-A173-3D92-853A-44FC35D45FFC) .warning: Can't find binary/dSYM for com.apple.driver.AppleAHCIPort (BE72151C-73BE-35B7-8C31-74F49E4C5E98) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.driver.AppleIntel8254XEthernet ( 34B30414-098D-3D22-AAB5-1A754D0647C6) .warning: Can't find binary/dSYM for com.apple.iokit.IOAHCIBlockStorage (C449634B-8121-3BFB-972D-966847C4321F) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.iokit.IOAHCISerialATAPI ( 681FA1E2-E3DE-3FEB-ACA7-16FC2B9078A6) .warning: Can't find binary/dSYM for com.apple.filesystems.hfs.encodings.kext (68A8D6C1-CDCA-371C-970B-325BF2E7ECAB) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .Target arch: x86_64 Instantiating threads completely from saved state in memory. .Target arch: x86_64 Instantiating threads completely from saved state in memory. .Target arch: x86_64 Instantiating threads completely from saved state in memory. .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.filesystems.hfs.kext ( 6C6C4A98-1534-3C52-B006-00FBC479233E) .warning: Can't find binary/dSYM for com.apple.BootCache (C38789F4-9226-303C-99BE-3B8EAF8EC5C2) .warning: Can' t find binary/dSYM for com.apple.AppleFSCompression.AppleFSCompressionTypeZlib ( 9B32DDE9-151F-31A1-90E9-3CEB2C7BE27C) .warning: Can't find binary/dSYM for com.apple.AppleFSCompression.AppleFSCompressionTypeDataless (C6F882D7-C35C-3963-A2FA-10033FF40107) .warning: Can' t find binary/dSYM for com.apple.driver.usb.AppleUSBHostCompositeDevice ( 30502C8D-F4B2-345F-B8F0-F8C54CAD7F46) .warning: Can't find binary/dSYM for com.apple.driver.usb.networking (74394A72-1E87-363E-8CFD-182BD8C9362E) .warning: Can' t find binary/dSYM for com.apple.driver.usb.AppleUSBHub ( F7BC6869-E4BA-3291-B7EA-BF28A0ABEF4A) .warning: Can't find binary/dSYM for com.apple.driver.usb.IOUSBHostHIDDevice (0548123A-013B-3C74-86A8-33DF73E9CBBB) .warning: Can' t find binary/dSYM for com.apple.driver.AppleHIDKeyboard ( 664B787F-6DE5-3211-9081-E434055A550B) .Target arch : x86_64 Instantiating threads completely from saved state in memory. .warning: Can't find binary/dSYM for com.parallels.kext.video (5520E5F4-AC7C-9446-6088-5D8CAF25478D) .warning: Can' t find binary/dSYM for com.parallels.driver.AppleIntelAC97Controller ( 705C3A56-06CE-E995-5A75-618C5EF3D45D) .warning: Can't find binary/dSYM for com.apple.vecLib.kext (C0ABF85C-CA30-3F02-9E1E-06F3BA5047A8) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.iokit.IOSlowAdaptiveClockingFamily ( F026208D-CC0C-3599-B303-9196904A584E) .warning: Can't find binary/dSYM for com.apple.driver.AppleIntelSlowAdaptiveClocking (6FE984DD-A1FE-309E-83CF-B346989A6F17) .warning: Can' t find binary/dSYM for com.apple.driver.IOPlatformPluginFamily ( 087648A2-8A44-3095-AEC7-44A872A46205) .warning: Can't find binary/dSYM for com.apple.driver.IOPlatformPluginLegacy (9156271B-C61E-3B40-B5B6-102369F12A8B) .warning: Can' t find binary/dSYM for com.apple.driver.AppleSMC ( 969D80B2-E714-3145-95B0-F61627E0EE4D) .warning: Can't find binary/dSYM for com.apple.driver.ACPI_SMC_PlatformPlugin (7224B682-B40F-3A4A-BCA0-82727D251ECB) .warning: Can' t find binary/dSYM for com.parallels.kext.tg ( 09C02F97-D104-80F1-2A96-6BEF8A2F6967) .warning: Can't find binary/dSYM for com.apple.driver.AppleSMBusController (4DAA381E-3690-3E94-8025-DFB34F714094) .warning: Can' t find binary/dSYM for com.apple.driver.AppleMCCSControl ( 102DD5D9-2DD5-3BCB-B5C0-BE08E1049CD6) .warning: Can't find binary/dSYM for com.apple.driver.AppleUpstreamUserClient (F39509A4-191C-35DA-B7D9-08F95E5AB8BC) .warning: Can' t find binary/dSYM for com.apple.driver.AppleHV ( 39AC9B9B-7B20-322F-82F0-044B3CC08D43) .warning: Can't find binary/dSYM for com.apple.driver.AppleSSE (907BB577-46DF-3C86-9034-758B61AD054D) .warning: Can' t find binary/dSYM for com.apple.Dont_Steal_Mac_OS_X ( B97F871A-44FD-3EA4-BC46-8FD682118C79) .warning: Can't find binary/dSYM for com.apple.iokit.IOBluetoothFamily (794ACDDD-2B46-3BF0-94E9-4FD7C109A427) .Target arch: x86_64 Instantiating threads completely from saved state in memory. .warning: Can' t find binary/dSYM for com.apple.iokit.IOBluetoothSerialManager ( 6F68B8CF-6543-328E-AF57-DD250412CF02) .warning: Can't find binary/dSYM for com.apple.iokit.IOSurface (D3B2D208-487C-3166-9F7D-D6159AABC428) .warning: Can' t find binary/dSYM for com.apple.iokit.IOUserEthernet ( 5EE448BD-95EC-35AD-B7FC-A1237E4BB346) .warning: Can't find binary/dSYM for com.apple.driver.pmtelemetry (F46D019B-17FF-3CD5-A093-0894B81C1404) .warning: Can' t find binary/dSYM for com.parallels.driver.AppleIntelAC97Audio ( F8F3B21C-958B-BB10-E13C-42CA34BF6815) .warning: Can't find binary/dSYM for com.apple.driver.AppleOSXWatchdog (757A8B72-2A1A-32BA-99EC-6D802DE6E91F) .warning: Can' t find binary/dSYM for com.apple.kext.triggers ( 4E564246-8804-3673-B440-606AD360A3BB) .warning: Can't find binary/dSYM for com.apple.filesystems.autofs (AA36D92F-D92B-3102-BAE3-F86A0A298143) .warning: Can' t find binary/dSYM for com.apple.filesystems.smbfs ( 42EF3BC8-5041-3E94-BC74-9D5906694E3A) .warning: Can't find binary/dSYM for com.apple.driver.usb.cdc (6CB80B6B-9071-38ED-9A4B-635ABF20A429) .Target arch: x86_64 Instantiating threads completely from saved state in memory. done. Target arch: x86_64 Instantiating threads completely from saved state in memory. kernel was compiled with optimization - stepping may behave oddly; variables may not be available. Process 1 stopped * thread #2: tid = 0x16cc, 0xffffff801440bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513, name = ' 0xffffff801c791028', queue = ' 0x0', stop reason = signal SIGSTOP frame #0: 0xffffff801440bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513 [opt] (lldb)
제대로 커널이 잡혔다면 디버기의 프로세스를 Resuming해주고 PoC를 실행시켜주면 디버거에서 크래쉬를 확인 할 수 있다.
( lldb) c Process 1 resuming ( lldb) Unloading 1 kext modules . done . Process 1 stopped * thread #4: tid = 0x1af6, 0xffffff8014751a8c kernel`fp_lookup(p=0xffffff801ebec780, fd=1, resultfp=0xffffff806eb6bf20, locked=0) + 92 at kern_descrip.c:3879, name = '0xffffff801c09a9a8', queue = '0x0', stop reason = EXC_BAD_INSTRUCTION (code=13, subcode=0x0) frame #0: 0xffffff8014751a8c kernel`fp_lookup(p=0xffffff801ebec780, fd=1, resultfp=0xffffff806eb6bf20, locked=0) + 92 at kern_descrip.c:3879 [opt] ( lldb) register read General Purpose Registers: rax = 0x4141414141414141 rbx = 0x0000000000000001 rcx = 0x0000000000000001 rdx = 0xffffff8020d0e800 rdi = 0xffffff801ebec848 rsi = 0x0000000000000001 rbp = 0xffffff806eb6bef0 rsp = 0xffffff806eb6bec0 r8 = 0x0000000000000000 r9 = 0x00007fffda6afa50 r10 = 0x000000000000000a r11 = 0x0000000000000246 r12 = 0xffffff801ebec780 r13 = 0xffffff801ec3e4f8 r14 = 0x0000000000000000 r15 = 0xffffff806eb6bf20 rip = 0xffffff8014751a8c kernel` fp_lookup + 92 at kern_descrip.c:3879 rflags = 0x0000000000010246 cs = 0x0000000000000008 fs = 0x0000000000000000 gs = 0x0000000000000000 ( lldb)
LLDB는 GDB와 커맨드가 비슷하지도 않아서 따로 배워두는게 좋다. 혹은 kgmacros라는 스크립트를 사용해서 gdb로 디버깅을 하는것도 나쁘지않다.
Logging the Heap PoC를 실행하고 브레이크포인트를 걸어도 힙을 일일히 트레이싱하는것은 힘들다. 하지만 위에서 다룬 boot-args를 통해 힙을 트레이싱 할 수가 있다. 이는 OSX heap에서 다루는 zone을 트레이싱하는것이다.
$ sudo nvram boot-args= "debug=0x144 -v -zc zlog1=kalloc.128 zlog2=kalloc.256"
위 커맨드와같이 -zc zlog1=zone 을 주고 재부팅을하면 끝난다. 중요한것은 해당 PoC가 어떤 zone을 사용하는지를 알아야한다. 모든 kalloc을 트레이싱하는것이 아니라, kalloc에 있는 여러 zone중에 우리가 선택한 zone을 트레이싱해주기때문에 편하게 트레이싱을 하고싶다면 사용하는 zone 하나만 boot-args 인자로 넘겨주면 된다.
( lldb) bt * thread #2: tid = 0x0cb5, 0xffffff801200bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513, name = '0xffffff8019752980', queue = '0x0', stop reason = signal SIGSTOP * frame #0: 0xffffff801200bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513 [opt] frame #1: 0xffffff801200bb4e kernel`Debugger(message=) + 910 at model_dep.c:1025 [opt] frame #2: 0xffffff8011ef368c kernel`panic(str="\"a freed zone element has been modified in zone %s: expected %p but found %p, bits changed %p, at offset %d of %d in element %p, cookies %p %p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/zalloc.c:651") + 236 at debug.c:458 [opt] frame #3: 0xffffff8011f3f5c0 kernel`backup_ptr_mismatch_panic [inlined] zone_element_was_modified_panic(offset=0) + 800 at zalloc.c:642 [opt] frame #4: 0xffffff8011f3f559 kernel`backup_ptr_mismatch_panic(zone=, element=, primary=4702111234474983745, backup=) + 697 at zalloc.c:710 [opt] frame #5: 0xffffff8011f3e739 kernel`try_alloc_from_zone(zone=, check_poison=) + 521 at zalloc.c:832 [opt] frame #6: 0xffffff8011f3d174 kernel`zalloc_internal(zone=, canblock=1, nopagewait=0) + 484 at zalloc.c:2284 [opt] frame #7: 0xffffff8011f84580 kernel`vm_map_copyin_internal + 51 at vm_map.c:9428 [opt] frame #8: 0xffffff8011f8454d kernel`vm_map_copyin_internal(src_map=, src_addr=140351705630208, len=3240, flags=, copy_result=) + 253 at vm_map.c:10279 [opt] frame #9: 0xffffff8011ed7629 kernel`ipc_kmsg_copyin_ool_descriptor [inlined] vm_map_copyin_common(src_map=, src_destroy=, copy_result=0xffffff8071adbe40, use_maxprot=0) + 201 at vm_map.c:10187 [opt] frame #10: 0xffffff8011ed7616 kernel`ipc_kmsg_copyin_ool_descriptor(dsc=0xffffff8018874c98, user_dsc=, is_64bit=, paddr=, copy=0xffffff8071adbe40, space_needed=, map=, mr=) + 182 at ipc_kmsg.c:2701 [opt] frame #11: 0xffffff8011ed7c25 kernel`ipc_kmsg_copyin_body(kmsg=0xffffff8018874c00, space=0xffffff8018925b40, map=0xffffff801c0e9e08) + 613 at ipc_kmsg.c:3035 [opt] frame #12: 0xffffff8011ee992f kernel`mach_msg_overwrite_trap(args=) + 287 at mach_msg.c:548 [opt] frame #13: 0xffffff8011ff26ae kernel`mach_call_munger64(state=0xffffff8018dd12c0) + 430 at bsd_i386.c:562 [opt] frame #14: 0xffffff8011ea5f66 kernel`hndl_mach_scall64 + 22
( lldb) bt * thread #2: tid = 0x13ab, 0xffffff8015c0bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513, name = '0xffffff80200f4288', queue = '0x0', stop reason = signal SIGSTOP * frame #0: 0xffffff8015c0bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513 [opt] frame #1: 0xffffff8015c0bb4e kernel`Debugger(message=) + 910 at model_dep.c:1025 [opt] frame #2: 0xffffff8015af368c kernel`panic(str="\"Invalid queue element linkage for %p: next %p next->prev %p prev %p prev->next %p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/queue.h:245") + 236 at debug.c:458 [opt] frame #3: 0xffffff8015bec040 kernel`pmap_enter_options [inlined] __QUEUE_ELT_VALIDATE + 81 at queue.h:244 [opt] frame #4: 0xffffff8015bebfef kernel`pmap_enter_options [inlined] insque at queue.h:347 [opt] frame #5: 0xffffff8015bebfef kernel`pmap_enter_options [inlined] pv_hash_add + 32 at pmap_internal.h:544 [opt] frame #6: 0xffffff8015bebfcf kernel`pmap_enter_options(pmap=, vaddr=, pn=, prot=, fault_type=, flags=, wired=, options=, arg=) + 5103 at pmap_x86_common.c:926 [opt] frame #7: 0xffffff8015b6fb41 kernel`vm_fault_enter(m=0xffffff801c1c3c00, pmap=, vaddr=140736734584832, prot=, caller_prot=, wired=0, change_wiring=, no_cache=0, cs_bypass=, user_tag=1962753648, pmap_options=, need_retry=, type_of_fault=) + 4481 at vm_fault.c:3292 [opt] frame #8: 0xffffff8015b71405 kernel`vm_fault_internal(map=, vaddr=, caller_prot=, change_wiring=0, interruptible=2, caller_pmap=0x0000000000000000, caller_pmap_addr=0, physpage_p=) + 4421 at vm_fault.c:4086 [opt] frame #9: 0xffffff8015c069fc kernel`user_trap [inlined] vm_fault(map=, vaddr=, fault_type=, change_wiring=0, interruptible=2, caller_pmap=, caller_pmap_addr=0) + 652 at vm_fault.c:3397 [opt] frame #10: 0xffffff8015c069d8 kernel`user_trap(saved_state=0xffffff801ff11060) + 616 at trap.c:1120 [opt] frame #11: 0xffffff8015aa5655 kernel`hndl_alltraps + 229
Call stack을 확인했을때 두개의 차이점이 확실하게 보인다. zlog을 적용한 call stack은 zalloc으로 할당되는것을 볼 수 있지만 적용하지 않은것은 할당되는것들이 보이지않는다. 이렇게 Heap Corruption을 다루는 1day가 있을때 zone 개념을 파악하고 zlog을 사용한다면 더 확실하게 디버깅 할 수 있는 장점이 있어 참고해두면 유용하게 사용 할 수 있다.
ETC 버그에 대한 이해도 중요하지만 디버깅 또한 중요하다. 간단하게 디버깅을 하여 여러가지 커맨드를 사용해볼것이다.
( lldb) bt * thread #2: tid = 0x1650, 0xffffff801200bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513, name = '0xffffff801a0eee18', queue = '0x0', stop reason = signal SIGSTOP * frame #0: 0xffffff801200bb4e kernel`Debugger [inlined] hw_atomic_sub(delt=1) at locks.c:1513 [opt] frame #1: 0xffffff801200bb4e kernel`Debugger(message=) + 910 at model_dep.c:1025 [opt] frame #2: 0xffffff8011ef368c kernel`panic(str="\"a freed zone element has been modified in zone %s: expected %p but found %p, bits changed %p, at offset %d of %d in element %p, cookies %p %p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/zalloc.c:651") + 236 at debug.c:458 [opt] frame #3: 0xffffff8011f3f5c0 kernel`backup_ptr_mismatch_panic [inlined] zone_element_was_modified_panic(offset=0) + 800 at zalloc.c:642 [opt] frame #4: 0xffffff8011f3f559 kernel`backup_ptr_mismatch_panic(zone=, element=, primary=4702111234474983745, backup=) + 697 at zalloc.c:710 [opt] frame #5: 0xffffff8011f3e739 kernel`try_alloc_from_zone(zone=, check_poison=) + 521 at zalloc.c:832 [opt] frame #6: 0xffffff8011f3d174 kernel`zalloc_internal(zone=, canblock=1, nopagewait=0) + 484 at zalloc.c:2284 [opt] frame #7: 0xffffff8011ed5248 kernel`ipc_kmsg_alloc(msg_and_trailer_size=4352) + 248 at ipc_kmsg.c:929 [opt] frame #8: 0xffffff8011ef832d kernel`ipc_kobject_server(request=, option=) + 141 at ipc_kobject.c:299 [opt] frame #9: 0xffffff8011ed5f61 kernel`ipc_kmsg_send(kmsg=, option=, send_timeout=) + 225 at ipc_kmsg.c:1826 [opt] frame #10: 0xffffff8011ee9957 kernel`mach_msg_overwrite_trap(args=) + 327 at mach_msg.c:556 [opt] frame #11: 0xffffff8011ff26ae kernel`mach_call_munger64(state=0xffffff8019fed920) + 430 at bsd_i386.c:562 [opt] frame #12: 0xffffff8011ea5f66 kernel`hndl_mach_scall64 + 22
bt 명령어는 BackTrace 약자로, 현재 커널이 어느위치에 있는지 프레임단위로 보여준다. 각 프레임들을 선택 할 수 있고, 우리가 원하는 프레임으로 뛰어 로컬 변수들을 확인 할 수도 있다.
( lldb) frame select 5 frame #5: 0xffffff8011f3e739 kernel`try_alloc_from_zone(zone=, check_poison=) + 521 at zalloc.c:832 [opt]
frame select 라는 명령으로 프레임 넘버를 선택해주면 그 frame으로 현재위치가 잡히고, rip또한 아래와 같이 그 프레임대로 잡히게 된다.
( lldb) register read General Purpose Registers: rbx = 0xffffff801f977000 rbp = 0xffffff8872cabc50 rsp = 0xffffff8872cabc10 r12 = 0x7e415085550ee3c7 r13 = 0x4141414141414141 r14 = 0xffffff8017cd70a0 r15 = 0x4141414141414141 rip = 0xffffff8011f3e739 kernel` try_alloc_from_zone + 521 at zalloc.c:832
rip가 우리가 선택한 frame대로 잡혀있는것을 확인 할 수 있고, 해당 함수에서의 로컬변수값을 볼 수 있다.
( lldb) frame var ( zone_t) zone = ( boolean_t * ) check_poison = ( zone_page_metadata * ) page_meta = 0xffffff8017cd70a0 ( vm_offset_t) element = 18446743524483756032 ( vm_offset_t * ) primary = 0xffffff801f977000 ( vm_offset_t) next_element_primary = 4702111234474983745 ( vm_offset_t) next_element = 9097641255853024199 ( vm_offset_t) next_element_backup = 4702111234474983745 ( vm_offset_t * ) backup =
OSX에서는 Page 맨 처음부분에 Meta data라는것이 존재하는데, 힙청크의 메타데이터와 같이 그 zone의 여러가지 정보들이 들어 있다.
iOS 10의 경우 메타데이터는 아래와 같다:
zindex: zone_array안에 있는 존의 index page_count : 페이지의 할당 사이즈 free_count : 페이지의 free element갯수 freelist_offset : 페이지의 처음 free element의 주소 우리가 여기서 봐야할 것은 Element라는 변수인데, 무엇인지 한번 확인해보겠다.
( lldb) memory read 0xffffff801f977000 0xffffff801f977000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 0xffffff801f977010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
PoC가 제대로 트리거되었다면 Element에는 A가 잔뜩 채워져있는것이 정상이다. zone에 할당된 엘리먼트에 memset으로 A를 채워넣었기때문에 위와같은 결과가 나오게된다.
이런식으로 PoC를 트리거 한 후, 원하는 프레임이 있다면 해당 프레임을 선택하고 로컬변수를 확인하는 식으로 디버깅을 진행하면 된다. 프레임에 관련된 커맨드는 종종 유용하게 쓰이니 알아두면 좋다.
맥에서 돌아가는 task들의 베이스주소를 확인이 가능한데, 우리가 볼 것은 커널이다. 커널의 task이름은 kernel_task인데, 커맨드로 해당 주소를 출력해볼것이다.
( lldb) showalltasks task vm_map ipc_space #acts flags pid process io_policy wq_state command 0xffffff80185b3aa0 0xffffff8014d1e6e8 0xffffff80180ab800 134 0 0xffffff80126ba360 -1 -1 -1 kernel_task 0xffffff80185b3000 0xffffff8018db0838 0xffffff80180ab840 6 1 0xffffff8018d81128 -1 -1 -1 launchd 0xffffff801961c000 0xffffff8019603268 0xffffff80195c2740 4 D 34 0xffffff8018d80cb0 -1 -1 -1 UserEventAgent 0xffffff801961caa0 0xffffff8019603838 0xffffff80195c2980 2 D 36 0xffffff8018d80838 TQ -1 -1 -1 uninstalld 0xffffff8019634aa0 0xffffff8019603458 0xffffff80195c29c0 2 D 37 0xffffff8018d81e90 -1 -1 -1 kextd 0xffffff8019634550 0xffffff8019602ba0 0xffffff80195c2700 10 D 38 0xffffff8018d82308 -1 -1 -1 fseventsd 0xffffff8018e67550 0xffffff8019602aa8 0xffffff80195c2680 10 D 44 0xffffff8018d7fad0 -1 -1 -1 configd 0xffffff801965baa0 0xffffff80196026c8 0xffffff80195c2a00 3 D 45 0xffffff8018d834e8 -1 -1 -1 powerd 0xffffff8018ee2000 0xffffff80196029b0 0xffffff80195c2a40 4 D 50 0xffffff8018d846c8 -1 -1 -1 logd ...
이렇게 task, vm_map, ipc_space 각각 할당된 주소를 확인할 수 있고, 해당 task의 객체들 또한 확인이 가능하다. 원하는 task의 process주소를 복사해서 아래와 같이 하면된다.
( lldb) showtaskvme 0xffffff80185b3aa0 vm_map entries for task 0xffffff80185b3aa0 task vm_map ipc_space #acts flags 0xffffff80185b3aa0 0xffffff8014d1e6e8 0xffffff80180ab800 134 vm_map pmap size #ents rsize start:end 0xffffff8014d1e6e8 0xffffff8012688f88 0x00000008f838a000 731 70200 0xffffff7f80000000:0xffffffffffffe000 entry start:end #pgs tag.kmod prot&flags object offset 0xffffff8014d28750 0xffffff7f80000000:0xffffff7f92600000 75264 0 00 0x0000000000000000 0x0 0xffffff8014d287a0 0xffffff7f92600000:0xffffff8000000000 449024 6 37s G_KEXT_MAP 0xffffff7f92600000 0xffffff8018d40640 0xffffff8000000000:0xffffff8012751000 75601 0 00 0x0000000000000000 0x80000000 0xffffff8018d40a50 0xffffff8012751000:0xffffff8012879000 296 0 37 0xffffff8018d93d00 0x0 0xffffff8018d40960 0xffffff8012879000:0xffffff8016ac4000 16971 0 00 0x0000000000000000 0x92879000 ... 0xffffff8014d28700 0xffffff8016b99000:0xffffff8017c1b000 4226 10 37 KERNEL_OBJECT 0xffffff8016b99000 0xffffff8014d286b0 0xffffff8017c1b000:0xffffff8047c1b000 196608 12 37s ZONE_MAP 0xffffff8017c1b000 0xffffff8014d28570 0xffffff8047c1b000:0xffffff804bc1b000 16384 0 37s KALLOC_MAP 0xffffff8047c1b000 0xffffff8014d287f0 0xffffff804bc1b000:0xffffff804bc42000 39 18 37 0xffffff801809b600 0x0 0xffffff8014d284d0 0xffffff804bc42000:0xffffff804bd5c000 282 18 37 0xffffff801809b700 0x0 0xffffff8014d28840 0xffffff804bd5c000:0xffffff804bd5d000 1 18 37 0xffffff801809b800 0x0 0xffffff8014d28890 0xffffff804bd5d000:0xffffff804bd84000 39 18 37 0xffffff801809b500 0x0 0xffffff8014d28480 0xffffff804bd84000:0xffffff804be9e000 282 18 37 0xffffff801809b400 0x0 0xffffff8014d28430 0xffffff804be9e000:0xffffff804be9f000 1 18 37 0xffffff801809b900 0x0 0xffffff8014d28520 0xffffff804be9f000:0xffffff804bedf000 64 0 00 KERNEL_OBJECT 0xffffff804be9f000 0xffffff8014d288e0 0xffffff804bedf000:0xffffff804bef1000 18 19 37 0xffffff801809ba00 0x0 0xffffff8014d28930 0xffffff804bef1000:0xffffff804bef5000 4 18 37 0xffffff801809bb00 0x0 0xffffff8014d28980 0xffffff804bef5000:0xffffff804befa000 5 1 37 0xffffff801809b300 0x0 0xffffff8014d289d0 0xffffff804befa000:0xffffff804bf00000 6 17 37 KERNEL_OBJECT 0xffffff804befa000 0xffffff8014d28a20 0xffffff804bf00000:0xffffff804bf01000 1 27 37 0xffffff801809bc00 0x0 0xffffff8014d283e0 0xffffff804bf01000:0xffffff804bf02000 1 27 37 0xffffff801809bd00 0x0 0xffffff8014d28a70 0xffffff804bf02000:0xffffff804c002000 256 7 37s IPC_KERNEL_MAP 0xffffff804bf02000 0xffffff8014d28b10 0xffffff804c002000:0xffffff804c802000 2048 7 37s IPC_KERNEL_COPY_MAP 0xffffff804c002000
커널 오브젝트도 존재하고, Zone이 맵핑된 주소등 다양한 정보들을 볼 수 있다. 원하는 개체를 확인하고 싶을때 위 커맨드를 사용해서 확인하면 된다. 그리고 간단하게 짚고 넘어가야하는것이 있는데 OSX를 공부하면 알게되는 zprint 커맨드이다. zprint는 OSX에서 할당되는 모든 Zone을 출력해주는데, 맥 터미널에서는 기본으로 제공해준다. 하지만 맥 커맨드로 zprint를 하면 주소는 나오지 않고 무슨 zone이 존재하는지만 보여준다. 그렇지만 디버거가 커널을 잡았을때는 다르다. LLDB에서도 zprint 커맨드를 제공해주는데 결과는 아래와 같다.
( lldb) zprint ZONE TOT_SZ PAGE_COUNT ALLOC_ELTS FREE_ELTS FREE_SZ ALL_FREE_PGS ELT_SZ ALLOC( ELTS PGS WASTE) FLAGS NAME ... 0xffffff801266a0e0 393216 96 22614 1962 31392 0 16 4096 256 1 CX kalloc.16 0xffffff801266a200 1134592 277 20951 14505 464160 1 32 4096 128 1 CX kalloc.32 0xffffff801266a320 836400 205 16259 1166 55968 1 48 4096 85 1 CX kalloc.48 0xffffff801266a440 1585152 387 24594 174 11136 0 64 4096 64 1 CX kalloc.64 0xffffff801266a560 477360 117 5320 647 51760 0 80 4096 51 1 CX kalloc.80 0xffffff801266a680 367200 90 3710 115 11040 0 96 8192 85 2 CX kalloc.96 0xffffff801266a7a0 2203648 538 17016 200 25600 1 128 4096 32 1 CX kalloc.128 0xffffff801266a8c0 236640 58 1264 215 34400 0 160 8192 51 2 CX kalloc.160 0xffffff801266a9e0 270336 66 1353 55 10560 0 192 12288 64 3 CX kalloc.192 0xffffff801266ab00 512000 125 1960 40 10240 0 256 4096 16 1 CX kalloc.256 0xffffff801266ac20 265824 65 902 21 6048 0 288 20480 71 5 CX kalloc.288 0xffffff801266ad40 1282048 313 2420 84 43008 1 512 4096 8 1 CX kalloc.512 0xffffff801266ae60 28224 7 20 29 16704 2 576 4096 7 1 CX kalloc.576 0xffffff801266af80 847872 207 780 48 49152 9 1024 4096 4 1 CX kalloc.1024 0xffffff801266b0a0 32256 8 18 10 11520 0 1152 8192 7 2 CX kalloc.1152 0xffffff801266b1c0 40960 10 17 15 19200 0 1280 20480 16 5 CX kalloc.1280 0xffffff801266b2e0 1568768 383 750 16 32768 3 2048 4096 2 1 CX kalloc.2048 0xffffff801266b400 6479872 1582 314 1268 5193728 1268 4096 4096 1 1 CX kalloc.4096 0xffffff801266b520 1949696 476 84 154 1261568 306 8192 8192 1 2 CX kalloc.8192 ...
터미널에서 제공해주는 zprint와는 다르게 LLDB에선 페이지의 메타데이터(주소, 엘리먼트 갯수 등등) 들이 전부 출력된다.
LLDB에는 수많은 커맨드들이 있기 때문에, tab기능을 이용하여 확인하면 원하는 커맨드를 사용할 수 있으니 참고하길 바란다.
다음 시리즈에서는 공개된 버그와 보안 패치를 바탕으로 exploit을 작성해보도록 할 예정이다.