彙編解析pe文件

主要是爲了練習一下彙編語言編成和pe文件結構。

#include<stdio.h>
#include<windows.h>
//winnt.h
char   *OutputDebug="OutputDebugStringA\0";//length=0x12
DWORD   KernelBase=0x7c800000;//方便試驗,直接用工具讀的一個值

WORD   dMZ=0;
WORD   dNumberOfSections=0;
DWORD  e_lfanew=0;
DWORD  dSignature=0;
WORD   wSizeOfOptionalHeader=0;
DWORD  DataDirExport=0;
DWORD  SectionVA=0,SectionVS=0,SectionHeaderPTRD;
DWORD  NumberOfNames=0;
DWORD  FuncIndex=0;
DWORD  FuncAddr=0;

DWORD sell()
{
	_asm
	{
		mov    eax,KernelBase
		mov    bx,word ptr [eax]
		mov    dMZ,bx
		cmp    bx,0x5a4d;MZ標示
		jnz    retu
		mov    ebx,dword ptr [eax+0x3c];獲取PE頭偏移
		mov    e_lfanew,ebx
		test   ebx,ebx
		jz     retu
		mov    ecx,dword ptr [eax+ebx]
		mov    dSignature,ecx
		cmp    ecx,0x4550;PE標示
		jnz    retu
		mov    cx,word ptr [eax+ebx+4+16]
		mov    wSizeOfOptionalHeader,cx
        ;直接讀的結構體裏面的偏移,這個用winDbg看可能比較直觀一點 
		mov    edx,dword ptr [eax+ebx+0x78];nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EPORT].VirtualAddress
		mov    DataDirExport,edx

		mov     dx,word ptr [eax+ebx+4+2];ImageNtHeaders.ImageFileHeader.NumberOfSection
		mov     dNumberOfSections,dx
find_sec:
		mov    ecx,dword ptr [eax+ebx+0xf8+0xc];SectionHeader.VirtualAddress
		mov    SectionVA,ecx
		cmp    dword ptr [eax+ebx+0x78],ecx
		jl     next_sec
		add    ecx,dword ptr [eax+ebx+0xf8+0x8];SectionHeader.Misc.VirtualSize
        cmp    dword ptr [eax+ebx+0x78],ecx
		jl     find
next_sec:
		dec    dx
		jnz    find_sec
		jmp    retu
find:
		mov     edx,dword ptr [eax+ebx+0x78];因爲模塊已經加載到內存,這裏可以直接用這個偏移加模塊基址,和從本地文件讀取有點差別
		mov     ecx,dword ptr [eax+edx+0x18];ImageExportDirectory.NumberOfNames
		mov     NumberOfNames,ecx

		mov     edx,dword ptr [eax+edx+0x20];ImageExportDirectory.AddressOfNames;存函數名稱字符串的偏移,這裏相當於一個數組
		push    ebx
		push    ecx
		add     edx,eax;加上基址
		mov     ebx,OutputDebug;要找的函數名稱
		mov     esi,ebx
		xor     ebx,ebx
		;int     3
find_func_name:
		mov     ecx,18
		push    esi
		mov     edi,dword ptr [edx+4*ebx];從字符串數組中取值比較
		add     edi,eax
		repe    cmps   ;字符串循環比較,ecx爲0或不等,結束比較
		test    ecx,ecx
		jz      get_func
		pop     esi
		inc     ebx
		pop     ecx
		cmp     ebx,ecx
		push    ecx
		jl      find_func_name
		jmp     search_done
get_func:
		mov     FuncIndex,ebx;保存函數標號
		mov     edi,ebx
		pop     esi
		pop     ecx
		pop     ebx
		
		mov     edx,dword ptr [eax+ebx+0x78];
		mov     edx,dword ptr [eax+edx+0x1c];ImageExportDirectory.AddressofFunctions
		add     edx,eax
		mov     ecx,dword ptr [edx+edi*4];從函數地址數組中取值(是偏移)
		mov     FuncAddr,ecx
		add     ecx,eax
		mov     edx,OutputDebug
		mov     esi,edx
		push    esi
		call    ecx;call OutputDebguStringA,可以用DbgView看到字符串'OutputDebugStringA'
		jmp     retu
search_done:
		pop    ecx
		pop    ebx
retu:
		xor    eax,eax
		;ret
	}
}

int main()
{
	sell();
	printf("dMZ:0x%x\n",dMZ);
	printf("e_lfanew:0x%x\n",e_lfanew);
	printf("dSignature:0x%x\n",dSignature);
	printf("dNumberOfSections:0x%x\n",dNumberOfSections);
	printf("wSizeOfOptionalHeader:0x%x\n",wSizeOfOptionalHeader);
	printf("DataDirExport:0x%x\n",DataDirExport);
	printf("SectionVA:0x%x\n",SectionVA);
	printf("SectionHeaderPTRD:0x%x\n",SectionHeaderPTRD);
	printf("NumberOfNames;0x%x\n",NumberOfNames);
	printf("FuncIndex:0x%x,..%d\n",FuncIndex,FuncIndex);
	printf("FuncAddr:0x%x\n",FuncAddr);
	getchar();
	return 0;
}

DbgView的截圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章