Network: WoW Gold | WoW Accounts | MPS Games | FPSowned
MMOwned - World of Warcraft Exploits, Hacks, Bots and Guides
Homepage »      Register »      Hall of Fame »      Ranks And Awards »      Advertise »      Marketplace »
 
Sign up



Do you like this excellent information? Then Donate HERE to remove ads and support the MMOwned community.


Go Back   MMOwned - World of Warcraft Exploits, Hacks, Bots and Guides > Programming > Programming section > C and C++

C and C++ Discussions about C and C++

Reply
 
LinkBack Thread Tools
  #1  
Old 03-30-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
Codes [Tutorial] DLL Injection

This was a post from the now-defunct site darawk.com. It was able to be resurrected from an internet archive site. It seems to be one of the better guides on injection, due to how thorough it is and it uses acceptable coding practices. I hope this can be of use to some of you who want to start your career and do some fun things with injection. Enjoy.



Introduction


In this tutorial i'll try to cover all of the known methods(or at least, those that I know =p) of injecting dll's into a process.
Dll injection is incredibly useful for TONS of stuff(game hacking, function hooking, code patching, keygenning, unpacking, etc..).
Though there are scattered tutorials on these techniques available throughout the web, I have yet to see any complete tutorials detailing
all of them(there may even be more out there than I have here, of course), and comparing their respective strength's and weakness's.
This is precisely what i'll attempt to do for you in this paper. You are free to reproduce or copy this paper, so long as proper
credit is given and you don't modify it without speaking to me first.


The CreateRemoteThread method


I've used this in tons of stuff, and I only recently realized that a lot of people have never seen it, or know how to do it.
I can't take credit for thinking it up...I got it from an article on codeproject, but it's a neat trick that I think more
people should know how to use.

The trick is simple, and elegant. The windows API provides us with a function called CreateRemoteThread(). This allows you
to start a thread in another process. For our purposes, i'll assume you know how threading works, and how to use functions like
CreateThread(if not, you can go here ). The main disadvantage of this method is that it will work only on windows NT and above.
To prevent it from crashing, you should use this function to check to make sure you're on an NT-based system(thanks to CatID for
pointing this out):
Code:
bool IsWindowsNT()

{

        // check current version of Windows

        DWORD version = GetVersion();

        // parse return

        DWORD majorVersion = (DWORD)(LOBYTE(LOWORD(version)));

        DWORD minorVersion = (DWORD)(HIBYTE(LOWORD(version)));

        return (version < 0x80000000);

}
The MSDN definition for CreateRemoteThread is as follows:
Code:
HANDLE CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, 

                                                   LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, 

                                                   LPDWORD lpThreadId );
So, it's essentially CreateThread, with an hProcess argument, so that we can tell it in which process to create the new thread.
Now, normally we would want to start the thread executing on some internal function of the process that we are interacting with.
However, to inject a dll, we have to do something a little bit different.

Code:
BOOL InjectDLL(DWORD ProcessID)

{

        HANDLE Proc;

        char buf[50]={0};

        LPVOID RemoteString, LoadLibAddy;

        if(!ProcessID)

                return false;

        Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID);

        if(!Proc)

        {

                sprintf(buf, "OpenProcess() failed: %d", GetLastError());

                MessageBox(NULL, buf, "Loader", NULL);

                return false;

        }

        LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

        WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME,strlen(DLL_NAME), NULL);

        CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);    

        

        CloseHandle(Proc);

        return true;

}
This code, calls CreateRemoteThread() with a lpStartAddress of LoadLibrary(). So, it starts a new thread in the remote process
and executes the LoadLibrary() function. Luckily for us, this function takes only one argument, the name of the dll to load. We can
pass this in the arg field of CreateRemoteThread(). However, there is a minor dilemma. Since this thread will not be executing in
our address space, it won't be able to refer to strings(such as the name of the dll) that are in our address space. So, before calling
CreateRemoteThread(), we have to allocate space in the other process, using VirtualAllocEx(), and write our string there. Finally,
we pass the pointer to the string inside the remote process in the single arg field of CreateRemoteThread(), and voila...Our dll is
now loaded and running smoothly within the remote process. This is the generic loader program I use whenever I need to load a dll.





The SetWindowsHookEx method


The SetWindowsHookEx method is a little bit more intrusive than the first, and creates more of a commotion in the injected
process, which we normally don't want. However, it is a little bit easier to use than the first, and does have it's own advantages
(like being able to inject into every process on the system in one shot). The SetWindowsHookEx() function is designed to allow you
to "hook" windows messages for a given thread. This requires that you inject a dll into that process's address space, so
SetWindowsHookEx() handles all that for us. The dll must have a function for the hook that it created though, otherwise it will
crash.

