Blizzhackers

Home of the Dupe since 2001

* Login   * Register    * FAQ    * Search

Join us on IRC: #bh@irc.synirc.net (or Mibbit Web IRC)


It is currently Mon Apr 23, 2018 4:34 pm


All times are UTC [ DST ]





Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject:
PostPosted: Thu Feb 22, 2007 6:57 pm 
 
User
User

Joined: Thu Feb 22, 2007 6:52 pm
I realize this thread is a little old, but I'm hoping someone could point me in the right direction. I'm using the CreateRemoteThread method, which works as long as I'm logged in as Administrator. However, if I'm logged in as a regular user, the DLL injection appears to work (i.e., no errors are returned or set by any of the functions used to inject the DLL), but the DLLMain routine is never executed.

I tried changing the OpenProcess flags to PROCESS_ALL_ACCESS but that didn't work.

Any suggestions?

EDIT: I should mention that after injection, even as regular user, GetLastError() returns 0.

Top
 Profile  
 Post subject:
PostPosted: Thu Feb 22, 2007 8:27 pm 
 
User
User

Joined: Thu Feb 22, 2007 6:52 pm
I'm an idiot. }:p

Turns out it's a path problem. For some reason, when run as a regular user it couldn't find the hook DLL but it could as Administrator. And the bizarre thing is that no "last error" is set when the remotely-executed LoadLibraryA can't find the dll, so it was a little tricky to find this bug. I assume this is because CreateRemoteThread can only indicate whether the thread creation was successful, and not the return value of the function being run in the newly-created thread (which in this case is LoadLibraryA).

Anyway, I just thought I'd mention this here in case someone else comes across the same problem -- ie the DLL seems to be injected because none of the routines signal an error, but in fact it's not injected because the DLL itself couldn't be found.

Top
 Profile  
 Post subject:
PostPosted: Fri Apr 06, 2007 7:12 am 
 
User
User

Joined: Wed Jun 30, 2004 12:45 am
I've been trying to inject a DLL using this method lately but am having a problem getting the DllMain() function to be called. It appears the dll is loaded in correctly as no errors are returned, but I have no way of actually executing the code in the dll. Should I be calling DllMain() myself or should it be called automatically if the DLL is loading correctly? Any help would be appreciated.

_________________
o_O;

Top
 Profile  
 Post subject:
PostPosted: Mon Apr 30, 2007 8:10 am 
 
User
User

Joined: Mon Apr 30, 2007 1:46 am
I'm trying out your CreateRemoteThread concept over the one I currently use, but I trigger my Nod32 scanner :evil: While this method looks fairly interesting, if it is flagged as such through heuristic scanners, is it still acceptable to use for making tools to distribute?

More questions to come about your code once I figure out how to disable Nod32's lock on Visual Studio :roll:

If you want to see the error:
Image

I'll expand on my method later as soon as I fully understand the thread concept.

Top
 Profile  
 Post subject:
PostPosted: Mon Apr 30, 2007 8:48 am 
 
Blizzhacker
Blizzhacker

Joined: Sun May 09, 2004 5:41 am
stimmedcow wrote:
I'm trying out your CreateRemoteThread concept over the one I currently use, but I trigger my Nod32 scanner :evil: While this method looks fairly interesting, if it is flagged as such through heuristic scanners, is it still acceptable to use for making tools to distribute?

More questions to come about your code once I figure out how to disable Nod32's lock on Visual Studio :roll:

If you want to see the error:
Image

I'll expand on my method later as soon as I fully understand the thread concept.


Nod32 is retarded. I'd say just distribute it like this and warn users of the potential error and tell them to disable it or allow it to occur or w/e. You could also just disguise the CreateRemoteThread call(which is no doubt what it's targetting) in some way.

_________________
Physco wrote:
Its all the same haha they try to disprove our religion but they cant, they just point out that theirs a lack of evidence and an overwhelming amount of evidence on their side.

Top
 Profile  
 Post subject:
PostPosted: Mon Apr 30, 2007 9:32 am 
 
User
User

Joined: Mon Apr 30, 2007 1:46 am
Thanks for your fast reply! I like this method, because it'd remove a function I am using now which was a lot of work, but an ungodly sight. However, while I've never seen anything bad myself, using DLLMain as the entry point to your code is not recommended by MSDN. (This isn't a MSDN knows all, we shouldn't think for ourselves kind of issue, so hear me out)

They provide a Best Practices DLL guide, http://www.microsoft.com/whdc/driver/ke ... tprac.mspx , which suggests the following style of DLLMain (my code, their logic)

// DLL entry point, needs to be empty
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
   // Get rid of warnings
   hModule; lpReserved; ulReason;

   // We do not need to know about Threaded events, so disable them (reduces overhead)
   DisableThreadLibraryCalls(hModule);

   // Load the DLL
        return TRUE;
}


Then, a secondary function is created. The DLL exports this function and then the target GetProcAddress's this function and invokes it.

// All startup code goes in OnInitialize
extern "C" __declspec(dllexport) void __cdecl Initialize(void)
{
   // Real Code
}


Now, to accomplish this, by MS standards, I created a function:
// Injects a DLL into a process at the specified address
BOOL InjectDLL(HANDLE hProcess, const char* dllNameToLoad, const char* funcNameToLoad, DWORD injectAddress, DWORD byteCountToReplace, void* userPatch, DWORD userPatchSize, DWORD addrLoadLibrary, DWORD addrGetProcAddress)


* byteCountToReplace has to be at least 5 for a JMP setup
* userPatch has to setup some sort of "continue execution" code at the end
* addrLoadLibrary / addrGetProcAddress are the addresses taken from the specific client (I.e. get address from OllyDbg, hit spacebar on a call)

What the function does is:
1. VirtualAllocEx a block of memory in the process
2. malloc's a block of memory in the loader to build the patch
3. Manually builds the injected ASM code to inject into #2
4. WriteProcessMemory's #2 into the address from #1
5. Sets up the call to #1 based on parameters passed.

Now a little example of what I do in #3 would be:
// Current index of the patch
      DWORD index = 0;

      // Offset for address of the DLL name
      DWORD textOffsetDLLName = 0;
      // Index from start where the DLL name address should be written
      DWORD dllNameIndex = 0;

      // Offset for address of the Function name
      DWORD textOffsetFuncName = 0;
      // Index from start where the Function name address should be written
      DWORD funcNameIndex = 0;

      // Save registers with PUSHAD
      patch[index++] = 0x60;

      // PUSH the place holder for the string of the DLL to inject
      patch[index++] = 0x68;
      dllNameIndex = index;
      memcpy(patch + index, &textOffsetDLLName, sizeof(textOffsetDLLName));
      index += 4;

      // Make a call to LoadLibraryA from the client
      patch[index++] = 0xFF;
      patch[index++] = 0x15;
      memcpy(patch + index, &addrLoadLibrary, sizeof(addrLoadLibrary));
      index += 4;

      // PUSH ESI and load the address of GetProcAddress into it
      patch[index++] = 0x56;
      patch[index++] = 0x8B;
      patch[index++] = 0x35;
      memcpy(patch + index, &addrGetProcAddress, sizeof(addrGetProcAddress));
      index += 4;


There's a bit more, but I essentially rebuild something alone the following lines in a C++ Pseudo style:
dll = "foo";
func = "bar";
LoadLibrary(dll)
ptr = GetProcAddress(dll, bar);
CALL ptr;


The tricky part of what I am doing is since I'm manually injecting the strings, I write out place holders for where they go, then write the strings contents, then go back and update the real offsets.

Now this works all fine, but there are a few things I do not like:
1. Having to get the LoadLib and GetProc addys for the target client manually
2. Having to find 5 bytes in the target exe that I can wipe out and restore in my own code cave before the program executes too far
3. The size of that function

As you can see, I'd be much more interested in using your solution because it's shorter, simpler, and works with way less effort. I can start my thread in suspended state as normal, use the thread method, and be done.

The only issue at hand is that of doing everything in the DLLMain. I myself, with my limited experiences have never ran into any problems using DLLMain, but I figured the "suggested way" was a bit more reliable for this kind of work. I myself don't have a problem with either, I only wrote my function for the fun/challenge.

What are your thoughts about using DLLMain as opposed to the "suggested method". I do understand we are working in a different context then that of a regular DLL using runtime linking, so some ideas are better ignored.

Top
 Profile  
 Post subject:
PostPosted: Mon Apr 30, 2007 10:42 pm 
 
Blizzhacker
Blizzhacker

Joined: Sun May 09, 2004 5:41 am
stimmedcow wrote:
The only issue at hand is that of doing everything in the DLLMain. I myself, with my limited experiences have never ran into any problems using DLLMain, but I figured the "suggested way" was a bit more reliable for this kind of work. I myself don't have a problem with either, I only wrote my function for the fun/challenge.

What are your thoughts about using DLLMain as opposed to the "suggested method". I do understand we are working in a different context then that of a regular DLL using runtime linking, so some ideas are better ignored.


You shouldn't do things from DllMain. The reason for this is that while DllMain is executing, other threads that are registered within DllMain will never start. I think certain objects will never be created also, so your code can deadlock.

What you should do is create a new thread in DllMain and then just return, and let the new thread do all your initialization.

_________________
Physco wrote:
Its all the same haha they try to disprove our religion but they cant, they just point out that theirs a lack of evidence and an overwhelming amount of evidence on their side.

Top
 Profile  
 Post subject: Injecting the magic for fun and profit?
PostPosted: Tue May 08, 2007 11:42 pm 
 
User
User

Joined: Mon May 07, 2007 8:00 pm
Great tutorial. One of the best I have seen. Thanks

Top
 Profile  
 Post subject:
PostPosted: Sat Jun 09, 2007 7:08 pm 
 
User
User

Joined: Sat Jun 09, 2007 7:03 pm
Hi,

All of method work nice but i can't compil the cave version with GCC.

The ASM code has not the good behaviour for GCC.
Can you help me ? :)

And is this method work with Vista ?

Thanks

Top
 Profile  
 Post subject: [Suggestion] Updating GetTargetProcessIdFromProcname
PostPosted: Sat Jul 21, 2007 9:36 am 
 
User
User

Joined: Mon Apr 30, 2007 1:46 am
There's a flaw in the current function that if the process name is not found, the last process that was checked id is returned. To fix this, I suggest the following update:

/*
Required Header Files:
   #include <windows.h>
   #include <tlhelp32.h>
   #include <shlwapi.h>
*/

unsigned long GetTargetProcessIdFromProcname(const char *process)
{
   PROCESSENTRY32 pe = {0};
   HANDLE thSnapshot = {0};
   BOOL retval = false;

   // Try to create a toolhelp snapshot and verify that it was actually created
   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(thSnapshot == INVALID_HANDLE_VALUE)
   {
      MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "Loader", MB_ICONERROR);
      return 0;
   }

   // Need to have this set for the WinAPI structures
   pe.dwSize = sizeof(PROCESSENTRY32);

   // Try to get the first process
    retval = Process32First(thSnapshot, &pe);

   // While we have processes to go through
   while(retval)
   {
      // As soon as we find the process id, return it
      if(StrStrI(pe.szExeFile, process))
      {
         return pe.th32ProcessID;
      }

      // Otherwise, get try to get the next process
      retval = Process32Next(thSnapshot,&pe);
   }

   // If we get here, no process ID was found, so return no
   // process ID instead of the last process found.
   return 0;
}


That way, a check against 0 can stop improper modifications of the wrong process.

----

Next, this is a function not directed at you since this is trivia stuff for you, but just anyone else who is running into problems with multiple instances of a process.

Take for example if you had 5 notepads open, each time you ran the function, you would only get one of those instances and it would be the same one until that particular instance closed.

A little function based on GetTargetProcessIdFromProcname can be constructed to store all process entries in a vector, to which you process each one of those IDs. As a result, you can act on all instances of a process name and not just one.

/*
Required Header Files:
   #include <windows.h>
   #include <tlhelp32.h>
   #include <shlwapi.h>
        #include <vector>
*/
std::vector<PROCESSENTRY32> GetProcessListByName(const char *process)
{
   PROCESSENTRY32 pe = {0};
   HANDLE thSnapshot = {0};
   BOOL retval = false;
   std::vector<PROCESSENTRY32> processList;

   // Try to create a toolhelp snapshot and verify that it was actually created
   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(thSnapshot == INVALID_HANDLE_VALUE)
   {
      MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "Loader", MB_ICONERROR);
      // (Vector is empty)
      return processList;
   }

   // Need to have this set for the WinAPI structures
   pe.dwSize = sizeof(PROCESSENTRY32);

   // Try to get the first process
    retval = Process32First(thSnapshot, &pe);

   // While we have processes to go through
   while(retval)
   {
      // As soon as we find the process id, add it to the vector
      if(StrStrI(pe.szExeFile, process))
      {
         processList.push_back(pe);
      }

      // Otherwise, get try to get the next process
      retval = Process32Next(thSnapshot,&pe);
   }

   // Return the list of processes with this name
   return processList;
}


Take note in this next example if no processes are found, the code that uses the process ids is never executed! So, it all works as it should.

Example Usage:
std::vector<PROCESSENTRY32> ids = GetProcessListByName("notepad.exe");
for(int x = 0; x < ids.size(); ++x)
{
   ULONG id = ids[x].th32ProcessID;

   //
   // Do what you normally do on 'id' now
   //
}


Most of the time all you need is the ID, but why not return the entire vector of all instances in case you need something else ;)

Top
 Profile  
 Post subject:
PostPosted: Fri Aug 17, 2007 5:17 pm 
 
User
User

Joined: Fri Aug 17, 2007 5:13 pm
Registry Method

In order to inject a DLL into processes that link with USER32.DLL, you simply can add the DLL name to the value of the following registry key:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

Its value contains a single DLL name or group of DLLs separated either by comma or spaces. According to MSDN documentation, all DLLs specified by the value of that key are loaded by each Windows-based application running within the current logon session. It is interesting that the actual loading of these DLLs occurs as a part of USER32's initialization. USER32 reads the value of mentioned registry key and calls LoadLibrary() for these DLLs in its DllMain code. However this trick applies only to applications that use USER32.DLL. Another restriction is that this built-in mechanism is supported only by NT and 2K operating systems. Although it is a harmless way to inject a DLL into a Windows processes there are few shortcomings:


In order to activate/deactivate the injection process you have to reboot Windows.
The DLL you want to inject will be mapped only into these processes that use USER32.DLL, thus you cannot expect to get your hook injected into console applications, since they usually don't import functions from USER32.DLL.
On the other hand you don't have any control over the injection process. It means that it is implanted into every single GUI application, regardless you want it or not. It is a redundant overhead especially if you intend to hook few applications only.

Top
 Profile  
 Post subject:
PostPosted: Tue Oct 02, 2007 10:16 pm 
 
User
User
User avatar

Joined: Mon Dec 18, 2006 9:24 pm
Wow, I love this thread. Now I know how these things work. : )
One more thing: what about unloading dll, are methods maintained before the ones u would use or are there any better ones now?

_________________
leech is fun, so as doing something by my own

Top
 Profile  
 Post subject:
PostPosted: Tue Nov 13, 2007 9:50 pm 
 
User
User

Joined: Tue Nov 13, 2007 9:40 pm
My god. I am stunned. Nice tutorial.. Absolutely beautiful... i think im going to cry... no seriously, it's so freakin useful. It was like my first time playing the game Prey, i downloaded it illegally, loved it so much that i actually went to store next day and bought it.

Great job, this clears up so much bullshift... been teaching myself solo through google searches quite literally... As i dont have the cash to buy expensive books and pdf ripoffs. This is a perfect tutorial for anyone wanting to understand the concepts of DLL Injection.
Hard in that it shows you how it works and provokes you to do something with it, and easy enough for an "intermediate" programmer to understand - yet not so easy that the kiddies can just copy and paste their code. Literally the bridge between beginner and intermediate...

Reading your tutorial was almost as good as sex, and my girlfriend is hot so that should give you some idea how great this is.
gamedeception.net was a complete waste of time.
this tutorial is all i needed to go from having "a whole bunch of C/C++ syntax knowledge" and "being able to do something with it".

Thanks again!

*edit
Oh snap! you even gave full source code. Lol i was already overwhelmed with a sense of nirvana, and all I had read was the conceptual info. Now im just.... idunno, i think i need some pot, this is fucking awesome.

Just curious, do you have a donation link for the forums? :P

Top
 Profile  
 Post subject: Dll injection VIA hooks
PostPosted: Wed Mar 12, 2008 1:10 pm 
 
User
User

Joined: Wed Mar 12, 2008 1:04 pm
Hey All,
I'm trying to get the dll injection code using windows hooks. I'm understanding the code pretty well, Its just more of the theory that I don't quite get. Here is the code that I am using:

BOOL InjectDll ( LPCWSTR dllName )
{
    HMODULE hDll;
    FARPROC cbtProcAddr;

   // Load our library
    hDll        = LoadLibrary ( dllName );
   // Get our process
    cbtProcAddr = GetProcAddress ( hDll, "CBTProc" );

   HWND hWnd = FindWindow ( 0, L"Form1" );
   // Set our hooks
    SetWindowsHookEx(WH_CBT, (HOOKPROC)cbtProcAddr, hDll, (DWORD) hWnd);
   
    return TRUE;
}


Now this is what I understand should be happening with the DllMain:
It should get called once from being loaded (vis LoadLibrary), which happens.
Because I'm setting a callback dll, the process that im hooking should also have to load the dll into it's memory (hence the dll injecting). This is not happening. So am I understanding wrong? Here is my dll code:

__declspec( dllexport ) LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    return CallNextHookEx(0, nCode, wParam, lParam);
};

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                )
{
    switch (ul_reason_for_call)
   {
      case DLL_PROCESS_ATTACH:
         MessageBox(NULL, "DLL attached", "None", 0);
         break;
      case DLL_PROCESS_DETACH:
         MessageBox(NULL, "DLL detached", "None", 0);
         break;
    }
    return TRUE;
}


So again... From my understanding, this should be working fine. I'm obviously misunderstanding something. Could someone point me in the right direction?[/code]

Edit: I have installed Process Explorer, which allows me to view the dll's that my processes are accessing, and it does NOT access my injected dll. Could it be that Windows XP no longer allows injection using this method?

Top
 Profile  
 Post subject: Re: Dll injection VIA hooks
PostPosted: Tue Apr 29, 2008 1:37 am 
 
Blizzhacker
Blizzhacker

Joined: Sun May 09, 2004 5:41 am
zenox wrote:
BOOL InjectDll ( LPCWSTR dllName )
{
    HMODULE hDll;
    FARPROC cbtProcAddr;

   // Load our library
    hDll        = LoadLibrary ( dllName );
   // Get our process
    cbtProcAddr = GetProcAddress ( hDll, "CBTProc" );

   HWND hWnd = FindWindow ( 0, L"Form1" );
   // Set our hooks
    SetWindowsHookEx(WH_CBT, (HOOKPROC)cbtProcAddr, hDll, (DWORD) hWnd);
   
    return TRUE;
}


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;
}


Note the difference. Fix the difference. Win.

_________________
Physco wrote:
Its all the same haha they try to disprove our religion but they cant, they just point out that theirs a lack of evidence and an overwhelming amount of evidence on their side.

Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron