-
-
Save davide99/967e313952c08ea33ccfc113a7040c2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;------------------------------------------------ | |
; Minimal Hello World with no linked libraries | |
; | |
; Author: Davide Pisanò | |
;------------------------------------------------ | |
.386 | |
.model flat, stdcall | |
option casemap:none | |
assume fs:nothing | |
.DATA | |
HelloWorldString db "Hello world", 0 | |
Kernel32Dll dw "K", "E", "R", "N", "E", "L", "3", "2", ".", "D", "L", "L", 0 | |
Kernel32DllLen equ 26 | |
LoadLibraryAName db "LoadLibraryA", 0 | |
LoadLibraryANameLen equ 13 | |
GetProcAddressName db "GetProcAddress", 0 | |
GetProcAddressNameLen equ 15 | |
User32Dll db "USER32.DLL", 0 | |
MessageBoxAName db "MessageBoxA", 0 | |
.CODE | |
memcmp PROC ptr1:DWORD, ptr2:DWORD, len:DWORD | |
push ESI | |
push EDI | |
push ECX | |
mov ESI, ptr1 ; ESI = ptr1 | |
mov EDI, ptr2 ; EDI = ptr2 | |
mov ECX, len ; ECX = len | |
cld ; Clear direction flag: increasing addresses | |
cmp ECX, ECX ; if len==0 don't compare anything | |
repe cmpsb ; compare bytes at DS:ESI and ES:EDI while ZF==1 | |
setne AL ; set AL if ZF=0 | |
movzx EAX, AL | |
pop ECX | |
pop EDI | |
pop ESI | |
ret | |
memcmp ENDP | |
findProcAddressByName PROC OrdinalPos:DWORD, OrdinalTableRVA:DWORD, AddressTableRVA:DWORD, DllBase:DWORD | |
push ECX | |
push EBX | |
mov EBX, DllBase | |
mov ECX, OrdinalTableRVA | |
shl OrdinalPos, 1 ; OrdinalPos * 2 | |
add ECX, OrdinalPos ; ECX = Ordinal function RVA | |
mov AX, [EBX + ECX] ; EBX = DLLBase, AX = ordinal function | |
movzx EAX, AX | |
shl EAX, 2 ; EAX * 4 | |
add EAX, AddressTableRVA | |
mov EAX, [EBX + EAX] ; EAX = function RVA | |
add EAX, EBX ; EAX = function pointer | |
pop EBX | |
pop ECX | |
ret | |
findProcAddressByName ENDP | |
MainEntry proc | |
LOCAL ExportedFunctions: DWORD | |
LOCAL ExportTableRVA: DWORD | |
LOCAL AddressTableRVA: DWORD | |
LOCAl OrdinalTableRVA: DWORD | |
LOCAL LoadLibraryA: DWORD | |
LOCAL GetProcAddress: DWORD | |
; | |
; Find kernel32.dll base address | |
; | |
mov EBX, [FS:30h] ; Get the PEB pointer from TEB (or TIB) | |
mov EBX, [EBX + 0Ch] ; Get the Ldr pointer from PEB | |
mov EBX, [EBX + 14h] ; Get the InMemoryOrderModuleList pointer from Ldr (pointer to first element) | |
findKernel32: | |
push Kernel32DllLen ; Length of KERNEL32.DLL | |
push [EBX + 40] ; Pointer to BaseDllName | |
push offset Kernel32Dll ; Pointer to Kernel32Dll | |
call memcmp | |
cmp EAX, 0 | |
je foundKernel32 | |
mov EBX, [EBX] ; Go to next entry | |
jmp findKernel32 | |
foundKernel32: | |
mov EBX, [EBX + 16] ; EBX = kernel32.dll base address | |
; | |
; Check the PE signature | |
; Status: | |
; - EBX = DLLBase | |
; | |
mov EAX, [EBX + 3Ch] ; *(EBX+3Ch) = PE RVA, we dereference it in EAX | |
add EAX, EBX ; EAX points to {'P', 'E', '\0', '\0'} reversed = 0x00004550 | |
mov ECX, EAX ; Save PE pointer for later | |
mov EAX, [EAX] ; dereference the pointer | |
cmp EAX, 00004550h | |
jne exit | |
; | |
; Find the export table RVA | |
; Status: | |
; - EBX = DLLBase | |
; - ECX = pointer to PE signature | |
; | |
mov EAX, [ECX + 78h] ; ECX + 78h points to the export table RVA, EAX contains the ExportTableRVA | |
mov ExportTableRVA, EAX | |
; | |
; Find the number of exported functions | |
; Status: | |
; - EAX = pointer to export table RVA | |
; - EBX = DLLBase | |
; | |
mov ECX, [EBX + EAX + 14h] ; 14 = offset | |
mov ExportedFunctions, ECX | |
; | |
; Find the address table RVA | |
; Status: | |
; - EAX = pointer to export table RVA | |
; - EBX = DLLBase | |
; | |
mov ECX, [EBX + EAX + 1Ch] ; 1C = offset | |
mov AddressTableRVA, ECX | |
; | |
; Find the name pointer table RVA | |
; Status: | |
; - EAX = pointer to export table RVA | |
; - EBX = DLLBase | |
; | |
mov ECX, [EBX + EAX + 20h] ; 20 = offset | |
mov ESI, ECX ; Save Name pointer table RVA for later | |
; | |
; Find the ordinal table RVA | |
; Status: | |
; - EAX = pointer to export table RVA | |
; - EBX = DLLBase | |
; | |
mov ECX, [EBX + EAX + 24h] ; 24 = offset | |
mov OrdinalTableRVA, ECX | |
; | |
; Find LoadLibraryA and GetProcAddress | |
; Registers that cannot be used: | |
; - EBX = DLLBase | |
; | |
mov LoadLibraryA, 0 | |
mov GetProcAddress, 0 | |
mov ECX, 0 | |
findFuncLoop: | |
cmp ECX, ExportedFunctions | |
je findFuncLoopEnd | |
mov EAX, LoadLibraryA | |
and EAX, GetProcAddress | |
cmp EAX, 0 | |
jnz findFuncLoopEnd ; found both functions? | |
mov EDX, [EBX + ESI] ; EDX = RVA of the function name, ESI = Name pointer table RVA | |
add EDX, EBX ; EDX = Pointer to function name "string" | |
push LoadLibraryANameLen ; 3rd argument | |
push offset LoadLibraryAName ; 2nd argument | |
push EDX ; 1st argument | |
call memcmp | |
cmp EAX, 0 ; found? | |
je foundLoadLibraryAPos | |
push GetProcAddressNameLen | |
push offset GetProcAddressName | |
push EDX | |
call memcmp | |
cmp EAX, 0 ; found? | |
je foundGetProcAddressNamePos | |
findFuncLoopTail: | |
inc ECX | |
add ESI, 4 ; move pointer to next function name | |
jmp findFuncLoop | |
foundLoadLibraryAPos: | |
mov LoadLibraryA, ECX ; initially save the position | |
jmp findFuncLoopTail | |
foundGetProcAddressNamePos: | |
mov GetProcAddress, ECX ; initially save the position | |
jmp findFuncLoopTail | |
findFuncLoopEnd: | |
mov EAX, LoadLibraryA | |
and EAX, GetProcAddress | |
cmp EAX, 0 ; We can't find the functions | |
je exit | |
push EBX ; DLLBase | |
push AddressTableRVA | |
push OrdinalTableRVA | |
push LoadLibraryA | |
call findProcAddressByName | |
mov LoadLibraryA, EAX ; override the position with the actual pointer | |
push EBX ; DLLBase | |
push AddressTableRVA | |
push OrdinalTableRVA | |
push GetProcAddress | |
call findProcAddressByName | |
mov GetProcAddress, EAX ; override the position with the actual pointer | |
push offset User32Dll | |
call LoadLibraryA | |
push offset MessageBoxAName | |
push EAX | |
call GetProcAddress | |
push 0 | |
push offset HelloWorldString | |
push offset HelloWorldString | |
push 0 | |
call EAX | |
exit: | |
ret | |
MainEntry endp | |
END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment