首页
社区
课程
招聘
[原创]IDB2EXE.idc 一个从IDB文件生成EXE文件的idc脚本示例
2010-1-6 16:15 21114

[原创]IDB2EXE.idc 一个从IDB文件生成EXE文件的idc脚本示例

2010-1-6 16:15
21114
#include <idc.idc>

//
//+++++++++++++++++++++++++++++++++++++++++++++
//
// IDB2EXE.idc 
//
// Written by Spark.   nkspark_at_gmail.com
// 
//          2010.01.06
//+++++++++++++++++++++++++++++++++++++++++++++
//

#define E_MAGIC 							0x5a4d
#define E_LFANEW							0xe0
#define E_LFANEW_OFFSET				0x3c
#define SIGNATURE 						0x00004550
#define MACHINE								0x014c
#define SECTIONNUMBER_OFFSET	0x06
#define IAT_OFFSET						0x80
#define PEHEADERLENGTH				0xf8
#define SECTIONTABLE_OFFSET		E_LFANEW + PEHEADERLENGTH
#define SECTIONENTRYLENGTH		0x28


static GetIDBFilePath()
{
	auto strIDBFilePath;//idb full path name;
	auto strEXEFileName;
	auto iNameEnd;
	auto iPathEnd;
	auto strPath;
	auto pFile;
	
	strPath = GetInputFilePath();
	strEXEFileName = GetInputFile();
	iPathEnd = strstr(strPath,strEXEFileName);
	iNameEnd = strstr(strEXEFileName,".");
	strIDBFilePath = substr(strPath,0,iPathEnd) + substr(strEXEFileName,0,iNameEnd) + ".idb";
	
	//Message("idb file lies in %s\n",strIDBFilePath);
	
	pFile = fopen(strIDBFilePath,"r");
	if(!pFile)
	{
		strIDBFilePath = AskStr(strIDBFilePath,"Please provide the path of IDB file:");
		return strIDBFilePath;
	}
	fclose(pFile);
	return 	strIDBFilePath;
}

//从IDB文件中获取IAT的偏移地址
static GetIATOffset(strIDBFilePath, PEHeaderOffset)
{
		auto pIDB;
		auto IATOffset;
		
		pIDB =fopen(strIDBFilePath,"rb");

		if(!pIDB)
		{
			Message("Can not open idb file!\n");
			return -1;
		}
		
		fseek(pIDB,PEHeaderOffset + IAT_OFFSET,0);
		IATOffset = readlong(pIDB,0);

		fclose(pIDB);
		return IATOffset;
	
}

//从IDB文件中获取PE头的起始地址
static SearchPEHeader(pIDB)
{
		auto PEHeaderOffset;
		auto i;
		auto iFileSize;
		
		
		fseek(pIDB,0x0,2);
		iFileSize = ftell(pIDB);
		
		if( iFileSize == -1)
			return -1;
		
		for(i=0;i<iFileSize;i++)
		{
			fseek(pIDB,i,0);
			//Signature "PE"
			if(readlong(pIDB,0) == SIGNATURE)
				//Machine 0x014c
				if(readshort(pIDB,0) == MACHINE)
				{
					PEHeaderOffset=ftell(pIDB);
					PEHeaderOffset = PEHeaderOffset -0x06;
					return PEHeaderOffset;					
				}
		}		
		return -1;
}

//IDB中的FirstThrunk已经被IDA自动填充,需要清理回原状
static PatchIAT(addrImageBase, addrIAT)
{		
		auto addrOriginalFirstThunk;
		auto addrFirstThunk;
		auto ValueOfIAT;
		
		Message("Start patching IAT at %x\n",addrIAT);
		
		if(Dword(addrIAT) == BADADDR)
		{
			Message("IAT data was not loaded into IDB file!\n");
			return -1;
		}
		
		do
		{
			addrOriginalFirstThunk = addrImageBase + Dword(addrIAT);
			addrFirstThunk = addrImageBase + Dword(addrIAT+0x10);
			
			do
			{
				PatchDword(addrFirstThunk,Dword(addrOriginalFirstThunk));
				addrOriginalFirstThunk = addrOriginalFirstThunk +0x04;
				addrFirstThunk = addrFirstThunk +0x04;
									
			}while(Dword(addrOriginalFirstThunk) != 0);
			
			addrIAT = addrIAT + 0x14;
			
		}while(Dword(addrIAT) != 0);
		
}

//为创建的EXE文件生成一个PE头
static BuildHeader(pFile,strIDBFilePath)
{
		auto i,j;
		auto pIDB;
		auto addrPE;
		auto iSectionNumber;
		auto lByte;

		pIDB =fopen(strIDBFilePath,"rb");
		if(!pIDB)
		{
			Message("Can not open idb file!\n");
			return -1;
		}
		
		fseek(pFile,0x0,0);
		writeshort(pFile,E_MAGIC,0);
		fseek(pFile,E_LFANEW_OFFSET,0);
		writeshort(pFile,E_LFANEW,0);
		
		
		addrPE = SearchPEHeader(pIDB);
		if(addrPE == -1)
		{
			Message("Can not find PE header in IDB file!\n");
			return -1;
		}
		Message("PEHeaderOffset is %x\n",addrPE);
		
		fseek(pIDB,addrPE,0);
		fseek(pFile,E_LFANEW,0);
		
		//Copy PE header
		//IAT should be set to 0 later!!!
		for(i=0;i<PEHEADERLENGTH;i++)
		{
				lByte = fgetc(pIDB);
				fputc(lByte,pFile);
		}

		fseek(pIDB,addrPE+SECTIONNUMBER_OFFSET,0);
		
		iSectionNumber = fgetc(pIDB);
					
		Message("there are %d sections!\n",iSectionNumber);
		
		//Prepare to write section table
		fseek(pFile,SECTIONTABLE_OFFSET,0);
		fseek(pIDB,addrPE+SECTIONTABLE_OFFSET-E_LFANEW,0);
		
		for(j=0;j<iSectionNumber;j++)
		{
			
			//每个表项有6字节偏移;
			fseek(pIDB,6,1);
			//最后一个表项有多余4字节偏移;
			if(j == (iSectionNumber-1))
				fseek(pIDB,4,1);
			
			
			//section table should be corrected later!!!!		
			for(i=0;i<SECTIONENTRYLENGTH;i++)
			{
					lByte = fgetc(pIDB);
					fputc(lByte,pFile);
			}
			Message("write %d section table!\n",j);
		}
		fclose(pIDB);
		
		//返回addrPE以备后用 :)
		return addrPE;
		
}

//内存地址转换为文件地址
static RVA2FA(pFile)
{
		auto iSectionNumber;
		auto iSectionBase;
		auto i;
		
		fseek(pFile,E_LFANEW + SECTIONNUMBER_OFFSET,0);
		iSectionNumber = readshort(pFile,0);

		fseek(pFile,SECTIONTABLE_OFFSET + (iSectionNumber -1) * SECTIONENTRYLENGTH + 0x14,0);
		iSectionBase = readlong(pFile,0);			
		Message("Section base in exe file is %x\n",iSectionBase);

		return iSectionBase;
		
}
//修正PE头信息
static PEHeaderCorrect(pFile)
{
		//关键处理,暂不外传!
		return 0;
}

static main()
{
	auto temp,i;
	auto startAddr, endAddr;
	auto countOR;
	auto pFile;
	auto strOutFileName;
	auto segStart;
	auto segEnd;
	auto iImageBase;
	auto iSectionAlignment;
	auto PEHeaderOffset;
	auto IATOffset;
	auto strIDBFilePath;
	auto iSectionBase;

	startAddr = MinEA();
	endAddr = MaxEA();
	iImageBase = FirstSeg() & 0xffff0000;
	iSectionAlignment = FirstSeg() & 0xffff;
	
	Message("Base:%x ,EP:%x , Min:%x  , Max:%x  \n",iImageBase,BeginEA(),MinEA(),MaxEA());
	
	strIDBFilePath = GetIDBFilePath();
	Message("idb file lies in %s\n",strIDBFilePath);
	
	strOutFileName = strIDBFilePath + "_dump.exe";

	pFile=fopen(strOutFileName,"w+b");
	
	PEHeaderOffset = BuildHeader(pFile,strIDBFilePath);
	if (PEHeaderOffset == -1)
		return -1;
		
	IATOffset = GetIATOffset(strIDBFilePath,PEHeaderOffset);
	if (IATOffset == -1)
		return -1;
		
	iSectionBase = RVA2FA(pFile);

	PatchIAT(iImageBase,iImageBase + IATOffset);
	
	for(i=startAddr;i<endAddr;)
	{
		segStart = GetSegmentAttr(i,SEGATTR_START);
		if(segStart == BADADDR) break;
		segEnd = GetSegmentAttr(i,SEGATTR_END);
		if(segEnd == BADADDR) break;		
		savefile(pFile, iSectionBase + segStart - iImageBase -iSectionAlignment,segStart,segEnd-segStart);
		Message("seg %x : %x : %x \n",GetSegmentAttr(i,SEGATTR_ALIGN),segStart,segEnd);
		i = segEnd + 1;
	}
	
	PEHeaderCorrect(pFile);
	
	fclose(pFile);
	
	return 0;
}


关键两点:
1、建立一个PE头。这个可以直接从IDB的原始文件中提取,可能好多人没想到。知道这一点后,基本上就可以自己写这个脚本了。
2、PE头修正。导出的EXE文件如果不修正的话,可能会跑不起来,例如IDA缺省情况下是不加载资源节的,这时导出的是不完整的EXE文件。我的自用版本可以让不完整的导出EXE正常跑到资源加载处正常退出。自用版本这里就不公开了,有人出高价的话,我可以卖给他 :)

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (25)
雪    币: 291
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leking 2010-1-6 22:26
2
0
可以从IDB的原始文件中恢复成EXE?太强大了吧
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
cntrump 13 2010-1-6 22:35
3
0
so cool !
雪    币: 255
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
五条 2010-1-7 10:23
4
0
自用版本这里公开吧
雪    币: 1379
活跃值: (708)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hmilywen 2010-1-7 16:28
5
0
膜拜啊!
雪    币: 429
活跃值: (1875)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 41 2010-1-7 16:36
6
0
膜拜LZ!!!
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
jackozoo 14 2010-1-7 17:15
7
0
thx LZ.
mark, 学习一下``
雪    币: 147
活跃值: (11)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xflin 2010-1-7 18:55
8
0
LZ的强悍,不需要解释
雪    币: 130
活跃值: (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ouyangtian 2010-1-8 17:02
9
0
wonderful, you are awesome
雪    币: 496
活跃值: (89)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
moodykeke 2010-1-8 21:11
10
0
强大。收藏。
雪    币: 134
活跃值: (84)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
NWMonster 1 2010-1-9 20:44
11
0
太强大了,太暴力了
雪    币: 4902
活跃值: (90)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
奘和 2010-1-9 21:40
12
0
彪悍不需要理由
俺比较想知道暂不外传的那部分
雪    币: 210
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
徐立岩 2010-1-12 09:41
13
0
很强大,进来学习下。
雪    币: 383
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hldgaofeng 2010-1-12 18:07
14
0
有何用处呢?
雪    币: 107
活跃值: (311)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Fido 2010-1-15 08:55
15
0
这个还是要关注的........
雪    币: 9085
活跃值: (1450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hxsoft 2010-1-15 10:13
16
0
想要大大的自用版本啊!
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小原 2010-4-8 11:37
17
0
非常强大 无法膜拜了 直接**吧 用力顶
雪    币: 58
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
skybright 2010-4-23 11:46
18
0
膜拜下lz。。。。
雪    币: 79
活跃值: (30)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
nnhy 3 2010-5-22 20:42
19
0
我不明白,IDB生成EXE有什么价值
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cnsgp 2010-6-4 22:30
20
0
不是一般的牛!是天牛!
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
OldBody 2010-11-5 12:08
21
0
Mark !
雪    币: 172
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wangshen 2011-2-8 18:08
22
0
强大。。模拜。。可惜不完整
雪    币: 234
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
tygyxyw 2011-2-23 08:38
23
0
在5.5中最后一个表项有多余96字节偏移
雪    币: 154
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leeonegor 2011-2-23 08:43
24
0
膜拜
雪    币: 53
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
nomaster 2011-2-23 09:08
25
0
同问....
游客
登录 | 注册 方可回帖
返回