Just wondering, is it possible to rid yourself of the IAT? or is it necessary?

Also, I notice when I call APIs my code first calls an address at the end of my code which in turn jumps to the API.

I'd like to skip this middle step. So I thought I could work around this by doing:



aGetMessage dd offset GetMessage
...
call aGetMessage


but it doesn't seem to change much.
So I'd like to rid myself of this "indirect" call. I think it's related to the import table, but not sure.

Thanks for any input

--Chorus
Posted on 2002-06-26 20:07:03 by chorus
You can use hutch's L2EXTIA utility to recreate the .INC files from the .LIB files. Then reassem your prog, and the jump table vanishes. :)

L2EXTIA works with the SDK .LIB files that come with MASM32. I've also used it with the Visual Studio 6 .LIB files, so far with no problems.

:)
Posted on 2002-06-26 21:11:13 by S/390
S/390 Thanks for the tip. I tried it out and it works just like you said.

However, after I compile I notice that my object file is bigger when the Jump Table is gone... this seems wrong. The reason I wanted to get rid of the Jump Table was to free up a little more space in the EXE.

Does anybody know why this is??

--Chorus
Posted on 2002-06-26 22:44:18 by chorus
Hummm, your .OBJ file could be larger if you include symbols. The new .INC files do have 2 symbols for each API call. But without symbols, the final .EXE should be smaller.

Another trick to make an .EXE file smaller is the /filealign:512 link option. The default is 4096, so each section is filled to a 4096 boundary when stored in the .EXE. 512 reduces the boundary, but the loader still places the sections on a 4K page boundary in memory. :)
Posted on 2002-06-26 23:13:42 by S/390
Posted on 2002-06-27 04:46:10 by Four-F
chorus
Yes, you can build your exe completely without import section. But your way is not reliable. If you hardcoded the offsets of API function there is no confidence that this address isn't change the next time you boot, windows can relocate kernel32 and this address will change.
In the start of your code in the stack (I don't remember where exactly, see under debugger) there is a pointer inside of kernel32. The point is to find GetProcAddress and GetModuleHandle function inside. After that you can call any API function.
Maybe there is another way to find the kernel32 in memory.
Good luck!
Posted on 2002-06-27 09:04:30 by masquer
You can always import by ordinals, but that also is not guaranteed to work under different operating systems and different DLL versions. Although, I've seen a small Win32 intro that uses opengl and imports by ordinals. Of course, you can always write your own import address finder, and say compare symbols by their 8-bit checksums, etc. That's real hardcore. :)
Posted on 2002-06-27 09:48:51 by comrade
Masquer, you're wrong. You can *not* totally remove the import table,
there's at least one (and probably more) windows versions where the
PE loader will (silently) refuse to load your EXE if you don't import
from kernel32. You don't have to import directly, thus you could import
from gdi32 (or whatever other DLL that ends up importing kernel32,
directly or not). But you must end up importing kernel32 or your app
will not load on (at least) win2ksp2, probably older win2k as well, and
I'd be surprised if such an executable loaded on XP.

As for relocation, I doubt that kernel32/user32 and other "really core"
DLLs will ever be relocated - but they can change addresses on different
service packs and windows versions (so there's good reason not to depend
on any hardcoded values).

Yes, there's a pointer-in-kernel32 on the stack (returnaddr) on all
current win32 versions (at least all 9x, NT4, win2k, XP, probably
also older NT versions). Question is, can we depend on it staying
this way? Nobody says the PE loader *has* to call your executable
from kernel32 code... it could in theory jump there, without leaving
anything on the stack. If you're going to do kernel32 scanning, a
cleaner approach is to import ExitProcess and scan backwards from there...
NT can have redirected exports, but I think it's safer betting on
ExitProcess staying in kernel32, than it is to bet on the kernel32-value
being on stack at program startup (not that either is likely to change).

