• Welcome to Valhalla Legends Archive.
 

Injecting a DLL via SetWindowsHookEx

Started by NicoQwertyu, November 15, 2004, 06:28 PM

Previous topic - Next topic

NicoQwertyu

I've been trying to learn how to inject code into a running process for a long time now, and I still am not able to grasp it.  Yes, I've searched google numerous times  :-[.

This is a simple dll and loader I'm trying to write that will simply force Calculator.exe to load my DLL.

testdll.dll

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>


extern "C" __declspec(dllexport) LRESULT CALLBACK DummieCallback(int nCode, WPARAM wParam, LPARAM lParam);


BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{

switch (dwReason)
{
case DLL_PROCESS_ATTACH: MessageBox(NULL, "DLL injected!", "OK", MB_OK); break;
case DLL_PROCESS_DETACH: MessageBox(NULL, "DLL ejected!", "OK", MB_OK); break;
}

    return TRUE;
}



extern "C" __declspec(dllexport) LRESULT CALLBACK DummieCallback(int nCode, WPARAM wParam, LPARAM lParam)
{

///////////
// This function is used for SetWindowsHookEx.
// We don't really care what it returns, but it's needed for the
// way I'm trying to do this.
//////////

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

}




launcher

#include <windows.h>
#include <stdio.h>

int main()
{
HWND hWndProcess;
DWORD dwThreadId;
HMODULE hInjected;
HOOKPROC hDummieProc;

hWndProcess = FindWindow(NULL, "Calculator");
dwThreadId = GetWindowThreadProcessId(hWndProcess, NULL);

if (hWndProcess == 0 || dwThreadId == 0)
{
MessageBox(NULL, "Unable to gain thread id!", "ERROR", MB_OK);
return 0;
}

hInjected = LoadLibrary("testdll.dll");
hDummieProc = (HOOKPROC)GetProcAddress(hInjected, "DummieCallback");

if (hInjected == NULL || hDummieProc == NULL)
{
MessageBox(NULL, "Unable to inject DLL!", "ERROR", MB_OK);
FreeLibrary(hInjected);
return 0;
}

SetWindowsHookEx(WH_CALLWNDPROC, hDummieProc, (HINSTANCE)hInjected, dwThreadId);
return 0;
}




The few message boxes that pop up are:

DLL Injected!  (LoadLibrary returned)
Unable to inject DLL! (dwThreadId is NULL)
DLL ejected! (my program ends?)


The problem I'm having is: GetProcAddress always returns NULL, and I don't know why.  Any help would be appreciated.



[Edit]
P.S. I'm using SetWindowsHookEx instead of the other couple alternatives for injecting code because I'm on Win ME.

MyndFyre

Quote from: NicoQwertyu on November 15, 2004, 06:28 PM
[Edit]
P.S. I'm using SetWindowsHookEx instead of the other couple alternatives for injecting code because I'm on Win ME.

That's the problem.  You're running on antiquated, unreliable, piece-of-trash code.  :P

I'll take a look at your actual code a little bit later.  For now I have to voice my disdain at Windows "Me".
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

dxoigmn



Adron

Make testdll.def:

library testdll
exports
    DummieCallback

Or, use dumpbin /exports to find what your function is being exported as and pass that exact string to GetProcAddress.

NicoQwertyu

Thanks a bunch, Adron.  I used the second suggestion and found out the export was "_DummieCallback@12".  Now calc.exe is loading my DLL, but I'm having a new problem.

I want to use inline asm to push a string onto the stack, then jmp to an address in calc.exe where it pushes the hWnd of a child window and calls SetWindowText.  I'm having a compile issue though, and I don't understand what's wrong.

Here's the asm that's giving me hell:
(This is called via my Hook)




// ...

char sBuffer[] = "Test";

// ...


__asm
{
mov eax, offset sBuffer
push eax
jmp 0x01004189
}  // <-- Line 38


This is the compile error I get:
testdll.cpp(38) : error C2415: improper operand type


Sorry if this is off-topic in the C++ forum, but I wasn't sure if I should start a new topic similar to this in the asm forum, or add it to this one.

iago

If you want to reasearch, the book "Programming Applications in Microsoft Windows" by Jeffrey Richter has a chapter dedicated to the various methods of dll injection.  SetWindowsHookEx is one, CreateRemoteThread is another (but that's only on 2k+), and I forget the others.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


MyndFyre

Quote from: NicoQwertyu on November 16, 2004, 07:44 PM

// ...
char sBuffer[] = "Test";
// ...
__asm
{
mov eax, offset sBuffer
push eax
jmp 0x01004189
}  // <-- Line 38


This is the compile error I get:
testdll.cpp(38) : error C2415: improper operand type

Compiler error C2415 is discussed here on MSDN.

I can't imagine that Microsoft's implementation of Assembler in the C/++ compiler wouldn't let you use 0x notation for hex numbers.  Perhaps you need to "cast" it to a pointer type?


jmp dword ptr 0x01004189


Let me know how that works out for you. :)
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.


drivehappy


MyndFyre

Quote from: drivehappy on November 17, 2004, 12:43 AM
Does this work?

mov ip, 0x01004189


I didn't know that could work.  What ever happend to CS, and didn't they make an ECS or EIP?

It seems like CS/IP would be somewhat deprecated.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.


iago

You can't jump straight to an address, because jmp is relative.  You either move it into a register and jump to the register or, if you want to preserve registers:
push 0x010004189
ret
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Kp

Quote from: iago on November 17, 2004, 07:31 AMYou can't jump straight to an address, because jmp is relative.

Actually, you can.  It just requires GNU tools and a bit of cleverness. :)
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

MyndFyre

#14
Quote from: iago on November 17, 2004, 07:31 AM
You can't jump straight to an address, because jmp is relative.  You either move it into a register and jump to the register or, if you want to preserve registers:
push 0x010004189
ret


Since when is jmp relative?  I thought there were a plethora of adressing modes, where the one he's using is an absolute.  :/

Edit: nvm, I'm a retard.  I guess I just don't get 32-bit addressing.  I remember that when you jmp'd on the 8086, you did it within the code segment.  It just seems to me that when you're running a 32-bit processor with 32-bit memory address registers, you ought to be able to jump to an absolute memory address.  Of course I can see where protection issues would arise...

:-/
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.