├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── LICENSE ├── README.md ├── analyse_obfuscation ├── __init__.py ├── helpers.py ├── output_results.py ├── run.py └── test_process_obfuscation.py ├── docs └── screenshot.png ├── requirements.txt ├── sample ├── .keep ├── inputs │ ├── file.cs │ ├── file.sct │ ├── file.vbs │ ├── sleep.vbs │ └── x86.dll └── sample.jsonl ├── sample_results ├── arp.log ├── at.log ├── bitsadmin.log ├── cacls.log ├── certutil.log ├── cmdkey.log ├── cmstp.log ├── csc.log ├── curl.log ├── findstr.log ├── fltmc.log ├── forfiles.log ├── icacls.log ├── ipconfig.log ├── jsc.log ├── mpcmdrun.log ├── msiexec.log ├── net.log ├── netsh.log ├── netstat.log ├── nslookup.log ├── ping.log ├── powershell.log ├── reg.log ├── regsvr32.log ├── robocopy.log ├── route.log ├── sc.log ├── schtasks.log ├── systeminfo.log ├── takeown.log ├── taskkill.log ├── tasklist.log ├── vbc.log ├── vssadmin.log ├── wevtutil.log ├── winrm.cmd.log ├── winrs.log └── wmic.log └── setup.py /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python 3.9 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: 3.9 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install flake8 pytest 27 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 28 | - name: Lint with flake8 29 | run: | 30 | # stop the build if there are Python syntax errors or undefined names 31 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 32 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 33 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | typings/ 132 | 133 | .vscode/ 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows Command-Line Obfuscation 2 | 3 | ## Background 4 | 5 | `analyse_obfuscation` is a python3 module for finding common command-line obfuscation techniques for a given program, as described in [this](https://wietze.github.io/blog/windows-command-line-obfuscation) blog post. 6 | 7 | By providing one or more commands, `analyse_obfuscation` will test if the following obfuscation techniques can be applied: 8 | 9 | 1) **Option Char substitution** 10 | 11 | _e.g. `ping -n 1 localhost` == `ping /n 1 localhost`_ 12 | 13 | 2) **Character substitution** 14 | 15 | _e.g. `reg eˣport HKCU out.reg` == `reg export HKCU out.reg`_ 16 | 17 | 3) **Character insertion** 18 | 19 | _e.g. `wevtutil gࢯli (…)` == `wevtutil gli (…)`_ 20 | 21 | 4) **Quotes insertion** 22 | 23 | _e.g. `netsh ad"vfi"rewall show (…)` == `netsh advfirewall show (…)`_ 24 | 25 | 5) **Shorthands** 26 | 27 | _e.g. `powershell /encod (…)` == `powershell /encodedcommand (…)`_ 28 | 29 | ## Goals 30 | 31 | Note that the goal of this project is to show that a given executable/command line can be obfuscated, not to give a complete list of possible obfuscations for a given command. It should however be possible to derive different obfuscation opportunities from `analyse_obfuscation`'s output. 32 | 33 | Blue teamers 🔵 may want to use this tool, for example, to check if an executable they have written a detection rule is vulnerable to command-line obfuscation, meaning the rule should be improved or additional rules are needed. Note that in some cases this game is unwinnable - please take a look at the recommendations in the [blog post](https://wietze.github.io/blog/windows-command-line-obfuscation) for suggestions on how to tackle this. 34 | 35 | Red teamers 🔴 may want to use this tool to find opportunities for bypassing simple detection rules. 36 | 37 | ## Usage 38 | 39 | ### Run 40 | 41 | The simplest way to use this project is by running it (without installation). 42 | 43 | * **Run script**: clone the entire repository, install all dependencies (`python3 -m pip install -r requirements.txt`) and run via: 44 | 45 | ```bash 46 | python3 -m analyse_obfuscation.run --help 47 | ``` 48 | 49 | ### Install 50 | 51 | By installing the project, it will be possible to simply call `analyse_obfuscation` from the command line. 52 | 53 | * **Via PyPI**: install the application via for example pip: 54 | 55 | ```bash 56 | python3 -m pip install analyse_obfuscation 57 | ``` 58 | 59 | * **From source**: you can install a local version of the module by cloning the entire repository, followed by these commands: 60 | (note that this requires `setuptools` to be installed) 61 | 62 | ```bash 63 | python3 setup.py sdist bdist_wheel 64 | python3 -m pip install dist/analyse_obfuscation-*-py3-none-any.whl --upgrade 65 | ``` 66 | 67 | ## Examples 68 | 69 | ![Screenshot](docs/screenshot.png) 70 | _Sample execution output of `analyse_obfuscation`_ 71 | 72 | Each execution generates a high-level result overview on the stdout, as can be seen in the screenshot. Additionally a .log file providing examples of commands found to be working is created. Sample report files generated by the below commands can be found in the [sample_results/](sample_results/) folder. 73 | 74 | ```bash 75 | # Check simple 'ping' command 76 | analyse_obfuscation --command "ping /n 1 localhost" 77 | 78 | # Check 'net share' command using {random}, which will be replaced by random string for each execution 79 | analyse_obfuscation --command "net share x=c:\ /remark:{random}" 80 | 81 | # Check 'powershell /encodedcommand' command with increased timeout, as executions tend to take long 82 | analyse_obfuscation --command "powershell /encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA==" --timeout 5 83 | 84 | # Check 'systeminfo' command by only looking at the exit code, not the output - since every output will be different due to (changing) timestamps 85 | analyse_obfuscation --command "systeminfo /s localhost" --timeout 5 --exit_code_only 86 | 87 | # Check all commands as specified in sample.json, saving all reports in 'reports/' 88 | analyse_obfuscation --json_file sample/sample.json --report_dir reports/ 89 | ``` 90 | 91 | **Note** that the results may contain false positives - especially when single-character command-line options are being tested (such as `/n` in `ping /n 1 localhost`). In such cases, character insertion (method 3) may contain whitespace characters, which doesn't really 'count' as insertion character as whitespaces between command-line arguments are usually filtered out anyway. Similarly, character substitution (method 2) may change the entire option: e.g. `ping /s 1 localhost` and `ping /r 1 localhost` are functionally different, but happen to give the same output. 92 | 93 | ## All options 94 | 95 | All command-line options of this project can be requested by using the `--help` option: 96 | 97 | ``` 98 | usage: analyse_obfuscation [--threads n] [--verbose] [--quiet] [--report_dir c:\path\to\dir] [--log_file c:\path\to\file.log] [--help] [--command "proc /arg1 /arg2"] 99 | [--range {full,educated,ascii,custom}] [--custom_range 0x??..0x?? [0x??..0x?? ...]] [--char_offset n] [--pre_command process_name] 100 | [--post_command process_name] [--exit_code_only] [--timeout n] [--json_file c:\path\to\file.jsonl] 101 | 102 | Tool for identifying executables that have command-line options that can be obfuscated. 103 | 104 | required arguments (either is required): 105 | --command "proc /arg1 /arg2" 106 | Single command to test 107 | --json_file c:\path\to\file.jsonl 108 | Path to JSON file (JSON Line formatted) containing commands config 109 | 110 | optional --command arguments: 111 | --range {full,educated,ascii,custom} 112 | Character range to scan (default=educated) 113 | --custom_range 0x??..0x?? [0x??..0x?? ...] 114 | Range to scan 115 | --char_offset n Character position used for insertion and replacement 116 | --pre_command process_name 117 | Command to run unconditionally before each attempt, piping the result to the stdin 118 | --post_command process_name 119 | Command to run unconditionally after each attempt (e.g. to clean up) 120 | --exit_code_only Only base success on the exit code (and not the output of the command) 121 | --timeout n Number of seconds per execution before timing out. 122 | 123 | optional arguments: 124 | --threads n Number of threads to use 125 | --verbose Increase output verbosity 126 | --quiet Decrease output verbosity 127 | --report_dir c:\path\to\dir 128 | Path to save report files to 129 | --log_file c:\path\to\file.log 130 | Path to save log to 131 | --help Show this help message and exit 132 | ``` 133 | 134 | ## Repository Contents 135 | 136 | Item|Description 137 | -|- 138 | [analyse_obfuscation/](analyse_obfuscation) | Code for python3 module, enabling one to analyse executables for common command-line obfuscation techniques. 139 | [sample/](sample/) | Sample config file to analyse built-in Windows executables, as well as related input files. Used to generate results in the above folder. 140 | [sample_results/](sample_results/) | Report files generated using the JSONL file in the above sample folder. 141 | -------------------------------------------------------------------------------- /analyse_obfuscation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wietze/windows-command-line-obfuscation/dd9c29e82ffc8375e97fabb98971c9c19ca01326/analyse_obfuscation/__init__.py -------------------------------------------------------------------------------- /analyse_obfuscation/helpers.py: -------------------------------------------------------------------------------- 1 | import enum 2 | import itertools 3 | import logging 4 | from typing import List 5 | 6 | import tqdm 7 | 8 | 9 | class SpecialCharOperation(enum.Enum): 10 | INSERT = 1 11 | REPLACE = 2 12 | 13 | 14 | class TqdmHandler(logging.Handler): 15 | def emit(self, record: logging.LogRecord): 16 | try: 17 | msg = self.format(record) 18 | tqdm.tqdm.write(msg) 19 | self.flush() 20 | except (KeyboardInterrupt, SystemExit): 21 | raise 22 | except: 23 | self.handleError(record) 24 | 25 | 26 | def ranges(i: List[int]) -> str: 27 | """Turns a list of integers to a string representation of the contained ranges""" 28 | result = [] 29 | for _, b in itertools.groupby(enumerate(i), lambda pair: pair[1] - pair[0]): 30 | b = list(b) 31 | result.append((b[0][1], b[-1][1])) 32 | 33 | return ' '.join(['0x{:0>4X}..0x{:0>4X}'.format(x, y) for x, y in result]) 34 | -------------------------------------------------------------------------------- /analyse_obfuscation/output_results.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import os 3 | import re 4 | from typing import Dict, List, Set, Tuple, Union 5 | 6 | import colorama 7 | import terminaltables 8 | 9 | from .helpers import ranges 10 | 11 | colorama.init() 12 | 13 | 14 | def print_results(results: Dict[str, Dict[str, Union[Set[Tuple[int, str]], str, None]]]) -> None: 15 | """ For a dict with (test, result_dict), prepare a terminaltables AsciiTable and print to stdout """ 16 | matrix = [['Process', 'Option Char', 'Char (insert)', 'Char (replace)', 'Quotes (insert)', 'Shorthands']] 17 | for display_name, test_outcomes in results.items(): 18 | matrix.append([display_name] + [parse_outcome(test_outcome) for test_outcome in test_outcomes.values()]) 19 | 20 | print(terminaltables.AsciiTable(matrix).table) 21 | 22 | 23 | def parse_outcome(value: Union[Set[Tuple[int, str]], str, None]) -> str: 24 | """Prepare a terminal-printable output based on a given test outcome""" 25 | 26 | if value is None: # If value is None, disregard 27 | return 'N/A' 28 | elif value: # If value is positive, return Yes 29 | return_format = str(colorama.Back.GREEN) + '{}' + str(colorama.Style.RESET_ALL) 30 | if isinstance(value, str): # If result is a string, only output Yes 31 | return return_format.format('Yes') 32 | elif isinstance(value, set): # If result is a list, provide a count as well 33 | return return_format.format('Yes ({})'.format(len(value))) 34 | else: 35 | raise Exception("Unknown result type {}".format(type(value))) 36 | else: # Value is negative, return No 37 | return str(colorama.Back.RED) + 'No' + str(colorama.Style.RESET_ALL) 38 | 39 | 40 | def write_report(report_dir: str, name: str, command: str, char_offset: int, scan_range: List[int], test_outcomes: Dict[str, Union[Set[Tuple[int, str]], str, None]]) -> None: 41 | """Write a report, containing test results, to a given directory""" 42 | 43 | # Prepare output path 44 | file_name = '{}.log'.format(re.sub(r'[\\/*?:"<>|]', "", name)) 45 | output_file = os.path.join(report_dir, file_name) 46 | 47 | # Open file 48 | with open(output_file, 'w', encoding='utf-16le') as f: 49 | # Print header 50 | f.write('PROCESS OBFUSCATION REPORT FOR {}\n'.format(name)) 51 | f.write('- Generated on {}\n'.format(datetime.datetime.now().isoformat())) 52 | f.write('- Command used : {}\n'.format(command)) 53 | f.write('- Insertion position: {}\n'.format((' '*char_offset)+'^')) 54 | f.write('- Char ranges scanned: {}\n'.format(ranges(scan_range))) 55 | 56 | # Dash/hypten test 57 | if 'option_char' in test_outcomes: 58 | f.write('\n:: Option Char Substitution\n') 59 | outcomes = test_outcomes['option_char'] 60 | if outcomes is not None: 61 | if outcomes: 62 | f.write('The following {} commands were found to be working:\n'.format(len(outcomes))) 63 | for identifier, command in sorted(outcomes, key=lambda x: x[0]): 64 | f.write('0x{:0>4X} : {}\n'.format(identifier, command)) 65 | else: 66 | f.write('No alternative commands were found.\n') 67 | else: 68 | f.write('The command does not contain any arguments starting with a slash or dash.\n') 69 | 70 | # Character insertion test 71 | outcomes = test_outcomes.get('char_insert') 72 | if outcomes is not None: 73 | f.write('\n:: Character Insertion\n') 74 | if outcomes: 75 | f.write('The following {} commands were found to be working:\n'.format(len(outcomes))) 76 | for identifier, command in sorted(outcomes, key=lambda x: x[0]): 77 | try: 78 | f.write('0x{:0>4X} : {}\n'.format(identifier, command)) 79 | except: 80 | f.write('0x{:0>4X} : (character can not be printed)\n'.format(identifier)) 81 | else: 82 | f.write('No alternative commands were found.\n') 83 | 84 | # Character substitution test 85 | outcomes = test_outcomes.get('char_substitute') 86 | if outcomes is not None: 87 | f.write('\n:: Character Substitution\n') 88 | if outcomes: 89 | f.write('The following commands were found to be working:\n') 90 | for identifier, command in sorted(outcomes, key=lambda x: x[0]): 91 | try: 92 | f.write('0x{:0>4X} : {}\n'.format(identifier, command)) 93 | except: 94 | f.write('0x{:0>4X} : (character can not be printed)\n'.format(identifier)) 95 | else: 96 | f.write('No alternative commands were found.\n') 97 | 98 | # Quote insertion test 99 | outcome = test_outcomes.get('quotes') 100 | if outcome is not None: 101 | f.write('\n:: Quote Insertion\n') 102 | if outcome: 103 | f.write('Inserting quotes in the first argument did work, such as:\n') 104 | f.write('{}\n'.format(outcome)) 105 | else: 106 | f.write('Inserting quotes in the first argument did not appear to be working.\n') 107 | 108 | # Shorthand commands 109 | outcomes = test_outcomes.get('shorthands') 110 | f.write('\n:: Shorthand Commands\n') 111 | if outcomes is not None: 112 | if outcomes: 113 | f.write('The following {} commands were found to be working:\n'.format(len(outcomes))) 114 | for identifier, command in sorted(outcomes, key=lambda x: len(x[1])): 115 | f.write('{}\n'.format(command)) 116 | else: 117 | f.write('No alternative commands were found.\n') 118 | else: 119 | f.write('The command is too short to be further shortened.\n') 120 | -------------------------------------------------------------------------------- /analyse_obfuscation/run.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | import logging 4 | import os 5 | import re 6 | import shlex 7 | from argparse import Namespace 8 | from typing import List, Tuple 9 | 10 | import tqdm 11 | 12 | from .helpers import SpecialCharOperation, TqdmHandler 13 | from .output_results import print_results, write_report 14 | from .test_process_obfuscation import TestCase, TestProcessObfuscation 15 | 16 | TESTS = {'option_char': lambda test, test_case: test.check_option_char(test_case.arg_index), 17 | 'char_insert': lambda test, test_case: test.check_special_chars(test_case.char_offset, SpecialCharOperation.INSERT), 18 | 'char_substitute': lambda test, test_case: test.check_special_chars(test_case.char_offset, SpecialCharOperation.REPLACE), 19 | 'quotes': lambda test, test_case: test.check_quote_injection(test_case.arg_index), 20 | 'shorthands': lambda test, test_case: test.check_shortened_option(test_case.arg_index)} 21 | 22 | 23 | def run_tests(test_cases: List[TestCase], threads: int, report_dir: str, log: logging.Logger) -> None: 24 | """ For a list of commands: run tests, create reports, write summary to stdout """ 25 | result = {} 26 | with tqdm.tqdm(test_cases, position=0, disable=len(test_cases) <= 1) as pbar: 27 | for test_case in pbar: 28 | # Extract display name 29 | _, display_name = os.path.split(test_case.command[0].strip('"')) 30 | pbar.set_description('Testing {}'.format(display_name)) 31 | 32 | try: 33 | # Create test class 34 | test = TestProcessObfuscation(test_case, threads, log) 35 | 36 | # Run individual tests 37 | test_outcomes = dict() 38 | for subtest, function in TESTS.items(): 39 | test_outcomes[subtest] = function(test, test_case) if not test_case.tests or subtest in test_case.tests else None 40 | 41 | # Parse results 42 | result[display_name] = test_outcomes 43 | 44 | # Write report 45 | write_report(report_dir, display_name, ' '.join(test_case.command), test_case.char_offset, test_case.scan_range, test_outcomes) 46 | except Exception: 47 | log.error("Unexpected error when executing", exc_info=True) 48 | 49 | # Print results to stdout 50 | print_results(result) 51 | 52 | 53 | def prepare_command(parser: argparse.ArgumentParser, command_flat: str, char_offset: int) -> Tuple[List[str], int, int]: 54 | """ Turns a flattened command string into a list, and generates a character offset in case none was provided """ 55 | log.info("Preparing parameters for {}".format(command_flat)) 56 | command_list = shlex.split(command_flat, posix=os.sep == '/') 57 | arg_index = -1 58 | if char_offset is not None: 59 | if not (0 <= char_offset and char_offset < len(command_flat)): 60 | parser.error("char offset not within bounds of (0 .. command length)") 61 | else: 62 | selected_char = command_flat[char_offset] 63 | if (0 <= char_offset and char_offset < len(command_list[0])): 64 | parser.error("cannot add characters to process name") 65 | if not re.findall(r'[a-zA-Z0-9]', selected_char): 66 | parser.error("selected char '{}' is not alphanumeric".format(selected_char)) 67 | 68 | i = 0 69 | for arg_index, arg in enumerate(command_list): 70 | i += len(arg) 71 | if i > char_offset: 72 | break 73 | else: 74 | # Second char of first argument (not counting process name) 75 | arg_index = TestProcessObfuscation.select_arg_index(command_list, None) 76 | command_part_offset = TestProcessObfuscation.get_command_part_offset(command_list[arg_index].split(':')[0]) 77 | 78 | char_offset = len(' '.join(command_list[0:arg_index])) + command_part_offset 79 | 80 | log.info("No char offset specified - using second char of first argument instead") 81 | log.info("Char offset = {} (char '{}', argument index = {})".format(char_offset, command_flat[char_offset], arg_index)) 82 | return (command_list, char_offset, arg_index) 83 | 84 | 85 | def create_test_case(args: Namespace, parser: argparse.ArgumentParser, json_file: bool) -> TestCase: 86 | """Generates a TestCase object based on the given arguments (either on the command line or in the JSON file)""" 87 | 88 | command = None 89 | if args.command: 90 | command, char_offset, arg_index = prepare_command(parser, args.command, args.char_offset) 91 | else: 92 | raise ValueError("'--command' is required" if not json_file else "'command' should be specified") 93 | 94 | # Parse char scan range options 95 | scan_range = None 96 | 97 | if args.custom_range: 98 | if (args.range is None or args.range == 'custom'): 99 | scan_range = sum(args.custom_range, []) 100 | if 0 in scan_range: 101 | parser.error("null bytes can not be included in custom ranges. Try starting from 1 instead.") 102 | else: 103 | raise ValueError("--custom_range can not be set when --range is not set to 'custom'.") 104 | elif args.range is None or args.range == 'educated': 105 | scan_range = list(range(0x01, 0xFF)) + list(range(0x0100, 0x052F)) + list(range(0x2070, 0x218F)) + list(range(0xFF00, 0xFFEF)) 106 | elif args.range == 'full': 107 | scan_range = list(range(0x01, 0xFFFF)) 108 | elif args.range == 'ascii': 109 | scan_range = list(range(0x01, 0xFF)) 110 | else: 111 | raise ValueError("Unexpected range '{}'".format(args.range)) 112 | 113 | log.info('{} range selected ({} values)'.format(args.range, len(scan_range))) 114 | 115 | # Parse report output dir 116 | log.info('Report files will be stored in {}'.format(os.path.abspath(args.report_dir))) 117 | if not os.path.isdir(args.report_dir): 118 | parser.error("path specified in --report_dir does not exist.") 119 | 120 | return TestCase(command=command, char_offset=char_offset, arg_index=arg_index, scan_range=scan_range, pre_command=args.pre_command, post_command=args.post_command, exit_code_only=args.exit_code_only, timeout=args.timeout, tests=args.tests) 121 | 122 | 123 | # Prepare logger 124 | log = logging.getLogger(__name__) 125 | log.setLevel(logging.DEBUG) 126 | 127 | 128 | def parse_arguments() -> None: 129 | # Prepare arguments 130 | parser = argparse.ArgumentParser(add_help=False, description='Tool for identifying executables that have command-line options that can be obfuscated.') 131 | 132 | parser._action_groups.pop() 133 | required = parser.add_argument_group('required arguments (either is required)') 134 | optional_c = parser.add_argument_group('optional --command arguments') 135 | optional = parser.add_argument_group('optional arguments') 136 | 137 | # Global settings 138 | optional.add_argument('--threads', metavar='n', type=int, help='Number of threads to use', default=None) 139 | optional.add_argument('--verbose', action='store_true', help='Increase output verbosity') 140 | optional.add_argument('--quiet', action='store_true', help='Decrease output verbosity') 141 | optional.add_argument('--report_dir', metavar='c:\\path\\to\\dir', type=str, help='Path to save report files to', default="."+os.sep) 142 | optional.add_argument('--log_file', metavar='c:\\path\\to\\file.log', type=str, help='Path to save log to') 143 | optional.add_argument('--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit') 144 | 145 | # Single command options 146 | required.add_argument('--command', metavar='"proc /arg1 /arg2"', type=str, help='Single command to test') 147 | optional_c.add_argument('--range', choices=['full', 'educated', 'ascii', 'custom'], help='Character range to scan (default=educated)') 148 | optional_c.add_argument('--custom_range', metavar='0x??..0x??', type=lambda x: list(range(int(x.split('..')[0], 0), int(x.split('..')[1], 0))), nargs='+', help='Range to scan') 149 | optional_c.add_argument('--char_offset', metavar='n', type=int, help='Character position used for insertion and replacement') 150 | optional_c.add_argument('--pre_command', metavar='process_name', type=str, help='Command to run unconditionally before each attempt, piping the result to the stdin') 151 | optional_c.add_argument('--post_command', metavar='process_name', type=str, help='Command to run unconditionally after each attempt (e.g. to clean up)') 152 | optional_c.add_argument('--exit_code_only', action='store_true', help='Only base success on the exit code (and not the output of the command)') 153 | optional_c.add_argument('--timeout', metavar='n', type=float, help='Number of seconds per execution before timing out.', default=2) 154 | optional_c.add_argument('--tests', choices=list(TESTS.keys()), type=str, nargs='+', help='Number of seconds per execution before timing out.', default=None) 155 | 156 | # JSON File options 157 | required.add_argument('--json_file', metavar='c:\\path\\to\\file.jsonl', type=str, help='Path to JSON file (JSON Line formatted) containing commands config') 158 | 159 | args = parser.parse_args() 160 | 161 | tests = [] 162 | 163 | # Parse verbosity options 164 | stream_handler = TqdmHandler() 165 | stream_handler.setFormatter(logging.Formatter("[%(levelname)-.4s] %(message)s")) 166 | if args.verbose: 167 | stream_handler.setLevel(logging.DEBUG) 168 | elif args.quiet: 169 | stream_handler.setLevel(logging.ERROR) 170 | else: 171 | stream_handler.setLevel(logging.WARNING) 172 | log.addHandler(stream_handler) 173 | 174 | # Parse log file options 175 | if args.log_file: 176 | file_path = os.path.abspath(args.log_file) 177 | file_handler = logging.FileHandler(file_path, 'w', encoding='utf-16le') 178 | file_handler.setLevel(logging.DEBUG) 179 | file_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)-.4s] (%(threadName)-10s) %(message)s')) 180 | log.addHandler(file_handler) 181 | 182 | if args.json_file: 183 | single_command_args = ['command', 'range', 'custom_range', 'char_offset', 'pre_command', 'post_command', 'exit_code_only', 'tests'] 184 | given_args = {key: value for (key, value) in args._get_kwargs()} 185 | if any([given_args[x] for x in single_command_args]): 186 | raise ValueError("When --json_file is specified, the following arguments should not be specified on the command line but in the JSON file: {}".format(', '.join(single_command_args))) 187 | 188 | with open(args.json_file, 'rt') as f: 189 | for line in f.readlines(): 190 | if not line.strip(): 191 | continue 192 | t_args = argparse.Namespace() 193 | t_args.__dict__.update(json.loads(line)) 194 | args = parser.parse_args(namespace=t_args) 195 | tests.append(create_test_case(args, parser, True)) 196 | else: 197 | tests = [create_test_case(args, parser, False)] 198 | 199 | run_tests(tests, threads=args.threads, report_dir=args.report_dir, log=log) 200 | 201 | 202 | if __name__ == "__main__": 203 | parse_arguments() 204 | -------------------------------------------------------------------------------- /analyse_obfuscation/test_process_obfuscation.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import random 4 | import re 5 | import shlex 6 | import subprocess 7 | from multiprocessing.pool import ThreadPool 8 | from typing import List, Set, Tuple, Union 9 | 10 | import tqdm 11 | 12 | from .helpers import SpecialCharOperation 13 | 14 | 15 | class TestCase(): 16 | def __init__(self, command: List[str], char_offset: int, arg_index: int, scan_range: List[int], pre_command: List[str], post_command: List[str], exit_code_only: bool, timeout: int, tests:List[str]): 17 | self.command = command 18 | self.char_offset = char_offset 19 | self.arg_index = arg_index 20 | self.scan_range = scan_range 21 | self.pre_command = pre_command 22 | self.post_command = post_command 23 | self.exit_code_only = exit_code_only 24 | self.timeout = timeout 25 | self.tests = tests 26 | 27 | 28 | class TestProcessObfuscation(): 29 | def __init__(self, test_case: TestCase, threads: int, log: logging.Logger): 30 | self.log = log 31 | self.command = test_case.command 32 | self.command_flat = ' '.join(test_case.command) 33 | self.pre_command = test_case.pre_command 34 | self.post_command = test_case.post_command 35 | self.expected_code, self.expected_output = self.__get_expected_result__() 36 | self.exit_code_only = test_case.exit_code_only 37 | self.scan_range = test_case.scan_range 38 | self.timeout = test_case.timeout 39 | self.threads = threads 40 | self.tqdm = None 41 | 42 | # Class Methods 43 | @classmethod 44 | def __randomise__(cls, command_parts: str) -> str: 45 | randomised = ''.join(random.choices('0123456789ABCDEF', k=10)) 46 | return command_parts.replace('{random}', randomised) 47 | 48 | @classmethod 49 | def select_arg_index(cls, command: List[str], arg_index: Union[int, None]) -> int: 50 | # Iterate over command-line arguments 51 | for i, command_part in enumerate(command): 52 | # The first argument will be the process, so ignore 53 | if i == 0 or (arg_index is not None and i != arg_index): 54 | continue 55 | # Check if the first character is a slash or hyphen - if so, select it 56 | if command_part[0] in ['/', '-']: 57 | return i 58 | # If no option char was found, fall back to the first argument 59 | # (least likely to be something like a filename) 60 | return 1 61 | 62 | @classmethod 63 | def get_command_part_offset(cls, command_part: str) -> int: 64 | # We prefer the below chars, because they have 'equivalents' in the Spacing Modifier Letters range (0x02B0 - 0x02FF) 65 | preferred_chars = 'hjrwyxsl' 66 | # Iterate over each char in the given command-line optoin 67 | for i, char in enumerate(command_part.lower()): 68 | # Ignore the first one - it will either be an option char, or 69 | # the first char of a keyword which is usually not the best candidate 70 | if i == 0: 71 | continue 72 | if any([char == preferred_char for preferred_char in preferred_chars]): 73 | return i+1 74 | 75 | return (2 if command_part[1] != '-' else 3) if len(command_part) > 1 else 1 76 | 77 | def __get_expected_result__(self) -> Tuple[int, str]: 78 | # Prepare command to run 79 | command = self.__randomise__(self.command_flat) 80 | # Run 'normal' command to get expected exit code 81 | try: 82 | result = self.__execute_command__(command, pre_command=self.pre_command) 83 | exit_code, stdout = result.returncode, "{} / {}".format(result.stdout, result.stderr) 84 | # Check if observed exit code is 0 85 | if exit_code != 0: 86 | self.log.warning("Observed exit code is {}, which is not 0 as usual".format(exit_code)) 87 | self.log.warning("Test outcome may contain unexpected results") 88 | self.log.warning(stdout) 89 | # sys.exit(-1) 90 | except FileNotFoundError: 91 | self.log.error("Command \"{}\" could not be executed: file not found".format(command)) 92 | raise 93 | return exit_code, stdout 94 | 95 | # Private Methods 96 | def __test_commands__(self, test: str, commands: List[Tuple[int, str]]) -> Set[Tuple[int, str]]: 97 | self.log.info('Preparing {} commands to run'.format(len(commands))) 98 | # Prepare ThreadPool 99 | with ThreadPool(self.threads) as thread_pool: 100 | # Prepare progress bar 101 | with tqdm.tqdm(total=len(commands), desc=test, position=1, leave=False) as self.tqdm: 102 | # Submit all commands to ThreadPool, collect results 103 | outcomes = list(thread_pool.map(self.__run_command__, [command for _, command in commands])) 104 | # Return all results when output was True 105 | return set([(identifier, command) for outcome, (identifier, command) in zip(outcomes, commands) if outcome]) 106 | 107 | def __run_command__(self, command: str): 108 | # Prepare command 109 | command = self.__randomise__(command) 110 | # self.log.info('About to run command "{}"'.format(shlex.split(command, posix=False))) 111 | try: 112 | # Run command 113 | result = self.__execute_command__(command, timeout=self.timeout, pre_command=self.pre_command) 114 | exit_code, stdout = result.returncode, "{} / {}".format(result.stdout, result.stderr) 115 | self.log.info('Exit code {} observed ({} desired) for {}'.format(exit_code, self.expected_code, command)) 116 | # Return result 117 | return exit_code == self.expected_code and (self.exit_code_only or stdout == self.expected_output) 118 | except subprocess.TimeoutExpired: 119 | self.log.warning('Timeout ({}s) elapsed for command "{}"'.format(self.timeout, command)) 120 | return False 121 | except Exception as e: 122 | self.log.info("Exception when executing \"{}\": {}".format(command, e)) 123 | return False 124 | finally: 125 | if self.post_command: 126 | result = None 127 | try: 128 | result = self.__execute_command__(self.post_command) 129 | except Exception as e: 130 | self.log.warning("Post command caused exception ({})".format(e)) 131 | finally: 132 | self.log.info("Post command exited with exit code {}".format(result.returncode if result else "?")) 133 | if self.tqdm: 134 | self.tqdm.update() 135 | 136 | def __get_option_argument__(self, arg_index: int) -> int: 137 | return self.select_arg_index(self.command, arg_index) 138 | 139 | def __execute_command__(self, command: str, timeout: int = None, pre_command: list[str] = []) -> subprocess.CompletedProcess: 140 | cmd = command.split(' ') # list(shlex.shlex(command, punctuation_chars=True, posix=True)) #[shlex.quote(c) for c in shlex.split(command, posix=True)] 141 | # self.log.debug('About to run command "{}"'.format(' '.join(cmd))) 142 | p1 = subprocess.Popen(shlex.split(pre_command, posix=True) if os.sep == '/' else pre_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) if pre_command else None 143 | return subprocess.run(cmd if os.sep == '/' else command, stdin=p1.stdout if p1 else None, capture_output=True, timeout=timeout) 144 | 145 | # Public Methods 146 | def check_special_chars(self, char_at_position: int, operation: SpecialCharOperation) -> Set[Tuple[int, str]]: 147 | # Prepare operation 148 | op = None 149 | if operation == SpecialCharOperation.INSERT: 150 | op = "insert" 151 | command_parts = self.command_flat[:char_at_position+1], self.command_flat[char_at_position+1:] 152 | elif operation == SpecialCharOperation.REPLACE: 153 | op = "replace" 154 | command_parts = self.command_flat[:char_at_position], self.command_flat[char_at_position+1:] 155 | else: 156 | raise ValueError('Unexpected operation {}'.format(operation)) 157 | self.log.info("Starting 'special chars ({})' test".format(op)) 158 | # Prepare commands to run (excluding 'original' command) 159 | new_commands = [(ordinal, chr(ordinal).join(command_parts)) for ordinal in self.scan_range if operation != SpecialCharOperation.REPLACE or chr(ordinal).lower() != self.command_flat[char_at_position].lower()] 160 | # Run commands, return results 161 | return self.__test_commands__("Special chars ({})".format(op), new_commands) 162 | 163 | def check_quote_injection(self, arg_index: int) -> Union[str, None]: 164 | self.log.info("Starting 'quote insertion' test") 165 | # Check if valid command was given 166 | if not self.command or len(self.command) < 2: 167 | return None 168 | # Simply add quotes between 0,1 and 1,2 of first argument - e.g. net s"t"art 169 | command_part = self.__get_option_argument__(arg_index) 170 | quote = '"' # if os.sep != '/' else '\\"' 171 | test_arg = self.command[command_part][:1] + quote + self.command[command_part][1] + quote + self.command[command_part][2:] 172 | new_command = ' '.join(self.command[:command_part] + [test_arg] + self.command[command_part+1:]) 173 | # Quotes don't work in subprocess when using lists 174 | result = self.__run_command__(new_command) 175 | # Return command if working, blank string if not 176 | return new_command if result else '' 177 | 178 | def check_shortened_option(self, arg_index: int) -> Union[None, Set[Tuple[int, str]]]: 179 | self.log.info("Starting 'shortened option' test") 180 | # Check if valid command was given 181 | if not self.command or len(self.command) < 2: 182 | raise ValueError('Unexpected length {}'.format(len(self.command))) 183 | # Shorten the second argument by [1..len(command)-1] chars 184 | selected_command_part_index = self.__get_option_argument__(arg_index) 185 | selected_command_part = self.command[selected_command_part_index] 186 | new_commands = [] 187 | # check if there are any colons or equal signs in there (e.g. /active:true) 188 | selected_command_part_split = list(filter(None, re.split("[:=]", selected_command_part))) 189 | if len(selected_command_part_split) > 1: 190 | # If so, only try to shorten the first bit - leave the argument intact (e.g. /activ:true.../a:true) 191 | size = len(selected_command_part_split[0]) 192 | # Check if argument is long enough 193 | if size <= 2: 194 | self.log.info("Length of selected command-line option is {}, cannot be further shortened".format(size)) 195 | return None 196 | for i in range(size-1): 197 | test_arg = selected_command_part[0:(i+1)] + selected_command_part[size:] 198 | new_commands.append((i, ' '.join(self.command[:selected_command_part_index] + [test_arg] + self.command[(selected_command_part_index+1):]))) 199 | else: 200 | # If not, just shorten the full argument 201 | size = len(selected_command_part) 202 | # Check if argument is long enough 203 | if size <= 2: 204 | self.log.info("Length of selected command-line option is {}, cannot be further shortened".format(size)) 205 | return None 206 | for i in range(size-1): 207 | test_arg = selected_command_part[0:(i+1)] 208 | new_commands.append((i, ' '.join(self.command[:selected_command_part_index] + [test_arg] + self.command[(selected_command_part_index+1):]))) 209 | # Return results of commands if any were generated, None if not 210 | return self.__test_commands__("Shorthand command", new_commands) if new_commands else None 211 | 212 | def check_option_char(self, arg_index_start: int = 1) -> Union[None, Set[Tuple[int, str]]]: 213 | self.log.info("Starting 'option char subtitution' test") 214 | 215 | delimiters_alternative = ['/', '\\', '\u2215', '\u244a', '\u2044', '\u29F8', '\u002D', '\u007E', '\u00AD', '\u058A', '\u05BE', '\u1400', '\u1806', '\u2010', '\u2010', '\u2012', '\u2013', '\u2014', '\u2015', '\u2053', '\u2212', '\u2212', '\u2212', '\u2E17', '\u2E3A', '\u2E3B', '\u301C', '\u3030', '\u30A0', '\uFE31', '\uFE32', '\uFE58', '\uFE63', '\uFF0D'] 216 | delimiters_standard = ['/', '-'] 217 | self.log.info("Looking for arguments starting with one of: {}".format(' '.join(delimiters_standard))) 218 | 219 | # Iterate over command-line arguments 220 | for i, command in enumerate(self.command[arg_index_start:], start=arg_index_start): 221 | # Check if delimiter is present 222 | if any([command.startswith(delimiter) for delimiter in delimiters_standard]): 223 | # If so, find its position 224 | pos = sum([len(c)+1 for c in self.command[:i]]) 225 | # Break command in two parts 226 | command_parts = self.command_flat[:pos], self.command_flat[pos+1:] 227 | self.log.info("Argument found ({})".format(command)) 228 | self.log.info("Preparing {} alternative signs to test".format(len(delimiters_alternative))) 229 | break 230 | else: 231 | self.log.info("No arguments found") 232 | return None # No option char found 233 | 234 | # Prepare commands to test 235 | new_commands = [(ord(char), char.join(command_parts)) for char in delimiters_alternative] 236 | return self.__test_commands__("Dash/hyphen", [command for command in new_commands if command[1] != self.command_flat]) 237 | -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wietze/windows-command-line-obfuscation/dd9c29e82ffc8375e97fabb98971c9c19ca01326/docs/screenshot.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorama 2 | terminaltables 3 | tqdm 4 | -------------------------------------------------------------------------------- /sample/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wietze/windows-command-line-obfuscation/dd9c29e82ffc8375e97fabb98971c9c19ca01326/sample/.keep -------------------------------------------------------------------------------- /sample/inputs/file.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ConsoleApp1 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine("Hello, world!"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sample/inputs/file.sct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /sample/inputs/file.vbs: -------------------------------------------------------------------------------- 1 | Module HelloWorld 2 | ' every console app starts with Main 3 | Sub Main( ) 4 | System.Console.WriteLine("Hello World") 5 | End Sub 6 | End Module -------------------------------------------------------------------------------- /sample/inputs/sleep.vbs: -------------------------------------------------------------------------------- 1 | WScript.Sleep 500 -------------------------------------------------------------------------------- /sample/inputs/x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wietze/windows-command-line-obfuscation/dd9c29e82ffc8375e97fabb98971c9c19ca01326/sample/inputs/x86.dll -------------------------------------------------------------------------------- /sample/sample.jsonl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {"command": "\"C:\\Program Files\\Windows Defender\\MpCmdRun.exe\" -RemoveDefinitions -All", "range": "full", "elevated": true} 5 | {"command": "arp -a", "range": "full"} 6 | {"command": "at 12:34 /interactive cmd", "range": "full"} 7 | {"command": "bitsadmin /transfer xy https://duckduckgo.com/robots.txt c:\\windows\\temp\\robots.txt", "timeout": 5, "exit_code_only": true, "range": "full", "elevated": true} 8 | {"command": "C:\\windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe -out:cache\\file.exe inputs\\file.cs", "char_offset": 59, "range": "full"} 9 | {"command": "c:\\windows\\Microsoft.NET\\Framework64\\v4.0.30319\\jsc.exe /target:exe /out:cache\\file.exe inputs\\file.js", "range": "full"} 10 | {"command": "c:\\windows\\Microsoft.NET\\Framework64\\v4.0.30319\\vbc.exe /target:exe /out:cache\\file.exe inputs\\file.vbs", "range": "full"} 11 | {"command": "certutil -split -urlcache -f https://www.bing.com/robots.txt cache\\{random}.txt", "range": "full"} 12 | {"command": "cmdkey /list", "range": "full"} 13 | {"command": "cmstp.exe /s c:\\windows\\temp\\cmstp.inf", "range": "educated"} 14 | {"command": "curl -N https://www.google.com/robots.txt -r 0-16", "range": "full"} 15 | {"command": "findstr /offline \"findstr\" \"*.json\"", "range": "full"} 16 | {"command": "fltmc.exe filters", "range": "full"} 17 | {"command": "forfiles /P c:\\windows\\ /M *.bin /c \"cmd /c echo hi\"", "range": "full"} 18 | {"command": "ipconfig /displaydns", "range": "full"} 19 | {"command": "nbtstat -n", "range": "full"} 20 | {"command": "net share x=c:\\ /remark:{random}", "post_command": "net share /delete x", "range": "full"} 21 | {"command": "netsh advfirewall show currentprofile state", "range": "full"} 22 | {"command": "netstat -p UDPv6", "range": "full"} 23 | {"command": "nltest /domain_trusts", "range": "full"} 24 | {"command": "nslookup -querytype=ALL -timeout=10 _ldap._tcp.dc._msdcs.WORKGROUP", "range": "full"} 25 | {"command": "ping /n 1 localhost", "range": "full"} 26 | {"command": "powershell /encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA==", "timeout": 5, "range": "educated", "comment": "Too slow for 'full' range"} 27 | {"command": "query process /id:123", "range": "full"} 28 | {"command": "qwinsta /mode", "range": "full"} 29 | {"command": "reg export HKCU\\SOFTWARE\\Microsoft\\accessibility cache\\out.reg /y", "range": "full"} 30 | {"command": "regsvr32 /s /u /i:inputs\\file.sct scrobj.dll", "char_offset":13, "range": "educated", "comment": "Special case - look at the generated file `inputs\\results.txt` to see the commands that worked."} 31 | {"command": "route print 123*", "range": "full"} 32 | {"command": "sc query eventlog", "range": "full"} 33 | {"command": "schtasks /showsid /TN \"\\Microsoft\\XblGameSave\\XblGameSaveTask\"", "range": "full"} 34 | {"command": "systeminfo /s localhost", "timeout": 5, "exit_code_only": true, "range": "full"} 35 | {"command": "takeown /F config.json", "range": "full"} 36 | {"command": "taskkill /im test.exe", "range": "full"} 37 | {"command": "tasklist /fi \"USERNAME eq test\"", "timeout": 5, "range": "full"} 38 | {"command": "wevtutil gli HardwareEvents", "exit_code_only": true, "range": "full"} 39 | {"command": "winrs -remote:localhost echo hello", "range": "full", "elevated": true} 40 | {"command": "wmic os get BuildNumber", "range": "full"} 41 | -------------------------------------------------------------------------------- /sample_results/arp.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR arp 2 | - Generated on 2021-01-02T14:08:31.751740 3 | - Command used : arp -a 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 8 commands were found to be working: 9 | 0x002F : arp /a 10 | 0x2010 : arp ‐a 11 | 0x2012 : arp ‒a 12 | 0x2015 : arp ―a 13 | 0x2044 : arp ⁄a 14 | 0x2212 : arp −a 15 | 0x2215 : arp ∕a 16 | 0xFF0D : arp -a 17 | 18 | :: Character Insertion 19 | The following 67 commands were found to be working: 20 | 0x0022 : arp -"a 21 | 0x0041 : arp -Aa 22 | 0x0044 : arp -Da 23 | 0x0047 : arp -Ga 24 | 0x0053 : arp -Sa 25 | 0x0061 : arp -aa 26 | 0x0064 : arp -da 27 | 0x0067 : arp -ga 28 | 0x0073 : arp -sa 29 | 0x00A0 : arp - a 30 | 0x0100 : arp -Āa 31 | 0x0101 : arp -āa 32 | 0x0102 : arp -Ăa 33 | 0x0103 : arp -ăa 34 | 0x0104 : arp -Ąa 35 | 0x0105 : arp -ąa 36 | 0x010E : arp -Ďa 37 | 0x010F : arp -ďa 38 | 0x0111 : arp -đa 39 | 0x011C : arp -Ĝa 40 | 0x011D : arp -ĝa 41 | 0x011E : arp -Ğa 42 | 0x011F : arp -ğa 43 | 0x0120 : arp -Ġa 44 | 0x0121 : arp -ġa 45 | 0x0122 : arp -Ģa 46 | 0x0123 : arp -ģa 47 | 0x015A : arp -Śa 48 | 0x015B : arp -śa 49 | 0x015C : arp -Ŝa 50 | 0x015D : arp -ŝa 51 | 0x015E : arp -Şa 52 | 0x015F : arp -şa 53 | 0x0191 : arp -Ƒa 54 | 0x0192 : arp -ƒa 55 | 0x01CD : arp -Ǎa 56 | 0x01CE : arp -ǎa 57 | 0x01DE : arp -Ǟa 58 | 0x01DF : arp -ǟa 59 | 0x01E4 : arp -Ǥa 60 | 0x01E5 : arp -ǥa 61 | 0x01E6 : arp -Ǧa 62 | 0x01E7 : arp -ǧa 63 | 0x0261 : arp -ɡa 64 | 0x02BA : arp -ʺa 65 | 0x030E : arp -̎a 66 | 0x0393 : arp -Γa 67 | 0x03A3 : arp -Σa 68 | 0x03B1 : arp -αa 69 | 0x03B4 : arp -δa 70 | 0x03C3 : arp -σa 71 | 0x2007 : arp - a 72 | 0x201F : arp -‟a 73 | 0x2026 : arp -…a 74 | 0x202F : arp - a 75 | 0x2033 : arp -″a 76 | 0x2036 : arp -‶a 77 | 0x210A : arp -ℊa 78 | 0xFF02 : arp -"a 79 | 0xFF21 : arp -Aa 80 | 0xFF24 : arp -Da 81 | 0xFF27 : arp -Ga 82 | 0xFF33 : arp -Sa 83 | 0xFF41 : arp -aa 84 | 0xFF44 : arp -da 85 | 0xFF47 : arp -ga 86 | 0xFF53 : arp -sa 87 | 88 | :: Character Substitution 89 | The following commands were found to be working: 90 | 0x0047 : arp -G 91 | 0x0067 : arp -g 92 | 0x00A0 : arp -  93 | 0x0100 : arp -Ā 94 | 0x0101 : arp -ā 95 | 0x0102 : arp -Ă 96 | 0x0103 : arp -ă 97 | 0x0104 : arp -Ą 98 | 0x0105 : arp -ą 99 | 0x011C : arp -Ĝ 100 | 0x011D : arp -ĝ 101 | 0x011E : arp -Ğ 102 | 0x011F : arp -ğ 103 | 0x0120 : arp -Ġ 104 | 0x0121 : arp -ġ 105 | 0x0122 : arp -Ģ 106 | 0x0123 : arp -ģ 107 | 0x0191 : arp -Ƒ 108 | 0x0192 : arp -ƒ 109 | 0x01CD : arp -Ǎ 110 | 0x01CE : arp -ǎ 111 | 0x01DE : arp -Ǟ 112 | 0x01DF : arp -ǟ 113 | 0x01E4 : arp -Ǥ 114 | 0x01E5 : arp -ǥ 115 | 0x01E6 : arp -Ǧ 116 | 0x01E7 : arp -ǧ 117 | 0x0261 : arp -ɡ 118 | 0x0393 : arp -Γ 119 | 0x03B1 : arp -α 120 | 0x2007 : arp -  121 | 0x2026 : arp -… 122 | 0x202F : arp -  123 | 0x210A : arp -ℊ 124 | 0xFF21 : arp -A 125 | 0xFF27 : arp -G 126 | 0xFF41 : arp -a 127 | 0xFF47 : arp -g 128 | 129 | :: Quote Insertion 130 | Inserting quotes in the first argument did work, such as: 131 | arp -"a" 132 | 133 | :: Shorthand Commands 134 | No alternative commands were found. 135 | -------------------------------------------------------------------------------- /sample_results/at.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR at 2 | - Generated on 2021-01-02T21:06:28.538054 3 | - Command used : at 12:34 /interactive cmd 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | No alternative commands were found. 9 | 10 | :: Character Insertion 11 | The following 2 commands were found to be working: 12 | 0x0009 : at 12:34 /inter active cmd 13 | 0x0020 : at 12:34 /inter active cmd 14 | 15 | :: Character Substitution 16 | The following commands were found to be working: 17 | 0x0009 : at 12:34 /inte active cmd 18 | 0x0020 : at 12:34 /inte active cmd 19 | 20 | :: Quote Insertion 21 | Inserting quotes in the first argument did work, such as: 22 | at 12:34 /"i"nteractive cmd 23 | 24 | :: Shorthand Commands 25 | The following 10 commands were found to be working: 26 | at 12:34 /i cmd 27 | at 12:34 /in cmd 28 | at 12:34 /int cmd 29 | at 12:34 /inte cmd 30 | at 12:34 /inter cmd 31 | at 12:34 /intera cmd 32 | at 12:34 /interac cmd 33 | at 12:34 /interact cmd 34 | at 12:34 /interacti cmd 35 | at 12:34 /interactiv cmd 36 | -------------------------------------------------------------------------------- /sample_results/bitsadmin.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR bitsadmin 2 | - Generated on 2021-01-02T18:20:46.580663 3 | - Command used : bitsadmin /transfer xy https://duckduckgo.com/robots.txt c:\windows\temp\robots.txt 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | No alternative commands were found. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Substitution 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did work, such as: 18 | bitsadmin /"t"ransfer xy https://duckduckgo.com/robots.txt c:\windows\temp\robots.txt 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/cmdkey.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR cmdkey 2 | - Generated on 2021-01-02T17:21:35.364722 3 | - Command used : cmdkey /list 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002D : cmdkey -list 10 | 11 | :: Character Insertion 12 | The following 2 commands were found to be working: 13 | 0x004C : cmdkey /Llist 14 | 0x006C : cmdkey /llist 15 | 16 | :: Character Substitution 17 | No alternative commands were found. 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did not appear to be working. 21 | 22 | :: Shorthand Commands 23 | The following 3 commands were found to be working: 24 | cmdkey /l 25 | cmdkey /li 26 | cmdkey /lis 27 | -------------------------------------------------------------------------------- /sample_results/cmstp.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR cmstp.exe 2 | - Generated on 2020-12-03T21:53:50.349533 3 | - Command used : cmstp.exe /s c:\users\wietze\downloads\cmstp.inf 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0x00FE 0x02B0..0x02FE 0x2070..0x209E 6 | 7 | :: Character Insertion 8 | The following 3 commands were found to be working: 9 | 0x2072 : cmstp.exe /⁲s c:\users\wietze\downloads\cmstp.inf 10 | 0x2073 : cmstp.exe /⁳s c:\users\wietze\downloads\cmstp.inf 11 | 0x209D : cmstp.exe /₝s c:\users\wietze\downloads\cmstp.inf 12 | 13 | :: Character Substitution 14 | The following commands were found to be working: 15 | 0x0049 : cmstp.exe /I c:\users\wietze\downloads\cmstp.inf 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did not appear to be working. 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/csc.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR csc.exe 2 | - Generated on 2020-11-28T22:27:16.668663 3 | - Command used : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe -out:My.exe inputs\file.cs 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 1 commands were found to be working: 9 | 0x002F : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:My.exe inputs\file.cs 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Replacement 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did not appear to be working. 19 | 20 | :: Shortened Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/curl.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR curl 2 | - Generated on 2021-01-04T02:00:40.003795 3 | - Command used : curl -N https://www.google.com/robots.txt -r 0-16 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | No alternative commands were found. 9 | 10 | :: Character Insertion 11 | The following 12 commands were found to be working: 12 | 0x004C : curl -NL https://www.google.com/robots.txt -r 0-16 13 | 0x0070 : curl -Np https://www.google.com/robots.txt -r 0-16 14 | 0x011D : curl -Nĝ https://www.google.com/robots.txt -r 0-16 15 | 0x0144 : curl -Nń https://www.google.com/robots.txt -r 0-16 16 | 0x0146 : curl -Nņ https://www.google.com/robots.txt -r 0-16 17 | 0x0154 : curl -NŔ https://www.google.com/robots.txt -r 0-16 18 | 0x019A : curl -Nƚ https://www.google.com/robots.txt -r 0-16 19 | 0x01E7 : curl -Nǧ https://www.google.com/robots.txt -r 0-16 20 | 0x01F0 : curl -Nǰ https://www.google.com/robots.txt -r 0-16 21 | 0x2009 : curl -N  https://www.google.com/robots.txt -r 0-16 22 | 0xFF41 : curl -Na https://www.google.com/robots.txt -r 0-16 23 | 0xFF46 : curl -Nf https://www.google.com/robots.txt -r 0-16 24 | 25 | :: Character Substitution 26 | The following commands were found to be working: 27 | 0x011E : curl -Ğ https://www.google.com/robots.txt -r 0-16 28 | 0x0139 : curl -Ĺ https://www.google.com/robots.txt -r 0-16 29 | 0x0143 : curl -Ń https://www.google.com/robots.txt -r 0-16 30 | 0x0144 : curl -ń https://www.google.com/robots.txt -r 0-16 31 | 0x01E4 : curl -Ǥ https://www.google.com/robots.txt -r 0-16 32 | 0x210A : curl -ℊ https://www.google.com/robots.txt -r 0-16 33 | 0x2112 : curl -ℒ https://www.google.com/robots.txt -r 0-16 34 | 0x211D : curl -ℝ https://www.google.com/robots.txt -r 0-16 35 | 0xFF11 : curl -1 https://www.google.com/robots.txt -r 0-16 36 | 37 | :: Quote Insertion 38 | Inserting quotes in the first argument did not appear to be working. 39 | 40 | :: Shorthand Commands 41 | No alternative commands were found. 42 | -------------------------------------------------------------------------------- /sample_results/findstr.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR findstr 2 | - Generated on 2020-11-30T15:00:17.278099 3 | - Command used : findstr /offline "findstr" "*.json" 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 11 commands were found to be working: 9 | 0x002D : findstr -offline "findstr" "*.json" 10 | 0x00AD : findstr ­offline "findstr" "*.json" 11 | 0x2010 : findstr ‐offline "findstr" "*.json" 12 | 0x2012 : findstr ‒offline "findstr" "*.json" 13 | 0x2013 : findstr –offline "findstr" "*.json" 14 | 0x2014 : findstr —offline "findstr" "*.json" 15 | 0x2015 : findstr ―offline "findstr" "*.json" 16 | 0x2044 : findstr ⁄offline "findstr" "*.json" 17 | 0x2212 : findstr −offline "findstr" "*.json" 18 | 0x2215 : findstr ∕offline "findstr" "*.json" 19 | 0xFF0D : findstr -offline "findstr" "*.json" 20 | 21 | :: Character Insertion 22 | No alternative commands were found. 23 | 24 | :: Character Replacement 25 | The following commands were found to be working: 26 | 0x0139 : findstr /offĹine "findstr" "*.json" 27 | 0x013A : findstr /offĺine "findstr" "*.json" 28 | 0x013B : findstr /offĻine "findstr" "*.json" 29 | 0x013C : findstr /offļine "findstr" "*.json" 30 | 0x013D : findstr /offĽine "findstr" "*.json" 31 | 0x013E : findstr /offľine "findstr" "*.json" 32 | 0x0141 : findstr /offŁine "findstr" "*.json" 33 | 0x0142 : findstr /offłine "findstr" "*.json" 34 | 0x019A : findstr /offƚine "findstr" "*.json" 35 | 0x2112 : findstr /offℒine "findstr" "*.json" 36 | 0x2113 : findstr /offℓine "findstr" "*.json" 37 | 0xFF2C : findstr /offLine "findstr" "*.json" 38 | 0xFF4C : findstr /offline "findstr" "*.json" 39 | 40 | :: Quote Insertion 41 | Inserting quotes in the first argument did work, such as: 42 | findstr /"o"ffline "findstr" "*.json" 43 | 44 | :: Shortened Commands 45 | No alternative commands were found. 46 | -------------------------------------------------------------------------------- /sample_results/fltmc.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR fltmc.exe 2 | - Generated on 2020-11-30T14:21:00.481512 3 | - Command used : fltmc.exe filters 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | The following 1 commands were found to be working: 12 | 0x0022 : fltmc.exe fi"lters 13 | 14 | :: Character Replacement 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did work, such as: 19 | fltmc.exe f"i"lters 20 | 21 | :: Shortened Commands 22 | No alternative commands were found. 23 | -------------------------------------------------------------------------------- /sample_results/forfiles.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR forfiles 2 | - Generated on 2020-12-03T22:36:42.564321 3 | - Command used : forfiles /P c:\windows\ /M *.bin /c "cmd /c echo HI" 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Character Insertion 8 | No alternative commands were found. 9 | 10 | :: Character Substitution 11 | The following commands were found to be working: 12 | 0x1D3E : forfiles /ᴾ c:\windows\ /M *.bin /c "cmd /c echo HI" 13 | 0x1D56 : forfiles /ᵖ c:\windows\ /M *.bin /c "cmd /c echo HI" 14 | 15 | :: Quote Insertion 16 | Inserting quotes in the first argument did work, such as: 17 | forfiles /"P" c:\windows\ /M *.bin /c "cmd /c echo HI" 18 | 19 | :: Shorthand Commands 20 | No alternative commands were found. 21 | -------------------------------------------------------------------------------- /sample_results/icacls.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR icacls 2 | - Generated on 2021-01-03T20:00:31.704185 3 | - Command used : icacls "c:\users\wietze\downloads\test.txt" /grant administrators:(f) 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | No alternative commands were found. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Substitution 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did work, such as: 18 | icacls "c:\users\wietze\downloads\test.txt" /"g"rant administrators:(f) 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/jsc.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR jsc.exe 2 | - Generated on 2021-01-04T01:41:59.300625 3 | - Command used : c:\windows\Microsoft.NET\Framework64\v4.0.30319\jsc.exe /target:exe /out:cache\file.exe inputs\file.js 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002D : c:\windows\Microsoft.NET\Framework64\v4.0.30319\jsc.exe -target:exe /out:cache\file.exe inputs\file.js 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Substitution 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did work, such as: 19 | c:\windows\Microsoft.NET\Framework64\v4.0.30319\jsc.exe /"t"arget:exe /out:cache\file.exe inputs\file.js 20 | 21 | :: Shorthand Commands 22 | The following 1 commands were found to be working: 23 | c:\windows\Microsoft.NET\Framework64\v4.0.30319\jsc.exe /t:exe /out:cache\file.exe inputs\file.js 24 | -------------------------------------------------------------------------------- /sample_results/mpcmdrun.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR MpCmdRun.exe 2 | - Generated on 2021-01-02T17:39:03.094686 3 | - Command used : "C:\Program Files\Windows Defender\MpCmdRun.exe" -RemoveDefinitions -All 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002F : "C:\Program Files\Windows Defender\MpCmdRun.exe" /RemoveDefinitions -All 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Substitution 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did work, such as: 19 | "C:\Program Files\Windows Defender\MpCmdRun.exe" -"R"emoveDefinitions -All 20 | 21 | :: Shorthand Commands 22 | No alternative commands were found. 23 | -------------------------------------------------------------------------------- /sample_results/msiexec.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR msiexec 2 | - Generated on 2020-11-30T06:39:36.837353 3 | - Command used : msiexec /y "inputs\test.dll" 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 1 commands were found to be working: 9 | 0x002D : msiexec -y "inputs\test.dll" 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Replacement 15 | The following commands were found to be working: 16 | 0x005A : msiexec /Z "inputs\test.dll" 17 | 0x007A : msiexec /z "inputs\test.dll" 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did not appear to be working. 21 | 22 | :: Shortened Commands 23 | No alternative commands were found. 24 | -------------------------------------------------------------------------------- /sample_results/net.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR net 2 | - Generated on 2020-11-29T00:38:17.078462 3 | - Command used : net share x=c:\ /remark:{random} 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | No alternative commands were found. 9 | 10 | :: Character Insertion 11 | The following 1 commands were found to be working: 12 | 0x0022 : net share x=c:\ /"remark:{random} 13 | 14 | :: Character Replacement 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did work, such as: 19 | net share x=c:\ /"r"emark:{random} 20 | 21 | :: Shortened Commands 22 | The following commands were found to be working: 23 | net share x=c:\ /r:{random} 24 | net share x=c:\ /re:{random} 25 | net share x=c:\ /rem:{random} 26 | net share x=c:\ /rema:{random} 27 | net share x=c:\ /remar:{random} 28 | -------------------------------------------------------------------------------- /sample_results/netsh.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR netsh 2 | - Generated on 2020-11-30T12:40:20.824276 3 | - Command used : netsh advfirewall show currentprofile state 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Replacement 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did work, such as: 18 | netsh a"d"vfirewall show currentprofile state 19 | 20 | :: Shortened Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/netstat.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR netstat 2 | - Generated on 2021-01-02T14:24:28.627896 3 | - Command used : netstat -p UDPv6 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 8 commands were found to be working: 9 | 0x002F : netstat /p UDPv6 10 | 0x2010 : netstat ‐p UDPv6 11 | 0x2012 : netstat ‒p UDPv6 12 | 0x2015 : netstat ―p UDPv6 13 | 0x2044 : netstat ⁄p UDPv6 14 | 0x2212 : netstat −p UDPv6 15 | 0x2215 : netstat ∕p UDPv6 16 | 0xFF0D : netstat -p UDPv6 17 | 18 | :: Character Insertion 19 | The following 33 commands were found to be working: 20 | 0x0046 : netstat -Fp UDPv6 21 | 0x004E : netstat -Np UDPv6 22 | 0x0050 : netstat -Pp UDPv6 23 | 0x0056 : netstat -Vp UDPv6 24 | 0x0066 : netstat -fp UDPv6 25 | 0x006E : netstat -np UDPv6 26 | 0x0070 : netstat -pp UDPv6 27 | 0x0076 : netstat -vp UDPv6 28 | 0x0143 : netstat -Ńp UDPv6 29 | 0x0144 : netstat -ńp UDPv6 30 | 0x0145 : netstat -Ņp UDPv6 31 | 0x0146 : netstat -ņp UDPv6 32 | 0x0147 : netstat -Ňp UDPv6 33 | 0x0148 : netstat -ňp UDPv6 34 | 0x03A6 : netstat -Φp UDPv6 35 | 0x03C0 : netstat -πp UDPv6 36 | 0x03C6 : netstat -φp UDPv6 37 | 0x207F : netstat -ⁿp UDPv6 38 | 0x20A7 : netstat -₧p UDPv6 39 | 0x2115 : netstat -ℕp UDPv6 40 | 0x2118 : netstat -℘p UDPv6 41 | 0x2119 : netstat -ℙp UDPv6 42 | 0x2131 : netstat -ℱp UDPv6 43 | 0x221A : netstat -√p UDPv6 44 | 0x2229 : netstat -∩p UDPv6 45 | 0xFF26 : netstat -Fp UDPv6 46 | 0xFF2E : netstat -Np UDPv6 47 | 0xFF30 : netstat -Pp UDPv6 48 | 0xFF36 : netstat -Vp UDPv6 49 | 0xFF46 : netstat -fp UDPv6 50 | 0xFF4E : netstat -np UDPv6 51 | 0xFF50 : netstat -pp UDPv6 52 | 0xFF56 : netstat -vp UDPv6 53 | 54 | :: Character Substitution 55 | The following commands were found to be working: 56 | 0x03C0 : netstat -π UDPv6 57 | 0x20A7 : netstat -₧ UDPv6 58 | 0x2118 : netstat -℘ UDPv6 59 | 0x2119 : netstat -ℙ UDPv6 60 | 0xFF30 : netstat -P UDPv6 61 | 0xFF50 : netstat -p UDPv6 62 | 63 | :: Quote Insertion 64 | Inserting quotes in the first argument did work, such as: 65 | netstat -"p" UDPv6 66 | 67 | :: Shorthand Commands 68 | No alternative commands were found. 69 | -------------------------------------------------------------------------------- /sample_results/ping.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR ping 2 | - Generated on 2020-11-30T07:07:36.415555 3 | - Command used : ping /n 1 localhost 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 1 commands were found to be working: 9 | 0x002D : ping -n 1 localhost 10 | 11 | :: Character Insertion 12 | The following 1 commands were found to be working: 13 | 0x006E : ping /nn 1 localhost 14 | 15 | :: Character Replacement 16 | No alternative commands were found. 17 | 18 | :: Quote Insertion 19 | Inserting quotes in the first argument did work, such as: 20 | ping /"n" 1 localhost 21 | 22 | :: Shortened Commands 23 | No alternative commands were found. 24 | -------------------------------------------------------------------------------- /sample_results/powershell.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR powershell 2 | - Generated on 2020-11-29T10:12:00.012891 3 | - Command used : powershell /encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0x00FE 0x02B0..0x02FE 0x2070..0x209E 6 | 7 | :: Different dash/hyphens 8 | The following 4 commands were found to be working: 9 | 0x002D : powershell -encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 10 | 0x2013 : powershell –encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 11 | 0x2014 : powershell —encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 12 | 0x2015 : powershell ―encodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 13 | 14 | :: Character Insertion 15 | No alternative commands were found. 16 | 17 | :: Character Replacement 18 | No alternative commands were found. 19 | 20 | :: Quote Insertion 21 | Inserting quotes in the first argument did work, such as: 22 | powershell /"e"ncodedcommand ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 23 | 24 | :: Shortened Commands 25 | The following 12 commands were found to be working: 26 | powershell /e ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 27 | powershell /en ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 28 | powershell /enc ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 29 | powershell /enco ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 30 | powershell /encod ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 31 | powershell /encode ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 32 | powershell /encoded ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 33 | powershell /encodedc ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 34 | powershell /encodedco ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 35 | powershell /encodedcom ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 36 | powershell /encodedcomm ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== 37 | powershell /encodedcomma ZQBjAGgAbwAgACIAQAB3AGkAZQB0AHoAZQAiAA== -------------------------------------------------------------------------------- /sample_results/regsvr32.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR regsvr32 2 | - Generated on 2021-01-02T20:09:36.730781 3 | - Command used : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0x00FE 0x02B0..0x02FE 0x2070..0x209E 6 | 7 | :: Option Char Substitution 8 | The following 30 commands were found to be working: 9 | 0x002D : regsvr32 /s /u -i:inputs\file.sct scrobj.dll 10 | 0x005C : regsvr32 /s /u \i:inputs\file.sct scrobj.dll 11 | 0x007E : regsvr32 /s /u ~i:inputs\file.sct scrobj.dll 12 | 0x00AD : regsvr32 /s /u ­i:inputs\file.sct scrobj.dll 13 | 0x058A : regsvr32 /s /u ֊i:inputs\file.sct scrobj.dll 14 | 0x05BE : regsvr32 /s /u ־i:inputs\file.sct scrobj.dll 15 | 0x1400 : regsvr32 /s /u ᐀i:inputs\file.sct scrobj.dll 16 | 0x1806 : regsvr32 /s /u ᠆i:inputs\file.sct scrobj.dll 17 | 0x2010 : regsvr32 /s /u ‐i:inputs\file.sct scrobj.dll 18 | 0x2012 : regsvr32 /s /u ‒i:inputs\file.sct scrobj.dll 19 | 0x2013 : regsvr32 /s /u –i:inputs\file.sct scrobj.dll 20 | 0x2014 : regsvr32 /s /u —i:inputs\file.sct scrobj.dll 21 | 0x2015 : regsvr32 /s /u ―i:inputs\file.sct scrobj.dll 22 | 0x2044 : regsvr32 /s /u ⁄i:inputs\file.sct scrobj.dll 23 | 0x2053 : regsvr32 /s /u ⁓i:inputs\file.sct scrobj.dll 24 | 0x2212 : regsvr32 /s /u −i:inputs\file.sct scrobj.dll 25 | 0x2215 : regsvr32 /s /u ∕i:inputs\file.sct scrobj.dll 26 | 0x244A : regsvr32 /s /u ⑊i:inputs\file.sct scrobj.dll 27 | 0x29F8 : regsvr32 /s /u ⧸i:inputs\file.sct scrobj.dll 28 | 0x2E17 : regsvr32 /s /u ⸗i:inputs\file.sct scrobj.dll 29 | 0x2E3A : regsvr32 /s /u ⸺i:inputs\file.sct scrobj.dll 30 | 0x2E3B : regsvr32 /s /u ⸻i:inputs\file.sct scrobj.dll 31 | 0x301C : regsvr32 /s /u 〜i:inputs\file.sct scrobj.dll 32 | 0x3030 : regsvr32 /s /u 〰i:inputs\file.sct scrobj.dll 33 | 0x30A0 : regsvr32 /s /u ゠i:inputs\file.sct scrobj.dll 34 | 0xFE31 : regsvr32 /s /u ︱i:inputs\file.sct scrobj.dll 35 | 0xFE32 : regsvr32 /s /u ︲i:inputs\file.sct scrobj.dll 36 | 0xFE58 : regsvr32 /s /u ﹘i:inputs\file.sct scrobj.dll 37 | 0xFE63 : regsvr32 /s /u ﹣i:inputs\file.sct scrobj.dll 38 | 0xFF0D : regsvr32 /s /u -i:inputs\file.sct scrobj.dll 39 | 40 | :: Character Insertion 41 | The following 222 commands were found to be working: 42 | 0x0001 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 43 | 0x0002 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 44 | 0x0003 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 45 | 0x0004 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 46 | 0x0005 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 47 | 0x0006 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 48 | 0x0007 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 49 | 0x0008 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 50 | 0x0009 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 51 | 0x000A : regsvr32 /s /u 52 | /i:inputs\file.sct scrobj.dll 53 | 0x000B : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 54 | 0x000C : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 55 | 0x000D : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 56 | 0x000E : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 57 | 0x000F : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 58 | 0x0010 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 59 | 0x0011 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 60 | 0x0012 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 61 | 0x0013 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 62 | 0x0014 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 63 | 0x0015 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 64 | 0x0016 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 65 | 0x0017 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 66 | 0x0018 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 67 | 0x0019 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 68 | 0x001A : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 69 | 0x001B : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 70 | 0x001C : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 71 | 0x001D : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 72 | 0x001E : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 73 | 0x001F : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 74 | 0x0020 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 75 | 0x0021 : regsvr32 /s /u! /i:inputs\file.sct scrobj.dll 76 | 0x0023 : regsvr32 /s /u# /i:inputs\file.sct scrobj.dll 77 | 0x0024 : regsvr32 /s /u$ /i:inputs\file.sct scrobj.dll 78 | 0x0025 : regsvr32 /s /u% /i:inputs\file.sct scrobj.dll 79 | 0x0026 : regsvr32 /s /u& /i:inputs\file.sct scrobj.dll 80 | 0x0027 : regsvr32 /s /u' /i:inputs\file.sct scrobj.dll 81 | 0x0028 : regsvr32 /s /u( /i:inputs\file.sct scrobj.dll 82 | 0x0029 : regsvr32 /s /u) /i:inputs\file.sct scrobj.dll 83 | 0x002A : regsvr32 /s /u* /i:inputs\file.sct scrobj.dll 84 | 0x002B : regsvr32 /s /u+ /i:inputs\file.sct scrobj.dll 85 | 0x002C : regsvr32 /s /u, /i:inputs\file.sct scrobj.dll 86 | 0x002D : regsvr32 /s /u- /i:inputs\file.sct scrobj.dll 87 | 0x002E : regsvr32 /s /u. /i:inputs\file.sct scrobj.dll 88 | 0x002F : regsvr32 /s /u/ /i:inputs\file.sct scrobj.dll 89 | 0x0030 : regsvr32 /s /u0 /i:inputs\file.sct scrobj.dll 90 | 0x0031 : regsvr32 /s /u1 /i:inputs\file.sct scrobj.dll 91 | 0x0032 : regsvr32 /s /u2 /i:inputs\file.sct scrobj.dll 92 | 0x0033 : regsvr32 /s /u3 /i:inputs\file.sct scrobj.dll 93 | 0x0035 : regsvr32 /s /u5 /i:inputs\file.sct scrobj.dll 94 | 0x0036 : regsvr32 /s /u6 /i:inputs\file.sct scrobj.dll 95 | 0x0037 : regsvr32 /s /u7 /i:inputs\file.sct scrobj.dll 96 | 0x0038 : regsvr32 /s /u8 /i:inputs\file.sct scrobj.dll 97 | 0x0039 : regsvr32 /s /u9 /i:inputs\file.sct scrobj.dll 98 | 0x003A : regsvr32 /s /u: /i:inputs\file.sct scrobj.dll 99 | 0x003B : regsvr32 /s /u; /i:inputs\file.sct scrobj.dll 100 | 0x003C : regsvr32 /s /u< /i:inputs\file.sct scrobj.dll 101 | 0x003D : regsvr32 /s /u= /i:inputs\file.sct scrobj.dll 102 | 0x003E : regsvr32 /s /u> /i:inputs\file.sct scrobj.dll 103 | 0x003F : regsvr32 /s /u? /i:inputs\file.sct scrobj.dll 104 | 0x0040 : regsvr32 /s /u@ /i:inputs\file.sct scrobj.dll 105 | 0x0041 : regsvr32 /s /uA /i:inputs\file.sct scrobj.dll 106 | 0x0042 : regsvr32 /s /uB /i:inputs\file.sct scrobj.dll 107 | 0x0043 : regsvr32 /s /uC /i:inputs\file.sct scrobj.dll 108 | 0x0044 : regsvr32 /s /uD /i:inputs\file.sct scrobj.dll 109 | 0x0045 : regsvr32 /s /uE /i:inputs\file.sct scrobj.dll 110 | 0x0046 : regsvr32 /s /uF /i:inputs\file.sct scrobj.dll 111 | 0x0047 : regsvr32 /s /uG /i:inputs\file.sct scrobj.dll 112 | 0x0048 : regsvr32 /s /uH /i:inputs\file.sct scrobj.dll 113 | 0x0049 : regsvr32 /s /uI /i:inputs\file.sct scrobj.dll 114 | 0x004A : regsvr32 /s /uJ /i:inputs\file.sct scrobj.dll 115 | 0x004B : regsvr32 /s /uK /i:inputs\file.sct scrobj.dll 116 | 0x004C : regsvr32 /s /uL /i:inputs\file.sct scrobj.dll 117 | 0x004D : regsvr32 /s /uM /i:inputs\file.sct scrobj.dll 118 | 0x004E : regsvr32 /s /uN /i:inputs\file.sct scrobj.dll 119 | 0x004F : regsvr32 /s /uO /i:inputs\file.sct scrobj.dll 120 | 0x0050 : regsvr32 /s /uP /i:inputs\file.sct scrobj.dll 121 | 0x0051 : regsvr32 /s /uQ /i:inputs\file.sct scrobj.dll 122 | 0x0052 : regsvr32 /s /uR /i:inputs\file.sct scrobj.dll 123 | 0x0053 : regsvr32 /s /uS /i:inputs\file.sct scrobj.dll 124 | 0x0054 : regsvr32 /s /uT /i:inputs\file.sct scrobj.dll 125 | 0x0055 : regsvr32 /s /uU /i:inputs\file.sct scrobj.dll 126 | 0x0056 : regsvr32 /s /uV /i:inputs\file.sct scrobj.dll 127 | 0x0057 : regsvr32 /s /uW /i:inputs\file.sct scrobj.dll 128 | 0x0058 : regsvr32 /s /uX /i:inputs\file.sct scrobj.dll 129 | 0x0059 : regsvr32 /s /uY /i:inputs\file.sct scrobj.dll 130 | 0x005A : regsvr32 /s /uZ /i:inputs\file.sct scrobj.dll 131 | 0x005B : regsvr32 /s /u[ /i:inputs\file.sct scrobj.dll 132 | 0x005C : regsvr32 /s /u\ /i:inputs\file.sct scrobj.dll 133 | 0x005D : regsvr32 /s /u] /i:inputs\file.sct scrobj.dll 134 | 0x005E : regsvr32 /s /u^ /i:inputs\file.sct scrobj.dll 135 | 0x005F : regsvr32 /s /u_ /i:inputs\file.sct scrobj.dll 136 | 0x0060 : regsvr32 /s /u` /i:inputs\file.sct scrobj.dll 137 | 0x0061 : regsvr32 /s /ua /i:inputs\file.sct scrobj.dll 138 | 0x0067 : regsvr32 /s /ug /i:inputs\file.sct scrobj.dll 139 | 0x006A : regsvr32 /s /uj /i:inputs\file.sct scrobj.dll 140 | 0x006C : regsvr32 /s /ul /i:inputs\file.sct scrobj.dll 141 | 0x006E : regsvr32 /s /un /i:inputs\file.sct scrobj.dll 142 | 0x006F : regsvr32 /s /uo /i:inputs\file.sct scrobj.dll 143 | 0x0070 : regsvr32 /s /up /i:inputs\file.sct scrobj.dll 144 | 0x0071 : regsvr32 /s /uq /i:inputs\file.sct scrobj.dll 145 | 0x0072 : regsvr32 /s /ur /i:inputs\file.sct scrobj.dll 146 | 0x0073 : regsvr32 /s /us /i:inputs\file.sct scrobj.dll 147 | 0x0074 : regsvr32 /s /ut /i:inputs\file.sct scrobj.dll 148 | 0x0075 : regsvr32 /s /uu /i:inputs\file.sct scrobj.dll 149 | 0x0076 : regsvr32 /s /uv /i:inputs\file.sct scrobj.dll 150 | 0x0077 : regsvr32 /s /uw /i:inputs\file.sct scrobj.dll 151 | 0x0078 : regsvr32 /s /ux /i:inputs\file.sct scrobj.dll 152 | 0x0079 : regsvr32 /s /uy /i:inputs\file.sct scrobj.dll 153 | 0x007A : regsvr32 /s /uz /i:inputs\file.sct scrobj.dll 154 | 0x007B : regsvr32 /s /u{ /i:inputs\file.sct scrobj.dll 155 | 0x007C : regsvr32 /s /u| /i:inputs\file.sct scrobj.dll 156 | 0x007D : regsvr32 /s /u} /i:inputs\file.sct scrobj.dll 157 | 0x007E : regsvr32 /s /u~ /i:inputs\file.sct scrobj.dll 158 | 0x007F : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 159 | 0x0081 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 160 | 0x008D : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 161 | 0x008F : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 162 | 0x0090 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 163 | 0x009D : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 164 | 0x00A0 : regsvr32 /s /u  /i:inputs\file.sct scrobj.dll 165 | 0x00A1 : regsvr32 /s /u¡ /i:inputs\file.sct scrobj.dll 166 | 0x00A2 : regsvr32 /s /u¢ /i:inputs\file.sct scrobj.dll 167 | 0x00A3 : regsvr32 /s /u£ /i:inputs\file.sct scrobj.dll 168 | 0x00A4 : regsvr32 /s /u¤ /i:inputs\file.sct scrobj.dll 169 | 0x00A5 : regsvr32 /s /u¥ /i:inputs\file.sct scrobj.dll 170 | 0x00A6 : regsvr32 /s /u¦ /i:inputs\file.sct scrobj.dll 171 | 0x00A7 : regsvr32 /s /u§ /i:inputs\file.sct scrobj.dll 172 | 0x00A8 : regsvr32 /s /u¨ /i:inputs\file.sct scrobj.dll 173 | 0x00A9 : regsvr32 /s /u© /i:inputs\file.sct scrobj.dll 174 | 0x00AA : regsvr32 /s /uª /i:inputs\file.sct scrobj.dll 175 | 0x00AB : regsvr32 /s /u« /i:inputs\file.sct scrobj.dll 176 | 0x00AC : regsvr32 /s /u¬ /i:inputs\file.sct scrobj.dll 177 | 0x00AD : regsvr32 /s /u­ /i:inputs\file.sct scrobj.dll 178 | 0x00AF : regsvr32 /s /u¯ /i:inputs\file.sct scrobj.dll 179 | 0x00B2 : regsvr32 /s /u² /i:inputs\file.sct scrobj.dll 180 | 0x00B3 : regsvr32 /s /u³ /i:inputs\file.sct scrobj.dll 181 | 0x00B4 : regsvr32 /s /u´ /i:inputs\file.sct scrobj.dll 182 | 0x00B6 : regsvr32 /s /u¶ /i:inputs\file.sct scrobj.dll 183 | 0x00B7 : regsvr32 /s /u· /i:inputs\file.sct scrobj.dll 184 | 0x00B8 : regsvr32 /s /u¸ /i:inputs\file.sct scrobj.dll 185 | 0x00B9 : regsvr32 /s /u¹ /i:inputs\file.sct scrobj.dll 186 | 0x00BC : regsvr32 /s /u¼ /i:inputs\file.sct scrobj.dll 187 | 0x00BD : regsvr32 /s /u½ /i:inputs\file.sct scrobj.dll 188 | 0x00BE : regsvr32 /s /u¾ /i:inputs\file.sct scrobj.dll 189 | 0x00C0 : regsvr32 /s /uÀ /i:inputs\file.sct scrobj.dll 190 | 0x00C1 : regsvr32 /s /uÁ /i:inputs\file.sct scrobj.dll 191 | 0x00C2 : regsvr32 /s /u /i:inputs\file.sct scrobj.dll 192 | 0x00C3 : regsvr32 /s /uà /i:inputs\file.sct scrobj.dll 193 | 0x00C4 : regsvr32 /s /uÄ /i:inputs\file.sct scrobj.dll 194 | 0x00C5 : regsvr32 /s /uÅ /i:inputs\file.sct scrobj.dll 195 | 0x00C6 : regsvr32 /s /uÆ /i:inputs\file.sct scrobj.dll 196 | 0x00C7 : regsvr32 /s /uÇ /i:inputs\file.sct scrobj.dll 197 | 0x00C8 : regsvr32 /s /uÈ /i:inputs\file.sct scrobj.dll 198 | 0x00C9 : regsvr32 /s /uÉ /i:inputs\file.sct scrobj.dll 199 | 0x00CA : regsvr32 /s /uÊ /i:inputs\file.sct scrobj.dll 200 | 0x00CB : regsvr32 /s /uË /i:inputs\file.sct scrobj.dll 201 | 0x00CC : regsvr32 /s /uÌ /i:inputs\file.sct scrobj.dll 202 | 0x00CD : regsvr32 /s /uÍ /i:inputs\file.sct scrobj.dll 203 | 0x00CE : regsvr32 /s /uÎ /i:inputs\file.sct scrobj.dll 204 | 0x00CF : regsvr32 /s /uÏ /i:inputs\file.sct scrobj.dll 205 | 0x00D0 : regsvr32 /s /uÐ /i:inputs\file.sct scrobj.dll 206 | 0x00D1 : regsvr32 /s /uÑ /i:inputs\file.sct scrobj.dll 207 | 0x00D2 : regsvr32 /s /uÒ /i:inputs\file.sct scrobj.dll 208 | 0x00D3 : regsvr32 /s /uÓ /i:inputs\file.sct scrobj.dll 209 | 0x00D4 : regsvr32 /s /uÔ /i:inputs\file.sct scrobj.dll 210 | 0x00D6 : regsvr32 /s /uÖ /i:inputs\file.sct scrobj.dll 211 | 0x00D7 : regsvr32 /s /u× /i:inputs\file.sct scrobj.dll 212 | 0x00D8 : regsvr32 /s /uØ /i:inputs\file.sct scrobj.dll 213 | 0x00D9 : regsvr32 /s /uÙ /i:inputs\file.sct scrobj.dll 214 | 0x00DA : regsvr32 /s /uÚ /i:inputs\file.sct scrobj.dll 215 | 0x00DB : regsvr32 /s /uÛ /i:inputs\file.sct scrobj.dll 216 | 0x00DC : regsvr32 /s /uÜ /i:inputs\file.sct scrobj.dll 217 | 0x00DD : regsvr32 /s /uÝ /i:inputs\file.sct scrobj.dll 218 | 0x00DE : regsvr32 /s /uÞ /i:inputs\file.sct scrobj.dll 219 | 0x00DF : regsvr32 /s /uß /i:inputs\file.sct scrobj.dll 220 | 0x00E0 : regsvr32 /s /uà /i:inputs\file.sct scrobj.dll 221 | 0x00E3 : regsvr32 /s /uã /i:inputs\file.sct scrobj.dll 222 | 0x00E4 : regsvr32 /s /uä /i:inputs\file.sct scrobj.dll 223 | 0x00E5 : regsvr32 /s /uå /i:inputs\file.sct scrobj.dll 224 | 0x00E9 : regsvr32 /s /ué /i:inputs\file.sct scrobj.dll 225 | 0x00EA : regsvr32 /s /uê /i:inputs\file.sct scrobj.dll 226 | 0x00EB : regsvr32 /s /uë /i:inputs\file.sct scrobj.dll 227 | 0x00EC : regsvr32 /s /uì /i:inputs\file.sct scrobj.dll 228 | 0x00EE : regsvr32 /s /uî /i:inputs\file.sct scrobj.dll 229 | 0x00EF : regsvr32 /s /uï /i:inputs\file.sct scrobj.dll 230 | 0x00F0 : regsvr32 /s /uð /i:inputs\file.sct scrobj.dll 231 | 0x00F1 : regsvr32 /s /uñ /i:inputs\file.sct scrobj.dll 232 | 0x00F2 : regsvr32 /s /uò /i:inputs\file.sct scrobj.dll 233 | 0x00F3 : regsvr32 /s /uó /i:inputs\file.sct scrobj.dll 234 | 0x00F4 : regsvr32 /s /uô /i:inputs\file.sct scrobj.dll 235 | 0x00F5 : regsvr32 /s /uõ /i:inputs\file.sct scrobj.dll 236 | 0x00F6 : regsvr32 /s /uö /i:inputs\file.sct scrobj.dll 237 | 0x00F7 : regsvr32 /s /u÷ /i:inputs\file.sct scrobj.dll 238 | 0x00F8 : regsvr32 /s /uø /i:inputs\file.sct scrobj.dll 239 | 0x00F9 : regsvr32 /s /uù /i:inputs\file.sct scrobj.dll 240 | 0x00FA : regsvr32 /s /uú /i:inputs\file.sct scrobj.dll 241 | 0x00FB : regsvr32 /s /uû /i:inputs\file.sct scrobj.dll 242 | 0x00FC : regsvr32 /s /uü /i:inputs\file.sct scrobj.dll 243 | 0x00FD : regsvr32 /s /uý /i:inputs\file.sct scrobj.dll 244 | 0x00FE : regsvr32 /s /uþ /i:inputs\file.sct scrobj.dll 245 | 0x02B9 : regsvr32 /s /uʹ /i:inputs\file.sct scrobj.dll 246 | 0x02BA : regsvr32 /s /uʺ /i:inputs\file.sct scrobj.dll 247 | 0x02BC : regsvr32 /s /uʼ /i:inputs\file.sct scrobj.dll 248 | 0x02C4 : regsvr32 /s /u˄ /i:inputs\file.sct scrobj.dll 249 | 0x02C6 : regsvr32 /s /uˆ /i:inputs\file.sct scrobj.dll 250 | 0x02C8 : regsvr32 /s /uˈ /i:inputs\file.sct scrobj.dll 251 | 0x02C9 : regsvr32 /s /uˉ /i:inputs\file.sct scrobj.dll 252 | 0x02CA : regsvr32 /s /uˊ /i:inputs\file.sct scrobj.dll 253 | 0x02CB : regsvr32 /s /uˋ /i:inputs\file.sct scrobj.dll 254 | 0x02CD : regsvr32 /s /uˍ /i:inputs\file.sct scrobj.dll 255 | 0x02DA : regsvr32 /s /u˚ /i:inputs\file.sct scrobj.dll 256 | 0x02DC : regsvr32 /s /u˜ /i:inputs\file.sct scrobj.dll 257 | 0x2070 : regsvr32 /s /u⁰ /i:inputs\file.sct scrobj.dll 258 | 0x2075 : regsvr32 /s /u⁵ /i:inputs\file.sct scrobj.dll 259 | 0x2077 : regsvr32 /s /u⁷ /i:inputs\file.sct scrobj.dll 260 | 0x207F : regsvr32 /s /uⁿ /i:inputs\file.sct scrobj.dll 261 | 0x2080 : regsvr32 /s /u₀ /i:inputs\file.sct scrobj.dll 262 | 0x2082 : regsvr32 /s /u₂ /i:inputs\file.sct scrobj.dll 263 | 0x2087 : regsvr32 /s /u₇ /i:inputs\file.sct scrobj.dll 264 | 0x2088 : regsvr32 /s /u₈ /i:inputs\file.sct scrobj.dll 265 | 266 | :: Character Substitution 267 | The following commands were found to be working: 268 | 0x0043 : regsvr32 /s /C /i:inputs\file.sct scrobj.dll 269 | 0x0045 : regsvr32 /s /E /i:inputs\file.sct scrobj.dll 270 | 0x0049 : regsvr32 /s /I /i:inputs\file.sct scrobj.dll 271 | 0x004E : regsvr32 /s /N /i:inputs\file.sct scrobj.dll 272 | 0x0053 : regsvr32 /s /S /i:inputs\file.sct scrobj.dll 273 | 0x0056 : regsvr32 /s /V /i:inputs\file.sct scrobj.dll 274 | 0x0063 : regsvr32 /s /c /i:inputs\file.sct scrobj.dll 275 | 0x0065 : regsvr32 /s /e /i:inputs\file.sct scrobj.dll 276 | 0x0069 : regsvr32 /s /i /i:inputs\file.sct scrobj.dll 277 | 0x006E : regsvr32 /s /n /i:inputs\file.sct scrobj.dll 278 | 0x0073 : regsvr32 /s /s /i:inputs\file.sct scrobj.dll 279 | 0x0076 : regsvr32 /s /v /i:inputs\file.sct scrobj.dll 280 | 281 | :: Quote Insertion 282 | Inserting quotes in the first argument did work, such as: 283 | regsvr32 /s /u /"i":inputs\file.sct scrobj.dll 284 | 285 | :: Shorthand Commands 286 | No alternative commands were found. 287 | -------------------------------------------------------------------------------- /sample_results/robocopy.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR robocopy 2 | - Generated on 2021-01-04T00:10:55.206747 3 | - Command used : robocopy c:\windows\temp c:\windows\temp\temp2 /L 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002D : robocopy c:\windows\temp c:\windows\temp\temp2 -L 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Substitution 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did not appear to be working. 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/route.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR ROUTE 2 | - Generated on 2021-01-02T14:38:35.220402 3 | - Command used : ROUTE PRINT 123* 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Substitution 14 | The following commands were found to be working: 15 | 0x0154 : ROUTE PŔINT 123* 16 | 0x0155 : ROUTE PŕINT 123* 17 | 0x0156 : ROUTE PŖINT 123* 18 | 0x0157 : ROUTE PŗINT 123* 19 | 0x0158 : ROUTE PŘINT 123* 20 | 0x0159 : ROUTE PřINT 123* 21 | 0x211B : ROUTE PℛINT 123* 22 | 0x211C : ROUTE PℜINT 123* 23 | 0x211D : ROUTE PℝINT 123* 24 | 0xFF32 : ROUTE PRINT 123* 25 | 0xFF52 : ROUTE PrINT 123* 26 | 27 | :: Quote Insertion 28 | Inserting quotes in the first argument did work, such as: 29 | ROUTE P"R"INT 123* 30 | 31 | :: Shorthand Commands 32 | No alternative commands were found. 33 | -------------------------------------------------------------------------------- /sample_results/sc.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR sc 2 | - Generated on 2020-11-29T03:08:00.958477 3 | - Command used : sc query eventlog 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Replacement 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did work, such as: 18 | sc q"u"ery eventlog 19 | 20 | :: Shortened Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/schtasks.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR schtasks 2 | - Generated on 2021-01-02T13:24:43.862104 3 | - Command used : schtasks /showsid /TN \Microsoft\XblGameSave\XblGameSaveTask 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 2 commands were found to be working: 9 | 0x002D : schtasks -showsid /TN \Microsoft\XblGameSave\XblGameSaveTask 10 | 0xFE63 : schtasks ﹣showsid /TN \Microsoft\XblGameSave\XblGameSaveTask 11 | 12 | :: Character Insertion 13 | No alternative commands were found. 14 | 15 | :: Character Substitution 16 | The following commands were found to be working: 17 | 0x02E2 : schtasks /ˢhowsid /TN \Microsoft\XblGameSave\XblGameSaveTask 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did work, such as: 21 | schtasks /"s"howsid /TN \Microsoft\XblGameSave\XblGameSaveTask 22 | 23 | :: Shorthand Commands 24 | No alternative commands were found. 25 | -------------------------------------------------------------------------------- /sample_results/systeminfo.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR systeminfo 2 | - Generated on 2020-11-30T14:00:18.809353 3 | - Command used : systeminfo /s localhost 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 2 commands were found to be working: 9 | 0x002D : systeminfo -s localhost 10 | 0xFE63 : systeminfo ﹣s localhost 11 | 12 | :: Character Insertion 13 | No alternative commands were found. 14 | 15 | :: Character Replacement 16 | The following commands were found to be working: 17 | 0x02E2 : systeminfo /ˢ localhost 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did work, such as: 21 | systeminfo /"s" localhost 22 | 23 | :: Shortened Commands 24 | No alternative commands were found. 25 | -------------------------------------------------------------------------------- /sample_results/takeown.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR takeown 2 | - Generated on 2021-01-02T21:21:32.881566 3 | - Command used : takeown /F config.json 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 2 commands were found to be working: 9 | 0x002D : takeown -F config.json 10 | 0xFE63 : takeown ﹣F config.json 11 | 12 | :: Character Insertion 13 | The following 2 commands were found to be working: 14 | 0x0009 : takeown /F config.json 15 | 0x0020 : takeown /F config.json 16 | 17 | :: Character Substitution 18 | The following commands were found to be working: 19 | 0x1DA0 : takeown /ᶠ config.json 20 | 21 | :: Quote Insertion 22 | Inserting quotes in the first argument did work, such as: 23 | takeown /"F" config.json 24 | 25 | :: Shorthand Commands 26 | No alternative commands were found. 27 | -------------------------------------------------------------------------------- /sample_results/taskkill.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR taskkill 2 | - Generated on 2021-01-02T15:11:02.001944 3 | - Command used : taskkill /im test.exe 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 2 commands were found to be working: 9 | 0x002D : taskkill -im test.exe 10 | 0xFE63 : taskkill ﹣im test.exe 11 | 12 | :: Character Insertion 13 | No alternative commands were found. 14 | 15 | :: Character Substitution 16 | The following commands were found to be working: 17 | 0x1D35 : taskkill /ᴵm test.exe 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did work, such as: 21 | taskkill /"i"m test.exe 22 | 23 | :: Shorthand Commands 24 | No alternative commands were found. 25 | -------------------------------------------------------------------------------- /sample_results/tasklist.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR tasklist 2 | - Generated on 2020-11-30T13:22:20.949047 3 | - Command used : tasklist /fi "USERNAME eq test" 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The following 2 commands were found to be working: 9 | 0x002D : tasklist -fi "USERNAME eq test" 10 | 0xFE63 : tasklist ﹣fi "USERNAME eq test" 11 | 12 | :: Character Insertion 13 | No alternative commands were found. 14 | 15 | :: Character Replacement 16 | The following commands were found to be working: 17 | 0x1DA0 : tasklist /ᶠi "USERNAME eq test" 18 | 19 | :: Quote Insertion 20 | Inserting quotes in the first argument did work, such as: 21 | tasklist /"f"i "USERNAME eq test" 22 | 23 | :: Shortened Commands 24 | No alternative commands were found. 25 | -------------------------------------------------------------------------------- /sample_results/vbc.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR vbc.exe 2 | - Generated on 2021-01-04T00:22:20.956666 3 | - Command used : c:\windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe /target:exe /out:cache\file.exe inputs\file.vbs 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002D : c:\windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe -target:exe /out:cache\file.exe inputs\file.vbs 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Substitution 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did not appear to be working. 19 | 20 | :: Shorthand Commands 21 | The following 1 commands were found to be working: 22 | c:\windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe /t:exe /out:cache\file.exe inputs\file.vbs 23 | -------------------------------------------------------------------------------- /sample_results/vssadmin.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR vssadmin.exe 2 | - Generated on 2021-01-03T22:36:50.549504 3 | - Command used : c:\users\wietze\downloads\test\vssadmin.exe list volumes 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Substitution 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did work, such as: 18 | c:\users\wietze\downloads\test\vssadmin.exe l"i"st volumes 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/winrm.cmd.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR winrm.cmd 2 | - Generated on 2021-01-03T23:23:18.787991 3 | - Command used : c:\windows\system32\winrm.cmd get winrm/config -format:text 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0x00FE 0x02B0..0x02FE 0x2070..0x209E 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002F : c:\windows\system32\winrm.cmd get winrm/config /format:text 10 | 11 | :: Character Insertion 12 | The following 1 commands were found to be working: 13 | 0x005E : c:\windows\system32\winrm.cmd get winrm/config -for^mat:text 14 | 15 | :: Character Substitution 16 | No alternative commands were found. 17 | 18 | :: Quote Insertion 19 | Inserting quotes in the first argument did not appear to be working. 20 | 21 | :: Shorthand Commands 22 | The following 1 commands were found to be working: 23 | c:\windows\system32\winrm.cmd get winrm/config -f:text 24 | -------------------------------------------------------------------------------- /sample_results/winrs.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR winrs 2 | - Generated on 2021-01-02T21:01:52.318909 3 | - Command used : winrs -r:localhost echo hello 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Option Char Substitution 8 | The following 1 commands were found to be working: 9 | 0x002F : winrs /r:localhost echo hello 10 | 11 | :: Character Insertion 12 | No alternative commands were found. 13 | 14 | :: Character Substitution 15 | No alternative commands were found. 16 | 17 | :: Quote Insertion 18 | Inserting quotes in the first argument did not appear to be working. 19 | 20 | :: Shorthand Commands 21 | No alternative commands were found. 22 | -------------------------------------------------------------------------------- /sample_results/wmic.log: -------------------------------------------------------------------------------- 1 | PROCESS OBFUSCATION REPORT FOR wmic 2 | - Generated on 2020-11-29T02:56:59.426171 3 | - Command used : wmic os get BuildNumber 4 | - Insertion position: ^ 5 | - Char ranges scanned: 0x0001..0xFFFE 6 | 7 | :: Different dash/hyphens 8 | The command does not contain any arguments starting with a slash or dash. 9 | 10 | :: Character Insertion 11 | No alternative commands were found. 12 | 13 | :: Character Replacement 14 | No alternative commands were found. 15 | 16 | :: Quote Insertion 17 | Inserting quotes in the first argument did not appear to be working. 18 | 19 | :: Shortened Commands 20 | No alternative commands were found. 21 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | description_short = "Project for identifying executables that have command-line options that can be obfuscated, possibly bypassing detection rules." 4 | with open("README.md", "r", encoding="utf-8") as fh: 5 | description_long = fh.read() 6 | 7 | setuptools.setup( 8 | name="analyse_obfuscation", 9 | version="1.1.0", 10 | author="@Wietze", 11 | description=description_short, 12 | long_description=description_long, 13 | long_description_content_type="text/markdown", 14 | url="https://github.com/wietze/windows-command-line-obfuscation", 15 | packages=setuptools.find_packages(), 16 | classifiers=[ 17 | "Programming Language :: Python :: 3", 18 | "License :: OSI Approved :: GNU Affero General Public License v3", 19 | "Operating System :: Microsoft :: Windows", 20 | 'Intended Audience :: Developers', 21 | 'Intended Audience :: Information Technology', 22 | 'Intended Audience :: System Administrators', 23 | 'Topic :: Security', 24 | 'Topic :: Internet :: Log Analysis', 25 | 'Environment :: Console', 26 | ], 27 | entry_points={ 28 | 'console_scripts': [ 29 | 'analyse_obfuscation = analyse_obfuscation.run:parse_arguments' 30 | ], 31 | }, 32 | install_requires=['tqdm', 'colorama', 'terminaltables'] 33 | ) 34 | --------------------------------------------------------------------------------