PEedit总结
——千里之行,始于足下
1.引言
1.1编写目的
该工具模仿LoadPE,目的是通过做项目来了解PE结构。
1.2背景
说明:
a.项目名称:PEedit
b.任务提出者:A1pass,编写者:GhostDL
1.3 开发工具
VS2012 Update3、OllDbg
1.4 参考资料
a.LordPE结构说明
b.《黑客免杀攻防》
c.《Windows PE权威指南》
d.网上相关资料
2.实际开发结果
2.1产品结构图
2.2版本
当前版本为Bate1.0版
2.3主要功能
a.查看及编辑PE基本信息
b.查看及编辑目录表结构信息
c.查看区段基本信息
d.查看输入表、输出表、资源表及重定位表信息
e.可用16Edit定位编辑
f.加密伪装壳
2.4性能
性能比较稳定,能够接受压力测试,可以抵御变态的PE文件
2.5进度
进度比较慢,以后慢慢完善。
3.开发
3.1程序文件列表
3.2相关代码
a.工具函数类
/******************************************************************/
/* 函数功能:多字节转宽字节,使用后需要delete */
/* 参数: 多字节 */
/* 返回值:WCHAR* */
/*******************************************************************/
WCHAR* MultiByte2WideChar(CHAR* multiChar)
{
DWORD dwNum = MultiByteToWideChar(CP_ACP,0,multiChar,-1,NULL,0);
WCHAR *wideChar = new WCHAR[dwNum];
MultiByteToWideChar (CP_ACP, 0, multiChar, -1, wideChar, dwNum);
return wideChar;
}
/*******************************************************************/
/* 函数功能:宽字节转多字节,使用后需要delete */
/* 参数: 多字节 */
/* 返回值:CHAR* */
/*******************************************************************/
CHAR* WideChar2MultiByte(WCHAR *wcChar )
{
//宽字节转换多字节
DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,wcChar,-1,NULL,0,NULL,FALSE);
char *psText;
psText = new char[dwNum];
WideCharToMultiByte (CP_OEMCP,NULL,wcChar,-1,psText,dwNum,NULL,FALSE);
return psText;
}
/*******************************************************************/
/* 函数功能:判断是否为PE文件 */
/* 参数:lpImage文件映像基址、文件大小 */
/* 返回值:TURE或FALSE */
/*******************************************************************/
BOOL IsPE_File(PVOID lpImage)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImage;
if ( pDos->e_magic != IMAGE_DOS_SIGNATURE )
return FALSE;
PIMAGE_NT_HEADERS32 pNT32 = (PIMAGE_NT_HEADERS32)((LONG)lpImage+pDos->e_lfanew);
if ( pNT32->Signature != IMAGE_NT_SIGNATURE )
return FALSE;
return TRUE;
}
/*******************************************************************/
/* 函数功能:获取真正内存地址 */
/* 参数:RVA相对虚地址、装入内存基址、PE文件头 */
/* 返回值:真正内存地址 */
/*******************************************************************/
DWORD RVA2Offset( DWORD dwRVA, PVOID lpImage, PIMAGE_NT_HEADERS32 pNT32 )
{
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT32);
for ( DWORD i=0; i<pNT32->FileHeader.NumberOfSections; i++ )
{
if ( dwRVA>=pSection[i].VirtualAddress && dwRVA<pSection[i].VirtualAddress+pSection[i].Misc.VirtualSize )
{
DWORD dwR_Offset = dwRVA - pSection[i].VirtualAddress;
DWORD dwOffset =(DWORD)lpImage+ dwR_Offset+ pSection[i].PointerToRawData;
return dwOffset;
}
}
return 0;
}
/*******************************************************************/
/* 函数功能:判断在哪个区段 */
/* 参数:lpImage文件映像基址 */
/* 返回值:所在区段的RVA */
/*******************************************************************/
DWORD GetRvaInWhitchSection( DWORD dwRVA,PVOID lpImage,PIMAGE_NT_HEADERS32 pNT32)
{
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT32);
for (DWORD i=0; i<pNT32->FileHeader.NumberOfSections; i++)
{
if (dwRVA>=pSection[i].VirtualAddress && dwRVA<pSection[i].VirtualAddress+pSection[i].Misc.VirtualSize)
{
return (DWORD)&pSection[i];
}
}
return 0;
}
/*******************************************************************/
/* 函数功能:获取PIMAGE_NT_HEADERS32 */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_NT_HEADERS32 */
/*******************************************************************/
PIMAGE_NT_HEADERS GetNtHeaders(LPVOID lpImage)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImage;
PIMAGE_NT_HEADERS32 pNT32 = (PIMAGE_NT_HEADERS32)((LONG)lpImage+pDos->e_lfanew);
return pNT32;
}
/*******************************************************************/
/* 函数功能:获取PIMAGE_FILE_HEADER */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_FILE_HEADER */
/*******************************************************************/
PIMAGE_FILE_HEADER GetFileHeader(LPVOID lpImage)
{
if(!IsPE_File(lpImage))
return NULL;
PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
PIMAGE_FILE_HEADER pImageHeader = &(pNT32->FileHeader);
return pImageHeader;
}
/*******************************************************************/
/* 函数功能:获取文件扩展头 */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_OPTIONAL_HEADER */
/*******************************************************************/
PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID lpImage)
{
if(!IsPE_File(lpImage))
return NULL;
PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
PIMAGE_OPTIONAL_HEADER pOH=&pNT32->OptionalHeader;
return pOH;
}
/*******************************************************************/
/* 函数功能:获取数据目录表 */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_DATA_DIRECTORY */
/*******************************************************************/
PIMAGE_DATA_DIRECTORY GetDataDirctory(LPVOID lpImage)
{
PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
PIMAGE_DATA_DIRECTORY pDir = (PIMAGE_DATA_DIRECTORY)pNT32->OptionalHeader.DataDirectory;
return pDir;
}
/*******************************************************************/
/* 函数功能:获取导入表 */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_IMPORT_DESCRIPTOR */
/*******************************************************************/
PIMAGE_IMPORT_DESCRIPTOR GetImportTable(LPVOID lpImage)
{
PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
PIMAGE_DATA_DIRECTORY pDir = GetDataDirctory(lpImage);
PIMAGE_DATA_DIRECTORY pImportDir = pDir+IMAGE_DIRECTORY_ENTRY_IMPORT;
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVA2Offset(pImportDir->VirtualAddress, lpImage, pNT32);
return pImport;
}
/*******************************************************************/
/* 函数功能:获得第一个节头 */
/* 参数:lpImage文件映像基址 */
/* 返回值:PIMAGE_SECTION_HEADER */
/*******************************************************************/
PIMAGE_SECTION_HEADER GetFirstSectionHeader(LPVOID lpImage)
{
PIMAGE_NT_HEADERS pNtHeader=GetNtHeaders(lpImage);
if (pNtHeader!=NULL)
{
return IMAGE_FIRST_SECTION(pNtHeader); //根据NT头得到首个SECTION的宏
}
return NULL;
}
/*******************************************************************/
/* 函数功能:关闭打开的文件 */
/* 参数:MAP文件结构体 */
/* 返回值:无 */
/*******************************************************************/
void UnLoadFile(PMAP_FILE_STRUCT pstMapFile)
{
if(pstMapFile->ImageBase)
UnmapViewOfFile(pstMapFile->ImageBase);
if(pstMapFile->hMapping)
CloseHandle(pstMapFile->hMapping);
if(pstMapFile->hFile)
CloseHandle(pstMapFile->hFile);
}
/*******************************************************************/
/* 函数功能:加载文件 */
/* 参数:文件绝对地址, MAP文件结构体 */
/* 返回值:无 */
/*******************************************************************/
BOOL LoadFileR(LPTSTR lpFilename,PMAP_FILE_STRUCT pstMapFile)
{
HANDLE hFile;
HANDLE hMapping;
LPVOID ImageBase;
memset(pstMapFile,0,sizeof(MAP_FILE_STRUCT));
hFile=CreateFile(lpFilename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0);
if (!hFile)
return FALSE;
hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(!hMapping)
{
CloseHandle(hFile);
return FALSE;
}
ImageBase=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
if(!ImageBase)
{
CloseHandle(hMapping);
CloseHandle(hFile);
return FALSE;
}
pstMapFile->hFile=hFile;
pstMapFile->hMapping=hMapping;
pstMapFile->ImageBase=ImageBase;
return TRUE;
}
LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_DROPFILES:
{
int FileNum = DragQueryFile((HDROP)wParam,-1,szFilePath,0);//得到拖动文件个数
if(FileNum!=1)
return FALSE;
DragQueryFile((HDROP)wParam, 0, szFilePath, MAX_PATH);
stMapFile.tFilePath = szFilePath;
SendDlgItemMessage(hWnd,IDC_FILEPATH_EDIT,WM_SETTEXT,MAX_PATH,(LPARAM)szFilePath);
UnLoadFile(&stMapFile);
if(!LoadFileR(szFilePath,&stMapFile))
{
MessageBox(hWnd,_T("Load file faild! :("),_T("PEInfo_Example"),MB_OK);
EnableEditCtrl(hWnd,FALSE);
return FALSE;
}
if(!IsPE_File(stMapFile.ImageBase))
{
MessageBox(hWnd,_T("Invalid PE Format file!:("),_T("PEInfo_Example"),MB_OK);
UnLoadFile(&stMapFile);
EnableEditCtrl(hWnd,FALSE);
return FALSE;
}
EnableEditCtrl(hWnd,TRUE);
ShowFileHeaderInfo(hWnd);
ShowOptionHeaderInfo(hWnd);
return TRUE;
}
case WM_INITDIALOG:
hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_SMALL));
SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
EnableEditCtrl(hWnd,FALSE);
return TRUE;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
// 打开文件
case IDC_OPEN_BTN:
OpenFileFun(hWnd);
return TRUE;
// 显示位置计算器
case IDC_CLAC:
DialogBox(hInst,MAKEINTRESOURCE(IDD_CALCPOS_DLG), hWnd, (DLGPROC)CalcPosDlgProc);
return TRUE;
// 保存主界面PE修改信息
case IDC_SAVE_BTN:
OnSavePE(hWnd);
return TRUE;
// 显示区段对话框
case IDC_SHOWSHT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_SHT_DLG), hWnd, (DLGPROC)SectionTableDlgProc);
return TRUE;
// 显示数据目录表
case IDC_SHOWDATADIR:
DialogBox(hInst, MAKEINTRESOURCE(IDD_DATADIR_DLG), hWnd, (DLGPROC)DataDirDlgProc);
return TRUE;
//加壳操作
case IDC_PACKER:
Packing(hWnd);
return TRUE;
// 点击退出
case IDC_EXIT:
SendMessage(hWnd, WM_CLOSE,0,0);
return TRUE;
}
break;
case IDC_ABOUTBTN:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About);
return TRUE;
//程序退出
case WM_CLOSE:
UnLoadFile(&stMapFile);
EndDialog(hWnd, 0);
return TRUE;
}
return FALSE;
}
/*******************************************************************/
/* 函数功能:显示目录表信息 */
/* 参数:HWND */
/* 返回值:无 */
/*******************************************************************/
void ShowDataDirInfo(HWND hDlg)
{
TCHAR tcBuff[9];
//获取PE扩展头
PIMAGE_OPTIONAL_HEADERpOH=GetOptionalHeader(stMapFile.ImageBase);
if(!pOH) return;
//循环获取目录表信息并显示在对话框中
for(int i=0;i<COUNT_OF_DATADIR;i++)
{
wsprintf(tcBuff,_T("%08lX"),pOH->DataDirectory[i].VirtualAddress);
SetDlgItemText(hDlg,EditID_Array[i].ID_RVA,cBuff);
wsprintf(tcBuff, _T("%08lX"), pOH->DataDirectory[i].Size);
SetDlgItemText(hDlg,EditID_Array[i].ID_SIZE,cBuff);
}
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)