├── examples ├── hello ├── hello64 └── src │ ├── hello.asm │ └── hello64.asm ├── stubs ├── x86_32_stub ├── x86_64_linux_stub ├── x86_64_mswin_stub ├── x86_32_stub.nasm ├── stub_to_c.py ├── x86_64_linux_stub.nasm ├── x86_32_stub.c ├── x86_64_linux_stub.c ├── x86_64_mswin_stub.c └── x86_64_mswin_stub.nasm ├── README.md └── asmloader.c /examples/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gynvael/asmloader/HEAD/examples/hello -------------------------------------------------------------------------------- /examples/hello64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gynvael/asmloader/HEAD/examples/hello64 -------------------------------------------------------------------------------- /stubs/x86_32_stub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gynvael/asmloader/HEAD/stubs/x86_32_stub -------------------------------------------------------------------------------- /stubs/x86_64_linux_stub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gynvael/asmloader/HEAD/stubs/x86_64_linux_stub -------------------------------------------------------------------------------- /stubs/x86_64_mswin_stub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gynvael/asmloader/HEAD/stubs/x86_64_mswin_stub -------------------------------------------------------------------------------- /stubs/x86_32_stub.nasm: -------------------------------------------------------------------------------- 1 | [bits 32] 2 | start: 3 | mov ebx, 0xcccccccc 4 | mov ecx, ebx 5 | jmp real_start 6 | 7 | ; Align to STUB_SIZE. 8 | times (0x200 - ($ - start)) db 0x0 9 | real_start: 10 | 11 | -------------------------------------------------------------------------------- /examples/src/hello.asm: -------------------------------------------------------------------------------- 1 | ; Use nasm (netwide assembler) to compile this. 2 | [bits 32] 3 | 4 | call print_hello 5 | db "Hello World!", 0xa, 0 6 | 7 | print_hello: 8 | call [ebx+3*4] 9 | add esp, 4 10 | 11 | push 0 12 | call [ebx] 13 | 14 | -------------------------------------------------------------------------------- /examples/src/hello64.asm: -------------------------------------------------------------------------------- 1 | ; Use nasm (netwide assembler) to compile this. 2 | [bits 64] 3 | 4 | call print_hello 5 | db "Hello World!", 0xa, 0 6 | 7 | print_hello: 8 | call [rbx+3*8] 9 | add rsp, 8 10 | 11 | push 0 12 | call [rbx] 13 | 14 | -------------------------------------------------------------------------------- /stubs/stub_to_c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # A script that generates .c files that can be included by asmloader. 3 | import subprocess 4 | 5 | def generate_c_file(fname): 6 | print "Processing:", fname 7 | subprocess.check_call(['nasm', fname + ".nasm"]) 8 | 9 | with open(fname, "rb") as f: 10 | d = f.read() 11 | 12 | out_fname = fname + ".c" 13 | with open(out_fname, "w") as f: 14 | f.write("#pragma once\n\n") 15 | f.write("unsigned char STUB_%s[] = {" % fname) 16 | for i, ch in enumerate(d): 17 | if i % 8 == 0: 18 | f.write("\n ") 19 | 20 | comma = ", " 21 | if i == len(d) - 1: 22 | comma = "" 23 | 24 | f.write("0x%.2x%s" % (ord(ch), comma)) 25 | 26 | f.write("\n};\n") 27 | 28 | 29 | if __name__ == "__main__": 30 | for fname in [ 31 | "x86_32_stub", 32 | "x86_64_mswin_stub", 33 | "x86_64_linux_stub", 34 | ]: 35 | generate_c_file(fname) 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Usage**: 2 | `asmloader ` 3 | 4 | What does this do (in short): 5 | 1. It allocates read/write/execute memory. 6 | 2. Loads the specified file into it. 7 | 3. And redirects the CPU (EIP/RIP) to it (i.e. executes the binary code that was in the file). 8 | + Plus it provides a very minor API set. 9 | 10 | The `file.bin` should be pure machine code without any headers. The code will be loaded to a random page address + 0x200. In EBX/RBX register there will be a pointer to an array of functions: 11 | 12 | 0. `exit` 13 | 1. `putchar` 14 | 2. `getchar` 15 | 3. `printf` 16 | 4. `scanf` 17 | 18 | For this set of APIs please use a standard cdecl calling convention regardless of the platform (i.e. arguments to the stack, caller cleans the stack afterwards). Note that this includes the 64-bit platforms which usually make use of the fastcall convention (but asmloader has a set of wrappers to make the API consistent). 19 | 20 | If you would like to use the platform's default calling convention on 64-bits, note that the RCX register contains the same API table minus the converting wrappers, so just do: 21 | 22 | `MOV RBX, RCX` 23 | 24 | And you're set to go. Note that on 32-bit x86 cdecl is used all around anyway, so this is not required (and ECX contains the same value as EBX). 25 | 26 | For the record, platform-specific calling conventions: 27 | * Windows/Linux 32-bit: cdecl 28 | * Windows 64-bit: fastcall (Windows x64) 29 | * Linux 64-bit: fastcall (System V AMD64 ABI) 30 | 31 | See http://en.wikipedia.org/wiki/X86_calling_conventions for details. 32 | 33 | In the current version it's platform specific which registers are volatile (i.e. scratch registers) and which are non-volatile (i.e. callee-preserved registers) when using the built in API (though this may change in future versions). 34 | 35 | For exiting please use the exit function. Returning (via RET instruction) from the shellcode yields undefined behavior, i.e. it might work on some platforms/version of asmloader, and might not work on others. 36 | 37 | If you don't call exit, the program will crash. 38 | 39 | Have fun :) 40 | 41 | 42 | Changelog: 43 | 44 | * 0.0.2 -> 0.1.0: 45 | Added 64-bit support (Windows and Linux). Refactoring all around. 46 | 47 | * 0.0.1 -> 0.0.2: 48 | Added a warning in case source code file is detected as first argument. 49 | 50 | -------------------------------------------------------------------------------- /stubs/x86_64_linux_stub.nasm: -------------------------------------------------------------------------------- 1 | [bits 64] 2 | [org 0xcdcdcdcdcdcdc000] ; Used for pseudo-relocations. 3 | 4 | start: 5 | lea rbx, [rel jump_table] ; Wrapped API. 6 | lea rcx, [rel import_table] ; Platform-specific API. 7 | jmp real_start 8 | 9 | stub_exit: 10 | mov rdi, [rsp+8] 11 | jmp [rel import_exit] 12 | ; Should not return. 13 | 14 | stub_putchar: 15 | mov [rel saved_rdi], rdi 16 | mov rdi, [rsp+8] 17 | call [rel import_putchar] 18 | mov rdi, [rel saved_rdi] 19 | ret 20 | 21 | stub_getchar: 22 | jmp [rel import_getchar] 23 | 24 | stub_printf: 25 | ; Note: Floating points won't work, as there is no easy way to detect which 26 | ; argument on the stack is a floating point (and should be moved to xmm 27 | ; registers). If this is reaaaaaalllyyyyy needed in the future, one can 28 | ; write a format string parser to figure out where the %f/etc are 29 | ; placed. But that seems to complicated for a simple app like this one. 30 | push qword [rel import_printf] 31 | jmp vaarg_converter 32 | 33 | stub_scanf: 34 | push qword [rel import_scanf] 35 | jmp vaarg_converter 36 | 37 | ; Expects function-to-be-called's address on the stack. 38 | vaarg_converter: 39 | ; Order of arguments: rdi, rsi, rdx, rcx, r8, r9, 40 | mov [rel saved_rdi], rdi 41 | mov [rel saved_rsi], rsi 42 | mov [rel saved_rdx], rdx 43 | mov [rel saved_rcx], rcx 44 | mov [rel saved_r8], r8 45 | mov [rel saved_r9], r9 46 | 47 | pop rdx ; Function to be called. 48 | pop rax ; Return address. 49 | mov [rel saved_ret], rax 50 | mov rax, rdx 51 | 52 | mov rdi, [rsp+8*0] 53 | mov rsi, [rsp+8*1] 54 | mov rdx, [rsp+8*2] 55 | mov rcx, [rsp+8*3] 56 | mov r8, [rsp+8*4] 57 | mov r9, [rsp+8*5] 58 | 59 | call rax 60 | 61 | mov rdi, [rel saved_rdi] 62 | mov rsi, [rel saved_rsi] 63 | mov rdx, [rel saved_rdx] 64 | mov rcx, [rel saved_rcx] 65 | mov r8, [rel saved_r8] 66 | mov r9, [rel saved_r9] 67 | jmp [rel saved_ret] 68 | 69 | ; Attempt to move out the data part to another cache-line. 70 | times (0x100 - ($ - start)) db 0x00 71 | 72 | jump_table: 73 | dq stub_exit 74 | dq stub_putchar 75 | dq stub_getchar 76 | dq stub_printf 77 | dq stub_scanf 78 | 79 | import_table: 80 | import_exit: dq 0xc0dec0dec0de0000 81 | import_putchar: dq 0xc0dec0dec0de0001 82 | import_getchar: dq 0xc0dec0dec0de0002 83 | import_printf: dq 0xc0dec0dec0de0003 84 | import_scanf: dq 0xc0dec0dec0de0004 85 | 86 | storage_area: 87 | saved_rdi: dq 0 88 | saved_rsi: dq 0 89 | saved_rdx: dq 0 90 | saved_rcx: dq 0 91 | saved_r8: dq 0 92 | saved_r9: dq 0 93 | saved_ret: dq 0 94 | 95 | ; Align to STUB_SIZE. 96 | times (0x200 - ($ - start)) db 0x0 97 | real_start: 98 | 99 | 100 | -------------------------------------------------------------------------------- /stubs/x86_32_stub.c: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | unsigned char STUB_x86_32_stub[] = { 4 | 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0x89, 0xd9, 0xe9, 5 | 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 12 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 13 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 18 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 68 | }; 69 | -------------------------------------------------------------------------------- /stubs/x86_64_linux_stub.c: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | unsigned char STUB_x86_64_linux_stub[] = { 4 | 0x48, 0x8d, 0x1d, 0xf9, 0x00, 0x00, 0x00, 0x48, 5 | 0x8d, 0x0d, 0x1a, 0x01, 0x00, 0x00, 0xe9, 0xed, 6 | 0x01, 0x00, 0x00, 0x48, 0x8b, 0x7c, 0x24, 0x08, 7 | 0xff, 0x25, 0x0a, 0x01, 0x00, 0x00, 0x48, 0x89, 8 | 0x3d, 0x2b, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x7c, 9 | 0x24, 0x08, 0xff, 0x15, 0x00, 0x01, 0x00, 0x00, 10 | 0x48, 0x8b, 0x3d, 0x19, 0x01, 0x00, 0x00, 0xc3, 11 | 0xff, 0x25, 0xfa, 0x00, 0x00, 0x00, 0xff, 0x35, 12 | 0xfc, 0x00, 0x00, 0x00, 0xeb, 0x08, 0xff, 0x35, 13 | 0xfc, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x48, 0x89, 14 | 0x3d, 0xfb, 0x00, 0x00, 0x00, 0x48, 0x89, 0x35, 15 | 0xfc, 0x00, 0x00, 0x00, 0x48, 0x89, 0x15, 0xfd, 16 | 0x00, 0x00, 0x00, 0x48, 0x89, 0x0d, 0xfe, 0x00, 17 | 0x00, 0x00, 0x4c, 0x89, 0x05, 0xff, 0x00, 0x00, 18 | 0x00, 0x4c, 0x89, 0x0d, 0x00, 0x01, 0x00, 0x00, 19 | 0x5a, 0x58, 0x48, 0x89, 0x05, 0xff, 0x00, 0x00, 20 | 0x00, 0x48, 0x89, 0xd0, 0x48, 0x8b, 0x3c, 0x24, 21 | 0x48, 0x8b, 0x74, 0x24, 0x08, 0x48, 0x8b, 0x54, 22 | 0x24, 0x10, 0x48, 0x8b, 0x4c, 0x24, 0x18, 0x4c, 23 | 0x8b, 0x44, 0x24, 0x20, 0x4c, 0x8b, 0x4c, 0x24, 24 | 0x28, 0xff, 0xd0, 0x48, 0x8b, 0x3d, 0xa6, 0x00, 25 | 0x00, 0x00, 0x48, 0x8b, 0x35, 0xa7, 0x00, 0x00, 26 | 0x00, 0x48, 0x8b, 0x15, 0xa8, 0x00, 0x00, 0x00, 27 | 0x48, 0x8b, 0x0d, 0xa9, 0x00, 0x00, 0x00, 0x4c, 28 | 0x8b, 0x05, 0xaa, 0x00, 0x00, 0x00, 0x4c, 0x8b, 29 | 0x0d, 0xab, 0x00, 0x00, 0x00, 0xff, 0x25, 0xad, 30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x13, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 37 | 0x1e, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 38 | 0x38, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 39 | 0x3e, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 40 | 0x46, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 41 | 0x00, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 42 | 0x01, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 43 | 0x02, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 44 | 0x03, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 45 | 0x04, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 68 | }; 69 | -------------------------------------------------------------------------------- /stubs/x86_64_mswin_stub.c: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | unsigned char STUB_x86_64_mswin_stub[] = { 4 | 0x48, 0x8d, 0x1d, 0xf9, 0x00, 0x00, 0x00, 0x48, 5 | 0x8d, 0x0d, 0x1a, 0x01, 0x00, 0x00, 0xe9, 0xed, 6 | 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4c, 0x24, 0x08, 7 | 0x48, 0x83, 0xec, 0x20, 0xff, 0x25, 0x06, 0x01, 8 | 0x00, 0x00, 0x51, 0x48, 0x8b, 0x4c, 0x24, 0x08, 9 | 0x48, 0x83, 0xec, 0x20, 0xff, 0x15, 0xfe, 0x00, 10 | 0x00, 0x00, 0x48, 0x83, 0xc4, 0x20, 0x59, 0xc3, 11 | 0x48, 0x83, 0xec, 0x20, 0xff, 0x15, 0xf6, 0x00, 12 | 0x00, 0x00, 0x48, 0x83, 0xc4, 0x20, 0xc3, 0xff, 13 | 0x35, 0xf3, 0x00, 0x00, 0x00, 0xeb, 0x08, 0xff, 14 | 0x35, 0xf3, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x48, 15 | 0x89, 0x0d, 0xf2, 0x00, 0x00, 0x00, 0x48, 0x89, 16 | 0x15, 0xf3, 0x00, 0x00, 0x00, 0x4c, 0x89, 0x05, 17 | 0xf4, 0x00, 0x00, 0x00, 0x4c, 0x89, 0x0d, 0xf5, 18 | 0x00, 0x00, 0x00, 0x5a, 0x58, 0x48, 0x89, 0x05, 19 | 0xf4, 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x48, 20 | 0x8b, 0x0c, 0x24, 0x48, 0x8b, 0x54, 0x24, 0x08, 21 | 0x4c, 0x8b, 0x44, 0x24, 0x10, 0x4c, 0x8b, 0x4c, 22 | 0x24, 0x18, 0x48, 0x89, 0x15, 0xdf, 0x00, 0x00, 23 | 0x00, 0x4c, 0x89, 0x05, 0xe0, 0x00, 0x00, 0x00, 24 | 0x4c, 0x89, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0xff, 25 | 0xd0, 0x48, 0x8b, 0x15, 0xc8, 0x00, 0x00, 0x00, 26 | 0x4c, 0x8b, 0x05, 0xc9, 0x00, 0x00, 0x00, 0x4c, 27 | 0x8b, 0x0d, 0xca, 0x00, 0x00, 0x00, 0x48, 0x89, 28 | 0x54, 0x24, 0x08, 0x4c, 0x89, 0x44, 0x24, 0x10, 29 | 0x4c, 0x89, 0x4c, 0x24, 0x18, 0x48, 0x8b, 0x0d, 30 | 0x7c, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x15, 0x7d, 31 | 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x05, 0x7e, 0x00, 32 | 0x00, 0x00, 0x4c, 0x8b, 0x0d, 0x7f, 0x00, 0x00, 33 | 0x00, 0xff, 0x25, 0x81, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x13, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 37 | 0x22, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 38 | 0x38, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 39 | 0x47, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 40 | 0x4f, 0xc0, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 41 | 0x00, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 42 | 0x01, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 43 | 0x02, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 44 | 0x03, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 45 | 0x04, 0x00, 0xde, 0xc0, 0xde, 0xc0, 0xde, 0xc0, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 68 | }; 69 | -------------------------------------------------------------------------------- /stubs/x86_64_mswin_stub.nasm: -------------------------------------------------------------------------------- 1 | [bits 64] 2 | [org 0xcdcdcdcdcdcdc000] ; Used for pseudo-relocations. 3 | 4 | start: 5 | lea rbx, [rel jump_table] ; Wrapped API. 6 | lea rcx, [rel import_table] ; Platform-specific API. 7 | jmp real_start 8 | 9 | ; Note that Windows uses the funny calling convention that requires the caller 10 | ; to allocate space on the stack for the 4 arguments even if registers are used 11 | ; to actually pass them. This space is sometimes used by the callee functions to 12 | ; store the received arguments for various reasons, so it's important to 13 | ; allocate it. 14 | ; https://msdn.microsoft.com/en-us/library/ms235286.aspx 15 | 16 | stub_exit: 17 | mov rcx, [rsp+8] 18 | sub rsp, 0x20 ; It's exit, so technically this shouldn't matter. But in the 19 | ; rare case of somebody using local variables with an atexit- 20 | ; -registered function we'll include it here as well. 21 | ; Probably it will never happen though. 22 | jmp [rel import_exit] 23 | ; Should not return. 24 | 25 | stub_putchar: 26 | push rcx 27 | mov rcx, [rsp+8] 28 | sub rsp, 0x20 29 | call [rel import_putchar] 30 | add rsp, 0x20 31 | pop rcx 32 | ret 33 | 34 | stub_getchar: 35 | sub rsp, 0x20 36 | call [rel import_getchar] 37 | add rsp, 0x20 38 | ret 39 | 40 | stub_printf: 41 | push qword [rel import_printf] 42 | jmp vaarg_converter 43 | 44 | stub_scanf: 45 | push qword [rel import_scanf] 46 | jmp vaarg_converter 47 | 48 | ; Expects function-to-be-called's address on the stack. 49 | vaarg_converter: 50 | ; Order of arguments: rcx, rdx, r8, r9, 51 | mov [rel saved_rcx], rcx 52 | mov [rel saved_rdx], rdx 53 | mov [rel saved_r8], r8 54 | mov [rel saved_r9], r9 55 | 56 | pop rdx ; Function to be called. 57 | pop rax ; Return address. 58 | mov [rel saved_ret], rax 59 | mov rax, rdx 60 | 61 | ; Since printf is a vararg, we don't really know how many arguments are there. 62 | ; However, the calling convention requires that there is space for exactly 63 | ; four arguments on the stack. If this condition is not met, the callee might 64 | ; overwrite some variables of the calling function. Since there is no (nice) 65 | ; way to prevent this, a way around it is to save the 3 (fmt parameter is 66 | ; required) values somewhere, and restore them after function returns. 67 | mov rcx, [rsp+8*0] 68 | mov rdx, [rsp+8*1] 69 | mov r8, [rsp+8*2] 70 | mov r9, [rsp+8*3] 71 | mov [rel saved_stack_slot_1], rdx 72 | mov [rel saved_stack_slot_2], r8 73 | mov [rel saved_stack_slot_3], r9 74 | 75 | call rax 76 | 77 | mov rdx, [rel saved_stack_slot_1] 78 | mov r8, [rel saved_stack_slot_2] 79 | mov r9, [rel saved_stack_slot_3] 80 | mov [rsp+8*1], rdx 81 | mov [rsp+8*2], r8 82 | mov [rsp+8*3], r9 83 | 84 | mov rcx, [rel saved_rcx] 85 | mov rdx, [rel saved_rdx] 86 | mov r8, [rel saved_r8] 87 | mov r9, [rel saved_r9] 88 | jmp [rel saved_ret] 89 | 90 | ; Attempt to move out the data part to another cache-line. 91 | times (0x100 - ($ - start)) db 0x00 92 | 93 | jump_table: 94 | dq stub_exit 95 | dq stub_putchar 96 | dq stub_getchar 97 | dq stub_printf 98 | dq stub_scanf 99 | 100 | import_table: 101 | import_exit: dq 0xc0dec0dec0de0000 102 | import_putchar: dq 0xc0dec0dec0de0001 103 | import_getchar: dq 0xc0dec0dec0de0002 104 | import_printf: dq 0xc0dec0dec0de0003 105 | import_scanf: dq 0xc0dec0dec0de0004 106 | 107 | storage_area: 108 | saved_rcx: dq 0 109 | saved_rdx: dq 0 110 | saved_r8: dq 0 111 | saved_r9: dq 0 112 | saved_ret: dq 0 113 | saved_stack_slot_1: dq 0 114 | saved_stack_slot_2: dq 0 115 | saved_stack_slot_3: dq 0 116 | 117 | ; Align to STUB_SIZE. 118 | times (0x200 - ($ - start)) db 0x0 119 | real_start: 120 | 121 | 122 | -------------------------------------------------------------------------------- /asmloader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simplified Assembly Loader v.0.0.3 3 | * by gynvael.coldwind//vx 4 | * http://gynvael.coldwind.pl/ 5 | * 6 | * -- License Stuff 7 | * 8 | * Copyright (C) 2017 by Gynvael Coldwind 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | * 28 | * -- Usage 29 | * 30 | * Usage: 31 | * asmloader 32 | * 33 | * What does this do (in short): 34 | * 1. It allocates read/write/execute memory. 35 | * 2. Loads the specified file into it. 36 | * 3. And redirects the CPU (EIP/RIP) to it (i.e. executes the binary code that 37 | * was in the file). 38 | * + It provides a very minor API set. 39 | * 40 | * File.bin should be pure machine code without any headers. 41 | * Your code will be loaded to a random page address + 0x200. 42 | * In EBX/RBX register there will be a pointer to an array of functions: 43 | * 0 exit 44 | * 1 putchar 45 | * 2 getchar 46 | * 3 printf 47 | * 4 scanf 48 | * For this set of APIs please use a standard cdecl calling convention 49 | * regardless of the platform (i.e. arguments to the stack, caller cleans the 50 | * stack afterwards). Note that this includes the 64-bit platforms which 51 | * usually make use of the fastcall convention (but asmloader has a set of 52 | * wrappers to make the API consistent). 53 | * 54 | * If you would like to use the platform's default calling convention on 55 | * 64-bits, note that the RCX register contains the same API table minus the 56 | * converting wrappers, so just do: 57 | * MOV RBX, RCX 58 | * And you're set to go. Note that on 32-bit x86 cdecl is used all around 59 | * anyway, so this is not required (and ECX contains the same value as EBX). 60 | * 61 | * For the record, platform-specific calling conventions: 62 | * Windows/Linux 32-bit: cdecl 63 | * Windows 64-bit: fastcall (Windows x64) 64 | * Linux 64-bit: fastcall (System V AMD64 ABI) 65 | * See http://en.wikipedia.org/wiki/X86_calling_conventions for details. 66 | * 67 | * In the current version it's platform specific which registers are volatile 68 | * (i.e. scratch registers) and which are non-volatile (i.e. callee-preserved 69 | * registers) when using the built in API (though this may change in future 70 | * versions). 71 | * 72 | * For exiting please use the exit function. Returning (via RET instruction) 73 | * from the shellcode yields undefined behavior, i.e. it might work on some 74 | * platforms/version of asmloader, and might not work on others. 75 | * 76 | * If you don't call exit, the program will crash. 77 | * 78 | * Have fun :) 79 | * 80 | * 81 | * Changelog: 82 | * 83 | * * 0.0.2 -> 0.1.0: 84 | * Added 64-bit support (Windows and Linux). Refactoring all around. 85 | * 86 | * * 0.0.1 -> 0.0.2: 87 | * Added a warning in case source code file is detected as first argument. 88 | * 89 | * 90 | */ 91 | 92 | #include 93 | #include 94 | #include 95 | #include 96 | #include 97 | #include 98 | #ifdef _WIN32 99 | # include 100 | #elif defined(__unix__) || __APPLE__ 101 | # include 102 | #endif 103 | 104 | #define ARCH_UNKNOWN 0 105 | #define ARCH_X86_32 1 106 | #define ARCH_X86_64_MSWIN 2 107 | #define ARCH_X86_64_LINUX 3 108 | 109 | // To avoid dealing with multiple different linkers the stubs are directly 110 | // included. 111 | #include "stubs/x86_64_linux_stub.c" 112 | #include "stubs/x86_64_mswin_stub.c" 113 | #include "stubs/x86_32_stub.c" 114 | 115 | #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || \ 116 | defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) 117 | # if defined(_WIN32) || defined(__WIN32) 118 | # define ARCH ARCH_X86_64_MSWIN 119 | # elif defined(__unix__) || defined(__APPLE__) 120 | # define ARCH ARCH_X86_64_LINUX 121 | # else 122 | # error Unsupported or unrecognized architecture. 123 | # endif 124 | #endif 125 | 126 | #if defined(i386) || defined(__i386) || defined(__i386__) || \ 127 | defined(__IA32__) || defined(_M_IX86) || defined(_X86_) || defined(__X86__) 128 | # define ARCH ARCH_X86_32 129 | #endif 130 | 131 | #ifndef ARCH 132 | # error Unsupported or unrecognized architecture. 133 | #endif 134 | 135 | #define STUB_SIZE 0x200 136 | #define STUB_PAD 1 137 | 138 | typedef int (*func_t)(); 139 | 140 | size_t file_size(FILE *f) { 141 | size_t pos, len; 142 | pos = ftell(f); 143 | fseek(f, 0, SEEK_END); 144 | len = ftell(f); 145 | fseek(f, pos, SEEK_SET); 146 | return len; 147 | } 148 | 149 | size_t find_magic_offset(const void *data, size_t data_size, 150 | const void *magic, size_t magic_size) { 151 | assert(magic_size <= data_size); 152 | 153 | const uint8_t *byte_data = (const uint8_t*)data; 154 | for (size_t i = 0; i <= data_size - magic_size; i++) { 155 | if (memcmp(byte_data + i, magic, magic_size) != 0) { 156 | continue; 157 | } 158 | 159 | return i; 160 | } 161 | 162 | return -1; 163 | } 164 | 165 | void replace_magic(void *data, size_t data_size, 166 | const void *magic, size_t magic_size, 167 | const void *replacement) { 168 | assert(magic_size <= data_size); 169 | size_t offset = find_magic_offset(data, data_size, magic, magic_size); 170 | 171 | // In general, this function must never fail. 172 | if (offset == (size_t)-1) { 173 | fprintf(stderr, "fatal: magic replacement failed; file a bug\n"); 174 | abort(); 175 | } 176 | 177 | uint8_t *byte_data = (uint8_t*)data; 178 | memcpy(byte_data + offset, replacement, magic_size); 179 | } 180 | 181 | void apply_relocs(void *data, size_t data_size, size_t data_addr, 182 | size_t reloc_magic, size_t reloc_mask) { 183 | assert(sizeof(size_t) <= data_size); 184 | assert((reloc_magic & ~reloc_mask) == 0); 185 | 186 | uint8_t *byte_data = (uint8_t*)data; 187 | for (size_t i = 0; i <= data_size - sizeof(size_t); i++) { 188 | size_t value; 189 | memcpy(&value, byte_data + i, sizeof(size_t)); 190 | if ((value & reloc_mask) != reloc_magic) { 191 | continue; 192 | } 193 | 194 | // Apply relocation. 195 | value = value - reloc_magic + data_addr; 196 | memcpy(byte_data + i, &value, sizeof(size_t)); 197 | } 198 | } 199 | 200 | void prepare_stub(void *dst) { 201 | #if ARCH == ARCH_X86_64_LINUX 202 | memcpy(dst, STUB_x86_64_linux_stub, sizeof(STUB_x86_64_linux_stub)); 203 | #elif ARCH == ARCH_X86_64_MSWIN 204 | memcpy(dst, STUB_x86_64_mswin_stub, sizeof(STUB_x86_64_mswin_stub)); 205 | #endif 206 | 207 | #if ARCH == ARCH_X86_64_LINUX || ARCH == ARCH_X86_64_MSWIN 208 | static size_t func_arr[] = { 209 | (size_t)exit, (size_t)putchar, (size_t)getchar, 210 | (size_t)printf, (size_t)scanf 211 | }; 212 | 213 | for (size_t i = 0; i < sizeof(func_arr) / sizeof(*func_arr); i++) { 214 | size_t magic = 0xc0dec0dec0de0000ULL + i; 215 | replace_magic(dst, STUB_SIZE, &magic, sizeof(magic), &func_arr[i]); 216 | } 217 | 218 | apply_relocs(dst, STUB_SIZE, (size_t)dst, 219 | 0xcdcdcdcdcdcdc000ULL, 0xfffffffffffff000ULL); 220 | #elif ARCH == ARCH_X86_32 221 | static void *func_arr[] = { exit, putchar, getchar, printf, scanf }; 222 | uint32_t func_arr_ptr = (size_t)func_arr; 223 | memcpy(dst, STUB_x86_32_stub, sizeof(STUB_x86_32_stub)); 224 | replace_magic(dst, STUB_SIZE, "\xCC\xCC\xCC\xCC", 4, &func_arr_ptr); 225 | #endif 226 | } 227 | 228 | const char *load_binary(void **dst_data, size_t *dst_size, const char *fname) { 229 | const char *ret = NULL; 230 | FILE *f = NULL; 231 | void *data = NULL; 232 | size_t size = 0; 233 | size_t alloc_size; 234 | 235 | f = fopen(fname, "rb"); 236 | if(!f) { 237 | ret = "could not open input file"; 238 | goto err; 239 | } 240 | 241 | size = file_size(f); 242 | if(size == 0) { 243 | ret = "file of 0 size"; 244 | goto err; 245 | } 246 | 247 | alloc_size = STUB_SIZE + size + STUB_PAD; 248 | 249 | #ifdef _WIN32 250 | data = VirtualAlloc(NULL, alloc_size, MEM_COMMIT | MEM_RESERVE, 251 | PAGE_EXECUTE_READWRITE); 252 | #else 253 | data = mmap(NULL, alloc_size, PROT_EXEC | PROT_READ | PROT_WRITE, 254 | MAP_ANON | MAP_PRIVATE, -1, 0); 255 | #endif 256 | 257 | #ifdef _WIN32 258 | if(!data) { 259 | #else 260 | if(data == (void*)-1) { 261 | data = NULL; 262 | #endif 263 | ret = "could not allocate memory"; 264 | goto err; 265 | } 266 | 267 | if(fread((uint8_t*)data + STUB_SIZE, 1, size, f) != size) { 268 | ret = "read error"; 269 | goto err; 270 | } 271 | 272 | fclose(f); f = NULL; 273 | 274 | prepare_stub(data); 275 | 276 | // Set last byte to int3. 277 | ((uint8_t*)data)[size + STUB_SIZE] = 0xCC; 278 | 279 | *dst_size = size; 280 | *dst_data = data; 281 | 282 | return ret; 283 | 284 | err: 285 | if(f) fclose(f); 286 | #ifdef _WIN32 287 | if(data) VirtualFree(data, 0, MEM_RELEASE); 288 | #else 289 | if(data) munmap(data, alloc_size); 290 | #endif 291 | return ret; 292 | } 293 | 294 | bool is_file_ext(const char *filename, const char *ext) { 295 | const char *fileext; 296 | 297 | // Get the extension. 298 | fileext = strrchr(filename, '.'); 299 | if(!fileext) { 300 | 301 | // There is no extension. Were we looking for one? 302 | if(!ext || ext[0] == '\0') 303 | return true; 304 | 305 | // Yes, and there is none. 306 | return false; 307 | } 308 | 309 | fileext += 1; // Skip the dot. 310 | 311 | // Compare. 312 | #ifdef _WIN32 313 | return (bool)(stricmp(fileext, ext) == 0); 314 | #elif defined(__unix__) || __APPLE__ 315 | return (bool)(strcasecmp(fileext, ext) == 0); 316 | #endif 317 | } 318 | 319 | // It's easier to set a breakpoint if this is a separate function. 320 | int run(func_t func) { 321 | return func(); 322 | } 323 | 324 | int main(int argc, char **argv) { 325 | const char *ret; 326 | void *data; 327 | size_t size; 328 | func_t func; 329 | int fret; 330 | 331 | // Needs to be synchronized with ARCH_* constants. 332 | const char *architectures[] = { 333 | "???", 334 | "x86-32", 335 | "x86-64-mswin", 336 | "x86-64-linux", 337 | }; 338 | 339 | printf("Simplified Assembly Loader v.0.1.0 by gynvael.coldwind//vx\n" 340 | "Architecture: %s\n", architectures[ARCH]); 341 | 342 | if(argc != 2) { 343 | puts("usage: asmloader \n" 344 | "note : use nasm to compile .asm to .bin\n" 345 | " : e.g. nasm file.asm -o file.bin\n" 346 | " : asmloader file.bin\n" 347 | "note : double check the bitness/architecture"); 348 | return 1; 349 | } 350 | 351 | // A common mistake is to enter the source .asm file as an argument 352 | // instead of the compiled file. Display a warning in such case. 353 | if(is_file_ext(argv[1], "asm") || 354 | is_file_ext(argv[1], "nasm")) { 355 | printf("warning: are you sure \"%s\" is the file you want to execute?\n" 356 | " : it seems to be a source assembly file, while asmloader\n" 357 | " : needs the compiled version (with proper machine code)\n" 358 | " : (if your app will crash this is most likely the cause)\n", 359 | argv[1]); 360 | 361 | // Continue execution. 362 | } 363 | 364 | ret = load_binary(&data, &size, argv[1]); 365 | if(ret != NULL) { 366 | printf("error: %s\n", ret); 367 | return 2; 368 | } 369 | 370 | #if ARCH == ARCH_X86_64_LINUX 371 | printf("Code loaded at 0x%.16lx (%u bytes)\n", 372 | (uint64_t)data + STUB_SIZE, (uint32_t)size); 373 | #elif ARCH == ARCH_X86_64_MSWIN 374 | printf("Code loaded at 0x%.16I64x (%u bytes)\n", 375 | (uint64_t)data + STUB_SIZE, (uint32_t)size); 376 | #elif ARCH == ARCH_X86_32 377 | printf("Code loaded at 0x%.8x (%u bytes)\n", 378 | (uint32_t)data + STUB_SIZE, (uint32_t)size); 379 | #endif 380 | fflush(stdout); 381 | 382 | func = (func_t)data; 383 | fret = run(func); 384 | 385 | #ifdef _WIN32 386 | VirtualFree(data, 0, MEM_RELEASE); 387 | #else 388 | munmap(data, STUB_SIZE + size + STUB_PAD); 389 | #endif 390 | 391 | return fret; 392 | } 393 | 394 | --------------------------------------------------------------------------------