mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/hacking-blogposts.git
synced 2025-05-16 04:16:59 +00:00
add hacking blogposts as they are
This commit is contained in:
parent
fa65088be1
commit
325b9c3814
1904 changed files with 91353 additions and 0 deletions
33
asm/0.md
Normal file
33
asm/0.md
Normal 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
86
asm/1.md
Normal 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
136
asm/2.md
Normal 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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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
104
asm/3.md
Normal 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
122
asm/4.md
Normal 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
88
asm/5.md
Normal 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
107
asm/6.md
Normal 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
180
asm/7.md
Normal 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
BIN
asm/img/0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
asm/img/1.png
Normal file
BIN
asm/img/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Loading…
Add table
Add a link
Reference in a new issue