# Forum > World of Warcraft > World of Warcraft Bots and Programs > WoW Memory Editing >  [QUESTION] Issues with OpenProcess C++ Win7 64bit

## Azzie2k8

So after 2 days of trying to solve this issue I feel like asking here for help is the only way to get this working.

I am sorry if I am breaking any rules by posting this since it seems to be somewhat a basic question.

I recently started dealing with c++ again and I want inject my dll into a process. I enabled Debug Priveleges (at least I hope so) and set the flags for OpenProcess. The real issue is that OpenProcess is returning the worng Process handles.
For example it is returning 0x3c for both notepad.exe and the explorer.exe which is simply impossible to my knowledge.

CreateRemoteThread is failing with error code 5 but I am pretty sure that is due to the wrong handle passed to it by OpenProcess.

Anyways here is the code. I know its not good but I am still learning so please point out issues I have in it if you feel like doing so.



```
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <tlhelp32.h>

typedef HINSTANCE (__stdcall *fpLoadLibrary)(char*);
typedef LPVOID (__stdcall *fpGetProcAddress)(HINSTANCE, char*);
typedef void (*fpFunktion)(void);

struct INJECTSTRUCT
{
    fpLoadLibrary LoadLibrary;
    fpGetProcAddress GetProcAddress;
    char path[255];
    char func[255];
};

DWORD WINAPI threadstart(LPVOID addr)
{
    HINSTANCE hDll;
    fpFunktion funktion;
    INJECTSTRUCT * is = (INJECTSTRUCT*)addr;       
    hDll = is->LoadLibrary(is->path);
    funktion = (fpFunktion)is->GetProcAddress(hDll, is->func);
    funktion();
    return 0;
}
void threadend()
{
}

DWORD FindProcessId(const std::wstring& processName)
{
    PROCESSENTRY32 processInfo;
    processInfo.dwSize = sizeof(processInfo);

    HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if ( processesSnapshot == INVALID_HANDLE_VALUE )
        return 0;

    Process32First(processesSnapshot, &processInfo);
    if ( !processName.compare(processInfo.szExeFile) )
    {
        CloseHandle(processesSnapshot);
        return processInfo.th32ProcessID;
    }

    while ( Process32Next(processesSnapshot, &processInfo) )
    {
        if ( !processName.compare(processInfo.szExeFile) )
        {
            CloseHandle(processesSnapshot);
            return processInfo.th32ProcessID;
        }
    }

    return 0;
}

void EnableDebugPrivilege()
{
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );

    LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );

    CloseHandle( hToken ); 
}


int main()
{
    HANDLE hProc;
    LPVOID start, thread;
    DWORD funcsize;
    HINSTANCE hDll;
    INJECTSTRUCT is;
    DWORD id;

    EnableDebugPrivilege();

    hDll = LoadLibrary(L"KERNEL32.dll");
    is.LoadLibrary = (fpLoadLibrary)GetProcAddress(hDll, "LoadLibraryA");
    is.GetProcAddress = (fpGetProcAddress)GetProcAddress(hDll, "GetProcAddress");
    strcpy_s(is.path, "DLL.dll");
    strcpy_s(is.func, "Funktion");
    funcsize = (DWORD)threadend-(DWORD)threadstart;

    id = FindProcessId(L"explorer.exe");

    hProc = OpenProcess( // Thanks to Cypher
        PROCESS_QUERY_INFORMATION | // Required by Alpha
        PROCESS_CREATE_THREAD | // For CreateRemoteThread
        PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx
        PROCESS_VM_WRITE, // For WriteProcessMemory
        FALSE, id);

    printf("Prozess ID:       %x\n", id);
    printf("Prozess Handle:       %x\n", hProc);

    start = VirtualAllocEx(hProc, 0, funcsize+sizeof(INJECTSTRUCT), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    printf("Memory:               %x\n", start);

    WriteProcessMemory(hProc, start, (LPVOID)&is, sizeof(INJECTSTRUCT), NULL);
    thread = (LPVOID)((DWORD)start+sizeof(INJECTSTRUCT));
    WriteProcessMemory(hProc, thread, (LPVOID)threadstart, funcsize, NULL);
    
    CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0); // returns 0 due to wrong handle
    
    //retuns 5 due to wrong handle ?
    char c[10];
    sprintf(c, "%d", GetLastError());
    printf(c);

    CloseHandle(hProc);

    getchar();
    return 0;
}
```

----------


## serverghost

> For example it is returning 0x3c for both notepad.exe and the explorer.exe which is simply impossible to my knowledge.


