ITPub博客

首页 > 大数据 > Hadoop > (加密解密技术内幕)PE教程5: Section Table

(加密解密技术内幕)PE教程5: Section Table

Hadoop 作者:kkobbe 时间:2013-11-26 12:54:00 0 删除 编辑

理论:

到本课为止,我们已经学了许多关于DOS
header和PE header的知识。接下来就该轮到section
table(节表)了。节表其实就是紧挨着PE header的一结构数组。该数组成员的数目由file header (IMAGE_FILE_HEADER)结构中NumberOfSections域的域值来决定。节表结构又命名为IMAGE_SECTION_HEADER。

IMAGE_SIZEOF_SHORT_NAME equ 8

IMAGE_SECTION_HEADER STRUCT   Name1
db IMAGE_SIZEOF_SHORT_NAME dup(?)   union Misc      PhysicalAddress dd
?      VirtualSize dd ?   ends   VirtualAddress dd ?   SizeOfRawData dd ?   PointerToRawData dd ?   PointerToRelocations dd ?   PointerToLinenumbers dd ?哦   NumberOfRelocations dw ?   NumberOfLinenumbers
dw ?   Characteristics dd ?IMAGE_SECTION_HEADER ENDS

同样,不是所有成员都是很有用的,我们只关心那些真正重要的。

Field

Meanings

Name1    事实上本域的名称是"name",只是"name"已被MASM用作关键字,所以我们只能用"Name1"代替。这儿的节名长不超过8字节。记住节名仅仅是个标记而已,我们选择任何名字甚至空着也行,注意这里不用null结束。命名不是一个ASCIIZ字符串,所以不用null结尾。    

VirtualAddress    本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h,而PE文件装在地址400000h处,那么本节就被载到401000h。    

SizeOfRawData    经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。(译者注:假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,则本域值为0x400,表示本节是0x400字节长)。    

PointerToRawData    这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。    

Characteristics    包含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。    

现在我们已知晓IMAGE_SECTION_HEADER结构,再来模拟一下PE装载器的工作吧:

读取IMAGE_FILE_HEADER的NumberOfSections域,知道文件的节数目。

SizeOfHeaders域值作为节表的文件偏移量,并以此定位节表。

遍历整个结构数组检查各成员值。

对于每个结构,我们读取PointerToRawData域值并定位到该文件偏移量。然后再读取SizeOfRawData域值来决定映射内存的字节数。将VirtualAddress域值加上ImageBase域值等于节起始的虚拟地址。然后就准备把节映射进内存,并根据Characteristics域值设置属性。

遍历整个数组,直至所有节都已处理完毕。

注意我们并没有使用节名:这其实并不重要。

示例:

本例程打开一PE文件遍历其节表,并在列表框控件显示各节的信息。

.386.model flat,stdcalloption casemap:noneinclude masm32includewindows.incinclude masm32includekernel32.incinclude masm32includecomdlg32.incinclude masm32includeuser32.incinclude masm32includecomctl32.incincludelib masm32libcomctl32.libincludelib masm32libuser32.libincludelib masm32libkernel32.libincludelib masm32libcomdlg32.libIDD_SECTIONTABLE equ 104IDC_SECTIONLIST equ 1001SEH struct

PrevLink dd ? ; the address of the previous seh
structureCurrentHandler dd ? ; the address of the new exception handlerSafeOffset dd ? ; The offset where it's safe to continue executionPrevEsp dd ? ; the old value in espPrevEbp dd ? ; The old value in ebpSEH ends.dataAppName db "PE tutorial no.5",0ofn
OPENFILENAME <>FilterString db "Executable Files (*.exe,
*.dll)",0,"*.exe;*.dll",0             db "All Files",0,"*.*",0,0FileOpenError db "Cannot open the file for reading",0FileOpenMappingError db "Cannot open the file for memory mapping",0FileMappingError db "Cannot map the file into memory",0FileInValidPE db
"This file is not a valid PE",0template db "%08lx",0SectionName db
"Section",0VirtualSize db "V.Size",0VirtualAddress db "V.Address",0SizeOfRawData db "Raw Size",0RawOffset db "Raw Offset",0Characteristics db "Characteristics",0.data?hInstance dd ?buffer db 512 dup(?)hFile dd ?hMapping dd ?pMapping dd ?ValidPE dd ?NumberOfSections dd ?.codestart procLOCAL seh:SEH   invoke GetModuleHandle,NULL   mov hInstance,eax   mov ofn.lStructSize,SIZEOF ofn   mov ofn.lpstrFilter, OFFSET
FilterString   mov ofn.lpstrFile, OFFSET buffer   mov ofn.nMaxFile,512   mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or
OFN_EXPLORER or OFN_HIDEREADONLY   invoke GetOpenFileName, ADDR ofn  
.if eax==TRUE      invoke CreateFile, addr buffer, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL      .if
eax!=INVALID_HANDLE_VALUE         mov hFile, eax         invoke
CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0         .if eax!=NULL            mov hMapping, eax            invoke
MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0            .if eax!=NULL               mov pMapping,eax               assume fs:nothing               push fs:[0]               pop seh.PrevLink               mov seh.CurrentHandler,offset SEHHandler              
mov seh.SafeOffset,offset FinalExit               lea eax,seh               mov fs:[0], eax               mov seh.PrevEsp,esp               mov seh.PrevEbp,ebp               mov edi, pMapping               assume edi:ptr IMAGE_DOS_HEADER               .if
[edi].e_magic==IMAGE_DOS_SIGNATURE                  add edi, [edi].e_lfanew                  assume edi:ptr IMAGE_NT_HEADERS                  .if
[edi].Signature==IMAGE_NT_SIGNATURE                     mov ValidPE, TRUE                  .else                     mov ValidPE, FALSE                  .endif               .else                  mov
ValidPE,FALSE               .endifFinalExit:               push
seh.PrevLink               pop fs:[0]               .if ValidPE==TRUE                  call ShowSectionInfo               .else                  invoke MessageBox, 0, addr FileInValidPE, addr AppName,
MB_OK+MB_ICONINFORMATION               .endif               invoke
UnmapViewOfFile, pMapping           .else               invoke
MessageBox, 0, addr FileMappingError, addr AppName, MB_OK+MB_ICONERROR          .endif          invoke CloseHandle,hMapping       .else          invoke MessageBox, 0, addr FileOpenMappingError, addr AppName,
MB_OK+MB_ICONERROR       .endif       invoke CloseHandle, hFile    .else       invoke MessageBox, 0, addr FileOpenError, addr AppName,
MB_OK+MB_ICONERROR    .endif  .endif  invoke ExitProcess, 0  invoke InitCommonControlsstart endpSEHHandler proc uses edx
pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD   mov edx,pFrame   assume edx:ptr SEH   mov eax,pContext   assume eax:ptr CONTEXT   push [edx].SafeOffset   pop [eax].regEip   push [edx].PrevEsp   pop [eax].regEsp   push [edx].PrevEbp   pop [eax].regEbp  
mov ValidPE, FALSE   mov eax,ExceptionContinueExecution   retSEHHandler endpDlgProc proc uses edi esi hDlg:DWORD, uMsg:DWORD,
wParam:DWORD, lParam:DWORD   LOCAL lvc:LV_COLUMN   LOCAL lvi:LV_ITEM   .if uMsg==WM_INITDIALOG      mov esi, lParam      mov
lvc.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM      mov
lvc.fmt,LVCFMT_LEFT      mov lvc.lx,80      mov lvc.iSubItem,0      mov lvc.pszText,offset SectionName      invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,0,addr lvc inc
lvc.iSubItem      mov lvc.fmt,LVCFMT_RIGHT      mov lvc.pszText,offset
VirtualSize      invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,1,addr lvc     
inc lvc.iSubItem      mov lvc.pszText,offset VirtualAddress     
invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,2,addr lvc      inc lvc.iSubItem      mov lvc.pszText,offset SizeOfRawData      invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,3,addr
lvc      inc lvc.iSubItem      mov lvc.pszText,offset RawOffset      invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,4,addr
lvc      inc lvc.iSubItem      mov lvc.pszText,offset Characteristics      invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTCOLUMN,5,addr
lvc      mov ax, NumberOfSections      movzx eax,ax      mov
edi,eax            mov lvi.imask,LVIF_TEXT      mov lvi.iItem,0      assume esi:ptr IMAGE_SECTION_HEADER      .while edi>0         mov lvi.iSubItem,0         invoke RtlZeroMemory,addr buffer,9         invoke lstrcpyn,addr buffer,addr [esi].Name1,8         lea
eax,buffer         mov lvi.pszText,eax         invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTITEM,0,addr lvi        
invoke wsprintf,addr buffer,addr template,[esi].Misc.VirtualSize        
lea eax,buffer         mov lvi.pszText,eax         inc lvi.iSubItem         invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_SETITEM,0,addr
lvi         invoke wsprintf,addr buffer,addr template,[esi].VirtualAddress         lea eax,buffer         mov lvi.pszText,eax         inc
lvi.iSubItem         invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_SETITEM,0,addr lvi        
invoke wsprintf,addr buffer,addr template,[esi].SizeOfRawData         lea
eax,buffer         mov lvi.pszText,eax         inc lvi.iSubItem         invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_SETITEM,0,addr
lvi         invoke wsprintf,addr buffer,addr
template,[esi].PointerToRawData         lea eax,buffer         mov
lvi.pszText,eax         inc lvi.iSubItem         invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_SETITEM,0,addr lvi        
invoke wsprintf,addr buffer,addr template,[esi].Characteristics         lea
eax,buffer         mov lvi.pszText,eax         inc lvi.iSubItem         invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_SETITEM,0,addr
lvi         inc lvi.iItem         dec edi         add esi, sizeof
IMAGE_SECTION_HEADER      .endw   .elseif      uMsg==WM_CLOSE         invoke EndDialog,hDlg,NULL   .else      mov eax,FALSE      ret   .endif   mov eax,TRUE   retDlgProc endpShowSectionInfo proc uses edi   mov edi, pMapping   assume
edi:ptr IMAGE_DOS_HEADER   add edi, [edi].e_lfanew   assume edi:ptr
IMAGE_NT_HEADERS   mov ax,[edi].FileHeader.NumberOfSections   movzx
eax,ax   mov NumberOfSections,eax   add edi,sizeof IMAGE_NT_HEADERS   invoke DialogBoxParam, hInstance, IDD_SECTIONTABLE,NULL, addr DlgProc,
edi   retShowSectionInfo endpend start

