第五十九课 win32 枚举窗口_鼠标键盘事件函数
1.查找指定窗口
::FindWindow()函数获取窗口句柄,再通过句柄控制窗口,函数的参数可以通过vs的spy++工具获得
TCHAR szTitle[MAX_PATH] = {0};
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
//修改窗口标题
::SetWindowText(hwnd,"新的窗口标题");
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
2.窗口控制(手动加载dll使用winapi)
TCHAR szTitle[MAX_PATH] = {0};
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
typedef void (WINAPI *PSWITCHTOTHISWINDOW) (HWND,BOOL);
PSWITCHTOTHISWINDOW SwitchToThisWindow;
HMODULE hUser32=LoadLibrary("user32.dll");
SwitchToThisWindow=(PSWITCHTOTHISWINDOW)GetProcAddress(hUser32,"SwitchToThisWindow");
//切换窗口
SwitchToThisWindow(hwnd,false);
Sleep(3000);
//关闭窗口
::SendMessage(hwnd,WM_CLOSE,0,0);
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
3.查找子窗口
方法一:缺点是子窗口的类型和标题容易冲突
TCHAR szTitle[MAX_PATH] = {0};
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
//查找子窗口
HWND hEdit = FindWindowEx(hwnd,NULL,"Edit","");
//设置标题
::SetWindowText(hEdit,"文本框新的标题");
//修改内容
::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)"新的内容");
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
方法二:使用控件ID查找子窗口
TCHAR szTitle[MAX_PATH] = {0};
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
//查找子窗口
HWND hEdit =::GetDlgItem(hwnd,0x3E9);
//获取内容
::SendMessage(hEdit,WM_GETTEXT,MAX_PATH,(LPARAM)szTitle);
//修改内容
::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)"新的内容");
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
4.枚举所有子窗口
BOOL CALLBACK EnumChildProc(HWND hWnd,LPARAM lParam)
{
TCHAR szTitle[MAX_PATH] = {0};
::GetWindowText(hWnd,szTitle,MAX_PATH);
MessageBox(NULL,szTitle,"[子窗口]",MB_OK);
return true;
}
VOID EnumChildWindow()
{
TCHAR szTitle[MAX_PATH] = {0};
HWND hWnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hWnd != NULL)
{
::EnumChildWindows(hWnd,EnumChildProc,0);
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
}
5.枚举所有打开的窗口
BOOL CALLBACK EnumOpenWindowProc(HWND hWnd,LPARAM lParam)
{
TCHAR szTitle[MAX_PATH] = {0};
::GetWindowText(hWnd,szTitle,MAX_PATH);
MessageBox(NULL,szTitle,"[窗口]",MB_OK);
if(strcmp(szTitle,"飞鸽传书 IP Messenger") == 0)
{
MessageBox(NULL,szTitle,"[窗口]",MB_OK);
return FALSE;
}
return TRUE;
}
VOID EnumOpenWindows()
{
EnumWindows(EnumOpenWindowProc,NULL);
}
6.模拟鼠标点击
TCHAR szTitle[MAX_PATH] = {0};
RECT r;
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
HWND hButton = FindWindowEx(hwnd,NULL,"Button","刷新(&R)");
//获取窗口坐标
::GetWindowRect(hButton,&r);
printf("%d %d",r.left,r.top);
//设置鼠标的位置
::SetCursorPos(r.left+10,r.top+10);
Sleep(2000);
//鼠标左键单击
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//点下左键
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//松开左键
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
7.模拟键盘点击
百度搜键盘键与虚拟键码对照表
最后一个大写C就是使用shirt和c同时设置
TCHAR szTitle[MAX_PATH] = {0};
RECT r;
HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger"));
if(hwnd != NULL)
{
//HWND hButton = FindWindowEx(hwnd,NULL,"Button","刷新(&R)");
HWND hEdit =::GetDlgItem(hwnd,0x3E9);
//获取窗口坐标
::GetWindowRect(hEdit,&r);
//设置鼠标的位置
::SetCursorPos(r.left+1,r.top+1);
Sleep(1000);
//鼠标左键单击
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//点下左键
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//松开左键
//模拟键盘
keybd_event(97,0,0,0);
keybd_event(97,0,KEYEVENTF_KEYUP,0);
Sleep(1000);
keybd_event(66,0,0,0);
keybd_event(66,0,KEYEVENTF_KEYUP,0);
Sleep(1000);
keybd_event(16,0,0,0);
keybd_event(67,0,0,0);
keybd_event(67,0,KEYEVENTF_KEYUP,0);
keybd_event(16,0,KEYEVENTF_KEYUP,0);
}
else
{
::MessageBox(NULL,TEXT("窗口没有找到"),TEXT("[ERROR]"),MB_OK);
}
第六十课 win32 加密壳项目
1、壳源程序在后面的描述中称为shell
2、准备加密的程序在后面的描述中称为src
0.正常其他壳思路
注:
我们在追加代码里面的函数比如CreateProcess,都需要自己load,因为可能没加载到那个函数所在dll
1.滴水加壳程序的编写
这里和上面的正常壳思路没关系的噢
先编写一个加壳程序,让我们准备加密的src程序加密完放到shell的新增节里面
#include<Windows.h>
#include<stdio.h>
#include"resource.h"
#include"源.h"
#pragma warning(disable : 4996)
int ShellFileSize; //Shell的大小
int SrcFileSize; //Src大小
//内存对齐计算
DWORD Align(int x, int y)
{
return (x + y - 1) / y * y; //四舍五路对齐 比5大 就让它多分配点内存 比5小就少分配点
//比如你说你要扩大一个EXE的大小 假如你的exe这么 172 546 而它在内存中对齐的方式是1000 173000/1000 200
}
void XORcrypt(char str2xor[], size_t len, char key) {
int i; for (i = 0; i < len; i++) {
str2xor[i] = (BYTE)str2xor[i] ^ key;
}
}
BOOL MemeryToFile(LPVOID FileBuffer, DWORD Size)
{
FILE* fpw = NULL;
fopen_s(&fpw,"E:\\sadasd.exe", "wb");
if (!fpw)
{
printf("打开文件失败\n");
return 0;
}
if (fwrite(FileBuffer, 1, Size, fpw) == 0)
{
printf("文件写入失败");
return 0;
}
fclose(fpw);
fpw = NULL;
printf("存盘成功");
}
void AddSection(LPVOID& pImageBuffer,char* SrcBuffer)
{
PIMAGE_DOS_HEADER pDos_header = NULL;
PIMAGE_NT_HEADERS pNT_header = NULL;
PIMAGE_FILE_HEADER pPE_header = NULL;
PIMAGE_OPTIONAL_HEADER32 pOption_header = NULL;
PIMAGE_SECTION_HEADER pSection_header = NULL;
PIMAGE_SECTION_HEADER pLastSection_header = NULL;
PIMAGE_SECTION_HEADER pNewSection_header = NULL;
BOOL flag = false;
//算出ImageBuffer中的dos头nt头pe头节表地址
pDos_header = (PIMAGE_DOS_HEADER)pImageBuffer;
pNT_header = (PIMAGE_NT_HEADERS)((DWORD)pDos_header + pDos_header->e_lfanew);
pPE_header = (PIMAGE_FILE_HEADER)((DWORD)pNT_header + 4);
pOption_header = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPE_header + IMAGE_SIZEOF_FILE_HEADER);
pSection_header = (PIMAGE_SECTION_HEADER)((DWORD)pOption_header + pPE_header->SizeOfOptionalHeader);
LPVOID pLastDos = LPVOID((DWORD)pImageBuffer + sizeof(IMAGE_DOS_HEADER));
//修改后的逻辑
pLastSection_header = pSection_header + pPE_header->NumberOfSections; //定位要添加节的内存地址
int a = pOption_header->SizeOfHeaders - ((DWORD)pLastSection_header - (DWORD)pDos_header);
if (a < 80)
{
printf("空间不足以插入新节表,需要头抬升\n");
flag = TRUE;
}
else
{
printf("空间足够插入新节表不需要头抬升\n");
}
if (flag)
{
//memcpy拷贝数据
memcpy(pLastDos, pNT_header, (DWORD)pNewSection_header - (DWORD)pNT_header);
//更新e_lfanew
pDos_header->e_lfanew = sizeof(IMAGE_DOS_HEADER);
//更新头抬升后的信息
pNT_header = (PIMAGE_NT_HEADERS)((DWORD)pDos_header + pDos_header->e_lfanew);
pPE_header = (PIMAGE_FILE_HEADER)((DWORD)pNT_header + 4);
pOption_header = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPE_header + IMAGE_SIZEOF_FILE_HEADER);
pSection_header = (PIMAGE_SECTION_HEADER)((DWORD)pOption_header + pPE_header->SizeOfOptionalHeader);
for (int i = 0; i < pPE_header->NumberOfSections; i++, pSection_header++)
{
}
pLastSection_header = pSection_header;
pNewSection_header = pSection_header + 1;
//给节表后空白区填充0
LPVOID pTemp = (LPVOID)((DWORD)pLastSection_header);
memset(pTemp, 0, IMAGE_SIZEOF_SECTION_HEADER * 3);
}
//memset(pLastSection_header,0,80); 对于一些特殊的软件(经过作者处理的)提的建议
memcpy(pLastSection_header, pSection_header + 1, IMAGE_SIZEOF_SECTION_HEADER);
//拷贝名字
strcpy((char*)pLastSection_header->Name, (char*)".NewS"); //修改名字
//倒数第二个节
PIMAGE_SECTION_HEADER temp = pSection_header + pPE_header->NumberOfSections - 1;
pLastSection_header->VirtualAddress = Align(temp->VirtualAddress + temp->Misc.VirtualSize, pOption_header->SectionAlignment); //修改节表的入口点
pLastSection_header->Misc.VirtualSize = SrcFileSize;
pLastSection_header->PointerToRawData = Align(temp->PointerToRawData + temp->SizeOfRawData, pOption_header->FileAlignment);
pLastSection_header->SizeOfRawData = SrcFileSize;
//修改节的数量
pPE_header->NumberOfSections++;
//修改拉伸后的内存大小
pOption_header->SizeOfImage += SrcFileSize;
LPVOID NewFileBufer = malloc(ShellFileSize + SrcFileSize);
memset(NewFileBufer, 0, ShellFileSize + SrcFileSize);
memcpy(NewFileBufer, pImageBuffer, ShellFileSize);
//定位最后一个节的位置
PIMAGE_DOS_HEADER pDos_header1 = NULL;
PIMAGE_NT_HEADERS pNT_header1 = NULL;
PIMAGE_FILE_HEADER pPE_header1 = NULL;
PIMAGE_OPTIONAL_HEADER32 pOption_header1 = NULL;
PIMAGE_SECTION_HEADER pSection_header1 = NULL;
pDos_header1 = (PIMAGE_DOS_HEADER)NewFileBufer;
pNT_header1 = (PIMAGE_NT_HEADERS)((DWORD)pDos_header1 + pDos_header1->e_lfanew);
pPE_header1 = (PIMAGE_FILE_HEADER)((DWORD)pNT_header1 + 4);
pOption_header1 = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPE_header1 + IMAGE_SIZEOF_FILE_HEADER);
pSection_header1 = (PIMAGE_SECTION_HEADER)((DWORD)pOption_header1 + pPE_header1->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER Last = pSection_header1 + pPE_header1->NumberOfSections - 1;
XORcrypt(SrcBuffer,SrcFileSize,0x32);
memcpy((VOID*)((DWORD)Last->PointerToRawData + (DWORD)NewFileBufer), SrcBuffer, ShellFileSize);
MemeryToFile(NewFileBufer, ShellFileSize + SrcFileSize);
}
//读取文件
void Read_PE(TCHAR* filePath, LPVOID& buffer,int& len)
{
FILE* fp;
fp = fopen(filePath, "rb");
fseek(fp, 0, 2);
len = ftell(fp);
fseek(fp, 0, 0);
buffer = malloc(ShellFileSize + SrcFileSize);
if (!buffer)
{
printf("分配空间失败");
fclose(fp);
return ;
}
size_t read = fread(buffer, len, 1, fp);
}
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter)
{
HWND hWnd = (HWND)lpParameter; //获取Dlg的句柄
TCHAR ShellPath[MAX_PATH] = { 0 }; //壳子路径
TCHAR SrcPath[MAX_PATH] = { 0 }; //Src路径
//获取壳子Edit句柄
HWND HEditShell = GetDlgItem(hWnd, IDC_EDIT_SHELL);
HWND HEditSrc = GetDlgItem(hWnd, IDC_EDIT_SRC);
//获取编辑框的路径文本
GetWindowText(HEditShell, ShellPath, MAX_PATH);
GetWindowText(HEditSrc, SrcPath, MAX_PATH);
//读Shell文件
LPVOID ShellFileBuffer = NULL;
Read_PE(ShellPath, ShellFileBuffer, ShellFileSize);
//读取Src的文件
LPVOID SrcFileBuffer = NULL;
Read_PE(SrcPath, SrcFileBuffer,SrcFileSize);
AddSection(ShellFileBuffer, (char*)SrcFileBuffer);
return 0;
}
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParma)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
{
HANDLE hanle = CreateThread(NULL, 0, ThreadProc, (LPVOID)hWnd, 0, NULL);
CloseHandle(hanle);
return TRUE;
}
case IDC_BUTTON_SHELL:
{
TCHAR m_FileName[MAX_PATH] = { 0 };
int m_index = 0;
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);//结构体大小
ofn.hwndOwner = NULL;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
ofn.lpstrFilter = NULL;//TEXT("*.exe\0*.xls\0");//设置过滤
ofn.nFilterIndex = m_index;//过滤器索引
ofn.lpstrFile = m_FileName;//接收返回的文件名,注意第一个字符需要为NULL
ofn.nMaxFile = sizeof(m_FileName);//缓冲区长度
ofn.lpstrInitialDir = NULL;//初始目录为默认
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
GetOpenFileName(&ofn);
HWND hEditShell = GetDlgItem(hWnd, IDC_EDIT_SHELL);
SetWindowText(hEditShell, m_FileName);
return TRUE;
}
case IDC_BUTTON_SRC:
{
TCHAR m_FileName[MAX_PATH] = { 0 };
int m_index = 0;
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);//结构体大小
ofn.hwndOwner = NULL;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
ofn.lpstrFilter = NULL;//TEXT("*.exe\0*.xls\0");//设置过滤
ofn.nFilterIndex = m_index;//过滤器索引
ofn.lpstrFile = m_FileName;//接收返回的文件名,注意第一个字符需要为NULL
ofn.nMaxFile = sizeof(m_FileName);//缓冲区长度
ofn.lpstrInitialDir = NULL;//初始目录为默认
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
GetOpenFileName(&ofn);
HWND hEditShell = GetDlgItem(hWnd, IDC_EDIT2);
SetWindowText(hEditShell, m_FileName);
return TRUE;
}
}
return TRUE;
}
return FALSE; //返回1 就是系统处理,0就是自己处理
}
int CALLBACK WinMain(HINSTANCE hIstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdSHow)
{
DialogBox(hIstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
return 0;
}
2.解密壳程序的编写
这里其实编写的是shell程序,shell自身解密自己的新增节,也就是src程序,解密出来后把src贴到shell程序的4gb程序里面运行。
但是这里我们随便拿一个exe程序作为shell,解密部分放在另外一个窗口程序,这样做是为了方便调试,如果直接写shell程序,由于需要解密自己的新增节和卸载自身内存空间,会比较难调试
#include <Windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH
#define PATH "C:\\Users\\xx\\Desktop\\new.exe"
int len;
void Read_PE(LPVOID& FileBuffer, OUT LPVOID& SrcBuffer, OUT DWORD& SrcSize)
{
FILE* fp;
fopen_s(&fp, PATH, "rb");
fseek(fp, 0, 2);
len = ftell(fp);
fseek(fp, 0, 0);
FileBuffer = malloc(len);
if (!FileBuffer)
{
printf("分配空间失败");
fclose(fp);
return;
}
size_t read = fread(FileBuffer, len, 1, fp);
PIMAGE_DOS_HEADER pDos_header = NULL;
PIMAGE_NT_HEADERS pNT_header = NULL;
PIMAGE_FILE_HEADER pPE_header = NULL;
PIMAGE_OPTIONAL_HEADER32 pOption_header = NULL;
PIMAGE_SECTION_HEADER pSection_header = NULL;
PIMAGE_SECTION_HEADER pLastSection_header = NULL;
//算出ImageBuffer中的dos头nt头pe头节表地址
pDos_header = (PIMAGE_DOS_HEADER)FileBuffer;
pNT_header = (PIMAGE_NT_HEADERS)((DWORD)pDos_header + pDos_header->e_lfanew);
pPE_header = (PIMAGE_FILE_HEADER)((DWORD)pNT_header + 4);
pOption_header = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPE_header + IMAGE_SIZEOF_FILE_HEADER);
pSection_header = (PIMAGE_SECTION_HEADER)((DWORD)pOption_header + pPE_header->SizeOfOptionalHeader);
pLastSection_header = pSection_header + pPE_header->NumberOfSections - 1;
SrcSize = pLastSection_header->SizeOfRawData;
SrcBuffer = malloc(SrcSize);
memcpy(SrcBuffer, (VOID*)((DWORD)pLastSection_header->PointerToRawData + (DWORD)FileBuffer), SrcSize);
}
void XORcrypt(char str2xor[], size_t len, char key) {
int i; for (i = 0; i < len; i++) {
str2xor[i] = (BYTE)str2xor[i] ^ key;
}
}
DWORD pFileBuffer_pImageBuffer(LPVOID pFileBuffer, LPVOID* ppImageBuffer)
{
PIMAGE_DOS_HEADER pDos_header = NULL;
PIMAGE_NT_HEADERS pNT_header = NULL;
PIMAGE_FILE_HEADER pPE_header = NULL;
PIMAGE_OPTIONAL_HEADER pOption_header = NULL;
PIMAGE_SECTION_HEADER pSection_header = NULL;
//验证MZ标志
pDos_header = (PIMAGE_DOS_HEADER)pFileBuffer;
if (pDos_header->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志\n");
free(pFileBuffer);
}
//计算NT头起始地址*
pNT_header = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDos_header->e_lfanew);
//验证NT头
if (pNT_header->Signature != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
free(pFileBuffer);
return 0;
}
//标准PE头和可选PE头
pPE_header = (PIMAGE_FILE_HEADER)((DWORD)pNT_header + 4);
pOption_header = (PIMAGE_OPTIONAL_HEADER)((DWORD)pPE_header + IMAGE_SIZEOF_FILE_HEADER);
//节表
pSection_header = (PIMAGE_SECTION_HEADER)((DWORD)pOption_header + pPE_header->SizeOfOptionalHeader);
*ppImageBuffer = malloc(pOption_header->SizeOfImage);
if (!*ppImageBuffer)
{
printf("分配空间失败\n");
return 0;
}
printf("SizeOfImage:%x\n", pOption_header->SizeOfImage);
memset(*ppImageBuffer, 0, pOption_header->SizeOfImage);
memcpy(*ppImageBuffer, pDos_header, pOption_header->SizeOfHeaders);
for (int i = 0; i < pPE_header->NumberOfSections; i++, pSection_header++)
{
memcpy((LPVOID)((DWORD)*ppImageBuffer + pSection_header->VirtualAddress), (LPVOID)((DWORD)pDos_header + pSection_header->PointerToRawData), pSection_header->SizeOfRawData);
}
pSection_header = NULL;
printf("拷贝完成\n");
return pOption_header->SizeOfImage;
}
VOID cProcess(LPVOID pSrcImageBuffer, DWORD ImageSize)
{
//创建子进程shell
//TCHAR szBuffer[MAX_PATH] = PATH;
STARTUPINFO ie_si = { 0 };
PROCESS_INFORMATION ie_pi;
ie_si.cb = sizeof(ie_si);
CreateProcess("C:\\Users\\xx\\Desktop\\new.exe",
NULL,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&ie_si,
&ie_pi
);
CONTEXT contx;
contx.ContextFlags = CONTEXT_FULL;
GetThreadContext(ie_pi.hThread, &contx);
//加载ZwUnmapViewOfSection函数卸载外壳程序文件映像
typedef NTSTATUS(WINAPI* ZWUNMAPVIEWOFSECTION)(
HANDLE ProcessHandle,
PVOID BaseAddress
);
HMODULE hNtdll = GetModuleHandle("ntdll.dll");
if (hNtdll == NULL) {
printf("Failed to get handle to ntdll.dll\n");
return;
}
//找到ImageBase内存镜像基址
PIMAGE_DOS_HEADER pDos_header = NULL;
PIMAGE_NT_HEADERS pNT_header = NULL;
PIMAGE_FILE_HEADER pPE_header = NULL;
PIMAGE_OPTIONAL_HEADER32 pOption_header = NULL;
PIMAGE_SECTION_HEADER pSection_header = NULL;
pDos_header = (PIMAGE_DOS_HEADER)pSrcImageBuffer;
pNT_header = (PIMAGE_NT_HEADERS)((DWORD)pDos_header + pDos_header->e_lfanew);
pPE_header = (PIMAGE_FILE_HEADER)((DWORD)pNT_header + 4);
pOption_header = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPE_header + IMAGE_SIZEOF_FILE_HEADER);
ZWUNMAPVIEWOFSECTION ZwUnmapViewOfSection = (ZWUNMAPVIEWOFSECTION)GetProcAddress(hNtdll, "ZwUnmapViewOfSection");
ZwUnmapViewOfSection(ie_pi.hProcess, (LPVOID)pOption_header->ImageBase);
if (ZwUnmapViewOfSection == NULL) {
printf("Failed to get address of ZwUnmapViewOfSection\n");
return;
}
//在子进程申请一块空间内存
LPVOID Vaddress = VirtualAllocEx(ie_pi.hProcess, (LPVOID)pOption_header->ImageBase, pOption_header->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (Vaddress == NULL) {
printf("申请空间失败\n");
Vaddress = VirtualAllocEx(ie_pi.hProcess, NULL, pOption_header->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (Vaddress == NULL) {
printf("申请空间失败,可能需要重定位\n");
return;
}
}
//往子进程的内存空间里面复制src数据
BOOL bResult = WriteProcessMemory(ie_pi.hProcess, (LPVOID)pOption_header->ImageBase, pSrcImageBuffer, ImageSize, NULL);
if (!bResult)
{
printf("Failed to write data to remote process memory\n");
CloseHandle(ie_pi.hProcess);
}
//修改运行环境的OEP和ImageBase
contx.Eip = (DWORD)((BYTE*)Vaddress + pOption_header->AddressOfEntryPoint); // 修改 Eip 为新的 OEP
SetThreadContext(ie_pi.hProcess, &contx);
// 恢复子进程执行
ResumeThread(ie_pi.hThread);
}
int main()
{
LPVOID ShellBuffer = NULL;
LPVOID SrcBuffer = NULL;
DWORD SrcSize = 0;
LPVOID pSrcImageBuffer = NULL;
LPVOID* ppImageBuffer = &pSrcImageBuffer;
DWORD ImageSize = 0;
Read_PE(ShellBuffer, SrcBuffer, SrcSize);
XORcrypt((char*)SrcBuffer, SrcSize, 0x32);
ImageSize = pFileBuffer_pImageBuffer(SrcBuffer, ppImageBuffer);
cProcess(pSrcImageBuffer, ImageSize);
getchar();
}
遇到的坑:(大坑)
1、打印的时候使用unicode字符集时,只能打印出E,因为printf打印时遇到00结束符就会停止打印
2、在卸载外壳程序文件映像ZwUnmapViewOfSection(ie_pi.hProcess, (LPVOID)pOption_header->ImageBase);第二个参数我写成pSrcImageBase导致一直没卸载成功,但是他不会报错所以我一直没调试出来这里出问题
3、不能在虚拟机环境运行md不知道为什么,听说需要转换一层地址好像