Skip to main content

ExecveStack1434

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

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

Student ID: SLAE64-1434

Target Operating System: 64 bit Linux (x86_64 GNU/Linux)

Resulting Shellcode Size (machine code bytes): 22 

Published: https://www.exploit-db.com/exploits/41174/

GitHub Link: https://github.com/rtaylor777/nasm/blob/master/ExecveStack1434.nasm

ExecveStack1434 source code

Testing

Once you have downloaded the ExecveStack1434.nasm source code from the GitHub link above, you will need to assemble it. Assuming you have the NASM assembler ( http://www.nasm.us/ ):

Assemble:
nasm -felf64 ExecveStack1434.nasm -o ExecveStack1434.o

Link:
ld ExecveStack1434.o -o ExecveStack1434

Then Execute:
./ExecveStack1434

This will launch the /bin/sh shell.

Object Dump

Once you have the object file ExecveStack1434.o:
objdump -M intel -D  ExecveStack1434.o


Terms

https://en.wikipedia.org/wiki/Machine_code
https://en.wikipedia.org/wiki/Opcode
https://en.wikipedia.org/wiki/Hex
https://en.wikipedia.org/wiki/Assembly_language
https://en.wikipedia.org/wiki/Shellcode
https://en.wikipedia.org/wiki/Null_character
https://en.wikipedia.org/wiki/Objdump 

Intro

The code that you see in the above listing, which I called ExecveStack1434.nasm, when executed will launch a /bin/sh shell.

At a high level the code first sets up some arguments (values to be passed) and then asks the system to run a function called execve. The purpose of the execve function is to launch (run) the command that you specify.


Execve


You can find out more about the execve system call by examining it's "man" page at the Linux command prompt.

man 2 execve

The function signature (declaration) resembles the C language because the Linux Kernel is written in C.

int execve(const char *filename, char *const argv[], char *const envp[]);

In assembly language we pass a number as an argument to indicate what system call we wish to make. On my system the numbers to pass for the various system calls are listed in this file:

"/usr/include/x86_64-linux-gnu/asm/unistd_64.h"

The parameters that the execve function specifies are all pointers. *filename is a pointer to the filename string which indicates what command to run. The next parameter is a pointer to an array called argv. This array holds a list of arguments that are to be passed to the command that we wish execve to launch. The last parameter is a pointer to an array of environment variable strings, which are to be set up in the environment for the command that we wish to run.

Bug 8408 ( https://bugzilla.kernel.org/show_bug.cgi?id=8408 ) - execve() wrongly permits argv and envp to be NULL. With some research I found that on Linux you can specify NULL for the pointer to the arguments array as well as the pointer to the environment variables array.

execve("/bin/echo", NULL, NULL); 

The result of the bug is that the kernel developers don't think that they should fix it.

Passing Arguments From Assembly Language



When passing arguments for a syscall (system call) the system expects the arguments to be in specific CPU registers.

RAX = System Call Number
RDI  = First Argument
RSI  = Second Argument
RDX = Third Argument
R10  = Fourth Argument
r8     = Fifth Argument
r9     = Sixth Argument

So for our system call we are going to put the pointer to the filename into RDI, and NULL into RSI and RDX.

The execve system call is specified by putting the number 59 into the RAX register. Then finally we actually make the call by specifying "syscall".

The Details

 

Okay in more detail, the first two lines:
These two lines actually use a bit of a trick to zero RAX, RDX and RSI.

When  you xor anything with itself it will zero it. When you multiply eax by whatever you specify (register or memory) in this case esi, the result is stored in edx:eax.

Anything multiplied by zero equals zero.

In the Intel® 64 and IA-32 Architectures Software Developer’s Manual ( https://software.intel.com/en-us/articles/intel-sdm ), I noticed that "32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register."

From experiments, I noticed that anything which altered a 32 bit register, automatically zeroed the upper 32 bits of that register.

So when you zero a 32 bit register such as eax, edx, esi you also zero its 64 bit register rax, rdx, rsi.

This is significant because the instructions which affect the 32 bit registers are typically smaller than the instructions which affect either the 64bit registers or the 16 bit registers. So we can save on code size by taking advantage of this knowledge.


The next line pushes zero onto the stack.

We are actually building a string on the stack. The stack grows from high memory towards low memory. Most other values in memory go from low towards high memory. So to put a string on the stack we actually have to build it in reverse. We start by putting the terminating character, a zero, on the stack.

The next line is building our command that we wish to run, and storing it into the rbx register. The hex code 0x68732f2f6e69622f is actually a hexadecimal representation of /bin//sh but in reverse.

Notice that there are 2 slashes between /bin and sh. This is a little trick to prevent zero bytes in our code. We want there to be exactly 8 non zero bytes that we are moving into rbx so that there will not be zeros in our machine code.

The operating system ignores it when you put in too many slashes in a directory path so it still works fine with the extra slash.

You may notice in my ExecveStack1434.nasm source file that I actually used the command:

mov rbx,'/bin//sh'

It is much more clear what it is in my source file. Isn't it nice that the NASM assembler reversed the string for us?

 Now that our string is built we push it onto the stack.

The next 2 instructions are getting a pointer to our string into the RDI register. RSP is the stack pointer and it already points to the string that we just pushed onto the stack.

The last 2 instructions are simply loading our system call number for execve (59) into the RAX register and then calling the system call.

We didn't have to load anything into RSI or RDX because they were zeroed at the beginning. Zero is considered the same thing as NUL.

About NULs


You may have noticed when we talked about our command (string) that we were creating for execve to run we were concerned about not having zeros in our machine code. The reason for that is kind of revealed by how we had to push a zero to the stack as the terminator for our filename string.

With shellcode we are often taking advantage of a programming error which allows us to push our shellcode bytes into an input field, or as some other form of input, for a vulnerable program. The vulnerable program would stop accepting our shellcode if it saw a zero byte because that normally would mark the end of the data (string, array etc.).

About Shellcode Size


It is generally desirable to create an especially small size (in machine code) shellcode because the size of a buffer that we may want to overflow in a vulnerable program may not be very large. The shellcode usually needs to fit in that buffer and it is preferable if there is room to spare.

In case you missed it earlier, let me repeat the following:

In the Intel® 64 and IA-32 Architectures Software Developer’s Manual ( https://software.intel.com/en-us/articles/intel-sdm ), I noticed that "32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register."

From experiments, I noticed that anything which altered a 32 bit register, automatically zeroed the upper 32 bits of that register.

So when you zero a 32 bit register such as eax, edx, esi you also zero its 64 bit register rax, rdx, rsi.

This is significant because the instructions which affect the 32 bit registers are typically smaller than the instructions which affect either the 64bit registers or the 16 bit registers. So we can save on code size by taking advantage of this knowledge.

It is also worth noting that any instruction which interacts with the R8 - R15 registers is typically larger than it would have been for the RAX, RBX, RCX, RDX, RDI, RSI registers. So avoid these new registers if they are not required.

Another subtlety is that some commands are larger depending on their register operands. Take the xchg command for example.

When optimizing for size it is worth experimenting with various alternative ways of coding.

Shellcode.c






You can see an example of running the shellcode above.

Read the following Blog post about how to use my helper scripts to automatically generate the shellcode.c file.

Helper Scripts

I created a Blog post concerning some helper scripts that I created for the SLAE process. You can see examples of working with ExecveStack1434.nasm using my scripts there.

http://a41l4.blogspot.ca/2017/02/slae-helper-scripts.html

Summary

The ExecveStack1434 shellcode when executed will open a /bin/sh shell.

The ExecveStack1434.nasm shellcode is well formed, free of NULLS, as small as the smallest similar shellcode on https://www.exploit-db.com and smaller than any similar code on http://shell-storm.org/shellcode/.


If you wish to learn more about assembly language, I highly recommend the "SecurityTube Linux Assembly Expert course and certification."

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




Comments

Popular posts from this blog

GIAC GXPN Review – SANS SEC660 (Advanced Penetration Testing, Exploit Writing, and Ethical Hacking)   Intro  SANS is a well respected and premier cyber security training company that employs industry experts as instructors. GIAC is a company that produces testing to validate the skills of security professionals. GIAC exams validate the learning outcomes of the SANS courses. Prerequisites Before attempting this course you should be familiar with penetration testing as this is an advanced course. I would say that you should also be familiar with assembly language and shellcoding. It would be best if you have studied basic stack overflow exploits prior to this course. You will need a basic understanding of programming in C or C++ (preferably both). Scripting using Python would be a useful prerequisite. If you could learn a bit of Ruby scripting it would help for the Metasploit module creation. Be familiar with various routing and networking protocols. Course Coverage This course covers ma

PolySetuidExecve1434

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification." http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ Student ID: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-77.php My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolySetuidExecve1434.nasm Published : https://www.exploit-db.com/exploits/41498/ Original Shellcode bytes = 49 My version: Number of bytes = 31 Number of nulls = 0 PolySetuidExecve1434.nasm Intro This shellcode when executed will first setuid(0) and then execute /bin/sh and provide you with a shell. The purpose of calling setuid(0) is, suppose that you have managed to inject this shellcode into an executable that is Set-UID root. I

PolyFlushIPTables1434

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification." http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ Student ID: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-683.php Original size: 50 bytes (don't believe what he says :) My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolyFlushIPTables1434.nasm Published : https://www.exploit-db.com/exploits/41503/ My version: Number of bytes = 47 Number of nulls = 0 PolyFlushIPTables1434.nasm  Intro This shellcode basically just executes /sbin/iptables -F without any other parameters. man iptables "-F, --flush [chain]               Flush  the  selected  chain (all the chains in the table if none i