0

I'm using a 64-bit Ubuntu 18.04.3 LTS VM and I'm trying to write a simple x64 assembly code that will print "Owned!!!".

Because I don't want any 0x00 or 0x0a bytes and I want the code to be position independent (because I'm learning how to write shellcodes), I wrote it this way:

;hello4.asm  attempts to make the code position independent

section .text

global _start

_start:
;clear out the registers we are going to need
xor rax, rax
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx

;write(int fd, char *msg, unsigned int len)
mov al, 4
mov bl, 1
;Owned!!! =  4f,77,6e,65,64,21,21,21
;push !,!,!,d
push 0x21212164
;push e,n,w,O 
push 0x656e774f
mov rcx, rsp
mov dl, 8
int 0x80

;exit(int ret)
mov al,1
xor rbx, rbx
int 0x80

This is the output that I'm getting:

user@PC:~/Desktop/exploitsclass/hello_shellcode$ nasm -f elf64 hello4.asm
user@PC:~/Desktop/exploitsclass/hello_shellcode$ ld hello4.o -o hello4
user@PC:~/Desktop/exploitsclass/hello_shellcode$ objdump -d hello4 -M intel

hello4:     file format elf64-x86-64


Disassembly of section .text:

0000000000400080 <_start>:
  400080:   48 31 c0                xor    rax,rax
  400083:   48 31 db                xor    rbx,rbx
  400086:   48 31 c9                xor    rcx,rcx
  400089:   48 31 d2                xor    rdx,rdx
  40008c:   b0 04                   mov    al,0x4
  40008e:   b3 01                   mov    bl,0x1
  400090:   68 64 21 21 21          push   0x21212164
  400095:   68 4f 77 6e 65          push   0x656e774f
  40009a:   48 89 e1                mov    rcx,rsp
  40009d:   b2 08                   mov    dl,0x8
  40009f:   cd 80                   int    0x80
  4000a1:   b0 01                   mov    al,0x1
  4000a3:   48 31 db                xor    rbx,rbx
  4000a6:   cd 80                   int    0x80
user@PC:~/Desktop/exploitsclass/hello_shellcode$ ./hello4
Segmentation fault (core dumped)

How do I fix this?

UPDATE:

I've understood that int 0x80 is intended for 32-bit programs and I should use syscall instead and that syscall has different ids for each system call.

The new code is:

;hello4.asm  attempts to make the code position independent

section .text

global _start

_start:
;clear out the registers we are going to need
xor rax, rax
xor rsi, rsi
xor rdi, rdi
xor rdx, rdx

;write(int fd, char *msg, unsigned int len)
mov al, 1
add di, 1
;Owned!!! =  4f,77,6e,65,64,21,21,21
;push !,!,!,d
push 0x21212164
;push e,n,w,O 
push 0x656e774f
mov rsi, rsp
mov dl, 8
syscall

;exit(int ret)
mov al, 60
xor rdi, rdi
syscall

The output is Owne% instead of Owned!!! now. It still needs to be fixed.

Ron Halfon
  • 105
  • 1
  • 2
  • 10

2 Answers2

1

With the help of @CertainLach I've written the correct code:

;hello4.asm  attempts to make the code position independent

section .text

global _start

_start:
;clear out the registers we are going to need
xor rax, rax
xor rsi, rsi
xor rdi, rdi
xor rdx, rdx

;write(int fd, char *msg, unsigned int len)
mov al, 1
add di, 1
;Owned!!! =  4f,77,6e,65,64,21,21,21
mov rsi, 0x21212164656e774f
push rsi
mov rsi, rsp
mov dl, 8
syscall

;exit(int ret)
mov al, 60
xor rdi, rdi
syscall

This code contains no null bytes or 0x0a bytes and it's position-independent, as following:

user@PC:~/Desktop/exploitsclass/hello_shellcode$ objdump -d hello4 -M intel

hello4:     file format elf64-x86-64


Disassembly of section .text:

0000000000400080 <_start>:
  400080:   48 31 c0                xor    rax,rax
  400083:   48 31 f6                xor    rsi,rsi
  400086:   48 31 ff                xor    rdi,rdi
  400089:   48 31 d2                xor    rdx,rdx
  40008c:   b0 01                   mov    al,0x1
  40008e:   66 83 c7 01             add    di,0x1
  400092:   48 be 4f 77 6e 65 64    movabs rsi,0x21212164656e774f
  400099:   21 21 21 
  40009c:   56                      push   rsi
  40009d:   48 89 e6                mov    rsi,rsp
  4000a0:   b2 08                   mov    dl,0x8
  4000a2:   0f 05                   syscall 
  4000a4:   b0 3c                   mov    al,0x3c
  4000a6:   48 31 ff                xor    rdi,rdi
  4000a9:   0f 05                   syscall 

This is also a correct way of implementing the solution, which is 1 bytecode less, but with more memory consumption:

user@PC:~/Desktop/exploitsclass/hello_shellcode$ cat hello4.asm
;hello4.asm  attempts to make the code position independent

section .text

global _start

_start:
;clear out the registers we are going to need
xor rax, rax
xor rsi, rsi
xor rdi, rdi
xor rdx, rdx

;write(int fd, char *msg, unsigned int len)
mov al, 1
add di, 1
;Owned!!! =  4f,77,6e,65,64,21,21,21
;push !,!,!,d
push 0x21212164
;push e,n,w,O
push 0x656e774f
mov rsi, rsp
mov dl, 16
syscall

;exit(int ret)
mov al, 60
xor rdi, rdi
syscall

user@PC:~/Desktop/exploitsclass/hello_shellcode$ objdump -d hello4 -M intel

hello4:     file format elf64-x86-64


Disassembly of section .text:

0000000000400080 <_start>:
  400080:   48 31 c0                xor    rax,rax
  400083:   48 31 f6                xor    rsi,rsi
  400086:   48 31 ff                xor    rdi,rdi
  400089:   48 31 d2                xor    rdx,rdx
  40008c:   b0 01                   mov    al,0x1
  40008e:   66 83 c7 01             add    di,0x1
  400092:   68 64 21 21 21          push   0x21212164
  400097:   68 4f 77 6e 65          push   0x656e774f
  40009c:   48 89 e6                mov    rsi,rsp
  40009f:   b2 10                   mov    dl,0x10
  4000a1:   0f 05                   syscall 
  4000a3:   b0 3c                   mov    al,0x3c
  4000a5:   48 31 ff                xor    rdi,rdi
  4000a8:   0f 05                   syscall

Thank you so much!

Ron Halfon
  • 105
  • 1
  • 2
  • 10
0

Can't answer your comment, you can't just change int 0x80 to syscall to make it work, system call numbers differ, i.e sys_write you have here, have id 4 for int 0x80, and id 1 with syscall

Here you can see numbers for syscall

And here for int 0x80

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • `mov dl, 8` => `mov dl, 16` – Yaroslav Bolyukin Oct 12 '19 at 15:44
  • Because it's a 64-bit address, is there a way to push the entire string to one line? I've tried `push 0x21212164656e774f` but it raised an error – Ron Halfon Oct 12 '19 at 15:56
  • Probally, % - it is symbol written by your terminal, if output has no newlines at end. You can try `echo -n "Hello world"` to test it – Yaroslav Bolyukin Oct 12 '19 at 15:57
  • 1
    I've examined `rsp` using gdb. This is the output: `(gdb) x/16x $rsp 0x7fffffffdf90: 0x4f 0x77 0x6e 0x65 0x00 0x00 0x00 0x00 0x7fffffffdf98: 0x64 0x21 0x21 0x21 0x00 0x00 0x00 0x00` Now I just need to make one push that will eliminate all the 0x00 bytes. – Ron Halfon Oct 12 '19 at 16:00
  • There is no instruction to push x64 bit value to stack, use ```mov rcx, 0x21212164656e774f push rcx ``` Instead, and then change `mov dx, 16` back to `mov dx, 8` – Yaroslav Bolyukin Oct 12 '19 at 16:01
  • Thank you so much! The `%` came from my ohmyzsh shell. When I switched to bash, it disappeared. – Ron Halfon Oct 12 '19 at 16:12
  • In fact, solution with `mov dl, 16` isn't correct, because it also writes 8 unneeded `\0` chars (You can verify it with `wc --bytes`), i written them because i messed `write` with windows and utf-16 :D – Yaroslav Bolyukin Oct 12 '19 at 16:29