서론
앞서 공부한 보호기법 설명에서와 같이 SMEP 보호기법은 결국 CR4 레지스터 값에 따라 결정된다.
만일 해당 값을 수정할 수 있다면 보호기법도 해제할 수 있지 않을까?
본론
SMEP은 유저 공간에서의 NX와 같이 실행 권한을 제한하는 방법이다.
CR4 레지스터에 SMEP을 제어하는 비트가 있어 이를 0으로 만들거나,
유저 공간의 rop과 같이 krop이 가능하다.
본 글에서는 CR4 overwrite를 기준으로 한다.
1. 환경설정
1.1. vmlinux 추출하기
앞과 동일하다.
1.2. 문제 환경 설정
앞과 동일하다.
init.d/S99pawnyable
#!/bin/sh
##
## Setup
##
mdev -s
mount -t proc none /proc
mkdir -p /dev/pts
mount -vt devpts -o gid=4,mode=620 none /dev/pts
chmod 666 /dev/ptmx
stty -opost
#echo 2 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
##
## Install driver
##
insmod /root/vuln.ko
mknod -m 666 /dev/holstein c `grep holstein /proc/devices | awk '{print $1;}'` 0
##
## User shell
##
echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
echo "[ Holstein v1 (LK01) - Pawnyable ]"
setsid cttyhack setuidgid 0 sh
##
## Cleanup
##
umount /proc
poweroff -d 0 -f
run.sh
#!/bin/sh
qemu-system-x86_64 \
-m 64M \
-nographic \
-kernel bzImage \
-append "console=ttyS0 loglevel=3 oops=panic panic=-1 nopti nokaslr" \
-no-reboot \
-cpu kvm64, +smep \
-smp 1 \
-monitor /dev/null \
-initrd rootfs.cpio \
-net nic,model=virtio \
-net user \
-s
2. module 분석
앞선 모듈과 동일한 모듈을 사용할거라 특별히 분석할 것은 없다.
2023.08.27 - [Kernel Exploit] - kernel - ret2usr
3. 취약점
마찬가지로 kernel buffer overflow가 취약점이다.
4. payload 작성
4.1 기존 CR4 값 확인
무엇보다 먼저 기존의 CR4 값을 알아내야한다.
이를 위해서는 의도적으로 커널 패닉을 발생시키면 로그에 값이 출력된다.
[ Holstein v1 (LK01) - Pawnyable ]
/ # ./payload
unable to execute userspace code (SMEP?) (uid: 0)
BUG: unable to handle page fault for address: 000000000040179e
#PF: supervisor instruction fetch in kernel mode
#PF: error_code(0x0011) - permissions violation
PGD 327c067 P4D 327c067 PUD 32d8067 PMD 32d0067 PTE 220f025
Oops: 0011 [#1] PREEMPT SMP NOPTI
CPU: 0 PID: 162 Comm: payload Tainted: G O 5.10.7 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:0x40179e
Code: Unable to access opcode bytes at RIP 0x401774.
RSP: 0018:ffffc9000040beb8 EFLAGS: 00000202
RAX: 0000000000000410 RBX: ffff88800313f400 RCX: 0000000000000000
RDX: 000000000000007f RSI: ffffc9000040bea8 RDI: ffff888003294400
RBP: 4141414141414141 R08: 000000000040179e R09: 4141414141414141
R10: 4141414141414141 R11: 4141414141414141 R12: 0000000000000410
R13: 0000000000000000 R14: 00007fffd25597a0 R15: ffffc9000040bef8
FS: 00000000004d03c0(0000) GS:ffff888003600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000000040179e CR3: 00000000032d2000 CR4: 00000000001006f0
Call Trace:
? putname+0x47/0x50
? ksys_write+0x53/0xd0
? __x64_sys_write+0x15/0x20
? do_syscall_64+0x38/0x50
? entry_SYSCALL_64_after_hwframe+0x44/0xa9
Modules linked in: vuln(O)
CR2: 000000000040179e
---[ end trace 18e1d8f121a5b38b ]---
RIP: 0010:0x40179e
Code: Unable to access opcode bytes at RIP 0x401774.
RSP: 0018:ffffc9000040beb8 EFLAGS: 00000202
RAX: 0000000000000410 RBX: ffff88800313f400 RCX: 0000000000000000
RDX: 000000000000007f RSI: ffffc9000040bea8 RDI: ffff888003294400
RBP: 4141414141414141 R08: 000000000040179e R09: 4141414141414141
R10: 4141414141414141 R11: 4141414141414141 R12: 0000000000000410
R13: 0000000000000000 R14: 00007fffd25597a0 R15: ffffc9000040bef8
FS: 00000000004d03c0(0000) GS:ffff888003600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000000040179e CR3: 00000000032d2000 CR4: 00000000001006f0
Kernel panic - not syncing: Fatal exception
Kernel Offset: disabled
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000000040179e CR3: 00000000032d2000 CR4: 00000000001006f0
각 레지스터는 아래와 같이 bit로 작동 여부를 판단한다.
현재 CR4의 값이 0x1006f0이고 이를 2진수로 변환하면 아래와 같다.
>>> bin(0x1006f0)
'0b100000000011011110000'
즉, 20번째 값이 1임을 알 수 있으며 이를 0으로 바꾸면 아래와 같다.
>>> hex(0b000000000011011110000)
'0x6f0'
4.2 ropgadget 찾기
cr4 또한 커널에서 값을 넣고 빼는 과정을 거치기에 가젯으로 찾을 수 있다.
다만 pwnyable 에서 제공하는 이미지의 경우 적절한 가젯이 잘 찾아지지는 않는다.
그래서 가장 유력해보이는 아래 가젯으로 시도해보았다.
ffffffff81028532: 0f 22 e7 mov %rdi,%cr4
ffffffff81028535: 8b 05 ed 2e d4 00 mov 0xd42eed(%rip),%eax # 0xffffffff81d6b428
ffffffff8102853b: 85 c0 test %eax,%eax
ffffffff8102853d: 7f a5 jg 0xffffffff810284e4
ffffffff8102853f: c3 ret
근데 실패함.... ㅋ
0xffffffff810284e4로 무조건 점프할 수 밖에 없는 구조인데, 내부에서 cr4 값을 다시 변조해버린다.
그래서, 다른 커널로 다시 시도해보았다.
(글이 엄청 길어진다...)
아래 링크를 참고하자.
2023.09.08 - [Kernel Exploit] - Kernel - cr4 overwrite #2
'Kernel Exploit' 카테고리의 다른 글
Kernel - stack pivoting #1 - with mov esp. (0) | 2023.09.08 |
---|---|
Kernel - SMEP 우회, cr4 overwrite #2 (0) | 2023.09.08 |
Kernel - SMEP 우회, krop (0) | 2023.09.07 |
kernel - ret2usr (0) | 2023.08.27 |
kernel debuging with pwndbg - pwndbg 설치 (0) | 2023.08.27 |