NASM and friends

Welcome to the first/second blog post on the scorch security blog. After the relative failure of the first blog post, I took down the site until I had the time to write another one. Without further ado, let us begin:

Recently, I’ve been dabbling in nasm. For the uninitiated, nasm is an assembly that is liked by many because of the simplicity of its syntax and its powerful preprocessor. Soon after picking it up, I realized that a simple, yet powerful standard library was needed. Since I switch between linux and windows regularly and I’m writing nasm on linux, syscalls are the main/only way to interface with anything outside of the process’ address-space. It’s not hard to call syscalls, but it gets rather repetitive quite quickly, especially if you are working on a large project. With this in mind, I decided to implement a simple standard library for nasm on linux that can be easily expanded for difference architectures and operating systems (I’m on a x86-x64 laptop running Ubuntu, but coding in x86 nasm).

Currently, it consists of a few .inc files that implement a number of syscalls, simple threading, and other useful functions like sbrk (similar to malloc) and memcpy.

The library isn’t perfect and it has a few bugs, particularly with threading. For example, a thread will sometimes crash when run in gdb. Also, most syscalls aren’t implemented, (let’s be honest here, there’s almost 200) but it’s very easy to add new ones and the process is abstracted enough that moving them over to x86-x64 assembly would be quite easy and painless.

Additionally, this library can be used in shellcode (it’s not null free though), if you are careful to include the .inc files somewhere in the code, rather than before it.

Some sample code is: (and yes, I tested it)

global _start
; _start goes first
_start:
    jmp main

%include "syscall.inc"
%include "thread.inc"
;%include "utils.inc"

main:
	thread.create child
	thread.join eax

parent:
    sys.write stdout, msg, msglen
    sys.exit 0
child:
    sys.write stdout, childmsg, childlen
    sys.exit 0
    

msg db "Parent...", 0xa
msglen equ  $ - msg
childmsg db "Child...", 0xa
childlen equ $ - childmsg

Compiled with:

> nasm -f elf thread.asm
> ld -m elf_i386 -o thread thread.o
> ./thread
Child...
Parent...

Threading and utils require the syscall.inc file, but you can just include syscall.inc without thread.inc or utils.inc.


Internals:

The syscalls are implemented rather simply as macros.

An example syscall is:

%macro sys.write 3
stackpatch_start
    mov edx, %3
    mov ecx, %2
    mov ebx, %1
    mov eax, SYS_WRITE
    syscall             ; syscall is a macro that resolves to "int 80h"
stackpatch_end
%endmacro

stackpatch_start and stackpatch_end are optional macros that restore the stack to its’ original value when “CLEAN_STACK” is defined. Some syscalls have problems when “CLEAN_STACK” is defined, so it’s not necessary. All syscalls have a prefix of “sys.” and all threading macros have a prefix of “thread.“.

Threading was a bit difficult to implement, largely because I made a typo in the clone syscall and accidentally called the close syscall. (This took way longer than it should’ve to figure out) I happened upon this blog which really helped (I did have to port from x86-x64 to x86).

This main threading func:

thread:                                 ; thanks to "http://nullprogram.com/blog/2015/05/15/".
    call .create_stack                  ; addr of stack in eax
    lea ecx, [eax + STACK_SIZE - 4]     ; ebx should now be the top of the new stack
    pop dword [ecx]                     ; pop func-to-thread onto top of new stack
    ; therefore, when eip hits ret, it will return to the new function 
    sys.clone CLONE_ALL, ecx, 0, 0, 0   ; returns 0 if this is the new thread
    ret

As you can see, abstracting the syscalls really helps with readability. This uses a cool way to send the newly-created thread to the supplied func-to-thread by placing it on the top of the new stack, so when the new thread hits ret, it will return to the supplied function.

Also, here is the link to the github repository.


If anyone has any suggestions, criticism, or needs help, please post a comment or contact me as per the contact page. I plan on expanding this library and any suggestions of what to implement are welcome.

Leave a comment