Results 1 to 6 of 6

Thread: imports are easy to fix

  1. #1

    imports are easy to fix

    Well I read post at openrce posted by blabberer in X-Code thread here at woodmann ( and saw interesting discussion between Rolf Rolles (waz up man ) and Kris Kaspersky debating which way of generic fixing is better. Kris votes for adding loader, but Rolf likes clean import to have good disasm in IDA. Infact I had this same problem a few months ago, it was easy to locate all APIs and add loader, who cares, app works, well it works and you don't have to analyse it as long as registration scheme is located in the wraper, but what if registration is located in program itself and you have to analyse it? It would be mess and boring task in IDA not seeing real APIs Basically that small discussion was inspiration to write this blog post

    Look at this messy fixed import. It looks like, for example, armadillo shuffled IAT or maybe ActiveMARK v6.xx fixed IAT. But take a closer
    look where are APIs located:

    00BBC368 >7C80A447  kernel32.QueryPerformanceCounter
    00BBC36C >7E450702  USER32.MessageBoxA
    kernel32.QueryPerformanceCounter = BBC364
    user32.MessageBoxA               = BBC368
    You might wonder how did I get this to work? Using API loader? No!!!

    What I have used here is 1API = 1 image import descriptor concept which I use to fix imports always. Basically this is how it works:

    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        union {
            DWORD   Characteristics;            
            DWORD   OriginalFirstThunk;         
        DWORD   TimeDateStamp;                  
        DWORD   ForwarderChain;                 
        DWORD   Name;
        DWORD   FirstThunk;                     
    According to PE specification OriginalFirstThunk points to API names, but if it is 0 then FirstThunk is pointing to API names, also FirstThunk is used to know where to store API addresses.

    So what we shall do to make this concept work?

    1. Build OriginalFirstThunk such that it only points to one API name
    2. place RVA in FirstThunk where we want API loaded
    3. When import table is built simply walk firstthunk and set it to
    specific value != 0 as windows loader will deny loading image if
    address to which FirstThunk is pointing is 0. Weird?! I didn't find
    anything in PE specification about this behaviour

    Lets see some code snipets from this library which you may find in src of my GenericUnpacker and import engine at

    First we define some struct which will hold our imports:

    import_struct           struct
            is_address      dd      ?               <--- RVA where we want API address to be
                                                         writen by windows loader
            is_dlllen       dd      ?               <--- len of dll name including terminating 0
            is_apilen       dd      ?               <--- len of API string including terminating 0
                                                         or 4 if API is imported by ordinal
            is_dllname      db      256     dup(0)  <--- dllname (ASCII)
            is_apiname      db      256     dup(0)  <--- API name or ordinal | 0x80000000
    import_struct           ends
    Now it's very simply to fix IAT:

    By number of this structs we know how many IMAGE_IMPORT_DESCRIPTORs we will have, but
    also tnhx to lengths stored in structs we can estimate size of newly built IAT including
    APIs aswell.

    OriginalFirstThunk will always point to API name or ordinal and also will take one more
    DWORD for 0 to tell windows loader that there are no more APIs to be loaded.

    EBX = memory used for IMAGE_IMPORT_DESCRIPTOR
    EDI = pointer where we write dll, api names or ordinals and is calculated
    as EBX + (number_of_import_structs + 1) * sizeof (IMAGE_IMPORT_DESCRIPTOR)

                            sub     edx, size import_struct
    __cycle_main_loop:      add     edx, size import_struct
                            cmp     [edx.is_address], 0
                            je      __done_building
                            ;copy dll name
                            mov     esi, edi
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [ebx.id_name], esi 
                            lea     esi, [edx.is_dllname]
                            mov     ecx, [edx.is_dlllen]
                            rep     movsb
                            ;write original first thunk
                            mov     esi, eax
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [ebx.id_originalfirstthunk], esi
                            mov     esi, dword ptr[edx.is_apiname]
                            test    esi, 80000000h
                            jz      __api_has_name
                            mov     [eax], esi
                            jmp     __firstthunk         
                            mov     esi, edi
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [eax], esi
                            lea     esi, [edx.is_apiname]
                            add     edi, 2
                            mov     ecx, [edx.is_apilen]
                            rep     movsb
                            mov     esi, [edx.is_address]
                            mov     [ebx.id_firstthunk], esi
                            add     ebx, size import_directory
                            add     eax, 8
                            jmp     __cycle_main_loop
    When this small loop is done, all we have to do is to walk all first_thunks and set them
    to != 0 so win loader can actually load this import table.

    With this concept you don't have to write sorting algos to get nice and clean IAT, who
    cares where are APIs located. In my, aspr2.3 dumper for example, I scan original code
    for APIs that are not stolen, then I go for stolen APIs and write them into array
    and I don't care if I have something like this:



    After this is done, then I go for APIs located in poly oep, or other stolen procedures
    which are located in markers. At this point IAT looks like nightmare and importrec nor
    any other public known engine can fix this IAT... But 1API = 1IDD concept fixes this
    without a problem!!!

    Think about it when writing unpacker and protection developers think too when
    you try to make "hard" IAT to stop importrec, you will lose one way or another
    Remember that not many people are using it lately
    Last edited by deroko; October 23rd, 2007 at 11:55. Reason: keep it upto date with edited blog post :p

  2. #2
    Super Moderator
    Join Date
    Dec 2004
    Blog Entries
    heya nice entry there sometimes i think i should reaally rebuild some fscked up import table im atleast happy my little post inspired you to write a blog

  3. #3
    not very sure, but it might happen that an error arise when the loader tries to make address-0 memory writeable? Since the IAT can be written even if it's read-only.

    mmh... yep, looks like it is
    Last edited by Maximus; October 23rd, 2007 at 12:51.
    I want to know God's thoughts ...the rest are details.
    (A. Einstein)
    ..."a shellcode is a command you do at the linux shell"...

  4. #4
    Actually it's strange there is code like this somewhere in ntdll loader:

    FirstThunk = import->FirstThunk + imagebase;
    if (*FirstThunk == 0)
    that's why I simply set it to != 0 value later on when IAT is added to dump

  5. #5
    aaah, i found the code for unprotectable memory only then!
    will dig more
    I want to know God's thoughts ...the rest are details.
    (A. Einstein)
    ..."a shellcode is a command you do at the linux shell"...

  6. #6
    Administrator dELTA's Avatar
    Join Date
    Oct 2000
    Ring -1
    Blog Entries
    Nice trick deroko, thanks for sharing as always.
    "Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."

Similar Threads

  1. Fix imports in a dll?
    By ukguy99 in forum The Newbie Forum
    Replies: 2
    Last Post: November 3rd, 2009, 13:21
  2. Help with a codecave, imports
    By abitofboth in forum The Newbie Forum
    Replies: 15
    Last Post: March 26th, 2009, 17:19
  3. ok i'm new go easy...
    By bakeacake in forum The Newbie Forum
    Replies: 5
    Last Post: November 1st, 2004, 18:30
  4. problem fixing imports
    By jolopez in forum Malware Analysis and Unpacking Forum
    Replies: 2
    Last Post: February 17th, 2004, 09:23
  5. easy but how ?????
    By black_ice in forum The Newbie Forum
    Replies: 3
    Last Post: November 8th, 2002, 21:13


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts