Swiss Hacking Challenge 2023 - x or y
Information
Challenge category: re
Challenge Description
Staring at the two options in front of her, Sarah was overwhelmed with indecision. She turned to her friend and asked, “Is it X or Y? I can’t decide. Can you help me figure it out?” Her friend took a moment to consider before replying, “Well, it depends on what you’re looking for. If you want something sweet, go for X. But if you want something savory, Y is the way to go.” Sarah thought about it for a moment before making her choice, grateful for her friend’s guidance.
Files
We are given an x_or_y.zip
file containing a binary:
x_or_y: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2551529b8c67cd6ec847697eff8e080df61bbc4c, for GNU/Linux 3.2.0, not stripped
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Exploitation
When opening up the file and showing the decompilation of the main
function we see the following:
undefined8 main(void)
{
bool bVar1;
long in_FS_OFFSET;
int local_5c;
undefined8 local_58;
undefined8 local_50;
undefined8 local_48;
undefined4 local_40;
undefined2 local_3c;
undefined local_3a;
byte local_38 [40];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_58 = 0x24a4b494b1a110a;
local_50 = 0x110d261e17104c2c;
local_48 = 0x49261d49491e264a;
local_40 = 0x1261d15;
local_3c = 0xb49;
local_3a = 4;
printf("Enter the password to continue: ");
fgets((char *)local_38,0x20,stdin);
bVar1 = true;
for (local_5c = 0; local_5c < 0x1f; local_5c = local_5c + 1) {
bVar1 = (bool)(bVar1 & (local_38[local_5c] ^ 0x79) ==
*(byte *)((long)&local_58 + (long)local_5c));
}
if (bVar1) {
puts("This password is correct.");
puts("Have a nice day!");
}
else {
puts("Sorry, this password is wrong :(");
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
Basically the local58
, local50
, local48
, local40
, local3c
and local3a
seem to contain the flag XORed with 0x79
. So we just need to XOR the values with 0x79
to get the flag.
import sys
def xor(x):
# xor the bytes
array = [ chr(x[i] ^ 0x79) for i in range(0, len(x))]
# change byte order
return [ array[i] for i in range(len(array)-1, -1, -1)]
# initialize the arrays
one = bytearray.fromhex("024A4B494B1A110A")
two = bytearray.fromhex("110D261E17104C2C")
three = bytearray.fromhex("49261D49491E264A")
four = bytearray.fromhex("040B4901261D15")
# concatenate the strings
total = xor(one) + xor(two) + xor(three) + xor(four)
# print the password
print("".join(total))
I had to try around a bit with the order of the arrays but in the end I got a flag.
Flag
The flag is:
shc2023{U5ing_th3_g00d_0ld_x0r}
Conclusion
x_or_y
was a weird challenge but it somehow worked. During writing this writeup I was like wtf did I do there. But it worked so I’m happy. Also, this is finally my last writeup for SHC quals 2023, looking back I don’t know if I’d do writeups for every challenge again.