编写OD插件将IDA中分析出来的函数名导入到OD中

逆向程序的时候,喜欢用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插件

VS环境设置为  Use Multi-Byte Character Set

如果提示“Please set default char type to unsigned (option /J)”  解决方案如下:

  1. In Solution Explorer,open the shortcut menu for the project and then chooseProperties.

  2. In the project Property Pages dialog Box,in the left pane underConfiguration Properties,expand C/C++ and then selectCommand Line.

  3. In the Additional Options pane,specify the/J compiler option.

需要注意的是 如果是用VS2012编译 在XP上OD启动加在这插件会报错,找不到“msvcr110.dll” 但是XP上最多支持msvcr100.dll 即便找来了msvcr110.dll注册它 也是要出错的 所以如果需要在XP上的OD运行该插件 用VS2010编译该插件就行 VS2012编译只能在WIN7 WIN8的OD上运行

#include <windows.h>
#include <Commdlg.h>	//for GetopenFileName function.
#include <tchar.h>		//for _tcscpy_s ... function.
#include <stdlib.h>		//for _countof ... function.
#include <Shlwapi.h>	//for String function of windows.
#include <strsafe.h>	//for StringCchPrintf ... function.

#include "plugin.h"  
#pragma comment(lib,"OLLYDBG.LIB")  

static HWND hwnd = NULL;  

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved
					  )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:     
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

//下面四个函数全都是插件回调函数,只有前两个函数是编写OD插件必须有的!!!  
//ODBG_PluginData这个函数是必须有的,作用就是设置插件的名字(在OD的Plugin)  
extc int _export cdecl ODBG_Plugindata(TCHAR shortname[32])   
{  

	strcpy_s(shortname,32,"IDA2OD");     

	return PLUGIN_VERSION;  
}  
//ODBG_Plugininit这个函数也是必须有的,看名字就知道是用来做一些初始化工作啦  
//ollydbgversion参数可以用来检查当前OD的版本,确保插件运行在兼容的OD版本上,hw是OD主窗口的句柄  
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw,DWORD *features)   
{  
	if (ollydbgversion < PLUGIN_VERSION)  
	{  
		MessageBox(hw,TEXT("CamelLu is not compatible with your Ollydbg version!"),0);  
		return -1;  
	}  
	hwnd = hw;  
	return 0;  
}  

//ODBG_Pluginmenu这个函数是用来添加菜单的,每个菜单项之间用'|'字符隔开  
extc int _export cdecl ODBG_Pluginmenu(int origin,TCHAR data[4096],VOID *item)   
{  
	if (origin == PM_MAIN)  
	{
		strcpy_s(data,4096,"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;       
	TCHAR wszFile[MAX_PATH];   
	PTSTR pBuffer = NULL;  
	PTSTR pLocate = NULL;  
	PTSTR pDellimiter = NULL;  
	PTSTR pTemp = NULL;  
	DWORD dwFileSize = 0;  
	DWORD dwBytesRead = 0;  
	DWORD dwImageBase = 0;  
	DWORD dwAddr = 0;   
	int	nSize;
	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] = '\0';  
			ofn.nMaxFile = _countof(wszFile);  
			ofn.lpstrFilter = TEXT(".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())  
				{  
					MessageBox(hwnd,TEXT("No debugee Now!!!"),0);  
					return;  
				}  
				hFile = CreateFile(  
					wszFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_norMAL,NULL);  
				if (INVALID_HANDLE_VALUE == hFile)  
				{  
					MessageBox(hwnd,TEXT("Failed to open .lu file!"),0);  
					return;  
				}  
				dwFileSize = GetFileSize(hFile,NULL);  
				if (INVALID_FILE_SIZE == dwFileSize)  
				{  
					MessageBox(hwnd,TEXT("GetFileSize Failed!"),0);  
					CloseHandle(hFile);  
					return;  
				}  
				pBuffer = (PTSTR)VirtualAlloc(  
					NULL,dwFileSize + sizeof(TCHAR),MEM_COMMIT,PAGE_READWRITE  
					);  
				if (NULL == pBuffer)  
				{  
					MessageBox(hwnd,TEXT("VirtualAlloc Failed!"),0);  
					CloseHandle(hFile);  
					return;  
				}  
				if (!ReadFile(  
					hFile,pBuffer,dwFileSize,&dwBytesRead,NULL)  
					)  
				{  
					MessageBox(hwnd,TEXT("ReadFile Failed!"),0);  
					VirtualFree(pBuffer,MEM_RELEASE);  
					CloseHandle(hFile);  
					return;  
				}  
				CloseHandle(hFile);  
				table = (t_table*)_Plugingetvalue(VAL_MODULES);  
				if (NULL == table)  
				{  
					MessageBox(hwnd,TEXT("Get modules Failed!"),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,(char *)_Plugingetvalue(VAL_EXEFILENAME)))  
					{  
						dwImageBase = module->base;  
						break;  
					}  
				}  
				pLocate = pBuffer;  
				pDellimiter = strstr(pLocate,"\r\n");  
				while (*(pDellimiter + 2) != 0)  
				{  
					nSize = pDellimiter - pLocate +  sizeof(TCHAR);
					pTemp = (PTSTR)VirtualAlloc(NULL,nSize,PAGE_READWRITE);  
					if (NULL == pTemp)  
					{  
						MessageBox(hwnd,TEXT("VirtualAlloc in loop Failed!"),0);  
						VirtualFree(pBuffer,MEM_RELEASE);  
						return;  
					}  

					strncpy_s(pTemp,pLocate,pDellimiter - pLocate);  
                    sscanf_s(pTemp,"%X-",&dwAddr);  
					
					_Quickinsertname(dwImageBase + dwAddr,NM_LABEL,strchr(pTemp,'-') + sizeof(TCHAR)); 
					VirtualFree(pTemp,MEM_RELEASE);  
					pLocate = pDellimiter + 2;  
					pDellimiter = strstr (pLocate,"\r\n");  
				}  
				_Mergequicknames();  
				VirtualFree(pBuffer,MEM_RELEASE);  
				MessageBox(hwnd,TEXT("I am done^ ^"),TEXT("CamelLu"),MB_OK);  
			}  

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

}  

OD插件的使用方法

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

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...