Has anyone tried anything like this before?
Thanks in advance!
-------
David Pochron news...@mindspring.com
Keep in mind that it's a pretty hairy subject though.
Good Luck.
Greg French
David Pochron <news...@mindspring.com> wrote in article
<01bc8789$5a54afa0$c55c0e26@pistol>...
: Is there a way to replace a bunch of functions in a particular DLL with
:
:
:
There should be a way to do this (I'm assuming you're not trying to hook
the
entry point, but rather, other exported functions).
Calls into a DLL go through an indirection table (this is what allows
the app
to _not_ have to relink when you get a new DLL). If you could modify the
indirecdtion table, you could point it to your own functions.
Unknown: is there a single indirection table for all applications using
the
DLL, or one table per app?
Doing this for Win32 DLLs is very difficult. It is possible to do it
within the context of a single application, but very tricky to hook Win32
DLL calls for all client apps. This is mainly do to the protected address
spaces each Win32 process runs in. In fact, Jeff Richter and Matt Pietrek
both devote whole chapters to the problem in their advanced 32-bit Windows
programming books, "Advanced Windows" and "Windows 95 System Programming
Secrets", respectively.
In 16-bit Windows programming, hooking exported function is simple. A big
reason for this is the single, "global" address space all 16-bit code runs
in. A popular MSDN utility, PROCHOOK.DLL, by James Finnegan, provides a
simple API for hooking and unhooking almost *any* 16-bit DLLs exports. It
works extremely well. Don't reinvent the wheel -- if you need to hook
16-bit DLLs, get PROCHOOK.
> Calls into a DLL go through an indirection table (this is what allows
> the app
> to _not_ have to relink when you get a new DLL). If you could modify the
> indirecdtion table, you could point it to your own functions.
No, the export table with the list of DLL function names is what provides
this transparency. If the export name list is what you meant by
"indirection table", then you're right. However, this is another aspect to
Win32 dynamic-linking that really literally "indirection table", but it's
in the client EXEs, not the DLLs (the Pietrek book has a good discussion
about Win32 dynamic linking).
> Unknown: is there a single indirection table for all applications using
> the
> DLL, or one table per app?
One per app. In 32-bit Windows, these is technically only one app per DLL.
Each DLL is individually mapped into each client app's address space.
That doesn't mean the code is duplicated, just that each DLL thinks it only
has one client when it's called since it gets call only in the unique (and
isolated) address space of that client.
Regards,
Matt Arnold
Mark of the Unicorn, Inc.
Remove "don't.spam." prefix to obtain my valid email address.
I have moved the DLL I want to replace off the main search path, and have
replaced it with a DLL with an identical name. The replacement DLL calls
LoadLibrary() with a specific path pointing to the old DLL in its init code
(DllMain()), and it works - I now have the new DLL with the replacement
functions, and access to the old DLL all in the same address space.
I have created a test app that makes an API call to a function I want to
replace in the new DLL, and it works. (Even though I am still linking with
the original DLL's .lib file!) However, I can't call any functions I
haven't replaced - I get a dialog popping up saying it can't find function
<xxxx> during runtime. This was expected.
What I'd like to do now is use GetProcAddress() repeatedly in the DllMain()
function in my new DLL with the handle to the old DLL I got from
LoadLibrary() and get all the addresses of all the functions I don't intend
to replace in the old DLL. Then, I'd like to take those addresses of those
functions and stuff them into the in-memory lookup table in my new DLL.
So, now the question is: Can a DLL modify it's own function look-up table
in memory, and if so, where is it located in the process' address space?
Alternatively, I could code a bunch of naked functions in the new DLL
(assuming naked functions can be exported?) in assembly that simply jump
straight to the address of the old DLL's functions I want to fall through
to, but that means figuring out how the APIs manage their call stack.
(I'd rather do the former, as the x86 is the one microprocessor I haven't
gotten around to learning yet. :-( )
Thanks again, everyone!
-------
David Pochron news...@mindspring.com
Actually, I've done it! I created a bunch of naked functions in a drop-in
DLL with the same name as the DLL I want to replace, and each function has
a single "JMP jumptable[nn]" where [nn] is an index to the original DLL's
function I was to simply drop through to.
Now I can replace just the functions I want, and ignore the rest without
having to figure out parameter lists.
I stuck my replacement DLL (A new WININET.DLL) in place of the original,
and renamed the original WININET.ORG. The new DLL explicitly looks for the
old one and loads it up into whatever process loaded WININET.DLL. Internet
Explorer, MS Mail and News all are still working fine. But....
Two problems still exist:
1) Four of the functions in WININET.DLL are C++ functions (something to do
with Proxy stuff), and I need to figure out how to create a naked function
for them. Is it possible in a .DEF file to remap an export to any function
name? That way I could create a function called "somecpp_func1()" with
nothing but a JMP and simply assign the exported decorated name to it.
2) I use LoadLibrary() to get the original DLL into the process' address
space, and this is done in the new DLL's init code under the PROCESS_ATTACH
case. What about the THREAD_ATTACH case? Do I need to call the old DLL's
init code with a THREAD_ATTACH so any init'ing it needs to do gets done?
For that matter, is there even a way to explicitly call the old loaded
DLL's init code with such a request? Or does the OS know I've called
LoadLibrary() on a DLL and it automatically forwards any new thread init's
to my loaded DLL as well?
Other than that, all is working well! I feel like I finally have the power
to make Windows work the way I want it to!
--
-------
David Pochron news...@mindspring.com
OK, I meant this is very difficult to do without being loaded into the each
client processes address space, which is basically what you've done with
your "replacement" DLL. I was also referring to the difficulty (in the
general case) of hooking Win32 DLL functions directly.
Direct hooks are very easy (relatively) under 16-bit Windows -- just check
out the PROCHOOK example on MSDN. Something like PROCHOOK would be
non-trivial to implement for Win32.
> I stuck my replacement DLL (A new WININET.DLL) in place of the original,
> and renamed the original WININET.ORG. The new DLL explicitly looks for
the
> old one and loads it up into whatever process loaded WININET.DLL.
Internet
> Explorer, MS Mail and News all are still working fine. But....
>
> Two problems still exist:
>
> 1) Four of the functions in WININET.DLL are C++ functions (something to
do
> with Proxy stuff), and I need to figure out how to create a naked
function
> for them. Is it possible in a .DEF file to remap an export to any
function
> name? That way I could create a function called "somecpp_func1()" with
> nothing but a JMP and simply assign the exported decorated name to it.
I don't understand, why can't you just GetProcAddress() the "C++" functions
as well and jump to them from your replacement DLL's entry-points?
There's nothing magic about an exported C++ function. I don't understand
what you're exact problem is. Is it a naming issue or a "thunking" issue?
> 2) I use LoadLibrary() to get the original DLL into the process' address
> space, and this is done in the new DLL's init code under the
PROCESS_ATTACH
> case. What about the THREAD_ATTACH case? Do I need to call the old
DLL's
> init code with a THREAD_ATTACH so any init'ing it needs to do gets done?
No, all DLLs loaded into a process (even indirectly) will receive all the
proper notifications directly from the system. That is, WININET.ORG will
get PROCESS_ATTACH and THREAD_ATTACH messages as necessary automatically.
> For that matter, is there even a way to explicitly call the old loaded
> DLL's init code with such a request? Or does the OS know I've called
> LoadLibrary() on a DLL and it automatically forwards any new thread
init's
> to my loaded DLL as well?
You've got it.
> Other than that, all is working well! I feel like I finally have the
power
> to make Windows work the way I want it to!
Yes, your technique is fine until someone else comes along and want's to
replace WININET.DLL using a different method.
I'm doing something similar right now, but in pascal... Technique should
be the same though.
Basically:
When your application starts:
Dynamically load the DLL containing replacement functions
Get the EXE image base using GetModuleHandle
Get the original DLL address using same
Use GetProcAddress to retrieve the addresses of the functions you wish
to replace
Locate the '.idata' section in the app, and scan it as an array of
DWORDs for the addresses of the original functions.
When an address is found, use VirtualProtect to modify protection to
EXECUTE_READWRITE, and replace the DWORD with the address of the
replacement function.
If you want to clean up, restore the protection
Regards,
Erik.
--
Independent contracting - Development of applications and drivers
for DOS, Win 3.1, Win 95, Win NT.
Visit http://www.info-pro.no/sperling for some free Delphi source.
Erik Sperling Johansen <er...@info-pro.no>
>Matt Arnold <marnold@don't.spam.motu.com> wrote in article
>>
>> Doing this for Win32 DLLs is very difficult. It is possible to do it
>> within the context of a single application, but very tricky to hook Win32
>> DLL calls for all client apps.
>
>Actually, I've done it! I created a bunch of naked functions in a drop-in
>DLL with the same name as the DLL I want to replace, and each function has
>a single "JMP jumptable[nn]" where [nn] is an index to the original DLL's
>function I was to simply drop through to.
Check out the ALIAS directive of MASM. It tells the linker to simply
replace one symbol name with another -- no calling or jumping
involved. Don't know if it will work with the COFF linker though.
>Matt Arnold <marnold@don't.spam.motu.com> wrote in article
>>
>> Doing this for Win32 DLLs is very difficult. It is possible to do it
>> within the context of a single application, but very tricky to hook Win32
>> DLL calls for all client apps.
There is some code that Matt Petriek (spelling?) made
available that does this flawlessly. This was for NT. It didn't
work when I first used it. I had to do one thing extra. He
modifies a DLL/EXE on the fly. I had to change the write
privileges on the area of memory I was writing to with a function
called VirtualProtect or something like that. Sorry I can't
remember the exact API name. I'm also in a location where I don't
have my references.
>
>Actually, I've done it! I created a bunch of naked functions in a drop-in
>DLL with the same name as the DLL I want to replace, and each function has
>a single "JMP jumptable[nn]" where [nn] is an index to the original DLL's
>function I was to simply drop through to.
>
>Now I can replace just the functions I want, and ignore the rest without
>having to figure out parameter lists.
>
>I stuck my replacement DLL (A new WININET.DLL) in place of the original,
>and renamed the original WININET.ORG. The new DLL explicitly looks for the
>old one and loads it up into whatever process loaded WININET.DLL. Internet
>Explorer, MS Mail and News all are still working fine. But....
>
>Two problems still exist:
>
>1) Four of the functions in WININET.DLL are C++ functions (something to do
>with Proxy stuff), and I need to figure out how to create a naked function
>for them. Is it possible in a .DEF file to remap an export to any function
>name? That way I could create a function called "somecpp_func1()" with
>nothing but a JMP and simply assign the exported decorated name to it.
I couldn't figure out a way to do it. IMPLIB used to take a
DLL and created an import library but you can't do that anymore.
You need the original DEF file (someone please tell me I'm
wrong).
However, I wrote a similar DLL for Winsock which works quite
well. In cases where I could not figure out a function signature
I took my best shot by assuming this:
In the 32 bit world it's a good bet that EVERY parameter is 4
bytes in size. Rarely would one pass an entire structure/union,
and all other parameters are passed on the 32 bit stack. In fact,
it may be that even structures are passed this way internally (as
pointers) even though you don't code it that way.
This was a while ago, but if you run "dumpbin" or "lib" on a
dll binary (I forgot which one) it will tell you the stack size
of ALL the parameters passed. It's a number that appears after an
@ sign. Just divide that number by 4 bytes and that gives you the
number of parameters, and thus, the signature you can use.
anyfunction( void* p1, void* p2, void* p3)
{
originalfunction( p1, p2, p3);
}
Since you are only intercepting and passing on this function,
you don't need to know the specifics of the parameters, only
their size and count.
The above approach worked and I never apparently had a
problem intercepting undocumented functions.
Or just use dumpbin to get the offset in the DLL of the routine in
question and look at the return instruction of the routine to see
how much the routine pops off the stack, i.e. ret 4 -> 1 parameter,
ret 8 -> 2 parameters, etc... This should work regardless of
the calling convention.
-------------------------------------------------------------------------
Gary Stephany Required disclaimer: Any opinions
Marquette Medical Systems, Inc. are my own and not necessarily
gary.s...@mail.mei.com those of my employer.
I've got a problem. I simply should (via VB, possibly) to replace
some functions with a simple 'exit'. For example i do want to
disable the file requester. If an applications should perform
a 'save as' function... i need to simulate an ESC key from the user.
Is there anyone here who can help me ? I'm in big trouble.
Thanks in advance.
Could you please explain exactly what you're programming? Are you
trying to automate any shrink-wrapped packages, like ms-word? If so,
it's very easy to disable such functions...
mike
Your technique won't work with my DLL's because I use a common exit point
for all DLL's and the ret instruction is always 0. I actually modify the
stack pointer based on a dynamic value, so I couldn't compile in the value
in the Ret call. (I guess I could have had a table of Ret calls for each
possible return value and jump to the correct one. Or better yet, create
the stub dynamically using VirtualMemory functions and execute it.) Oh
well. Too late, I guess.
Gary Stephany <gary.s...@mail.mei.com> wrote in article
<33CF9A...@mail.mei.com>...