Created
January 23, 2019 11:20
-
-
Save gynvael/772301c0924f8db4d2a050e9d772da3c to your computer and use it in GitHub Desktop.
32-bit PE loader from OSAmber (part of bootloader)
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
[bits 16] | |
[org 0x0] | |
%define SEGMENT_PHYSICAL_ADDR 0x20000 | |
%define SEGNO(segno,ti,rpl) (segno*8+ti*4+rpl) | |
%define PADDR(a) (a+SEGMENT_PHYSICAL_ADDR) | |
%define PEIMAGE_PADDR 0x20200 | |
%define IDOSH_LFANEW 0x3C | |
%define IOPTH_IMGSIZE 0x50 | |
%define IOPTH_IMGBASE 0x34 | |
%define IOPTH_ENTRYPOINT 0x28 | |
; Assumptions: | |
; cs == 0x2000 | |
; ip == 0 | |
start: | |
; Set ds same to cs | |
mov ax, cs | |
mov ds, ax | |
; Switch to protected mode | |
; Block interrupts | |
cli | |
; Load the GDT address into GDTR | |
lgdt [initial_gdt_table_desc] | |
; Set protected mode flag | |
mov eax, cr0 | |
or al, 1 | |
; Enter the flag and jump | |
mov cr0, eax | |
jmp dword SEGNO(1,0,0):PADDR(pmode_start) ; first segment, | |
; Yep, we are in the protected mode | |
[bits 32] | |
pmode_start: | |
; Re set the other segment regs | |
; fs and gs will not be used for now | |
mov ax, SEGNO(2,0,0) | |
mov ds, ax | |
mov es, ax | |
mov ss, ax | |
; Set the stack somewhere | |
mov esp, 0x800000 ; For now it will be enough (from 8MB down) | |
; | |
; Mini PE Loader | |
; Load the PE image and jump to EP | |
; | |
; Get the IMAGE_DOS_HEADER.e_lfanew | |
mov ebx, [PEIMAGE_PADDR+IDOSH_LFANEW] | |
add ebx, PEIMAGE_PADDR | |
; Get the IMAGE_NT_HEADERS.SizeOfImage | |
mov ecx, [ebx+IOPTH_IMGSIZE] | |
; Get the IMAGE_NT_HEADERS.ImageBase | |
mov edi, [ebx+IOPTH_IMGBASE] | |
; Setup esi | |
mov esi, PEIMAGE_PADDR | |
; Start to copy | |
shr ecx, 2 | |
rep movsd | |
; Get the EP, add ImageBase | |
mov eax, [ebx+IOPTH_ENTRYPOINT] | |
add eax, [ebx+IOPTH_IMGBASE] | |
; Well, thats it, time to say goodbye | |
; And jump to the PE image | |
jmp eax | |
; Make sure this address is aligned to 0x20 ;> | |
times (0x20-(($-start)% 0x20)) db 0 | |
initial_gdt_table: | |
; Null entry | |
dd 0 | |
dd 0 | |
; Code section | |
dw 0xffff ; Lower limit | |
dw 0x0000 ; Lower base | |
db 00000000b ; Mid base | |
db 10011010b ; Type = 1010 (Code, Execute/Read) | |
; S (Desc Type) = 1 (code or data) | |
; DPL (Priv lvl) = 0 (one ring to rule them all) | |
; P (Present) = 1 (yep) | |
db 11001111b ; Mid limit = 0xf | |
; AVL = 0 (nope) | |
; L (64-bit) = 0 (nope) | |
; D/B (16/32?) = 1 (32-bit) | |
; Granularity = 1 (4KB) | |
db 00000000b ; High base | |
; Data section | |
dw 0xffff ; Lower limit | |
dw 0x0000 ; Lower base | |
db 00000000b ; Mid base | |
db 10010010b ; Type = 0010 (Data, Read/Write) | |
; S (Desc Type) = 1 (code or data) | |
; DPL (Priv lvl) = 0 (one ring to rule them all) | |
; P (Present) = 1 (yep) | |
db 11001111b ; Mid limit = 0xf | |
; AVL = 0 (nope) | |
; L (64-bit) = 0 (nope) | |
; D/B (16/32?) = 1 (32-bit) | |
; Granularity = 1 (4KB) | |
db 00000000b ; High base | |
; Another null entry | |
dd 0 | |
dd 0 | |
initial_gdt_table_end: | |
initial_gdt_table_desc: | |
; There are 4 entries, 8 bytes each | |
; 4*8 = 20h | |
; So, the mask is 20h-1 -> 1Fh -> 0000000000011111 | |
dw 0000000000011111b | |
dd PADDR(initial_gdt_table) ; | |
; Padding | |
times (0x200-($-start)) db 0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment