# Some cool RE chall
## 2024
### Trustme

Open the trustme.exe in IDA, checking the main wont find us anything so special beside an antidebug and checking debugger function

But these 2 lines, definately cause an exception, this is some type of exception handler RE.
```
MEMORY[0] = 0;
JUMPOUT(0);
```

But I'm still too new with this so I will be open the string and find where it start doing it's magic

I see it connect to a IP and Port, so I just start from it. The address of the function that we need to focus was an offset with no calling or jumping into it, maybe it must have something to do with the "Exception Handling"


If you debug a little bit you will see it sending and receive thing from that IP address

So what it was retrieving was the RC4 key to decrypt something


after the 4 bytes Length must be data it got encrypted with the key that it received

This look right because the string was a random generated string

The size seem correct, since the hex-value of the size it 0x40 and it sent 4 bytes so its "40000000" convert to decimal is 64, the string was 64 bytes longs

original key
```
WTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibnM
```
Next the server send something back to us, maybe a DLL or PE since there was a a function was validating the header "MZ" then run the thing got decrypted.



Now, let's get back the file got sent back from the server, since we already got the key, this should be it!

So this was a DLL, it exported 4 option to run, gen0-3





To summerize this was the function of those option
**Gen0:** write the string backward
**Gen1:** upper -> lower and lower -> upper
**Gen2:** which rotates the string right by 1
**Gen3:** Caeser Cipher +13
So the how does the server and client exchange the encrypt and key? Actually it like the the first part, since the server already got our key so we can skip that part, but it send the byte that set the mode of the encryption key


This is all the mode in order

```
mode: 2,1,1,2,3,2,3,1,2,3,1,0,2,3,0,0,2,1,1,0,0,3
```
So we just need to dump this stream out, get rid of the first part about the DLL and the original key, the mode was set for the type of the key, using the original key we can get all of the 4 keys
```
00
MnbivxwTqsaDwDmDPlufDqJXpDVbgekuzKrOddMKVymjiawsFZrqPNqfaJbWjPTW
01
wtpJwBjAFQnpQRzfSWAIJMYvkmDDoRkZUKEGBvdPxjQdFULpdMdWdASQtWXVIBNm
02
MWTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibn
03
JGCwJoWnsdACdeMSfjnvwzlIXZqqBeXmhxrtoIQcKWdQshyCQzQjQnfdGjkivoaZ
```
With a little skill of prompting, we can ask Claude or GPT to write a script to solve this.
```python!
def rc4_decrypt(encrypted_data, key):
if isinstance(key, str):
key = key.encode('utf-8')
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
result = bytearray()
for byte in encrypted_data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
result.append(byte ^ k)
return bytes(result)
def hex_to_bytes(hex_data):
try:
hex_data = ''.join(hex_data.split())
return bytes.fromhex(hex_data)
except Exception as e:
print(f"Error converting hex to bytes: {str(e)}")
return None
def process_file(input_file, output_file, rc4_keys):
try:
with open(input_file, 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
decoded_data = []
lines = content.splitlines()
i = 0
current_mode = None
hex_chunks = []
while i < len(lines):
line = lines[i].strip()
if line in ["00", "01", "02", "03"]:
if current_mode is not None and hex_chunks:
key_name = f"gen{current_mode[-1]}"
current_key = rc4_keys[key_name]
combined_hex = ''.join(hex_chunks)
byte_data = hex_to_bytes(combined_hex)
if byte_data:
try:
decoded = rc4_decrypt(byte_data, current_key)
decoded_data.append(decoded)
#print(f"Mode {current_mode}: Decoded {len(byte_data)} bytes")
except Exception as e:
print(f"Error decoding with mode {current_mode}: {str(e)}")
current_mode = line
hex_chunks = []
print(f"mode {current_mode}")
i += 1 # Move to the next line
if i < len(lines):
#print(f"Skipping line: {lines[i]}")
i += 1
elif current_mode is not None:
if line:
hex_chunks.append(line)
i += 1
else:
i += 1
if current_mode is not None and hex_chunks:
key_name = f"gen{current_mode[-1]}"
current_key = rc4_keys[key_name]
combined_hex = ''.join(hex_chunks)
byte_data = hex_to_bytes(combined_hex)
if byte_data:
try:
decoded = rc4_decrypt(byte_data, current_key)
decoded_data.append(decoded)
print(f"Mode {current_mode}: Decoded {len(byte_data)} bytes")
except Exception as e:
print(f"Error decoding with mode {current_mode}: {str(e)}")
with open(output_file, 'wb') as f:
for data in decoded_data:
f.write(data)
print(f"Successfully decoded data and wrote to {output_file}")
except Exception as e:
print(f"Error: {str(e)}")
def main():
input_file = "input.txt"
output_file = "IloveCarlotta.bmp"
rc4_keys = {
"gen0": "MnbivxwTqsaDwDmDPlufDqJXpDVbgekuzKrOddMKVymjiawsFZrqPNqfaJbWjPTW",
"gen1": "wtpJwBjAFQnpQRzfSWAIJMYvkmDDoRkZUKEGBvdPxjQdFULpdMdWdASQtWXVIBNm",
"gen2": "MWTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibn",
"gen3": "JGCwJoWnsdACdeMSfjnvwzlIXZqqBeXmhxrtoIQcKWdQshyCQzQjQnfdGjkivoaZ"
}
process_file(input_file, output_file, rc4_keys)
if __name__ == "__main__":
main()
```