Code:
HHOOK SetWindowsHookEx(   

        int idHook,

        HOOKPROC lpfn,

        HINSTANCE hMod,

        DWORD dwThreadId

);

idHook is just that, the ID of the message that we want to hook. There are many of them(for a complete list, go
here ), however we'll want to use one that's as unintrusive as possible, and has the least likelihood of causing alarm bells to
go off in any AV software(SetWindowsHookEx is the staple of all ring3 keyloggers). The WH_CBT message seems innocuous enough.


WH_CBT
Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application. For more information,
see the CBTProc hook procedure.

--MSDN


So, we'll need to create a placebo CBT hook proc in our dll, so that when the hook is called, we can handle it properly.

Code:
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)

{

        return CallNextHookEx(0, nCode, wParam, lParam);

};

All we're doing is calling the next hook in the chain of hooks that exist for this message. Getting back to the SetWindowsHookEx()
function, the next parameter we see is lpfn. lpfn is exactly as it sounds "long pointer to function". That's a pointer to our CBT
hook proc function. So, to get this, we'll have to either hardcode the address, or load the dll first ourselves. Hardcoding anything
is a bad idea, so we'll load the dll using LoadLibrary(), and use GetProcAddress() to get the address of our function.


Code:
HMODULE hDll;

unsigned long cbtProcAddr;

hDll            = LoadLibrary("injected.dll");

cbtProcAddr = GetProcAddress(hDll, "CBTProc");
Now, in cbtProcAddr we have the address of our function. Parameter 3, of SetWindowsHookEx() is a handle to our dll, we've
already obtained this in the process of getting the address of CBTProc(hDll is a handle to our dll, returned by LoadLibrary). Now,
there is only one parameter left in the SetWindowsHookEx() function, the dwThreadId parameter. If you want to inject your dll into
every process on the system(useful for global function hooks, keyloggers, trojans, rootkits, etc..) you can simply specify 0 for
this parameter. If you want to target a specific process, you'll need to get the ID of one of it's threads. There are many ways
of doing this, and i'll try to enumerate as many as I can think of in Appendix B. So,
to put it all together into one neat little function:

Code:
BOOL InjectDll(char *dllName)

{

        HMODULE hDll;

        unsigned long cbtProcAddr;

        hDll            = LoadLibrary(dllName);

        cbtProcAddr = GetProcAddress(hDll, "CBTProc"); 

        SetWindowsHookEx(WH_CBT, cbtProcAddr, hDll, GetTargetThreadIdFromWindow("targetApp"));

   

        return TRUE;

}

The code cave method

Instead of exploiting a windows API function to force the process to load our Dll, this time we'll allocate a little chunk
memory inside the target application, and inject a little stub that loads our dll. The advantage of this approach is that it
will work on any version of windows, and it's also the least detectable of any of the methods mentioned thus far. Our stub will
look like this:
Code:
__declspec(naked) loadDll(void)

{

        _asm{

                 push 0xDEADBEEF          //placeholder, we'll replace it with the real return address once we know it

                         pushfd                   //save the flags

                 pushad                   //save the registers

                 push 0xDEADBEEF          //placeholder, we'll overwrite it with the address of the string

                         mov eax, 0xDEADBEEF  //we'll overwrite this with the real address of LoadLibrary in a bit

                         call eax                 //call LoadLibrary

                         popad                            //restore the registers

                 popfd                    //restore the flags

                         ret                      //jump to the value that was pushed at the beginning

                 }

}
0xDEADBEEF is just there to mark addresses that we can't know beforehand, and have to patch-in at runtime. Ok, let's make a list
of the things that we need to do to make this work:


- Allocate space for the stub - Allocate space for the name of the dll - Suspend the main thread of our target - Get the address of the next instruction to be executed(need this for the next step) - Patch the proper address to return to in the stub - Patch the address of the dll name - Patch the address of LoadLibrary - Set the address of the next instruction to be executed in our target's thread, to the address of the beginning of our stub - Resume the target's thread



To allocate space inside the target, we'll use VirtualAllocEx(). We'll need to open a handle to the process
with the VM_OPERATION privelege specified, in order to do this. For our dllName string, we'll only need read and write priveleges.
For the stub however, we'll need read, write, and execute priveleges. Then we'll write in our dllName string, so that we can reference
it from the stub once it's inserted.

