LeFF, that is not the case. You should experiment more.
LeFF, that is not the case. You should experiment more.
http://home.no/zorgion/bsod.jpg
Watch the language, will you ? Unless you wanna get into my ignore list.
That is the import address TABLENT_HEADERS -> OPTIONAL_HEADER -> DATA_DIRECTORIES ->
If you had bothered reading my previous topic, you would had read that The imported function address is found as a (read-only) variable in the .rdata section.
That means the actual function address, the one that I am manipulating, not the table entries, which I do not bother with because they are there for the NT loader !
The table entry is there to do the proper function address re-direction at load-time, something that I am skipping altogether (that is the point of this post).
If you can't bother reading a post properly, then don't bother trolling.
Last edited by t0ns0fPhun; 24-02-2012 at 07:09.
mov esi, fs:[ecx + 30h]
mov esi, [esi + 0Ch]
mov esi, [esi + 1Ch]
Actually LeFF is right, though he didn't explained himself good enough.
In YOUR example you can ignore the headers because the import table is at the start of the .rdata section. But you cannot rely on that. The actual Address is stored in the Image Data Directories, only with this address you will be able to load a file a little more complex that your current.
Also what about relocations, TLS and other advanced things? You should use the PE Header to get the actual addresses, so your packer stays generic and doesn't has to use hardcoded addresses.
So basically you should start with having the complete file inside and really recoding the windows loader.
Rebuilding the import table IS loading all required DLLs and updating the 'pointers' in the import table.
Looking back at your 1st post 0x0040101A and 0x00401020 are in the IAT. You HAVE TO update the Import Address Table.
With the IAT you get all Apis with their corresponding DLL, then you iterate over one of the loaded DLL lists and get the address of each Api from that.
This (Actually your whole process [But this quote highlights the similarities better]) is pretty much the way all serious crypters (Including even mine) do that. (Though they avoid that suspicious ImageBase)
He does not have to hardcode addresses, and he does neither need to have the complete file inside. That's the point of him doing it that way. It was to not make it work like the windows loader. Adding the whole PE inside your program takes more space & is easier to detect.
I've been using almost the same method for PE injection. I write my program to the target program, then writes my own loader to it and in the end call CreateRemoteThread to begin my loader. Workes like a charm.
That was what we already found out by his first post.Rebuilding the import table IS loading all required DLLs and updating the 'pointers' in the import table.
Looking back at your 1st post 0x0040101A and 0x00401020 are in the IAT. You HAVE TO update the Import Address Table.
With the IAT you get all Apis with their corresponding DLL, then you iterate over one of the loaded DLL lists and get the address of each Api from that.
Anyway this topic is dead. Nothing more can be gained by discussing it here further. If you have anything you would like to add give me a PM after.
Last edited by zorgion; 24-02-2012 at 17:49.
http://home.no/zorgion/bsod.jpg
Actually I just finished the proof of concept code.
I've only tested it with a helloworld.exe (included) but it should work with more complex applications.
The process is simple really:
(1)Copy the actual guest application in memory, place it in its requested imagebase, align properly.
(2)Find the the imported function names, store them for a lookup.
(3)Rebuild the imported function addresses, by loading the import module and updating the pointers to imported function addresses.
(4)Pass execution into the copied code.
Finding the imported function names does require the Import Table. Yet LeFF is very wrong, the Import address table is almost always in .rdata.
Proof can be seen by simply running the compiled app in OllyDbg, and following in dump the .rdata section.
Other than getting its address from the DataDirectory array, I do not rely much on the headers.
In the code, I do use the headers, mostly to align and copy the sections, get the entry point, etc.
However, all that information could be saved someplace else in a crypter, saving alot of space.
I am not saying that this is the best way to do it, in fact, I wrote this code on Saturday morning, so I can expect alot of bugs and errors.
One advantage I see over the other method (creating a processes suspended, and overwritting its image), is that everything here is encapsulated
in a single process. You can effectively protect the guest app, by running all sorts of anti methods prior to passing execution to it.
In the code above, the guest app is simply an *.exe passed as an argument. However, nothing stops you from using the same method in a crypter.
All you have to do, is copy from your location the binary (which may be encrypted, compressed, etc ).
Will it work in all cases ? I do not know. Can it work in most cases ? I think so. Obviously the NT PE loader is much better than this.
Feel free to try it out, comment, or report bugs or better ideas.
Have a nice weekend !
PS: @wacked I think you are saying the same thing in different words. It is my understanding that rebuilding an import table, means just that, rebuilding the entire import table.
That is not the case here, I simply load the functions and library modules, and update the function addresses to point to the correct address. If that is what LeFF meant, he could
have tried to explain it better, instead he chose to try to insult.
mov esi, fs:[ecx + 30h]
mov esi, [esi + 0Ch]
mov esi, [esi + 1Ch]
I looked at your PoC and it looks like you don't know what you are doing. There are many mistakes and they are there because you don't understand the PE format yet. This works only in a few cases.
I'll give you a funny example:
TryCode:DWORD VirtualSize = 0; DWORD SectionHdrStart = (DWORD)guestFileBase + (DWORD)dos_hdr->e_lfanew + sizeof(IMAGE_NT_HEADERS); IMAGE_SECTION_HEADER *tmp = (IMAGE_SECTION_HEADER*)SectionHdrStart; for ( unsigned int i = 1; i <= pe_hdr->FileHeader.NumberOfSections; i++) { VirtualSize = tmp->VirtualAddress; tmp = (IMAGE_SECTION_HEADER*)(SectionHdrStart + i * sizeof(IMAGE_SECTION_HEADER)); } VirtualSize += pe_hdr->OptionalHeader.SectionAlignment;
next time...Code:VirtualSize = pe_hdr->OptionalHeader.SizeOfImage;
"There exists very little information on the web"? LOL
pecoff_v8.docx
An In-Depth Look into the Win32 Portable Executable File Format
and many more...
Calls to GetProcAddress & LoadLibrary when writing your own PE / DLL loader is failure before even starting.
http://home.no/zorgion/bsod.jpg
For a crypter maybe.. But if you got the time to write a PE / DLL loader you migth as well load the needed library's by CreateFile & Parse the imports with your own custom GetProcAddress to make sure it get's loaded in case someone is debugging and trying to follow your calls. Or if you inject the code (loader) into a remote target & the app have hooked either of them.
If I see someone loading any dll's (even system) in the middle of the code, then I'll follow the code to see what it does. Do this with every exe / dll before I run it on my system.
http://home.no/zorgion/bsod.jpg
Well, maybe your first post was too aggressive. Anyway I load LoadLibrary&GetProcAddress by going through loadedmodulelist and getting function addresses from it.
There are currently 1 users browsing this thread. (0 members and 1 guests)