逆向程序的时候,喜欢用IDA静态分析,用OD动态调试,如果把IDA分析出来的函数名称都导入到OD中,调试的时候就知道哪些函数不需要再看了。以前我一直用GODUP的map loader,但是有些时候感觉它有点问题,还有一个插件叫MapConv也有这个功能,不过我还是打算自己写一个,主要是为了学习如何编写OD插件

首先我用一个IDC脚本将idb中所有函数的名称都导出到一个文件当中

代码:
//CamelLu.idc
#include <idc.idc>
static CamelLu()
{
    auto addr,path,file,imagebase;
    Message("Functions' Names Dumper - CamelLu(2011.7.19)\n");
    file = fopen(GetInputFilePath(),"rb");
    if (0 == file)
    {
        Warning("open INPUTFILE failed!");
        return;
    }
    if (0 != fseek(file,0x3c,0))
    {
        Warning("seek e_lfanew failed!");
        fclose(file);
        return;
    }
    imagebase = readlong(file,0);
    if (0 != fseek(file,imagebase + 0x34,0))
    {
        Warning("seek imagebase failed!");
        fclose(file);
        return;        
    }
    imagebase = readlong(file,0);
    fclose(file);
    path = AskFile(1,"*.lu","Please enter output file name");
    if (BADADDR == path)
    {
        Warning("AskFile failed!");
        return;
    }
    file = fopen(path,"w");
    if (0 == file)
    {
        Warning("fopen failed!");
        return;
    }
    addr = MinEA();
    if ("" != GetFunctionName(addr))
        fprintf(file,"%X---%s\n",addr,GetFunctionName(addr));
    for(addr = NextFunction(addr);BADADDR != addr;addr = NextFunction(addr))    
         fprintf(file,"%X-%s\n",addr - imagebase,GetFunctionName(addr));
    fclose(file);
    Message("output functions' names finished!");
}
这个idc脚本文件没有main函数,因为我要使用快捷键来调用它
使用方法:
在IDA的安装目录下面找到idc这个目录,把上面这个脚本保存到这个目录中,然后idc目录下找到
ida.idc这个文件,打开它,在#include<idc.idc>的下面加入#include<CamelLu.idc>,然后在它的main函数里面加入AddHotkey("Alt-9","CamelLu");
接下来你就可以在IDA中按Alt+9来调用这个脚本了(为脚本选择热键的时候要注意,如果这个热键已经被其他脚本或者插件使用的话,AddHotKey会失败,IDA不会给你提示的噢

接下来再写一个OD插件来解析上面输出的文件,用Quickinsertname和Mergequicknames函数把函数名加到相应的地址就OK。我对插件框架的几个函数用途都写了简单的注释,相信大家看过之后都能自己写OD插件了
代码:
#include <windows.h>
#include <string.h>

#include "plugin.h"

#pragma comment(lib,"OLLYDBG.LIB")
static HINSTANCE hinst = NULL;
static HWND hwnd = NULL;
BOOL WINAPI DllEntryPoint(HINSTANCE hinstance,DWORD dwreason,LPVOID lpvreserved) 
{
    if (dwreason==DLL_PROCESS_ATTACH)
        hinst=hinstance;                          
    return 1;                           
}

//下面四个函数全都是插件回调函数,只有前两个函数是编写OD插件必须有的!!!
//ODBG_PluginData这个函数是必须有的,作用就是设置插件的名字(在OD的Plugin)
extc int _export cdecl ODBG_Plugindata(char shortname[32]) 
{
    strcpy(shortname,"CamelLu");       
    return PLUGIN_VERSION;
}
//ODBG_Plugininit这个函数也是必须有的,看名字就知道是用来做一些初始化工作啦
//ollydbgversion参数可以用来检查当前OD的版本,确保插件运行在兼容的OD版本上,hw是OD主窗口的句柄
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw,ulong *features) 
{
    hwnd = hw;
    return 0;
}

