Now that I’m making progress, I wanted to share the code and descriptions for assembly Hello World.
Assembly Hello World – Introduction
I’ve taken the SecurityTube Linux Assembly Expert (SLAE) course for the past few weeks, and I’m really enjoying it.
That means that I’ll definitely have a smattering of assembly posts in the works, so stay tuned!
This post will cover the Linux x86 assembly “Hello World” program, and a bit about how it works/debugging it.
Hello World – The Code
First, I’ll start by just sharing my final application code. It is very well commented, but I’ll also explain it a bit further below.
; HelloWorld.nasm ; Author: Ray Doyle ; Global identifier - identifies that "_start" is the entry point global _start ; Text section - where the program code lives section .text ; The entry point of the program _start: ; ; Print "Hello World!" on the screen ; ; Move the value 4 into EAX (system call for write) mov eax, 4 ; Move the value 1 into EBX (fd1 = STDOUT) mov ebx, 1 ; Move the pointer to the string into ECX via its label mov ecx, message ; Move the value 12 into EDX (length of "Hello World!") ;mov edx, 12 mov edx, mlen ; Send an 0x80 interrupt to invoke the system call int 0x80 ; ; Exit the program gracefully ; ; Move the value 1 into EAX (system call for exit) mov eax, 1 ; Move the value 5 into EBX (arbitrary value for exit status) mov ebx, 5 ; Send an 0x80 interrupt to invoke the system call int 0x80 ; Data section - where all the initialized data is located section .data ; Defining and storing the "Hello World!" string ; Label "message" used for this string ; db = define byte or series of bytes message: db "Hello World!" ; Define an mlen value that is equal to the length of message ; This is a shortcut that NASM understands and computes mlen equ $-message
While this post/blog isn’t an assembly tutorial, there are a few things that I want to cover.
First, the .text section is where the actual application lives, and the .data section is where the application stores initialized data.
Next, the main method of printing “Hello World!” is to call the sys_write followed by the sys_exit syscalls. For more information on i386 Linux system calls, you can visit the following reference.
You load the parameters for system calls into EAX, EBX, ECX, and EDX in order.
For example, the sys_write syscall takes 3 parameters: unsigned int fd, char * buf, size_t count. In this case, I’m loading 4 into EAX (the number for sys_write), 1 into EBX (fd1 is STDOUT), my message variable (the actual character buffer) into ECX, and mlen (the calculated length of my string) into EDX.
Once the program has loaded all the registers, I make a call to interrupt 0x80. This is the most common method of making a syscall.
After my sys_write is called, I follow the same steps for sys_exit, so that the program exits cleanly.
Compiling, Linking, Running, and Debugging
Once I finished my program, it was time to get it executable.
First, I used NASM to compile the application into an object file.
Next, I used ld to link the object file into an actual executable.
Finally, I ran the application and verified the exit status (which I set as 5).
As you can see, this is fairly long for a “Hello World” program. That said, I wanted to add plenty of comments as I went along, so that I was sure that I understood it.
doyler@slae:~/slae/module1-4$ nasm -f elf32 -o HelloWorld.o HelloWorld.nasm doyler@slae:~/slae/module1-4$ ld -o HelloWorld HelloWorld.o doyler@slae:~/slae/module1-4$ ./HelloWorld Hello World! doyler@slae:~/slae/module1-4$ echo $? 5 doyler@slae:~/slae/module1-4$ wc -l HelloWorld.nasm 54 HelloWorld.asm
Now that I had a working program, it was time to do some debugging.
As with most applications on Linux, I prefer to use GDB.
First, I set a breakpoint on the _start entry point of the application.
When the program hit my breakpoint, I took a quick look at the disassembly to verify that it was the same as what I wrote in my .nasm file.
Next, I took a quick look at the registers (i r = info registers) to verify where EIP was pointing and that the CPU had loaded 0x4 into EAX.
Finally, I looked at the string representation of the memory address that the program would load into ECX. As expected, this was my “Hello World!” string.
doyler@slae:~/slae/module1-4$ gdb -q HelloWorld Reading symbols from /home/doyler/slae/module1-4/HelloWorld...(no debugging symbols found)...done. (gdb) break _start Breakpoint 1 at 0x8048080 (gdb) r Starting program: /home/doyler/slae/module1-4/HelloWorld Breakpoint 1, 0x08048080 in _start () (gdb) set disassembly-flavor intel (gdb) disass Dump of assembler code for function _start: => 0x08048080 <+0>: mov eax,0x4 0x08048085 <+5>: mov ebx,0x1 0x0804808a <+10>: mov ecx,0x80490a4 0x0804808f <+15>: mov edx,0xc 0x08048094 <+20>: int 0x80 0x08048096 <+22>: mov eax,0x1 0x0804809b <+27>: mov ebx,0x5 0x080480a0 <+32>: int 0x80 End of assembler dump. (gdb) stepi 0x08048085 in _start () (gdb) i r eax 0x4 4 ecx 0x0 0 edx 0x0 0 ebx 0x0 0 esp 0xbffff3e0 0xbffff3e0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x8048085 0x8048085 <_start+5> eflags 0x202 [ IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) x/s 0x80490a4 0x80490a4 <message>: "Hello World!"
Assembly Hello World – Conclusion
While assembly is definitely something newer to me, I’m really looking forward to this course.
I definitely have a few post ideas in mind, and that is not counting the SLAE final exam.
While these skills are only partially relevant to my current role, they should help a ton with my exploit development. I’ve already completed the GXPN, but I will be starting the OSCE once this course is over!