Assembly Hack (x64):
ALERT: If there are grammatical errors or logical errors, please let us know, thank you.
Very often we are told that to “pierce” a computational system, we must use Exploit.
True, in many cases the use of these leads to a bad advantage.
ShellFl0w does not teach you how to use exploits, as it would be trivial.
Give a fish to a man and nourish him for a day. Teach him to fish and feed him all his life.
This aphorism is the exact reason we must undertake, as only through our knowledge we are able to build a plan to exploit a vulnerability, we will learn how Exploit is planned and how to develop, exploitation writing requires knowledge not trivial in the programming field, so we will write about the Assembly code, with the NASM assembler.
Have fun with Assembly:
NASM, or Netwide Assembler, is a free Intel x86 assembler software that can be used to write 16-bit, 32-bit (IA-32) and 64-bit (x86-64) programs. We will use this!
First of all, we write what is our code, so just copy and paste it now.
ALERT: I work here with the 64-bit log, and on Linux, other software architectures may be a problem
section .data msg item "Hello, World!", 10 section .text global _start _start: mov rax, 1 mob rdi, 1 mov rsi, msg mov rdx, 16 syscall mov rax, 60 mov rdi, 0 syscall
msg item "Hello, World!", 10
msg is the name assigned to the address in memory, when we called “msg” we will get its position.
db is Define Byte, it means that we define some raw bytes of data to be inserted then in the code.
“Hello, World!” are the data bytes that we have defined
the “10” end is included in the defined data bytes, and it is pointing to a new line (a new line, essentially)
For now, we are only interested in full logs and xmm registers. You should already know what the registers are, but here’s a brief review. The 16 full registers are 64-bit wide and are called:
R 0 R 1 R 2 R 3 R 4 R 5 R 6 R 7 R 8 R 9 R 10 R 11 R 12 R 13 R 14 R 15 RAX RCX RDX RBX RSP RBP RSI RDI
When we write about assembly code we can decide to access logs, the larger the system architecture is larger are the registers.
Registers are part of the processor that temporarily holds the memory, in architects x86_64, the registers hold 64 bits.
Later we will clearly work with the remaining architectures, which will be useful again.
When processes are loaded into memory, they are usually divided into small sections. In fact, there are six main sections that some will be covered in this article, others later.
The .text section in base matches the .text portion of a binary executable file.
It contains instructions that the machine will have to perform.
The .data section contains the values of the initialized “variables”.
in our case: msg
A system call, or a syscall, is when a program requests a service from the kernel. System calls vary between operating systems for obvious reasons, each different operating system uses a different kernel.
All syscalls have an ID associated with a number.
If you are interested (and should) I recommend reading the syscall list, which can easily be found on the internet, but maybe I do an article at the end of the chapter.
In this case, we will use a syscall (sys_write) that will allow us to display a string, then output a “variable”, ergo print.
mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, 16 syscall
This portion of code follows this logic:
1] In the log: “rax”, we will insert the affected syscall ID, in this case: sys_write having as ID: 1, then rax == 1.
2] In the log: “rdi”, we will insert the first topic of the file_descriptor, we have these options: 0,1,2; For 0, the input standard is 1 for standard output, 2 for standard error. Of course, the error, or the logical thinking of the error (what is meant by error) is defined by the programmer. In this case, we will insert 1, because our interest is the output.
3] In the log: “rsi”, we will insert the “buffer”, in this case, our string: msg.
4] In the log: “rdx”, the so-called “count”, that is the buffer lenght (msg), the quantity of byte that we will to print (msg + 15).
5] We will close with syscall, the call to the kernel.
mov rax, 60 mov rdi, 0 syscall
This part of the code deals with the ret, that is, the classic return we can see in C:
1] In the log: “rax”, we will insert the ID (60) equivalent to sys_exit, to exit.
2] The syscall parameter is inserted, in “ rdi ” we will insert 0 because we do not have error codes.
global _start _start:
This is very important for our program, so let’s say the assembler analyzes and tries to find _start because, thanks to it knows exactly where to go, that is from that label!
in this global service, for this purpose, globalization of the label is possible.
┌─[freenix@sec]─[~] └──╼ $ nasm -felf64 code.asm // Assembly ┌─[freenix@sec]─[~] └──╼ $ ld code.o -o result // Linking ┌─[freenix@sec]─[~] └──╼ $ ./result // Execute Hello world!
In the next article, we can see other things about Assembly!