首页
社区
课程
招聘
[原创]4.PE文件挑战题
发表于: 2008-12-14 09:43 1848

[原创]4.PE文件挑战题

2008-12-14 09:43
1848
题目 4.PE文件挑战题
ID    Compiler

.586
.model flat, stdcall
option casemap :none ; case sensitive
;include \masmplus\include\windows.inc ;头部包含文件
;include \masmplus\include\user32.inc
;include \masmplus\include\kernel32.inc
;includelib \masmplus\lib\kernel32.lib
;includelib \masmplus\lib\user32.lib

  @pushsz MACRO  str
  LOCAL next
  call  next  
  db    str,0   
  next:
  ENDM

  @pushszl MACRO  str
  LOCAL next
  call  next  
  db    str,0ah, 0dh, 0   
  next:
  ENDM
MB_OK                                                                equ     00000000h
TRUE                                 equ 1
FALSE                                equ 0
NULL                                 equ 0

IMAGE_DOS_SIGNATURE equ 5A4Dh     
IMAGE_NT_SIGNATURE equ 00004550h

IMAGE_DOS_HEADER STRUCT
  e_magic           WORD      ?
  e_cblp            WORD      ?
  e_cp              WORD      ?
  e_crlc            WORD      ?
  e_cparhdr         WORD      ?
  e_minalloc        WORD      ?
  e_maxalloc        WORD      ?
  e_ss              WORD      ?
  e_sp              WORD      ?
  e_csum            WORD      ?
  e_ip              WORD      ?
  e_cs              WORD      ?
  e_lfarlc          WORD      ?
  e_ovno            WORD      ?
  e_res             WORD   4 dup(?)
  e_oemid           WORD      ?
  e_oeminfo         WORD      ?
  e_res2            WORD  10 dup(?)
  e_lfanew          DWORD      ?
IMAGE_DOS_HEADER ENDS

IMAGE_NUMBEROF_DIRECTORY_ENTRIES            equ 16

IMAGE_DATA_DIRECTORY STRUCT
  VirtualAddress    DWORD      ?
  isize             DWORD      ?
IMAGE_DATA_DIRECTORY ENDS

IMAGE_OPTIONAL_HEADER32 STRUCT
  Magic                         WORD       ?
  MajorLinkerVersion            BYTE       ?
  MinorLinkerVersion            BYTE       ?
  SizeOfCode                    DWORD      ?
  SizeOfInitializedData         DWORD      ?
  SizeOfUninitializedData       DWORD      ?
  AddressOfEntryPoint           DWORD      ?
  BaseOfCode                    DWORD      ?
  BaseOfData                    DWORD      ?
  ImageBase                     DWORD      ?
  SectionAlignment              DWORD      ?
  FileAlignment                 DWORD      ?
  MajorOperatingSystemVersion   WORD       ?
  MinorOperatingSystemVersion   WORD       ?
  MajorImageVersion             WORD       ?
  MinorImageVersion             WORD       ?
  MajorSubsystemVersion         WORD       ?
  MinorSubsystemVersion         WORD       ?
  Win32VersionValue             DWORD      ?
  SizeOfImage                   DWORD      ?
  SizeOfHeaders                 DWORD      ?
  CheckSum                      DWORD      ?
  Subsystem                     WORD       ?
  DllCharacteristics            WORD       ?
  SizeOfStackReserve            DWORD      ?
  SizeOfStackCommit             DWORD      ?
  SizeOfHeapReserve             DWORD      ?
  SizeOfHeapCommit              DWORD      ?
  LoaderFlags                   DWORD      ?
  NumberOfRvaAndSizes           DWORD      ?
  DataDirectory                 IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER32 ENDS

IMAGE_OPTIONAL_HEADER  equ  <IMAGE_OPTIONAL_HEADER32>

IMAGE_FILE_HEADER STRUCT
  Machine               WORD    ?
  NumberOfSections      WORD    ?
  TimeDateStamp         DWORD   ?
  PointerToSymbolTable  DWORD   ?
  NumberOfSymbols       DWORD   ?
  SizeOfOptionalHeader  WORD    ?
  Characteristics       WORD    ?
IMAGE_FILE_HEADER ENDS

IMAGE_NT_HEADERS32 STRUCT
  Signature       DWORD ?
  FileHeader      IMAGE_FILE_HEADER <>
  OptionalHeader  IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS32 ENDS

IMAGE_NT_HEADERS        equ  <IMAGE_NT_HEADERS32>

IMAGE_EXPORT_DIRECTORY STRUCT
  Characteristics           DWORD      ?
  TimeDateStamp             DWORD      ?
  MajorVersion              WORD       ?
  MinorVersion              WORD       ?
  nName                     DWORD      ?
  nBase                     DWORD      ?
  NumberOfFunctions         DWORD      ?
  NumberOfNames             DWORD      ?
  AddressOfFunctions        DWORD      ?
  AddressOfNames            DWORD      ?
  AddressOfNameOrdinals     DWORD      ?
IMAGE_EXPORT_DIRECTORY ENDS

.code
start:
        call        @F
@@:
        pop                eax
        test        eax, 80000000h
        jnz                RunAsDriver
        push        dword ptr [esp]
        call        GetBase
        push        esi
        push        edi
        push        ebx
        mov                esi, eax ;->hModule
        call        GetKernelBase
        mov                edi, eax ;->hKernel
        cmp                edi, esi
        jnz                LoadAsDll
        @pushsz 'LoadLibraryA'
        push        edi
        call        GetApiAddress
        ;mov                esi, eax
        @pushsz        'user32.dll'
        call        eax
        @pushsz        'MessageBoxA'
        push        eax
        call        GetApiAddress
        push        MB_OK
        @pushsz        'Run As Exe'
        @pushsz        '以Exe方式运行'
        push        NULL
        call        eax
        pop                ebx
        pop                edi
        pop                esi
        ret
LoadAsDll:
        @pushsz 'LoadLibraryA'
        push        edi
        call        GetApiAddress
        ;mov                esi, eax
        @pushsz        'user32.dll'
        call        eax
        @pushsz        'MessageBoxA'
        push        eax
        call        GetApiAddress
        push        MB_OK
        @pushsz        'Run As Dll'
        @pushsz        '以Dll方式运行'
        push        NULL
        call        eax
        pop                ebx
        pop                edi
        pop                esi
        ret 0Ch
RunAsDriver:
        assume        fs:nothing
        ;int        3
        mov  eax,dword ptr fs:[34h]        ;KdVersionBlock获取内核基址Windows
    add  eax,18h
    mov  eax,[eax]
    mov  eax,[eax]
    mov  eax,[eax+18h]
        push        edi
        push        esi
        mov                edi, eax
        @pushsz        'DbgPrint'
        push        eax
        call        GetApiAddress
        @pushszl        'Run as Driver'
        call        eax
        add                esp, 4
        mov                eax, 0C0000001h
        pop                esi
        pop                edi
        ret                08h
GetBase   proc uses esi edi dwKernelRet:DWORD
    LOCAL dwReturn: DWORD

    mov edi, dwKernelRet
    and edi, 0ffff0000h
    .while TRUE
        .if word ptr [edi] == IMAGE_DOS_SIGNATURE
            mov esi, edi                             
            add esi, [esi + IMAGE_DOS_HEADER.e_lfanew]
            .if word ptr [esi] == IMAGE_NT_SIGNATURE   
                mov dwReturn, edi                  
                .break
            .endif
        .endif
        
        dec edi
        xor di, di
        .break  .if edi < 070000000h  
    .endw
    mov eax, dwReturn
    ret
GetBase   endp
GetKernelBase proc uses esi edi ebx ecx edx
        local   buffer[24]:byte

        assume fs:nothing
        call        @F
@@:
        pop                ebx
        sub                ebx, offset @B
        mov                eax, fs:[30h]
        mov                eax, dword ptr [eax+0Ch]
        lea                edx, dword ptr [eax+0Ch]
        mov                eax, dword ptr [edx]
        xor                edi, edi
        .while  eax != edx
                        movzx        ecx, word ptr[eax+2Ch]
                        .if                ecx == 18h
                                mov                esi, dword ptr [eax+30h]
                                lea                edi,   buffer
                                shr                ecx, 2
                                rep                movsd
                                lea                edi,   buffer
                                mov                ecx, 0Ch
                                .repeat
                                        or                word ptr[edi], 20h
                                        add                edi, 2
                                .untilcxz
                                mov                ecx, 0Ch
                                lea                edi,   buffer
                                mov                esi, offset Kernel32
                                add                esi, ebx
                                repe        cmpsw
                                .if ZERO?
                                        mov                edi, [eax+18h]        ;DllBase
                                        .break
                                .endif
                        .endif
                        mov                eax, [eax]
                        xor                edi, edi
        .endw
        mov                eax, edi
        ret
GetKernelBase endp
Kernel32 db 'k',0,'e',0,'r',0,'n',0,'e',0,'l',0,'3',0,'2', 0, '.',0,'d',0,'l',0,'l',0

GetApiAddress   proc uses ecx ebx edx esi edi hModule:DWORD, szApiName:DWORD
    LOCAL dwReturn: DWORD
    LOCAL dwApiLength: DWORD

    mov dwReturn, 0

   
    mov esi, szApiName
    mov edx, esi
Continue_Searching_Null:
    cmp byte ptr [esi], 0
    jz We_Got_The_Length
    inc esi                       
    jmp Continue_Searching_Null   
We_Got_The_Length:
    inc esi                  
        sub esi, edx                  
    mov dwApiLength, esi           

   
    mov esi, hModule
    add esi, [esi + 3ch]
    assume esi: ptr IMAGE_NT_HEADERS
    mov esi, [esi].OptionalHeader.DataDirectory.VirtualAddress
    add esi, hModule
    assume esi:ptr IMAGE_EXPORT_DIRECTORY   ; esi 指向 Kernel32.dll 的输出表

    ;遍历 AddressOfNames 指向的数组匹配名字:
    mov ebx, [esi].AddressOfNames
    add ebx, hModule                ; 别忘了加上基地址,AddressOfNames 是 RVA
    xor edx, edx                    ; edx = \"函数计数\",初始化为0
    .repeat
        push esi                    ; 保存esi,后面会用到。
        mov edi, [ebx]              ; edi = 输出表中的当前函数名字
        add edi, hModule            ; 别忘了加上基地址
        mov esi, szApiName          ; 函数名字的首地址
        mov ecx, dwApiLength        ; 函数名字的长度
        cld                         ; 设置方向标志
        repz cmpsb                  ; 开始查找,我们先去喝杯咖啡吧  :)
        .if ZERO?                   ; 找到啦?
            pop esi                 ; 恢复 esi
            jmp _Find_Index         ; 查找该函数的地址索引 [Page]
        .endif
        pop esi                     ; 恢复 esi
        add ebx, 4                  ; 下一个函数(每个函数的地址占用4个字节)
        inc edx                     ; 增加函数计数
    .until edx >= [esi].NumberOfNames
    jmp _Exit                       

    ;函数名称索引 -> 序号索引 -> 地址索引
    ;公式:
    ;API’s Address = ( API’s Ordinal * 4 ) + AddressOfFunctions’ VA + Kernel32 imagebase
_Find_Index:
    sub ebx, [esi].AddressOfNames   ; 上面的 repz cmpsb 那里,如果匹配的话,
                                    ; esi 就指向了下一个函数的首地址,所以要先减掉它。
sub ebx, hModule                ; 减掉基地址,得到 RVA
    shr ebx, 1                      ; 要除以 2 ,还是因为 repz cmpsb 那行
    add ebx, [esi].AddressOfNameOrdinals    ; AddressOfNameOrdinals
    add ebx, hModule                ; 别忘了基地址
    movzx eax, word ptr [ebx]       ; Now, eax = API’s Ordinal [Page]
    shl eax, 2                      ; 要乘以 4 才得到偏移
    add eax,[esi].AddressOfFunctions; + AddressOfFunctions’ VA
    add eax, hModule                ; + Kernel32 imagebase

    ;从地址表得到导出函数地址
    mov eax, [eax]                  ; 得到函数的 RVA
    add eax, hModule                ; 别忘了基地址(说了很多次了,呵呵)
    mov dwReturn, eax               ; 最终得到的函数的线性地址。(呼……好累啊,终于完成了)
_Exit:
    mov eax, dwReturn               ; done!  :)

    ret
GetApiAddress       endp

end start

ml /nologo /c /coff c:\exe.asm

link /nologo /driver /base:0x10000 /align:32 /subsystem:windows exe.obj

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
2
100   分
2008-12-14 10:29
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
3
HI, 007 Compiler:

请您报上大名,方便我们进行后期的统计以及奖品邮寄工作。

也欢迎继续回答其他题目!
2008-12-15 12:00
0
游客
登录 | 注册 方可回帖
返回
//