forked from KolibriOS/kolibrios
665 lines
17 KiB
NASM
665 lines
17 KiB
NASM
|
; ------------------------------------------------------------- ;
|
||
|
; KWINE is a fork of program PELoad written by 0CodErr
|
||
|
; author - rgimad
|
||
|
; ------------------------------------------------------------- ;
|
||
|
ORG 0
|
||
|
BITS 32
|
||
|
; ------------------------------------------------------------- ;
|
||
|
PATH_SIZE equ 4096
|
||
|
PARAMS_SIZE equ 4096
|
||
|
STACK_SIZE equ 4096
|
||
|
END_ equ IMAGE_BASE - (PATH_SIZE + PARAMS_SIZE + STACK_SIZE)
|
||
|
; ------------------------------------------------------------- ;
|
||
|
IMAGE_BASE equ 400000H
|
||
|
; ------------------------------------------------------------- ;
|
||
|
MENUET01 db 'MENUET01'
|
||
|
version dd 1
|
||
|
program.start dd start_
|
||
|
program.end dd END_
|
||
|
program.memory dd END_ + PATH_SIZE + PARAMS_SIZE + STACK_SIZE
|
||
|
program.stack dd END_ + PATH_SIZE + PARAMS_SIZE + STACK_SIZE
|
||
|
program.params dd END_ + PATH_SIZE
|
||
|
program.path dd END_
|
||
|
; ------------------------------------------------------------- ;
|
||
|
load.library:
|
||
|
mov eax, 68
|
||
|
mov ebx, 19
|
||
|
mov ecx, [esp + 4]
|
||
|
int 64
|
||
|
ret 4
|
||
|
; ------------------------------------------------------------- ;
|
||
|
getprocaddress:
|
||
|
mov edx, [esp + 8]
|
||
|
xor eax, eax
|
||
|
test edx, edx
|
||
|
jz .end
|
||
|
.next:
|
||
|
xor eax, eax
|
||
|
cmp [edx], dword 0
|
||
|
jz .end
|
||
|
mov esi, [edx]
|
||
|
mov edi, [esp + 4]
|
||
|
.next_:
|
||
|
lodsb
|
||
|
scasb
|
||
|
jne .fail
|
||
|
or al, al
|
||
|
jnz .next_
|
||
|
jmp .ok
|
||
|
.fail:
|
||
|
add edx, 8
|
||
|
jmp .next
|
||
|
.ok:
|
||
|
mov eax, [edx + 4]
|
||
|
.end:
|
||
|
ret 8
|
||
|
; ------------------------------------------------------------- ;
|
||
|
realloc.app.mem:
|
||
|
mov eax, 64
|
||
|
mov ebx, 1
|
||
|
mov ecx, [esp + 4]
|
||
|
int 64
|
||
|
ret 4
|
||
|
; ------------------------------------------------------------- ;
|
||
|
set.current.directory:
|
||
|
mov eax, 30
|
||
|
mov ebx, 1
|
||
|
mov ecx, [esp + 4]
|
||
|
int 64
|
||
|
ret 4
|
||
|
; ------------------------------------------------------------- ;
|
||
|
%if 0 ; comment
|
||
|
int2str:
|
||
|
%define number [esp + 8 + 8 * 4]
|
||
|
%define buffer [esp + 4 + 8 * 4]
|
||
|
pushad
|
||
|
mov edi, buffer
|
||
|
mov eax, " " ; 4 spaces
|
||
|
stosd
|
||
|
stosd
|
||
|
stosw
|
||
|
xor al, al
|
||
|
stosb
|
||
|
dec edi
|
||
|
dec edi
|
||
|
mov ecx, 10
|
||
|
mov eax, number
|
||
|
.next:
|
||
|
xor edx, edx
|
||
|
div ecx ; ecx = 10
|
||
|
add edx, 48 ; edx = (eax MOD ecx) + 48
|
||
|
mov [edi], dl
|
||
|
dec edi
|
||
|
test eax, eax
|
||
|
jnz .next
|
||
|
popad
|
||
|
ret 8
|
||
|
%undef number
|
||
|
%undef buffer
|
||
|
%endif ; endcomment
|
||
|
; ------------------------------------------------------------- ;
|
||
|
; test_file_path db "/hd3/1/mntest.exe",0
|
||
|
; complex
|
||
|
; address
|
||
|
; data
|
||
|
; hello
|
||
|
; numbers +-
|
||
|
; proc
|
||
|
; sptrim
|
||
|
; se
|
||
|
; clear
|
||
|
; locals +-
|
||
|
; tokenise -
|
||
|
; mntest
|
||
|
file_path dd 0
|
||
|
lib_name dd 0
|
||
|
lib dd 0
|
||
|
func dd 0
|
||
|
func_name dd 0
|
||
|
; ------------------------------------------------------------- ;
|
||
|
sz_pe_load db "PELoad",0
|
||
|
; ------------------------------------------------------------- ;
|
||
|
con_init dd 0
|
||
|
con_write_asciiz dd 0
|
||
|
con_exit dd 0
|
||
|
console dd 0
|
||
|
sz_con_init db "con_init",0
|
||
|
sz_con_write_asciiz db "con_write_asciiz",0
|
||
|
sz_con_exit db "con_exit",0
|
||
|
sz_console db "/sys/lib/console.obj",0
|
||
|
; ------------------------------------------------------------- ;
|
||
|
MZ dw 0
|
||
|
PE dw 0
|
||
|
lfa_new dd 0
|
||
|
NumberOfSections dd 0
|
||
|
SizeOfOptionalHeader dd 0
|
||
|
EntryPoint dd 0
|
||
|
SizeOfImage dd 0
|
||
|
SizeOfHeaders dd 0
|
||
|
DataDirectories dd 0
|
||
|
SectionsTable dd 0
|
||
|
Import dd 0
|
||
|
; ------------------------------------------------------------- ;
|
||
|
ERROR_MESSAGE dd 0
|
||
|
err_params db "Parameters error",0
|
||
|
err_file_path db "No input file path",0
|
||
|
err_read_file db "Read file error",0
|
||
|
err_mz_not_found db "No DOS signature found",0
|
||
|
err_pe_not_found db "No PE signature found",0
|
||
|
err_load_library db "Error load library: ",0
|
||
|
err_func_not_found db "Not found function: ",0
|
||
|
|
||
|
; ------------------------------------------------------------- ;
|
||
|
%if 0 ; comment
|
||
|
msg_buffer resb 256
|
||
|
sz_new_line db 10,0
|
||
|
sz_space db " ",0
|
||
|
sz_space_colon_space db " : ",0
|
||
|
%endif ; endcomment
|
||
|
sz_empty db "",0
|
||
|
|
||
|
|
||
|
start_:
|
||
|
; ------------------------------------------------------------- ;
|
||
|
; find params and file path
|
||
|
; mov eax, test_file_path
|
||
|
mov eax, [program.params]
|
||
|
cmp [eax], byte 34 ; quote
|
||
|
jne .no_quote
|
||
|
inc eax
|
||
|
mov edi, eax
|
||
|
.find_quote_or_zero:
|
||
|
cmp [edi], byte 0
|
||
|
je .found
|
||
|
cmp [edi], byte 34 ; quote
|
||
|
je .found
|
||
|
inc edi
|
||
|
jmp .find_quote_or_zero
|
||
|
.no_quote:
|
||
|
mov edi, eax
|
||
|
.find_space_or_zero:
|
||
|
cmp [edi], byte 0
|
||
|
je .found
|
||
|
cmp [edi], byte 32 ; space
|
||
|
je .found
|
||
|
inc edi
|
||
|
jmp .find_space_or_zero
|
||
|
.found:
|
||
|
mov [edi], byte 0
|
||
|
mov [file_path], eax
|
||
|
; check file path
|
||
|
mov eax, [file_path]
|
||
|
mov al, [eax]
|
||
|
test al, al
|
||
|
jne file_path_ok
|
||
|
mov [ERROR_MESSAGE], dword err_file_path
|
||
|
jmp ERROR
|
||
|
file_path_ok:
|
||
|
; check MZ signature (IMAGE_DOS_HEADER.e_magic)
|
||
|
push dword [file_path];filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword MZ;buffer
|
||
|
push dword 2;count
|
||
|
push dword 0
|
||
|
push dword 0;position
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
test eax, eax
|
||
|
je read_ok
|
||
|
mov [ERROR_MESSAGE], dword err_read_file
|
||
|
jmp ERROR
|
||
|
read_ok:
|
||
|
cmp word [MZ], "MZ"
|
||
|
je MZ_exists
|
||
|
mov [ERROR_MESSAGE], dword err_mz_not_found
|
||
|
jmp ERROR
|
||
|
MZ_exists:
|
||
|
; get lfa_new (IMAGE_DOS_HEADER.e_lfanew)
|
||
|
push dword [file_path];filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword lfa_new;buffer
|
||
|
push dword 4;count
|
||
|
push dword 0
|
||
|
push dword 60;position
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
; check PE signature (IMAGE_OPTIONAL_HEADER.Magic)
|
||
|
push dword [file_path];filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword PE;buffer
|
||
|
push dword 2;count
|
||
|
push dword 0
|
||
|
push dword [lfa_new];position
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
cmp word [PE], "PE"
|
||
|
je PE_exists
|
||
|
mov [ERROR_MESSAGE], dword err_pe_not_found
|
||
|
jmp ERROR
|
||
|
PE_exists:
|
||
|
; get size of headers (IMAGE_OPTIONAL_HEADER.SizeOfHeaders)
|
||
|
push dword [file_path];filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword SizeOfHeaders;buffer
|
||
|
push dword 4;count
|
||
|
push dword 0
|
||
|
mov eax, [lfa_new]
|
||
|
add eax, 84
|
||
|
push eax;position
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
; resize app memory and load headers
|
||
|
mov eax, IMAGE_BASE
|
||
|
add eax, [SizeOfHeaders]
|
||
|
push eax
|
||
|
call realloc.app.mem
|
||
|
|
||
|
push dword [file_path];filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword IMAGE_BASE;buffer
|
||
|
push dword [SizeOfHeaders];count
|
||
|
push dword 0
|
||
|
push dword 0;position
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
|
||
|
add esp, (25 * 5) ; restore our stack top
|
||
|
|
||
|
mov edx, [lfa_new]
|
||
|
; get SizeOfImage (IMAGE_OPTIONAL_HEADER.SizeOfImage)
|
||
|
mov eax, [IMAGE_BASE + edx + 80]
|
||
|
mov [SizeOfImage], eax
|
||
|
; get EntryPoint (IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint)
|
||
|
mov eax, [IMAGE_BASE + edx + 40]
|
||
|
mov [EntryPoint], eax
|
||
|
; get DataDirectories (IMAGE_OPTIONAL_HEADER.DataDirectory)
|
||
|
lea eax, [edx + 120]
|
||
|
mov [DataDirectories], eax
|
||
|
; get SizeOfOptionalHeader (IMAGE_FILE_HEADER.SizeOfOptionalHeader)
|
||
|
movzx eax, word [IMAGE_BASE + edx + 20]
|
||
|
mov [SizeOfOptionalHeader], ax
|
||
|
; get SectionsTable
|
||
|
lea eax, [edx + 24]
|
||
|
add ax, [SizeOfOptionalHeader]
|
||
|
mov [SectionsTable], eax
|
||
|
; get Import
|
||
|
mov eax, IMAGE_BASE
|
||
|
add eax, [DataDirectories]
|
||
|
add eax, 1 * 8
|
||
|
mov eax, [eax]
|
||
|
mov [Import], eax
|
||
|
; get NumberOfSections (IMAGE_FILE_HEADER.NumberOfSections)
|
||
|
movzx eax, word [IMAGE_BASE + edx + 6]
|
||
|
mov [NumberOfSections], eax
|
||
|
; resize app memory and load sections to their virtual address
|
||
|
mov eax, IMAGE_BASE
|
||
|
add eax, [SizeOfImage]
|
||
|
push eax
|
||
|
call realloc.app.mem
|
||
|
|
||
|
mov ecx, [NumberOfSections]
|
||
|
next_section:
|
||
|
lea eax, [ecx - 1]
|
||
|
lea eax, [eax * 4 + eax]
|
||
|
lea eax, [eax * 8]
|
||
|
add eax, IMAGE_BASE
|
||
|
add eax, [SectionsTable]
|
||
|
|
||
|
push dword [file_path] ; filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
mov edx, [eax + 12]
|
||
|
add edx, IMAGE_BASE
|
||
|
push edx ; buffer (IMAGE_SECTION_HEADER.VirtualAddress)
|
||
|
push dword [eax + 16] ; count (IMAGE_SECTION_HEADER.SizeOfRawData)
|
||
|
push dword 0
|
||
|
push dword [eax + 20] ; position (IMAGE_SECTION_HEADER.PointerToRawData)
|
||
|
push dword 0
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
|
||
|
dec ecx
|
||
|
jnz next_section
|
||
|
|
||
|
mov eax, [NumberOfSections]
|
||
|
lea eax, [eax * 4 + eax]
|
||
|
lea eax, [eax * 4 + eax]
|
||
|
add esp, eax ; restore our stack top
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
; ==========================================================
|
||
|
%if 0 ; comment
|
||
|
push sz_console
|
||
|
call load.library
|
||
|
; mov [console], eax
|
||
|
mov ecx, eax
|
||
|
mov ebx, getprocaddress
|
||
|
push ecx
|
||
|
push sz_con_init
|
||
|
call ebx
|
||
|
mov [con_init], eax
|
||
|
push ecx
|
||
|
push sz_con_write_asciiz
|
||
|
call ebx
|
||
|
mov [con_write_asciiz], eax
|
||
|
push ecx
|
||
|
push sz_con_exit
|
||
|
call ebx
|
||
|
mov [con_exit], eax
|
||
|
push sz_pe_load
|
||
|
push -1
|
||
|
push -1
|
||
|
push -1
|
||
|
push -1
|
||
|
call [con_init]
|
||
|
|
||
|
mov ecx, [NumberOfSections]
|
||
|
next_sect:
|
||
|
lea eax, [ecx - 1]
|
||
|
lea eax, [eax * 4 + eax]
|
||
|
lea eax, [eax * 8]
|
||
|
add eax, IMAGE_BASE
|
||
|
add eax, [SectionsTable]
|
||
|
push eax
|
||
|
|
||
|
push eax
|
||
|
call [con_write_asciiz]
|
||
|
push sz_space_colon_space
|
||
|
call [con_write_asciiz]
|
||
|
|
||
|
|
||
|
pop eax
|
||
|
add eax, 20
|
||
|
mov eax, [eax]
|
||
|
push eax
|
||
|
push msg_buffer
|
||
|
call int2str
|
||
|
push msg_buffer
|
||
|
call [con_write_asciiz]
|
||
|
|
||
|
push sz_new_line
|
||
|
call [con_write_asciiz]
|
||
|
|
||
|
|
||
|
dec ecx
|
||
|
jnz next_sect
|
||
|
%endif ; endcomment
|
||
|
; ==============================================
|
||
|
; program.path = program.path_without_filename & "lib/"
|
||
|
mov edi, [program.path]
|
||
|
xor al, al
|
||
|
xor ecx, ecx
|
||
|
dec ecx
|
||
|
repne scasb
|
||
|
std
|
||
|
mov al, "/"
|
||
|
repne scasb
|
||
|
cld
|
||
|
inc edi
|
||
|
inc edi
|
||
|
mov eax, "lib/"
|
||
|
stosd
|
||
|
;
|
||
|
mov [lib_name], edi
|
||
|
|
||
|
xor ecx, ecx
|
||
|
next_descriptor:
|
||
|
lea eax, [ecx * 4 + ecx]
|
||
|
lea eax, [eax * 4]
|
||
|
add eax, IMAGE_BASE
|
||
|
add eax, [Import]
|
||
|
mov edx, [eax + 12]
|
||
|
add edx, IMAGE_BASE
|
||
|
|
||
|
%if 0 ; comment
|
||
|
pushad
|
||
|
push edx
|
||
|
call [con_write_asciiz]
|
||
|
push sz_new_line
|
||
|
call [con_write_asciiz]
|
||
|
popad
|
||
|
%endif ; endcomment
|
||
|
|
||
|
pushad
|
||
|
; concatenate (program.path_without_filename & "lib/") & lib_name
|
||
|
mov esi, edx
|
||
|
mov edi, [lib_name]
|
||
|
.copy_lib_name:
|
||
|
lodsb
|
||
|
stosb
|
||
|
test al, al
|
||
|
jnz .copy_lib_name
|
||
|
; try to load library
|
||
|
push dword [program.path]
|
||
|
call load.library
|
||
|
test eax, eax
|
||
|
jnz .lib_loaded
|
||
|
; concatenate "Error load library: " & lib_name
|
||
|
sub edi, [lib_name]
|
||
|
mov esi, edi
|
||
|
mov edi, err_load_library
|
||
|
xor al, al
|
||
|
xor ecx, ecx
|
||
|
dec ecx
|
||
|
repne scasb
|
||
|
dec edi
|
||
|
mov ecx, esi
|
||
|
mov esi, edx
|
||
|
rep movsb
|
||
|
;
|
||
|
popad
|
||
|
mov [ERROR_MESSAGE], dword err_load_library
|
||
|
jmp ERROR
|
||
|
.lib_loaded:
|
||
|
mov [lib], eax
|
||
|
popad
|
||
|
xor ebx, ebx
|
||
|
next_function:
|
||
|
mov edx, [eax + 16]
|
||
|
lea esi, [edx + ebx * 4 + IMAGE_BASE]
|
||
|
mov [func], esi
|
||
|
mov edx, [esi]
|
||
|
test edx, edx
|
||
|
jz .done
|
||
|
inc edx
|
||
|
inc edx
|
||
|
add edx, IMAGE_BASE
|
||
|
|
||
|
%if 0 ; comment
|
||
|
pushad
|
||
|
push edx
|
||
|
call [con_write_asciiz]
|
||
|
push sz_new_line
|
||
|
call [con_write_asciiz]
|
||
|
popad
|
||
|
%endif ; endcomment
|
||
|
|
||
|
pushad
|
||
|
mov [func_name], edx
|
||
|
; look for address of imported function
|
||
|
push dword [lib]
|
||
|
push edx
|
||
|
call getprocaddress
|
||
|
test eax, eax
|
||
|
jnz .func_found
|
||
|
popad
|
||
|
; concatenate "Not found function: " & name of function
|
||
|
mov edi, err_func_not_found
|
||
|
xor al, al
|
||
|
xor ecx, ecx
|
||
|
dec ecx
|
||
|
repne scasb
|
||
|
dec edi
|
||
|
mov esi, edx
|
||
|
.copy_func_name:
|
||
|
lodsb
|
||
|
stosb
|
||
|
test al, al
|
||
|
jnz .copy_func_name
|
||
|
;
|
||
|
dec edi
|
||
|
mov eax, " in "
|
||
|
stosd
|
||
|
|
||
|
mov esi, [lib_name]
|
||
|
.copy_lib_name:
|
||
|
lodsb
|
||
|
stosb
|
||
|
test al, al
|
||
|
jnz .copy_lib_name
|
||
|
|
||
|
mov [ERROR_MESSAGE], dword err_func_not_found
|
||
|
jmp ERROR
|
||
|
.func_found:
|
||
|
mov edx, [func]
|
||
|
mov [edx], eax
|
||
|
popad
|
||
|
inc ebx
|
||
|
jmp next_function
|
||
|
.done:
|
||
|
|
||
|
inc ecx
|
||
|
lea eax, [ecx * 4 + ecx]
|
||
|
lea eax, [eax * 4]
|
||
|
add eax, IMAGE_BASE
|
||
|
add eax, [Import]
|
||
|
mov eax, [eax + 12]
|
||
|
cmp eax, dword 0
|
||
|
jnz next_descriptor
|
||
|
|
||
|
|
||
|
; set.current.directory
|
||
|
mov edi, [file_path]
|
||
|
xor al, al
|
||
|
xor ecx, ecx
|
||
|
dec ecx
|
||
|
repne scasb
|
||
|
std
|
||
|
mov al, "/"
|
||
|
repne scasb
|
||
|
cld
|
||
|
mov [edi + 1], byte 0
|
||
|
push dword [file_path]
|
||
|
call set.current.directory
|
||
|
mov [edi + 1], byte "/" ; restore full file_path
|
||
|
|
||
|
; ---------------------- ;
|
||
|
; call load_console_lib ;
|
||
|
; ---------------------- ;
|
||
|
|
||
|
; go to EntryPoint
|
||
|
mov eax, [EntryPoint]
|
||
|
add eax, IMAGE_BASE
|
||
|
jmp eax
|
||
|
|
||
|
|
||
|
; push dword [EntryPoint]
|
||
|
; push msg_buffer
|
||
|
; call int2str
|
||
|
; push msg_buffer
|
||
|
; call [con_write_asciiz]
|
||
|
|
||
|
%if 0 ; comment
|
||
|
push 0
|
||
|
call [con_exit]
|
||
|
%endif ; endcomment
|
||
|
|
||
|
%if 0 ; comment
|
||
|
; dump ---------------------------------------
|
||
|
push dword dump_path;filepath
|
||
|
dec esp
|
||
|
mov [esp], byte 0
|
||
|
push dword 0 ;buffer
|
||
|
mov eax, IMAGE_BASE
|
||
|
add eax, [SizeOfImage]
|
||
|
push eax;count
|
||
|
push dword 0
|
||
|
push dword 0;position
|
||
|
push dword 2
|
||
|
mov ebx, esp
|
||
|
mov eax, 70
|
||
|
int 64
|
||
|
|
||
|
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
int 64
|
||
|
|
||
|
dump_path db "/hd3/1/dump.bin",0
|
||
|
%endif ; endcomment
|
||
|
; ==========================================================
|
||
|
|
||
|
|
||
|
ERROR:
|
||
|
|
||
|
push sz_console
|
||
|
call load.library
|
||
|
; mov [console], eax
|
||
|
mov ecx, eax
|
||
|
mov ebx, getprocaddress
|
||
|
push ecx
|
||
|
push sz_con_init
|
||
|
call ebx
|
||
|
mov [con_init], eax
|
||
|
push ecx
|
||
|
push sz_con_write_asciiz
|
||
|
call ebx
|
||
|
mov [con_write_asciiz], eax
|
||
|
push ecx
|
||
|
push sz_con_exit
|
||
|
call ebx
|
||
|
mov [con_exit], eax
|
||
|
|
||
|
push sz_pe_load
|
||
|
push -1
|
||
|
push -1
|
||
|
push -1
|
||
|
push -1
|
||
|
call [con_init]
|
||
|
push dword [ERROR_MESSAGE]
|
||
|
call [con_write_asciiz]
|
||
|
push 0
|
||
|
call [con_exit]
|
||
|
|
||
|
xor eax, eax
|
||
|
dec eax
|
||
|
int 64
|
||
|
|
||
|
|
||
|
|
||
|
; load_console_lib:
|
||
|
; push sz_console
|
||
|
; call load.library
|
||
|
|
||
|
; push eax
|
||
|
; push sz_con_init
|
||
|
; call getprocaddress
|
||
|
; mov [con_init], eax
|
||
|
|
||
|
; push sz_empty
|
||
|
; push -1
|
||
|
; push -1
|
||
|
; push -1
|
||
|
; push -1
|
||
|
; call [con_init]
|
||
|
|
||
|
; ret
|