Assembly Language
Figure from https://cs.lmu.edu/~ray showing the basic parts of a program in Assembly.
- The sections correspond (sort of) to the sections we have seen in the executables, e.g.
.text
is for code,.data
is for constant data. - Labels are used for identifying instructions in the code (such as the start of the code or places we might want to jump to). Labels are also used for labeling constant strings.
]
To assemble we use:
nasm -f elf32 fileName.asm
to generate a 32-bit object filenasm -f elf64 fileName.asm
to generate a 64-bit object file
Simple examples
x86
; fileName: hw32.asm
; Minimal example invoking a system function (64 bits)
section .data
helloStr: db 'Hello, world!',0
section .text
global main
main:
mov eax, 4 ; eax = 4, means "call the write system call"
mov ebx, 1 ; ebx = 1 means "use the stdout"
mov ecx, helloStr ; ecx must contain the address of the string to be printed
mov edx, 14 ; edx must contain the string length
int 0x80
mov eax, 1 ; eax = 1 means "call exit fuction"
mov ebx, 0 ; ebx = 0 means "passing a 0 as argument"
int 0x80
Assuming that you name the file hw32.asm
, you can assemble using:
nasm -f elf32 hw32.asm
which generates hw32.o
Then link into an executable using:
ld -dynamic-linker -m elf_i386 /lib/ld-linux.so.2 -e main hw32.o -o hw32
AMD-64
; fileName: hw64.asm
; Minimal example invoking a system function (64 bits)
section .data
helloStr: db 'Hello, world!',0
section .text
global main
main:
mov rax, 1 ; rax = 1 for the write syscall
mov rdi, 1 ; rdi = 1, filedescriptor stdout
mov rsi, helloStr ; rsi = address of the string
mov rdx, 12 ; rdx = length of the string
syscall ; make the system call
mov rax, 60 ; use the _exit syscall
mov rdi,0 ; error code 0
syscall ; make syscall
Assuming that you name the file h64.asm
, you can assemble using:
nasm -f elf64 hw64.asm
ld -s -dynamic-linker /lib64/ld-linux-x86-64.so.2 -e main hw64.o -o hw64
Example using an external (non system call) function
; fileName: hwExt32.asm
; Minimal example invoking a library function (32 bits)
extern puts
section .data
helloStr: db 'Hello, world!',0
section .text
global main
main:
push helloStr
call puts
nasm -f elf32 hwExt32.asm
ld -lc -dynamic-linker -m elf_i386 /lib/ld-linux.so.2 -e main hwExt32.o -o hwExt32
; fileName: hwExt64.asm
; Minimal example invoking a library function (64 bits)
extern puts
section .data
helloStr: db 'Hello, world!',0
section .text
global main
main:
mov rdi, helloStr
call puts
nasm -f elf64 hwExt64.asm
ld -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 -e main hwExt64.o -o hwExt64
Display the content of the address pointed to by the ESP
x/wx $esp
which is the same as:
x/wx (char *) $esp
Display the content of the address pointed to by the ESP
x/s *( (char **) $esp)
Get the content pointed to by the $esp + 0x8
x/s *( (char **) ($esp + 0x8) )
Command line arguments in x86 stack
a.out
is a executable generated from a c Source fIle.
Here is gdb analyzing the call ./a.out uno dos tres
and breakpointed just after entering main
. Notice that the content of argv is at ESP + 12
.
[-------------------------------------code-------------------------------------]
0x80483d6 <frame_dummy+38>: jmp 0x8048350 <register_tm_clones>
0x80483db <main>: push ebp
0x80483dc <main+1>: mov ebp,esp
=> 0x80483de <main+3>: mov eax,0x0
0x80483e3 <main+8>: pop ebp
0x80483e4 <main+9>: ret
0x80483e5: xchg ax,ax
0x80483e7: xchg ax,ax
[------------------------------------stack-------------------------------------]
0000| 0xffffc9b8 --> 0x0
0004| 0xffffc9bc --> 0xf7e06637 (<__libc_start_main+247>: add esp,0x10)
0008| 0xffffc9c0 --> 0x4
0012| 0xffffc9c4 --> 0xffffca54 --> 0xffffccd6 ("/tmp/a.out")
0016| 0xffffc9c8 --> 0xffffca68 --> 0xffffccee ("XDG_SEAT=seat0")
Command line arguments in AMD-64 stack
a.out
is a AMD-64 binary generated from a C source file.
Here is gdb analyzing the call ./a.out uno dos tres
and breakpointed just after entering main
. Notice that the content of argv is at ESP + 24
.
[-------------------------------------code-------------------------------------]
0x4004d1 <frame_dummy+33>: jmp 0x400450 <register_tm_clones>
0x4004d6 <main>: push rbp
0x4004d7 <main+1>: mov rbp,rsp
=> 0x4004da <main+4>: mov DWORD PTR [rbp-0x4],edi
0x4004dd <main+7>: mov QWORD PTR [rbp-0x10],rsi
0x4004e1 <main+11>: mov eax,0x0
0x4004e6 <main+16>: pop rbp
0x4004e7 <main+17>: ret
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd720 --> 0x4004f0 (<__libc_csu_init>: push r15)
0008| 0x7fffffffd728 --> 0x7ffff7a2d830 (<__libc_start_main+240>: mov edi,eax)
0016| 0x7fffffffd730 --> 0x4
0024| 0x7fffffffd738 --> 0x7fffffffd808 --> 0x7fffffffdcd6 ("/tmp/a.out")
0032| 0x7fffffffd740 --> 0x4f7ffcca0
0040| 0x7fffffffd748 --> 0x4004d6 (<main>: push rbp)
0048| 0x7fffffffd750 --> 0x0
0056| 0x7fffffffd758 --> 0xed614e9c5c7408b8
[------------------------------------------------------------------------------]
[-------------------------------------code-------------------------------------]
0x40027b <exit@plt+11>: jmp 0x400250
0x400280 <main>: push rbp
0x400281 <main+1>: mov rbp,rsp
=> 0x400284 <main+4>: mov rdi,QWORD PTR [rsp+0x10]
0x400289 <main+9>: mov rdi,QWORD PTR [edi+0x8]
0x40028e <main+14>: call 0x400260 <puts@plt>
0x400293 <main+19>: mov edi,0x0
0x400298 <main+24>: call 0x400270 <exit@plt>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd808 --> 0x0
0008| 0x7fffffffd810 --> 0x4
0016| 0x7fffffffd818 --> 0x7fffffffdce2 --> 0x7500652f706d742f ('/tmp/e')
0024| 0x7fffffffd820 --> 0x7fffffffdce9 --> 0x736f64006f6e75 ('uno')
0032| 0x7fffffffd828 --> 0x7fffffffdced --> 0x7365727400736f64 ('dos')
0040| 0x7fffffffd830 --> 0x7fffffffdcf1 --> 0x4744580073657274 ('tres')
0048| 0x7fffffffd838 --> 0x0
0056| 0x7fffffffd840 --> 0x7fffffffdcf6 ("XDG_SEAT=seat0")
[------------------------------------------------------------------------------]
extern puts
global main
section .data
callDenied: db 'call denied!',0x0a,0
tooFew: db 'call small !',0x0a,0
section .text
main:
push ebp
mov ebp, esp
; write your code here -------------------------------
check_argc:
mov eax, [ebp + 4]
cmp eax, 1
jg check_argv1 ; we're ok
push tooFew
call puts
jmp done
; ----------------------------------------------------
check_argv1:
mov eax, [ebp+12]
movzx eax, byte [eax]
cmp al, 0x2e
jne do_execve
push callDenied
do_execve:
mov eax, 11 ; 11 is the system call number
mov ebx, [ebp+12] ; ebp+12 is the address of argv[1]
lea ecx, [esp+08] ; esp + 0x8 is the address of the argv
mov edx, 0
int 0x80 ; int 0x80 is the invocation to the system call
done:
leave
ret
nasm -f elf32 execve.asm; ld -m elf_i386 -lc -dynamic-linker /lib/ld-linux.so.2 -e main execve.o -o execve