CreateRemoteThread - ERROR_ACCESS_DENIED

Posts 1–6 of 6 · Page 1 of 1
CreateRemoteThread - ERROR_ACCESS_DENIED
I think my code is finally working now. Only problem is that for some reason, even though I've opened the process with PROCESS_ALL_ACCESS, CreateRemoteThread throws back an error: ERROR_ACCESS_DENIED.

The error was retrieved with GetLastError() and it spit out '5', which translates to ERROR_ACCESS_DENIED.

Code:
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>

char* dllPath = "C:\\Users\\Kalist\\Desktop\\Projects\\DLL\\bin\\Debug\\DLL.dll";
char* ProcToInject = "calc.exe";

int main(){
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    HANDLE procSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if(procSnap == INVALID_HANDLE_VALUE){
        std::cout << "Snapshot function failed" << std::endl;
    }

    DWORD procID = 0;
        if(Process32First(procSnap, &pe32)){
            do{
               if(!strcmp(pe32.szExeFile, ProcToInject)){
                    procID = pe32.th32ProcessID;
                    break;
               }
            }while(Process32Next(procSnap, &pe32));
        }
    CloseHandle(procSnap);

    if(procID != 0){

        HANDLE procAccess = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
        if(procAccess == NULL){
            std::cout << "OpenProcess error: " << GetLastError() << std::endl;
        }

        LPVOID remoteString = (LPVOID)VirtualAllocEx(procAccess, NULL, strlen(dllPath)+1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if(remoteString == NULL){
            std::cout << "VirtualAllocEx error: " << GetLastError() << std::endl;
        }

        bool memoryWritten = WriteProcessMemory(procAccess, (LPVOID)remoteString, dllPath, strlen(dllPath)+1, NULL);
        if(memoryWritten == 0){
            std::cout << "WriteProcessMemory error: " << GetLastError() << std::endl;
        }

        LPVOID getLibAdd = (LPVOID)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
        if(getLibAdd == NULL){
            std::cout << "GetProcAddress error: " << GetLastError() << std::endl;
        }

        HANDLE remoteThread = CreateRemoteThread(procAccess, NULL, 0, (LPTHREAD_START_ROUTINE)getLibAdd, (LPVOID)remoteString, 0, NULL);
        if(remoteThread == NULL){
            std::cout << "CreateRemoteThread error: " << GetLastError() << std::endl;
        }
        CloseHandle(procAccess);
    }else{
        std::cout << "Failed to retrieve procID" << std::endl;
    }
}
It doesn't work because your code is for x86 while by calculator (calc.exe) is x86_64 by default. Try it on some other process that has a *32 in task manager (x86 program) and it should work. Some evidence:



This is my code (thanks to Darawk) but before you try my code try yours on an x86 program:

Code:
#include <cstdio>
#include <Windows.h>
#include <TlHelp32.h>
#include <string>

using std::string;
using std::wstring;

#define PROCESS_NAME		L"Swag.exe"
#define MODULE_NAME			"C:\\Users\\Swag\\Desktop\\Dll.dll"

int wmain()
{
	// Get a snapshot and then filter for getting
	// the Id of the process we want
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	if(hSnapshot == INVALID_HANDLE_VALUE)
	{
		printf_s("Error: Could not get snapshot (Code: %i)\n", GetLastError());
		return S_FALSE;
	}

	// Iterate 'snapshotted' processes for the one
	// we want
	PROCESSENTRY32 pe32 = { };
	pe32.dwSize = sizeof(PROCESSENTRY32);

	if(!Process32First(hSnapshot, &pe32))
	{
		printf_s("Error: Process32First returned false (Code: %i)\n", GetLastError());
		CloseHandle(hSnapshot);
		return S_FALSE;
	}

	bool foundProcess = false;
	do
	{
		if(std::wstring(pe32.szExeFile) == PROCESS_NAME)
		{
			foundProcess = true;
			break; // Found the process we want
		}

	} while(Process32Next(hSnapshot, &pe32));

	if(!foundProcess)
	{
		printf_s("Error: Failed to find process (Code: %i)\n", GetLastError());
		CloseHandle(hSnapshot);
		return S_FALSE;
	}

	// Get the Id of the process and use it
	// to inject the module into the process
	DWORD procId = pe32.th32ProcessID;

	HANDLE hProcess = OpenProcess(((PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)), FALSE, procId);

	if(hProcess == NULL)
	{
		printf_s("Error: Failed to open process (Code: %i)\n", GetLastError());
		CloseHandle(hSnapshot);
		return S_FALSE;
	}

	auto addrOfLoadLibrary = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
	auto remoteAlloc = VirtualAllocEx(hProcess, NULL, strlen(MODULE_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

	if(WriteProcessMemory(hProcess, remoteAlloc, MODULE_NAME, strlen(MODULE_NAME), NULL) == 0)
	{
		printf_s("Error: Failed to write to process' memory (Code: %i)\n", GetLastError());
		CloseHandle(hProcess);
		CloseHandle(hSnapshot);
		return S_FALSE;
	}

	if(CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) addrOfLoadLibrary, remoteAlloc, NULL, NULL) == NULL)
	{
		printf_s("Error: Failed to create remote thread (Code: %i)\n", GetLastError());
		CloseHandle(hProcess);
		CloseHandle(hSnapshot);
		return S_FALSE;
	}

	printf_s("Finished Successfully!\n");

	// Clean up a bit
	CloseHandle(hSnapshot);
	CloseHandle(hProcess);

	return S_OK;
}
Try running as an administrator, or use RtlAdjustPrivilege and SeDebugPrivilege (this allows your process to even interfere with system's process e.g csrss.exe)

Code:
  NTSTATUS NTAPI RtlAdjustPrivilege(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);  //This is the prototype of the RtlAdjustPrivilege function.
 
  RtlAdjustPrivilege(20,TRUE,FALSE,&bl);  //20 is the value of SeDebugPrivilege
LINK WITH NTDLL.LIB !
Quote Originally Posted by ZER0MEM0RY View Post
Try running as an administrator, or use RtlAdjustPrivilege and SeDebugPrivilege (this allows your process to even interfere with system's process e.g csrss.exe)

Code:
  NTSTATUS NTAPI RtlAdjustPrivilege(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);  //This is the prototype of the RtlAdjustPrivilege function.
 
  RtlAdjustPrivilege(20,TRUE,FALSE,&bl);  //20 is the value of SeDebugPrivilege
LINK WITH NTDLL.LIB !
Still won't allow you to bypass the WoW64 barrier implemented in the system.
It works like a charm, I simply downloaded the MinGW64 compiler and implemented it into CodeBlocks. Now I can inject both 32bit and 64bit as I see fit.
Quote Originally Posted by Kalist View Post
It works like a charm, I simply downloaded the MinGW64 compiler and implemented it into CodeBlocks. Now I can inject both 32bit and 64bit as I see fit.
Were you using MSVC before? Try compiling again with MSVC but in 64-bit and try again.
Posts 1–6 of 6 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?