首页
社区
课程
招聘
[原创][原创]编写PE文件分析器之二 查看输入表 输出表
2008-12-29 11:16 12378

[原创][原创]编写PE文件分析器之二 查看输入表 输出表

2008-12-29 11:16
12378
[大家好,在写输入表这一部分的时候,主要是为了自己能更加深入的理解PE文件格式; 输入表的部分代码参考了北极星2003老兄的一部分,然而发现,在北极星2003写的那个pe文件分析器导入表部分,它用了firstThunk 作为指针来输出Thunk rva 和函数名,由于在内存映射时改变FirstThunk中的数据,所以函数名就怎么都显示不出来了; 由于打算将这个PE文件分析器继续写下去,所以在完成每一部分后,我会将源代码发出;以便大家学习讨论,共同进步,也希望大家能对程序做些改进,而不是简单的复制粘贴代码,由于临近期末,所以时间不多,进度也就慢了点;大家多包涵;

这里给大家两个截图




源代码中Exe文件被剔除,为了减少空间;大家用Visual C++ 6.0 编译下就可以了;

#include<windows.h>
#include <commctrl.h>
#include "resource.h"
#ifndef _IMAGEHLP_H 
#include "imagehlp.h"
#pragma comment ( lib, "imagehlp.lib" )
#endif

/*-----------------------------
  全局变量定义
  -----------------------------*/

HINSTANCE	hInst;
HANDLE			hFile,hFileMap; 
LPVOID			lpMemory;
PIMAGE_OPTIONAL_HEADER	pOptionHeader = NULL;
PIMAGE_FILE_HEADER	pFileHeader = NULL;
PIMAGE_SECTION_HEADER	pSectionHeader = NULL;
PIMAGE_NT_HEADERS	pNtHeader = NULL;
	
/*----------------------------------
  对话框函数说明
  *---------------------------------*/
BOOL CALLBACK DlgProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam);
BOOL CALLBACK DataDlgProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam);
BOOL CALLBACK ImportDlgProc(HWND	hDlg, UINT message,WPARAM wParam,LPARAM lparam);


/*----------------------------------
  数据显示函数说明
  *---------------------------------*/
void	ShowSection(HWND hDlg);
void ShowDataDirectoryInDlg ( HWND hwnd );
void ShowSectionTable(HWND hDlg,PIMAGE_FILE_HEADER	pFileHeader,PIMAGE_SECTION_HEADER	pSectionHeader);
void	ShowImportDescInfo(HWND hDlg);
void ShowDllFunction( HWND hDlg, int index );
/*----------------------------------
  控件初始化函数说明
  *---------------------------------*/
BOOL WINAPI InitListViewColumns(HWND hDlg);
BOOL WINAPI	InitImportDescriptor(HWND	hDlg);

/*----------------------------------
  Pe文件处理函数函数说明
  *---------------------------------*/
BOOL IsPeFile(LPVOID ImageBase);
PIMAGE_NT_HEADERS	GetNtHeader(LPVOID	ImageBase);
PIMAGE_FILE_HEADER	WINAPI	GetFileHeader(LPVOID	Imagebase);
PIMAGE_OPTIONAL_HEADER	GetOptionalHeader(LPVOID	ImageBase);
PIMAGE_SECTION_HEADER	GetFirstSectionHeader(PIMAGE_NT_HEADERS	pNtHeader);
PIMAGE_IMPORT_DESCRIPTOR	GetFirstImportDesc(LPVOID	ImageBase);
/*----------------------------------
  主函数入口
  *---------------------------------*/

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowcmd)
{
	hInst = hInstance;
    DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG),NULL,DlgProc);

    return 0;
}

/*----------------------------------
  主程序对话框函数
  *---------------------------------*/