分析:

本例重用了PE教程2的代码,校验PE文件的有效性后,继续调用函数ShowSectionInfo显示各节信息。

ShowSectionInfo proc uses edi   mov edi, pMapping   assume edi:ptr IMAGE_DOS_HEADER   add edi, [edi].e_lfanew  
assume edi:ptr IMAGE_NT_HEADERS

我们将edi用作指向PE文件数据的指针。首先,将指向DOS
header地址的pMapping赋给edi,再加上e_lfanew域值等于PE header的地址。

   mov ax,[edi].FileHeader.NumberOfSections   mov
NumberOfSections,ax

因为我们要遍历节表,所以必须先获取文件的节数目。这就得靠file header里的NumberOfSections域了,切记这是个word域。

   add edi,sizeof IMAGE_NT_HEADERS

现在edi正指向PE header的起始地址,加上PE header结构大小后恰好指向节表了。

   invoke DialogBoxParam, hInstance,
IDD_SECTIONTABLE,NULL, addr DlgProc, edi

调用DialogBoxParam显示列表对话框,注意我们已将节表地址作为最后一个参数传递过去了,该值可从WM_INITDIALOG消息的lParam参数中提取。

在对话框过程里我们响应WM_INITDIALOG消息,将lParam值(节表地址)存入esi,节数目赋给edi并设置列表控件。万事俱备后,进入循环将各节信息插入到列表控件中,这部分相当简单。

      .while edi>0         mov lvi.iSubItem,0

字符串置入第一列。

         invoke RtlZeroMemory,addr buffer,9         invoke lstrcpyn,addr buffer,addr [esi].Name1,8         lea
eax,buffer         mov lvi.pszText,eax

要显示节名,当然要将其转换为ASCIIZ字符串先。

         invoke
SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTITEM,0,addr lvi

然后显示第一列。继续我们伟大的工程,显示完本节中最后一个欲呈现的值后,立马下一个结构。

         dec edi         add esi, sizeof
IMAGE_SECTION_HEADER      .endw

每处理完一节就递减edi,然后将esi加上IMAGE_SECTION_HEADER结构大小,使其指向下一个IMAGE_SECTION_HEADER结构。

遍历节表的步骤:

PE文件有效性校验。

定位到PE header的起始地址。

从file header的NumberOfSections域获取节数。

通过两种方法定位节表:ImageBase+SizeOfHeaders或者PE header的起始地址+ PE header结构大小。(节表紧随PE header)。如果不是使用文件映射的方法,可以用SetFilePointer直接将文件指针定位到节表。节表的文件偏移量存放在SizeOfHeaders域里。(SizeOfHeaders是IMAGE_OPTIONAL_HEADER的结构成员)

处理每个IMAGE_SECTION_HEADER结构。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23227356/viewspace-1111956/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2010-01-22