Code:
void *dllString, *stub;

        unsigned long wowID;

        HANDLE hProcess

        

        wowID   = GetTargetProcessIdFromProcname(PROC_NAME);            //See Appendix A for 

                                                                        //this function

        hProcess = OpenProcess((PROCESS_VM_WRITE | PROCESS_VM_OPERATION), false, wowID);

        dllString = VirtualAllocEx(hProcess, NULL, (strlen(DLL_NAME) + 1), MEM_COMMIT, PAGE_READWRITE);

        stub      = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

        WriteProcessMemory(hProcess, dllString, DLL_NAME, strlen(DLL_NAME), NULL);
To accomplish our next few tasks, we'll need a handle to one of our target's threads. We can use the functions from Appendix B
to get the ID of one such thread, and then use the OpenThread API to get a handle. We'll need to be able to get and set context, and
also suspend and resume the thread.

Code:
unsigned long threadID;

        HANDLE hThread;

        threadID = GetTargetThreadIdFromProcname(PROC_NAME);

        hThread   = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID);
Now, we need to pause the thread in order to get it's "context". The context of a thread is the current state of all of it's
registers, as well as other peripheral information. However, we're mostly concerned with the EIP register, which points to the
next instruction to be executed. So, if we don't suspend the thread before retrieving its context information, it'll continue
executing and by the time we get the information, it'll be invalid. Once we've paused the thread, we'll retrieve it's context
information using the GetThreadContext() function. We'll grab the value
of the current next instruction to be executed, so that we know where our stub should return to. Then it's just a matter of
patching up the stub to have all of the proper pointers, and forcing the thread to execute it.

Code:
SuspendThread(hThread);

        ctx.ContextFlags = CONTEXT_CONTROL;

        GetThreadContext(hThread, &ctx);

        oldIP   = ctx.Eip;

        ctx.Eip = (DWORD)stub;                                          //Set the EIP of the context to the address of our stub

        ctx.ContextFlags = CONTEXT_CONTROL;

        VirtualProtect(loadDll, stubLen, PAGE_EXECUTE_READWRITE, &oldprot);     //Right now loadDll is code, which isn't writable.  We need         

                                                                                //to change that.

        memcpy((void *)((unsigned long)loadDll + 1), &oldIP, 4);        //Patch the first push instruction

        memcpy((void *)((unsigned long)loadDll + 8), &dllString, 4);    //Patch the 2nd push instruction

        memcpy((void *)((unsigned long)loadDll + 13), &loadLibAddy, 4); //Patch the mov eax, 0xDEADBEEF to mov eax, LoadLibrary

        WriteProcessMemory(hProcess, stub, loadDll, stubLen, NULL);     //Write the stub into the target

        SetThreadContext(hThread, &ctx);                                //Set the new context of the target's thread

        ResumeThread(hThread);                                          //Let the target thread continue execution, starting at our stub
All that's left now, is to cleanup the evidence. Before we do that though, we should pause the injector for a bit, to be sure
that the target has time to execute our stub(don't want any nasty race conditions). We'll use Sleep() to pause for 8 seconds before
unmapping the memory that we allocated, and exiting the injector.

Code:
   Sleep(8000);

        VirtualFreeEx(hProcess, dllString, strlen(DLL_NAME), MEM_DECOMMIT);

        VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT);

        CloseHandle(hProcess);

        CloseHandle(hThread);
This method should work on any version of windows, and should be the least likely to trigger any A/V alarms or cause the program
to malfunction. If you can understand it and implement it properly, this is definitely the best of the three methods.




Appendix A - Methods of obtaining a process Id

If the process you're targeting has a window, you can use the FindWindow function, in conjunction with GetWindowThreadProcessId,
as shown here:

Code:
unsigned long GetTargetProcessIdFromWindow(char *className, char *windowName)

{

        unsigned long procID;

        HWND targetWnd;

        targetWnd = FindWindow(className, windowName);

        GetWindowThreadProcessId(targetWnd, &procId);

        

        return procID;

}
If you only know the name of the executable file or it just doesn't have a window:

Code:
unsigned long GetTargetProcessIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot;

   BOOL retval, ProcFound = false;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

        retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   return pe.th32ProcessID;

}
Appendix B - Methods of obtaining a thread Id

If the process you're targeting has a window, you can use the FindWindow function, in conjunction with GetWindowThreadProcessId
and the toolhelp API, as shown here:

Code:
unsigned long GetTargetThreadIdFromWindow(char *className, char *windowName)

{

        HWND targetWnd;

        HANDLE hProcess

        unsigned long processId, pTID, threadID;

        targetWnd = FindWindow(className, windowName);

        GetWindowThreadProcessId(targetWnd, &processId);



        _asm {

        mov eax, fs:[0x18]

        add eax, 36

        mov [pTID], eax

        }

        hProcess = OpenProcess(PROCESS_VM_READ, false, processID);

        ReadProcessMemory(hProcess, (const void *)pTID, &threadID, 4, NULL);

        CloseHandle(hProcess);

        return threadID;

}
If you only know the name of the executable of your target, then you can use this code to locate it:

Code:
unsigned long GetTargetThreadIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot, hProcess;

   BOOL retval, ProcFound = false;

   unsigned long pTID, threadID;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

        retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   CloseHandle(thSnapshot);

   

        _asm {

                mov eax, fs:[0x18]

                add eax, 36

                mov [pTID], eax

        }

        hProcess = OpenProcess(PROCESS_VM_READ, false, pe.th32ProcessID);

        ReadProcessMemory(hProcess, (const void *)pTID, &threadID, 4, NULL);

        CloseHandle(hProcess);

        return threadID;

}

Appendix C - CreateRemoteThread complete example source code


Code:
#include <windows.h>

#include <stdio.h>

#include <tlhelp32.h>

#include <shlwapi.h>

#define PROCESS_NAME "target.exe"

#define DLL_NAME "injected.dll"



//I could just use PROCESS_ALL_ACCESS but it's always best to use the absolute bare minimum of priveleges, so that your code works in as 

//many circumstances as possible.

#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)

  

BOOL WriteProcessBYTES(HANDLE hProcess,LPVOID lpBaseAddress,LPCVOID lpBuffer,SIZE_T nSize);

BOOL LoadDll(char *procName, char *dllName);

BOOL InjectDLL(DWORD ProcessID, char *dllName);

unsigned long GetTargetProcessIdFromProcname(char *procName);

bool IsWindowsNT()

{

        // check current version of Windows

        DWORD version = GetVersion();

        // parse return

        DWORD majorVersion = (DWORD)(LOBYTE(LOWORD(version)));

        DWORD minorVersion = (DWORD)(HIBYTE(LOWORD(version)));

        return (version < 0x80000000);

}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

        if(IsWindowsNT())

                LoadDll(PROCESS_NAME, DLL_NAME);

        else

        MessageBox(0, "Your system does not support this method", "Error!", 0);

        return 0;

}



BOOL LoadDll(char *procName, char *dllName)

{

        DWORD ProcID = 0;

        ProcID = GetProcID(procName);

        if(!(InjectDLL(ProcID, dllName)))

                MessageBox(NULL, "Process located, but injection failed", "Loader", NULL);

        

        return true;

}

BOOL InjectDLL(DWORD ProcessID, char *dllName)

{

        HANDLE Proc;

        char buf[50]={0};

        LPVOID RemoteString, LoadLibAddy;

        if(!ProcessID)

                return false;

        Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID);

        if(!Proc)

        {

                sprintf(buf, "OpenProcess() failed: %d", GetLastError());

                MessageBox(NULL, buf, "Loader", NULL);

                return false;

        }

        LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

        WriteProcessMemory(Proc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL);

                CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);    

        

        CloseHandle(Proc);

        return true;

}

unsigned long GetTargetProcessIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot;

   BOOL retval, ProcFound = false;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

   retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   return pe.th32ProcessID;

}

Appendix D - SetWindowsHookEx complete example source code


Code:
#include <windows.h>

#include <tlhelp32.h>

#define PROC_NAME "target.exe"

#define DLL_NAME "injected.dll"

void LoadDll(char *procName, char *dllName);

unsigned long GetTargetThreadIdFromProcname(char *procName);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

        LoadDll(PROC_NAME, DLL_NAME);

        return 0;

}

void LoadDll(char *procName, char *dllName)

{

        HMODULE hDll;

        unsigned long cbtProcAddr;

        hDll            = LoadLibrary(dllName);

        cbtProcAddr = GetProcAddress(hDll, "CBTProc"); 

        SetWindowsHookEx(WH_CBT, cbtProcAddr, hDll, GetTargetThreadIdFromProcName(procName));

   

        return TRUE;

}

unsigned long GetTargetThreadIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot, hProcess;

   BOOL retval, ProcFound = false;

   unsigned long pTID, threadID;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

        retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   CloseHandle(thSnapshot);

   

        _asm {

                mov eax, fs:[0x18]

                add eax, 36

                mov [pTID], eax

        }

        hProcess = OpenProcess(PROCESS_VM_READ, false, pe.th32ProcessID);

        ReadProcessMemory(hProcess, (const void *)pTID, &threadID, 4, NULL);

        CloseHandle(hProcess);

        return threadID;

}
Appendix E - Code cave example source code

