1

As part of a CTF challenge I have to understand the inner workings of a cryptlock type malware, and use it to decrypt a file containing the flag.

I used GHIDRA to decompile the binary.

The encryption function seems pretty basic, it is just the following line inside a while loop repeated until all bytes of the file have been xored : local_111c[local_1120] = local_111c[local_1120] ^ *(byte *)(param_2 + local_1120 % 0x20);

Where local_1120 is the loop counter, local_111c is a buffer where the file to encrypt is read into, and param_2 is an integer that seems to be always 0, the function is called like the following FUN_00401000((LPCSTR)0x0,0), with both parameters set to 0;

What does *(byte *)(param_2 + local_1120 % 0x20 refer to? As far as I understand it, it would be the value at the address pointed to by an integer cast to a byte pointer, but the modulo makes it so the adress can't be above 32?

I need to understand what could the value pointed to could have been in order to xor back the file to its original state.

2
  • Are you following order of operations?
    – mumbel
    Commented Mar 9, 2021 at 13:31
  • Are you sure param_2 is 0? Because this looks like a typical cyclic xor to me with a key that's expected to be 32 bytes (hence the index 0x20). In that case param_2 would be a pointer to the the xor key. Commented Dec 5, 2021 at 0:36

2 Answers 2

1

based on what is provided local_1120 % 0x20 can range between 0x0 to 0x1f only

:\>python printmod.py 0x0 0x20
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
:\>python printmod.py 0x80480040 0x80480060
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
:\>python printmod.py 0xffffffe0 0x100000000
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
:\>python printmod.py 0xffffffffffffffe0 0x10000000000000000
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
:\>type printmod.py
import sys

def printmod(start,stop,step=1):
    for i in range(start,stop,step):
        print(("%02x" % (i%0x20)),end=" ")

def main():
    if( len(sys.argv) != 3):
        sys.exit("provide 2 hex numbers as arguments like foo.py 4b 8c")
    printmod(int(sys.argv[1],16),int(sys.argv[2],16))

if(__name__=="__main__"):
    main()
:\>

so if param2 is not a valid memory address but NULL as you indicate it will result in an access violation since you are dereferencing the pointer with *(byte *)

you have to find out or force param2 to be a valid memory block

0

Let's see.

*(byte *)(param_2 + local_1120 % 0x20)

Inside we take local_1120 and mod it with 32, as you note. Then we add an offset from param_2, and cast that new address to a pointer to a byte. Finally, we dereference the pointer to obtain a byte at that address.

To my eye, we are using a 32-byte decryption key that we use over and over (thus the modular arithmetic). We have to get a real address; we cannot dereference NULL without a problem, so param_2 must be the address of the decryption key when you enter the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.