I am trying to inject a dll into a specific application in rust. I gave up trying to do so in pure rust, as it was not working no matter what. So, I used a C injector and compiled it and it worked perfectly. However, when I use the CC crate to compile it and use the function, it no longer works at all. In this case, I was simply trying to inject a dll I made.
The code for the C is:
// test.c
#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#pragma comment(lib, "ntdll.lib")
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx(PHANDLE,
ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID,
BOOL, SIZE_T, SIZE_T, SIZE_T, LPVOID);
struct NtCreateThreadExBuffer
{
SIZE_T Size;
SIZE_T Unknown1;
SIZE_T Unknown2;
PULONG Unknown3;
SIZE_T Unknown4;
SIZE_T Unknown5;
SIZE_T Unknown6;
PULONG Unknown7;
SIZE_T Unknown8;
};
DWORD GetPid(const wchar_t *targetProcess)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (snap && snap != INVALID_HANDLE_VALUE && Process32First(snap, &procEntry))
{
do
{
if (!wcscmp(procEntry.szExeFile, targetProcess))
{
break;
}
} while (Process32Next(snap, &procEntry));
}
CloseHandle(snap);
return procEntry.th32ProcessID;
}
void injectAmongUs()
{
DWORD dwPid = GetPid(L"Among Us.exe");
struct NtCreateThreadExBuffer ntbuffer;
memset(&ntbuffer, 0, sizeof(struct NtCreateThreadExBuffer));
DWORD temp1 = 0;
DWORD temp2 = 0;
ntbuffer.Size = sizeof(struct NtCreateThreadExBuffer);
ntbuffer.Unknown1 = 0x10003;
ntbuffer.Unknown2 = 0x8;
ntbuffer.Unknown3 = (DWORD *)&temp2;
ntbuffer.Unknown4 = 0;
ntbuffer.Unknown5 = 0x10004;
ntbuffer.Unknown6 = 4;
ntbuffer.Unknown7 = &temp1;
ntbuffer.Unknown8 = 0;
HANDLE proc = OpenProcess(GENERIC_ALL, 0, dwPid);
HANDLE hThread;
wchar_t path[] = L"path/to/dll";
LPVOID allocAddr = VirtualAllocEx(proc, 0, sizeof(path), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(proc, allocAddr, path, sizeof(path), NULL);
NTSTATUS status = NtCreateThreadEx(&hThread, GENERIC_ALL, NULL, proc,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"), allocAddr,
FALSE, NULL, NULL, NULL, &ntbuffer);
}
If I compile this file exactly the way it is but add a main method:
int main()
{
injectAmongUs();
return 1;
}
It works perfectly as intended. However, if I remove the main method and use CC with this build script:
// build.rs
fn main() {
cc::Build::new()
.file("test.c")
.compile("injector.dll");
}
and then call it in main with
//main.rs
extern "C" {
fn injectAmongUs();
}
fn main() {
unsafe {
injectAmongUs();;
}
}
which results in (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
.
How can I get it to successfully inject as if I just ran the .exe normally? Currently I just put the .exe with it, but that is not desirable and would rather it be built and used as a library. Note, I am trying to inject Among Us, and so I am running this as 32 bit with cargo run --target i686-pc-windows-msvc
.
User contributions licensed under CC BY-SA 3.0