• 标 题:重建EasyPDF v1.5.2 的import table (4千字)
  • 作 者:fs0
  • 时 间:2001-6-9 23:46:50
  • 链 接:http://bbs.pediy.com

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);
}