No point in finding GetProcAddress, since you'll have to do your own
GetProcAddress to find the original GetProcAddress. Also better use
LoadLibrary than GetModuleHandle, or you will only be able to get procs
from DLLs that are already mapped in your process.

Stay away from ordinal imports, they are evil.


compare symbols by their 8-bit checksums

Better use 32bit checksums, there's too many clashes with 8bit ones.
Posted on 2002-06-27 12:58:06 by f0dder
hi,

using the opportunity: the ordinal numbers of kernel32.dll are changing between windows versions?

ancev
Posted on 2002-06-27 14:20:52 by ancev
perhaps, perhaps not. I'm not going to take the chance of my apps
breaking on later windows versions.
Posted on 2002-06-27 14:23:11 by f0dder
Better use 32bit checksums, there's too many clashes with 8bit ones.

maybe at least 16, but 32 would be too chuky if you plan to cut down on size
Posted on 2002-06-27 14:24:34 by comrade
Hmm.. not sure about all this ordinal stuff... sounds a little more complicated than I want to go to trim a couple bytes off my code. I thought I had read somewhere that some programmers don't use the IAT in an effort to dissuade crackers from their efforts. But if it can't be eliminated, then that's that, I guess.

S/390, just thought I'd let you know that I was partially wrong about the file size with the different includes. Turns out the obj file *is* bigger, but the exe is smaller. Dunno why Hutch even distributes the original include files if his utility makes better ones. They seem to be functionally identical.

Four-F, very nice links. I've only had a quick minute to browse through the site, but it looks like I'll be reading a lot of material in the next couple days. Thanks :)

--Chorus
Posted on 2002-06-28 22:22:09 by chorus
You can always try realigning the executable to save some size. I do know for a fact many virii coders don't use IAT but rather import functions manually, if that's what you were talking about.
Posted on 2002-06-28 22:27:54 by comrade
Well, you can't *eliminate* the IAT as your app then wont run on
a lot of windows versions - but you can do with only a single kernel32
import and do the rest by hand, if you really want to. Virwriters
are able to do without IAT since host executables already have
imports.
Posted on 2002-06-29 03:58:17 by f0dder
f0dder, I meant actual "original" virii executables and trojan horses import IAT manually to fool off anti-virus software. I've had AVP detect my trojan as "Possible Unknown Trojan Horse" simply because of my imports and lack of user interface.
Posted on 2002-06-29 12:07:58 by comrade

I've had AVP detect my trojan as "Possible Unknown Trojan Horse" simply because of my imports and lack of user interface.


:mad:

comrade,
you are such proud about writing a trojan?
Read the board rules before you post something about that topic again!
Posted on 2002-06-29 12:12:49 by bazik
Learn to comprehend what you read and think twice before you post.
Posted on 2002-06-29 12:48:06 by comrade
ok... back on topic here...
So I looked up importing by ordinals and checked out the links Four-F provided earlier and I think I can import by ordinals now.

However, I have 2 questions:

1) Where do I find the ordinal numbers for procs in kernel32.dll, etc? I have a feeling it's not as straight forward as surfing over to MSDN and finding some kinda list (besides... I already tried that..)

2) I think ancev asked this before, do the ordinal numbers change from platform to platform? Or is MS good about this??

Thanks

--Chorus

--edit--
you know, I just went and double checked Comrade's original post and I think he answered my questions...
Posted on 2002-06-29 19:08:42 by chorus
1) Use this utility (attached)...
Manual VA and Manual RVA fields should be swapped together, will fix that in next version.
2) Ordinals for critical libraries (kernel32, user32, etc) should differ from platform to platform and from version to version but for other libraries they may stay the same.
Posted on 2002-06-29 22:21:40 by comrade
comrade, I think this is what you meant to type??:

I've had AVP detect my program as "Possible Unknown Trojan Horse" simply because of my imports and lack of user interface.
Posted on 2002-06-30 04:00:54 by ThoughtCriminal