控制台界面;
exe程序加壳;
代码加密;
重定位;
IAT加密;
软件授权;
TLS模拟执行;
花指令;
混淆;
反调试;
反dump;
#编译环境
Win10 VS2015;
代码段加密
支持重定位
IAT加密
未加密的IAT显示为函数地址
软件授权
通过机器码加密
模拟执行TLS函数
花指令
代码混淆
反调试
多种反调试,总有一种适合你
支持x64和od,未检测到调试则显示ok
程序分为加壳程序与stub壳代码部分;
加壳程序将宿主程序进行处理;
将stub部分植入宿主程序;
程序运行时由stub代码对宿主程序进行解密及修复;
熟悉壳执行流程;
IAT加解密原理;
反调试原理;
加深对PE文件结构理解;
###Hash获取函数
壳自身所用到的函数都通过Hash值来获取;
//获取API
void GetAPI()
{
g_nTls;
HMODULE hKernel;
//获取模块基址
__asm
{
push eax; //保存寄存器
mov eax, fs:[0x30]; //获取PEB
mov eax, [eax + 0x0c]; //获取PEB_LDR
mov eax, [eax + 0x1c]; //获取IninitalizationOrderModuleList链表
mov eax, [eax]; //获取Kernel32.dll/Kerbase.dll
mov eax, [eax + 0x08]; //获取模块基址
mov hKernel, eax //保存模块基址
pop eax; //恢复寄存器
}
//通过Hash获取地址
pfnGetProcAddress = pGetProceAddress(FindFunByHash(hKernel, 0xbbafdf85)); //以下0xXXXXXXXX均为Hash值
//获取LoadLibraryExA
pfnLoadLibraryExA = (pLoadLibraryExA)(FindFunByHash(hKernel, 0xc0d83287));
//获取VirtualProtectEx
pfnVirtualProtect = (pVirtualProtect)(FindFunByHash(hKernel, 0xef64a41e));
//获取GetModuleHandleA
pfnGetModuleHandleA = (pGetModuleHandleA)(FindFunByHash(hKernel, 0xf4e2f2b2));
//获取VirtualAlloc
pfnVirtualAlloc = (pVirtualAlloc)(FindFunByHash(hKernel, 0x1ede5967));
//获取基址
g_hModule = (DWORD)pfnGetModuleHandleA(NULL);
pfnExitProcess = (pExitProcess)(FindFunByHash(hKernel, 0x4fd18963));
pfnGetVolumeInformationA = (pGetVolumeInformationA)(FindFunByHash(hKernel, 0x7666caec));
pfnGetCurrentProcess = (pGetCurrentProcess)(FindFunByHash(hKernel, 0x3a2fe6bb));
pfnGetCurrentThread=(pGetCurrentThread)(FindFunByHash(hKernel, 0x8ffb3b6e));
pfnSetUnhandledExceptionFilter=(pSetUnhandledExceptionFilter)(FindFunByHash(hKernel, 0x4807d145));
char strNtdll[10] = {0x4E, 0x74, 0x64, 0x6C, 0x6C, 0x2E, 0x64, 0x6C, 0x6C,0x00};
HMODULE hNt = pfnLoadLibraryExA(strNtdll, 0, 0);
pfnNtQueryInformationProcess = (pNtQueryInformationProcess)(FindFunByHash(hNt, 0x72aab605));
pfnNtQuerySystemInformation = (pNtQuerySystemInformation)(FindFunByHash(hNt, 0xeffc1dbe));
pfnNtQueryObject = (pNtQueryObject)(FindFunByHash(hNt, 0x0db59c8a));
pfnZwSetInformationThread = (pZwSetInformationThread)(FindFunByHash(hNt, 0x3d83d869));
//定义字符串
char strDllUser[11] = {0x55, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00};
//载入User32
HMODULE hUser = pfnLoadLibraryExA(strDllUser, 0, 0);
//获取MessageBoxA
pfnMessageBoxA = (pMessageBoxA)(FindFunByHash(hUser, 0x1e380a6a));
pfnGetWindowThreadProcessId=(pGetWindowThreadProcessId)(FindFunByHash(hUser, 0xa0667fbe));
//获取窗口相关函数
pfnRegisterClassA= (pRegisterClassA)(FindFunByHash(hUser, 0x0bc05e32));
pfnCreateWindowExA= (pCreateWindowExA)(FindFunByHash(hUser, 0x1fdaf55b));
pfnShowWindow = (pShowWindow)(FindFunByHash(hUser, 0xdd8b5fb8));
pfnGetMessageA = (pGetMessageA)(FindFunByHash(hUser, 0x6106044b));
pfnFindWindowA=(pFindWindowA)(FindFunByHash(hUser, 0x3db19602));
pfnTranslateMessage = (pTranslateMessage)(FindFunByHash(hUser, 0xe09980a2));
pfnDispatchMessageA = (pDispatchMessageA)(FindFunByHash(hUser, 0x7a1506c2));
pfnGetDlgItemTextA = (pGetDlgItemTextA)(FindFunByHash(hUser, 0x1584c411));
pfnPostQuitMessage = (pPostQuitMessage)(FindFunByHash(hUser, 0xcaa94781));
pfnDefWindowProcA = (pDefWindowProcA)(FindFunByHash(hUser, 0x22e85ca4));
return;
}
加壳程序加壳时将INT中的函数名称替换为Hash值;
修复宿主程序IAT也通过Hash获取函数;
均未使用GetProcAddress
,增加脱壳难度
//修复IAT
void RecIAT()
{
//判断是否存在导入表
if (!g_Conf.dwImportRva)
{
return ;
}
//构造跳转代码
BYTE bJmpByte[] = {
0xe8, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x58, 0xeb, 0x01, 0xe8, 0xb8, 0x11, 0x11, 0x11, 0x11, 0xeb,
0x01, 0x15, 0x35, 0x16, 0x16, 0x16, 0x16, 0xeb, 0x01, 0xff, 0x50, 0xeb, 0x02, 0xff, 0x15, 0xc3 };
//获取原INT地址
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(g_hModule + g_Conf.dwImportRva);
//外层循环遍历模块
while (pImport->Name)
{
//获取宿主INT
PIMAGE_THUNK_DATA32 pThunkINT = (PIMAGE_THUNK_DATA32)(g_hModule+ pImport->OriginalFirstThunk);
//获取宿主IAT
PIMAGE_THUNK_DATA32 pThunkIAT = (PIMAGE_THUNK_DATA32)(g_hModule + pImport->FirstThunk);
//获取DLL模块名称
char *DllName = (CHAR*)(g_hModule + pImport->Name);
//载入DLL模块
HMODULE hDllModule = pfnLoadLibraryExA(DllName, 0, 0);
//获取模块 EAT
PIMAGE_NT_HEADERS pDLLNt = GetNtHeader((PBYTE)hDllModule); //NT头
PIMAGE_EXPORT_DIRECTORY pDLLExport = (PIMAGE_EXPORT_DIRECTORY)
((PBYTE)hDllModule + *(PDWORD)((PBYTE)pDLLNt + 0x78)); //EXPORT
PDWORD pDLLEAT = (PDWORD)((PBYTE)hDllModule + pDLLExport->AddressOfFunctions); //EAT
//修改内存属性
DWORD dwOldProt = 0;
pfnVirtualProtect(pThunkIAT, 1, PAGE_READWRITE, &dwOldProt);
//内层循环遍历模块中的函数
while (pThunkINT->u1.AddressOfData)
{
//检测是否序号
bool IsOrdinal= (pThunkINT->u1.AddressOfData & 0xFFFF0000) == 0;
DWORD dwFunAddress = 0;
if (IsOrdinal)
{
//通过序号得到函数地址,需要加DLL基址
dwFunAddress = (DWORD)(pDLLEAT[pThunkINT->u1.Ordinal] + (PBYTE)hDllModule);
}
//名称命名
else
{
//通过Hash获取函数地址
dwFunAddress = FindFunByHash(hDllModule, pThunkINT->u1.AddressOfData);
}
//申请空间实现IAT跳转
PBYTE pNewAddr= (PBYTE)pfnVirtualAlloc(0, sizeof(bJmpByte), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//计算秘钥
DWORD dwIATKey = g_Conf.dwEncodeKey;
IATKey(&dwIATKey);
//替换秘钥
PDWORD pKey = (PDWORD)&(bJmpByte[19]);
*pKey = dwIATKey;
//替换地址
PDWORD pAddr = (PDWORD)&(bJmpByte[11]);
*pAddr = dwFunAddress ^ dwIATKey;
//拷贝代码
memcpy(pNewAddr, bJmpByte, sizeof(bJmpByte));
//存入IAT
pThunkIAT->u1.AddressOfData = (DWORD)pNewAddr;
//下一个INT
pThunkINT++;
pThunkIAT++;
}
//恢复内存属性
pfnVirtualProtect(pThunkIAT, 1, dwOldProt, &dwOldProt);
//下一个导入表
pImport++;
}
}