Skip to content

Instantly share code, notes, and snippets.

@mojobojo
Last active April 27, 2024 18:35
Show Gist options
  • Save mojobojo/921a5af897e86bb940a2 to your computer and use it in GitHub Desktop.
Save mojobojo/921a5af897e86bb940a2 to your computer and use it in GitHub Desktop.
; Compile with nasm
; nasm Small.asm -o Small.exe
bits 64
%define ImageAddress 0x0000000140000000
%define BaseAddress 0x00010000
%define addr(x) (x+ImageAddress+BaseAddress)
%define Kernel32Handle rsp+0x50
%define Kernel32PeHeader rsp+0x58
%define GetProcAddress rsp+0x60
; DOS Header
e_magic:
dw 0x5A4D
Start:
jmp Main
; Pad all the way until 0x0C (where the PE header should be)
times 0x10 - ($ - $$) db 0
; NT Header
NTHeader:
Siganture:
dd 0x4550
Machine:
dw 0x8664
NumberOfSections:
dw 1
TimeDateStamp:
dd 0x0
PointerToSymbolTable:
dd 0x0
NumberOfSymbols:
dd 0x0
SizeOfOptionalHeaders:
dw SectionHeader-OptionalHeaders
Characteristics:
dw 0x0022 ; 0x030F
; Optional Headers
OptionalHeaders:
Magic:
dw 0x20B
MajorAndMinorLinkerVersion:
db 0
db 0
SizeOfCode:
dd 0x0
SizeOfInitalizedData:
dd 0x0
SizeOfUninitalizedData:
dd 0x0
AddressOfEntryPoint:
dd BaseAddress+Start
; Since these are overlapping structs this is the DOS headers PE pointer
BaseOfData:
dd NTHeader
ImageBase:
dq ImageAddress
SectionAlignment:
dd 0x00010000
FileAlignment:
dd 0x00000200
MajorAndMinorOSVersion:
dw 0x0
dw 0x0
MajorAndMinorImageVersion:
dw 0x0
dw 0x0
MajorSybsystemVersion:
dw 0x0004
MinorSubsystemVersion:
dw 0x0000
Win32VersionValue:
dd 0
SizeOfImage:
dd 0x00020000
SizeOfHeaders:
dd HeaderSize
CheckSum:
dd 0x0
Subsystem:
dw 0x0002
DllCharacteristics:
dw 0x0000
SizeOfStackReserve:
dq 0x0
SizeOfStackCommit:
dq 0x0
SizeOfHeapReserve:
dq 0x0
SizeOfHeapCommit:
dq 0
LoaderFlags:
dd 0x0
NumberOfRvaAndSizes:
dd 3
DataDirectories:
dd 0 ; Export Directory RVA
dd 0 ; Export Directory Size
dd 0 ; Import Directory RVA
dd 0 ; Import Directory Size
dd 0
dd 0
SectionHeader:
db "HANDMADE"
dd 0x00010000
dd 0x00010000
dd 0x00000200
dd 0x00000001
dd 0x0
dd 0
dw 0x0
dw 0x0
dd 0xE00000E0
HeaderSize equ $-$$
Main:
; NOTE: The stack needs to be 16 byte aligned and starts out
; 8 byte aligned
sub rsp, 0x128
; Get the offset to the modules that load with the application
mov rax, [gs:0x30]
add rax, 0x60
mov rax, [rax]
add rax, 0x18
mov rax, [rax]
add rax, 0x20
mov rax, [rax]
; Loop through each module
.NextModule:
mov rbx, rax
add rbx, 0x30
mov rbx, [rbx]
cmp rbx, 0
je Error ; This happens if we dont locate KERNEL32.DLL
mov rbx, rax
add rbx, 0x50
mov rbx, [rbx]
mov rcx, addr(Kernel32DllStr)
xor r8, r8
xor r9, r9
xor r10, r10
; Compare strings to find kernel32.dll
.Loop:
; We are comparing ASCII against unicode here
mov r8w, [rbx] ; Module name
mov r9b, [rcx] ; kernel32.dll string
xor r9, r8
add r10, r9
add rbx, 2
inc rcx
cmp r8w, 0
jne .Loop
cmp r10, 0 ; If compare succeeds r10 is zero
je SearchSuccess
mov rax, [rax]
jmp .NextModule
SearchSuccess:
add rax, 0x20
mov rax, [rax] ; Pointer to Kernel32.dll base
mov cx, [rax]
cmp cx, 0x5A4D
jne Error ; Bad DOS ehader
mov rbx, rax
add rbx, 0x3C ; Offset to PE header
xor rcx, rcx
mov ecx, [rbx]
mov rbx, rax
add rbx, rcx
mov cx, [rbx]
cmp cx, 0x4550
jne Error ; Bad PE header
; Last thing we need to do is find GetProcAddress
mov rcx, rbx
add rcx, 0x88 ; Export directory RVA
mov ecx, [rcx]
add rcx, rax
add rcx, 0x20
mov ecx, [rcx] ; RVA name table
add rcx, rax
xor r12, r12
.NextOrdinal:
xor r8, r8
xor r9, r9
xor r10, r10
xor r11, r11
mov rdx, addr(GetProcAddressName)
mov r8d, [rcx]
add rcx, 4
add r8, rax
.Loop:
mov r9b, [rdx]
mov r10b, [r8]
xor r10, r9
add r11, r10
inc rdx
inc r8
cmp r9b, 0
jne .Loop
cmp r11, 0 ; If compare succeeds r11 is zero
je LoadGetProcAddress
inc r12
jmp .NextOrdinal
LoadGetProcAddress:
; Okay now we found the GetProcAddress ordinal. Now we can finally get it so
; we can call it.
mov rcx, rbx
add rcx, 0x88 ; Export directory RVA
mov ecx, [rcx]
add rcx, rax
add rcx, 0x1C
mov ecx, [rcx]
add rcx, rax
imul r12, 4
add rcx, r12
mov ecx, [rcx]
add rcx, rax ; rcx = GetProcAddress
mov [Kernel32Handle], rax
mov [Kernel32PeHeader], rbx
mov [GetProcAddress], rcx
mov rcx, [Kernel32Handle]
mov rdx, addr(LoadLibraryAStr)
call [GetProcAddress]
cmp rax, 0
je Error ; In case GetProcAddress failed
mov rcx, addr(User32DllStr)
call rax ; LoadLibraryA
cmp rax, 0
je Error ; Failed to open user32.dll
; Resolve MessageBoxA
mov rcx, rax
mov rdx, addr(MessageBoxAStr)
call [GetProcAddress]
cmp rax, 0
je Error
; Finally call MessageBoxA
xor r9, r9 ; uType
xor rcx, rcx ; hWnd
mov rdx, addr(HelloWorldText) ; lpText
mov r8, addr(HelloWorldText) ; lpCaption
call rax
xor rax, rax
jmp EndFunction
Error:
mov rax, 1
EndFunction:
add rsp, 0x128
ret
Kernel32DllStr:
db "KERNEL32.DLL", 0
User32DllStr:
db "USER32.DLL", 0
MessageBoxAStr:
db "MessageBoxA", 0
LoadLibraryAStr:
db "LoadLibraryA", 0
GetProcAddressName:
db "GetProcAddress", 0
HelloWorldText:
db "Hello World", 0
; Apparently windows doesnt like it unless its aligned
EndPadding:
times 1024-($-$$) db 0
ImageSize equ $-$$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment