digitalmars.D.learn - DLL Injection
- "valente500" <valente500 live.com> Feb 07 2012
- maarten van damme <maartenvd1994 gmail.com> Feb 09 2012
- "valente500" <valente500 live.com> Feb 10 2012
- maarten van damme <maartenvd1994 gmail.com> Feb 10 2012
- "valente500" <valente500 live.com> Feb 10 2012
- maarten van damme <maartenvd1994 gmail.com> Feb 11 2012
- "s0beit" <s0beit myg0t.com> Nov 26 2012
- "s0beit" <s0beit myg0t.com> Nov 26 2012
- "s0beit" <s0beit myg0t.com> Dec 01 2012
- "js.mdnq" <js_adddot+mdng gmail.com> Dec 01 2012
- "s0beit" <s0beit myg0t.com> Dec 01 2012
- "s0beit" <s0beit myg0t.com> Dec 01 2012
- maarten van damme <maartenvd1994 gmail.com> Dec 02 2012
- "s0beit" <s0beit myg0t.com> Dec 02 2012
- maarten van damme <maartenvd1994 gmail.com> Dec 03 2012
- "s0beit" <s0beit myg0t.com> Dec 03 2012
- maarten van damme <maartenvd1994 gmail.com> Dec 03 2012
I've been trying for a while now to inject a DLL written in D
into another process, and I just haven't been able to get it
working.
Here's the code for the DLL:
import std.c.windows.windows;
import core.sys.windows.dll;
__gshared HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID
pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach(hInstance, true);
*cast(int*)0x22FF3C = 1337;
break;
case DLL_PROCESS_DETACH:
dll_process_detach(hInstance, true);
break;
case DLL_THREAD_ATTACH:
dll_thread_attach(true, true);
break;
case DLL_THREAD_DETACH:
dll_thread_detach(true, true);
break;
default: break;
}
return true;
}
Basically I just copy and pasted the code from the DLL tutorial
on the D website and added the *cast(int*)0x22FF3C = 1337; line.
The process I'm injecting it into has a value at that address
which I want to change.
The problem is that when I inject the DLL into the process with
Winject (a DLL Injector), the value changes fine, but Winject
complains "Injection seemed successful, but DLLMain() never
returned (TIMEOUT)", and then the process crashes 30 seconds
later.
I also tested it with another injector, and the process just
freezes. So I'm wondering how to write a DLL that injects
successfully.
Cheers.
Feb 07 2012
--047d7b3395a58e41fb04b8900073
Content-Type: text/plain; charset=ISO-8859-1
does it ever go past the cast point? what happens when you try{}catch and
print the error out?
I've injected but with writeprocessmemory.
--047d7b3395a58e41fb04b8900073
Content-Type: text/html; charset=ISO-8859-1
does it ever go past the cast point? what happens when you try{}catch and print
the error out?<br>I've injected but with writeprocessmemory.<br><br>
--047d7b3395a58e41fb04b8900073--
Feb 09 2012
Well if I change the DLL_PROCESS_ATTACH case to this:
case DLL_PROCESS_ATTACH:
MessageBoxA(null, "Injected!", "DLL", MB_OK);
g_hInst = hInstance;
dll_process_attach(hInstance, true);
try
{
*cast(int*)0x12FE6C = 1337;
}
catch(Exception e)
{
MessageBoxA(null, "Exception!", "DLL", MB_OK);
}
MessageBoxA(null, "Finished!", "DLL", MB_OK);
break;
then I get the "Injected!" and "Finished!" MessageBox()s popping
up, but not the "Exception!", so yes the code does get past the
cast line (but still crashes). The same thing happens even if I
remove the try/catch block and the cast line altogether.
I changed my post-mortem debugger from the default Dr. Watson to
Visual Studio's just-in-time debugger, and after it displays
"Finished!", I get an unhandled win32 exception in the injected
process.
And yer, I would normally use WriteProcessMemory() for something
this trivial, but I want to eventually do some more advanced
stuff.
Feb 10 2012
--047d7b3395a50391fc04b89e3589 Content-Type: text/plain; charset=ISO-8859-1 strange, does this happen with the corresponding C version? and what happens if you inject a D dll without changing that value? --047d7b3395a50391fc04b89e3589 Content-Type: text/html; charset=ISO-8859-1 strange, does this happen with the corresponding C version?<div>and what happens if you inject a D dll without changing that value?</div><div><br></div> --047d7b3395a50391fc04b89e3589--
Feb 10 2012
Everything works perfectly if I write the DLL in C++ (and I've never had any errors with C++ DLL's before that are similar to this one). If I remove the cast line and MessageBox()'s in the D version, then I still get the error.
Feb 10 2012
--047d7b15aadd977c9904b8ae5f01
Content-Type: text/plain; charset=ISO-8859-1
I've also injected some dll's and when I recompiled them they seemed to
crash the target program too.
this means that no C program will be able to load a dll written in D :s
the test I compiled was
import std.c.windows.windows;
import core.sys.windows.dll;
__gshared HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
default:
dll_thread_detach( true, true );
break;
}
return true;
}
with dmd version 2.055
It used to work. is this a bug/regression? I'm going to upgrade my dmd to
the newest level and try again
--047d7b15aadd977c9904b8ae5f01
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I've also injected some dll's and when I recompiled them they seeme=
d to crash the target program too.<div>this means that no C program will be=
able to load a dll written in D :s</div><div>the test I compiled was</div>
<div><div>import std.c.windows.windows;</div><div>import core.sys.windows.d=
ll;</div><div><br></div><div>__gshared HINSTANCE g_hInst;</div><div><br></d=
iv><div>extern (Windows)</div><div>BOOL DllMain(HINSTANCE hInstance, ULONG =
ulReason, LPVOID pvReserved)</div>
<div>{</div><div>=A0 =A0 switch (ulReason)</div><div>=A0 =A0 {</div><div><s=
pan class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>case DLL_PRO=
CESS_ATTACH:</div><div><span class=3D"Apple-tab-span" style=3D"white-space:=
pre"> </span> =A0 =A0g_hInst =3D hInstance;</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span> =A0 =
=A0dll_process_attach( hInstance, true );</div><div><span class=3D"Apple-ta=
b-span" style=3D"white-space:pre"> </span> =A0 =A0break;</div><div><br></di=
v><div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>cas=
e DLL_PROCESS_DETACH:</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span> =A0 =
=A0dll_process_detach( hInstance, true );</div><div><span class=3D"Apple-ta=
b-span" style=3D"white-space:pre"> </span> =A0 =A0break;</div><div><br></di=
v><div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>cas=
e DLL_THREAD_ATTACH:</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span> =A0 =
=A0dll_thread_attach( true, true );</div><div><span class=3D"Apple-tab-span=
" style=3D"white-space:pre"> </span> =A0 =A0break;</div><div><br></div><div=
<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>default:<=
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span> =A0 =
=A0dll_thread_detach( true, true );</div><div><span class=3D"Apple-tab-span=
" style=3D"white-space:pre"> </span> =A0 =A0break;</div><div>=A0 =A0 }</div=
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span></di=
<div>=A0 =A0 return true;</div><div>}</div></div><div><br></div><div>with d=
md version 2.055</div><div>It used to work. is this a bug/regression? I'=
;m going to upgrade my dmd to the newest level and try again</div>
--047d7b15aadd977c9904b8ae5f01--
Feb 11 2012
I recently had this problem, and I think I've solved it for now
if anyone is still looking for a fix ... it's really ghetto but
it seems to work for me.
extern (Windows) BOOL DllMain(HMODULE hModule, ULONG ulReason,
LPVOID pvReserved)
{
if(ulReason == DLL_PROCESS_ATTACH)
{
DllMainReal(hModule);
core.memory.GC.collect(); //collect garbage before the return
asm
{
mov EAX, 1;
ret; // Don't give the garbage collector the chance to make
things messy
}
}
return TRUE;
}
Nov 26 2012
On Tuesday, 27 November 2012 at 01:01:10 UTC, s0beit wrote:I recently had this problem, and I think I've solved it for now if anyone is still looking for a fix ... it's really ghetto but it seems to work for me. extern (Windows) BOOL DllMain(HMODULE hModule, ULONG ulReason, LPVOID pvReserved) { if(ulReason == DLL_PROCESS_ATTACH) { DllMainReal(hModule); core.memory.GC.collect(); //collect garbage before the return asm { mov EAX, 1; ret; // Don't give the garbage collector the chance to make things messy } } return TRUE; }
Actually completely disregard, what was actually happening was me being stupid. The reason why it didn't fault here is because I totally screwed up the stack and I believe that caused the exception handler to trigger when the DllMain call was finished. I don't know why this would prevent my module from crashing, but it did. It also halted execution of the rest of my code, go figure. No solution for this still. I'll keep working on it, but right now all I've got to go on is invalid memory access in one of the GC's Free functions.
Nov 26 2012
Alright, at the end of my long search I have finally concluded that this is some sort of threading problem. Any D module loaded in a new thread, from a C/++ application will crash. The solution, I believe, in this case might be to hijack the program's "main" thread and execute your LoadLibrary call there. When you call LoadLibrary on a D module from a C++ application's "main" function, everything is fine. When you call it with a newly created thread (CreateThread or CreateRemoteThread) it will crash universally. I have not found a remedy to this issue, but the method to inject your module by hijacking the thread might work. It's an older method of injection since before CreateThread APIs came along, but the basic idea is that you get the handle to the program's primary thread, get the context and force the Eip to your destination which calls LoadLibrary. Then you JMP back to the old Eip. I'll post here if I have any success with it, I am currently too busy to test my theory.
Dec 01 2012
On Saturday, 1 December 2012 at 11:24:51 UTC, s0beit wrote:Alright, at the end of my long search I have finally concluded that this is some sort of threading problem. Any D module loaded in a new thread, from a C/++ application will crash. The solution, I believe, in this case might be to hijack the program's "main" thread and execute your LoadLibrary call there. When you call LoadLibrary on a D module from a C++ application's "main" function, everything is fine. When you call it with a newly created thread (CreateThread or CreateRemoteThread) it will crash universally. I have not found a remedy to this issue, but the method to inject your module by hijacking the thread might work. It's an older method of injection since before CreateThread APIs came along, but the basic idea is that you get the handle to the program's primary thread, get the context and force the Eip to your destination which calls LoadLibrary. Then you JMP back to the old Eip. I'll post here if I have any success with it, I am currently too busy to test my theory.
Would it be possible for you to write wrapper in C that hooks into the process then that wrapper loads up your D code? Since you are saying you can do this in C, and C should be able to interface well with D, it seems like it should work.
Dec 01 2012
On Saturday, 1 December 2012 at 12:29:51 UTC, js.mdnq wrote:On Saturday, 1 December 2012 at 11:24:51 UTC, s0beit wrote:Alright, at the end of my long search I have finally concluded that this is some sort of threading problem. Any D module loaded in a new thread, from a C/++ application will crash. The solution, I believe, in this case might be to hijack the program's "main" thread and execute your LoadLibrary call there. When you call LoadLibrary on a D module from a C++ application's "main" function, everything is fine. When you call it with a newly created thread (CreateThread or CreateRemoteThread) it will crash universally. I have not found a remedy to this issue, but the method to inject your module by hijacking the thread might work. It's an older method of injection since before CreateThread APIs came along, but the basic idea is that you get the handle to the program's primary thread, get the context and force the Eip to your destination which calls LoadLibrary. Then you JMP back to the old Eip. I'll post here if I have any success with it, I am currently too busy to test my theory.
Would it be possible for you to write wrapper in C that hooks into the process then that wrapper loads up your D code? Since you are saying you can do this in C, and C should be able to interface well with D, it seems like it should work.
You can probably make something in D to do that, but I must be clear that it will only work if you're injecting in the main thread. Anything outside of the main thread will crash. If you, say, hook a function that is called by the primary application thread and call your LoadLibrary there it might work fine. I think my method of injection (Context hijack on a main thread) is probably the best to use for D, I'll post some injector code if/when I get that far.
Dec 01 2012
Alright, I was finally able to give it a try: http://s0beit.me/d/d-module-injector/ I released the source code as well as the binary here if anyone wants to try. It worked for me in a game I was playing with.
Dec 01 2012
Thanks, interesting blog :) 2012/12/2 s0beit <s0beit myg0t.com>:Alright, I was finally able to give it a try: http://s0beit.me/d/d-module-injector/ I released the source code as well as the binary here if anyone wants to try. It worked for me in a game I was playing with.
Dec 02 2012
On Sunday, 2 December 2012 at 22:30:56 UTC, maarten van damme wrote:Thanks, interesting blog :) 2012/12/2 s0beit <s0beit myg0t.com>:Alright, I was finally able to give it a try: http://s0beit.me/d/d-module-injector/ I released the source code as well as the binary here if anyone wants to try. It worked for me in a game I was playing with.
Thanks! Please let me know the results if you end up trying it, I want to confirm it works depending on certain conditions.
Dec 02 2012
Strangely, the main in my dll is getting executed multiple times and msvcr71.dll gets injected too. Is this normal? 2012/12/3 s0beit <s0beit myg0t.com>:On Sunday, 2 December 2012 at 22:30:56 UTC, maarten van damme wrote:Thanks, interesting blog :) 2012/12/2 s0beit <s0beit myg0t.com>:Alright, I was finally able to give it a try: http://s0beit.me/d/d-module-injector/ I released the source code as well as the binary here if anyone wants to try. It worked for me in a game I was playing with.
Thanks! Please let me know the results if you end up trying it, I want to confirm it works depending on certain conditions.
Dec 03 2012
On Monday, 3 December 2012 at 11:08:34 UTC, maarten van damme wrote:Strangely, the main in my dll is getting executed multiple times and msvcr71.dll gets injected too. Is this normal?
mcvcr71.dll is probably loaded by your library, I don't know if D uses visual studio dependencies... one would think not... What are you injecting into? Your DLL should only be executed once, I would go as far as to say it's impossible that it's being executed multiple times because calling LoadLibrary multiple times will not invoke the DLL_PROCESS_ATTACH action multiple times, after the initial load it will only return the pre-existing handle. Are you making sure to check if the "dwReason" in DllMain is DLL_PROCESS_ATTACH? If you aren't, it will seem like it's being called multiple times when new threads are created.
Dec 03 2012
Yes, that was the problem :p I have no idea about mcvr71, maybe because of std.process but that isn't that huge a concern
Dec 03 2012









maarten van damme <maartenvd1994 gmail.com> 