Wednesday, July 17, 2013

SLAE Assignment # 5 - Shellcode Analysis Part 1

Posted by John ( Admin ) on 5:33 AM

The Past two months i was really busy with other work and hence i was not able to spend enough time on the SLAE course.  I hope i will be able to complete all the assignments within this month, today i will be doing my 5th assignment which is to analyse any three metasploit linux/x86 payloads . I decided to first analyse linux/x86/exec payload 

1. linux/x86/exec

To get more info about the payload we can use the "S" option which stands for summary

sudo msfpayload -p linux/x86/exec S

Summary of the Payload :-
       Name: Linux Execute Command
     Module: payload/linux/x86/exec
    Version: 0
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 143
       Rank: Normal

Provided by:
  vlad902 <vlad902@gmail.com>

Basic options:
Name  Current Setting  Required  Description
----  ---------------  --------  -----------
CMD                    yes       The command string to execute

Description:
  Execute an arbitrary command

So from the summary, The above payload requires a command which will be executed remotely, I decided to execute the "ls" command.

sudo msfpayload -p linux/x86/exec CMD=ls S

Summary of the Payload :-

       Name: Linux Execute Command
     Module: payload/linux/x86/exec
    Version: 0
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 150
       Rank: Normal

Provided by:
  vlad902 <vlad902@gmail.com>

Basic options:
Name  Current Setting  Required  Description
----  ---------------  --------  -----------
CMD   ls               yes       The command string to execute

Description:
  Execute an arbitrary command

Now our payload is ready, I will first use libemu to analyse the payload 

Libemu Analysis 


sudo msfpayload -p linux/x86/exec CMD=ls R | ./sctest -vvv -Ss 10000 


                                                                                 

To get the out put in a nice graphical flow chart format , We use the "-G" option

sudo msfpayload -p linux/x86/exec CMD=ls R |./sctest -vvv -Ss 10000 -G
exec.dot

The out put file is stored in .dot format to convert it to .png format, we need to issue the following command

dot  exec.dot -Tpng -o exec.png



From the above flow chart we can clearly see that "execve" system call has been used , we can have a look at the man page to get some info on execve

man 2 execve 


From the man page, We understand that execve executes a program but it requires three inputs (*filename, *agrv and *envp) .From libemu's output the arguments are not clear to us .

So for further analysis it necessary for us to first test the shellcode in our C template,  After which we can use tools such as strace and gdb for analysis . To do this we will first get the payload output in C format by issuing the following command


sudo msfpayload -p linux/x86/exec CMD=ls C

 /*
 * linux/x86/exec - 38 bytes
 * http://www.metasploit.com
 * VERBOSE=false, PrependSetresuid=false, 
 * PrependSetreuid=false, PrependSetuid=false, 
 * PrependSetresgid=false, PrependSetregid=false, 
 * PrependSetgid=false, PrependChrootBreak=false, 
 * AppendExit=false, CMD=ls
 */
unsigned char buf[] = 
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c"
"\x73\x00\x57\x53\x89\xe1\xcd\x80";


Now, Let's copy the shellcode and use it in our C template (For Testing a shellcode locally)

*/
*#include stdio.h
*#include string.h
/*

unsigned char code[] = \

"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c"
"\x73\x00\x57\x53\x89\xe1\xcd\x80"
main()

{
        printf("Shellcode Length:  %d\n", strlen(code));

        int (*ret)() = (int(*)())code;

        ret();
}


we compile and run the program

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

./shellcode

as expected  the ls command  is executed




Now lets find the arguments passed in the execve system call by using Strace

Strace Analysis 


We use  the "-e" option to filter "execve" system call

strace -e execve ./shellcode



By correlating the output, we find the arguments of execve
  • filename :-  Contains the path of the binary to be  executed which is (/bin/sh)
  • agrv [] :-   Contains  an array of argument strings passed to the new program.  By convention, the first of  these  strings should  contain  the *file name associated with the file being executed that  is ["/bin/sh", "-c", "ls"] 
  • envp [] :-  Is an array of strings, conventionally of the form key=value, which are passed as environment to the new program, this is nothing but a null pointer [/* 0 vars */]
