https://www.malwaretech.com/ransomware1
This CTF is for a very basic ransomware program. The goal is to derive a key to decrypt the flag. Debugging wasn't allowed and is useless as the key is not stored inside the program anyway
After analyzing ransomware.exe_ in IDA, this the interesting block I set my sights on:
mov eax, [ebp+byte_counter]
xor edx, edx
mov ecx, 20h
div ecx
mov eax, [ebp+arg_4]
movzx ecx, byte ptr [eax+edx]
mov edx, [ebp+byte_counter]
movzx eax, [ebp+edx+Buffer]
xor eax, ecx
mov ecx, [ebp+byte_counter]
mov [ebp+ecx+Buffer], al
jmp short loc_4010A8
This tells us 3 key things about the ransomware:
- the key is 32 bytes long
- a basic XOR cipher is the encryption mechanism
- the plaintext is encrypted 1 byte at a time
With these 3 things in mind, this function breaks down into 2 parts.
mov eax, [ebp+byte_counter]
xor edx, edx
mov ecx, 20h
div ecx
mov eax, [ebp+arg_4]
movzx ecx, byte ptr [eax+edx]
Essentially, this section is how the key is looped over. It uses the remainder in a modulus operation to select the key's byte to based on the corresponding byte to be encrypted/decrypted. I'll be honest, I got hung up on this part for a long time. The modulus operation is as follows:
byte_counter % key_length = key_index
byte_counter = the index of the byte inside the plaintext
key_length = length of the key
key_index = the index of the byte inside the key
Here are two examples:
byte_counter = 5
key_length = 32
5 % 32 = 5
So the sixth byte of plaintext (index 5) will be XORed with the sixth byte in the key
byte_counter = 120
key_length = 32
120 % 32 = 24
So the 121st byte of plaintext (index 120) will be XORed with the 24th byte of the key
mov edx, [ebp+byte_counter]
movzx eax, [ebp+edx+Buffer]
xor eax, ecx
mov ecx, [ebp+byte_counter]
mov [ebp+ecx+Buffer], al
jmp short loc_4010A8
The key_byte that is selected after the modulus operation is loaded into the ecx register.
Then ecx is XORed with eax, which contains the byte in the file denoted by the byte_counter
Although, these are 32-bit registers, the key to my understanding was seeing mov [ebp+ecx+Buffer], al. This moves just the LSB from eax into the buffer which shows that it's basically only working on 1 byte at a time since al is only 1 byte.
After I understood the encryption mechanism, getting the key was super easy.
To get the key, we can XOR the first 32 bytes of an encrypted Sample Picture with a known unencrypted picture. These pictures are from the Windows 7 Sample Pictures and are available online.
decryptor.go is used to derive the key from the koala images and decrypt flag.txt_encrypted