首页
社区
课程
招聘
[原创]PEArmor 0.46 静态脱壳机原理及源码
发表于: 2009-3-12 22:41 9949

[原创]PEArmor 0.46 静态脱壳机原理及源码

2009-3-12 22:41
9949
  首先感谢天草老师,这些天跟他学习到了不少东西。这个其实是他布置的作业,给大家分享下成果。
      PEArmor这个壳特点:1、aplib压缩 2、IAT加密 3、程序Call和Jmp跳入壳里然后解密执行真api(不知道密届术语)。壳分两层外壳,第一层解压出第二层外壳,然后跳入第二层外壳去执行(第二层开始处大量花),第二层解压出各个段,接着还原IAT,再根据加密表把程序代码里的 call和jmp指向外壳,跳向oep。
    首先我找第一层壳的入口,找需要解压二层外壳所需要的相关数据的偏移,解压二层外壳。
	//*************************************************************************
	//搜索特征码,在壳第一层找真正壳代码入口。
	//*************************************************************************
	BYTE szPCode1[] = "\x5D\x81\xED\x05\x00\x00\x00\x8D\x75\x3D\x56";
	shellstart = searchMem(pPEImage,szPCode1,sizeof(szPCode1));
	if (shellstart == NULL)
	{
		return FALSE;
	}

BYTE * FistPackBaseAddr = NULL;
	DWORD  dwFirstPackSize = 0;   
	HANDLE hFistPackTempMem = 0;
//*************************************************************************
//    解压第二层外壳
 //*************************************************************************
	   __try
	   {
		   FistPackBaseAddr = shellstart - 0xAF;
		   dwFirstPackSize  = GETDWORD(FistPackBaseAddr + 0x82);
		   hFistPackTempMem = VirtualAlloc(NULL,dwFirstPackSize, MEM_COMMIT, PAGE_READWRITE);
		   aP_depack_asm((PVOID)(GETDWORD(FistPackBaseAddr+0x7e)+FistPackBaseAddr),(PVOID)hFistPackTempMem);
	   }
	   __except(EXCEPTION_EXECUTE_HANDLER)
	   {
		   VirtualFree(hFistPackTempMem,dwFirstPackSize,MEM_RELEASE);
		   return FALSE;
	   }

//*************************************************************************
//搜索特征码,在壳第二层找真正壳代码入口(跳过无数花,准确定位,同时也确认是当前版本的壳)。
//*************************************************************************

	   BYTE szPCode2[] = "\xE8\x00\x00\x00\x00\x5A\x83\xEA\x05\x5D\xB9\x03\x00\x00\x00";
	   
	   shellstart2 = searchMem((BYTE *)hFistPackTempMem,szPCode2,sizeof(szPCode2));
	   
	   if (shellstart2 == NULL)
	   {
		   return FALSE;
	   }

      接下来就是要解压PE的各个区段的真真数据了。
BOOL CPEArmor046UnPack::unPackEachSection()
{

	   __try
	   {
		   DWORD dwOffset = 0x2ED;
		   while (GETDWORD(shellstart2 + dwOffset)!=0)
		   {
			   DWORD dwCurrentSectionSize = GETDWORD(shellstart2 + dwOffset);
			   HANDLE hEachSectionTempMem = VirtualAlloc(NULL,dwCurrentSectionSize, MEM_COMMIT, PAGE_READWRITE);
			   DWORD dwEachSectionPackDataAddr = GETDWORD(shellstart2 + dwOffset + 0x4) + (DWORD)pImage;
			   aP_depack_asm((PVOID)(dwEachSectionPackDataAddr),(PVOID)hEachSectionTempMem);
			   memcpy((PVOID)dwEachSectionPackDataAddr,(PVOID)hEachSectionTempMem,dwCurrentSectionSize);
			   VirtualFree(hEachSectionTempMem,dwCurrentSectionSize,MEM_RELEASE);
			   dwOffset += 0xC;
		   }
	   }
	   
	   __except(EXCEPTION_EXECUTE_HANDLER)
	   {
		   return FALSE;
	   }
	   return TRUE;
}

       分析IAT,找出修复IAT需要的数据存入Vector。
BOOL CPEArmor046UnPack::analyzeImportTable()
{

				
	__try{
		
		BOOL blApiStrShuffle  = GETDWORD(shellstart2 + 0x2B8) == 1?TRUE:FALSE;
		
		
		if (blApiStrShuffle)  //IAT加密方式1
		{
			DWORD dwOrgImportaddr  = GETDWORD(shellstart2 + 0x2c0) + (DWORD)shellstart2;
			while (TRUE)
			{
				if (GETDWORD((PDWORD)(dwOrgImportaddr))==0)
				{
					break;
				}
				STOrgImport stOrgImportDataTemp ;
				stOrgImportDataTemp.dwThunkTable = GETDWORD((PDWORD)(dwOrgImportaddr));
				stOrgImportDataTemp.strdllName.assign((char *)(dwOrgImportaddr+5));
				stOrgImportDataTemp.dwApiNumber = GETDWORD((PBYTE)(dwOrgImportaddr + 5 + GETBYTE((PBYTE)(dwOrgImportaddr + 4)) + 1));
				dwOrgImportaddr = dwOrgImportaddr + 5 + GETBYTE(dwOrgImportaddr + 4) +5;
				BOOL blIsApiOrd = GETBYTE(dwOrgImportaddr)==0?TRUE:FALSE;
				stOrgImportDataTemp.isOrd = blIsApiOrd;
				if (blIsApiOrd) //序号
				{
					for (int i = 0 ; i < stOrgImportDataTemp.dwApiNumber;i++)
					{
						DWORD dwApiOrg = GETDWORD(dwOrgImportaddr+1);
						stOrgImportDataTemp.vecApiOrd.push_back(dwApiOrg);
						dwOrgImportaddr = dwOrgImportaddr + 1 + sizeof(DWORD) + 1;
					}
				}
				else  //APi名
				{
					for (int i = 0 ; i < stOrgImportDataTemp.dwApiNumber;i++)
					{
						string strApiName;
						strApiName.assign((char *)(dwOrgImportaddr+1));
						stOrgImportDataTemp.vecApiName.push_back(strApiName);
						dwOrgImportaddr = dwOrgImportaddr + 1 + GETBYTE(dwOrgImportaddr)+1;
					}
				}
				
				vecImport.push_back(stOrgImportDataTemp);
				
			}
			
		}
		else  // IAT不自定义存储格式的 (IAT加密方式2)
		{
			DWORD dwDllBase = GETDWORD(shellstart2 + 0x2c0) + (DWORD)pImage;
			
			DWORD dwApiOrdOrName = NULL;
			DWORD dwIatAddr = NULL;
			while(TRUE)
			{
				
				DWORD dwDllNameAddr = GETDWORD((PBYTE)dwDllBase + 0xc);
				if (dwDllNameAddr != 0)
				{
					
					dwDllNameAddr = dwDllNameAddr + (DWORD)pImage; //dllname
					
					
					if (GETDWORD(dwDllBase) !=0)
					{
						dwApiOrdOrName = GETDWORD(dwDllBase) + (DWORD)pImage;
						dwIatAddr = GETDWORD(dwDllBase + 0x10)+(DWORD)pImage;
					}
					else
					{
						dwApiOrdOrName = GETDWORD(dwDllBase + 0x10) + (DWORD)pImage;
						dwIatAddr = GETDWORD(dwDllBase + 0x10)+(DWORD)pImage;
					}
					
					
					STOrgImport stOrgImportDataTemp;
					if (GETDWORD(dwApiOrdOrName) & 0x80000000)
					{
						stOrgImportDataTemp.isOrd = TRUE;
					}
					else
					{
						stOrgImportDataTemp.isOrd = FALSE;
					}
					stOrgImportDataTemp.dwThunkTable = dwIatAddr - (DWORD)pImage;
					stOrgImportDataTemp.strdllName.assign((char *)dwDllNameAddr);
					
					
					
					while(TRUE)
					{
						if (GETDWORD(dwApiOrdOrName) == 0)
						{
							dwDllBase = dwDllBase + 0x14;
							
							vecImport.push_back(stOrgImportDataTemp);
							break;
						}
						else
						{
							//处理
							
							if ( GETDWORD(dwApiOrdOrName) & 0x80000000 )
							{
								DWORD dwOrd = GETDWORD(dwApiOrdOrName) & 0x7fffffff;
								stOrgImportDataTemp.vecApiOrd.push_back(dwOrd);
							}
							else
							{
								DWORD dwApiNameAddr = (GETDWORD(dwApiOrdOrName) + 2 ) + (DWORD)pImage;
								string strApiName;
								strApiName.assign((char *)dwApiNameAddr);
								stOrgImportDataTemp.vecApiName.push_back(strApiName);
							}
							
							dwApiOrdOrName = dwApiOrdOrName + 0x4;
							
							dwIatAddr = dwIatAddr + 0x4;
						}
					}
					
					
				}
				else
				{
					break;
				}
			}
		}
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			return FALSE;
		}
		return TRUE;
}

         根据分析的数据修复IAT。
