kolibrios-gitea/programs/emulator/kwine/kwine.asm
Rustem Gimadutdinov (rgimad) 81120905e2 kwine v0.0.2
git-svn-id: svn://kolibrios.org@7873 a494cfbc-eb01-0410-851d-a64ba20cac60
2020-05-05 22:40:04 +00:00

665 lines
17 KiB
NASM

; ------------------------------------------------------------- ;
; KWINE is a fork of program PELoad written by 0CodErr
; author of fork - 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