重建EasyPDF v1.5.2 的import table (4千字)

看雪資料發表於2001-06-09

EasyPDF v1.5.2 是用Visual Protect 3加的殼
被重定向的import table 都是kernel32.dll, user32.dll等
其重定向方式為

IAT [0068C208] = 01BFAC18
01BFAC18:
B84CC39200    mov eax, 0092C34C
FFE0          jmp eax

0092C34C:
B88818F7BF  mov eax, BFF71888  <-- GetCurrentThreadId
FFE0        jmp eax

看上去很簡單, 但Import REConstructor v1.2 的 Trace Level1 (Disasm)是不能分析這種重定向方式的,
因此我們只能手動重建了, 逐個將 BFxxxxxx 填回去是一件非常累人的事情, 幸好其redirect方式很固定,
都是mov eax, xxxxxxxx, jmp eax 每次的程式碼不同之處只是 xxxxxxxx , 我們可以寫個程式來讀
IAT 指向的第1, 6, 7位元組是否分別為 B8, FF, E0, 是就認為這是個有效的redirect, 再根據第5個位元組
比 B0 大, 不是就以2--5位元組為指向下一個jmp的地址再讀, 是就認為這個DWORD是真正的Import Table Address,
將其寫到 IAT處 (如上例的[0068C208]). 然後處理下一個 IAT, 直到 IAT size / 4 個為止.

下面附上源程式, 四個引數 m_processid(程式ID), m_imagebase(IMAGE BASE), m_iatrva(IAT RVA), m_iatsize(IAT SIZE)
(為什麼是 m_xxxxx ? , 呵呵是VC裡搬過來的(:)

這樣處理完以後就剩下一個被重定向為 0089EF0C 的IAT, debug 看一下, 看其push進去的引數和返回結果就知道這是GetProcAddress.
EasyPDF.exe 重建好了, vspdf.dll也差不多, Process ID 就是 EasyPDF.exe的, 關鍵是找到 IAT RVA 和 IAT SIZE, 其 OEP 是 0x1000,
不過Import REConstructor說找不到IAT, 我試了 OEP 為 0x1CBC0 就能發現 IAT, 但 size 好像也不對, 我也沒仔細看, 反正我是把它改大了.
對那些沒用的IAT都 cut 掉. 還有就是EasyPDF.exe 的 662082 jz near xxxxxxxx. 好, 大功告成。

// file name exp.cpp
// compile with "cl exp.cpp user32.lib"
#include <windows.h>

void main( void )
{
    DWORD m_processid, m_imagebase, m_iatrva, m_iatsize;
    
    m_processid = 0xFFF529C6;
    m_imagebase = 0x00400000;
    m_iatrva    = 0x0028C204;
    m_iatsize  = 0x00000A0C;
    
    unsigned char buf[MAX_PATH];
    HANDLE h_process;
    DWORD dw_ImageBase = 0x400000;
    unsigned int *p_iatva, *p_first_iatrva, *p_NextRedirect;
    unsigned long *p_oldprotection=0;
    int num, NestedCount, i;

    dw_ImageBase = m_imagebase;
    num = m_iatsize/4;
__try
{
    p_first_iatrva = (unsigned int*) m_iatrva;
    if ( (h_process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, m_processid)) != NULL )
    {
        p_iatva  = (unsigned int *) ((unsigned int)p_first_iatrva + dw_ImageBase);
        for(i=0; i<num; i++)
        {
            if( ReadProcessMemory( h_process, (void *)p_iatva, buf, 4, 0 ) )
            {
                p_NextRedirect = (unsigned int*) buf;
                p_NextRedirect = (unsigned int*) *p_NextRedirect;
                for( NestedCount=0; NestedCount<5; NestedCount++)
                    if( ReadProcessMemory( h_process, (void *)p_NextRedirect, buf, 10, 0 ) )
                    {
                        if (*buf == 0xB8 && *(buf+5) == 0xff && *(buf+6) == 0xe0)    //mov eax, hhxxxxxx
                        {                                                            //jmp eax
                            p_NextRedirect = (unsigned int *)(void *) (buf + 1);
                            p_NextRedirect = (unsigned int*) *p_NextRedirect;
                            if ( *(buf+4) < 0xB0 )                                //when hh >= 0xb0 assume it is the real import address, only test on my ME.
                                continue;                                    //Visual Protect seem to redirect kernel32.dll, user32.dll ... only.
                            else
                            {
                                if(!VirtualProtectEx(h_process, (void *)p_iatva, 4, PAGE_READWRITE, p_oldprotection))
                                {
                                    MessageBox(0, "Error changing access protection of process!", "exp", MB_OK);
                                    break;
                                }
                                if(!WriteProcessMemory(h_process, (void *)p_iatva, (void *)(buf+1), 4, 0))
                                {
                                    wsprintf( (char *) buf,"Write process memory error at %x , error code : %x", p_iatva, GetLastError());
                                    MessageBox(0, (char *) buf, "exp", MB_OK | MB_ICONERROR);
                                    break;
                                }
                                else
                                    break;  //next iat
                            }
                        }
                        else
                            break; //does not match format or already write
                    }
                    else
                    {
                        //MessageBox(0, "Read process memory error!", "exp", MB_OK | MB_ICONERROR);
                        break;
                    }
            }
            else
                MessageBox(0, "Read process IAT memory error!", "exp", MB_OK | MB_ICONERROR);
            
            p_iatva ++;  //get next iat
        }
        MessageBox(0, "Write process memory end.", "exp", MB_OK | MB_ICONINFORMATION);
    }
    else
        MessageBox(0, "Can not open process!", "exp", MB_OK | MB_ICONERROR);
}
__except(1)
{
    MessageBox(0, "Found exception!!!", "exp", MB_OK | MB_ICONERROR);
}

    CloseHandle(h_process);
}

相關文章