Code:
#include <windows.h>

#include <tlhelp32.h>

#include <shlwapi.h>

#define PROC_NAME "target.exe"

#define DLL_NAME "injected.dll"

unsigned long GetTargetProcessIdFromProcname(char *procName);

unsigned long GetTargetThreadIdFromProcname(char *procName);

__declspec(naked) loadDll(void)

{

        _asm{

                 push 0xDEADBEEF          //placeholder, we'll replace it with the real return address once we know it

                 pushfd                           //save the flags

                 pushad                           //save the registers

                 push 0xDEADBEEF          //placeholder, we'll overwrite it with the address of the string

                 mov eax, 0xDEADBEEF  //we'll overwrite this with the real address of LoadLibrary in a bit

                 call eax                         //call LoadLibrary

                 popad                            //restore the registers

                 popfd                            //restore the flags

                 ret                              //jump to the value that was pushed at the beginning

                 }

}

__declspec(naked) loadDll_end(void)

{

}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

        void *dllString;

        void *stub;

        unsigned long wowID, threadID, stubLen, oldIP, oldprot, loadLibAddy;

        HANDLE hProcess, hThread;

        CONTEXT ctx;

        

        stubLen = (unsigned long)loadDll_end - (unsigned long)loadDll;

        

        loadLibAddy = (unsigned long)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        wowID   = GetTargetProcessIdFromProcname(PROC_NAME);

        hProcess = OpenProcess((PROCESS_VM_WRITE | PROCESS_VM_OPERATION), false, wowID);

        dllString = VirtualAllocEx(hProcess, NULL, (strlen(DLL_NAME) + 1), MEM_COMMIT, PAGE_READWRITE);

        stub      = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 

        WriteProcessMemory(hProcess, dllString, DLL_NAME, strlen(DLL_NAME), NULL);

        

        threadID = GetTargetThreadIdFromProcname(PROC_NAME);

        hThread   = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID);

        SuspendThread(hThread);

        ctx.ContextFlags = CONTEXT_CONTROL;

        GetThreadContext(hThread, &ctx);

        oldIP   = ctx.Eip;

        ctx.Eip = (DWORD)stub;

        ctx.ContextFlags = CONTEXT_CONTROL;

        VirtualProtect(loadDll, stubLen, PAGE_EXECUTE_READWRITE, &oldprot);

        memcpy((void *)((unsigned long)loadDll + 1), &oldIP, 4);

        memcpy((void *)((unsigned long)loadDll + 8), &dllString, 4);

        memcpy((void *)((unsigned long)loadDll + 13), &loadLibAddy, 4);

        WriteProcessMemory(hProcess, stub, loadDll, stubLen, NULL);

        SetThreadContext(hThread, &ctx);

        ResumeThread(hThread);

        Sleep(8000);

        VirtualFreeEx(hProcess, dllString, strlen(DLL_NAME), MEM_DECOMMIT);

        VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT);

        CloseHandle(hProcess);

        CloseHandle(hThread);

        return 0;

}



unsigned long GetTargetProcessIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot;

   BOOL retval, ProcFound = false;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

        retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   CloseHandle(thSnapshot);

   return pe.th32ProcessID;

}

unsigned long GetTargetThreadIdFromProcname(char *procName)

{

   PROCESSENTRY32 pe;

   HANDLE thSnapshot, hProcess;

   BOOL retval, ProcFound = false;

   unsigned long pTID, threadID;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE)

   {

          MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);

          return false;

   }

   pe.dwSize = sizeof(PROCESSENTRY32);

        retval = Process32First(thSnapshot, &pe);

   while(retval)

   {

          if(StrStrI(pe.szExeFile, procName) )

          {

                 ProcFound = true;

                 break;

          }

          retval        = Process32Next(thSnapshot,&pe);

          pe.dwSize = sizeof(PROCESSENTRY32);

   }

   CloseHandle(thSnapshot);

   

        _asm {

                mov eax, fs:[0x18]

                add eax, 36

                mov [pTID], eax

        }

        hProcess = OpenProcess(PROCESS_VM_READ, false, pe.th32ProcessID);

        ReadProcessMemory(hProcess, (const void *)pTID, &threadID, 4, NULL);

        CloseHandle(hProcess);

        return threadID;

}
Reply With Quote


Donate to remove ads, get your "DONATOR title, and get access to the MMOwned community's elite Shoutbawx.

  #2  
