摘要:本文主要向大家介绍了C/C++知识点之压缩壳的实现相关细节,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
本文主要向大家介绍了C/C++知识点之压缩壳的实现相关细节,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
加壳 原理:
改变原始OEP的指向 指向壳程序 壳程序可以添加其它程序 如弹密码框 只有密码正确就运行(只是所有函数动态加载)
typedef int (WINAPI *LPMESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, UINT); //MessageBoxW
typedef DWORD(WINAPI *LPGETPROCADDRESS)(HMODULE, LPCSTR); // GetProcAddress
typedef HMODULE(WINAPI *LPLOADLIBRARYEX)(LPCTSTR, HANDLE, DWORD); // LoadLibaryEx
typedef HMODULE(WINAPI *GETModuleHandle)(
_In_opt_ LPCTSTR lpModuleName
);
typedef BOOL(WINAPI* SHOWWINDOW)(
_In_ HWND hWnd,
_In_ int nCmdShow
);
typedef BOOL(WINAPI* GteMessage)(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax
);
typedef LRESULT(WINAPI* DISpatchMessage)(
_In_ const MSG *lpmsg
);
typedef ATOM(WINAPI* REGisterClass)(
_In_ const WNDCLASS *lpWndClass
);
typedef HWND(WINAPI *CREateWindowEx)(
_In_ DWORD dwExStyle,
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam
);
typedef VOID(WINAPI* POSTQuitMessage)(
_In_ int nExitCode
);
typedef LRESULT(WINAPI* DEFWindowProc)(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
typedef BOOL(*UPDateWindow)(
_In_ HWND hWnd
);
typedef int (WINAPI* GETWindowText)(
_In_ HWND hWnd,
_Out_ LPTSTR lpString,
_In_ int nMaxCount
);
typedef int (WINAPI* GETWindowTextLength)(
_In_ HWND hWnd
);
typedef HWND(WINAPI* GETDlgItem)(
_In_opt_ HWND hDlg,
_In_ int nIDDlgItem
);
typedef BOOL(WINAPI* SETWindowText)(
_In_ HWND hWnd,
_In_opt_ LPCTSTR lpString
);
typedef BOOL(WINAPI* TRanslateMessage)(
_In_ const MSG *lpMsg
);
typedef LPVOID(WINAPI *MYVIRTUALALLOC)(
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
typedef BOOL(WINAPI *MYVIRTUALFREE)(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD dwFreeType
);
typedef HMODULE(WINAPI *MYLOADLIBRARY)(
_In_ LPCSTR lpLibFileName
);
wchar_t g_wcbuf100[100] = { 0 };
wchar_t g_MIMA100[100] = L"haidragon";
wchar_t wStrtext[100] = L"请输入密码";
_declspec(thread) int g_num;
/////////////////////////////////////////////////////////////
//初始化
LPGETPROCADDRESS g_funGetProcAddress = nullptr;
LPLOADLIBRARYEX g_funLoadLibraryEx = nullptr;
HMODULE hModuleKernel32 = nullptr;
HMODULE hModuleUser32 = nullptr;
GETModuleHandle g_funGetModuleHandle = nullptr;
LPMESSAGEBOX g_funMessageBox = nullptr;
CREateWindowEx g_funCreateWindowEx = nullptr;
POSTQuitMessage g_funPostQuitMessage = nullptr;
DEFWindowProc g_funDefWindowProc = nullptr;
GteMessage g_funGetMessage = nullptr;
REGisterClass g_funRegisterClass = nullptr;
SHOWWINDOW g_funShowWindow = nullptr;
UPDateWindow g_funUpdateWindow = nullptr;
DISpatchMessage g_funDispatchMessage = nullptr;
GETWindowText g_funGetWindowText = nullptr;
GETWindowTextLength g_funGetWindowTextLength = nullptr;
GETDlgItem g_funGetDlgItem = nullptr;
SETWindowText g_funSetWindowText = nullptr;
TRanslateMessage g_funTranslateMessage = nullptr;
MYVIRTUALALLOC g_VirtualAlloc = nullptr;
MYVIRTUALFREE g_VirtualFree = nullptr;
MYLOADLIBRARY g_LoadLibraryA = nullptr;
DWORD g_dwImageBase;
DWORD g_oep;
void start();
PACKINFO g_PackInfo = { (DWORD)start };
//获取kernel32模块加载基址
DWORD GetKernel32Base()
{
DWORD dwKernel32Addr = 0;
__asm
{
push eax
mov eax, dword ptr fs : [0x30] // eax = PEB的地址
mov eax, [eax + 0x0C] // eax = 指向PEB_LDR_DATA结构的指针
mov eax, [eax + 0x1C] // eax = 模块初始化链表的头指针InInitializationOrderModuleList
mov eax, [eax] // eax = 列表中的第二个条目
mov eax, [eax + 0x08] // eax = 获取到的Kernel32.dll基址(Win7下获取的是KernelBase.dll的基址)
mov dwKernel32Addr, eax
pop eax
}
return dwKernel32Addr;
}
//获取GetProcAddress的基址
DWORD GetGPAFunAddr()
{
DWORD dwAddrBase = GetKernel32Base();
// 1. 获取DOS头、NT头
PIMAGE_DOS_HEADER pDos_Header;
PIMAGE_NT_HEADERS pNt_Header;
pDos_Header = (PIMAGE_DOS_HEADER)dwAddrBase;
pNt_Header = (PIMAGE_NT_HEADERS)(dwAddrBase + pDos_Header->e_lfanew);
// 2. 获取导出表项
PIMAGE_DATA_DIRECTORY pDataDir;
PIMAGE_EXPORT_DIRECTORY pExport;
pDataDir = pNt_Header->OptionalHeader.DataDirectory;
pDataDir = &pDataDir[IMAGE_DIRECTORY_ENTRY_EXPORT];
pExport = (PIMAGE_EXPORT_DIRECTORY)(dwAddrBase + pDataDir->VirtualAddress);
// 3、获取导出表的必要信息
DWORD dwModOffset = pExport->Name; // 模块的名称
DWORD dwFunCount = pExport->NumberOfFunctions; // 导出函数的数量
DWORD dwNameCount = pExport->NumberOfNames; // 导出名称的数量
PDWORD pEAT = (PDWORD)(dwAddrBase + pExport->AddressOfFunctions); // 获取地址表的RVA
PDWORD pENT = (PDWORD)(dwAddrBase + pExport->AddressOfNames); // 获取名称表的RVA
PWORD pEIT = (PWORD)(dwAddrBase + pExport->AddressOfNameOrdinals); //获取索引表的RVA
// 4、获取GetProAddress函数的地址
for (DWORD i = 0; i < dwFunCount; i++)
{
if (!pEAT[i])
{
continue;
}
// 4.1 获取序号
DWORD dwID = pExport->Base + i;
// 4.2 变量EIT 从中获取到 GetProcAddress的地址
for (DWORD dwIdx = 0; dwIdx < dwNameCount; dwIdx++)
{
// 序号表中的元素的值 对应着函数地址表的位置
if (pEIT[dwIdx] == i)
{
//根据序号获取到名称表中的名字
DWORD dwNameOffset = pENT[dwIdx];
char * pFunName = (char*)(dwAddrBase + dwNameOffset);
//判断是否是GetProcAddress函数
if (!strcmp(pFunName, "GetProcAddress"))
{
// 获取EAT的地址 并将GetProcAddress地址返回
DWORD dwFunAddrOffset = pEAT[i];
return dwAddrBase + dwFunAddrOffset;
}
}
}
}
return -1;
}
//初始化API
bool InitializationAPI()
{
g_num;//使用tls变量,产生tls节表
//初始化
g_funGetProcAddress = (LPGETPROCADDRESS) GetGPAFunAddr();
g_funLoadLibraryEx = (LPLOADLIBRARYEX) g_funGetProcAddress((HMODULE)GetKernel32Base(), "LoadLibraryExW");
hModuleKernel32 = g_funLoadLibraryEx(L"Kernel32.dll", NULL, NULL);
hModuleUser32 = g_funLoadLibraryEx(L"user32.dll", NULL, NULL);
g_LoadLibraryA = (MYLOADLIBRARY) g_funGetProcAddress(hModuleKernel32, "LoadLibraryA");
g_funGetModuleHandle = (GETModuleHandle) g_funGetProcAddress(hModuleKernel32, "GetModuleHandleW");
g_VirtualAlloc = (MYVIRTUALALLOC) g_funGetProcAddress(hModuleKernel32, "VirtualAlloc");
g_VirtualFree = (MYVIRTUALFREE) g_funGetProcAddress(hModuleKernel32, "VirtualFree");
g_funMessageBox = (LPMESSAGEBOX) g_funGetProcAddress(hModuleUser32, "MessageBoxW");
g_funCreateWindowEx = (CREateWindowEx) g_funGetProcAddress(hModuleUser32, "CreateWindowExW");
g_funPostQuitMessage = (POSTQuitMessage) g_funGetProcAddress(hModuleUser32, "PostQuitMessage");
g_funDefWindowProc = (DEFWindowProc) g_funGetProcAddress(hModuleUser32, "DefWindowProcW");
g_funGetMessage = (GteMessage) g_funGetProcAddress(hModuleUser32, "GetMessageW");
g_funRegisterClass = (REGisterClass) g_funGetProcAddress(hModuleUser32, "RegisterClassW");
g_funShowWindow = (SHOWWINDOW) g_funGetProcAddress(hModuleUser32, "ShowWindow");
g_funUpdateWindow = (UPDateWindow) g_funGetProcAddress(hModuleUser32, "UpdateWindow");
g_funDispatchMessage = (DISpatchMessage) g_funGetProcAddress(hModuleUser32, "DispatchMessageW");
g_funGetWindowText = (GETWindowText) g_funGetProcAddress(hModuleUser32, "GetWindowTextW");
g_funGetWindowTextLength = (GETWindowTextLength)g_funGetProcAddress(hModuleUser32, "GetWindowTextLengthW");
g_funGetDlgItem = (GETDlgItem) g_funGetProcAddress(hModuleUser32, "GetDlgItem");
g_funSetWindowText = (SETWindowText) g_funGetProcAddress(hModuleUser32, "SetWindowTextW");
g_funTranslateMessage = (TRanslateMessage) g_funGetProcAddress(hModuleUser32, "TranslateMessage");
g_dwImageBase = (DWORD)g_funGetModuleHandle(NULL);
g_oep = g_PackInfo.TargetOepRva + g_dwImageBase;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
) {
switch (uMsg)
{
case WM_CREATE: {
wchar_t wStr[20] = L"窗口回调函数触发";
wchar_t wStr2[20] = L"haha";
g_funMessageBox(NULL, wStr, wStr2, NULL);
/////////////////////////////////////////////////////////////////////////////////////
DWORD dwStyle = ES_LEFT | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE;
DWORD dwExStyle = WS_EX_CLIENTEDGE | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
HWND hWnd = g_funCreateWindowEx(
dwExStyle, //dwExStyle 扩展样式
L"Edit", //lpClassName 窗口类名
wStrtext, //lpWindowName 窗口标题
dwStyle, //dwStyle 窗口样式
150, //x 左边位置
100, //y 顶边位置
200, //nWidth 宽度
20, //nHeight 高度
hwnd, //hWndParent 父窗口句柄
(HMENU)0x1002, //ID
g_funGetModuleHandle(0), //hInstance 应用程序句柄
NULL //lpParam 附加参数
);
return 0;
/////////////////////////////////////////////////////////////////////////////////
}
case WM_COMMAND: {
WORD wId = LOWORD(wParam);
WORD wCode = HIWORD(wParam);
HANDLE hChild = (HANDLE)lParam;
if (wId == 0x1001 && wCode == BN_CLICKED)
{
HWND hwndCombo = g_funGetDlgItem(hwnd, 0x1002);
int cTxtLen = g_funGetWindowTextLength(hwndCombo);
g_funGetWindowText(hwndCombo, g_wcbuf100, 100);
wchar_t wStr[20] = L"按钮触发";
wchar_t wStr2[20] = L"haha";
g_funMessageBox(NULL, wStr, wStr2, NULL);
wchar_t wStr3[20] = L"";
if (decide() == 1) {
//g_funPostQuitMessage(0);
g_funShowWindow(hwnd, SW_HIDE);
//运行壳代码
FusedFunc((DWORD)AllFunc);
//_asm jmp g_PackInfo.TargetOep;
wchar_t wStr[20] = L"密码正确!!!";
wchar_t wStr2[20] = L"haha";
g_funMessageBox(NULL, wStr, wStr2, NULL);
_asm jmp g_oep;
}
else {
wchar_t wStr[20] = L"密码错误请重新输入!!!";
wchar_t wStr2[20] = L"haha";
g_funMessageBox(NULL, wStr, wStr2, NULL);
}
g_funSetWindowText(hwndCombo, wStr3);
return 1;
}
break;
}
case WM_CLOSE:
{
g_funPostQuitMessage(0);
//return 0;
break;
}
}
// 返回默认的窗口处理过程
return g_funDefWindowProc(hwnd, uMsg, wParam, lParam);
}
void CtrateWin() {
MSG msg = { 0 };
wchar_t wStr[20] = L"allenboy";
wchar_t wStr2[20] = L"haha";
g_funMessageBox(NULL, wStr, wStr2, NULL);
// 先注册窗口类
WNDCLASS wcs = {};
wcs.lpszClassName = L"dragon";
wcs.lpfnWndProc = WindowProc;
wcs.hbrBackground = (HBRUSH)(COLOR_CAPTIONTEXT + 1);
/////////////////////////////////////////////////////////////////////////////////////////
//RegisterClass
//RegisterClass(&wcs);
g_funRegisterClass(&wcs);
//#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\
//nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
//注册窗口
//CreateWindowEx
//窗口类名一定要与上面的一致
HWND hWnd = g_funCreateWindowEx(0L, L"dragon", L"haidragon", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
500, 200, 500, 500,
NULL, NULL, NULL, NULL);
// 三种风格 WS_OVERLAPPEDWINDOW WS_POPUPWINDOW WS_CHILDWINDOW
g_funCreateWindowEx(0L, L"BUTTON", L"ok", WS_CHILD | WS_VISIBLE,
200, 150,// 在父窗口的客户区的位置,
100, 50,// 宽 高
hWnd,// 父窗口
(HMENU)0x1001,// 如果是顶层窗口 就是菜单句柄 子窗口就是本身的ID
//GetModuleHandle
g_funGetModuleHandle(0), NULL);
//ShowWindow(hWnd, SW_SHOW);
g_funShowWindow(hWnd, SW_SHOW);
g_funUpdateWindow(hWnd);
/*while (GetMessage(&msg, 0, 0, 0))
{
DispatchMessage(&msg);
}*/
while (g_funGetMessage(&msg, 0, 0, 0))
{
//DispatchMessage(&msg);
g_funTranslateMessage(&msg);
g_funDispatchMessage(&msg);
}
}
效果图
加密代码段 简单异或
//对代码段进行加密
void PEpack::Encode()
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)m_pNewBuf;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + m_pNewBuf);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
// 定位到代码段,并将每个段加密
pSection = pSection + m_codeIndex;
PCHAR pStart = pSection->PointerToRawData + m_pNewBuf;
for (int i = 0; i < (pSection->Misc.VirtualSize); i++)
{
pStart[i] ^= 0x20;
}
}
////////////壳中解密//////////////////////
//解密
void Decode()
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)g_dwImageBase;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + g_dwImageBase);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
// 找到.text段,并解密
while (TRUE)
{
if (!strcmp((char*)pSection->Name, ".text"))
{
PCHAR pStart = pSection->VirtualAddress + (PCHAR)g_dwImageBase;
for (int i = 0; i < pSection->Misc.VirtualSize; i++)
{
pStart[i] ^= 0x20;
}
break;
}
pSection = pSection + 1;
}
}
压缩(除tls 表 资源表 与 头除外 这里先于拷贝壳的重定位表 不然也会被压缩 就运行不起来了 )
压缩时的问题有 资源段问题 tls段问题
首先 运行时很会用到 资源 同时当运行壳代码之前会启动线程,因些就会用到tls数据段
所以这俩个都不压 其它全部压然后 放到最后,同时在压缩的时候重建PE(也就是后面的往上移)
最重的一点是在所有操作前 保存相关节与节的前后顺序与在原来大小和压缩后的大小等等
效果图
压缩 (同时重建PE)
//压缩PE文件
void PEpack::CompressPE(PPACKINFO &pPackInfo)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)m_pNewBuf;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + m_pNewBuf);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
// 用于记录压缩区段的个数
pPackInfo->PackSectionNumber = 0;
// 1.1 获取文件头的大小,并获取除资源段,tls之外段的文件中的总大小
DWORD SecSizeWithOutResAndTls = 0;
PIMAGE_SECTION_HEADER pSectionTmp1 = pSection;
BOOL isFirstNoEmptySec = TRUE;
DWORD dwHeaderSize = 0;
//先计算要拷贝的总大小
for (SIZE_T i = 0; i < pNt->FileHeader.NumberOfSections; i++)
{
// 用于获得第一个非空区段的文件偏移,也就是文件头大小
if (isFirstNoEmptySec && pSectionTmp1->SizeOfRawData != 0)
{
dwHeaderSize = pSectionTmp1->PointerToRawData;
isFirstNoEmptySec = FALSE;
}
// 用于获取 非 rsrc/tls段的总大小
if (pSectionTmp1->VirtualAddress != m_pResSectionRva &&
pSectionTmp1->VirtualAddress != m_pTlsSectionRva)
{
SecSizeWithOutResAndTls += pSectionTmp1->SizeOfRawData;
}
pSectionTmp1 = pSectionTmp1 + 1;
}
// 1.2 读取要压缩的段到内存
// 申请内存
PCHAR memWorked = new CHAR[SecSizeWithOutResAndTls];
// 已经拷贝的内存大小
DWORD dwCopySize = 0;
// 保存这些区段到内存
PIMAGE_SECTION_HEADER pSectionTmp2 = pSection;
//再次循环
for (SIZE_T i = 0; i < pNt->FileHeader.NumberOfSections; i++)
{
//判断是否为tls与资源表
if (pSectionTmp2->VirtualAddress != m_pResSectionRva &&
pSectionTmp2->VirtualAddress != m_pTlsSectionRva)
{
//开始拷贝
memcpy_s(memWorked + dwCopySize, pSectionTmp2->SizeOfRawData,
m_pNewBuf + pSectionTmp2->PointerToRawData, pSectionTmp2->SizeOfRawData);
dwCopySize += pSectionTmp2->SizeOfRawData;
}
pSectionTmp2 = pSectionTmp2 + 1;
}
// 1.3 压缩,并获取压缩后的大小(文件对齐在添加区段中进行)
LONG blen;
PCHAR packBuf = Compress(memWorked, SecSizeWithOutResA
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号