BOOL CALLBACK DlgProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam)
{

	HMENU			hMenu = GetMenu(hDlg);
	OPENFILENAME	FileName = {0,0,0},
					*lpFileName = &FileName;
	TCHAR			szPe[]="\"PE File(*.exe)\" \0*.exe;*.dll;*.scr;*.fon;*.drv;\0\"*.All File(*.*) \0*.*\0\0";
	TCHAR			szFileName[256]={""};
	TCHAR			buf[16];

	LVITEM	lvItem;
	ZeroMemory(&lvItem,sizeof(LVITEM));

	

	switch(message)
	{
		case	WM_INITDIALOG:
				EnableMenuItem(hMenu,IDM_DATA_DIRECTORY,MF_GRAYED);
				InitListViewColumns(hDlg);
				
				break;
		case	WM_CLOSE:
				UnmapViewOfFile(lpMemory);
				CloseHandle(hFileMap);
				CloseHandle(hFile);
				EndDialog(hDlg,NULL);
				EndDialog(hDlg,NULL);
				break;
	  
		case	WM_COMMAND:
				  switch(LOWORD(wParam))
				 {
				  case	IDM_DATA_DIRECTORY:
						DialogBox(hInst,MAKEINTRESOURCE(IDD_DATA_DIRECTORY),hDlg,DataDlgProc);
						break;

				  case  IDM_EXIT:
						UnmapViewOfFile(lpMemory);
						CloseHandle(hFileMap);
						CloseHandle(hFile);
						EndDialog(hDlg,NULL);
						break;

				  case	IDM_OPEN:
						FileName.hInstance = (HINSTANCE)hDlg;
						FileName.hwndOwner = hDlg;
						FileName.lStructSize = sizeof(OPENFILENAME);
						FileName.lpstrFilter = szPe;
						FileName.lpstrFile = szFileName;
						FileName.Flags = OFN_FILEMUSTEXIST||OFN_PATHMUSTEXIST;
						FileName.nMaxFile = sizeof(szFileName);
				
				
						 if(!GetOpenFileName(lpFileName))
						 {
							 MessageBox(hDlg,"GetOpenFileName 调用失败","ERROR",NULL);
							 break;
						 }
				
						SetDlgItemText(hDlg,IDC_FILENAME,szFileName);
 
						hFile = CreateFile(FileName.lpstrFile,           // open  pe file 
					    GENERIC_READ,              // open for reading 
					    FILE_SHARE_READ|| FILE_SHARE_WRITE,           // share for reading 
						NULL,                      // no security 
						OPEN_EXISTING,             // existing file only 
						FILE_ATTRIBUTE_NORMAL,     // normal file 
						NULL);                     // no attr. template 
 
						if (hFile == INVALID_HANDLE_VALUE) 
						{ 
							 MessageBox(hDlg,"Could not open file.","ERROR",MB_ICONERROR); 
							 break;// process error 
						} 

						if(GetFileSize(hFile,NULL)!=0)
						{
							hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
							if(hFileMap!=0)
							{
							lpMemory = MapViewOfFile(hFileMap,FILE_MAP_READ,NULL,NULL,NULL);
							}
						}
				
						if(IsPeFile(lpMemory))
						{

							pNtHeader = GetNtHeader(lpMemory);
							pFileHeader = GetFileHeader(lpMemory);
							pOptionHeader = GetOptionalHeader(lpMemory);
							pSectionHeader	= GetFirstSectionHeader(pNtHeader);
							if(!(pFileHeader&&pOptionHeader))
							{
								MessageBox(hDlg,"获取文件头指针失败","PEINFO",MB_ICONERROR);
								break;
							}
							else
							{

								wsprintf(buf,"%04lX",pFileHeader->Machine);
								SetDlgItemText(hDlg,IDC_MACHINE,buf);

								wsprintf(buf,"%04lX",pFileHeader->NumberOfSections);
								SetDlgItemText(hDlg,IDC_NUMSECTION,buf);

								wsprintf(buf,"%04lX",pOptionHeader->Magic);
								SetDlgItemText(hDlg,IDC_MAGIC,buf);

								wsprintf(buf,"%08lX",pOptionHeader->AddressOfEntryPoint);
								SetDlgItemText(hDlg,IDC_ENTERPOINT,buf);
						
								ShowSectionTable(hDlg,pFileHeader,pSectionHeader);
							}


						}
						else
						{
							MessageBox(hDlg,"你选择的不是PE文件","error",MB_ICONERROR);
							SendMessage(hDlg,WM_CLOSE,NULL,NULL);
						}
						
						EnableMenuItem(hMenu,IDM_DATA_DIRECTORY,MF_ENABLED);
				
							break;


						}
		
					
				}
		return FALSE;
}

/*--------------------------------
  数据目录对话框的关联函数,
  ------------------------------*/
BOOL CALLBACK DataDlgProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam)
{
	

	switch(message)
	{
		case	WM_INITDIALOG:
				ShowDataDirectoryInDlg ( hDlg );
			
				break;
		case	WM_CLOSE:
				EndDialog(hDlg,NULL);
				break;
		case	WM_COMMAND:
				switch(LOWORD(wParam))
				{
					case	IDC_IMDLG:
				
					DialogBox((HINSTANCE)GetModuleHandle(0),MAKEINTRESOURCE(IDD_IMPORT_DLG),hDlg,ImportDlgProc);
				
					break;
				}
			
	}
		return FALSE;
}


BOOL	CALLBACK	ImportDlgProc(HWND	hDlg, UINT message,WPARAM wParam,LPARAM lparam)
{
	switch(message)
	{
	case	WM_INITDIALOG:
			InitImportDescriptor(	hDlg);
			ShowImportDescInfo(hDlg);
		break;
	case	WM_CLOSE:
		EndDialog(hDlg,NULL);
		break;
	case WM_NOTIFY:
		switch ( LOWORD(wParam) )
		{
		case	IDC_IMPORT_DESCRIPTOR:
			switch ( ((LPNMHDR)lparam)->code)
			{
			case LVN_ITEMCHANGED:
				LPNMLISTVIEW temp = ( (LPNMLISTVIEW)lparam ) ;
				if( temp->uNewState )
				{
					ShowDllFunction ( hDlg, ( (LPNMLISTVIEW)lparam )->iItem ) ;
				}
				break ;
			}
			return TRUE ;
		}
		break ;
	}
	return	FALSE;
}


/*------------------------------------
   用于显示数据目录表的函数
   --------------------------------*/
void ShowDataDirectoryInDlg ( HWND hDlg )
{
		typedef	struct
				{
				UINT	ID_RVA;
				UINT	ID_SIZE;
				} DataDir_EditID;

		DataDir_EditID	DataDirEditId[]=
		{
			{	IDC_EXPORT_RAV,				IDC_EXPORT_SIZE			},
			{	IDC_IMPORT_RVA,				IDC_IMPORT_SIZE			},
			{	IDC_RES_RVA,				IDC_RES_SIZE			},
			{	IDC_EXCEPTION_RVA,			IDC_EXCEPTION_SIZE		},
			{	IDC_SECURITY_RVA,			IDC_SECURITY_SIZE		},
			{	IDC_BASE_RVA,				IDC_BASE_SIZE			},
			{	IDC_DEBUG_RVA,				IDC_DEBUG_SIZE			},
			{	IDC_COPYRIGHT_RVA,			IDC_COPYRIGHT_SIZE		},
			{	IDC_GLOBAL_RVA,				IDC_GLOBAL_SIZE			},
			{	IDC_THREAD_RVA,				IDC_THREAD_SIZE			},
			{	IDC_LOAD_RVA,				IDC_LOAD_SIZE			},
			{	IDC_BOUND_RVA,				IDC_BOUND_SIZE			},
			{	IDC_IAT_RVA,				IDC_IAT_SIZE			},
			{	IDC_DELAY_RVA,				IDC_DELAY_SIZE			},
			{	IDC_COM_RVA,				IDC_COM_SIZE			}	
		};
/*----------------------------
循环显示数据目录表
------------------------------*/
			TCHAR	buff[16];	
	
			for (int j=0; j< 15; j++ )
			{
					wsprintf ( buff, "%08lX", pOptionHeader->DataDirectory[j].VirtualAddress ) ;
					SetWindowText ( GetDlgItem ( hDlg, DataDirEditId[j].ID_RVA ), buff ) ;

					wsprintf ( buff, "%08lX", pOptionHeader->DataDirectory[j].Size ) ;
					SetWindowText ( GetDlgItem ( hDlg, DataDirEditId[j].ID_SIZE ), buff ) ;
			}
}

PIMAGE_IMPORT_DESCRIPTOR	GetFirstImportDesc(LPVOID	ImageBase)
{
	
	DWORD pImportOffset = (pOptionHeader->DataDirectory[1]).VirtualAddress ;
	
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) \
		ImageRvaToVa ( pNtHeader, ImageBase, pImportOffset, &pSectionHeader ) ; 
	if(!pImportDesc)
	{
		return	NULL;
	}
	return	pImportDesc;
}

void	ShowImportDescInfo(HWND hDlg)
{
	HWND	hList = GetDlgItem(hDlg,IDC_IMPORT_DESCRIPTOR);
	LVITEM	lvi;
	TCHAR	cBuff[10],
			szDllName[256];
	PIMAGE_IMPORT_DESCRIPTOR  pImportDesc = GetFirstImportDesc(lpMemory);
	DWORD dwErrorCode = GetLastError();
	
	
	
	for(int i=0;pImportDesc->FirstThunk;i++)
	{
		ZeroMemory(cBuff,sizeof(cBuff));
		ZeroMemory(&lvi,sizeof(LVITEM));
		memset(szDllName,0,sizeof(szDllName));
		lvi.mask = LVIF_TEXT;
		lvi.iItem = i;

		lvi.pszText = szDllName;
		lvi.iSubItem = 0;
		LPVOID pDllName = (PIMAGE_IMPORT_DESCRIPTOR)(ImageRvaToVa(pNtHeader,lpMemory,(DWORD)pImportDesc->Name,&pSectionHeader));
		wsprintf ( szDllName, "%s", (char*)pDllName ) ;
		ListView_InsertItem(hList,&lvi);

		lvi.pszText = cBuff;
		lvi.iSubItem =1;
		wsprintf(cBuff,"%08lX",pImportDesc->OriginalFirstThunk);
		SendDlgItemMessage ( hDlg, IDC_IMPORT_DESCRIPTOR, LVM_SETITEM, 0, (LPARAM)&lvi ) ;

	    lvi.pszText = cBuff;
		lvi.iSubItem =2;
		wsprintf(cBuff,"%08lX",pImportDesc->TimeDateStamp);
		SendDlgItemMessage ( hDlg, IDC_IMPORT_DESCRIPTOR, LVM_SETITEM, 0, (LPARAM)&lvi ) ;
		
		lvi.pszText = cBuff;
		lvi.iSubItem =3;
		wsprintf(cBuff,"%08lX",pImportDesc->ForwarderChain);
		SendDlgItemMessage ( hDlg, IDC_IMPORT_DESCRIPTOR, LVM_SETITEM, 0, (LPARAM)&lvi ) ;
		pImportDesc++ ;

		lvi.pszText = cBuff;
		lvi.iSubItem =4;
		wsprintf(cBuff,"%08lX",pImportDesc->Name);
		SendDlgItemMessage ( hDlg, IDC_IMPORT_DESCRIPTOR, LVM_SETITEM, 0, (LPARAM)&lvi ) ;

		lvi.pszText = cBuff;
		lvi.iSubItem =5;
		wsprintf(cBuff,"%08lX",pImportDesc->FirstThunk);
		SendDlgItemMessage ( hDlg, IDC_IMPORT_DESCRIPTOR, LVM_SETITEM, 0, (LPARAM)&lvi ) ;
	}

}

void ShowDllFunction( HWND hDlg, int index )
{
	HWND hList = GetDlgItem(hDlg,IDC_THUNK);
	ListView_SetExtendedListViewStyle(hList,LVS_EX_FULLROWSELECT);
    ListView_DeleteAllItems(hList);

	LVITEM	lvi;
	TCHAR	cBuff[10],
			szFunName[256];
	PIMAGE_IMPORT_DESCRIPTOR  pImportDesc = GetFirstImportDesc(lpMemory);
	DWORD dwErrorCode = GetLastError();

	PIMAGE_IMPORT_DESCRIPTOR pCurrentImportDesc =&pImportDesc[index];
	DWORD *INTEntry = (DWORD*)ImageRvaToVa ( pNtHeader, \
		lpMemory, (DWORD)pCurrentImportDesc->OriginalFirstThunk, &pSectionHeader ) ;
	
	DWORD *IATEntry = (DWORD*)ImageRvaToVa ( pNtHeader, \
		lpMemory, (DWORD)pCurrentImportDesc->FirstThunk, &pSectionHeader ) ;
	for(int i=0;((DWORD)(*INTEntry))||((DWORD)(*IATEntry));i++)
	{
		ZeroMemory(&lvi,sizeof(LVITEM));
		ZeroMemory(cBuff,sizeof(cBuff));
		ZeroMemory(szFunName,sizeof(szFunName));

		lvi.mask = LVIF_TEXT;
		lvi.iItem = i;

		lvi.pszText = cBuff;
		lvi.iSubItem = 0;
		wsprintf(cBuff,"%08lX",(DWORD)(*INTEntry));
		ListView_InsertItem(hList,&lvi);

		lvi.iSubItem = 1;
		wsprintf(cBuff,"%08lX",(DWORD)(*IATEntry));
		SendDlgItemMessage ( hDlg, IDC_THUNK, LVM_SETITEM, 0, (LPARAM)&lvi);
		

		if(HIWORD(*INTEntry)&0x8000)
		{
			wsprintf ( szFunName, "ord:%08lX", (DWORD)(LOWORD(*INTEntry)) ) ;
			strcpy ( cBuff, "--" ) ;
		}
		else
		{
			PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)ImageRvaToVa \
				(pNtHeader, lpMemory, (DWORD)(*INTEntry), &pSectionHeader ) ; 
			if ( pByName )
			{
				wsprintf ( cBuff, "%04lX", pByName->Hint ) ;
				wsprintf ( szFunName, "%s", (char*)pByName->Name ) ;
			}
		}
		lvi.pszText = cBuff;
		lvi.iSubItem = 2 ;
		SendDlgItemMessage (hDlg, IDC_THUNK, LVM_SETITEM, 0, (LPARAM)&lvi ) ;

		lvi.pszText = szFunName ;
		lvi.iSubItem = 3 ;
		SendDlgItemMessage ( hDlg, IDC_THUNK, LVM_SETITEM, 0, (LPARAM)&lvi ) ;

		INTEntry++;
		IATEntry++;
		


	}
	

}
/*-----------------------------
 初始化输入表列表
 *-------------------------------*/

BOOL WINAPI	InitImportDescriptor(HWND	hDlg)
{
	HWND	hList = GetDlgItem(hDlg,IDC_IMPORT_DESCRIPTOR);
	SendMessage(hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
					(LPARAM)LVS_EX_FULLROWSELECT	); 
	HWND	hList1 = GetDlgItem(hDlg,IDC_THUNK);
	SendMessage(hList1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
					(LPARAM)LVS_EX_FULLROWSELECT	);
		
	TCHAR	IID[][20] ={"DLL名称","OriginalFirstThunk","时间日期标志","ForwarderChain","Name of RVA","FirstThunk"};
	TCHAR	THUNK[][10] ={"ThunkRVA","Thunk值","Hint","API名称"};
	LVCOLUMN	lvc;
	ZeroMemory(&lvc,sizeof(LVCOLUMN));
	int iCol;
	lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
    lvc.fmt = LVCFMT_LEFT; 
    lvc.cx = 80; 
	
	for(iCol = 0;iCol<6;iCol++)
	{
		lvc.iSubItem = iCol;
		lvc.pszText = IID[iCol];
		if (ListView_InsertColumn(hList, iCol, &lvc) == -1) 
			return FALSE; 
	}
	for(iCol = 0;iCol<4;iCol++)
	{
		lvc.iSubItem = iCol;
		lvc.pszText =THUNK[iCol];
		if (ListView_InsertColumn(hList1, iCol, &lvc) == -1) 
			return FALSE; 
	}
	return	TRUE;
}
/*----------------------------------
	区块列表控件初始化
  *---------------------------------*/


BOOL WINAPI InitListViewColumns(HWND hDlg)
{ 
	HWND	hList = GetDlgItem(hDlg,IDC_SECTION_LIST);	
	SendMessage(hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
					(LPARAM)LVS_EX_FULLROWSELECT	);    //设置树形控件的扩展样式

	TCHAR	section_header[][8]={"Name","VOffset","Vsize","ROffset","RSize","Flags"};
       // temporary buffer 

    LVCOLUMN	lvc; 
	ZeroMemory(&lvc,sizeof(LVCOLUMN));

    int iCol; 
 
    // Initialize the LVCOLUMN structure. 
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
    lvc.fmt = LVCFMT_LEFT; 
    lvc.cx = 80; 
    
 
    // Add the columns. 
    for (iCol = 0; iCol < 6; iCol++) 
	{ 
        lvc.iSubItem = iCol; 
        lvc.pszText = section_header[iCol];
        if (ListView_InsertColumn(hList, iCol, &lvc) == -1) 
			return FALSE; 
    } 
	    return TRUE; 
} 
/*----------------------------
	显示区块信息
  *----------------------------*/
void ShowSectionTable(HWND hDlg,PIMAGE_FILE_HEADER	pFileHeader,PIMAGE_SECTION_HEADER	pSectionHeader)
{
	LVITEM	lvItem;
	ZeroMemory(&lvItem,sizeof(LVITEM));
	TCHAR			buf[16];

			for ( int i = 0; i < pFileHeader->NumberOfSections; i++ )
			{

				ZeroMemory( &lvItem, sizeof ( lvItem ) ) ;
				lvItem.mask		=	LVIF_TEXT ;
				lvItem.iItem	=	i ;

				ZeroMemory(buf,sizeof(buf));
				CopyMemory(buf, pSectionHeader->Name, 8 ) ;

						
				lvItem.pszText	=	buf ;
				SendDlgItemMessage ( hDlg, IDC_SECTION_LIST, LVM_INSERTITEM, 0, (LPARAM)&lvItem ) ;

				lvItem.pszText  = buf;
				wsprintf ( buf, "%08lX", pSectionHeader->VirtualAddress);
				lvItem.iSubItem = 1;
				SendDlgItemMessage ( hDlg,IDC_SECTION_LIST, LVM_SETITEM, 0, (LPARAM)&lvItem);
		
				wsprintf ( buf, "%08lX", pSectionHeader->Misc.VirtualSize);
				lvItem.iSubItem = 2;
				SendDlgItemMessage ( hDlg,IDC_SECTION_LIST, LVM_SETITEM, 0, (LPARAM)&lvItem);
	
				wsprintf ( buf, "%08lX", pSectionHeader->PointerToRawData);
				lvItem.iSubItem = 3;
				SendDlgItemMessage ( hDlg,IDC_SECTION_LIST, LVM_SETITEM, 0, (LPARAM)&lvItem);
			
				wsprintf ( buf, "%08lX", pSectionHeader->SizeOfRawData);
				lvItem.iSubItem = 4;
				SendDlgItemMessage ( hDlg,IDC_SECTION_LIST, LVM_SETITEM, 0, (LPARAM)&lvItem);
	
				wsprintf ( buf, "%08lX", pSectionHeader->Characteristics);
				lvItem.iSubItem = 5;
				SendDlgItemMessage ( hDlg,IDC_SECTION_LIST, LVM_SETITEM, 0, (LPARAM)&lvItem);

				pSectionHeader++ ;
			}

}


 //判断是否是PE文件结构
BOOL	IsPeFile(LPVOID	ImageBase)  
{
	PIMAGE_DOS_HEADER	pDosHeader = NULL;
	PIMAGE_NT_HEADERS	pNtHeader  = NULL;
	
	if(!ImageBase)
		return FALSE;
	pDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
	if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		return FALSE;
	pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew);
	if(pNtHeader->Signature != IMAGE_NT_SIGNATURE )
		return	FALSE;
	return		TRUE;
}

//FileHeader 内容的读取

PIMAGE_NT_HEADERS	GetNtHeader(LPVOID	ImageBase) //获取NT结构指针
{
	PIMAGE_DOS_HEADER	pDosHeader = NULL;
	PIMAGE_NT_HEADERS	pNtHeader  = NULL;

	if(!IsPeFile(ImageBase))
		return	NULL;
	pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
	pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew);
	return		pNtHeader;
}

PIMAGE_FILE_HEADER	WINAPI	GetFileHeader(LPVOID	Imagebase)
{
	PIMAGE_FILE_HEADER	pFileHeader;
	PIMAGE_NT_HEADERS	pNtHeader = NULL;
	pNtHeader = GetNtHeader(Imagebase);
	if(!pNtHeader)
		return	NULL;
	pFileHeader = & pNtHeader->FileHeader; 
	return	pFileHeader;
}

PIMAGE_OPTIONAL_HEADER	GetOptionalHeader(LPVOID	ImageBase)
{
	PIMAGE_OPTIONAL_HEADER	pOptionHeader = NULL;
	PIMAGE_NT_HEADERS	pNtHeader = NULL;
	pNtHeader = GetNtHeader(ImageBase);
	if(!pNtHeader)
		return	NULL;
	pOptionHeader = & pNtHeader->OptionalHeader;
	return	pOptionHeader;
}


PIMAGE_SECTION_HEADER	GetFirstSectionHeader(PIMAGE_NT_HEADERS	pNtHeader)
{
	PIMAGE_SECTION_HEADER	pSectionHeader;
	pSectionHeader =IMAGE_FIRST_SECTION(pNtHeader);
	return	pSectionHeader;
}

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (5)
雪    币: 10214
活跃值: (2240)
能力值: ( LV5,RANK:71 )
在线值:
发帖
回帖
粉丝
joker陈 2008-12-29 15:16
2
0
记得n年前,我还不懂事的时候,研究游戏帐户找回工具,那时常被游戏的基址搞得。。。气血不调、大便干燥、日不能食、夜不得寐。。。那时就幻想要是我能读取寄存器就好了。当时不知道有Debug API这个东西。早上好好看了点资料,自己摸索了下,有点心得,与同学们分享下。网上有关DEBUG API的资料不是很多有个英文版的和一个翻译版的。同学们可以搜索下(key :win32 debug api),看看更详细的介绍。
debuggee被测试程序(Test.exe)很简单,明码比较的代码如下:
procedure Ttest.Button1Click(Sender: TObject);
begin
if Edit1.Text='ade123' then
MessageBox(0,'密码正确','恭喜',48)
else
MessageBox(0,'密码错误','提示',48)
end;
用OD载入得到关键算法如下:(怎么找关键算法?我也不是太懂,我也是菜鸟,凭经验+运气找到的。呵呵)
004501C3    E8 54F2FDFF     CALL message.0042F41C
004501C8    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
004501CB    BA 28024500     MOV EDX,message.00450228                 ; ASCII "ade123"
004501D0    E8 4740FBFF     CALL message.0040421C
004501D5    75 15           JNZ SHORT message.004501EC
004501D7    6A 30           PUSH 30
004501D9    68 30024500     PUSH message.00450230
004501DE    68 38024500     PUSH message.00450238
004501E3    6A 00           PUSH 0
004501E5    E8 AE62FBFF     CALL <JMP.&user32.MessageBoxA>
004501EA    EB 13           JMP SHORT message.004501FF
004501EC    6A 30           PUSH 30
004501EE    68 44024500     PUSH message.00450244
004501F3    68 4C024500     PUSH message.0045024C
004501F8    6A 00           PUSH 0
004501FA    E8 9962FBFF     CALL <JMP.&user32.MessageBoxA>
004501FF    33C0            XOR EAX,EAX
注意红色那行,将密码所在地址传递给EDX,继续一个CALL进行比较。而如果,我们在004501D0这里将程序断点断下来,然后我们去看看EDX的值,这个值就是存放的密码的地址啊。奸笑中,哈哈。
实现代码如下:
begin
wHandle:=FindWindow('TTest',0); //Tdebugee
//Sleep(5000);
//p.X:=10;
//p.Y:=10;
//wHandle:=WindowFromPoint(p);
if wHandle>0 then ade_ThreadId:=GetWindowThreadProcessId(wHandle,@ade_ProcessId);
if ade_ThreadId>0 then ade_Process:=OpenProcess(PROCESS_ALL_ACCESS,False,ade_ProcessId);
ade_Thread:=OpenThread(ade_ThreadId,False);
if DebugActiveProcess(ade_ProcessId)then
begin
    //============DebugStart===============
    while True do
    begin
      if WaitForDebugEvent(DebugEv,INFINITE) then
       begin
         //dwContinuesStatus:=DBG_EXCEPTION_NOT_HANDLED;
         case DebugEv.dwDebugEventCode of
         EXCEPTION_DEBUG_EVENT:       //意外处理,断点等时触发。
           begin
           if (DebugEv.Exception.ExceptionRecord.ExceptionCode<>EXCEPTION_BREAKPOINT) then
               rc:=False //目标程序自己异常,让它自己处理
           else
             begin        //处理断点
               if DebugEv.Exception.ExceptionRecord.ExceptionAddress=Pointer(ade_address) then
               begin
               SuspendThread(ThreadHandle);
               rc:=True;
               Context.ContextFlags:=CONTEXT_FULL;
               GetThreadContext(ThreadHandle,Context);
               //ReadProcessMemory(ade_Process,Pointer(Context.Edx),@adr,4,num);
               //MessageBox(0,'tishi',PChar(IntToStr(Context.Edx)),48);
               EAX:=Trim(GetMem(ade_Process,Context.Edx,20));
               MessageBox(0,'断点事件产生',PChar(eax),48);
               ResumeThread(ThreadHandle);
               end;
             end;
           //Break;
           end;
         CREATE_PROCESS_DEBUG_EVENT: //刚创建调试时触发
          begin
          ThreadHandle:=DebugEv.CreateProcessInfo.hThread;//线程
          ade_buf[0]:=$cc;
          ade_buf[1]:=$90;
          SuspendThread(ade_Thread); //挂起
          WriteProcessMemory(ade_Process,Pointer(ade_Address),@ade_buf,2,WriteMemory); //向messagebox写入断点
          ResumeThread(ade_Thread); //恢复
          MessageBox(0,'Start Debug,写入完毕','Title',48);
          //Break;
          end;
         EXIT_PROCESS_DEBUG_EVENT:    //退出调试时触发
          begin
          MessageBox(0,'End Debug','Title',48);
          //Break;
          end;   
          end;//end case
         if rc then
         ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId,DBG_CONTINUE)//本程序处理
         else
         ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); //目标程序自己处理
       end;
    end;  
end
else
MessageBox(0,'调试目标进程出错','Title',48);
end;
运行效果如下:

代码没有进行修改,尽管能正确截取,但是破坏了原程序的运行,需要把CC改回,并将EIP减一。


请高手帮忙把中间delphi的代码改成c语言。
雪    币: 1137
活跃值: (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
dreamzgj 2 2008-12-29 16:35
3
0
LZ好文章

期待LZ更精彩的部分。
雪    币: 201
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jmir 2009-5-24 15:05
4
0
正在学PE结构,很有帮助,
友情PS:3楼好水,,,,,,,,,,,,,
雪    币: 13
活跃值: (49)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ywqjwq 2009-5-28 14:15
5
0
正在学PE结构,很有帮助~还是这里高手多啊
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
望穿秋水 2010-4-3 15:34
6
0
先回复再看!谢谢
游客
登录 | 注册 方可回帖
返回