Old 03-30-2009
1814 is offline.
Sergeant
  
 
Join Date: Mar 2008
Posts: 67
Reputation: 17
Points: 622, Level: 1
Points: 622, Level: 1 Points: 622, Level: 1 Points: 622, Level: 1
Level up: 45%, 278 Points needed
Level up: 45% Level up: 45% Level up: 45%
Activity: 0.4%
Activity: 0.4% Activity: 0.4% Activity: 0.4%

[Only registered and activated users can see links. ] ,_,
Reply With Quote
  #3  
Old 03-30-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
What, would you like a tutorial on something else? ¬_¬
Reply With Quote
  #4  
Old 04-09-2009
bsharp is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Apr 2009
Posts: 1
Reputation: 1
I don't understand this at all... all I'm trying to do is simply "inject a dll file" and geta WAR online bot to work. I downloaded wINJECT, and tried to look up how to use it, and to be honest it's confusing the living shit out of me. Isn't there a simple way to inject this dll file thing and just be done with it?
Reply With Quote
  #5  
Old 04-09-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
For simple injection without anticheat circumvention, just use the simple utility RemoteDLL.
(it will actually work fine on wow too)
If you're planning on developing though, you should just write your own. This tutorial convers everything but how to write a DLL.
Reply With Quote
  #6  
Old 04-13-2009
Xarg0's Avatar
Xarg0 is offline.
Knight-Lieutenant
  
 
Join Date: Jan 2008
Location: South Pole
Posts: 345
Reputation: 47
Points: 1,547, Level: 3
Points: 1,547, Level: 3 Points: 1,547, Level: 3 Points: 1,547, Level: 3
Level up: 21%, 553 Points needed
Level up: 21% Level up: 21% Level up: 21%
Activity: 0.8%
Activity: 0.8% Activity: 0.8% Activity: 0.8%

When you install a hook DLL with SetWindowsHookEx you'll need to call UnhookWindowsEx before the targeted programm terminates, otherwise your dll wont be undloaded properly.
__________________
I hacked 127.0.0.1
Reply With Quote
  #7  
Old 04-14-2009
Cypher's Avatar
Cypher is offline.
Kynox's sister's pimp
Legendary User
  
 
Join Date: Apr 2006
Location: ntdll.dll
Posts: 4,567
Nominated 63 Times in 4 Posts
Nominated TOTM/W Award(s): 1
Reputation: 1120
Points: 63,982, Level: 37
Points: 63,982, Level: 37 Points: 63,982, Level: 37 Points: 63,982, Level: 37
Level up: 42%, 2,218 Points needed
Level up: 42% Level up: 42% Level up: 42%
Activity: 19.1%
Activity: 19.1% Activity: 19.1% Activity: 19.1%

"due to how thorough it is and it uses acceptable coding practices."

I hope you don't mean that... Without even looking at it in depth I can see numerous programming errors and potential disasters.
__________________
[Only registered and activated users can see links. ]

Results of MaiN getting trolled in regards to mixing managed and unmanaged code:
Quote:
(4:25:36 PM) MaiN: I really don't care what you think
(4:25:41 PM) Cypher: rifk
(4:25:42 PM) Cypher: trolled
(4:25:47 PM) MaiN: no seriously
(4:25:50 PM) MaiN: I never have
Reply With Quote
  #8  
Old 04-14-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
Please enlighten us on one of them.
Reply With Quote
  #9  
Old 04-16-2009
Cypher's Avatar
Cypher is offline.
Kynox's sister's pimp
Legendary User
  
 
Join Date: Apr 2006
Location: ntdll.dll
Posts: 4,567
Nominated 63 Times in 4 Posts
Nominated TOTM/W Award(s): 1
Reputation: 1120
Points: 63,982, Level: 37
Points: 63,982, Level: 37 Points: 63,982, Level: 37 Points: 63,982, Level: 37
Level up: 42%, 2,218 Points needed
Level up: 42% Level up: 42% Level up: 42%
Activity: 19.1%
Activity: 19.1% Activity: 19.1% Activity: 19.1%

Okay I'll pick one at random.

Code:
hDll            = LoadLibrary("injected.dll");

cbtProcAddr = GetProcAddress(hDll, "CBTProc");
 


Bzzzt! Wrong!
[Only registered and activated users can see links. ]

How about this:
Code:
void* stub;

<insert large gap filled with unrelated code here>

stub      = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
C++ Coding Standards, Item 18.
Declare variable as locally as possible.

I just picked one, but pretty much all the code is written like that.

Code:
#define PROC_NAME "target.exe"
Use of a macro when it's totally unnecessary.
"The first rule about . . [macros] is: don't use them if you do not have to. . . almost every macro demonstrates a flaw in either the programming language or in the program."
Who was it that said that? Oh right, the primary creator of C++!

On top of that, the code has basically zero error handling for the Win32 API, and absolutely zero proper error reporting.

No offence, but it's obvious you're not a competent or fluent C++ programmer (I checked your other threads), so please stop giving advice on topics outside your knowledge.
__________________
[Only registered and activated users can see links. ]

Results of MaiN getting trolled in regards to mixing managed and unmanaged code:
Quote:
(4:25:36 PM) MaiN: I really don't care what you think
(4:25:41 PM) Cypher: rifk
(4:25:42 PM) Cypher: trolled
(4:25:47 PM) MaiN: no seriously
(4:25:50 PM) MaiN: I never have
Reply With Quote
  #10  
Old 04-16-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
You have the audacity to say things like "it's obvious you're not a competent or fluent C++ programmer" just because I'm good at different things than you. I do client and server programming, I'm good at octrees and 3d while you're good at reversing. I'm humble about it, too.

You're just reaching for things to complain about now, such as semantics. Not having anything to do with the logical, functional portion of code.

I'm here trying to help people, offering the only guide that includes all methods I could find that wasn't full of errors. Sure, it's got a few flaws, but they don't effect performance.

Cypher, I know using a macro is considered bad. And I know why.
If you can't tell me and the fine people of this board WHY using a macro is bad, you're a troll.

Since you want to make an issue of it, and you decided to call me out, we shall compare knowledge on general c++.
A test of your knowledge.. Tell me how differently the compiler treats:
#define text "text"
compared to:
static char const*const text = "text";
and WHY #define is considered evil.
Reply With Quote
  #11  
Old 04-16-2009
Cypher's Avatar
Cypher is offline.
Kynox's sister's pimp
Legendary User
  
 
Join Date: Apr 2006
Location: ntdll.dll
Posts: 4,567
Nominated 63 Times in 4 Posts
Nominated TOTM/W Award(s): 1
Reputation: 1120
Points: 63,982, Level: 37
Points: 63,982, Level: 37 Points: 63,982, Level: 37 Points: 63,982, Level: 37
Level up: 42%, 2,218 Points needed
Level up: 42% Level up: 42% Level up: 42%
Activity: 19.1%
Activity: 19.1% Activity: 19.1% Activity: 19.1%

Quote:
Originally Posted by jagged software View Post
You have the audacity to say things like "it's obvious you're not a competent or fluent C++ programmer" just because I'm good at different things than you. I do client and server programming, I'm good at octrees and 3d while you're good at reversing. I'm humble about it, too.

You're just reaching for things to complain about now, such as semantics. Not having anything to do with the logical, functional portion of code.

I'm here trying to help people, offering the only guide that includes all methods I could find that wasn't full of errors. Sure, it's got a few flaws, but they don't effect performance.

Cypher, I know using a macro is considered bad. And I know why.
If you can't tell me and the fine people of this board WHY using a macro is bad, you're a troll.

Since you want to make an issue of it, and you decided to call me out, we shall compare knowledge on general c++.
A test of your knowledge.. Tell me how differently the compiler treats:
#define text "text"
compared to:
static char const*const text = "text";
and WHY #define is considered evil.

Symbol tables.

Dumbass.

You're the one that brought up "acceptable coding practices", all I did was point out that the code was far from acceptable if you conform to modern programming standards and practices. I don't get what you're crying about. Butt-hurt that I called you out?

P.S. Ask a stupid question, get a hostile answer.

P.S.S. Its amusing you could think that question is some kind of test. Talk about basic. C'mon, ask something hard, ask something fun.
__________________
[Only registered and activated users can see links. ]

Results of MaiN getting trolled in regards to mixing managed and unmanaged code:
Quote:
(4:25:36 PM) MaiN: I really don't care what you think
(4:25:41 PM) Cypher: rifk
(4:25:42 PM) Cypher: trolled
(4:25:47 PM) MaiN: no seriously
(4:25:50 PM) MaiN: I never have

Last edited by Cypher; 04-16-2009 at 03:02 PM.
Reply With Quote
  #12  
Old 04-17-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4

And symbol tables is the best reason why you call that #define unacceptable. heh.
Cypher, no code is perfect. Understand this, it's part of the human condition. For example, if you were to post some of your code, I could point out several things that could be improved upon or are not considered standard. If I post my own code, others would be able to find things I overlooked. I'm objective, I realize this.

