Log in

View Full Version : Exports and kernel32.dll under w9x


ancev
February 17th, 2006, 21:14
hi,

i have a big problem adding functions to the export table of a dll...

the dll is the kernel32.dll of w95 and w98, and i am adding support for VirtualAllocEx(), VirtualFreeEx() and CreateRemoteThread() to these OSes, via modifications on kernel32.dll

my problem is not in the api-simulacrum code, but in the dll file manipulation.

in w98, all work fine, becoz w98 kernel32.dll have stubs for these apis, that always return ERROR_NOTSUPPORTED. so, i just change the export table of these apis to point to my code, and all worked as a charm.

but in w95, the only api name that already exists is CreateRemoteThread(). i need add to the export table VirtualAllocEx() and VirtualFreeEx() entries.

so, i did that.

i recreate the export table and all its data in a new section, find the alphabetical sorted place to insert my new apis (i found the hard way that i cant just insert them in the end of original export list), preserve ordinal, and like.

the modified w95 kernel32.dll look right. even the checksum (that w95 dont check) its right.

all the pe utils show the export table as it should be. tdump, lordpe, etc, and even ida.

the new functions point to the right place, and the old ones continue pointing to their original places.

but, for some unknow reason, w95 crash while loading with my modified kernel32. if i comment out the "export-adding" part, w95 load, and CreateRemoteThread() its the only new api available (so, kernel32 isnt untouchable under w95... the problem is in the export thingie).

anybody know anything about this stuffs? may w95 have hardcoded, in some dark corner, the number of apis of kernel32? its w95 expecting the apis be in some particular way? its my house build over a indian cemetary?!?

thanks for any help,
vecna

ps: i tried to add some bogus exports to w98 kernel32.dll, and it also crashed. so, the problem should be in my export-add-routine

Kayaker
February 18th, 2006, 00:46
Hi ancev,

Considering I reversed a Windows 3.10 app the other day to get it to install on Win98, I guess this is a pretty reasonable question dealing with Win95 ;-)

Just in case, you might find some stuff here of interest, an old site for defines, Krnl386.exe structures and the like for Win9x
http://mitglied.lycos.de/pepage/


It could be that there is a check of number of exports of kernel32.dll while loading, or something similar screwing things up. I noticed in Win98 that kernel32.dll has several of these unused API's with the stubs you speak of, leading to KERNEL32_17 it seems.

Just an idea, for Win95, if there are also any *extra* blank APIs, what about overwriting and redirecting them instead of *adding* 2 new APIs for VirtualAllocEx(), VirtualFreeEx(). This way you wouldn't have to change the PE ExportDirectory NumberOfFunctions or NumberOfNames, and if there is any hidden check that relies on that it should pass the test.

Kayaker

LLXX
February 18th, 2006, 03:07
What about putting a modified kernel32.dll in the directory of a program that uses the new APIs? Does it crash when loading such a program? And if so, how exactly does it crash?

I think the programmers of w95 have hardcoded some things.

Can you put the new import table within the same section as the existing one? Or is there not enough padding at the end to do that?

dELTA
February 18th, 2006, 05:00
Another idea, similar to that of LLXX, perhaps with a little bigger possibility to cause trouble (due to different hard codings and checks of different kinds), but much cleaner if it really works, would be to rename kernel32.dll, and then create a wrapper DLL for it, that redirects all normal APIs to the real (renamed) copy, but implements the extra ones itself? Hence the original export table is untouched in the original DLL, but you could add whatever you want to the export table of your own wrapper DLL, what do you think?

ancev
February 18th, 2006, 12:53
kayaker,

thanks for the url. altought not directly useful for current problem, it is very nice to have all that info handly. its liu tao tao page?

i will check about using "unused" apis to hold Virtual*Ex apis. The problem will be that i will need, anyway, reorder the tables, coz they need be sorted in alphabetic order. and i also would like a more generic approach.

w95 (at least), when you use GetProcAddress(), dont go linearly throught the names, till it find the one you want (and then get ordinal and address). it get the api name thats in the middle of the table, and check if the name you want is above or below (alphabetical order). then it get the upper/below part of the table, and do the same, till it find the api you want. "divide and conquer" search i think is called.

any suggestion of what apis i can recycle?



LLXX,

i put the prog below in a tmp dir, together with a patched kernel32.dll

Code:

#include <stdio.h>
#include <windows.h>
int main( int argc, char *argv[] )
{
int aux = (int) GetProcAddress( LoadLibrary( "KERNEL32.DLL" ), "GetProcAddress" );
printf( "0x%08x\n", aux );
aux = (int) GetProcAddress( LoadLibrary( "KERNEL32.DLL" ), "VirtualAllocEx" );
printf( "0x%08x\n", aux );
return 0;
}


in a clean system, first printf() work, and second not, as expected. if i put patched kernel32 in same dir, both apis fail... so seens the way i mess with export table is good enought for tdump, lordpe, ida and all others tools, but not for w95 OS

i will check the program above under softice (not easy, coz my w95 is a vmware virtual one) and see why its failing. maybe this give a clue about how should be the export table

about the export table(i think is this you mean), i put it all on a new section. header, table pointers, and names. at first, i just copied the tables, increased them, and use the names and like from the original position.

as it dont worked, i thought that was this the reason, so i moved everything to new section. but that wasnt the problem, so, as soon i fix it, i will go back to old scheme, using names and everything i can from original, to minimize duplicated info on dll.



delta,

your idea is very nice. i just must take care of mantain the same ordinal order of apis in "proxy dll". and it surely would work.

but, if i have to give up original idea, i probably would made my patch w98 only, and forget about w95... i mean, i could care less about w95 (well, w98 too). i dont have such machines anymore, and all its done via vmware.

i just thought it would be cool to make such upgrade patch to show the über quality of my brand new c++ pe class (that now dont seens so true, since it cant handle export adding properly ).

in the end, seens the work is more than i thought, and for no reward at the end

i just dont give up yet coz i dont like to abandon project coz i´m unable code them (i prefer abandon them coz i am lazy, or got another project to do )



thanks for the invaluable help, guys

an new idea is really welcome

ancev

ps: i did a last minute test, and passed kernel32.dll throught my routines, but not adding anything. thus, it only reordered the existing exports in a new section. and worked fine... so, seens the problem is directly related to adding apis to kernel32

pps: LLXX, the test program return 0 two times not coz the export is bad (or beside this). the problem is that 0xbff70000 its already in use for original kernel32.dll, and in w95, that dll dont have relocs, so it cant be loaded. in short: maybe GetProcAddress() will fail, but LoadLibrary() fail first

ancev
February 18th, 2006, 17:07
hi again,

some last minute info...

i let the w95 system crash, entered softice, and assembled and debugged this little snippet (inside kernel32.dll space):

Code:

bff71000 push ofs str_VirtualAllocEx
bff71005 push bff70000
bff71000 call GetProcAddress


and it worked! so, the export adding routine is working fine, and GetProcAddress() is able to find the addresses i add.

the problem seens to be, then, in the interaction of the patched kernel32.dll with the rest of the system.

instants before the crash (blue screen), a msg about GDI.EXE not being loaded (reinstall the system) appear

the crash is at 0137:00000009, and the cause is

Code:

bff7f0f1 call [var_inside_kernel32]


[var_inside_kernel32] should hold a address, but hold 0, so the crash happen...

my guess is that the failed GDI.EXE is causing the problem. [var_inside_kernel32] hold something related to it

maybe the hardcoded stuffs is in the 16b components

ancev

Peres
February 18th, 2006, 18:18
Ancev,

I guess your kernel32.dll must be larger than the original one since you added a new export section. If the new image needs extra pages to be loaded, then chances are it won't fit together with (often hardcoded!) base addresses of the other system dlls.

Give it a try

Peres

naides
February 18th, 2006, 21:20
Naive suggestions from a non expert.
Could you trace Win95 while it is loading kernel32.dll and GDI.exe?

Sice 4.32, (I am not sure if 2.7 which is the one you would need to use) can be made to load very early, right after NTOSKRNL module, before most of the system dlls.
Then you could directly find out, via debugger, what or where is crashing your updated kernel32.dll loading/working

Question 2:
could support for VirtualAllocEx(), VirtualFreeEx() and CreateRemoteThread() be added into a different system dll, or a new dll which is not as critically monitored as kernel32.dll? It might be easier to modif the application side of the problem, redirecting the calls to kernel32.dll->VirtualAllocEx() to Ancev_only.dll->VirtualAllocEx() for instance

ancev
February 18th, 2006, 22:32
peres,

good tip! what you said can be my case... copying all the export stuffs to a new section adds 0x1000 (at least), to the kernel32. and more then simulacrum code, others 0x1000

that would explain why it work with just the new EXPORTS (rebuild, but without anything added) and with the update code alone.

thats worth checking. i will research about that and post the results.


naides,

i am trying to do that, but, since its lots of code to trace, and i am using vmware+softice, i not having much sucess, yet

about another dll holding the new apis, it wouldnt help me. it will work fine for appz i code, but wouldnt help with existing tools (that is my objetive)

already exists some dlls (rt32.dll and other by elicz) and some libraries to link to your executable to have these apis working in w9x. i thought would be cool having them by default, ready for use of appz... but isnt so easy as i thought

ancev

LLXX
February 18th, 2006, 22:41
Quote:
[Originally Posted by peres]Ancev,

I guess your kernel32.dll must be larger than the original one since you added a new export section. If the new image needs extra pages to be loaded, then chances are it won't fit together with (often hardcoded!) base addresses of the other system dlls.

Give it a try

Peres
That's my thought too. I don't have a w95 kernel ready for inspection (using 98se at the moment) but my w98 kernel32.dll has approximately 1500 bytes of padding following its export table. I'd guess that on w95 there should be padding too; 1500 bytes is more than enough for adding a few extra exports. I say extract the export table from the DLL, add your exports to it, then place the new export table back in the same place as the original one, i.e. keep the file the same size.

Quote:
[Originally Posted by naides]Sice 4.32, (I am not sure if 2.7 which is the one you would need to use) can be made to load very early, right after NTOSKRNL module, before most of the system dlls.
Then you could directly find out, via debugger, what or where is crashing your updated kernel32.dll loading/working
9x systems don't have an NTOSKRNL... they have a VMM
Quote:
[Originally Posted by naides]Naive suggestions from a non expert.

ancev
February 25th, 2006, 16:45
hi guys,

thank very much for the ideas and suggestions, but nothing worked

i tried all the ideas, inclusive the ones to not increase the imagesize of kernel32.dll

i tried with others dlls, and it worked, so, seens something is something hardcoded to w95

so, i made my update w98 only!

its attached to this msg, with the source included (but this time, in c++ )

thanks once again for all the help

ancev

ps: run the exe in win98 and you now have VirtualAllocEx(), VirtualFreeEx() and CreateRemoteThread()... to remove the update, just run the exe with --remove cmdline param

pps: tested to compile with bcc32 and msvc. probably work with all compilers

LLXX
February 25th, 2006, 20:51
Is that for 98SE or 98 first edition?

Do you want that update distributed to other win98 users?

The Win9x forum at http://www.msfn.org/board might be pleased to see your efforts

ancev
February 26th, 2006, 09:01
LLXX,

i tested on 98 first edition (at least i dont remember any SE logo on vmware), but probably work in both

distribute at will - maybe we find somebody able to do it work on w95

vecna

LLXX
February 26th, 2006, 18:58
Right click My Computer and choose Properties, you'll be able to see the version there.

4.10.1998 = First Edition
4.10.2222A = Second Edition

As an additional reversing exercise, you might want to try adding 48-bit LBA support to EDSI_506.PDR, to resolve an important issue with Win98 (not being able to use hard drives over 128Gb).

ancev
February 28th, 2006, 17:49
LLXX,

tested it in first edition (the one i already tested) and second edition - work fine

in w95, there´s the bug we already discussed... and in winme, you should disable SFP, else old kernel32 replace new at each reboot

about 48b lba, i dont know what is need to do, nor have that big hdd

ancev