//ODBG_Pluginmenu这个函数是用来添加菜单的,每个菜单项之间用'|'字符隔开
extc int _export cdecl ODBG_Pluginmenu(int origin,char data[4096],void *item) 
{
    if (origin == PM_MAIN)
        strcpy(data,"0&Load functions\' names|1&About");
    return 1;
}
//ODBG_Pluginaction函数用于添加响应ODBG_Pluginmenu函数添加的菜单,很简单,看看下面的代码就明白了
extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item) 
{
    OPENFILENAME ofn;     
    wchar_t wszFile[MAX_PATH]; 
    unsigned char *pBuffer = NULL;
    unsigned char *pLocate = NULL;
    unsigned char *pDellimiter = NULL;
    unsigned char *pTemp = NULL;
    DWORD dwFileSize = 0;
    DWORD dwBytesRead = 0;
    DWORD dwImageBase = 0;
    DWORD dwAddr = 0;
    char szBuffer[10];
    HANDLE hFile = INVALID_HANDLE_VALUE;
    if (origin == PM_MAIN)
        if (action == 0)
        {
   
            ZeroMemory(&ofn, sizeof(ofn));
            ofn.lStructSize = sizeof(ofn);
            ofn.hwndOwner = hwnd;
            ofn.lpstrFile = wszFile;
            ofn.lpstrFile[0] = L'\0';
            ofn.nMaxFile = sizeof(wszFile);
            ofn.lpstrFilter = L".lu\0*.lu\0";
            ofn.nFilterIndex = 1;
            ofn.lpstrFileTitle = NULL;
            ofn.nMaxFileTitle = 0;
            ofn.lpstrInitialDir = NULL;
            ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

            if (GetOpenFileName(&ofn)==TRUE) 
            {
                if (STAT_NONE == _Getstatus())
                {
                    MessageBoxW(hwnd,L"No debugee now!!!",0,0);
                    return;
                }
                hFile = CreateFileW(
                    wszFile,
                    GENERIC_READ,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL);
                if (INVALID_HANDLE_VALUE == hFile)
                {
                    MessageBoxW(hwnd,L"Failed to open .lu file!",0,0);
                    return;
                }
                dwFileSize = GetFileSize(hFile,NULL);
                if (INVALID_FILE_SIZE == dwFileSize)
                {
                    MessageBoxW(hwnd,L"GetFileSize failed!",0,0);
                    CloseHandle(hFile);
                    return;
                }
                pBuffer = VirtualAlloc(
                    NULL,
                    dwFileSize + 1 * sizeof(unsigned char),
                    MEM_COMMIT,
                    PAGE_READWRITE
                    );
                if (NULL == pBuffer)
                {
                    MessageBoxW(hwnd,L"VirtualAlloc failed!",0,0);
                    CloseHandle(hFile);
                    return;
                }
                if (!ReadFile(
                    hFile,
                    pBuffer,
                    dwFileSize,
                    &dwBytesRead,
                    NULL)
                    )
                {
                    MessageBoxW(hwnd,L"ReadFile failed!",0,0);
                    VirtualFree(pBuffer,0,MEM_RELEASE);
                    CloseHandle(hFile);
                    return;
                }
                CloseHandle(hFile);
                dwImageBase = _Plugingetvalue(VAL_MAINBASE);
                pLocate = pBuffer;
                pDellimiter = strstr(pLocate,"\r\n");
                while (*(pDellimiter + 2) != 0)
                {
                    pTemp = VirtualAlloc(NULL,pDellimiter - pLocate + 1 * sizeof(unsigned char),MEM_COMMIT,PAGE_READWRITE);
                    if (NULL == pTemp)
                    {
                        MessageBoxW(hwnd,L"VirtualAlloc in loop failed!",0,0);
                        VirtualFree(pBuffer,0,MEM_RELEASE);
                        return;
                    }
                    strncpy(pTemp,pLocate,pDellimiter - pLocate);
                    sscanf(pTemp,"%X-",&dwAddr);
                    _Quickinsertname(dwImageBase + dwAddr,NM_LABEL,strchr(pTemp,'-') + 1 * sizeof(unsigned char));
                    VirtualFree(pTemp,0,MEM_RELEASE);
                    pLocate = pDellimiter + 2;
                    pDellimiter = strstr(pLocate,"\r\n");
                }
                _Mergequicknames();
                VirtualFree(pBuffer,0,MEM_RELEASE);
                MessageBoxW(hwnd,L"I am done^ ^",L"CamelLu",MB_OK);
            }

        }
        else if (action == 1)
        {
            MessageBoxW(hwnd,L"CamelLu Functions\' Names Importer\r\nWritten by CamelLu 2011.7.19\r\n",L"Camellu",MB_ICONINFORMATION);
        }

}
OD插件的使用方法:
如果是原版的OD,直接把编译好的DLL放到od主程序的目录就可以了,看雪版的OD把DLL放到plugin目录下。

