{ "info": { "author": "David Cannings", "author_email": "david@edeca.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Win32 (MS Windows)", "License :: OSI Approved :: GNU Affero General Public License v3", "Operating System :: Microsoft :: Windows", "Programming Language :: Python :: 2" ], "description": "# Introduction\n\nrtfraptor is a simple tool to aid analysis of malicious RTF files by extracting OLEv1 objects. It was inspired by a \nblog post by Denis O'Brien (link below).\n\nIt works by running Word and intercepting calls to OLEv1 functions. This allows raw OLE objects to be dumped\nfrom memory for further analysis. The tool is designed to be run on Windows.\n\nThis is useful for:\n\n* Avoiding manual analysis of obfuscated RTF files.\n* Extracting malicious objects (packager objects, Equation Editor abuse, embedded documents etc.).\n* Identifying what vulnerabilities (or features) a RTF document is trying to abuse.\n* Verifying the output of other tools (e.g. static document parsers).\n\nThe tool was written by [David Cannings](https://twitter.com/edeca) and is released under the AGPL.\n\n# Example\n\n![Example screen grab](doc/example.gif)\n\n## Installation\n\nInstall rtfraptor like so:\n\n $ pip install rtfraptor\n\nThis will automatically fetch and install dependencies. It is recommended to install in a \n[virtual environment](https://virtualenv.pypa.io/en/latest/userguide/).\n\n## Usage\n\nAt minimum the options `--executable` and `--file` need to be passed, like so:\n\n (analysis_venv) > rtfraptor --executable \"C:\\Program Files\\Microsoft Office\\Office15\\WINWORD.EXE\" --file 7296D52E0713F4BF15CD4E80EF0DA37E.rtf\n \nTo save JSON output and dump the raw OLEv1 objects to disk, pass the following options:\n\n --json output.json --save-path ole_parts\n\n**Note:** this tool runs Word. Analysis of suspicious documents should be done inside a virtual machine. The tool \n**does not** stop any final payload from executing, and you may wish to isolate the virtual machine from any \nnetworking. \n\n## Output\n\n## Raw object output\n\nRaw OLEv1 objects can be stored using the `--save-path` option. Below is an example Packager object which contains \na portable executable file.\n\n```\n00000000 01 05 00 00 02 00 00 00 08 00 00 00 50 61 63 6b |............Pack|\n00000010 61 67 65 00 00 00 00 00 00 00 00 00 fe 12 00 00 |age.........\u00fe...|\n00000020 02 00 63 72 6f 73 73 61 61 61 2e 64 6c 6c 00 43 |..crossaaa.dll.C|\n00000030 3a 5c 63 72 6f 73 73 61 61 61 2e 64 6c 6c 00 00 |:\\crossaaa.dll..|\n00000040 00 03 00 31 00 00 00 43 3a 5c 55 73 65 72 73 5c |...1...C:\\Users\\|\n00000050 52 65 76 65 72 73 65 5c 41 70 70 44 61 74 61 5c |Reverse\\AppData\\|\n00000060 4c 6f 63 61 6c 5c 54 65 6d 70 5c 63 72 6f 73 73 |Local\\Temp\\cross|\n00000070 61 61 61 2e 64 6c 6c 00 00 12 00 00 4d 5a 90 00 |aaa.dll.....MZ..|\n00000080 03 00 00 00 04 00 00 00 ff ff 00 00 b8 00 00 00 |........\u00ff\u00ff..\u00b8...|\n00000090 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|\n000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|\n000000b0 00 00 00 00 00 00 00 00 d8 00 00 00 0e 1f ba 0e |........\u00d8.....\u00ba.|\n000000c0 00 b4 09 cd 21 b8 01 4c cd 21 54 68 69 73 20 70 |.\u00b4.\u00cd!\u00b8.L\u00cd!This p|\n000000d0 72 6f 67 72 61 6d 20 63 61 6e 6e 6f 74 20 62 65 |rogram cannot be|\n000000e0 20 72 75 6e 20 69 6e 20 44 4f 53 20 6d 6f 64 65 | run in DOS mode|\n... snip ...\n```\n\n## Console output\n\nConsole output is generated listing any suspicious OLE objects (those in \n[`oletools.common.clsid`](https://github.com/decalage2/oletools/blob/master/oletools/common/clsid.py)):\n\n```\n(analysis_venv) > rtfraptor --executable \"C:\\Program Files\\Microsoft Office\\Office15\\WINWORD.EXE\" --file 7296D52E0713F4BF15CD4E80EF0DA37E.rtf --json output.json --save-path ole_parts\nWARNING Suspicious OLE object loaded, class id 00020821-0000-0000-C000-000000000046 (Microsoft Excel.Chart.8)\nWARNING Object size is 390702, SHA256 is 2a7f92bf37cef77c4fa2e97fcf3478b3e4e4296514817bd8c12e58300b485406\nWARNING Suspicious OLE object loaded, class id 00020821-0000-0000-C000-000000000046 (Microsoft Excel.Chart.8)\nWARNING Object size is 390190, SHA256 is f8ac5b37f52b6316178c293704fcc762d0a29d2700c7eda53724f552413c7b98\nWARNING Suspicious OLE object loaded, class id F20DA720-C02F-11CE-927B-0800095AE340 (OLE Package Object (may contain and run any file))\nWARNING Object size is 359115, SHA256 is 2ea248d43d4bd53e234530db0de2517a7f44deba5f43367636232019b2e9e822\nWARNING Suspicious OLE object loaded, class id F20DA720-C02F-11CE-927B-0800095AE340 (OLE Package Object (may contain and run any file))\nWARNING Object size is 4902, SHA256 is 28c9afbe46a35a6d7115ca3da535854efddc9749f1ff13722fa98d2bd3a8122b\nWARNING Suspicious OLE object loaded, class id F20DA720-C02F-11CE-927B-0800095AE340 (OLE Package Object (may contain and run any file))\nWARNING Object size is 5926, SHA256 is 5b5850f3217e8465d6add2da18a495d87d33552c6c8f400e52e5ab9cf06ba2e9\nWARNING Suspicious OLE object loaded, class id 0002CE02-0000-0000-C000-000000000046 (Microsoft Equation 3.0 (Known Related to CVE-2017-11882 or CVE-2018-0802))\nWARNING Object size is 7727, SHA256 is 38d9e74ede4ef67e78e028ecd815c54a777e11c6c4e7838ecbe26fd7e7c03d7c\nWARNING Suspicious OLE object loaded, class id 0002CE02-0000-0000-C000-000000000046 (Microsoft Equation 3.0 (Known Related to CVE-2017-11882 or CVE-2018-0802))\nWARNING Object size is 7727, SHA256 is a612b7b97f021797c5911cfe02bd9a145f96abb880990830eaf021f98a4a7c8a\n```\n\n## JSON output\n\nThe tool will produce output in JSON format if the `--json` option is passed. This can be used for further processing,\nand is in the following format:\n\n```\n{\n \"sha256\": \"8326bcb300389a2d654e6e921e259e553f33f8949984c2da55ccb6e9ed3f6480\",\n \"input_file\": \"7296D52E0713F4BF15CD4E80EF0DA37E.rtf\",\n \"objects\": {\n \"0\": {\n \"class_id\": \"00020821-0000-0000-C000-000000000046\",\n \"sha256\": \"2a7f92bf37cef77c4fa2e97fcf3478b3e4e4296514817bd8c12e58300b485406\",\n \"description\": \"Microsoft Excel.Chart.8\",\n \"size\": 390702\n },\n ... snip ...\n \"2\": {\n \"class_id\": \"F20DA720-C02F-11CE-927B-0800095AE340\",\n \"sha256\": \"2ea248d43d4bd53e234530db0de2517a7f44deba5f43367636232019b2e9e822\",\n \"description\": \"OLE Package Object (may contain and run any file)\",\n \"size\": 359115\n },\n ... snip ...\n \"5\": {\n \"class_id\": \"0002CE02-0000-0000-C000-000000000046\",\n \"sha256\": \"38d9e74ede4ef67e78e028ecd815c54a777e11c6c4e7838ecbe26fd7e7c03d7c\",\n \"description\": \"Microsoft Equation 3.0 (Known Related to CVE-2017-11882 or CVE-2018-0802)\",\n \"size\": 7727\n },\n ... snip ...\n}\n```\n\nKeys in `objects` are provided in the order the OLEv1 objects were loaded.\n\n# FAQ\n\n## What do I need to make it work?\n\nAt minimum you'll need:\n \n * Windows - tested on 7, should work from XP to 10\n * Python 2 - tested on 2.7.15 (32-bit)\n * Word - tested with Office 2013 (32-bit)\n \nIn theory 64-bit versions of Office and Python should work. The Python interpreter needs to match Office.\n\n## Why use this instead of `rtfobj`?\n\nStatic analysis is clearly preferable in many cases. However, it's never perfect and emulating a complex parser \nbrings a lot of challenges.\n\nUsing this tool you are guaranteed to obtain accurate OLEv1 data from Word, after RTF obfuscation has been \ndealt with. At minimum it proves useful for comparing the output of other tools.\n\n## Does it work with any Microsoft Office program?\n\nIn theory yes. Word, Excel and Powerpoint should all use the same parts of `ole32.dll`. \n\nHowever, the current approach is aimed at OLEv1. This is used by RTF but is considered legacy. Other formats such as \nComposite Document Format (CDF, as used by `.doc` / `.xls`) and OOXML (as used by `.docx` / `.xslx`) do not typically \nuse OLEv1.\n\n## What versions of Office are supported?\n\nThis tool was tested with Office 2013. It should work with any 32-bit desktop version of Office.\n\nIt's likely that changes would be required to support 64-bit versions of Office. If there is significant demand this \ncan be investigated further.\n\n## How does it work?\n\nAt present the code hooks three functions which are involved in loading an OLEv1 object:\n\n * `ole32!OleConvertOLESTREAMToIStorage` - which converts legacy OLEv1 objects to an objects implementing `IStorage`.\n * `ole32!OleLoad` - which is called when an OLEv1 object is loaded.\n * `ole32!OleGetAutoConvert` - which is called by `OleLoad` to convert the GUID. \n\nThis chain of functions provides the raw OLEv1 data, confirmation it has been loaded and finally the class identifier.\n\nThe method is slightly fragile as `ole32!OleGetAutoConvert` can be called from other (benign) sources. A better \napproach would be to understand the layout of `IStorage` in memory, which might allow a single hook on `ole32!OleLoad`.\n\n## Can this approach be extended?\n\nYes. The primary reason this proof-of-concept has been released is because it can be used in other ways.\n\nFor example, it's possible to intercept calls to functions such as `packager!CopyStreamToFile` or parts of Equation \nEditor. Using this approach you can check function arguments at strategic points to look for invalid data, which \nhelps confirm the vulnerability (or feature) being exploited.\n\nYou can also catch *all* calls to OLE functions (e.g. `combase!StringFromCLSID`) and compare what a \"normal\" \ndocument does versus a malicious one. Using this method it's possible to spot abuse of legitimate features, use of \nWindows scripting languages, potential exploitation of new vulnerabilities etc. \n\nBut be careful - Office applications make use of COM for lots of legitimate purposes (including activation) so you'll \nneed to filter out known good :)\n\n## Can I embed this in my own processing?\n\nYes. The tool is a Python module that can be used from within your own code. \n\nSee `rtfraptor.engine` for the core code and `rtfraptor.app` for the example implementation.\n\n## Why only Python 2?\n\nAlthough I love Python 3, the debugging library used (winappdbg) currently only supports Python 2.\n\n# Known issues\n\n## Safe mode in Word\n\nThe target application (typically Word) is forcibly killed after the timeout expires. This can cause a Safe Mode \nprompt next time the application is started, for example if there is a popup waiting for user input. \n\nIf using the tool manually, raise the timeout and close Word manually. If operating as part of an automated toolchain, \nconsider resetting the virtual machine between runs or deleting the relevant registry keys.\n\n# See also\n\nThe following resources are useful:\n\n* The [blog post](http://malwageddon.blogspot.com/2018/11/deobfuscation-tips-rtf-files.html) by \n [Denis O'Brien](https://twitter.com/Malwageddon) that inspired this tool.\n* [rtfobj](https://github.com/decalage2/oletools/wiki/rtfobj), part of oletools by \n [Decalage](https://twitter.com/decalage2).\n* This [Blackhat 2015 presentation](https://www.blackhat.com/docs/us-15/materials/us-15-Li-Attacking-Interoperability-An-OLE-Edition.pdf) \n on \"Attacking Interoperability\" by [Haifei Li](https://twitter.com/HaifeiLi).\n* The Twitter account for [Mario Vilas](https://twitter.com/Mario_Vilas) who wrote \n [winappdbg](https://github.com/MarioVilas/winappdbg).", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/edeca/rtfraptor", "keywords": "", "license": "GNU Affero General Public License v3", "maintainer": "", "maintainer_email": "", "name": "rtfraptor", "package_url": "https://pypi.org/project/rtfraptor/", "platform": "", "project_url": "https://pypi.org/project/rtfraptor/", "project_urls": { "Homepage": "https://github.com/edeca/rtfraptor" }, "release_url": "https://pypi.org/project/rtfraptor/1.0.0/", "requires_dist": null, "requires_python": "", "summary": "Dump interesting OLE parts from RTF documents by instrumenting Word", "version": "1.0.0" }, "last_serial": 4548887, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "2112fbc331f54ac636ad939d4500d557", "sha256": "9b0fe2852110df67060d3f757f4ecd29c3371455bec3260609c10b644e0dfcf4" }, "downloads": -1, "filename": "rtfraptor-1.0.0.tar.gz", "has_sig": false, "md5_digest": "2112fbc331f54ac636ad939d4500d557", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11270, "upload_time": "2018-11-30T22:41:09", "url": "https://files.pythonhosted.org/packages/7e/18/d28367cee5dc9ce09c4ac113c21f2e7b13d569b09ecf2df8752676fd0ba1/rtfraptor-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2112fbc331f54ac636ad939d4500d557", "sha256": "9b0fe2852110df67060d3f757f4ecd29c3371455bec3260609c10b644e0dfcf4" }, "downloads": -1, "filename": "rtfraptor-1.0.0.tar.gz", "has_sig": false, "md5_digest": "2112fbc331f54ac636ad939d4500d557", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11270, "upload_time": "2018-11-30T22:41:09", "url": "https://files.pythonhosted.org/packages/7e/18/d28367cee5dc9ce09c4ac113c21f2e7b13d569b09ecf2df8752676fd0ba1/rtfraptor-1.0.0.tar.gz" } ] }