字节补丁生成工具

可以生成加载器补丁exe和字节补丁exe,用附加可执行代码等方法可用于一些程序的破解

#ifndef APIMACRO_H
#define APIMACRO_H

通用控件头文件和链接库
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
//


///Sets the dialog box icons//
inline void chSETDLGICONS(HWND hWnd, int idi) {
   SendMessage(hWnd, WM_SETICON, ICON_BIG,  (LPARAM) 
      LoadIcon((HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE), 
         MAKEINTRESOURCE(idi)));
   SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) 
      LoadIcon((HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE), 
      MAKEINTRESOURCE(idi)));
}

inline void chMB(PCSTR szMsg) {
   char szTitle[MAX_PATH];
   GetModuleFileNameA(NULL, szTitle, _countof(szTitle));
   MessageBoxA(GetActiveWindow(), szMsg, szTitle, MB_OK);
}

#define chBEGINTHREADEX(psa, cbStackSize, pfnStartAddr, \
   pvParam, dwCreateFlags, pdwThreadId)                 \
      ((HANDLE)_beginthreadex(                          \
         (void *)        (psa),                         \
         (unsigned)      (cbStackSize),                 \
         (PTHREAD_START) (pfnStartAddr),                \
         (void *)        (pvParam),                     \
         (unsigned)      (dwCreateFlags),               \
         (unsigned *)    (pdwThreadId)))


//通用控件使用前务必InitCommonControls初始化
//List_View 控件宏       行数列数索引均从0开始
static LV_ITEM		_stLVI;
static LV_COLUMN	_stLVC;

//在ListView中新增一行///
inline int ListView_AddLine(HWND hwndCtl)
{
	RtlZeroMemory (&_stLVI,sizeof(LV_ITEM) );
	_stLVI.mask			= LVIF_TEXT;
	_stLVI.pszText		= TEXT("无数据可显示");
	_stLVI.iSubItem		= 0;
	return ListView_InsertItem(hwndCtl, &_stLVI);
}



在ListView中增加一个标题列///
inline void ListView_InsertCaption(HWND hwndCtl, int iColumn, int iWidth, LPTSTR lpszCaption)
{
	RtlZeroMemory (&_stLVC,sizeof(LV_COLUMN) );
	_stLVC.mask			= LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
	_stLVC.fmt			= LVCFMT_LEFT;
	_stLVC.pszText		= lpszCaption;
	_stLVC.cx			= iWidth;
	_stLVC.iSubItem		= iColumn;
	ListView_InsertColumn(hwndCtl, iColumn, &_stLVC);
}


在ListView中更改一个标题列///
inline void ListView_SetCaption(HWND hwndCtl, int iColumn, LPTSTR lpszCaption)
{
	RtlZeroMemory (&_stLVC,sizeof(LV_COLUMN) );
	_stLVC.mask			= LVCF_TEXT | LVCF_FMT;
	_stLVC.fmt			= LVCFMT_LEFT;
	_stLVC.pszText		= lpszCaption;
	_stLVC.iSubItem		= iColumn;
	ListView_SetColumn(hwndCtl, iColumn, &_stLVC);
}


#endif

 

 

#ifndef RVATOOFFSET_H
#define RVATOOFFSET_H

#include <windows.h>

//各种PE中偏移的转换实现//

char szNotFound[] = "无法查找";
///将RVA偏移转换成文件偏移,失败返回-1

DWORD RvaToOffset (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva)
{
	::IMAGE_NT_HEADERS		*lpPEHead;
	::IMAGE_SECTION_HEADER	*lpSectionHead;
	DWORD i;
	lpPEHead		= (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
	i	= lpPEHead->FileHeader.NumberOfSections;
	lpSectionHead	= (IMAGE_SECTION_HEADER*)(++lpPEHead); 
	for ( ; i > 0 ; i--, lpSectionHead++)
	{
		if ( (dwRva >= lpSectionHead->VirtualAddress) && (dwRva < (lpSectionHead->VirtualAddress + lpSectionHead->SizeOfRawData) ) )
		{
			dwRva	= dwRva - lpSectionHead->VirtualAddress + lpSectionHead->PointerToRawData;
			return dwRva;
		}
	}
	return -1;
}





将RVA偏移转成文件指针偏移,失败返回-1

DWORD RvaToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwRva)
{
	DWORD	Offset	= RvaToOffset(lpFileHead, dwRva);
	if(Offset == -1)
		return -1;
	return	(DWORD)(lpFileHead) + Offset;
}





将虚拟地址转成文件指针偏移,失败返回-1

DWORD VirtualAddressToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwVirtualAddress)
{
	::IMAGE_NT_HEADERS		*lpPEHead;
	lpPEHead		= (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
	
	return RvaToPointer(lpFileHead, dwVirtualAddress - lpPEHead->OptionalHeader.ImageBase);
}





获得RVA偏移处的节区名称

PBYTE GetRvaSection (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva)
{
	IMAGE_NT_HEADERS		*lpPEHead;
	IMAGE_SECTION_HEADER	*lpSectionHead;
	DWORD i;
	lpPEHead		= (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
	i	= lpPEHead->FileHeader.NumberOfSections;
	lpSectionHead	= (IMAGE_SECTION_HEADER*)(++lpPEHead); 
	for ( ; i > 0 ; i--, lpSectionHead++)
	{
		if ( (dwRva >= lpSectionHead->VirtualAddress) && (dwRva < (lpSectionHead->VirtualAddress + lpSectionHead->SizeOfRawData) ) )
		{
			return (PBYTE)lpSectionHead;
		}
	}
	return (PBYTE)szNotFound;
}





///获得指定RVA所处节区的节表头,失败返回NULL/

PIMAGE_SECTION_HEADER GetSectionOfRva (IMAGE_DOS_HEADER *lpFileHead, char* secName)
{
	::PIMAGE_NT_HEADERS lpNtHead		= (PIMAGE_NT_HEADERS)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
	DWORD dwSec = lpNtHead->FileHeader.NumberOfSections;
	IMAGE_SECTION_HEADER* lpSection	= (PIMAGE_SECTION_HEADER) (lpNtHead + 1);
	
	for (DWORD i=0; i < dwSec; i++)
	{
		if(!strncmp((char*)lpSection->Name, secName, IMAGE_SIZEOF_SHORT_NAME) )
			return lpSection;
		lpSection++;
	}
	return NULL;
}





文件偏移转换成RVA///

DWORD OffsetToRva(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOffset)
{
	::IMAGE_NT_HEADERS		*lpPEHead;
	::IMAGE_SECTION_HEADER	*lpSectionHead;
	DWORD i;
	lpPEHead		= (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
	i	= lpPEHead->FileHeader.NumberOfSections;
	lpSectionHead	= (IMAGE_SECTION_HEADER*)(++lpPEHead); 

	for ( ; i > 0; i--, lpSectionHead++)
	{
		if ( (dwOffset >= lpSectionHead->PointerToRawData) && (dwOffset < (lpSectionHead->PointerToRawData + lpSectionHead->SizeOfRawData) ) )
		{
			dwOffset	= dwOffset - lpSectionHead->PointerToRawData + lpSectionHead->VirtualAddress;
			return dwOffset;
		}
	}
	return -1;
}





文件偏移转换成内存指针///

DWORD OffsetToPointer(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOffset)
{
	DWORD	RVA	= OffsetToRva(lpFileHead, dwOffset);
	if( RVA == -1)
		return -1;
	return	(DWORD)(lpFileHead) + RVA;
}





/按指定大小对齐//

DWORD Align(DWORD dwSize, DWORD dwAlignment)
{
	return (dwSize + dwAlignment - 1) /dwAlignment * dwAlignment;
}





///获得区块有效数据部分大小/

DWORD GetValidSize(PBYTE lpMemory, PIMAGE_SECTION_HEADER lpSection)
{
	PBYTE	lpData;
	DWORD	dwSize=0;

	lpData	= (PBYTE)( lpMemory + lpSection->PointerToRawData + lpSection->SizeOfRawData - 1);
	while (*lpData == 0)
	{
		lpData--;
		dwSize++;
	}
	dwSize -= 8;  //减去8个字节防止是字符串或某结构的结尾
	if (dwSize > 0)
		return lpSection->SizeOfRawData - dwSize;
	else
		return lpSection->SizeOfRawData;
}



#endif


 


 

#ifndef KERNEL_H
#define KERNEL_H
#include "RvaToOffset.h"

#define ITEM_NUM 16
//静态补丁类型
#define ADD_LAST_SECTION 1	//添加代码到最后一个区段	
#define ADD_NEW_SECTION  2  //添加代码到一个新建的区段
#define ADD_TO_HEADER	 3  //添加代码到PE头部
#define	BYTE_PATCH		 4  //这里再加一种字节补丁,针对一些简单的程序

//动态补丁类型
#define SLEEP_PATCH 1	
#define DEBUG_PATCH 2

extern HINSTANCE	hInst;   //此变量在主文件中定义

//主要功能函数实现
BOOL IsPeFile(TCHAR szFileName[])
{
	HANDLE	hFile;
	WORD	wMagic;
	DWORD   dwRead,dw;
	if (INVALID_HANDLE_VALUE != ( hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, \
																		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL) ) )
	{
		ReadFile(hFile , &wMagic, 2, &dwRead, NULL);
		if ( wMagic == 0x5A4D)
		{
			SetFilePointer(hFile, 0x3C, 0, FILE_BEGIN);
			ReadFile(hFile , &dw, 4, &dwRead, NULL);
			SetFilePointer(hFile, dw, 0, FILE_BEGIN);
			ReadFile(hFile , &wMagic, 2, &dwRead, NULL);
			if (wMagic == 0x4550)
				return TRUE;
		}
	}
	return FALSE;
}



// 计算字符串的CRC32值
// 参数:欲计算CRC32值字符串的首地址和大小
// 返回值: 返回CRC32值

DWORD CalCRC32(BYTE* ptr,DWORD Size)
{

	DWORD crcTable[256],crcTmp1;
	
	//动态生成CRC-32表
	for (int i=0; i<256; i++)
	 {
		crcTmp1 = i;
		for (int j=8; j>0; j--)
		 {
			if (crcTmp1&1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
			 else crcTmp1 >>= 1;
		}

		 crcTable[i] = crcTmp1;
	 }
	//计算CRC32值
	DWORD crcTmp2= 0xFFFFFFFF;
	while(Size--)
	{
		crcTmp2 = ((crcTmp2>>8) & 0x00FFFFFF) ^ crcTable[ (crcTmp2^(*ptr)) & 0xFF ];
		ptr++;
	}
		
	return (crcTmp2^0xFFFFFFFF);
}

DWORD GetCRC32(TCHAR szFileName[])
{
	PIMAGE_DOS_HEADER	    pDosHeader=NULL;
    PIMAGE_NT_HEADERS       pNtHeader=NULL;
    PIMAGE_SECTION_HEADER   pSecHeader=NULL;

	DWORD fileSize, CRC32, NumberOfBytesRW;
 	PBYTE  pBuffer ; 

	//打开文件
	HANDLE hFile = CreateFile( szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
	if ( hFile == INVALID_HANDLE_VALUE ) 
		 return FALSE;

	//获得文件长度 :
	fileSize = GetFileSize(hFile,NULL);
	if (fileSize == 0xFFFFFFFF) 
		return FALSE;

	pBuffer = new BYTE[fileSize];     // 申请内存
	ReadFile(hFile,pBuffer, fileSize, &NumberOfBytesRW, NULL);//读取文件内容
	CloseHandle(hFile);  //关闭文件

	pDosHeader	= (PIMAGE_DOS_HEADER)pBuffer;
	fileSize	= fileSize - pDosHeader->e_lfanew;
	CRC32	= CalCRC32(pBuffer + pDosHeader->e_lfanew, fileSize);
	delete	pBuffer;
	return CRC32;
}


/*需要工具修正的节为.sdata节
#pragma data_seg(".sdata")
DWORD	dwTypeOfPatch = 0;			/指示补丁类型
DWORD	dwPatchNum = 2;				//补丁数量
//偏移8
TCHAR	szFileName[MAX_PATH] = { 0 };
//偏移528
DWORD	dwPatchAddress[16] = { 0}  //利用调试寄存器打丁///
/打此类补丁应在补丁地址第一个地址填上希望中断的地址以确保所有地址数据已解码,以保证补丁正确性///
//偏移592
BYTE	byOldData[16] = { 0};		//补丁处旧数据和新数据
//偏移608
BYTE	byNewData[16] = { 0};
#pragma data_seg()
根据需要加入了CRC32验证,需要补丁工具在PE头前4个字节写上目标文件的CRC32*/



//创建补丁文件,补丁模版以资源的形式存储在程序中
//参数:szPatchName:创建的补丁文件名     szFileName:目标文件名     lpPatchAddress:补丁地址数组  
//	   lpNewByte:补丁原始数据数组       lpNewByte:补丁新数据数组  dwTypeOfPatch:补丁类型
//	   dwPatchNum:补丁数量				ID:补丁模版的资源ID		  bCRC32:是否加入CRC32文件验证
BOOL CreatePatch(TCHAR szPatchName[], TCHAR szFileName[], DWORD lpPatchAddress[],BYTE lpOldByte[],BYTE lpNewByte[],\
				 DWORD	dwTypeOfPatch, DWORD dwPatchNum, DWORD ID, BOOL bCRC32 )
{
	static	char	secName[8] = ".sdata";
	DWORD	CRC32;
	if (bCRC32)		
	{
		CRC32 = GetCRC32(szFileName );
		if (!CRC32)
		{
			MessageBox(NULL, TEXT("CRC32提取出错"), NULL, 0);
			return FALSE;
		}
	}
	
	DWORD	dwResSize;
	PBYTE	lpResData;
	HGLOBAL	hGlobal;
	HRSRC hRes	= FindResource(hInst, MAKEINTRESOURCE(ID), L"PETYPE" );
	if (hRes)
	{
		dwResSize	= SizeofResource(hInst, hRes);
		hGlobal		= LoadResource(hInst, hRes);
		if (hGlobal )
		{
			lpResData	= (PBYTE)LockResource(hGlobal);
			if (lpResData )
			{

///开始写入文件并修正补丁中的参数//

				HANDLE					hFile, hMap;
				PBYTE					lpMemory;
				PIMAGE_NT_HEADERS		lpNtHeaders;
				PIMAGE_SECTION_HEADER	lpSectionHeader;
				PBYTE					lpSectionData;
				DWORD*					lpCRC32;
				DWORD					dwFileSize, dwRead, dwSectionNum;

				if (INVALID_HANDLE_VALUE != ( hFile = CreateFile (szPatchName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL) ) )
				{
					WriteFile(hFile, lpResData, dwResSize, &dwRead, NULL);    //写入文件
					dwFileSize	= GetFileSize (hFile, NULL);
					//修正数据
					if (dwFileSize)
					{
						hMap	= CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
						if (hMap)
						{
							lpMemory	= (BYTE *)MapViewOfFile (hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
							if (lpMemory)
							{
								lpNtHeaders		= (PIMAGE_NT_HEADERS)(lpMemory + ((PIMAGE_DOS_HEADER)lpMemory)->e_lfanew);
								if (bCRC32)    //写CRC32值
								{
									lpCRC32			= (DWORD*)((PBYTE)(lpNtHeaders)-4);
									*lpCRC32		= CRC32;
								}
								dwSectionNum	= lpNtHeaders->FileHeader.NumberOfSections;
								lpSectionHeader	= (PIMAGE_SECTION_HEADER)(lpNtHeaders + 1);
								
								//查找需修正变量所在区段
								for (DWORD i=0; i < dwSectionNum; i++, lpSectionHeader++)
								{
									if ( !lstrcmpiA( (LPCSTR)lpSectionHeader->Name, secName) )
										break;
								}
								lpSectionData			= lpMemory + RvaToOffset( (PIMAGE_DOS_HEADER)lpMemory, lpSectionHeader->VirtualAddress);
修正变量///
								int x;
								*(DWORD*)lpSectionData	= dwTypeOfPatch;
								*(DWORD*)(lpSectionData+4) = dwPatchNum;
								
								for(x=lstrlen(szFileName); x > 0; x--)
									if(szFileName[x] == TEXT('\\') )
										break;
								
								lstrcpy( (LPWSTR)(lpSectionData+8), &(szFileName[x]) );
								memcpy(lpSectionData+528, lpPatchAddress, ITEM_NUM*sizeof(DWORD));
								memcpy(lpSectionData+592, lpOldByte, ITEM_NUM*sizeof(BYTE));
								memcpy(lpSectionData+608, lpNewByte, ITEM_NUM*sizeof(BYTE));
修正完毕
								
								UnmapViewOfFile (lpMemory);
								CloseHandle (hMap);
								CloseHandle (hFile);
								return TRUE;
							}

						}

					}

				}


				return FALSE;
			}
		}
	}
	return FALSE;
}


#endif


 

 

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>
#include "resource.h"
#include "ApiMacro.h"
#include "kernel.h"

//搞掉些烦人的警告
#pragma warning(disable:4244)
#pragma warning(disable:4996)

#define ITEM_NUM	16		//ListView最大项目数
#define CODE_SIZE	1024*32 //自定义补丁代码的最大长度
static  char	g_szBuffer[CODE_SIZE] = { 0 };	//32KB缓存
static  char	g_szUserCode[CODE_SIZE] = { 0 };//32KB用户代码缓存
BOOL	DIY_OK = FALSE;


//添加WIN7风格界面
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0'\
															processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")

界面辅助函数//
void SuperClass();	//编辑控件超类化,生成16进制编辑控件
LONG WINAPI ProcEdit(HWND, UINT, WPARAM, LPARAM);	//新编辑控件窗口过程
void PopFileInitialize (HWND hwnd);  //文件对话框初始化
BOOL PopFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName); //打开对话框
BOOL PopFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName); //保存对话框
/

//主对话框窗口过程
BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

//主对话框消息处理函数
BOOL Main_OnNotify	(HWND hwnd, int wParam,	LPNMHDR pnm);
BOOL Main_OnCommand	(HWND hDlg, int id,HWND hCtrl, UINT codeNotify);
BOOL Main_OnInitDialog (HWND hWnd, HWND hWndFocus, LPARAM lParam) ;

//高级设置对话框
BOOL CALLBACK SetDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
//帮助对话框
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) ;
//地址输入对话框
BOOL CALLBACK AddressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
//定制补丁对话框
BOOL CALLBACK DiyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void GetListData( );	//提取ListView的数据存到全局变量中
void GetPeHeader(TCHAR szFileName[]); //获取整个PE头部数据
BOOL CreateDiyPatch();	//定制补丁生成函数



HINSTANCE	hInst;
HWND		g_hWnd;			//主对话框窗口句柄
HWND		g_hListView;   //表格视图句柄
BOOL		g_bOffset = FALSE;  //记录补丁地址是否是用文件偏移,如果是则转换成虚拟地址	
DWORD		g_dwLineOfNum = 0;  //记录ListView数据行数
DWORD		g_dwTypeOfPatch = 1;//记录补丁类型,并赋值默认方法
DWORD		g_dwTypeOfLoader= 1;//记录Loader类型,并赋值默认方法
BOOL		g_bIsPeFile = FALSE;//指示目标文件是否是PE文件
PBYTE		g_lpPeHeader= NULL; //指向整个PE头部,用于RVA与offset之间的转换
DWORD		g_dwAddress = 0;	//地址对话框获得的地址

TCHAR		g_szFileName[MAX_PATH] = { 0 };		//目标文件名
TCHAR		g_szPatchName[MAX_PATH]= { 0 };		//补丁文件名

DWORD		g_pPatchAddress[ITEM_NUM] = { 0 };	//补丁地址
BYTE		g_pOldByte[ITEM_NUM] = { 0 };		//老数据
BYTE		g_pNewByte[ITEM_NUM] = { 0 };		//新数据


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值