Note:- Both *argv and *envp must be terminated by a NULL pointer



GDB Analysis 

Now lets use gdb to step through the program to find out the registers, which have been used and also to analyse the program flow 

 gdb -q ./shellcode

Now lets set the disassembly  to "Intel" format and then set a break point at  "code"

(gdb) set disassembly-flavor intel
(gdb) break *&code 
Breakpoint 1 at 0x804a040
(gdb) run
Starting program: /home/john/libemu/tools/sctest/shellcode 
Shellcode Length:  15
Breakpoint 1, 0x0804a040 in code ()
(gdb) disassemble 
Dump of assembler code for function code:
=> 0x0804a040 <+0>: push   0xb
   0x0804a042 <+2>: pop    eax
   0x0804a043 <+3>: cdq    
   0x0804a044 <+4>: push   edx
   0x0804a045 <+5>: pushw  0x632d
   0x0804a049 <+9>: mov    edi,esp
   0x0804a04b <+11>:    push   0x68732f
   0x0804a050 <+16>:    push   0x6e69622f
   0x0804a055 <+21>:    mov    ebx,esp
   0x0804a057 <+23>:    push   edx
   0x0804a058 <+24>:    call   0x804a060 
   0x0804a05d <+29>:    ins    BYTE PTR es:[edi],dx
   0x0804a05e <+30>:    jae    0x804a060 
   0x0804a060 <+32>:    push   edi
   0x0804a061 <+33>:    push   ebx
   0x0804a062 <+34>:    mov    ecx,esp
   0x0804a064 <+36>:    int    0x80
   0x0804a066 <+38>:    add    BYTE PTR [eax],al
End of assembler dump.


Now i will comment on each step, for better understanding and i will also set break points when required 

Dump of assembler code for function code:

=> 0x0804a040 <+0>:   push   0xb         ; Syscall Number of Execve is pushed on the stack
   0x0804a042 <+2>: pop    eax       ; Syscall Number of Execve is poped into the EAX Register
   0x0804a043 <+3>: cdq              ; Convert double-word to quad-word 
   0x0804a044 <+4>: push   edx       ; EDX is pushed on the stack 
   0x0804a045 <+5>: pushw  0x632d    ;  "-C" is pushed on the stack
   0x0804a049 <+9>: mov    edi,esp   ; Address of esp in moved into EDI register which nothing but "-c" 
   0x0804a04b <+11>: push   0x68732f  ; "/sh" is moved on the stack in reverse stack grows from higher memory to lower memory
   0x0804a050 <+16>: push   0x6e69622f ; "/bin" is moved on the stack in reverse stack grows from higher memory to lower memory
   0x0804a055 <+21>: mov    ebx,esp    ; Address of esp is moved into EBX register which is a pointer to "/bin/sh"
   0x0804a057 <+23>: push   edx        ; EDX Register is pushed on the stack (Null)




From the above analysis we know the following

  • EAX :-  Contains the system call number of execve which is 11 (hex - 0xb)
  • EBX :-  Contains the binary to be executed "/bin/sh" 
  • EDX :-  Contains Nulls for null terminating (argv and envp)
  • EDI  :-  Contains the address of "-c" one of the arguments

Now lets set a break point at 0x0804a058 (Before the Call instruction)

(gdb) break * 0x0804a058
Breakpoint 2 at 0x804a058
(gdb) c
Continuing.

Breakpoint 2, 0x0804a058 in code ()
(gdb) disassemble
Dump of assembler code for function code:
   0x0804a040 <+0>: push   0xb
   0x0804a042 <+2>: pop    eax
   0x0804a043 <+3>: cdq  
   0x0804a044 <+4>: push   edx
   0x0804a045 <+5>: pushw  0x632d
   0x0804a049 <+9>: mov    edi,esp
   0x0804a04b <+11>: push   0x68732f
   0x0804a050 <+16>: push   0x6e69622f
   0x0804a055 <+21>: mov    ebx,esp
   0x0804a057 <+23>: push   edx
=> 0x0804a058 <+24>: call   0x804a060 
   0x0804a05d <+29>: ins    BYTE PTR es:[edi],dx
   0x0804a05e <+30>: jae    0x804a060 
   0x0804a060 <+32>: push   edi
   0x0804a061 <+33>: push   ebx
   0x0804a062 <+34>: mov    ecx,esp
   0x0804a064 <+36>: int    0x80
   0x0804a066 <+38>: add    BYTE PTR [eax],al
End of assembler dump.


Now lets step through and analyse the stack $esp before and after the call instruction
=> 0x0804a058 <+24>: call   0x804a060 
   0x0804a05d <+29>: ins    BYTE PTR es:[edi],dx
   0x0804a05e <+30>: jae    0x804a060 
   0x0804a060 <+32>: push   edi
   0x0804a061 <+33>: push   ebx
   0x0804a062 <+34>: mov    ecx,esp
   0x0804a064 <+36>: int    0x80
   0x0804a066 <+38>: add    BYTE PTR [eax],al
End of assembler dump.
(gdb) x/xw $esp
0xbffff2ca: 0x00000000
(gdb) stepi
0x0804a060 in code ()
(
gdb) x/xw $esp
0xbffff2c6: 0x0804a05d
(gdb) x/xs 0x0804a05d
0x804a05d :  "ls"
(gdb) disassemble
Dump of assembler code for function code:
   0x0804a040 <+0>: push   0xb
   0x0804a042 <+2>: pop    eax
   0x0804a043 <+3>: cdq    
   0x0804a044 <+4>: push   edx
   0x0804a045 <+5>: pushw  0x632d
   0x0804a049 <+9>: mov    edi,esp
   0x0804a04b <+11>: push   0x68732f
   0x0804a050 <+16>: push   0x6e69622f
   0x0804a055 <+21>: mov    ebx,esp
   0x0804a057 <+23>: push   edx
   0x0804a058 <+24>: call   0x804a060 
   0x0804a05d <+29>: ins    BYTE PTR es:[edi],dx
   0x0804a05e <+30>: jae    0x804a060 
=> 0x0804a060 <+32>: push   edi
   0x0804a061 <+33>: push   ebx
   0x0804a062 <+34>: mov    ecx,esp
   0x0804a064 <+36>: int    0x80
   0x0804a066 <+38>: add    BYTE PTR [eax],al
End of assembler dump.


From the above analysis, we confirm that the payload is using  "jump call pop" technique . The argument "ls" is now on the stack

 Lets continue our analysis

=> 0x0804a060 <+32>:  push   edi ; Pointer to "-c"
   0x0804a061 <+33>: push   ebx  ; Pointer to "/bin/sh"
   0x0804a062 <+34>: mov    ecx,esp ; pointer to " /bin/sh -c ls "
   0x0804a064 <+36>: int    0x80


Lets set a break point just before interrupt "0x80" and see how the stack and other registers are laid out


(gdb) break *0x0804a064
Breakpoint 3 at 0x804a064
(gdb) c
Continuing.

Breakpoint 3, 0x0804a064 in code ()
(gdb) disassemble

   0x0804a061 <+33>: push   ebx
   0x0804a062 <+34>: mov    ecx,esp
=> 0x0804a064 <+36>: int    0x80
   0x0804a066 <+38>: add    BYTE PTR [eax],al



Now lets analyse the registers 

(gdb) info registers 
eax            0xb 11                  ; Execve Sys call number
ecx            0xbffff2be -1073745218 ; address of "/bin/sh -c ls"  
edx            0x0 0                   ; Null (envp)
ebx            0xbffff2ce -1073745202 ; pointer to "bin/sh"
esp            0xbffff2be 0xbffff2be




  • EAX :-  Contains the system call number of execve which is 11 (hex - 0xb)
  • EBX :-  Contains the binary to be executed "/bin/sh" 
  • ECX :-  Pointer to "/bin/sh -c ls "
  • EDX  :-  Contains Null (envp)


So from the above analysis we found out that "execve" system call was used and we also found out  that the shellcode used "jump call pop technique" to execute the command that we first feed in "ls"





Kindly Bookmark and Share it:

0 comments:

Post a Comment