首先感谢天草老师,这些天跟他学习到了不少东西。这个其实是他布置的作业,给大家分享下成果。
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; }
代码:
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; }
代码:
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; }
代码:
BOOL CPEArmor046UnPack::fixOEP() { __try { DWORD oep = GETDWORD(shellstart2 + 0x2C8); *(PDWORD((DWORD)pPEImage + 0x28)) = oep; fixSpecialApiEncode(); } __except(EXCEPTION_EXECUTE_HANDLER) { return FALSE; } return TRUE; }
最后dump就OK了。只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!