y0u_bat
macOS Kernel Debugging Guide 본문
macOS Kernel Debugging Guide
이문서에서는 10.10.5 OS X에서 lldb를 이용하여 커널 디버깅하는 기초적인 내용에 대해서 다룹니다.
우선 맥 커널 디버깅을 하기 위해서는 Kernel 버전이 동일한 macOS 가상머신이 두개 있어야합니다.
커널 버전에 맞는 KDK 를 두 가상머신에 전부다 깔아줍니다.
설치하고 나면, /Library/Developer/KDKs/*.kdk/System/Kernels/kernel.development 가 있을텐데, 이것을 /System/Library/Kernels/ 에 복사해줍니다. 복사해주면 부팅할때 development kernel로 부팅 할 수 있습니다.
sudo cp /Library/Developer/KDKs/KDK_*.kdk/System/Library/Kernels/kernel.development /Systems/Library/Kernels
NVRAM boot-args
업데이트
nvram 은 전원이 꺼져 있을때 정보를 유지하는 메모리입니다. 부팅할때 시스템에서 nvram에 있는 boot-args 을 검사하여 부팅 합니다.
macOS kernel debug 하기 위해서 boot-args를 설정 해야됩니다.
sudo nvram boot-args="debug=0x141 kext-dev-mode=1 kcsuffix=development pmuflags=1 -v"
debug=0x141
는 디버그 모드 활성화 시키고 부팅할때 원격 디버거 연결을 기다립니다.(DB_HALT | DB_ARP | DB_LOG_PI_SCRN)
옵션을 사용하고 있습니다.
kext-dev-mode=1
는 서명되지 않은 kext를 로드 할 수 있습니다.kcsuffix=development
는 시스템에 복사한 development kernel로 부팅 할 수 있게 해줍니다.pmuflags=1
는 watchdog timer를 비활성화 해줍니다.-v
는 디버깅할때 유용한 kernel verbose 모드를 활성화 시킵니다.
kext cache 무효화
sudo kextcache -invalidate /
새로운 커널을 사용할려면 kextcache를 무효화 시켜야 됩니다.
Reboot
sudo reboot
변경 사항들을 저장할려면 재부팅을 해야됩니다.
Xcode 설치
디버거를 실행시킬 가상머신에서 다음과 같은 명령어로 Xcode를 설치 할 수 있습니다
xcode-select --install
xcode를 설치하고 나면 lldb가 정상적으로 실행되는것을 볼 수 있습니다.
macOS kernel Debugging
이제 환경 설정은 다 끝나서, 커널 디버깅을 할 수 있습니다.
(lldb) target create /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development
Loading kernel debugging from /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.dSYM/Contents/Resources/DWARF/../Python/kernel.py
LLDB version lldb-340.4.119
settings set target.process.python-os-plugin-path "/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/core/operating_system.py"
command script import "/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.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.10.5_14F27.kdk/System/Library/Kernels/kernel.development' (x86_64).
(lldb)
lldb를 실행하고 target을 KDK에 있는 kernel.development로 설정해줍니다.
그리고 디버거 모드를 활성화 시킨 vm을 부팅해줍니다.
Darwin Bootstrapper Version 2.0.2: Sun Jul 5 21:53:13 PDT 2015; root:libxpc_executables-559.40.1~1/launchd/RELEASE_X86_64
boot-args="debug=0x141 kext-dev-mode=1 kcsuffix=development pmuflags=1 -v"
IOKernelDebugger: registering debugger
ethernet MAC address: 00:1c:42:11:1d:6c
ip address: 10.37.129.7
Waiting for remote debugger connection.
디버거 모드를 활성시킨 vm에서 위와 같은 화면이 뜨는것을 볼 수 있습니다.
이제 lldb에서 kdp-remote 10.37.129.7
으로 remote debugging를 시작 할 수 있습니다.
(lldb) kdp-remote 10.37.129.7
Version: Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/DEVELOPMENT_X86_64; UUID=C75BDFDD-9F27-3694-BB80-73CF991C13D8; stext=0xffffff801ee00000
Kernel UUID: C75BDFDD-9F27-3694-BB80-73CF991C13D8
Load Address: 0xffffff801ee00000
Loading kernel debugging from /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.dSYM/Contents/Resources/DWARF/../Python/kernel.py
LLDB version lldb-340.4.119
settings set target.process.python-os-plugin-path "/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/core/operating_system.py"
Target arch: x86_64
Instantiating threads completely from saved state in memory.
command script import "/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/xnu.py"
xnu debug macros loaded successfully. Run showlldbtypesummaries to enable type summaries.
Kernel slid 0x1ec00000 in memory.
Loaded kernel file /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development
Loading 57 kext modules ......................................................... done.
Target arch: x86_64
Instantiating threads completely from saved state in memory.
kernel.development was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 1 stopped
* thread #2: tid = 0x0146, 0xffffff801eebb4c8 kernel.development`kdp_register_send_receive(send=<unavailable>, receive=<unavailable>) + 392 at kdp_udp.c:463, name = '0xffffff8025a61b50', queue = '0x0', stop reason = signal SIGSTOP
frame #0: 0xffffff801eebb4c8 kernel.development`kdp_register_send_receive(send=<unavailable>, receive=<unavailable>) + 392 at kdp_udp.c:463 [opt]
(lldb)
맥 커널을 실행 시키고 나서부터는 커널을 다시 멈출 수 없습니다. 그래서 커널을 실행하기전에 미리 브레이크포인터와 설정들을 커널을 실행하기전에 미리 해줘야됩니다. 만약에 커널을 정지할려고 하면 오류 메세지가 뜨는것을 볼 수 있습니다.
(lldb) breakpoint set --name OSUnserializeBinary
Breakpoint 2: where = kernel.development`OSUnserializeBinary(char const*, unsigned long, OSString**) + 29 at OSSerializeBinary.cpp:287, address = 0xffffff801f46080d
breakpoint set —name fuction
으로 커널의 원하는 함수에 브레이크 포인트를 걸 수 있습니다.
그리고 continue 하면, 커널이 실행되면서 해당 브레이크 포인터에서 브레이크 걸리는것을 볼 수 있습니다.
'System > [macOS]' 카테고리의 다른 글
[MacOS] WindowServer analysis (CVE-2018-4193) (2) | 2018.09.05 |
---|---|
구구콘 macOS kernel 1day 발표자료. (0) | 2017.05.13 |
macOS App to ISO file Convert (0) | 2017.03.16 |
CVE-2016-1758 macOS kernel information leak (0) | 2017.02.25 |