首页 > 其他分享 >滴水逆向笔记系列-win32总结8-59.枚举窗口_鼠标键盘事件函数-60.加密壳项目

滴水逆向笔记系列-win32总结8-59.枚举窗口_鼠标键盘事件函数-60.加密壳项目

时间:2024-03-17 17:37:31浏览次数:14  
标签:win32 59 HEADER 60 header pOption DWORD PIMAGE NULL

第五十九课 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);							
}					

image.png

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查找子窗口
image.png

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.正常其他壳思路

image.pngimage.png
注:
我们在追加代码里面的函数比如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结束符就会停止打印
image.png
image.png
2、在卸载外壳程序文件映像ZwUnmapViewOfSection(ie_pi.hProcess, (LPVOID)pOption_header->ImageBase);第二个参数我写成pSrcImageBase导致一直没卸载成功,但是他不会报错所以我一直没调试出来这里出问题
3、不能在虚拟机环境运行md不知道为什么,听说需要转换一层地址好像
image.png

标签:win32,59,HEADER,60,header,pOption,DWORD,PIMAGE,NULL
From: https://www.cnblogs.com/xiaoxin07/p/18078821

相关文章

  • 滴水逆向笔记系列-win32总结9-61.CE使用-62.ShellCode_远程线程注入
    第六十一课CE使用下载完CE后用ce自带的小作业练练1.第二题先打开进程Firstscan搜索100,发现有很多100,我们先让右边程序Hitme,然后Nextscan搜索96,发现已经搜出来了,正常数据会很多,就需要继续改继续搜,最后点击下面value修改为1000即可2.第三题先NewScan搜索小于500的,点击......
  • 滴水逆向笔记系列-win32总结10-63.IAT HOOK-64.Inline HOOK
    第六十三课IATHOOK这节课得把前面PE部分的IAT表复习好,再来做就简单多了1.IATHOOK是什么其实就是找到IAT表的位置再换成自己定义的函数,只是我们替换的函数需要和原函数的结构保持一直,比如我们要HOOKMessagebox函数,那么我们需要定义一个MyMessagebox函数,他的结构应该与Messa......
  • 滴水逆向笔记系列-win32总结7-57.进程创建-58.挂起方式创建进程
    第五十七课win32进程创建1.进程创建的过程父进程创建子进程,父进程挂了子进程不会挂0x00程序、imagebuffer、进程的关系程序就是一个普通的二进制文件;imagebuffer就是程序拉伸到内存后的二进制文件,但是没有线程去执行他,进程则是有线程去运行这个imagebuffer0x01过程......
  • 860. 柠檬水找零c
    boollemonadeChange(int*bills,intbillsSize){intmoney[21]={0};for(inti=0;i<billsSize;i++){if(bills[i]==5){money[5]++;}elseif(bills[i]==10){money[5]--;money[10]++;if(m......
  • 【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式
    [蓝桥杯2013省A]大臣的旅费题目描述很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同......
  • 滴水逆向笔记系列-win32总结4-50.创建线程-51.线程控制_CONTEXT结构
    第五十课win32创建线程1.进程与线程程序就是在硬盘里还没跑起来的二进制文件,进程就是已经运行中的程序,一个进程至少有一个线程,比如一个正在举行的活动需要几十个人帮忙干活,进程就是那个活动,线程就是那几十个人一个线程启动是需要占用一个cpu的一个新线程也会创建一个新堆......
  • 滴水逆向笔记系列-win32总结5-52.临界区-53.互斥体
    第五十二课win32临界区1.线程安全问题其实就是多个线程同时对一个资源(即全局变量等)进行操作2.临界区设计图临界区的使用1、创建CRITICAL_SECTION: CRITICAL_SECTIONcs; 2、在使用前进行初始化 InitializeCriticalSection(&cs); ......
  • 蓝桥杯单片机STC15F2K60S2第十三届省赛代码详细讲解(附完整代码)
     一、前言            在蓝桥杯单片机的比赛当中,很多传感器都是会经常使用到的,比如说DS18B20和DS1302等,都是会经常用到的,所以我们要把这些传感器都学会一下。在省十三的蓝桥杯单片机题目中,我自己也写了一下这个代码,可能有些地方会有点问题,但是大致的功能还是能......
  • 滴水逆向笔记系列-win32总结1-43.宽字节-44.事件_消息_消息处理函数
    第四十三课win32宽字节1.编码0x00.ASCII码1、ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符2、标准ASCII码使用7位二进制数来表示所有的大写和小写字母,数字0到9、标点符号,以及在美式英语中使用的特殊控制字符。3、扩展ASCII码允许将......
  • 滴水逆向笔记系列-win32总结2-45.esp寻址_定位回调函数-46.子窗口_消息处理函数-47.资
    第四十五课win32esp寻址_定位回调函数自己vs编译的exe入口函数好像和课程视频哩的vc6不一样,没办法跟着视频走,可以用课件里给的作业exe勉强跟着视频学,前面的都差不多,课件下载地址:https://www.bcdaren.com/video/videoPlay/3303185150621818881.win32应用程序入口识别没加过壳......