add hacking blogposts as they are

This commit is contained in:
oxeo0 2025-05-07 01:02:00 +02:00
parent fa65088be1
commit 325b9c3814
1904 changed files with 91353 additions and 0 deletions

33
asm/0.md Normal file
View file

@ -0,0 +1,33 @@
# Assembly x86_64 -
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 0.asm
## Compiling
Here we're going to use nasm to compile our assembly code:
` ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()

86
asm/1.md Normal file
View file

@ -0,0 +1,86 @@
# Assembly x86_64 - Hello World!
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 0.asm
section .data
text db "Hello, World!",10
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
## Compiling
Here we're going to use nasm to compile our assembly code:
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ nasm -f elf64 0.asm -o 0.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ls -lash
total 16K
4.0K drwxr-xr-x 2 nothing nothing 4.0K Mar 2 16:17 .
4.0K drwxr-xr-x 5 nothing nothing 4.0K Mar 2 16:01 ..
4.0K -rw-r--r-- 1 nothing nothing 179 Mar 2 16:09 0.asm
4.0K -rw-r--r-- 1 nothing nothing 848 Mar 2 16:17 0.o
Now we have our 0.asm code and the 0.o object file, now we need to link it using the gnu linker (ld) to make an executable file
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ld 0.o -o 0
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ls -lash
total 28K
4.0K drwxr-xr-x 2 nothing nothing 4.0K Mar 2 16:19 .
4.0K drwxr-xr-x 5 nothing nothing 4.0K Mar 2 16:01 ..
12K -rwxr-xr-x 1 nothing nothing 8.7K Mar 2 16:19 0
4.0K -rw-r--r-- 1 nothing nothing 179 Mar 2 16:09 0.asm
4.0K -rw-r--r-- 1 nothing nothing 848 Mar 2 16:17 0.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ file 0
0: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
and now we have our executable file called '0', we make it executable with chmod +x and then execute it:
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ chmod +x 0
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ./0
Hello, World!
And that concludes our first assembly code! in the next part we're going to explain everything about this code [here](2.html).

136
asm/2.md Normal file
View file

@ -0,0 +1,136 @@
# Assembly x86_64 - Hello World Explained
## Assembly Code
in the previous tutorial we made the following code:
section .data
text db "Hello, World!",10
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
now let's explain what this code is about piece by piece:
section .data
text db "Hello, World!",10
here 'db' stands for 'define bytes', this means we define raw data to insert into our code
after 'db' this is the bytes of data we are defining, each character in the string of text is a single byte. the '10' is a newline character, which can be represented as '\n'
the 'text' part is a name assigned to the address in memory that this data is located in. Whenever we use "text" later in the code, this will act as the memory address of the data 'db' that we defined, This is like putting a label on the memory address that contains the bytes define.
Registers are a part of the processor that temporarily holds memory, in the x86_64 architecture, registers hold 64 bits.
This means that each register can hold the values on its own, the main registers we will make use of are the following:
1. rax
2. rbx
3. rcx
4. rdx
5. rsi
6. rdi
7. rbp
8. r10
9. r9
10. r8
Now we also make use of a systemcall (abbreviated to syscall) which is used when a program requests a service from the kernel. Different Operating Systems mean different Kernels which means different Syscalls, they are not the same depending on the OS. All syscalls have an ID associated with them which is a number. Syscalls also take arguements which are inputs.
Now if you want to use syscalls, you first need the ID of the syscall and then you must know what arguements to give it, But you also need to know which registers correspond to the ID and to the arguements, so remember this table right here:
**
1. rax = syscall ID
2. rdi = arg 1
3. rsi = arg 2
4. rdx = arg 3
5. r10 = arg 4
6. r8 = arg 5
7. r9 = arg 6
**
Now where do we find informations about these syscalls ?We can use the list of them right [here ](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md) this is a very well made list made by Chromium OS Docs.
![](img/0.png)
in the code we used we basically used the 'write' syscall whose id is 1.
Therefore we set the rax register to 1 because that's our syscall id:
in the first arguement is a variable referenced in the docs as 'fd' which stands for file descriptor, we set that one to 1:
in the second arguement is our text variable we defined earlier, and the last arguement is a limit for the size of our text output (in characters) being set to 14. so we get the following code:
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, 14
syscall
Now the thing is we have yet another syscall after our hello world write syscall:
mov rax, 60
mov rdi, 0
syscall
And here we have an 'exit' syscall to end our executable.
![](img/1.png)
and thus we get resulting final code:
section .data
text db "Hello, World!",10
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
Most x86_64 assembly code have 3 sections, the .data section , the .bss section and the .text section. the label we used here _start acts like a function, everytime we will use the word _start in our code, it is going to execute the portion of code that's associated with it.
In the next subject we're going to dig into jumps, calls and comparaisons, you can click [here](3.html).

104
asm/3.md Normal file
View file

@ -0,0 +1,104 @@
# Assembly x86_64 - Jumps, Calls
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 3.asm
section .data
mytext db "Hello, World!", 10
section .text
global _start
_start:
call _printHello
mov rax, 60
mov rdi, 0
syscall
_printHello:
mov rax, 1
mov rdi, 1
mov rsi, mytext
mov rdx, 14
syscall
ret
Now let's examine what our code does:
section .data
mytext db "Hello, World!", 10
section .text
global _start
As we saw in the previous tutorial, these are the 2 initial sections, in the first .data section we define our constants (here there is mytext which contains the "Hello, World!" string of text with a newline character (represented as 10 or "\n")). Then we define the label _start to be globally accessible as a function under the .text section.
_start:
call _printHello
mov rax, 60
mov rdi, 0
syscall
Here is our main function called _start, and in it we use a call, this is used to basically use another label (or function) that contains code. And then after that we make use of the syscall whose id is 60 which is the exit syscall and with the arguement 0. Which makes our binary exit with the code 0 after the function _printHello is executed.
_printHello:
mov rax, 1
mov rdi, 1
mov rsi, mytext
mov rdx, 14
syscall
ret
In here as we explained in the previous tutorial, we use the syscall id (rax) 1, with the first arguement (rdi) set as 1, the second arguement (rdi) contains our 'mytext' constant ("Hello, World !" with a newline character), and lastly the third arguement (rdx) is the limit of the text we want to print out (here its 14 characters).
When you use the call instruction, you basically fetch another function (or label) of your choice, in this function you can return to the original position of where the call was made with the 'ret' instruction like we put at the end of the _printHello function.
## Compiling
Here we're going to use nasm and ld to compile our assembly code, and then we just execute it and see that our hello world is printed out:
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ nasm -f elf64 3.asm -o 3.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ cat 3.o
@0!'Hello, World!
<****H.data.text.shstrtab.symtab.strtab.rela.text3.asmmytext_start_printHello%
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ld 3.o -o 3
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ls -lash | grep 3
12K -rwxr-xr-x 1 nothing nothing 8.7K Mar 2 20:01 3
4.0K -rw-r--r-- 1 nothing nothing 219 Mar 2 20:00 3.asm
4.0K -rw-r--r-- 1 nothing nothing 896 Mar 2 20:00 3.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ./3
Hello, World!
In the next tutorial we will see how to get user input, you can click [here](4.html).

122
asm/4.md Normal file
View file

@ -0,0 +1,122 @@
# Assembly x86_64 - User Input
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 4.asm
section .data
mytext1 db "What is your name? "
mytext2 db "Hello, "
section .bss
myname resb 16 ; we reserve 16 bytes and we can access it with the label 'myname'
section .text
global _start
_start:
call _printText1
call _getName
call _printText2
call _printName
mov rax, 60
mov rdi, 0
syscall
_printText1: ;print 'what your the name ?'
mov rax, 1 ; syscall ID 1 (write text)
mov rdi, 1 ; first arg = 1
mov rsi, mytext1 ; second arg = our text1 (what is your name?)
mov rdx, 19 ; third arg = the text limit
syscall ;run the syscall
ret ; finish the function
_getName: ;get user input
mov rax, 0 ; syscall ID 0 (read user input)
mov rdi, 0 ; first arg 0 is stdin, 1 is stdout, 2 is stderr
mov rsi, myname ; second arg (where will we store user input?)
mov rdx, 16 ; third arg the limit of user input characters we want
syscall ;make the syscall
ret ;finish the function
_printText2: ;print 'Hello'
;same as printtext1
mov rax, 1
mov rdi, 1
mov rsi, mytext2
mov rdx, 7
syscall
ret
_printName: ;print the name
;same as pritntext 1 and 2
mov rax, 1
mov rdi, 1
mov rsi, myname ; this is the myname label with it's 16 reserved bytes from earlier
mov rdx, 16
syscall
ret
Now this code contains what we learned previously, with the exception of the following chunks of code:
section .bss
myname resb 16
this is used to declare a variable called 'myname' and we reserve 16 bytes for it. Ideally to store our user input string of text.
_getName:
mov rax, 0 ; syscall ID 0 (read user input)
mov rdi, 0
mov rsi, myname
mov rdx, 16
syscall
ret
The _getName function first sets the rax register as 0 (syscall ID 0) to read the user input, more info [here](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md)
the first arguement (rdi) is set to 0 because we want stdin (1 is stdout and 2 is stderr)
the second arguement (rsi) is the variable we want to store our user input to,
the third arguement (rdx) is set to 16 because that is the maximum size of reserved bytes for our 'myname' variable.
and lastly we just run the syscall and end the function.
## Compiling
Here we're going to use nasm to compile our assembly code and then use ld to create the binary out of the .o file:
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ nasm -f elf64 4.asm -o 4.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ld 4.o -o 4
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ./4
What is your name? Pierre
Hello, Pierre
And that's it ! in the next tutorial we will cover math operations and the stack, you can click [here](5.html).

88
asm/5.md Normal file
View file

@ -0,0 +1,88 @@
# Assembly x86_64 - Math operations
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 5.asm
section .data
digit db 0, 10
section .text
global _start
_start:
mov rbx, 48 ;48 in the ASCII chart is the "0" character
call _printRAX ;print "0" + 1
call _printRAX ;print "1" + 1
call _printRAX ;print "2" + 1
call _printRAX ;print "3" + 1
call _printRAX ;print "4" + 1
mov rax, 60
mov rdi, 0
syscall
_printRAX:
add rbx, 1 ; we increment rbx by 1 (48, 49, 50, 51, ...)
mov [digit], rbx ; we move the current value of rbx into the 'digit' memory address
mov rax, 1 ; we use the syscall ID 1
mov rdi, 1 ; we set the first arg to 1
mov rsi, digit ; the second arg is set to be our 'digit' memory address
mov rdx, 2 ; the third arg is the length of 2 bytes (let's not forget the newline char which is the '10' above)
syscall
ret
Now let's check what's new in the code:
mov [digit], rbx
Here we are moving the rbx register into the memory address that's referenced by the 'digit' label.
mov rbx, 48
add rbx, 1
mov [digit], rbx
Now first we set the value of rbx to be 48, which is the "0" character in ascii. Then we want to add the value 1 to the value stored in rbx. and then we just move the rbx value into the memory address referenced by the 'digit' label
Basically our code should print the character 1, 2, 3, 4 and 5
## Compiling
Here we're going to use nasm to compile our assembly code:
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ nasm -f elf64 5.asm -o 5.o
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ld 5.o -o 5
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ./5
12345%
And that's it ! next tutorial we'll look into loops, you can click [here](6.html).

107
asm/6.md Normal file
View file

@ -0,0 +1,107 @@
# Assembly x86_64 - CLI Arguements
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 6.asm
section .data
msg db 'Hello, world', 0xa ; our hello world string of text
len equ $ - msg ; the length of the msg variable
filename db 'test.txt', 0 ; the name of the file : test.txt
lenfilename equ $ - filename ; the length of the filename variable
fd dq 0 ;
section .text
global _start
_start:
mov rax, 2 ; syscall id 2 to open the file
mov rdi, filename
mov rsi, 0102o ;O_CREAT, man open
mov rdx, 0666o ; RW no X for root, group and user
syscall
mov [fd], rax
mov rax, 1 ;syscall id 1 to print text
mov rdi, [fd] ;file descriptor
mov rsi, msg ;message to write
mov rdx, len ;message length
syscall ;call kernel
mov rax, 3 ;syscall id 3 to close the file
mov rdi, [fd] ; value is 0
syscall
mov rax, 60 ;system call number (sys_exit)
syscall ;call kernel
Now let's inspect what's new in this code:
_start:
mov rax, 2 ; syscall id 2 to open the file
mov rdi, filename
mov rsi, 0102o ;O_CREAT, man open
mov rdx, 0666o ; RW no X for root, group and user
syscall
First we make use of the [syscall](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md#x86_64-64_bit) id 2 (rax register) to open a file, the name is specified in the first arguement (rdi) , then for the 2nd arguement (rsi) , we open it with the [O_CREAT flag](https://man7.org/linux/man-pages/man2/open.2.html), to create the file if it doesnt exist. For the 3rd arguement (rdx) we set the permissions to RW RW RW.
mov [fd], rax
mov rax, 1 ;syscall id 1 to print text
mov rdi, [fd] ;file descriptor
mov rsi, msg ;message to write
mov rdx, len ;message length
syscall ;call kernel
the file descriptor is returned by the open syscall (id 2) we used previously, so we just put it in the [fd] label to be able to use it later. Then we use the syscall id 1 (rax), first arg (rdi) is the file descriptor because we don't want to output our text to stdout nor stderr (2) we want it in the file. Next arguement (rsi) is the message to write and then rdx is the message length.
mov rax, 3 ;syscall id 3 to close the file
mov rdi, [fd]
syscall
mov rax, 60 ;system call number (sys_exit)
syscall ;call kernel
And then lastly we use the syscall id 3 to close the file, and it's first arguement is the file we previously opened. The last syscall that we use is the exit syscall to end the binary execution.
## Compiling
Here we're going to use nasm to compile our assembly code and then use ld to get the binary and execute it:
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ nasm -f elf64 6.asm -o 6.o
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ ld 6.o -o 6
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ ./6
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ cat test.txt
Hello, world
And we see that we have been able to print out the Hello World text string inside of test.txt ! In the next tutorial we will check out a minimal shellcode used to spawn a /bin/sh shell. you can click [here](7.html).

180
asm/7.md Normal file
View file

@ -0,0 +1,180 @@
# Assembly x86_64 - Spawning a Shell
## Assembly Code
We're going to use vim to write our code
[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 7.asm
section .text
global _start
_start:
xor esi, esi
xor edx, edx
push 0x3b
pop rax
mov rbx, 0x68732f2f6e69622f
push rsi
push rbx
mov rdi, rsp
syscall
Now let's check out what is new in the above code:
_start:
xor esi, esi
xor edx, edx
using xor on the same register has the property of being equivalent to mov esi, 0 but being shorter (only 2 bytes) the processor recognizes the special case and treats it as a mov esi, 0 so the execution time is the same. so we clear out the esi and edx registers,
push 0x3b ;push the value of the syscall id onto the stack (0x3b is 59)
pop rax ;take the out the top of the stack to put it into rax
Next we push the value 0x3b (59) onto the stack, and then pop the value out into rax, The equivalent is **mov rax, 59** However this results in a shorter shellcode as we're going to see later on. Now since we have our execve() syscall, we want to give it an arguement, we want it to spawn **/bin/sh** and we want it to be 8 bytes so we get the following: **/bin//sh** :
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ echo '/bin//sh' | xxd
00000000: 2f62 696e 2f2f 7368 0a /bin//sh.
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ echo 'hs//nib/' | xxd
00000000: 6873 2f2f 6e69 622f 0a hs//nib/.
So we get our following mov instruction:
mov rbx, 0x68732f2f6e69622f ; put the little endian hex val of '/bin//sh' into rbx
## Compiling
Here we're going to use nasm to compile our assembly code and then ld to create the binary file:
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ nasm -f elf64 7.asm
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ ld 7.o -o 7
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ ./7
[ 192.168.100.1/24 ] [ /dev/pts/3 ] [/home/nothing/binexp/asm]
→ echo $0 ; exit
bash
exit
[ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
→ echo $0
/bin/zsh
And that's it! But if we wanted to create shellcode for binary exploitation, we would adjust the assembly code as follows:
[bits 64]
xor esi, esi ; xor out esi and edx
xor edx, edx
push 0x3b ;push the value of the syscall id onto the stack (0x3b is 59)
pop rax ;take the out the top of the stack to put it into rax
mov rbx, 0x68732f2f6e69622f ; put the little endian hex val of '/bin//sh' into rbx
push rsi ; push the value of rsi
push rbx ; push the value of rbx
mov rdi, rsp ; move the value of rsp ( ) into rdi (first arguement)
syscall
And then we would compile it not with the elf64 flag, but this time we don't need a binary file, we want what's called shellcode to use in conjunction with python pwntools:
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ nasm -f bin 7.asm
[ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
→ cat 7
11j;XH/bin//shVSH%
Now let's view the hexdump of our shellcode inside of python pwntools:
[ 192.168.0.18/24 ] [ /dev/pts/7 ] [~/binexp/asm]
→ vim hexdump.py
from pwn import *
#read the shellcode file we compiled
with open('7', 'rb') as f:
shellcode = f.read()
print(shellcode)
Here basically we take our shellcode file (named 7) and we store its contents into the shellcode variable. Then we print it:
[ 192.168.0.18/24 ] [ /dev/pts/18 ] [~/binexp/asm]
→ python3 hexdump.py
b'1\xf61\xd2j;XH\xbb/bin//shVSH\x89\xe7\x0f\x05'
However this isn't all that accurate for us. Here you can see the non-ascii characters being represented as \x00 \x01 \x02 and such. So to get more information on the shellcode characters we should use the hexdump function that's built-in to pwntools:
from pwn import *
#read the shellcode file we compiled
with open('7', 'rb') as f:
shellcode = f.read()
print(hexdump(shellcode))
And we get the following result:
[ 192.168.0.18/24 ] [ /dev/pts/18 ] [~/binexp/asm]
→ python3 hexdump.py
00000000 31 f6 31 d2 6a 3b 58 48 bb 2f 62 69 6e 2f 2f 73 │1·1·│j;XH│·/bi│n//s│
00000010 68 56 53 48 89 e7 0f 05 │hVSH│····│
00000018
And that's it! we have some payload ready to be used for binary exploitation purposes.

BIN
asm/img/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
asm/img/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB