您没有来错地!为了更好的发展,黑基网已于9月19日正式更名为【安基网】,域名更换为www.safebase.cn,请卸载旧的APP并安装新的APP,给您带来不便,敬请理解!谢谢

黑基Web安全攻防班
安基网 首页 IT技术 安全攻防 查看内容

PE结构、SEH相关知识掌握

2009-6-2 11:18| 投稿: security

摘要: 1.2 4.PE结构、SEH相关知识掌握         今天这节课程中,我们来讲解一下部分PE结构,以及SEH[Structu...
1.2 4.PE结构、SEH相关知识掌握         今天这节课程中,我们来讲解一下部分PE结构,以及SEH[Structured Exception Handling(结构化异常处理)]的知识。因为它在我们病毒编写中也是非常重要的。想象一下,如果我们连我们的被感染对象的文件格式都不熟悉的话,我们如何感染? 那么在上几节课程中,我们在文章中已经穿插了部分PE结构的内容,今天我们就来再深入的熟悉一下PE结构以及SEH的相关知识,为我们后面的文章做好铺垫。 1. 抛弃链接器, 手工定义PE结构程序:         当然我不喜欢很传统的给大家罗列一堆PE结构,然后来给大家讲解结构成员,我还是喜欢实际的的编写。所以这节课程,我们就通过编写一个自定义PE结构的程序来让大家充分的了解PE结构。(实际上在fasm中也就是抛弃fasm所有的宏,然后以二进制数据形式编译)         好了,我们了解下我们的PE结构组成部分。    20090416212722n.jpg (69.63 KB) 2009-4-17 11:56         OK,了解了以上后,我们就来手工的定义一个PE文件结构的程序,我们仅让它拥有一个节。那么接下来我们来一步一步的构造整个文件结构,首先是IMAGE_DOS_HEADER, 然后是Dos STUB[要不要都行],喜欢的就加上吧,...........一直到Section。         我们在开始之前要定义几个常量,方便后续的添加。首先是我们的基地址。我们定义为         Image_Base = 00400000h        然后是我们内存对齐值我们设置为1000h,以及我们的节映射到内存基于基地址的偏移 我们也设置为 1000h。那么我们定义         Code_Base = 1000h         好了,接下来我们就开始一步步的定义文件结构, 首先是IMAGE_DOS_HEADER 结构。 struct IMAGE_DOS_HEADER   e_magic           dw      ?  e_cblp            dw      ?  e_cp              dw      ?  e_crlc            dw      ?  e_cparhdr         dw      ?  e_minalloc        dw      ?  e_maxalloc        dw      ?  e_ss              dw      ?  e_sp              dw      ?  e_csum            dw      ?  e_ip              dw      ?  e_cs              dw      ?  e_lfarlc          dw      ?  e_ovno            dw      ?  e_res             dw   4 dup(?)  e_oemid           dw      ?  e_oeminfo         dw      ?  e_res2            dw  10 dup(?)  e_lfanew          dd      ?ends         IMAGE_DOS_HEADER结构中最重要的两个成员是e_magic,和e_lfanew。前者是两个字节的“MZ”标识符,后者是4个字节的指向IMAGE_NT_HEADERS结构的文件偏移。所以其余成员我们可以以0代替。定义如下 DOS_HEADER:.e_magic           db          'MZ'.e_cblp            dw      0.e_cp              dw      0.e_crlc            dw      0.e_cparhdr         dw      0.e_minalloc        dw      0.e_maxalloc        dw      0.e_ss              dw      0.e_sp              dw      0.e_csum            dw      0.e_ip              dw      0.e_cs              dw      0.e_lfarlc          dw      0.e_ovno            dw      0.e_res             dw   4 dup(0).e_oemid           dw      0.e_oeminfo         dw      0.e_res2            dw  10 dup(0).e_lfanew          dd  NT_HEADERS;-------------------------------------Dos_Stub:        mov ah, 4ch        int 21h;------------------------------------ NT_HEADERS:         OK,我们定义完DOS_HEADER,我们来定义NT_HEADERS结构。 [1]: struct IMAGE_NT_HEADERS        Signature                                dd        ?        FileHeader                                IMAGE_FILE_HEADER        OptionalHeader                        IMAGE_OPTIONAL_HEADER32ends         1. 首先第一个成员是Signature4个字节PE文件标志,它被定义为00004550h。ASCII码表示法则为dd “PE”。        2. 紧接着是我们的FileHeader成员。 [2]: struct IMAGE_FILE_HEADER        Machine                        dw        ?        NumberOfSections            dw        ?        TimeDateStamp                dd        ?        PointerToSymbolTable        dd        ?        NumberOfSymbols                dd        ?        SizeOfOptionalHeader        dw        ?        Characteristics                dw        ?ends                 (1): 第一个2字节成员Machine,表示运行平台。我们一般设置为14ch,表示 Intel I386。        (2): 第二个2字节成员NumberOfSections,表示我们的节数量,这个程序中我们设置一个Section,所以我们填写为1。        (3): 3 - 5 , 4字节成员因为没有什么用,所以我们设置为0.TimeDateStamp(文件创建时间) ,PointerToSymbolTable(COFF符号表的文件偏移量),NumberOfSymbols(符号表符号数量)。        (4): SizeOfOptionalHeader成员表示的是下面IMAGE_OPTIONAL_HEADER32结构的字节大小。我们用默认的IMAGE_OPTIONAL_HEADER32字节大小,0E0h。        (5): Characteristics成员表示的是文件的属性。我们普通的EXE文件一般是010fh。                [3:]        接下来是我们的OptionalHeader结构成员。 struct IMAGE_OPTIONAL_HEADER32        Magic                                dw        ?        MajorLinkerVersion                db        ?        MinorLinkerVersion                db        ?        SizeOfCode                        dd        ?        SizeOfInitializedData                dd        ?        SizeOfUninitializedData                dd        ?        AddressOfEntryPoint                dd        ?        BaseOfCode                        dd        ?        BaseOfData                        dd        ?        ImageBase                        dd        ?        SectionAlignment                dd        ?        FileAlignment                        dd        ?        MajorOperatingSystemVersion        dw        ?        MinorOperatingSystemVersion        dw        ?        MajorImageVersion                     dw       ?        MinorImageVersion                     dw       ?        MajorSubsystemVersion                 dw       ?        MinorSubsystemVersion                 dw       ?        Win32VersionValue                     dd      ?        SizeOfImage                           dd      ?        SizeOfHeaders                         dd      ?        CheckSum                              dd      ?        Subsystem                             dw       ?        DllCharacteristics                    dw       ?        SizeOfStackReserve                    dd      ?        SizeOfStackCommit                     dd      ?        SizeOfHeapReserve                     dd      ?        SizeOfHeapCommit                      dd      ?        LoaderFlags                           dd      ?        NumberOfRvaAndSizes                   dd      ?        DataDirectory                        IMAGE_DATA_DIRECTORY        rb                         sizeof.IMAGE_DATA_DIRECTORY*15ends           (1): 首先第一个成员.Magic是一个标记,一般我们普通的可执行文件,这个标记值为 010Bh。        (2): 下面两个1字节MajorLinkerVersion一般为0.它表示为我们的链接程序的版本号。        (3): SizeOfCode表示代码段的大小。这个大小值是代码段对齐后的值。这里我们设置的文件对齐值是200h,所以我们这里填写为200h。(也就是512byte)。        (4): SizeOfInitializedData表示初始化数据的字节大小,不包括代码段。我们这里填写为0。        (5): SizeOfUninitializedData表示未初始化数据的字节大小。即我们常说的.bbs节,这里我们没用。所以填写0。        (6): AddressOfEntryPoint成员指向我们程序的OEP,这个值是一个RVA地址,相对于我们基地址的偏移。这里我们把这个值设置为我们定义的Code节的偏移。由于我们Code段节我们设置它映射内存的虚拟地址是1000h,所以我们需要通过这个1000h - Code段文件偏移  = 相对于Code段的偏移。 通过这个相对偏移 + 文件偏移 = RVA地址。我们把这个相对偏移定义为Rva_Del = Code_Base - @Code。        (7): BaseOfCode表示代码段起始RVA地址。我们直接用Code_Base即可。        (8): BaseOfData表示数据段的起始RVA地址。我们可以设置为0.        (9): ImageBase表示我们的基地址。我们这里设置我们上面定义好的Image_Base。        (10): MajorOperatingSystemVersion和MinorOperatingSystemVersion表示的是操作系统的主版本号,和次版本好,我们一般用不上。所以这两个成员可以设置为0.        (11): MajorImageVersion, MinorImageVersion 表示用户自定义主、次版本号。对我们来说没用,设置为0.        (12): MajorSubsystemVersion和MinorSubsystemVersion表示最低子系统版本号,我们通常设置MajorSubsystemVersion为4。        (13): Win32VersionValue通常是保留值,一般为0.        (14): SizeOfImage表示映像文件载入内存后的总大小。我们这里一个节 + 我们的PE头部。我们设置为2000h        (15): SizeOfHeaders表示size(DosHeader + DosStub + NtHeader + Section Header)        (16): CheckSum效验和值。一般EXE文件为0.        (17): Subsystem表示子系统值。 2 GUI, 3 CUI。        (18): DllCharacteristics指定DLLMain函数何时被调用。默认0.        (19): SizeOfStackReserve 在exe文件中默认的线程堆栈保留大小。这里我们设置为10000h,因为它在需要时才被提交。        (20): SizeOfStackCommit 表示开始委派的堆栈大小。默认是4KB。        (21): SizeOfHeapReserve表示在exe文件中默认的堆空间保留大小,同样我们设置为10000h。        (22): SizeOfHeapCommit表示开始委派的堆空间大小。默认是4KB。        (23): LoaderFlags默认为0。        (24): NumberOfRvaAndSizes表示下面数据目录段的成员数量。10h         (25): DataDirectory数据目录表。表中成员为16个IMAGE_DATA_DIRECTORY结构的成员。我们不需要任何结构,这里全部填0. [4:]        接下来是节表结构。struct IMAGE_SECTION_HEADER    Name1 rb 8    union        PhysicalAddress dd  ?        VirtualSize dd      ?    ends    VirtualAddress dd       ?    SizeOfRawData dd        ?    PointerToRawData dd     ?    PointerToRelocations dd ?    PointerToLinenumbers dd ?    NumberOfRelocations dw  ?    NumberOfLinenumbers dw  ?    Characteristics dd      ?ends         (1):首先第一个8字节成员表示节名称。        (2):VirtualSize表示节映射内存的大小。我们这里填写为1000h。        (3):VirtualAddress表示节空间映射到内存基于基地址的偏移。这里我们填写我们之前定义好的Code_Base。        (4):SizeOfRawData表示节在磁盘空间中的大小。我们通过定义节代码指令的最后偏移 - 节起始偏移即可求出。        (5): PointerToRawData表示节所在文件中的物理文件偏移。我们直接用我们定义的@Code 标号即可。        (6): PointerToRelocations PointerToLinenumbers NumberOfRelocations 没什么用处直接填充0.        (7): Characteristics表示节属性,这个属性很重要,它决定了节空间映射到内存后的内存空间属性。我们这里用E0000020(可读可写可执行)           OK.到这里我们的结构就完成了,然后就是在我们的代码段偏移中写代码了。我们仅写一个ret指令。 OK。我们来看下我们最后的程序代码。  代码:;-----------------------------------------; Format Pe File  By:XFish;------------------------------------------Code_Base   = 1000hFile_Algin  = 200hRva_Del     = Code_Base - @CodeImage_Base  = 00400000h;________________________________________________________________DOS_HEADER:.e_magic                db        'MZ'.e_cblp                 dw      0.e_cp                   dw      0.e_crlc                 dw      0.e_cparhdr              dw      0.e_minalloc             dw      0.e_maxalloc             dw      0.e_ss                   dw      0.e_sp                   dw      0.e_csum                 dw      0.e_ip                   dw      0.e_cs                   dw      0.e_lfarlc                       dw      0.e_ovno                 dw      0.e_res                  dw   4 dup(0).e_oemid                dw      0.e_oeminfo              dw      0.e_res2                 dw  10 dup(0).e_lfanew               dd  NT_HEADERS   Dos_Stub:        mov ah, 4ch        int 21h                NT_HEADERS:.Signature                dd        'PE';++                                        ;IMAGE_FILE_HEADER.Machine                dw        14ch           ;.Inten I386.NumberOfSections         dw        1.TimeDateStamp                dd        0.PointerToSymbolTable        dd        0.NumberOfSymbols        dd        0        .SizeOfOptionalHeader        dw        0E0h.Characteristics        dw        010fh          ;.exe Signature;--;++                                        ;IMAGE_OPTIONAL_HEADER32.Magic                        dw        10Bh         ;.exe file.MajorLinkerVersion        db        0.MinorLinkerVersion        db        0.SizeOfCode                dd        File_Algin.SizeOfInitializedData        dd        0.SizeOfUninitializedData dd        0.AddressOfEntryPoint        dd        @Code + Rva_Del ;oep.BaseOfCode                dd        Code_Base        ;Code Section Rva.BaseOfData                 dd        0                ;Data Section Rva.ImageBase                dd        Image_Base.SectionAlignment        dd        Code_Base        ;Section Mem Align.FileAlignment                dd        File_Algin        ;Section Disk Align.MajorOperSystemVersion dw        0                ;system version 主.MinorOperSystemVersion dw        0                ;system version 次.MajorImageVersion        dw        0                ;user version   主.MinorImageVersion        dw        0                ;user version   次.MajorSubsystemVersion        dw        4.MinorSubsystemVersion        dw        0.Win32VersionValue        dd        0                ;Reserved 0.SizeOfImage                dd        2000h.SizeOfHeaders                dd        File_Algin        ;DosHeader + DosStub + NtHeader + Section Header.CheckSum                dd        0.SubSystem                dw        2                ;Gui.DllCharacteristics        dw        0.SizeOfStackReserve        dd        10000h                .SizeOfStackCommit        dd        1000h                ;Stack = 4kb.SizeOfHeapReserve        dd        10000h.SizeOfHeapCommit        dd        1000h                ;Heap = 4kb.LoaderFlags                dd        0.NumberOfRvaAndSizes        dd        10h                ;16.Export                 rd         2.Import                        rd        2.Misc_Section                rd        28        _SECTION_HEADER:.Name1                        db        '.code', 0, 0, 0.VirtualSize                dd        1000h.VirtualAddress                dd        Code_Base.SizeOfRawData                dd        @Code_End - @Code.PointerToRawData        dd        @Code.PointerToRelocations   dd         0.PointerToLinenumbers   dd         0.NumberOfRelocations    dw         0.NumberOfLinenumbers    dw         0.Characteristics        dd        0E0000020h align        200h;------------------------------------ @Code:         ret        @Code_End:这里留个问题给大家想想,此代码编译完后程序体积是多少字节呢?         好了,通过以上的编码,相信你对PE结构已经很熟悉了。那么我们继续往下吧,我们来学习SEH技术的利用。 (2): SEH技术的利用。         关于seh技术,很久之前Hume就总结过了,所以我在这里不想过多总结了。大家看可以在这个地址中看下Hume的文章。                http://www.pediy.com/bbshtml/bbs4/kanxue310.htm         我要讲解下关于seh技术的利用,例如如何在我们的汇编自程序当中利用技巧,方便的排错。                 传统的SEH的框架我想我就不多说了。        如下:        push    SEH_Handler        push    dword ptr fs:[0]        mov        [fs:0], esp`        大家看如下代码:  代码:        call        .SetupSEH        .ErrorHandler:        mov        esp, [esp+8]        ;[esp+8],指向lpseh。lpseh是我们EXCEPTION_REGISTRATION结构的地址。        xor        eax, eax        pop        dword [fs:eax]        ;取出EXCEPTION_REGISTRATION->prev ;前一个_EXCEPTION_REGISTRATION结构        pop        ecx                ;修正堆栈        ret                        ;ExitThread        .SetupSEH:        xor        edx, edx        push        dword [fs:edx]        mov        [fs:edx], esp        int        3这段代码是如果异常发生,则我们的异常过程将esp堆栈指针修复,然后恢复[fs:0]的成员。然后修正堆栈,退出线程。我们平时封装子程序的时候或者是写线程处理过程的时候完全可以利用以上代码方便的封装。         OK,写一段我们自定义PE文件结构的异常处理过程代码。 代码:;-----------------------------------------; Format Pe File  By:XFish;------------------------------------------include 'win32a.inc'Code_Base   = 1000hFile_Algin  = 200hRva_Del     = Code_Base - @CodeImage_Base  = 00400000h;________________________________________________________________DOS_HEADER:.e_magic                db        'MZ'.e_cblp                 dw      0.e_cp                   dw      0.e_crlc                 dw      0.e_cparhdr              dw      0.e_minalloc             dw      0.e_maxalloc             dw      0.e_ss                   dw      0.e_sp                   dw      0.e_csum                 dw      0.e_ip                   dw      0.e_cs                   dw      0.e_lfarlc                       dw      0.e_ovno                 dw      0.e_res                  dw   4 dup(0).e_oemid                dw      0.e_oeminfo              dw      0.e_res2                 dw  10 dup(0).e_lfanew               dd  NT_HEADERS   Dos_Stub:        mov ah, 4ch        int 21h                NT_HEADERS:.Signature                dd        'PE';++                                        ;IMAGE_FILE_HEADER.Machine                dw        14ch           ;.Inten I386.NumberOfSections         dw        1.TimeDateStamp                dd        0.PointerToSymbolTable        dd        0.NumberOfSymbols        dd        0        .SizeOfOptionalHeader        dw        0E0h.Characteristics        dw        010fh          ;.exe Signature;--;++                                        ;IMAGE_OPTIONAL_HEADER32.Magic                        dw        10Bh         ;.exe file.MajorLinkerVersion        db        0.MinorLinkerVersion        db        0.SizeOfCode                dd        File_Algin.SizeOfInitializedData        dd        0.SizeOfUninitializedData dd        0.AddressOfEntryPoint        dd        @Code + Rva_Del ;oep.BaseOfCode                dd        Code_Base        ;Code Section Rva.BaseOfData                 dd        0                ;Data Section Rva.ImageBase                dd        Image_Base.SectionAlignment        dd        Code_Base        ;Section Mem Align.FileAlignment                dd        File_Algin        ;Section Disk Align.MajorOperSystemVersion dw        0                ;system version 主.MinorOperSystemVersion dw        0                ;system version 次.MajorImageVersion        dw        0                ;user version   主.MinorImageVersion        dw        0                ;user version   次.MajorSubsystemVersion        dw        4.MinorSubsystemVersion        dw        0.Win32VersionValue        dd        0                ;Reserved 0.SizeOfImage                dd        @Code_End - @Code + 1000h.SizeOfHeaders                dd        File_Algin        ;DosHeader + DosStub + NtHeader + Section Header.CheckSum                dd        0.SubSystem                dw        2                ;Gui.DllCharacteristics        dw        0.SizeOfStackReserve        dd        10000h                .SizeOfStackCommit        dd        1000h                ;Stack = 4kb.SizeOfHeapReserve        dd        10000h.SizeOfHeapCommit        dd        1000h                ;Heap = 4kb.LoaderFlags                dd        0.NumberOfRvaAndSizes        dd        10h                ;16.Export                 rd         2.Import                        rd        2.Misc_Section                rd        28        _SECTION_HEADER:.Name1                        db        '.code', 0, 0, 0.VirtualSize                dd        1000h.VirtualAddress                dd        Code_Base.SizeOfRawData                dd        @Code_End - @Code.PointerToRawData        dd        @Code.PointerToRelocations   dd         0.PointerToLinenumbers   dd         0.NumberOfRelocations    dw         0.NumberOfLinenumbers    dw         0.Characteristics        dd        0E0000020h align        200h;------------------------------------ @Code:        db        0E8h                ;call opcode        dd        SetupSEH - ErrorHandler        ErrorHandler:        db        8bh        db        64h        db        24h        db        08h                 ;mov esp, [esp+8]        db        31h        db        0c0h                ;xor eax, eax        db        64h        db        8fh        db        00                ;pop dword [fs:0]        db        59h                ;pop ecx        ret        SetupSEH:        db        31h        db        0d2h                ;xor edx, edx        db        64h                        db        0ffh        db        32h                ;push dword [fs:0]        db        64h        db        89h        db        22h                ;mov dword [fs:0], esp        db        0cdh                        db        03h                ;int 3        ret        @Code_End:OK,今天的这篇文章就到这里了。我们下篇文章再见。以下是随文的程序和代码。。 bin.rar seh.rar  

小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

最新

返回顶部