Quote:
It seems to be one of the better guides on injection, due to how thorough it is and it uses acceptable coding practices.
It's not too far off, it's just got a few imperfections. I agree with you there. But it's a good start for people who don't know what the three main methods of injection are all about.
Using #define with a string is not too bad, because it's just thrown in at compile time exactly as if you were to put it in the code yourself. For example:
SomeFunction("abc"); and #define abc "abc" SomeFunction(abc); compile EXACTLY the same.
Anyways, nuff said, cheers. Have a happy day.
Reply With Quote
  #13  
Old 04-18-2009
Cypher's Avatar
Cypher is offline.
Kynox's sister's pimp
Legendary User
  
 
Join Date: Apr 2006
Location: ntdll.dll
Posts: 4,567
Nominated 63 Times in 4 Posts
Nominated TOTM/W Award(s): 1
Reputation: 1120
Points: 63,982, Level: 37
Points: 63,982, Level: 37 Points: 63,982, Level: 37 Points: 63,982, Level: 37
Level up: 42%, 2,218 Points needed
Level up: 42% Level up: 42% Level up: 42%
Activity: 19.1%
Activity: 19.1% Activity: 19.1% Activity: 19.1%

" And symbol tables is the best reason why you call that #define unacceptable. heh."

You say that then don't provide what you consider to be the better explanation?

For a macro function yes there are much better explanations. But for a hard-coded c-style string the difference is far from huge.

There's a difference between "no code is perfect" and "this code is awful". So how about you stop misrepresenting me because you've got nothing to go on.

What you said is VERY far off. Sure it's a good start, but it is NOT thorough and NOT acceptable C++.
__________________
[Only registered and activated users can see links. ]

Results of MaiN getting trolled in regards to mixing managed and unmanaged code:
Quote:
(4:25:36 PM) MaiN: I really don't care what you think
(4:25:41 PM) Cypher: rifk
(4:25:42 PM) Cypher: trolled
(4:25:47 PM) MaiN: no seriously
(4:25:50 PM) MaiN: I never have
Reply With Quote
  #14  
Old 04-18-2009
jagged software is offline.
Site n00b.. (A leecher if I've been here for more than a month and can't earn 5 rep)
  
 
Join Date: Feb 2009
Posts: 48
Reputation: -4
Okay everyone, it has come to my attention that this code is garbage. My bad, I apologize! To make this code acceptable C++, please change the following line:
#define PROC_NAME "target.exe"
to:
static char const*const PROC_NAME = "target.exe";


Because according to Cypher, it will f*** up your SYMBOL TABLES@! oh noes!

You ever use NULL in your code Cypher? ((You use it frequently in your released sources.)) Because then you'd be doing the same f***ing thing as you're attacking. You'd be using a f***ing macro.
#define NULL 0
Just use 0 instead. Hypocrite.

Macros are bad because they do not do native type checking. They're also messy when you have to use multiple lines, and if you're doing logical checking from within a macro (such as an IF statement) you would get much better performance out of doing it in a function, because of optimization. Also, macros can be bad because of token concatenation. But that is beyond the scope of this article. But those are the only reasons macros are bad. According to Bjarne Stroustrup, avoid them if you can: "I really hate macros. Yes they're useful sometimes, and yes I use them."

Gone are the days of C, when macros were quicker, and faster. Now, there's a ton of C++ functionality that macros will just plain f*** up. That's why they're bad.

Anyways, let me summarize this post into a readers digest version for newcomers:
Jaggedsoft: Here's a spot for you guys to get started. It's acceptable.
Cypher: THAT IS NOT ACCEPTABLE see it has a macroes@! YOU GO TO HELL AND DIE
Jaggedsoft: ok


Edit: Very mature of you to lower my reputation. Programmers are supposed to be objective, not subjective. Whatever fuels that ego of yours.

Last edited by jagged software; 04-18-2009 at 04:33 PM.
Reply With Quote
  #15  
Old 04-19-2009
Xarg0's Avatar
Xarg0 is offline.
Knight-Lieutenant
  
 
Join Date: Jan 2008
Location: South Pole
Posts: 345
Reputation: 47
Points: 1,547, Level: 3
Points: 1,547, Level: 3 Points: 1,547, Level: 3 Points: 1,547, Level: 3
Level up: 21%, 553 Points needed
Level up: 21% Level up: 21% Level up: 21%
Activity: 0.8%
Activity: 0.8% Activity: 0.8% Activity: 0.8%

@Jagged software:
Don't you need to obtain SeDebugPrivilege before you're trying to inject anything?
__________________
I hacked 127.0.0.1
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are On



All times are GMT -4. The time now is 11:56 PM.




Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514