BOOL CPEArmor046UnPack::fixImportTable()
{

	__try{
		
		DWORD dwDLLNumber = vecImport.size();
		BYTE * NewImportAddrSave = this->addNewImportSectionAddr;
		BYTE * temppoint = (BYTE *)(this->addNewImportSectionAddr+(dwDLLNumber + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR));
		for(vector<STOrgImport>::iterator it = vecImport.begin(); it != vecImport.end();++it)
		{
			
			IMAGE_IMPORT_DESCRIPTOR STNewIID = {0};
			string strDllName = it->strdllName;
			strDllName.copy((char *)temppoint,strDllName.length(),0);//复制到新增区域
			// fill IID struct
			STNewIID.FirstThunk = it->dwThunkTable;
			STNewIID.Name = (DWORD)(temppoint-pImage);
			STNewIID.OriginalFirstThunk=0;
			
			
			temppoint += strDllName.length() + 1 + 2; //加三个零
			
			PDWORD iat = (PDWORD)(STNewIID.FirstThunk + (DWORD)pImage);
			
			//序号方式处理
			if (it->isOrd)
			{
				for(vector<DWORD>::iterator itapi = it->vecApiOrd.begin(); itapi != it->vecApiOrd.end();++itapi)
				{
					*iat = *itapi | 0x80000000;
					iat++;
				}
			}
			else //APi名字方式处理
			{
				for(vector<string>::iterator itapi = it->vecApiName.begin(); itapi != it->vecApiName.end();++itapi)
				{
					itapi->copy((char *)temppoint,(*itapi).length());
					
					*iat = temppoint - 2 - pImage;
					iat++;
					temppoint += (*itapi).length() + 1 + 2;//加三个零
				}
				
			}
			*iat = 0;
			
			memcpy((PVOID)NewImportAddrSave,(PVOID)&STNewIID,sizeof(IMAGE_IMPORT_DESCRIPTOR));
			NewImportAddrSave += sizeof(IMAGE_IMPORT_DESCRIPTOR);
		}
		
		((PIMAGE_NT_HEADERS)pPEImage)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = this->addNewImportSectionAddr - pImage;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	return TRUE;
}

        修复壳里的Call和Jmp。按hying的说法,这里叫特殊代码处理
BOOL CPEArmor046UnPack::fixSpecialApiEncode()
{

	
	__try{
		
		DWORD ApiIsEncode = GETDWORD(shellstart2 + 0x2BC);
		
		if (ApiIsEncode == 1) //是否特殊代码处理 FF 15 或 FF 25
		{
			
			//修复Api 
			
			DWORD dwDecodeTable =  GETDWORD(shellstart2 + 0x2c4) + (DWORD)shellstart2;
			while ( (*(PDWORD)dwDecodeTable) != 0)
			{
				DWORD dwDecodeVal = *(PDWORD)dwDecodeTable;
				
				dwDecodeVal = dwDecodeVal  << 1;
				dwDecodeVal = dwDecodeVal >> 1;
				
				if( ( *((PBYTE)dwDecodeTable+3) ) == 0x80 )
				{
					//25ff
					DWORD dwDecodeIAT = *(PDWORD)(dwDecodeTable + 4);
					dwDecodeVal = dwDecodeVal - (DWORD)pe.ImageBase() + (DWORD)pImage;
					*((PWORD)(dwDecodeVal - 6)) = 0x25ff;
					*((PDWORD)(dwDecodeVal - 4)) = dwDecodeIAT;
				}
				else
				{
					DWORD dwDecodeIAT = *(PDWORD)(dwDecodeTable + 4);
					dwDecodeVal = dwDecodeVal - (DWORD)pe.ImageBase() + (DWORD)pImage;
					*((PWORD)(dwDecodeVal - 6)) = 0x15ff;
					*((PDWORD)(dwDecodeVal - 4)) = dwDecodeIAT;
				}
				dwDecodeTable = dwDecodeTable + 8;
			}
			
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	return TRUE;
}

         修复OEP。
BOOL CPEArmor046UnPack::fixOEP()
{
	
	__try
	{
		
		DWORD oep = GETDWORD(shellstart2 + 0x2C8);
		*(PDWORD((DWORD)pPEImage + 0x28)) = oep;
		
		fixSpecialApiEncode();
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	return TRUE;
}

         源代码下载:http://files.cnblogs.com/zhujian198/PEArmorperfectionUnpackOOP.rar
          最后dump就OK了。只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (7)
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好文,学习,感谢分享
2009-3-13 12:39
0
雪    币: 304
活跃值: (82)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
3
终于看到c++版的脱壳机了
2009-3-14 10:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
那位大牛转换成delphi的就好了
2009-3-19 09:44
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
做个现成的注册机不是更好吗?
2009-3-21 21:56
0
雪    币: 1254
活跃值: (625)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
注册机,这个跟注册机有什么关系?请教下。
2009-3-21 22:38
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
太牛叉了,终于见到VC源代码注册机了,非常感谢LZ分享。

带[Overlay]加PEArmor 0.46壳的软件,脱壳时在分析IAT的时候失败了 ,怎么回事?
2009-5-12 03:33
0
雪    币: 116
活跃值: (56)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
c++........好文,学习,感谢LZ
2009-5-14 09:51
0
游客
登录 | 注册 方可回帖
返回
//