Section Table(节表)
理论 :
到本课为止,我们已经学了许多关于 DOS header 和 PE header 的知识。接下来就该轮到 section table (节表)了。节表其实就是紧挨着 PE header 的一结构数组。该数组成员的数目由 file header ( IMAGE_FILE_HEADER ) 结构中 NumberOfSections 域的域值来决定。节表结构又命名为 IMAGE_SECTION_HEADER 。
同样,不是所有成员都是很有用的,我们只关心那些真正重要的。
现在我们已知晓 IMAGE_SECTION_HEADER 结构,再来模拟一下 PE 装载器的工作吧 :
读取 IMAGE_FILE_HEADER 的 NumberOfSections 域,知道文件的节数目。 SizeOfHeaders 域值作为节表的文件偏移量,并以此定位节表。 遍历整个结构数组检查各成员值。 对于每个结构,我们读取 PointerToRawData 域值并定位到该文件偏移量。然后再读取 SizeOfRawData 域值来决定映射内存的字节数。将 VirtualAddress 域值加上 ImageBase 域值等于节起始的虚拟地址。然后就准备把节映射进内存,并根据 Characteristics 域值设置属性。 遍历整个数组,直至所有节都已处理完毕。
注意我们并没有使用节名 : 这其实并不重要。
示例 :
本例程打开一 PE 文件遍历其节表,并在列表框控件显示各节的信息。
本例重用了 PE 教程 2 的代码,校验 PE 文件的有效性后,继续调用函数 ShowSectionInfo 显示各节信息。
我们将 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
字符串置入第一列。
要显示节名,当然要将其转换为 ASCIIZ 字符串先。
invoke SendDlgItemMessage,hDlg,IDC_SECTIONLIST,LVM_INSERTITEM,0,addr lvi
然后显示第一列。
继续我们伟大的工程,显示完本节中最后一个欲呈现的值后,立马下一个结构。
每处理完一节就递减 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 结构。
理论 :
到本课为止,我们已经学了许多关于 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
同样,不是所有成员都是很有用的,我们只关心那些真正重要的。
现在我们已知晓 IMAGE_SECTION_HEADER 结构,再来模拟一下 PE 装载器的工作吧 :
读取 IMAGE_FILE_HEADER 的 NumberOfSections 域,知道文件的节数目。 SizeOfHeaders 域值作为节表的文件偏移量,并以此定位节表。 遍历整个结构数组检查各成员值。 对于每个结构,我们读取 PointerToRawData 域值并定位到该文件偏移量。然后再读取 SizeOfRawData 域值来决定映射内存的字节数。将 VirtualAddress 域值加上 ImageBase 域值等于节起始的虚拟地址。然后就准备把节映射进内存,并根据 Characteristics 域值设置属性。 遍历整个数组,直至所有节都已处理完毕。
注意我们并没有使用节名 : 这其实并不重要。
示例 :
本例程打开一 PE 文件遍历其节表,并在列表框控件显示各节的信息。
.386 .model flat,stdcall option casemap:none include masm32includewindows.inc include masm32includekernel32.inc include masm32includecomdlg32.inc include masm32includeuser32.inc include masm32includecomctl32.inc includelib masm32libcomctl32.lib includelib masm32libuser32.lib includelib masm32libkernel32.lib includelib masm32libcomdlg32.lib IDD_SECTIONTABLE equ 104 IDC_SECTIONLIST equ 1001 SEH struct PrevLink dd ? ; the address of the previous seh structure CurrentHandler dd ? ; the address of the new exception handler SafeOffset dd ? ; The offset where it's safe to continue execution PrevEsp dd ? ; the old value in esp PrevEbp dd ? ; The old value in ebp SEH ends .data AppName db "PE tutorial no.5",0 ofn OPENFILENAME <> FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0 db "All Files",0,"*.*",0,0 FileOpenError db "Cannot open the file for reading",0 FileOpenMappingError db "Cannot open the file for memory mapping",0 FileMappingError db "Cannot map the file into memory",0 FileInValidPE db "This file is not a valid PE",0 template db "%08lx",0 SectionName db "Section",0 VirtualSize db "V.Size",0 VirtualAddress db "V.Address",0 SizeOfRawData db "Raw Size",0 RawOffset db "Raw Offset",0 Characteristics db "Characteristics",0 .data? hInstance dd ? buffer db 512 dup(?) hFile dd ? hMapping dd ? pMapping dd ? ValidPE dd ? NumberOfSections dd ? .code start proc LOCAL 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 .endif FinalExit: 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 InitCommonControls start endp SEHHandler 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 ret SEHHandler endp DlgProc 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 ret DlgProc endp ShowSectionInfo 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 ret ShowSectionInfo endp end 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
字符串置入第一列。
nvoke 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 结构。
发表评论
-
压缩与脱壳-PE文件格式 七
2009-04-13 11:44 695Export Table(引出表) 上一课我们已经学习了 ... -
压缩与脱壳-PE文件格式 六 续
2009-04-13 11:39 1078assume edi:ptr IMAGE_IMPORT_D ... -
压缩与脱壳-PE文件格式 六 续一
2009-04-13 11:33 977示例 : 本例程打开一 PE 文件,将所有引入函数名读入一 ... -
压缩与脱壳-PE文件格式 六
2009-04-13 11:29 898Import Table (引入表) 本课我们将学习引入表。 ... -
压缩与脱壳-PE文件格式 四
2009-04-13 11:05 1081Optional Header 我们已经学习了关于 DOS ... -
压缩与脱壳-PE文件格式 三
2009-04-13 11:03 914File Header (文件头) ... -
压缩与脱壳-PE文件格式 二
2009-04-13 10:55 978检验PE文件的有效性 理 ... -
压缩与脱壳-PE文件格式 一
2009-04-13 10:48 1233PE 文件格式一览 PE 的 ... -
脱壳基础知识入门之认识壳
2009-04-13 10:35 10801.什么是壳 在一些计算 ...
相关推荐
### PE文件中脱壳技术的研究 #### 摘要与背景 随着信息技术的快速发展,软件保护成为了一个重要的议题。为了防止软件被非法复制或者逆向工程,开发人员常常采用一种称为“加壳”的技术来保护自己的软件产品。然而...
都会使计算机产生安全隐患或者使软件的核心技术被窃取,所以保护PE文件不被修改是一件很重要的工作,当前通常采用加壳的方法对PE文件进行保护,这其中UPX是具有代表性的压缩类外壳。 本文首先对PE文件格式进行了全面...
UPX是一个着名的压缩壳,主要功能是压缩PE文件(比如exe,dll等文件),有时候也可能被病毒用于免杀。壳upx是一种保护程序。 ........................ UPX是大家熟悉的EXE/Dll资源压缩工具,也称作可执行文件压缩...
PE文件格式是Windows操作系统中用于执行程序的标准格式,包括可执行文件(.exe)、动态链接库(.dll)等。PE脱壳工具能够识别并处理这些文件中的各种壳技术,例如UPX、ASPack、PECompact等。这些壳通常用于压缩程序...
UPX(UPX UnPacker eXtended)是一款广泛使用的可执行文件压缩工具,它能够将PE(Portable Executable,Windows平台上的可执行文件格式)文件进行压缩,从而减小程序的体积,提高分发效率。然而,这也为逆向工程和...
在计算机安全领域,PECompact是一款知名的可执行文件打包和压缩工具,它能够将Windows下的PE(Portable Executable)格式文件进行压缩,从而减小文件体积,提高分发效率。然而,这样的压缩过程也使得一些恶意软件...
总结以上内容,脱壳是逆向工程的重要组成部分,需要掌握PE文件格式、SEH机制、调试工具的使用,以及对各种加密算法和保护技术的理解。只有对这些基础知识和高级技术有了充分的认识,才能在软件安全和逆向工程的道路...
5. **生成脱壳文件**:最后,经过以上步骤后,Aspack stripper将生成一个未经ASPack压缩的新版本文件,供用户进一步分析。 值得注意的是,Aspack stripper的使用需要一定的专业知识,因为不恰当的操作可能导致文件...
2. **脱壳机制**:脱壳工具的核心在于正确地解压UPX壳并恢复原始的未压缩PE文件。源码可能会包含解压算法,根据UPX的压缩格式进行还原。 3. **内存操作**:由于程序可能已经在内存中运行,脱壳工具可能需要在内存中...
对于想要深入理解脱壳技术的学习者来说,熟悉PE文件格式至关重要。 **PE文件格式简介** - **定义**:PE格式由微软开发,用于定义Windows平台上可执行文件(如.EXE、.DLL等)的结构。 - **关键特性**:PE文件包含了...
- **静态与动态分析的兼容性**:构建一个可以在静态分析时重建有效PE文件,并在动态分析时执行的PE文件。 - **防止恶意软件检测**:确保脱壳过程不会被恶意软件检测到,避免分析过程中的干扰。 - **兼容性问题**:...
这个过程涉及到对PE(Portable Executable)文件格式的理解,包括节区、导入表、导出表等关键结构。脱壳机通过识别和解析ASPack的特定标志和模式来实现这一目标。 在安全社区中,ASPack常被视为一种双刃剑。一方面...
ASPACK是一款著名的软件压缩和加壳工具,由Andrey Breslav开发,它能将可执行文件进行压缩,减小其体积,同时增加反调试和反静态分析的特性,使得程序更加难以逆向工程分析。ASPACK 2.1和2.2是该工具的两个较早版本...
你可以用它来压缩或解压缩PE(Windows)、ELF(Linux)或DOS格式的可执行文件。例如,将一个.exe文件压缩,可以使用以下命令: ``` upx -q your_program.exe ``` 如果想要脱壳,只需添加`-d`参数: ``` upx -qd your...
有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET反编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和...
这个工具的工作原理,它的壳特征和编译器特征保存在HackFans.txt里面,能识别出来的壳,基本上都有对应的脱壳函数,用壳特征脱壳,可以脱壳,对于一些不好特殊的壳你可以用OEP侦测来脱壳,这要依赖编译器特征,你也可以自己...
UPX(Ultimate Packer for eXecutables)是一款著名的开源加壳工具,它能够对可执行文件(如Windows下的PE文件)进行压缩和加密,以减小文件大小、提高加载速度,同时也能提供一定的保护作用,防止恶意逆向分析。...
PE文件结构包括头、节区和各种数据目录,PEID能够深入解析这些部分,帮助用户确定程序是否被加壳以及加的是哪种类型的壳。 在提供的压缩包文件列表中,我们有两个文件: 1. `PEiD_095_20060510_WestKing_HA.exe`:...