It is not only possible but extremely likely that you get the same handle values. Look up the way handles work in Windows and you will see why.




> CreateRemoteThread is failing with error code 5 but I am pretty sure that is due to the wrong handle passed to it by OpenProcess.


Which is expected behavior when you try to call it from a 32bit application for a 64bit process. While 64bit applications are able to perform code injection into both 32bit and 64bit processes 32bit processes are unable to perform code injection into 64bit processes.

----------


## Azzie2k8

> It is not only possible but extremely likely that you get the same handle values. Look up the way handles work in Windows and you will see why.


Okay here I was mistaken that handles were unique on my machine. I just took that for granted. Sorry I will look that up. I will rip my hair out if that was all the issue but thanks.

Edit: So I looked up handles and found this 


> This process handle is private to an application--in other words, process handles cannot be shared. A process also has a process Id which, unlike the Handle, is unique and, therefore, valid throughout the system.


What I don't get is that they are not unique, okay but that they cannot be shared. I mean notepad and explorer arent the apllication right ?

----------


## serverghost

You can read up about kernel objects and the process handle table here:
A Process' Kernel Object Handle Table - 51CTO.COM

Last but not least:


```
CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0); // returns 0 due to wrong handle
```

You are in fact leaking a handle here. If you don't want to actually use the thread handle returned by CreateRemoteThread (or CreateThread for that matter) call it like this:


```
CloseHandle(CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0)); // returns 0 due to wrong handle
```

----------


## Azzie2k8

Thank you for your help. I apllied those changes you mentioned. I guess I will go back to crash wow and find out what is causing that  :Big Grin: 

Btw would you recommend another way of injection for wow ? Uh solved that issue now its accessing invalid adresses. This is gonna be a great day for me  :Big Grin:

----------


## serverghost

> What I don't get is that they are not unique, okay but that they cannot be shared. I mean notepad and explorer arent the apllication right ?


For a detailed explanation read the article I linked to above. But to give you a short explanation:

Each process has it's own handle table. The handle table essentially assigns every kernel object (like processes or files for example) you want to access a unique handle value. So the handle value returned by OpenProcess for example is just an index used by Windows to get the address of the actual kernel object you want to access.

So while the handle value 0x3c may exist in process A and B it will most likely reference different kernel objects. This is why handles can't be shared directly by different applications.

This also explains why you get the same handle value no matter what process you open. Since OpenProcess will always return the index to the first free entry in the processes handle table.

---------- Post added at 05:22 AM ---------- Previous post was at 05:07 AM ----------




> Btw would you recommend another way of injection for wow ? Uh solved that issue now its accessing invalid adresses. This is gonna be a great day for me


The way you used is the most flexible and stable. Just be sure to use a 32bit process to inject into another 32bit process and a 64bit process to inject into another 64bit process. While code injection from a 64bit process into a 32bit process works as well it takes a bit more work.

----------


## _Mike

> Which is expected behavior when you try to call it from a 32bit application for a 64bit process. While 64bit applications are able to perform code injection into both 32bit and 64bit processes 32bit processes are unable to perform code injection into 64bit processes.


Not entirely true. You can't just CreateRemoteThread() into a 64bit app directly, but it certainly isn't impossible.

Btw, technically there are no 32bit processes on a 64bit windows ;)

----------


## Azzie2k8

I can't even say if it apropiate to ask for you help again. I am feeling kinda bad but I am getting ERROR_INVALID_ADDRESS(Attempt to access invalid address.) when calling CreateRemoteThread.

I changed the build to 32bit and I am starting the program with admin mode. I have no idea how that is caused and I dont think i will find out tonight...

btw the handle explanation is cool I never knew this.

----------


## boredevil

I´m everything but an expert if it comes to winapi. So i can´t give you detailed informations, without having my injector source by hand. Already forgot how it was done exactly..
Createremotethread was also not working for me. You could google for injection methods using NtCreateThreadEx that did the magic for me on win7.

----------


## _Mike

Inject into something that's running 32bit code, explorer.exe is 64bit code.

----------


## Azzie2k8

> Inject into something that's running 32bit code, explorer.exe is 64bit code.


I injected into Wow which is 32 bit, right ? The error is telling me that the that acces was denied and due to this the code could not be executed. Could this be caused by the code in the dll being corrupt ? Allthough the DLL is pretty much empty besides the main function.

----------


## _Mike

Access denied means just what it says, you don't have permission to do what you're trying to do.
My bet is that your EnableDebugPrivilege function is failing, but since you don't check return values you would never know.
AdjustTokenPrivileges Function (Windows)

----------


