I went to Tampa, Florida last weekend to participate Raymond James CTF. My team got 3rd place with $2500 award.
The weather in Florida is so0O gO0od: 24 degrees C, meanwhile it’s like 3 degrees C in Baltimore.
The team photo:
My eyes were closed lol.
The trophy:
The coin from gam3z:
The onsite-CTF was 70% forensics, 20% binary reverse and 10% Misc. I’m not good at forensics so I didn’t contribute much on that. However, I earn 185 out of 215 points from the pre-challenge by solving a binary reverse problem. Those points from the pre-challenge give our team a huge advantage during the on-site CTF.
Write up for the binary reverse problem from pre-challenge(without IDA):
Step 1: Understand the program
Use the password in the email from t0k3nz@gam3z-inc.com to extract the binary from the Zip file.
file Ghost_Protocol_Access
Ghost_Protocol_Access: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=cf8c2aebbde52c274e2f71dc3a83bb63e4a629e3, stripped
I copy the binary to my Ubuntu VM and run the binary:
The program print out two messages:
"This version of bash is terribly out of date....your environment is not secure and this program will not run."
"You're not even authorized to use this program!"
I load the binary in Hopper Disassembler(https://www.hopperapp.com/) and search for the string: “This version of bash is terribly out of date....
“
The string was used in function: sub_401c99. I then load the binary in radare2, I prefer reading assembly code in r2 because it looks nicer:
r2 Ghost_Protocol_Access
aaa
s 0x401c99
pdf
The program check for things like “gdb”, “r2”, and “bash”. If “gdb” or “r2” is found, the program will print out the string:
"Seriously....you're trying to debug and disassemble me?!?\n ....ridiculous....I don't even know what to say.....so disappointed...."
If “bash” is found, the program will print:
"This version of bash is terribly out of date....your environment is not secure and this program will not run."
Now I understand the function “sub_401c99” does some environment check and exit the program. My next step is to find out where this function gets called in the program.
I reload the binary in radare2:
r2 Ghost_Protocol_Access
aaa
pdf
Noticed the function address “0x401c99” was one of the function argument for the next function call(sub.libc_start_main_40). To display the instruction in function sub.libc_start_main_40 in r2, I used following command:
s sub.libc_start_main_40
pdf
I can’t really understand what the program is doing inside the function “sub.libc_start_main_40
” by reading the assembly code only, I need to run the program in GDB to understand the program flow.
gdb ./Ghost_Protocol_Access
The program starts at address 0x004015f0:
I put break point at the beginning of the program:
tbreak *0x004015f0
run
Run the program line by line(in assembly) in GDB with “next” and “step”. Pressing “n” in gdb for a while and the program stop at address: 0x402347:
whats in eax? It’s the function(sub_0x401c99) I mentioned before, the function that checks environment and quit the program.
At this point I understand after entering the function “sub.libc_start_main_40
“, the program call “sub_0x401c99
” and the program die afterword.
I am not sure what to do at this point, I just randomly do a “strings Ghost_Protocol_Access | grep t0k3n
” and got some interesting result:
Since I know one of the token named “acc3ss”, I start searching the string “acc3sst0k3n” in the program. I search the string in r2 with command "/ $string"
:
In hopper, it shows the strings was used in function sub_401987:
I notice the function sub_401987 doesn’t get call in the program:
Hopper has the feature to show where a function get called, if a function get called, it will show something like this in hopper:
I want to see what function sub_401987 does, my plan is to patch the program and let the function sub_401987 run.
Step 2: Patch the binary to get the Token(Flag):
First Patch:
Remember at the beginning of the program, the environment checking function: sub_0x401c99 was moved into the register and get called in “sub.libc_start_main_40” function. I first patch the binary to change the value from sub_0x401c99 to sub_401987, so sub_401987 will be called afterwords.
The opcode 48c7c7991c40. means 48c7c7991c4000, the small dot, in the end, represent two zero “00”. I use this website to convert between opcode and assembly: https://defuse.ca/online-x86-assembler.htm#disassembly2
I need the opcode for mov rdi, 0x401987
:
Patch the binary in r2:
oo+
(enable write)
s 0x0040160d
wx 48C7C787194000
q
Run the program again:
The program ask for a “Confirmation Code”, I am not sure what the code is so I enter some random string:
Second Patch:
Check the sub_0x00401987 function in r2:
s 0x00401987
pdf
There are two place call the function “call sub.You_re_not_even_authorized_to_use_this_program_70d”. The jump come from CODE XREF from main (0x401b42)
and CODE XREF from main (0x401b0d)
Both section does the same thing: call a function, compare the output to a variable, jump if not equal:
I patch the jump instruction to let the program can keep running without doing the jump:
oo+
s 0x401b42
wx 909090909090
s 0x401b0d
wx 909090909090
q
Change jne instruction to nop:
Run the program again to get the flag:
Step 3: Fix the image file:
After the program print our both token, it also outputs a file called: “acc3sst0k3n”:
My teammate told me this file can be base64 decode to an image, but the file is somewhere corrupted and they can’t the flag in the image.
I did remember there is a super long string in function sub_0x0401987:
I am not sure what was this at the beginning, I went to address “0x00496498” in r2 and type:
s 0x00496498
ps 100000
In r2 it outputs a huge amount of base64 encoded string, the image below shows the end of the string.
I search for "XXH+Kk"
in “acc3sst0k3n” file and found a “NUL”.
I delete the "NUL"
and run the following command to convert base64 encoded file to an image:
base64 -D acc3sst0k3n > a.png
View the image: