Files
nullsecuritynet-tools/binary/hyperion/source/Src/Container/32/loadexecutable.asm
T
Levon 'noptrix' Kayan 485fad8b48 re-commit
2023-11-14 12:04:48 +02:00

584 lines
13 KiB
NASM

;Loads the exe which is stored in input_image
;into memory and starts its execution
proc loadExecutable stdcall APITable:DWORD,\
input_image:DWORD
local str1[256]:BYTE, ret_val:DWORD, image_file_header:DWORD,\
loaded_file:DWORD
pushad
;verify checksum of packed executable
writeWithNewLine createStringVerifyChecksum, str1, le_exit_error
stdcall verifyChecksum, [input_image], INFILE_SIZE
test eax,eax
jz le_exit_error
;verify whether the content of the data section is pe
writeWithNewLine createStringVerifyPE, str1, le_exit_error
mov eax,[input_image]
add eax,4
stdcall verifyPE, eax, INFILE_SIZE
test eax,eax
mov [image_file_header],eax
jz le_exit_error
;copy pe header and sections into memory
writeNewLineToLog APITable
writeWithNewLine createStringMappingFileInMemory, str1, le_exit_error
mov eax,[input_image]
add eax,4
mov ebx,INFILE_SIZE
sub ebx,4
stdcall loadFile, [APITable], [image_file_header], eax, ebx
test eax,eax
mov [loaded_file],eax
jz le_exit_error
;loading import table
writeNewLineToLog APITable
writeWithNewLine createStringLoadingFilesAPIs, str1, le_exit_error
stdcall loadImportTable, [APITable], [loaded_file]
test eax,eax
jz le_exit_error
;set the correct permissions for each section
writeNewLineToLog APITable
writeWithNewLine createStringSettingPermissions, str1, le_exit_error
mov eax,[input_image]
add eax,4
mov ebx,INFILE_SIZE
sub ebx,4
stdcall setPermissions, [APITable], [image_file_header], eax, ebx
test eax,eax
jz le_exit_error
le_exit_success:
popad
mov eax,1
ret
le_exit_error:
popad
mov eax,0
ret
endp
;load the APIs in the import table
proc loadImportTable, APITable:DWORD, image_base:DWORD
local str1[256]:BYTE, import_table:DWORD, null_directory_entry[sizeof.IMAGE_IMPORT_DESCRIPTOR]:BYTE
pushad
;find import table in data directory
mov edx,[image_base]
mov eax,[edx+IMAGE_DOS_HEADER.e_lfanew]
add eax,edx
add eax,4
;image file header now in eax
add eax,sizeof.IMAGE_FILE_HEADER
lea eax,[eax+IMAGE_OPTIONAL_HEADER32.DataDirectory]
;first data directory entry now in eax
add eax,sizeof.IMAGE_DATA_DIRECTORY
;import data directory entry now in eax
mov eax,[eax+IMAGE_DATA_DIRECTORY.VirtualAddress]
add eax,edx
;pointer to import table now in eax
mov [import_table],eax
writeWithNewLine createStringFoundImportTable, str1, le_exit_error
writeRegisterToLog APITable, [import_table]
test eax,eax
jz pit_exit_error
;init null directory entry
lea esi,[null_directory_entry]
mov ecx,sizeof.IMAGE_IMPORT_DESCRIPTOR
mov al,0
pit_init_null_directory_loop:
mov [esi],al
inc esi
dec ecx
jnz pit_init_null_directory_loop
mov ebx,[import_table]
;iterate over the directory tables
pit_next_directory_entry:
lea esi,[null_directory_entry]
mov edi,ebx
mov ecx,sizeof.IMAGE_IMPORT_DESCRIPTOR
rep cmpsb
je pit_exit_success
;load APIs of this directory
stdcall loadImportDirectoryTable, [APITable], [image_base], ebx
test eax,eax
jz pit_exit_error
;next entry
add ebx,sizeof.IMAGE_IMPORT_DESCRIPTOR
jmp pit_next_directory_entry
pit_exit_success:
popad
mov eax,1
ret
pit_exit_error:
popad
mov eax,0
ret
endp
;loads the APIs
proc loadImportDirectoryTable stdcall, APITable:DWORD, image_base:DWORD, directory_entry:DWORD
local str1[256]:BYTE, lookup_table:DWORD, import_address_table:DWORD, dll_image_base:DWORD
pushad
;write info about data directory table to logfile
writeNewLineToLog APITable
test eax,eax
jz lidt_exit_error
writeWithNewLine createStringProcessImportDirectory, str1, lidt_exit_error
mov eax,[directory_entry]
mov eax,[eax+IMAGE_IMPORT_DESCRIPTOR.Name_]
add eax,[image_base]
mov ebx,eax
;pointer to dll name in ebx
writeLog APITable, eax
test eax,eax
jz lidt_exit_error
writeNewLineToLog APITable
test eax,eax
jz lidt_exit_error
;load the corresponding dll
invoke LoadLibrary, ebx
test eax,eax
jz lidt_exit_error
mov [dll_image_base],eax
;read pointer to the api tables
mov edx,[directory_entry]
mov eax,[edx+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
add eax,[image_base]
mov [lookup_table],eax
mov eax,[edx+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
add eax,[image_base]
mov [import_address_table],eax
;index to current API
sub ecx,ecx
;iterate the lookup_table entries
lidt_next_lookup_entry:
mov eax,[lookup_table]
add eax,ecx
mov eax,[eax]
test eax,eax
jz lidt_exit_success
mov ebx,eax
and eax,IMAGE_ORDINAL_FLAG32
jnz lidt_byordinal
lidt_byname:
createStringName str1
lea eax,[str1]
writeLog APITable, eax
test eax,eax
jz lidt_exit_error
add ebx,[image_base]
lea ebx,[ebx+IMAGE_IMPORT_BY_NAME.Name_]
mov eax,ebx
writeLog APITable, eax
test eax,eax
jz lidt_exit_error
writeNewLineToLog APITable
test eax,eax
jz lidt_exit_error
;API name pointer in ebx
push ecx
invoke GetProcAddress, [dll_image_base], ebx
pop ecx
test eax,eax
jz lidt_exit_error
mov ebx,[import_address_table]
add ebx,ecx
mov [ebx],eax
;fetch next API
add ecx,4
jmp lidt_next_lookup_entry
lidt_byordinal:
createStringOrdinal str1
lea eax,[str1]
writeLog APITable, eax
test eax,eax
jz lidt_exit_error
;remove the ordinal flag
xor ebx,IMAGE_ORDINAL_FLAG32
mov eax,ebx
writeRegisterToLog APITable, eax
test eax,eax
jz pit_exit_error
;API ordinal in ebx
push ecx
invoke GetProcAddress, [dll_image_base], ebx
pop ecx
test eax,eax
jz lidt_exit_error
mov ebx,[import_address_table]
add ebx,ecx
mov [ebx],eax
;fetch next API
add ecx,4
jmp lidt_next_lookup_entry
lidt_exit_success:
popad
mov eax,1
ret
lidt_exit_error:
popad
mov eax,0
ret
endp;
;sets the memory permissions for each section
proc setPermissions stdcall, APITable:DWORD, image_file_header:DWORD, file_image_base:DWORD, \
file_image_size:DWORD
local number_of_sections:DWORD, image_base:DWORD, section_headers:DWORD,\
pe_header_size:DWORD, str1[256]:BYTE, vprotect_ret:DWORD
pushad
;find section header
mov edx,[image_file_header]
sub eax,eax
mov ax,[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
;search for section header
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
;first section header found
mov [section_headers],eax
mov eax,sizeof.IMAGE_SECTION_HEADER
mov edx,[number_of_sections]
mul edx
;end of section header sections found
add eax,[section_headers]
mov ebx,[file_image_base]
sub eax,ebx
;unaligned size of pe header in eax
mov [pe_header_size],eax
;set pe header page read-only
mov edx,[APITable]
lea eax,[vprotect_ret]
stdcall dword [edx+VirtualProtect], [image_base], [pe_header_size], PAGE_READONLY, eax
test eax,eax
jz sp_exit_error
;some output for the user
writeRegisterToLog APITable, [image_base]
test eax,eax
jz sp_exit_error
;set the section page permissions
mov ecx,[number_of_sections]
mov ebx,[section_headers]
sp_load_section_loop:
stdcall setSection, [APITable], ebx, [image_base], [file_image_base]
test eax,eax
jz sp_exit_error
add ebx,sizeof.IMAGE_SECTION_HEADER
dec ecx
jnz sp_load_section_loop
sp_exit_success:
popad
mov eax,1
ret
sp_exit_error:
popad
sub eax,eax
ret
endp;
;sets the complete image of the decrypted file writeable so
;we can copy pe header and sections into into
proc loadFile stdcall, APITable:DWORD, image_file_header:DWORD, file_image_base:DWORD, \
file_image_size:DWORD
local number_of_sections:DWORD, image_base:DWORD, aux:DWORD,\
str1[256]:BYTE, vprotect_ret:DWORD, section_headers:DWORD, pe_header_size:DWORD
pushad
;find section header
mov edx,[image_file_header]
sub eax,eax
mov ax,[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
;make the complete image writable
mov eax,[edx+IMAGE_OPTIONAL_HEADER32.SizeOfImage]
mov [aux],edx ;store edx, we need it later
lea edx,[vprotect_ret]
mov ebx,[APITable]
stdcall dword [ebx+VirtualProtect], [image_base], eax, PAGE_READWRITE, edx
test eax,eax
jz lf_exit_error
;some output for the user
writeWithNewLine createStringLoadedPEHeader, str1, lf_exit_error
writeRegisterToLog APITable, [image_base]
test eax,eax
jz lf_exit_error
mov edx,[aux] ;restore edx
;continue search for section header
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
;first section header found
mov [section_headers],eax
mov eax,sizeof.IMAGE_SECTION_HEADER
mov edx,[number_of_sections]
mul edx
;end of section header sections found
add eax,[section_headers]
mov ebx,[file_image_base]
sub eax,ebx
;unaligned size of pe header in eax
mov [pe_header_size],eax
;copy header to memory
mov edi,[image_base]
mov esi,[file_image_base]
mov ecx,[pe_header_size]
rep movsb
;load the sections
mov ecx,[number_of_sections]
mov ebx,[section_headers]
lf_load_section_loop:
stdcall loadSection, [APITable], ebx, [image_base], [file_image_base]
test eax,eax
jz lf_exit_error
add ebx,sizeof.IMAGE_SECTION_HEADER
dec ecx
jnz lf_load_section_loop
lf_exit_success:
popad
mov eax,[image_base]
ret
lf_exit_error:
popad
mov eax,0
ret
endp
;load the corresponding section into memory
proc loadSection stdcall, APITable:DWORD, section_header:DWORD, image_base:DWORD,\
file_image_base:DWORD
local str1[256]:BYTE
pushad
;copy from file into memory
mov edx,[section_header]
mov edi,[edx+IMAGE_SECTION_HEADER.VirtualAddress]
add edi,[image_base]
mov esi,[file_image_base]
add esi,[edx+IMAGE_SECTION_HEADER.PointerToRawData]
mov ecx,[edx+IMAGE_SECTION_HEADER.SizeOfRawData]
rep movsb
;print some infos to the log file
createStringLoaded str1
lea eax,[str1]
writeLog APITable, eax
test eax,eax
jz ls_exit_error
lea edi,[str1]
mov byte [edi+8],0
mov edx,[section_header]
lea esi,[edx+IMAGE_SECTION_HEADER._Name]
mov ecx,8
push edi
rep movsb
pop edi
writeLog APITable, edi
writeNewLineToLog APITable
mov edx,[section_header]
mov eax,[edx+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,[image_base]
writeRegisterToLog APITable, eax
ls_exit_success:
popad
mov eax,1
ret
ls_exit_error:
popad
sub eax,eax
ret
endp
;set the memory page permission for the corresponding section
proc setSection stdcall, APITable:DWORD, section_header:DWORD, image_base:DWORD,\
file_image_base:DWORD
local section_flags:DWORD, vprotect_ret:DWORD, str1[256]:BYTE
pushad
mov edx,[section_header]
;section execute/read/write?
mov ebx,[edx+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 ssn_no_execute_read_write
mov eax,PAGE_EXECUTE_READWRITE
mov [section_flags],eax
jmp ssn_set_memory
ssn_no_execute_read_write:
;section execute/read?
mov ebx,[edx+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 ssn_no_execute_read
mov eax,PAGE_EXECUTE_READ
mov [section_flags],eax
jmp ssn_set_memory
ssn_no_execute_read:
;section read/write?
mov ebx,[edx+IMAGE_SECTION_HEADER.Characteristics]
and ebx,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
cmp ebx,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
jne ssn_no_read_write
mov eax,PAGE_READWRITE
mov [section_flags],eax
jmp ssn_set_memory
ssn_no_read_write:
;section read?
mov ebx,[edx+IMAGE_SECTION_HEADER.Characteristics]
and ebx,IMAGE_SCN_MEM_READ
cmp ebx,IMAGE_SCN_MEM_READ
jne ssn_no_read
mov eax,PAGE_READONLY
mov [section_flags],eax
jmp ssn_set_memory
ssn_no_read:
mov eax,PAGE_NOACCESS
mov [section_flags],eax
;set section permissions
ssn_set_memory:
mov edx,[section_header]
mov eax,[edx+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,[image_base]
mov ebx,[edx+IMAGE_SECTION_HEADER.VirtualSize]
mov ecx,[APITable]
lea edx,[vprotect_ret]
stdcall dword [ecx+VirtualProtect],eax,ebx,[section_flags], edx
test eax,eax
jz ssn_exit_error
;some output for the user
mov edx,[section_header]
mov eax,[edx+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,[image_base]
writeRegisterToLog APITable, eax
ssn_exit_success:
popad
mov eax,1
ret
ssn_exit_error:
popad
sub eax,eax
ret
endp;
;check MZ und PE signature and return start of the image file header
proc verifyPE stdcall, image_base:DWORD, section_size:DWORD
local retval:DWORD
pushad
mov edx,[image_base]
mov ax,[edx+IMAGE_DOS_HEADER.e_magic]
cmp ax,IMAGE_DOS_SIGNATURE
jne vpe_exit_error
mov eax,[edx+IMAGE_DOS_HEADER.e_lfanew]
add edx,eax
mov eax,dword [edx]
cmp eax,IMAGE_NT_SIGNATURE
jne vpe_exit_error
add edx,4
mov [retval],edx
vpe_exit_success:
popad
mov eax,[retval]
ret
vpe_exit_error:
popad
sub eax,eax
ret
endp
;First 4 bytes of data seciton contain a checksum
;Verify that the checksum is correct
;TODO: CHECKSUM SIZE is atm hardcoded
proc verifyChecksum stdcall, section_address:DWORD, section_size:DWORD
pushad
mov ebx,dword [section_address]
mov eax,[ebx]
add ebx,4
mov ecx,[section_size]
sub ecx,4
;checksum is in eax
;pointer to file in ebx
;size of file in ecx
sub edi,edi
vs_calc_cs:
sub edx,edx
mov dl,byte [ebx]
add edi,edx
inc ebx
dec ecx
jnz vs_calc_cs
;calculated checksum is in edi
cmp edi,eax
jne vs_exit_error
vs_exit_success:
popad
mov eax,1
ret
vs_exit_error:
popad
sub eax,eax
ret
endp