## Azzie2k8

> Access denied means just what it says, you don't have permission to do what you're trying to do.
> My bet is that your EnableDebugPrivilege function is failing, but since you don't check return values you would never know.
> AdjustTokenPrivileges Function (Windows)


I thought so too but both functions OpenProcessToken and AdjustTokenPriveleges return true

----------


## _Mike

Are you verifying with GetLastError()? It can fail even if it returns true.

----------


## Azzie2k8

I did but i currently changed alot in the code using boredevils help. LastError always return either 487 oder 5 which both say that access is denied. currently i have a corrupted stack though dunno why though

----------


## _Mike

487 is ERROR_INVALID_ADDRESS (System Error Codes (Windows)), not access denied.
The code you posted in the OP is a bit to messy for me to want to properly read it  :Smile: , but you are overcomplicating things imo.
Just write the name of the dll to the target and CreateRemoteThread into LoadLibrary directly, then get the offset to your function locally, and CreateRemoteThread into that.

----------


## Azzie2k8

> 487 is ERROR_INVALID_ADDRESS (System Error Codes (Windows)), not access denied.
> The code you posted in the OP is a bit to messy for me to want to properly read it , but you are overcomplicating things imo.
> Just write the name of the dll to the target and CreateRemoteThread into LoadLibrary directly, then get the offset to your function locally, and CreateRemoteThread into that.


Maybe you are right and I should really just get to a working version...I will amke a strip down version of it.

----------


## _Mike

I just had a closer look at your code and the main problem I can see is your threadstart function. It's to dependent on specific compiler settings to work, mainly that /RTCs cannot be enabled. (unless you make sure that the crt dll has the same location in both your injector and target, or you relocate the call manually)
There's also
funcsize = (DWORD)threadend-(DWORD)threadstart;
which might be a problem.. As far as I know there's nothing in the C(++) standards that says that functions have to be linked in the same order that they appear in the source code.
Yes, it currently works like that in msvc but it's unreliable to depend on in my opinion.

----------


## Azzie2k8

> I just had a closer look at your code and the main problem I can see is your threadstart function. It's to dependent on specific compiler settings to work, mainly that /RTCs cannot be enabled. (unless you make sure that the crt dll has the same location in both your injector and target, or you relocate the call manually)
> There's also
> funcsize = (DWORD)threadend-(DWORD)threadstart;
> which might be a problem.. As far as I know there's nothing in the C(++) standards that says that functions have to be linked in the same order that they appear in the source code.
> Yes, it currently works like that in msvc but it's unreliable to depend on in my opinion.


Okay thanks alot. I am using a slightly different approach now thanks to Boredevil. Anyways since this problem is solved now I will need to Hook a function to execute my code, right ? I don't want to bother anyone with this but if you already know a good place where I can read up about this I'd be very happy if you posted a link.
Btw thanks to everyone who participated in this thread  :Smile:

----------


## Azzie2k8

I have another issue that I dont understand but I dont want to open a new thread for this.

I try to hook End Scene via MS Detours 1.5 but wow constantly crashes when DetourFunction is called.

What am I doing wrong here ?



```
HRESULT (__stdcall *Real_EndScene)(LPDIRECT3DDEVICE9);

HRESULT __stdcall My_EndScene(LPDIRECT3DDEVICE9 device)
{
	return Real_EndScene(device);
}


UINT CALLBACK Install( LPVOID lpParam)
{	
	DWORD pDevice_1 = *(DWORD*)(0x00C5DF88);
	DWORD pDevice_2 =  *(DWORD*)(pDevice_1 + 0x397C); //This contains another pointer so we will dereference again
	DWORD pDevice = *(DWORD*)pDevice_2; // Pointer to Class VMT 
	DWORD EndScene = *(DWORD*)(pDevice +0xA8); // Offset off EndScene within classes VMT

	Real_EndScene = (HRESULT (__stdcall *)(LPDIRECT3DDEVICE9))DetourFunction((PBYTE)EndScene,(PBYTE)My_EndScene);

	return 0;
}
```

----------


## JuJuBoSc

Because you don't add baseAddress to first offset, as already stated many time.

----------


## Azzie2k8

> Because you don't add baseAddress to first offset, as already stated many time.


uhm I thought that was coming with the 4.whatever patch ? Is it already using ASLR?

----------


## Cheatz0

> uhm I thought that was coming with the 4.whatever patch ? Is it already using ASLR?


4.0.1 - Which is now.

----------


## Azzie2k8

Lol I didnt even know...sry i dont play wow  :Big Grin: 

well then time to go lookup how that one works

----------

