Follow the Assembly to Shellcode

Last time in our OS portion of the blog we discussed writing the Helloworld program in assembly using system calls.  Lets keep following the path from assembly to shellcode.

Using the Stack Structure in Our Program

We have mentioned the stack many times when discussing exploits.  In this instance we are returning to the stack but we going to a lower level.  There are some important instructions in the x86 architecture involving the stack.  (A good thing to mention here is that assembly is architecture specific so the x86 does matter.)

  • push – pushes the specified argument onto the stack.
  • pop   – pops a value off the top of the stack and stores in the destination operand (register).
  • call    – calls a function, jumping execution to the specified location.
  • ret     – return from a function, pop return address from the stack and move execution to it.

Think about all four of these actions for a second.  Our goal is to take control of the execution of a system.  Which ones would be helpful in achieving that goal?  Call and ret are the ones that jump execution to a new place, so those are the ones that could potentially offer us an attack surface.

The Code

BITS 32                     ;Tell nasm this is 32-bit code

    call mark_below         ;Call below the string to instructions
    db "Hello World!",0xa,0x0d  ;with newline carriage return bytes

mark_below:
; ssize_t write(int fd, const void *buf, size_t count);
  pop ecx                 ;pop the return address (string ptr) into ecx
  mov eax, 4              ;Write syscall #
  mov ebx, 1              ;STDOUT fd
  mov edx, 15             ;length of string
  int 0x80                ;Execute syscall

; void _exit(int status);
  mov eax, 1            ;exit syscall #
  mov ebx, 0            ;status = 0
  int 0x80              ;execute syscall

In this code we are using the architecture to skew the rules in our favor.  In HTAE it is explained that when we store a string after a call instruction the address of the string is pushed onto the top of the stack.  Then we can pop that address into a register.  Notice that in this version of the helloworld program instead of calling the “Hello World!” string in a variable by mov ecx, msg as we did previously.  Notice that we do have to pop the address to the appropriate register though, ecx.  It is also worth noting that the next instruction address is pushed onto the stack, it doesn’t have to be a string.  It does matter what order things are pushed onto the stack though.  If we were to have more than one string then the last string pushed onto the stack would be the first string address popped off the stack and stored.

Structuring the program in this way has another effect as well.  The way the program executes in the system is different.   This program once assembled is unable to be linked into an executable.  The advantage though is that once the instructions are injected into a program they will just execute.  Lets take a look at some of the differences in these formats in with hexdump.

$ hexdump -C helloworld1
00000000  e8 0e 00 00 00 48 65 6c  6c 6f 20 57 6f 72 6c 64  |.....Hello World|
00000010  21 0a 0d 59 b8 04 00 00  00 bb 01 00 00 00 ba 0f  |!..Y............|
00000020  00 00 00 cd 80 b8 01 00  00 00 bb 00 00 00 00 cd  |................|
00000030  80 

Now lets compare to the helloworld we wrote last time that assembled into a linked executable file.

$ hexdump -C ./a.out
00000000  7f 45 4c 46 01 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 03 00 01 00 00 00  80 80 04 08 34 00 00 00  |............4...|
00000020  9c 01 00 00 00 00 00 00  34 00 20 00 02 00 28 00  |........4. ...(.|
00000030  06 00 03 00 01 00 00 00  00 00 00 00 00 80 04 08  |................|
00000040  00 80 04 08 a2 00 00 00  a2 00 00 00 05 00 00 00  |................|
00000050  00 10 00 00 01 00 00 00  a4 00 00 00 a4 90 04 08  |................|
00000060  a4 90 04 08 0d 00 00 00  0d 00 00 00 06 00 00 00  |................|
00000070  00 10 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000080  b8 04 00 00 00 bb 01 00  00 00 b9 a4 90 04 08 ba  |................|
00000090  0e 00 00 00 cd 80 b8 01  00 00 00 bb 00 00 00 00  |................|
000000a0  cd 80 00 00 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |....Hello World!|
000000b0  0a 00 2e 73 79 6d 74 61  62 00 2e 73 74 72 74 61  |...symtab..strta|
000000c0  62 00 2e 73 68 73 74 72  74 61 62 00 2e 74 65 78  |b..shstrtab..tex|
000000d0  74 00 2e 64 61 74 61 00  00 00 00 00 00 00 00 00  |t..data.........|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 80 80 04 08  |................|
000000f0  00 00 00 00 03 00 01 00  00 00 00 00 a4 90 04 08  |................|
00000100  00 00 00 00 03 00 02 00  01 00 00 00 00 00 00 00  |................|
00000110  00 00 00 00 04 00 f1 ff  10 00 00 00 a4 90 04 08  |................|
00000120  00 00 00 00 00 00 02 00  14 00 00 00 80 80 04 08  |................|
00000130  00 00 00 00 10 00 01 00  1b 00 00 00 b1 90 04 08  |................|
00000140  00 00 00 00 10 00 02 00  27 00 00 00 b1 90 04 08  |........'.......|
00000150  00 00 00 00 10 00 02 00  2e 00 00 00 b4 90 04 08  |................|
00000160  00 00 00 00 10 00 02 00  00 68 65 6c 6c 6f 77 6f  |.........hellowo|
00000170  72 6c 64 2e 61 73 6d 00  6d 73 67 00 5f 73 74 61  |rld.asm.msg._sta|
00000180  72 74 00 5f 5f 62 73 73  5f 73 74 61 72 74 00 5f  |rt.__bss_start._|
00000190  65 64 61 74 61 00 5f 65  6e 64 00 00 00 00 00 00  |edata._end......|
000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

Besides the obvious size difference one of the first things that jumped out to me was the ELF flag is missing in the first one. If you remember from our discussion of hexdump that flags the file as an executable and linkable file format.  We are also able to identify the different assembly program segments in the executable hexdump.  Whereas the first one only contains the string and instructions.

Getting Machine Code to Assembly Code

We have a neat command at our disposal that will convert machine code into assembly code.  Lets take a look at our helloworld1 machine code converted back to assembly instructions.

$ ndisasm -b32 helloworld1
00000000  E80E000000        call dword 0x13
00000005  48                dec eax
00000006  656C              gs insb
00000008  6C                insb
00000009  6F                outsd
0000000A  20576F            and [edi+0x6f],dl
0000000D  726C              jc 0x7b
0000000F  64210A            and [fs:edx],ecx
00000012  0D59B80400        or eax,0x4b859
00000017  0000              add [eax],al
00000019  BB01000000        mov ebx,0x1
0000001E  BA0F000000        mov edx,0xf
00000023  CD80              int 0x80
00000025  B801000000        mov eax,0x1
0000002A  BB00000000        mov ebx,0x0
0000002F  CD80              int 0x80

One of the awesome things about this is we now have a map from our hexdump to assembly.  I’ll leave going through this and understanding each piece to your own discretion, though I would highly recommend it.

The Point

The actual purpose behind this programming experiment is to jump to something that could be considered shellcode.  What we have done with helloworld1 is create a set of instructions that when injected into a running program will just start executing.  In this case all that we could expect to happen is that “Hello World!” would be printed to the screen.  That’s a step in the right direction of getting hello root shell we own the OS.

Next Time

Our helloworld1 instruction set is going to make a visit to the notesearch program we’ve seen before.  We will hopefully get an output of “Hello World!” during execution.  We will have to wait and see though.  If you’ve read HTAE you already know the answer to that hope.  We will learn something along the way though.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s