## 2023
### Oxygen
This challenge force you to read asm instead of pseudocode so I wont be showing pseudocode

```asm!
mov eax, 8
imul rax, 0
mov rcx, [rbp+7A0h+arg_8]
mov rcx, [rcx+rax] ; int
call j_maybe_imporatnt
mov [rbp+7A0h+var_5B8], 0FFFFFFFFFFFFFFFFh
mov [rbp+7A0h+s], 0FFFFFFFFFFFFFFFFh
mov [rbp+7A0h+ppResult], 0
mov [rbp+7A0h+len], 200h
lea rdx, [rbp+7A0h+WSAData] ; lpWSAData
mov cx, 202h ; wVersionRequested
call cs:WSAStartup
mov [rbp+7A0h+var_5DC], eax
cmp [rbp+7A0h+var_5DC], 0
jz short loc_7FF70822B99C
mov eax, 1
jmp check_stack
;
loc_7FF70822B99C: ; CODE XREF: main_0+B0↑j
mov r8d, 30h ; '0' ; Size
xor edx, edx ; Val
lea rcx, [rbp+7A0h+pHints] ; void *
call j_memset
mov [rbp+7A0h+pHints.ai_family], 2
mov [rbp+7A0h+pHints.ai_socktype], 1
mov [rbp+7A0h+pHints.ai_protocol], 6
mov [rbp+7A0h+pHints.ai_flags], 1
lea r9, [rbp+7A0h+ppResult] ; ppResult
lea r8, [rbp+7A0h+pHints] ; pHints
lea rdx, pServiceName ; "1337"
xor ecx, ecx ; pNodeName
call cs:getaddrinfo
mov [rbp+7A0h+var_5DC], eax
cmp [rbp+7A0h+var_5DC], 0
jz short loc_7FF70822BA14
call cs:WSACleanup
mov eax, 1
jmp check_stack
;
loc_7FF70822BA14: ; CODE XREF: main_0+122↑j
mov rax, [rbp+7A0h+ppResult]
mov r8d, [rax+0Ch] ; protocol
mov rax, [rbp+7A0h+ppResult]
mov edx, [rax+8] ; type
mov rax, [rbp+7A0h+ppResult]
mov ecx, [rax+4] ; af
call cs:socket
mov [rbp+7A0h+var_5B8], rax
cmp [rbp+7A0h+var_5B8], 0FFFFFFFFFFFFFFFFh
jnz short loc_7FF70822BA67
mov rcx, [rbp+7A0h+ppResult] ; pAddrInfo
call cs:freeaddrinfo
call cs:WSACleanup
mov eax, 1
jmp check_stack
loc_7FF70822BA67: ; CODE XREF: main_0+168↑j
mov rax, [rbp+7A0h+ppResult]
mov r8d, [rax+10h] ; namelen
mov rax, [rbp+7A0h+ppResult]
mov rdx, [rax+20h] ; name
mov rcx, [rbp+7A0h+var_5B8] ; s
call cs:bind
mov [rbp+7A0h+var_5DC], eax
cmp [rbp+7A0h+var_5DC], 0FFFFFFFFh
jnz short print_phase1
mov rcx, [rbp+7A0h+ppResult] ; pAddrInfo
call cs:freeaddrinfo
mov rcx, [rbp+7A0h+var_5B8] ; s
call cs:closesocket
call cs:WSACleanup
mov eax, 1
jmp check_stack
```
**ai_family to 2 (AF_INET, IPv4)
ai_socktype to 1 (SOCK_STREAM, TCP)
ai_protocol to 6 (IPPROTO_TCP)
ai_flags to 1 (AI_PASSIVE)**
This mean it setting up a connection, with the port is 1337, its binding that port and pNodeName is the value for getaddrinfo() null along with AI_PASSIVE flag is on so it actually open listenning on **0.0.0.0:1337**

This function here, printing the word "gimme oxygen!" then start listenning. I was saying about this above.
After receiving the data sending to, it start the next process, we can see here it was getting the key or something, it will do something with data "maybe_unpack", and using ope virtual protect

Checking the data, we can see this is some kind of data and it got called in another function look like a xor algorithm


Using CypherChef we can xor the whole data easily, but the outcome will be weird but do not let that stop you.

This is a shellcode, we can put it in IDA and investigate furthur, using IDA we will know what will the shellcode do


```py!
def sub0(key):
v3 = 0
for j in range(11):
i = 0x20
if (v3 & 1 != 0):
while True:
a = i | 0xA
b = i & 0xA
if ((a + b) == ord(key[j])):
print(chr(i),end="")
break
i += 1
else:
while True:
a = i | 0xA
b = i & 0xA
if ((a - b) == ord(key[j])):
print(chr(i),end="")
break
i += 1
v3 += 1
print(sub0("n[}>}C]qRm["))
```
After decoding with the hardcoded key we get the value "dQw4w9WgXcQ"

So it receive the value got send to it then encode the key if it equal to the hardcoded key it will print congratz and send something back.

```
import socket
host = "127.0.0.1"
port = 1337
message = "dQw4w9WgXcQ"
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.sendall(message.encode())
data = s.recv(1024)
if data:
print("Received:", data.decode())
```

---