[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 436
  • Last Modified:

Writing system DLLs in Borland C++ 5.2

I need to write a system DLL that will be mapped into the Windows virtual address space above 2GB whenever it gets loaded.

My compiled example code from Microsoft Visual C seems to work. Author claimed
that all he did is to tweak the SECTIONS bit in the associated .DEF file, and set the image base.

So I did the same thing in the Borland IDE, only to notice that my DLL file
never gets loaded to my desired base :(

Can somebody please help me... please?


0
ShienShin
Asked:
ShienShin
  • 7
  • 4
1 Solution
 
NickRepinCommented:
Windows is free to load dll to ANY address, not only to those specified in the dll.

Why do you need 2GB?

If you need to share data, it's another question.
0
 
NickRepinCommented:
It seems that you need to create a shared section.

To do this in Borland, place all shared data into the separate .cpp file.

shared.cpp
----------
#pragma option -zR.SHARED
#pragma option -zT

#include <windows.h>

//This is for MS VC only
//#pragma data_seg(".SHARED")

// Any shared data here,
// for example
HHOOK   fip_hHook          = 0;

//This is for MS VC only
//#pragma data_seg()

..DEF
----
SECTIONS
  .SHARED CLASS '' READ WRITE SHARED
0
 
NickRepinCommented:
Dynamic Loading of Win32 DLLs
Last reviewed: December 17, 1996
Article ID: Q90745  
The information in this article applies to:
Microsoft Win32 Application Programming Interface (API) included with:


    - Microsoft Windows NT versions 3.1, 3.5, 3.51, 4.0
    - Microsoft Windows 95 version 4.0

.....


Each DLL has a preferred base address, specified at link time. If the address space from the base address to the base address plus image size is unavailable, then the DLL is loaded elsewhere and fixups will be applied. There is no way to specify a load address at load time.


......

 
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
ShienShinAuthor Commented:
Thanks heaps Nick :)  Haven't tried
out your codes yet, but please inform me
if I got the wrong idea.

Basically, I'm writing an API hook with
the help of a third party library. My
DLL needs to load at above 2GB in
virtual address space, otherwise the
installed hook will only effect the
loader application.

Today I noticed that if I link my code
with Microsoft's linker, my DLL file
goes up to shared memory nicely. With
Borland's linker, the API hook maps into
my own address space (<2GB) and causes Access Violations as other processes will try to peek into my private space.
Seems that different linkers affects the load address (with the same code).

I guess that your instructions will
cause BC++ 5.2 to make my hook code sharable...? Otherwise, I'll just
defect to Microsoft :)


0
 
NickRepinCommented:
You should't accept the answer if you are not sure.

Well, could you explain what exactly are you doing? How do you load your dll?

At first, did you check that your MS-compiled dll was loaded above 2GB?
It's easy - just check the numeric value of the dll module handle. If it points to the memory above 2GB, then it's really so. If not (I'm almost sure), then your dll is relocated to the another address.

As far as I know, according MS docs, there is no way to force dll to load at fixed address.
Moreover, there is no such thing as shared 2-3GB segment on NT.

Most likely that you need to share data between multiple instances of your dll. In this case see my answer above.

I wonder if you need to share the code sections.

Just try my answer first and let's see what to do next.
0
 
ShienShinAuthor Commented:
Hi again Nick. Sorry, not too familiar with the protocol here yet.

Yes, I did check the module handle
(return value of LoadLibrary). Somehow, a Microsoft-linked DLL will have a module handle similar to the image base as specified in the DLL file. This isn't true with Borland's linker.

My API-hook lib docs stated that it will
never work on Windows NT, but that'll be
somebody else's headache :)

Interesting thing is, when I wrote my
keyboard hook in Borland C++, I noticed that Windows actually maps my DLL into the address space of the active process
upon activation of the hotkey. This is done by observing the "reason" parameter in DLLEntryPoint. Thus, my hook procedure can be accessed globally without all the above-2-Gigs stuff.

The above-2-Gigs requirement is imposed
by my 3rd-party API hook library because
it never maps my hook procedure into
foreign processes that needs to access
my code. Observation is, if the library
redirects an API call into my procedure
in DLL with module handle < 2GB, system crashes. Otherwise, no problems.

What would you suggest Nick. Should I just rely on the unique property of Microsoft-linked DLLs? Or, is it time
for me to look for newer 32-bit API-hook libraries -- I can't write my VxDs yet!
0
 
NickRepinCommented:
You're still not provided me with the information about your dll.

<<I noticed that Windows actually maps my DLL into the address space of the active process upon activation of the hotkey.>>
It's true for all hooks, MS or Borland compiled - doesn't matter. Hook is loaded into the address space only when a specific event occurs.

<<The above-2-Gigs requirement is imposed by my 3rd-party API hook >>.

As far as I know, Microsoft doesn't say that you can load your dll's into 2-3GB segment. It's incorrect to rely on this. Suppose, that some other hook already installed on the PC and it uses the same address as your dll. In this case your dll will not be loaded at the right address.

There are other ways to share data with other applications, for example, memory mapped files (MMF) or shared sections.
It's better to use shared sections to pass HHOOK handles between multiple instances of your DLL.
Probably, MMF for 3-rd paty DLL is ok.

<<My API-hook lib docs stated that it will never work on Windows NT, but that'll be somebody else's headache>>

Well, if you are going to sell your DLL, then it would be better if it worked on NT as well, right?
Use portable code and dont't try to load your dll at 2-3GB segment. It can work on your PC, but may fail on other.
0
 
ShienShinAuthor Commented:
Hi Nick :) Sorry for being a bit  secretive" 'bout the DLL, I might get strangled for revealing too much. *Ouch*

It's meant to contain a function that inspects parameters of a rerouted  indows API call. I thought that to do
data sharing, one needs to first set up
some consensus between the various target processes? Is this possible with
hook procs with no prior knowledge of
what it'll face?

Yeah my 3rd party library sucks. Apart
from having this lousy >2GB crap, it
fails on NT machines. Worse still, API
rerouting is not done by placing a JMP
instruction at the original entry point.
It merely allocates modified addresses
upon an explicit request, e.g. during load-time of processes with statically linked DLLs, and GetProcAddress() calls.
So I couldn't even reroute "simple" calls such as MessageBoxA() to alter the
default Windows behaviour...

Thanks for everything so far. I'll need to spend time finding ways of actually setting the API hook up...


0
 
NickRepinCommented:
I've written many hooks including the ones which intercepted API calls.
There was no need to place the hook dll at the predefined address.
In all cases it was enough to use the shared sections or the file mappings.
0
 
ShienShinAuthor Commented:
Will you be able to intercept very "basic" ones such as Rectangle()? Would
you like to share some nifty methods of
intercepting them? I saw some authors
using debugging hooks to intercept APIs
but they requires their "debugger" to be
loaded before the actual program :(

The API-intercepting problem has been asked in Experts Exchange before. Usually they attract pretty vague answers, otherwise brief theoretical tips.

I don't have much points left, if you
feel that I should open this question,
please just say so. Thanks!
0
 
NickRepinCommented:
It depends on what do you want to do.

In general, there are two ways:

1) changing the import table (easiest, but doesn't work with LoadLibrary/GetProcAddress)

2) jmp instruction at the beginning of the function. Works in all cases, but hard ro implement.

As to Rectangle, it's better to modify the import table.
0

Featured Post

2018 Annual Membership Survey

Here at Experts Exchange, we strive to give members the best experience. Help us improve the site by taking this survey today! (Bonus: Be entered to win a great tech prize for participating!)

  • 7
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now