Thursday, January 29, 2009

Beginning Shellcode

This is again FreeBSD specific for a 64 bit processor.


There's a few things that need to be considered when writing shellcode, that is - you can't have any NOPSs in your ASM code as some operating systems will choke on a NOP. Also, your ASM code should not contain any memory address - we don't know where the application is going to live in memory so you can't accurely rely on calling a particular address. More often than not you'll get junk data or a SEGV.

To get around this memory address problem we can do a few hacky things. Here is one way of doing it, not saying this is the best or only way, this is just what I do.


.data

.text
.global _start
_start:

# Instead of copying things directory into registers
# it's easier to push values into the stack and pop them off
# this way there's no references to memory addresses and there's
# no NOPs
push $4 #size of the string
pop %rdx

push $0x68616c62 # the string 'blah' in reverse
mov %rsp,%rsi

push $1 # file descriptor
pop %rdi

push $4 # write sys call
pop %rax

syscall

push $1
pop %rax # exit syscall
syscall



Using objdump we can see the code is free of hard coded memory addrsses and NOPs. Also notice you the string in the .text section


$ objdump -Ds puts2

puts2: file format elf64-x86-64

Contents of section .text:
4000b0 6a045a68 626c6168 4889e66a 015f6a04 j.ZhblahH..j._j.
4000c0 580f056a 01580f05 X..j.X..
Disassembly of section .text:

00000000004000b0 <_start>:
4000b0: 6a 04 pushq $0x4
4000b2: 5a pop %rdx
4000b3: 68 62 6c 61 68 pushq $0x68616c62
4000b8: 48 89 e6 mov %rsp,%rsi
4000bb: 6a 01 pushq $0x1
4000bd: 5f pop %rdi
4000be: 6a 04 pushq $0x4
4000c0: 58 pop %rax
4000c1: 0f 05 syscall
4000c3: 6a 01 pushq $0x1
4000c5: 58 pop %rax
4000c6: 0f 05 syscall


From this objdump we can gather together the hex characters needed for our shell code. This is :

\x6a\x04\x5a\x68\x62\x6c\x61\x68\x48\x89\xe6\x6a\x01\x5f\x6a\x04\x58\x0f\x05\x6a
\x01\x58\x0f\x05


The following C code can be used to execute this shellcode:


int main ( int argc, char **argv )
{
char code[]= "\x6a\x04\x5a\x68\x62\x6c"
"\x61\x68\x48\x89\xe6\x6a\x01\x5f\x6a\x04"
"\x58\x0f\x05\x6a\x01\x58\x0f\x05";

int (*func)();
func = ( int(*)() ) code;
(int) (*func)();
return 0;

}

No comments: