Re: Shellcode itself segfaults

From: Justin Ferguson (jnferguson@gmail.com)
Date: Tue Jun 20 2006 - 20:10:24 EDT


Hi Goober,

> 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".

Yes main is 'just a symbol', if you have two main's there is a
conflict in the namespace. I hadn't considered that all the original
poster put in his code was the char main[], this changes things a bit
obviously.

> 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):

I apologize, I was incorrect in my statement about argv[], I had a
just woke up blunder and was looking for a pointer to a pointer to
NULL.

>
> 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.

It *could* be it, but I doubt thats the issue, on a 'hardened' box
with a recent GCC it's putting char main[] into the data segment (as
it should). My point still remains that you should *always* make sure
envp is valid, I've encountered plenty of instances where an invalid
envp causes the shellcode to crash, specifically some debian boxes
come to mind.

Finally as the goober said, you, Paul, should put the shellcode in
your code in a manner that is 'well defined' as to what the compiler
is going to do, i.e. on the stack or .data/.bss/heap/whatever.

You may find it nice to do something like this, which allows you to
work on or deploy your shellcode without having to write it out as
opcodes in a character array:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

__asm__ (
        "sc_start: \n"
        "nop \n"
        /* shellcode here */
        "nop \n"
        "sc_end: \n"

);

int
main(void)
{
        extern unsigned char sc_start, sc_end;
        unsigned char *sc = NULL;
        size_t sc_len = &sc_end - &sc_start;
        void (*exec_ptr)() = NULL;

        /* change calloc() to alloca() or similar
         * if you need the code on the stack
         * instead of on the heap
         */
        sc = calloc(sc_len, (size_t)1);

        if (NULL == sc) {
                perror("calloc()");
                return EXIT_FAILURE;
        }

        memcpy(sc, &sc_start, sc_len);

        exec_ptr = (void *)sc;

        exec_ptr();

        return EXIT_SUCCESS;
}

------------------------------------------------------------------------------
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