-
Writing programs in x86-64 ASM and pwncollege embryoasm writeup
Before reading this, it’s an advice to please read previous article of ASM series.
So now that we know some basics of registers and syscalls. We will move onto the part where we use our newfound knowledge to write some assembly code.
The following ASM code is specific to GAS (GNU Assembler)
Step by Step Hello world ASM program breakdown
.section .text .intel_syntax noprefix .global _start _start: mov rax, 1 lea rsi, [rip+str] mov rdx, 13 syscall mov rax, 60 mov rdi, 0 syscall str: .string "Hello world\n"Now in my first article, I explained different sections/mapping of memory. Most important sections among those are
.textsection and.data, because it is.textwhere we write code and.datawhere we define variables and constants.In the above hello world program, we are only using the
.textsection and keeping the code as minimal and simple as possible.So in the first line we are defining the section. In order to define a section we do
.section <section name>In our case, as we are only using
.text:.section .textNow because we are using GAS, the default ASM sytax is AT&T but we are writing in intel syntax so we need to specify that to the assembler. We do this using :
.intel_syntax noprefix.globalis GAS directive which helps in defining symbols in object file. Every ASM code must have a_startsymbol. It defines the entry point of ASM code.In GAS we do all this using :
.global _start # first we define a symbol _start : # then we mark the entry pointOh ! by the way, we use
#in GAS for comments.MOV instruction
The
movinstruction is the very basic and is used extensively in a assembly program. It is used to copy/move data from one register to another. In intel, it works in the following way :mov <destination register> , <source register>For example we need to copy number 6263 in register
rax, We’ll do :mov rax, 6263 # rax = 6263LEA instruction
The
leainstruction is used to copy some address in some register.lea <destination register> , <source effective address>This is also used extensively because we are loading effective address, So we can also do math in one instruction itself and assembler will understand it and assemble it for us. In
movinstruction it’s not possible.SYSCALL instruction
syscall instruction, as name says, is used for making system calls.
Main Hello world code
Now to write something on screen, we need to write on stdout (it’s file descriptor is 1). So in total we need to do 2 syscalls (write and exit syscalls).
To do write syscall we need to give it some arguments. We give arguments based on calling convention (Discussed in previous article) .

We can either use a good website or if you are a console fan then method used in previous article to get syscall number and to see arguments use 2nd page of
mancommand.
echo SYS_write | gcc -include sys/syscall.h -E -So, putting everything together and writing a subroutine for
writesyscall1st argument : fd (File descriptor which in our case is 1 for stdout)
2nd argument : buf (Buffer, Address of info which has to be written on screen ?)
3rd argument : count (Buffer size)All these arguments have to be set according to calling convention.
mov rax, 1 # syscall code is set through rax register mov rdi, 1 # set fd to stdout (1) lea rsi, [rip+str] # use rip (instruction pointer) to access label str mov rdx, 13 # Hello world\n\0 size = 13 syscall # perform syscallLabel
stris basically a space in memory where “hello world” is stored in form of bytes.leainstruction will calculate the address of the start of buffer usingripregister (instruction pointer).I recommend you to write the
exitsubroutine without looking at my code.Exit subroutine :
mov rax, 60 # syscall code for exit is 60 mov rdi, 0 # return address of exit syscall # perform syscallSo to putting all the pieces together and we get our assembly code :
.section .text .intel_syntax noprefix .global _start _start: mov rax, 1 lea rsi, [rip+str] mov rdx, 13 syscall mov rax, 60 mov rdi, 0 syscall str: .string "Hello world\n"I hope after reading this, you would have understood assembly and basic concepts related to memory. Now like any other language, assembly is just about practice, pratice and practice. Once you master it, I guarantee, assembly and C will become your favorite language.
Pwn.College Embryoasm Writeup
I have already started the instance, so let’ connnect
ssh -i ~/.ssh/key.pub hacker@dojo.pwn.college.
So this is easy. As explained above. We can just do
mov rdi, 0x1337full code :
.section .text .intel_syntax noprefix .global _start _start : mov rdi, 0x1337First we assemble it and compile it into an ELF then we will convert copy bytes of that ELF in a different file.
to do so :
gcc -nostdlib -static exp.s -o exp objcopy --dump-section .text=exp.bin expThen we will pipe the bytes into the challenge.

We can also do this using python script through pwntools.
Python script :
#!/usr/bin/env python3 import pwn pwn.context.log_level = "INFO" pwn.context.encoding = "latin" pwn.context.arch = "amd64" pwn.warnings.simplefilter("ignore") assembly = """mov rdi, 0x1337""" proc = pwn.process("/challenge/embryoasm_level1") print(proc.readrepeat(1).decode()) proc.send(pwn.asm(assembly)) print(proc.readrepeat(1).decode())In future I’ll write some interesting articles on some more instructions in ASM, file operations through assembly, shellcoding and operating system design.
A wise man👨💻 (check out his blog) once said to me, “its almost like playing lego … you have to put the pieces together …”
On that note,
Signing out