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