附件中包含了CamelLu.idc,CamelLu Functions' Names Importer插件的源代码以及编译好的DLL
PS.
我这个插件还有点问题,就是调试DLL的话不能用,因为我发现调试DLL的时候_Plugingetvalue(VAL_MAINBASE)函数得到的是LoadDll.exe的基址,基址一错自然写名称的地方就错啦= =!
好了,明天还要干活,回去睡觉去了
上传的附件 CamelLu.rar

  • 标 题:今天有空,修改了一下,对DLL也没问题了
  • 作 者:CamelLu
  • 时 间:2011-07-23 14:17:18

代码:
#include <windows.h>
#include <string.h>

#include "plugin.h"

#pragma comment(lib,"OLLYDBG.LIB")
static HINSTANCE hinst = NULL;
static HWND hwnd = NULL;
BOOL WINAPI DllEntryPoint(HINSTANCE hinstance,DWORD dwreason,LPVOID lpvreserved) 
{
    if (dwreason==DLL_PROCESS_ATTACH)
        hinst=hinstance;                          
    return 1;                           
}

//下面四个函数全都是插件回调函数,只有前两个函数是编写OD插件必须有的!!!
//ODBG_PluginData这个函数是必须有的,作用就是设置插件的名字(在OD的Plugin)
extc int _export cdecl ODBG_Plugindata(char shortname[32]) 
{
    strcpy(shortname,"CamelLu");       
    return PLUGIN_VERSION;
}
//ODBG_Plugininit这个函数也是必须有的,看名字就知道是用来做一些初始化工作啦
//ollydbgversion参数可以用来检查当前OD的版本,确保插件运行在兼容的OD版本上,hw是OD主窗口的句柄
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw,ulong *features) 
{
    if (ollydbgversion < PLUGIN_VERSION)
    {
        MessageBoxW(hw,L"CamelLu is not compatible with your Ollydbg version!",0,0);
        return -1;
    }
    hwnd = hw;
    return 0;
}

//ODBG_Pluginmenu这个函数是用来添加菜单的,每个菜单项之间用'|'字符隔开
extc int _export cdecl ODBG_Pluginmenu(int origin,char data[4096],void *item) 
{
    if (origin == PM_MAIN)
        strcpy(data,"0&Load functions\' names|1&About");
    return 1;
}
//ODBG_Pluginaction函数用于添加响应ODBG_Pluginmenu函数添加的菜单,很简单,看看下面的代码就明白了
extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item) 
{
    OPENFILENAME ofn;     
    wchar_t wszFile[MAX_PATH]; 
    unsigned char *pBuffer = NULL;
    unsigned char *pLocate = NULL;
    unsigned char *pDellimiter = NULL;
    unsigned char *pTemp = NULL;
    DWORD dwFileSize = 0;
    DWORD dwBytesRead = 0;
    DWORD dwImageBase = 0;
    DWORD dwAddr = 0;
    char szBuffer[10];
    t_table *table = NULL;
    t_sorted *sorted = NULL;
    t_module *module = NULL;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    int nIndex = 0;
    if (origin == PM_MAIN)
        if (action == 0)
        {
   
            ZeroMemory(&ofn, sizeof(ofn));
            ofn.lStructSize = sizeof(ofn);
            ofn.hwndOwner = hwnd;
            ofn.lpstrFile = wszFile;
            ofn.lpstrFile[0] = L'\0';
            ofn.nMaxFile = sizeof(wszFile);
            ofn.lpstrFilter = L".lu\0*.lu\0";
            ofn.nFilterIndex = 1;
            ofn.lpstrFileTitle = NULL;
            ofn.nMaxFileTitle = 0;
            ofn.lpstrInitialDir = NULL;
            ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

            if (GetOpenFileName(&ofn)==TRUE) 
            {
                if (STAT_NONE == _Getstatus())
                {
                    MessageBoxW(hwnd,L"No debugee now!!!",0,0);
                    return;
                }
                hFile = CreateFileW(
                    wszFile,
                    GENERIC_READ,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL);
                if (INVALID_HANDLE_VALUE == hFile)
                {
                    MessageBoxW(hwnd,L"Failed to open .lu file!",0,0);
                    return;
                }
                dwFileSize = GetFileSize(hFile,NULL);
                if (INVALID_FILE_SIZE == dwFileSize)
                {
                    MessageBoxW(hwnd,L"GetFileSize failed!",0,0);
                    CloseHandle(hFile);
                    return;
                }
                pBuffer = VirtualAlloc(
                    NULL,
                    dwFileSize + 1 * sizeof(unsigned char),
                    MEM_COMMIT,
                    PAGE_READWRITE
                    );
                if (NULL == pBuffer)
                {
                    MessageBoxW(hwnd,L"VirtualAlloc failed!",0,0);
                    CloseHandle(hFile);
                    return;
                }
                if (!ReadFile(
                    hFile,
                    pBuffer,
                    dwFileSize,
                    &dwBytesRead,
                    NULL)
                    )
                {
                    MessageBoxW(hwnd,L"ReadFile failed!",0,0);
                    VirtualFree(pBuffer,0,MEM_RELEASE);
                    CloseHandle(hFile);
                    return;
                }
                CloseHandle(hFile);
                table = (t_table*)_Plugingetvalue(VAL_MODULES);
                if (NULL == table)
                {
                    MessageBoxW(hwnd,L"Get modules failed!",0,0);
                    VirtualFree(pBuffer,0,MEM_RELEASE);
                    CloseHandle(hFile);
                    return;
                }
                sorted = &table->data;
                for (nIndex = 0;nIndex < sorted->n;++nIndex)
                {
                    module = (t_module *)((DWORD)sorted->data + nIndex * sorted->itemsize);
                    if (0 == strcmp(module->path,_Plugingetvalue(VAL_EXEFILENAME)))
                    {
                        dwImageBase = module->base;
                        break;
                    }
                }
                pLocate = pBuffer;
                pDellimiter = strstr(pLocate,"\r\n");
                while (*(pDellimiter + 2) != 0)
                {
                    pTemp = VirtualAlloc(NULL,pDellimiter - pLocate + 1 * sizeof(unsigned char),MEM_COMMIT,PAGE_READWRITE);
                    if (NULL == pTemp)
                    {
                        MessageBoxW(hwnd,L"VirtualAlloc in loop failed!",0,0);
                        VirtualFree(pBuffer,0,MEM_RELEASE);
                        return;
                    }
                    strncpy(pTemp,pLocate,pDellimiter - pLocate);
                    sscanf(pTemp,"%X-",&dwAddr);
                    _Quickinsertname(dwImageBase + dwAddr,NM_LABEL,strchr(pTemp,'-') + 1 * sizeof(unsigned char));
                    VirtualFree(pTemp,0,MEM_RELEASE);
                    pLocate = pDellimiter + 2;
                    pDellimiter = strstr(pLocate,"\r\n");
                }
                _Mergequicknames();
                VirtualFree(pBuffer,0,MEM_RELEASE);
                MessageBoxW(hwnd,L"I am done^ ^",L"CamelLu",MB_OK);
            }

        }
        else if (action == 1)
        {
            MessageBoxW(hwnd,L"CamelLu Functions\' Names Importer\r\nWritten by CamelLu 2011.7.19\r\n",L"Camellu",MB_ICONINFORMATION);
        }

}
请下载本楼层的附件吧
上传的附件 CamelLu.7z