-
-
[原创]PEArmor 0.46 静态脱壳机原理及源码
-
发表于:
2009-3-12 22:41
10273
-
[原创]PEArmor 0.46 静态脱壳机原理及源码
首先感谢天草老师,这些天跟他学习到了不少东西。这个其实是他布置的作业,给大家分享下成果。
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;
}
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;
}
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;
}
[注意]APP应用上架合规检测服务,协助应用顺利上架!