#1
1.No null bytes in case of strcpy, which stops copying after it encounters a null byte
2.Size limit of on how much shellcode we can put
3.Only alphanumeric characters are copied
These conditions cause us to develop different methods to write our shellcode in a way that it will implement the same logic but still be able to bypass the limitations imposed by the program
Today we will attempt to solve case #1 by learning about techniques that we can use to tackle this issue, so shit right ? now gtfoh if u dont wanna listen XD
these techniques are often called Null Terminated Programming, as they allow us to compile assembly code that will not contain any null bytes in the final shellcode.
Please note that some of the techniques described here will probably be relevant for different assembly languages as well so i’ll leave it as an exercise for the reader to check these techniques on a different language.
Recommended Prerequisites:
  • x64/x86 assembly knowledge
  • Basic knowledge on building shellcodes
SetupFor our setup, i’m using a script i wrote for compiling shellcode for x86/x64
which we can also use to compile our shellcode.
next, we can use this repository in order to debug and run our shellcode nicely
YOU SEE that i dont use any fucking program all making with some scripts from github or even handmade shits so for REVERSING U DONT ACTUALLY NEED TOOLS AND STUFF 
JUST USE UR BRAIN AND PROGRAMMING SKILLS SUCK MA DICK NOW SadNigga
Quick Refreshment on x64 syscallsIn x64 linux systems, Each syscall has a special number that represents it, when we want to perform a call to a certain syscall we first need to store the correct syscall number in RAX, then we pass the arguments 1-6 to the syscall using the registries RDI, RSI, RDX, RCX, R8, R9 accordingly.
Finally, we use the instruction syscall which performs the syscall itself and stores the return value in RAX.
The full x64 syscall map table can be found here 
For windows syscal use here
Let’s have a look at this simple assembly code i wrote named printf_file.asm:

 
Code:
[code]
 
SYS_READ equ 0

SYS_WRITE equ 1

SYS_OPEN equ 2 

SYS_EXIT equ 60

AMOUNT_TO_READ equ 16 

global _start

section .text

_start:

  jmp get_file_path 

  continue:

  

  ; syscall to open the file

  mov eax, SYS_OPEN

  pop rdi ; pop address of string to rdi

  mov rsi, 0 ; set O_RDONLY flag

  syscall

    

  ; syscall to read file

  sub sp, 0xff

  lea rsi, [rsp]

  

  ; syscall to write file contents to stdout  

  mov rdi, rax ; use the returned fd

  mov rdx, AMOUNT_TO_READ; amount to read

  mov rax, SYS_READ

  syscall

  

  ; syscall write to stdout

  mov rdi,1 ; set stdout fd = 1

  mov rdx, rax ; write to stdout the amount of bytes read

  mov rax, SYS_WRITE

  syscall

  mov rax, SYS_EXIT

  syscall ; finish execution

; jump here in order to get the address of the string

get_file_path:

call continue 

file_path: db "/tmp/my_file", 0
[/code]
This code performs a simple task, it reads 16 bytes from the file located in
/tmp/my_file and outputs those bytes to stdout.
Notice the cool trick we implemented in order to obtain the string that contains the path to the file.
to get that address, we perform a call to a label near that string called get_file_path,
afterwards we immediately perform a second call to the continue label that brings us back to the rest of our shellcode.
Because the second call was invoked, the address to return to after the second call now points to the string, because that is the first “instruction” after the call instruction. we then pop that address to RDI so that RDI (the first param in x64 syscall conventions) can point to the string of the file we wish to open
You can compile it the above assembly code by running

 
Code:
[code]
path_to_make_shellcode_ /make_shellcode_linux/make_shellcode.sh/ ./printf_file.asm 64
[/code]
and run it using

 
Code:
[code]
path_to_shellrun/shellrun ./print_file.bin
[/code]
Let’s check if the shellcode works properly

 
Code:
[code]
echo “this_is_my_data” > /tmp/my_file
[/code]
 
[Image: 2GisYvqJ2g32ypelhJtfb8vTpLrTloKBc_Xg_rUl...t7lWavbuCP]
901×42 
So far so good.
But under the surface, hide a horrible secret…
It’s full of null bytes!!!
 
[Image: Fc2CVxwKLf9qQRtXk9PfySqeIegGGla4_tzHvumG...fbkfiKBh58]
768×129 
Hexdump just showed us that this shellcode is riddled with null bytes,
Let’s begin our work at curing this code by going over the correct ways to bypass situations where instructions generate null bytes
I will show the opcodes of the instruction on the left side
and the instruction itself on the right side
Note:I’ll be using this website in order to show the bytes generated from the instructions were about to show. I recommend to you all to test your instruction combinations there.
Method 1: Math is awesomeI’ll start of by saying that the mov instruction is many times obsolete when you have the power of math at your side
Loading 0 to a registerBad way:Lets look at the following instruction:

 
Code:
[code]
48 c7 c0 00 00 00 00   mov rax, 0
[/code]
it is 7 bytes long and more importantly, contains 4 null bytes!
we can easily use the following instructions instead
Good way:
 
Code:
[code]
48 31 c0 xor rax, rax
[/code]

 
Code:
[code]
48 c7 c0 ff ff ff ff     mov rax,0xffffffffffffffff
48 ff c0     inc rax
[/code]
in case the value of rbx is 0, we can execute this instruction.
(this can also be done with any other register with a 0 value)

 
Code:
[code]
48 f7 e3    mul rbx
[/code]
The mul instruction will multiply rax with the contents of rbx and store it in rax
because rbx is 0 in this case then 0 will also be stored in rax
**Loading large values to registries **What about putting large values in registries? For example, if i wanted to read a big file with my shellcode.
Bad way
 
Code:
[code]
48 c7 c2 00 00 01 00     mov rdx,0x10000
[/code]
Good wayYou can use the shift operations in order to load large numbers

 
Code:
[code]
48 31 d2     xor   rdx,rdx
48 83 c2 02    add   rdx,0x2
48 c1 e2 0f    shl   rdx,0xf
[/code]
This will result in rdx having the value 0x10000 at the end of the shift operation.
Method 2: Using your lower partsBefore you start thinking dirty, different parts of each register in x64 can be accessed as an operand.
These parts are mapped in the following way:
 
[Image: SYDfjfarq95nvS9-Z98I2E8Frpo-DKCIoi7zHEPr...wmitUiYGkH]
927×602 
This allows us to use the al operand for example instead of the rax operand when we want to perform reading and writing actions on the lower 8 bits of the rax register.
When we do so, the instruction that is executed is much smaller and can also aid us when trying to avoid null bytes.
**Bad way:
 
Code:
[code]
48 c7 c0 02 00 00 00    mov rax,0x2
48 c7 c3 ff 0f 00 00    mov rbx,0xfff
[/code]
Good way
 
Code:
[code]
 
48 31 db              xor    rbx,rbx
48 31 c0              xor    rax,rax
b0 02                 mov    al,0x2
66 bbff 0f            mov    bx,0xfff
[/code]
Field TestAfter we learned these two new methods, let’s implement and modify the assembly code we saw at the beginning of the article

 
Code:
[code]
 


SYS_READ equ 0

SYS_WRITE equ 1

SYS_OPEN equ 2

SYS_EXIT equ 60

AMOUNT_TO_READ equ 16

global _start

section .text

_start:

  jmp get_file_path 

  continue:

  

  ; syscall to open the file

  xor rax, rax

  add al, SYS_OPEN

  pop rdi ; pop address of string to rdi

  xor rsi, rsi ; set O_RDONLY flag

  syscall

    

  ; syscall read file

  sub sp, 0xfff

  lea rsi, [rsp]

  mov rdi, rax

  xor rdx, rdx

  add dl, AMOUNT_TO_READ; amount to read

  xor rax, rax

  syscall

    

  ; syscall write to stdout

  xor rdi, rdi

  add dl, 1 ; set fd to point to stdout

  mov rdx, rax

  xor rax, rax

  add al, SYS_WRITE

  syscall

  

  mov al, SYS_EXIT

  syscall ; finish execution

; jump here in order to get the address of the string  

get_file_path:

call continue

flag: db "/tmp/my_file", 0
[/code]
After we compile this code, we can run it and see that it works exactly the same as the previous code:
 
[Image: 7iMRAtrTTlODrFBp62JTO2cilRkQ36h5rocXJjxi...gFHDgcGbHx]
970×49 
let’s see if hexdumps finds any null bytes…
 
[Image: LJ1HbJHG3o0VkE9eYj4nsPzH_AFrpHD_9eWCtIz4...aKWBB3WjZL]
857×127 
Awesome!
Note: Don’t be confused by the one null byte that hexdump found, that null byte belongs to the string in our shellcode and it’s placed at the end of the shellcode.
It doesn’t seem like it is in the end because memory is saved in little endian.
ConclusionsToday we learned about how we can compile our shellcode to be free of null bytes. We learned along the way about different ways we can perform the same resulting actions using different and sometimes shorter instructions(opcode wise) in x64.
the fucking procedure is goning to belike this no matter what sys u using u can allways bypass the null bytes like this it just require u to know assembly lang and some math dog shit nvm fuck u all bye SadNigga