|
|
|
[求助]IAT 的位置可以改变不?
貌似以前没在论坛上发过。 以下是加解密函数。 很简单遍历代码节把引用都找出来判断是否是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; } |
|
[求助]IAT 的位置可以改变不?
很简单的。 遍历代码节把所有引用找出来 然后记录。 修改以后在重新自己填充一遍就OK。 貌似我OPEN SOURCE过 |
|
[活动结束]Kx币换QQ公仔,限量30只
OHOH..抢到一只。。。 |
|
|
|
[活动结束]Kx币换QQ公仔,限量30只
貌似我可以领一只。。。 |
|
xxxxxxxxxxxx
论坛上的新帖用手机RSS订阅一目了然。。。 用电脑上的机会反而少了。 发言也就少了。 相信很多人用手机订阅论坛。 |
|
[原创]SEH分析笔记(X86篇)
为了你这种认真的态度,都要发帖支持你一下。。。 |
|
|
|
[原创]MzfHips(开源)
欢迎加入。。。 你头像我很喜欢 。。。 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值