能力值:
( LV13,RANK:520 )
|
-
-
2 楼
iat 可以移动,
但是很复杂.
给你提供两个思路.
1. 利用反汇编引擎找出所有数据.修改.
2. 把iat清空, 利用veh一个个捕获.把所有异常的地址,纪录下来,做成一个表,就像relocation那样.
然后再修改表格中地址指向的数据, 即 "IAT"
不知道对你有没有帮助.
|
能力值:
(RANK:1290 )
|
-
-
4 楼
很简单的。 遍历代码节把所有引用找出来 然后记录。 修改以后在重新自己填充一遍就OK。 貌似我OPEN SOURCE过
|
能力值:
(RANK:1290 )
|
-
-
5 楼
貌似以前没在论坛上发过。 以下是加解密函数。 很简单遍历代码节把引用都找出来判断是否是IAT的范围内 是就抽出来记录。 解密时重新构造表填充。 再把原先的位置指定到新的位置 收功。
/*
* 介绍:
* 力量解密引入表
*
* 参数:
* pMem:要保护函数的映射
* addrOrigImageBase:要保护函数原先的基地址
* pImportProtect:引入表保护结构指针
* bOnFile:是否是文件
* ofJmpTableRva:新的引入跳转表的RVA
*/
PREFERENCE_IMPORT_TABLE_ADDRESS __API__ PowerEncryptImportTable(__memory pMem, __address addrOrigImageBase, PIMPORT_PROTECT pImportProtect, __bool bOnFile, __offset ofJmpTableRva) {
__byte bXor = 0;
__memory pCodeStart = NULL;
__integer iCodeSize = 0;
__integer iProcCount = 0, iLibCount = 0, iIndex = 0;
__address addrImageBase = 0;
__address addrCurrOrigImageBase = 0;
__address OrigJmpAddressTable[__MAX_JMP_ADDRESS_TABLE_COUNT__] = {0};
__bool JmpAddressTableMakeSure[__MAX_JMP_ADDRESS_TABLE_COUNT__] = {0};//用于确认当前位置是否被占用
JMPTABLE_TO_ADDRESS JmpTableToAddressList[__MAX_JMP_ADDRESS_TABLE_COUNT__] = {0};
__integer iJmpAddressTableCount = 0;
__dword *pJmpAddressTableRva = NULL;
__address addrNowAddress = 0;
PIMAGE_NT_HEADERS pNtHdr = NULL;
PIMAGE_DATA_DIRECTORY pImageImportDataDirectory = NULL;
PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = NULL;
ud_t ud_obj = {0};
PREFERENCE_IMPORT_TABLE_ADDRESS pReferenceImportTableAddres = NULL;
PREFERENCE_IMPORT_TABLE_ADDRESS *pCurrReferenceImportTableAddresPoint = &pReferenceImportTableAddres;
// 初始化数据
pImageImportDataDirectory = ExistDataDirectory(pMem, IMAGE_DIRECTORY_ENTRY_IMPORT);
if (!pImageImportDataDirectory)
return NULL;
/*
* 获取目标映射的基地址
* 要修复的基地址可以通过函数的参数addrOrigImageBase指定,如果addrOrigImageBase == 0xFFFFFFFF则使用
* addrImageBase,如果addrOrigImageBase != 0xFFFFFFFF,则使用addrOrigImageBase
*/
pNtHdr = GetNtHeader(pMem);
addrImageBase = pImportProtect->addrImageBase;
// 获取目标文件代码段的地址与长度
if (bOnFile) {
//addrImageBase = (__address)(pNtHdr->OptionalHeader.ImageBase);
pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(pMem + Rva2Raw(pMem, pImageImportDataDirectory->VirtualAddress));
pCodeStart = pMem + GetEntryPointSection(pMem)->PointerToRawData;
} else {
//addrImageBase = (__address)pMem;
pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)__RvaToVa__(pMem, pImageImportDataDirectory->VirtualAddress);
pCodeStart = pMem + GetEntryPointSection(pMem)->VirtualAddress;
}
iCodeSize = GetEntryPointSection(pMem)->Misc.VirtualSize;
__logic_memset__(JmpAddressTableMakeSure, FALSE, __MAX_JMP_ADDRESS_TABLE_COUNT__);
// 设置IMAGE_PROTECT
bXor = (__byte)GenerateRandomNumber();//随机生成出一个KEY
pImportProtect->bXor = bXor;
// 将引入表信息存入IMPORT_PROTECT结构
// 有些程序只适用FirstThunk
while (pImageImportDescriptor->FirstThunk) {
__address addrCurrAddress = 0;
__dword dwCurrRva = 0;
__char *svDllName = NULL;
PIMAGE_THUNK_DATA pTdIn = NULL;
PIMAGE_THUNK_DATA pTdOut = NULL;
if (bOnFile)
svDllName = (__char *)(pMem + Rva2Raw(pMem, pImageImportDescriptor->Name));
else
svDllName = (__char *)__RvaToVa__(pMem, pImageImportDescriptor->Name);
EncryptIATCallBack(iLibCount, LIB_NAME, (__memory)svDllName, __logic_strlen__(svDllName), FALSE, 0, (__void *)pImportProtect);
// 填充引入表地址
if (bOnFile) {
pTdIn = (PIMAGE_THUNK_DATA)(pMem + Rva2Raw(pMem, pImageImportDescriptor->OriginalFirstThunk));
pTdOut = (PIMAGE_THUNK_DATA)(pMem + Rva2Raw(pMem, pImageImportDescriptor->FirstThunk));
// 没有OriginalFirstThunk的情况
if ((__memory)pTdIn == pMem)
pTdIn = pTdOut;
} else {
pTdIn = (PIMAGE_THUNK_DATA)__RvaToVa__(pMem, pImageImportDescriptor->OriginalFirstThunk);
pTdOut = (PIMAGE_THUNK_DATA)__RvaToVa__(pMem, pImageImportDescriptor->FirstThunk);
// 没有OriginalFirstThunk的情况
if ((__memory)pTdIn == pMem)
pTdIn = pTdOut;
}
iProcCount = 0;
if (addrOrigImageBase == __USE_DEF_IMAGEBASE_AS_ORIG__)
addrCurrOrigImageBase = addrImageBase;
else
addrCurrOrigImageBase = addrOrigImageBase;
addrCurrAddress = __RvaToVa__(addrCurrOrigImageBase, pImageImportDescriptor->FirstThunk);
// 加密函数
while (pTdIn->u1.Function) {
// 随机取出一个要放入的位置
__integer iOffsetTableIndex = RandJmpAddress(&JmpAddressTableMakeSure);
// 获取新的FirstThunk
__dword dwNewFirstThunk = (__dword)(ofJmpTableRva + iOffsetTableIndex * sizeof(__address));
OrigJmpAddressTable[iJmpAddressTableCount] = addrCurrAddress;
JmpTableToAddressList[iJmpAddressTableCount].addrAddress = addrCurrAddress;
// 合成新的引入地址表偏移
JmpTableToAddressList[iJmpAddressTableCount].dwNewRva = dwNewFirstThunk;
iJmpAddressTableCount++;//跳入表计数
// 以序号引出还是以函数名引出
if (pTdIn->u1.Ordinal & IMAGE_ORDINAL_FLAG32) {
__word wOrd = pTdIn->u1.Ordinal;
EncryptIATCallBack(iIndex, PROC_NAME, (__memory)&wOrd, 2, TRUE, dwNewFirstThunk, (__void *)pImportProtect);
} else {
__char *szProcName = NULL;
PIMAGE_IMPORT_BY_NAME pIbn = NULL;
if (bOnFile)
pIbn = (PIMAGE_IMPORT_BY_NAME)(pMem + Rva2Raw(pMem, pTdIn->u1.AddressOfData));
else
pIbn = (PIMAGE_IMPORT_BY_NAME)__RvaToVa__(pMem, pTdIn->u1.AddressOfData);
szProcName = (__char *)(pIbn->Name);
EncryptIATCallBack(iIndex, PROC_NAME, (__memory)szProcName, __logic_strlen__(szProcName), FALSE, dwNewFirstThunk, (__void *)pImportProtect);
}
// 下一个函数
addrCurrAddress += sizeof(__address);
iProcCount++;//函数计数增加
iIndex++;//索引计数增加
pTdIn++;
pTdOut++;
}/* end while */
// 在下一个DLL之前,记录当前库所有的API数量
pImportProtect->iApiNumberInThisLibrary[iLibCount] = iProcCount;
// 下一个DLL
pImageImportDescriptor++;
iLibCount++;
}/* end while */
pJmpAddressTableRva = &(pImportProtect->dwFirstThunkList);
// 验证
if (iIndex != pImportProtect->iApiNameCrc32Count)
return NULL;
// 进行随机混淆
ud_init(&ud_obj);
ud_set_input_buffer(&ud_obj, pCodeStart, iCodeSize);//默认一个函数的最大长度为4096
ud_set_mode(&ud_obj, 32);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
while (ud_disassemble(&ud_obj)) {
__memory pFileSaveAddress = NULL;
struct ud_operand *pCurrOperand = NULL;
/*
* 找到拥有内存访问能力的指令,如果指令访问的内存地址在表中的话,则将其改写为新的内存
* 地址
*/
if (ud_obj.operand[0].type != UD_NONE) {
// 如果拥有操作数
__integer iOperandCount = 0;
///*
// * 这里仅处理MOV,CALL,JMP 三条指令
// * 因为不同编译只有这三条指令会对引入表造成访问
// */
//if (ud_obj.mnemonic == UD_Imov) {
// if ((ud_obj.operand[1].type == UD_OP_MEM) && (ud_obj.operand[1].base == UD_NONE) && \
// (ud_obj.operand[1].index == UD_NONE) && (ud_obj.operand[1].size == 32)) {
// pCurrOperand = &(ud_obj.operand[1]);
// pFileSaveAddress = (__memory)(ud_obj.inp_buff) - sizeof(__dword);
// }
//} else if ((ud_obj.mnemonic == UD_Icall) || (ud_obj.mnemonic == UD_Ijmp)) {
// if ((ud_obj.operand[0].type == UD_OP_MEM) && (ud_obj.operand[0].base == UD_NONE) && \
// (ud_obj.operand[0].index == UD_NONE) && (ud_obj.operand[0].offset) && (ud_obj.operand[0].size == 32)) {
// pCurrOperand = &(ud_obj.operand[0]);
// pFileSaveAddress = (__memory)(ud_obj.inp_buff) - sizeof(__dword);
// }
//}
//////////////////////////////////////////////////////////////////////////
// 2012.2.10 修改为 所有指令只要有内存访问
// 形如:xxx dword ptr [address]
// xxx dword ptr [address], reg
// xxx reg, dword ptr [address]
if ((ud_obj.operand[0].type == UD_OP_MEM) && (ud_obj.operand[0].base == UD_NONE) && \
(ud_obj.operand[0].index == UD_NONE) && (ud_obj.operand[0].offset) && (ud_obj.operand[0].size == 32)) {
pCurrOperand = &(ud_obj.operand[0]);
pFileSaveAddress = (__memory)(ud_obj.inp_buff) - sizeof(__dword);
}
else if ((ud_obj.operand[1].type == UD_OP_MEM) && (ud_obj.operand[1].base == UD_NONE) && \
(ud_obj.operand[1].index == UD_NONE) && (ud_obj.operand[1].size == 32)) {
pCurrOperand = &(ud_obj.operand[1]);
pFileSaveAddress = (__memory)(ud_obj.inp_buff) - sizeof(__dword);
}
if (pFileSaveAddress) {
__memory pCurrInstFileAddress = ud_obj.inp_buff - ud_obj.inp_ctr;
/*
* 如果是内存访问操作
* 取出地址与跳转地址表中进行检索
*/
__address addrTargetAddress = (__address)(pCurrOperand->lval.sdword);
__dword dwNowRva = GetNewRvaFromJmpAddressTable(addrTargetAddress, &JmpTableToAddressList, iJmpAddressTableCount);
if (dwNowRva != __NOT_IN_JMPADDRESSTABLE__) {
addrNowAddress = addrImageBase + dwNowRva;
*(__address *)pFileSaveAddress = addrNowAddress;//重新设置
// 设置一个引入表引用结构
(*pCurrReferenceImportTableAddresPoint) = (PREFERENCE_IMPORT_TABLE_ADDRESS)__logic_new__(REFERENCE_IMPORT_TABLE_ADDRESS, 1);
if (bOnFile) {
(*pCurrReferenceImportTableAddresPoint)->ofReferenceRVA = Raw2Rva(pMem, (__integer)(pFileSaveAddress - pMem));
(*pCurrReferenceImportTableAddresPoint)->addrReferenceMemAddress = addrImageBase + Raw2Rva(pMem, (__integer)(pCurrInstFileAddress - pMem));
} else {
(*pCurrReferenceImportTableAddresPoint)->ofReferenceRVA = (__integer)(pFileSaveAddress - pMem);
(*pCurrReferenceImportTableAddresPoint)->addrReferenceMemAddress = addrImageBase + (__integer)(pCurrInstFileAddress - pMem);
}
(*pCurrReferenceImportTableAddresPoint)->pReferenceFileAddress = pCurrInstFileAddress;
__logic_memcpy__(&((*pCurrReferenceImportTableAddresPoint)->ud_obj), &ud_obj, sizeof(ud_t));
// 增加引用引入表内存指令RVA,如果大于最大的计数则加密引入表失败直接退出
if (pImportProtect->iImportTableReferenceAddressCount >= __MAX_IMPORT_REFERENCE_COUNT__) {
// 释放已经分配的内存
ReleaseReferenceImportTableAddress(&pReferenceImportTableAddres);
return NULL;
}/* end if */
pImportProtect->ofImportTableReferenceAddressRVA[pImportProtect->iImportTableReferenceAddressCount] = (*pCurrReferenceImportTableAddresPoint)->ofReferenceRVA;
pImportProtect->ofAPINowRVA[pImportProtect->iImportTableReferenceAddressCount] = dwNowRva;
(pImportProtect->iImportTableReferenceAddressCount)++;
// 移动到下一个
pCurrReferenceImportTableAddresPoint = &((*pCurrReferenceImportTableAddresPoint)->pNext);
}
}/* end if */
}/* end if */
}
pImportProtect->ofJmpTableRva = ofJmpTableRva;//设置新跳转表的RVA
// 销毁原先的引入表
if (bOnFile)
DeleteDataDirectoryObject(pMem, IMAGE_DIRECTORY_ENTRY_IMPORT);
else
DeleteDataDirectoryObjectOnMemMap(pMem, IMAGE_DIRECTORY_ENTRY_IMPORT);
return pReferenceImportTableAddres;
}
/*
* 介绍:
* 解密引入地址表,此函数在目标文件中调用,用于修复
*
* 参数:
* pArg:力量解密引入表参数结构
*/
__bool __API__ PowerDecryptImportTable(PPOWERDECRYPTIMPORTTABLE_ARG pArg) {
PIMPORT_PROTECT pImportProtect = NULL;
FPAddThunkCodeStub pAddThunkCodeStub = NULL;
__byte bXor = 0;
HMODULE hDll = NULL, hCurrDll = NULL;
__integer i = 0, j = 0, iIndex = 0;
__integer iLength = 0;
__char *pLibName = NULL;
__char LibName[64] = {0};
__dword dwLibNameCrc32 = 0;
__bool bDllIsProtect = FALSE;
__PrintDbgInfo_OutputDbgString__("Entry PowerDecryptImportTable");
// 初始化数据
pImportProtect = pArg->pImportProtect;
pAddThunkCodeStub = pArg->pAddThunkCodeStub;
bXor = pImportProtect->bXor;//获取密钥的解密密码
for (i = 0; i < pImportProtect->iLibraryKeyCount; i++) {
__dword dwKey = 0;
__memory pKey = NULL;
dwKey = pImportProtect->dwLibraryKeyList[i];//解密密钥
pKey = (__memory)&dwKey;
XorKey4Bytes(pKey, bXor);
iLength = pImportProtect->iLibraryNameLengthList[i];
__logic_memset__(LibName, 0, 64);
pLibName = pImportProtect->LibraryNameList[i];
XorArray(dwKey, (__memory)pLibName, (__memory)LibName, iLength);//解密
// 获取库名的CRC32值
dwLibNameCrc32 = crc32((__memory)LibName, iLength);
// 加载并重映射DLL
hCurrDll = g_pLoadLibraryA(LibName);
// 如果是在保护内的库则重新映射
if (ThisValueIsInList(dwLibNameCrc32, pImportProtect->dwProtectDllCrc32List, pImportProtect->iProtectDllCrc32Count)) {
// 查看是否是排除在执行DllMain的库
if (ThisValueIsInList(dwLibNameCrc32, pImportProtect->dwProtectDllCallDllMainCrc32List, pImportProtect->iProtectDllCallDllMainCrc32Count))
hDll = (HMODULE)RemapDll((__memory)hCurrDll, g_pVirtualAlloc, TRUE);
else
hDll = (HMODULE)RemapDll((__memory)hCurrDll, g_pVirtualAlloc, FALSE);
// 设置此DLL经过保护
bDllIsProtect = TRUE;
} else {
hDll = (HMODULE)hCurrDll;
// 设置此DLL未经过保护
bDllIsProtect = FALSE;
}
// 获取API地址
for (j = 0; j < pImportProtect->iApiNumberInThisLibrary[i]; j++) {
__memory pHashData = NULL;
__address addrImageBase = 0;
__dword dwFirstThunk = 0;
__address *paddrOut = NULL;
pHashData = (__memory)&(pImportProtect->dwApiNameCrc32List[iIndex]);
addrImageBase = pImportProtect->addrImageBase;
dwFirstThunk = pImportProtect->dwFirstThunkList[iIndex];
paddrOut = (__address *)(addrImageBase + (__address)dwFirstThunk);
if (pImportProtect->bIsOrdList[iIndex]) {
__dword dwOrd = pImportProtect->dwApiNameCrc32List[iIndex] & 0xFFFF;//取低2字节
__PrintDbgInfo_OutputDbgString__("Already goto xGetProcAddressByHash by API ord");
*paddrOut = (__address)xGetProcAddressByHash(hDll, (__memory)dwOrd, 2, DecrypterHashFunc);
} else {
__PrintDbgInfo_OutputDbgString__("Already goto xGetProcAddressByHash by API name hash value");
*paddrOut = (__address)xGetProcAddressByHash(hDll, pHashData, sizeof(__address), DecrypterHashFunc);
}
// 在需要抽取的API列表中找寻
__PrintDbgInfo_OutputDbgString__("Already goto ThisApiIsInProtectList");
if (ThisValueIsInList(pImportProtect->dwApiNameCrc32List[iIndex], &(pImportProtect->dwProtectApiCrc32List), pImportProtect->iProtectApiCrc32Count)) {
__memory pNowAddress = NULL;
__memory pNewAddress = NULL;
__offset ofOffset = 0;
//__integer iProcSize = 0;
pNowAddress = (__memory)(*paddrOut);
// 计算这个函数的长度
//iProcSize = SimpleCalcThisProcedureLength(pNowAddress);
if (pAddThunkCodeStub) {
pNewAddress = pAddThunkCodeStub((__address)pNowAddress);
if (!pNewAddress) goto _default_add_thunk_code_stub;//如果为空则直接转入默认处理
} else {
_default_add_thunk_code_stub:
// 产生一个中间函数
pNewAddress = __logic_new_size__(0x10);
// 计算偏移
ofOffset = CalcCurrOffsetFromAddress(32, (__address)pNowAddress, (__address)pNewAddress, 5);
*(__byte *)pNewAddress = 0xE9;
*(__offset *)(pNewAddress + 1) = ofOffset;
}
// 重新设定地址
*paddrOut = (__address)pNewAddress;
}
// 增加索引计数
iIndex++;
}/* end for */
// 如果在保护范围内则清除这个DLL的无用信息
if (bDllIsProtect) {
__PrintDbgInfo_OutputDbgString__("Already goto ClearRemapDllUnSafeInfo");
ClearRemapDllUnSafeInfo(hDll);
}/* end if */
}
// 检验
if (iIndex != pImportProtect->iApiNameCrc32Count)
return FALSE;
// 这里开启一个非常重要就是修订目标代码节要引用的
__PrintDbgInfo_OutputDbgString__("Fix target code reference API memory address");
{
__integer i = 0;
__memory pMem = NULL;
pMem = (__memory)(pImportProtect->addrImageBase);
for (i = 0; i < pImportProtect->iImportTableReferenceAddressCount; i++) {
__address *pReference = NULL;
__address addrNowAddress = 0;
// 获得引用的地址
pReference = (__address *)(pMem + pImportProtect->ofImportTableReferenceAddressRVA[i]);
addrNowAddress = (__address)(pMem + pImportProtect->ofAPINowRVA[i]);
// 设置
*pReference = addrNowAddress;
}/* end for */
}
__PrintDbgInfo_OutputDbgString__("Exit PowerDecryptImportTable");
return TRUE;
}
|