Reverse Engineering — Castors CTF 2020

kosong
6 min readJun 1, 2020

Here some writeup of RE challenges that i’ve been solved on Castors CTF 2020.

Mapping

Mapping is a golang binary. The first step i do is try to decompile it Using IDA .

main_main function

There is main_apply function that doing something with our input , i know it from debugging the binary and set breakpoint on main_apply call instruction.

My dummy input is ABCD , so the next step is try to determine what is main_apply function do.

main_apply function

if we look at main apply function , there is looping for each byte of our input and if our input decimal is greater or equal than 128 ( unprintable characters ) runtime_decoderune will be called if not just increment it. Before the looping end there is runtime_mapaccess1 function that will mapping our input to something that has been specified. The last instruction on that function is returning the result as base64.

Because our input is ABCD and the first character is A , so A will be mapped fisrt. The return value of runtime_mapaccess1 with argument A is 0x5a

It is possible to knowing each mapped value by doing examine $rax after runtime_mapaccess1 function called but it is more easier to know the mapped value after all characters mapped. So we just need to set breakpoint at base64 encode instruction.

Input all printable character as password
the mapped value from all printable characacters

After that you will find instruction that compare our base64 mapped input with the real flag.

So the last step is writing a script to mapping the mapped flag to original value.

import base64flag=[0x65,0x48,0x70,0x7a,0x64,0x47,0x39,0x79,0x63,0x31,0x68,0x58,0x51,0x58,0x74,0x70,0x59,0x6c,0x38,0x30,0x63,0x6a,0x46,0x75,0x4d,0x6d,0x67,0x78,0x4e,0x44,0x59,0x31,0x62,0x6c,0x38,0x30,0x4d,0x58,0x6c,0x6f,0x4d,0x46,0x38,0x32,0x4d,0x6c,0x39,0x35,0x4d,0x44,0x51,0x30,0x4d,0x48,0x4a,0x66,0x4e,0x47,0x51,0x78,0x62,0x6c,0x39,0x69,0x4e,0x58,0x56,0x79,0x4d,0x6e,0x30,0x3d]
tmp=[0x35,0x36,0x37,0x30,0x31,0x32,0x33,0x34,0x38,0x39,0x7a,0x79,0x78,0x6a,0x6b,0x6c,0x6d,0x64,0x65,0x66,0x67,0x68,0x69,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x63,0x62,0x61,0x5a,0x59,0x58,0x46,0x47,0x41,0x42,0x48,0x4f,0x50,0x43,0x44,0x45,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x49,0x4a,0x4b,0x4e,0x4d,0x4c]
alpha=list('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
dicti=dict(zip(tmp,alpha))
flag=base64.b64decode(''.join(map(chr,flag)))
result=""
for i in flag:
try:
result+=dicti[ord(i)]
except Exception as e:
result+=i
print result

Flag : castorsCTF{my_7r4n5l4710n_74bl3_15_b3773r_7h4n_y0ur5}

Ransom

Ransom is also golang binary. The first step i do is try to decompile it using IDA.

main_main function

First , the binary will try to get seed value using main_getSeed.

main_getSeed function

From the code we know that there will be a HTTP request with GET method . Looking at the pcap file we know that the response is a number ( seed value ) .

traffic.pcapng

Here we assume that the result is the seed value. After that we look at main_send function and there is a HTTP request with POST method.

main_send function

Looking at pcap file we find a HTTP request with POST method.

traffic.pcapng

So until here we know that the exact value of seed is 1337 , because there is only one HTTP request with POST method and the value is 1337 . The return value main_send is “ok” .

There will be checking that compare v9 with 1 and v11 with 3 and v10 value with “ok\n” . The last is doing encryption with main_encrypt function ,looking at the main_encrypt function there is looping , randint , xoring, and many comparation. Here we know that PNG has file signature , so my idea is try to encrypt dummy png file and check the encrypted dummy png file signature. If the header is same as the flag.png so we have successfully encrypting the file with same seed. After trying to do that and the results are same as I thought. So the last step i do to decrypt the file is run the binary again with same seed ( because i see that there is only basic operation to encrypt the file such as xor and looping ). Here is the step i do to decrypt the flag.png

1. Creating fake web server with return value 1337 if the request using GET method and return "ok" if the request using POST method
2. Debugging binary to ensure that we give true logic on comparation

First create loopback interface that have address same as the server in pcap.

sudo ifconfig lo:40 192.168.0.2 netmask 255.255.255.0 up

Change the port address of apache to 8081. (Here i use lampp)

After that just create fake seed.php and .htaccess

Debug the binary and change some register that doesn’t meet the value.

After that continue and we will get the original flag.png

flag.png

Flag : castorsCTF{this_is_not_my_final_form}

Octopus

Given obfus file which the content is golang binary encoded in base64. So we just need to decode it and write it to file . The problem here i have worked in a few hours to try solving the old binary , i just knew that the binary changed after try to get some hint on discord.

I have done a long enough analysis to figure out what this challenge mean , because there is no input and i don’t know what i must to do. In the end i realized that the binary work properly , nothing needs to be patched . So because i working on old binary , i try to decode that unicode , something like converting UTF-32 to UTF-8 and etc. Here is the value of encoded flag.

0x00008dc200008fc2    0x0000a4c20000a3c2
0x0000a2c200009dc2 0x0000adc20000a3c2
0x000089c2000096c2 0x000090c20000a3c2
0x00009cc2000089c2 0x000096c2000083c2
0x00009cc200009ac2 0x0000a5c2000089c2
0x00009bc2000089c2 0x000000000000a4c2

And here is the result if you run the old binary

But i still can’t decode it , after that i try to look at discord server to find any hint about it and i got the information about the new binary was uploaded. So after that i try to analyze the new binary and exactly it has the same algorithm like the old one but more simple.

main_main function ( new binary )

Looking at the result given from the binary , it is like base64 encoded string. So the next step i do is try to decode it and got the flag!

The important lesson i learn from the octopus challenge is “overthinking will kill you :) ” and i was really caught in tentacles same as the challenge description for few hours :’) .

Flag : castorsCTF{Wh0_s41d_AnY7hlnG_B0uT_m4tH}

Thank You!

--

--

kosong

CTF Player | Currently learning about Reverse Engineering and Cryptography