/*
* 介绍:
* 力量解密引入表
*
* 参数:
* 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;
}