Reputation: 83
I have programmed a piece of x64 linux assembly. All it does is just prints a line "Hello world", that's all. However what I want to do is copy the bytes from it's object file by objdump, so that I can make my own shellcode for my buffer overflow attacks.
The problem I a facing is that the shellcode contains lots of null bytes and that will terminate the execution of my shellcode.
root@kali:~/C scripts/shellcode/Assembly Based Shellcode# cat print.asm
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, 12
syscall
mov rax, 60
xor rdi, rdi
syscall
message:
db "Hello world", 10
root@kali:~/C scripts/shellcode/Assembly Based Shellcode# nasm -f elf64 print.asm && ld print.o -o print && ./print
Hello world
root@kali:~/C scripts/shellcode/Assembly Based Shellcode# objdump -D print.o
print.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start>:
0: b8 01 00 00 00 mov $0x1,%eax
5: bf 01 00 00 00 mov $0x1,%edi
a: 48 be 00 00 00 00 00 movabs $0x0,%rsi
11: 00 00 00
14: ba 0c 00 00 00 mov $0xc,%edx
19: 0f 05 syscall
1b: b8 3c 00 00 00 mov $0x3c,%eax
20: 48 31 ff xor %rdi,%rdi
23: 0f 05 syscall
0000000000000025 <message>:
25: 48 rex.W
26: 65 6c gs insb (%dx),%es:(%rdi)
28: 6c insb (%dx),%es:(%rdi)
29: 6f outsl %ds:(%rsi),(%dx)
2a: 20 77 6f and %dh,0x6f(%rdi)
2d: 72 6c jb 9b <message+0x76>
2f: 64 fs
30: 0a .byte 0xa
root@kali:~/C scripts/shellcode/Assembly Based Shellcode#
I hoped the shellcode would be free from null bytes. However it is not. Can someone help me and correct my code?
Upvotes: 2
Views: 3759
Reputation: 56
You seem to be confused in assembly and buffer overflows.
I reprogrammed the assembly file like this :
section .text
GLOBAL _start
_start:
xor rax, rax ; Clear the RAX register
push rax ; Push the NULL byte [ string terminator ]
add al, 0x1 ; RAX = 1, to put the system in sys_write mode
mov rdi, rax ; RDI = 1, to setup the fist parameter for write ( file descriptor to write to ). The integral value for 'stdout' is 1.
lea rsi, [rel msg+0x41414141] ; Move the relative RIP address of msg to RSI to prepare the string buffer for writing to the stdout. Also add a large 4-byte offset to evade NULL bytes.
sub rsi, 0x41414141 ; Subtract that large offset to make the RSI point correctly.
xor rdx, rdx ; Empty the 3rd argument for write
mov dl, 0xc ; RDX = 12, 12 ==> string length of msg
syscall ; system call
msg db "Hello world", 0xa
section .text
GLOBAL _start
_start:
push 0x1
pop rax
mov rdi, rax
mov rbx, 'AAAAArld'
shr rbx, 0x28
push rbx
mov rbx, 'Hello wo'
push rbx
mov rsi, rsp
push 0xc
pop rdx
syscall
and then I compiled the program like this :
root@kali:~/Desktop/assembly# nasm -f elf64 main.asm; ld main.o -o main.elf; ./main.elf
Hello world
Segmentation fault
The seg fault really doesn't matter because you want to use this as shellcode for a buffer overflow attack so there is anyway a seg fault there.
Now, extract the bytes from the object code :
root@kali:~/Desktop/assembly# for i in $(objdump -D main.o | grep "^ " | cut -f2); do echo -n "\x$i"; done; echo
\x48\x31\xc0\x50\x04\x01\x48\x89\xc7\x48\x8d\x35\x4f\x41\x41\x41\x48\x81\xee\x41\x41\x41\x41\x48\x31\xd2\xb2\x0c\x0f\x05\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0a
[ OPTION ] : You can test your shellcode before executing it in a memory corruption exploit
For that just copy the bytes from the above command and make a new C file [ it seems you are confused in the C script as well ]
#include <stdio.h>
int main(void) {
char shellcode[] = "\x48\x31\xc0\x50\x04\x01\x48\x89\xc7\x48\x8d\x35\x4f\x41\x41\x41\x48\x81\xee\x41\x41\x41\x41\x48\x31\xd2\xb2\x0c\x0f\x05\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0a";
int (*ret)() = (int (*)())shellcode;
// The above line will create an integer pointer ret make it point to a function which doesn't require parameter [ indicated by the () ]. Then it will type casting to cast the shellcode to a function pointer of the same type.
// So this will essentially cast your shellcode array address to a function pointer which you can later use to call it as a function and execute the code.
ret(); // Execute the shellcode
}
Then compile the program and make sure to make the stack executable otherwise you will end up getting a seg fault here itself and the shellcode will not execute.
root@kali:~/Desktop/assembly# gcc -z execstack test.c; ./a.out
Hello world
Segmentation fault
From the above code it seems like the shellcode seems to work just fine!
I have tried this on a basic application and it works so your problem should be solved.
Another point to mention is that, only if your executable application [ the one you are going to be exploiting ] uses input methods which stop on a NULL bytes like strcpy()
, only then you have to remove NULL bytes.
If your executable uses input functions like gets()
and fgets()
then you don't need to worry about NULL bytes [ unless you are looking forward for format string vulnerability as well ]
This came from the man page of fgets:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
this clearly means that the NULL bytes shouldn't bother your exploit.
I hope your doubts get cleared!
Upvotes: 4