├── .github
├── FUNDING.yml
└── workflows
│ ├── deploy.yml
│ └── pull.yml
├── .gitignore
├── LICENSE
├── README.md
├── algorithms
├── __init__.py
├── add1501_shl5.py
├── add_65599.py
├── add_hiword_add_lowword.py
├── add_rol5_hash_again.py
├── add_ror13.py
├── add_ror13_hash_again.py
├── add_ror4.py
├── adler32_666.py
├── babbleloader.py
├── babbleloader_0125.py
├── blister2.py
├── brc4_1_4_5.py
├── brc4_joaat.py
├── carbanak.py
├── ch_add_rol8.py
├── conti.py
├── conti_5b2d.py
├── conti_b801fcda.py
├── conti_e9ff0077.py
├── conti_mm3.py
├── crc32.py
├── crc32_bzip2.py
├── crc32_mpeg_2.py
├── crc64_ecma_182.py
├── cryptbot_ror13_add_10.py
├── d0nut.py
├── danabot.py
├── deedrat.py
├── deedrat_export_name.py
├── djb2_lowercase.py
├── djb2_nokoyawa.py
├── djb2_uppercase.py
├── djb2_vohuk_ransomware_dec_2022.py
├── dualacc_modfff1.py
├── emotet.py
├── emotet_mul_65599_xor_19ad760.py
├── fnv1.py
├── fnv1_64.py
├── fnv1_xor67f.py
├── fnv1a.py
├── fnv1a_64.py
├── guloader_3C389ABC.py
├── lockbit3_C8B32494_s0.py
├── lockbit3_C8B32494_string.py
├── lockbit4_0225.py
├── lokibot.py
├── lumma_fnv1a.py
├── mamon_hash.py
├── metasploit.py
├── mul21_add.py
├── mul21_add_seed_8952.py
├── mul7_add.py
├── mul83_add.py
├── mult21_add.py
├── mult21_add_170f.py
├── mult3_add_init_9C.py
├── murmur2_lummas_v3.py
├── mythic_unknown.py
├── or20_xor_rol19.py
├── or21_xor_rol11.py
├── or23_xor_rol17.py
├── paradise_murmurhash3.py
├── permutations_82f63b78.py
├── permutations_e8677835.py
├── revil_010F.py
├── rol3_xor.py
├── rol3_xor_eax.py
├── rol5_add.py
├── rol5_xor.py
├── rol7_add.py
├── rol7_add_xor2.py
├── rol7_xor.py
├── rol8_xor_b0d4d06.py
├── rol9_add.py
├── rol9_xor.py
├── ror11_add.py
├── ror13_add.py
├── ror13_add_negative_seed.py
├── ror13_add_sub1.py
├── ror13_add_sub20.py
├── ror7_add.py
├── ror8_add_xor_ab832e83.py
├── ror9_add.py
├── sdbm_65599_x64.py
├── shl1_add.py
├── shl7_shr19_xor.py
├── shl7_sub.py
├── shr1_shl7_2326.py
├── shr2_shl5_xor.py
├── shr2_shl5_xor_init_c4d5a97a_stealbit.py
├── smokeloader_rol8_xor.py
├── tonepipeshell.py
├── tonepipeshell_alt.py
├── tonepipeshell_feb_2025.py
├── xor_rol9.py
├── xor_shr8.py
└── zloader_bot.py
├── hashdb.py
└── tests
└── test_algorithms.py
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | patreon: oalabs
2 |
3 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: AWS Lambda Deploy
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 |
7 | workflow_dispatch:
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 |
16 | - name: Setup distribution package
17 | run: |
18 | echo "Building distribution package"
19 | mkdir ./dist
20 | mkdir ./dist/python
21 | mkdir ./dist/python/algorithms
22 | cp *.py ./dist/python
23 | cp -r ./algorithms/* ./dist/python/algorithms/
24 | cd ./dist
25 | zip -r hashdb.zip ./python
26 |
27 | - name: Set up Python 3.9
28 | uses: actions/setup-python@v2
29 | with:
30 | python-version: 3.9
31 |
32 | - name: Install AWS CLI and tools
33 | run: |
34 | python -m pip install --upgrade pip
35 | pip install awscli
36 | sudo apt-get update
37 | sudo apt-get install -y jq
38 |
39 | - name: Publish to AWS Lambda Layer
40 | env:
41 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
42 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
43 | LAMBDA_LAYER_ARN: ${{ secrets.LAMBDA_LAYER_ARN }}
44 | AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
45 | HASHDB_WORKER_LAMBDA_ARN: ${{ secrets.HASHDB_WORKER_LAMBDA_ARN }}
46 | HASHDB_API_LAMBDA_ARN: ${{ secrets.HASHDB_API_LAMBDA_ARN }}
47 | run: |
48 | echo "Publishing as a layer..."
49 | RESULT_DATA=$(aws lambda publish-layer-version --layer-name "$LAMBDA_LAYER_ARN" --zip-file fileb://dist/hashdb.zip)
50 | LAYER_VERSION=$(jq '.Version' <<< "$RESULT_DATA")
51 | echo "Updating hashdb worker to use layer version $LAYER_VERSION..."
52 | UPDATE_RESULT_DATA1=$(aws lambda update-function-configuration --function-name "$HASHDB_WORKER_LAMBDA_ARN" --layers "$LAMBDA_LAYER_ARN:$LAYER_VERSION")
53 | UPDATE_RESULT_DATA2=$(aws lambda update-function-configuration --function-name "$HASHDB_API_LAMBDA_ARN" --layers "$LAMBDA_LAYER_ARN:$LAYER_VERSION")
54 | echo '::set-output name=SELECTED_COLOR::green'
55 | echo "Done"
56 |
57 |
58 |
--------------------------------------------------------------------------------
/.github/workflows/pull.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: Pull request filtering algorithms
5 |
6 | on:
7 | pull_request:
8 | branches: [ main ]
9 |
10 | workflow_dispatch:
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 | - name: Lint with flake8
28 | run: |
29 | # stop the build if there are Python syntax errors or undefined names
30 | flake8 ./algorithms --count --select=E9,F63,F7,F82 --show-source --statistics
31 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
32 | flake8 ./algorithms --count --exit-zero --max-complexity=15 --max-line-length=127 --statistics --show-source
33 | - name: Test with pytest
34 | run: |
35 | python -m pytest
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Apple crap
2 | .DS_Store
3 | .AppleDouble
4 | .LSOverride
5 |
6 | # Byte-compiled / optimized / DLL files
7 | __pycache__/
8 | *.py[cod]
9 | *$py.class
10 |
11 | # C extensions
12 | *.so
13 |
14 | # Distribution / packaging
15 | .Python
16 | build/
17 | develop-eggs/
18 | dist/
19 | downloads/
20 | eggs/
21 | .eggs/
22 | lib/
23 | lib64/
24 | parts/
25 | sdist/
26 | var/
27 | wheels/
28 | pip-wheel-metadata/
29 | share/python-wheels/
30 | *.egg-info/
31 | .installed.cfg
32 | *.egg
33 | MANIFEST
34 |
35 | # PyInstaller
36 | # Usually these files are written by a python script from a template
37 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
38 | *.manifest
39 | *.spec
40 |
41 | # Installer logs
42 | pip-log.txt
43 | pip-delete-this-directory.txt
44 |
45 | # Unit test / coverage reports
46 | htmlcov/
47 | .tox/
48 | .nox/
49 | .coverage
50 | .coverage.*
51 | .cache
52 | nosetests.xml
53 | coverage.xml
54 | *.cover
55 | *.py,cover
56 | .hypothesis/
57 | .pytest_cache/
58 |
59 | # Translations
60 | *.mo
61 | *.pot
62 |
63 | # Django stuff:
64 | *.log
65 | local_settings.py
66 | db.sqlite3
67 | db.sqlite3-journal
68 |
69 | # Flask stuff:
70 | instance/
71 | .webassets-cache
72 |
73 | # Scrapy stuff:
74 | .scrapy
75 |
76 | # Sphinx documentation
77 | docs/_build/
78 |
79 | # PyBuilder
80 | target/
81 |
82 | # Jupyter Notebook
83 | .ipynb_checkpoints
84 |
85 | # IPython
86 | profile_default/
87 | ipython_config.py
88 |
89 | # pyenv
90 | .python-version
91 |
92 | # pipenv
93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
96 | # install all needed dependencies.
97 | #Pipfile.lock
98 |
99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
100 | __pypackages__/
101 |
102 | # Celery stuff
103 | celerybeat-schedule
104 | celerybeat.pid
105 |
106 | # SageMath parsed files
107 | *.sage.py
108 |
109 | # Environments
110 | .env
111 | .venv
112 | env/
113 | venv/
114 | ENV/
115 | env.bak/
116 | venv.bak/
117 |
118 | # Spyder project settings
119 | .spyderproject
120 | .spyproject
121 |
122 | # Rope project settings
123 | .ropeproject
124 |
125 | # mkdocs documentation
126 | /site
127 |
128 | # mypy
129 | .mypy_cache/
130 | .dmypy.json
131 | dmypy.json
132 |
133 | # Pyre type checker
134 | .pyre/
135 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |  [](https://discord.gg/cw4U3WHvpn) [](https://www.patreon.com/oalabs)
4 | # HashDB
5 |
6 | HashDB is a community-sourced library of hashing algorithms used in malware.
7 |
8 | ## How To Use HashDB
9 |
10 | HashDB can be used as a stand alone hashing library, but it also feeds the [HashDB Lookup Service](https://hashdb.openanalysis.net) run by OALabs. This service allows analysts to reverse hashes and retrieve hashed API names and string values.
11 |
12 | ### Stand Alone Module
13 |
14 | HashDB can be cloned and used in your reverse engineering scripts like any standard Python module. Some example code follows.
15 | ```python
16 | >>> import hashdb
17 | >>> hashdb.list_algorithms()
18 | ['crc32']
19 | >>> hashdb.algorithms.crc32.hash(b'test')
20 | 3632233996
21 | ```
22 |
23 | ### HashDB Lookup Service
24 |
25 | OALabs run a free [HashDB Lookup Service](https://hashdb.openanalysis.net) that can be used to query a hash table for any hash listed in the HashDb library. Included in the hash tables are the complete set of Windows APIs as well as a many common strings used in malware. You can even add your own strings!
26 |
27 | #### HashDB IDA Plugin
28 |
29 | The HashDB lookup service has an IDA Pro plugin that can be used to automate hash lookups directly from IDA!
30 | The client can be downloaded from GitHub [here](https://github.com/OALabs/hashdb-ida).
31 |
32 | ## How To Add New Hashes
33 |
34 | HashDB relies on community support to keep our hash library current! Our goal is to have contributors spend **no more than five minutes** adding a new hash, from first commit, to PR. To achieve this goal we offer the following streamlined process.
35 |
36 | 1. Make sure the hash algorithm doesn’t already exist… we know that seems silly but just double check.
37 |
38 | 2. Create a branch with a descriptive name.
39 |
40 | 3. Add a new Python file to the `/algorithms` directory with the name of your hash algorithm. Try to use the official name of the algorithm, or if it is unique, use the name of the malware that it is unique to.
41 |
42 | 4. Use the following template to setup your new hash algorithm. All fields are mandatory and case sensitive.
43 |
44 | ```python
45 | #!/usr/bin/env python
46 |
47 | DESCRIPTION = "your hash description here"
48 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
49 | TYPE = 'unsigned_int'
50 | # Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
51 | TEST_1 = hash_of_string_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
52 |
53 |
54 | def hash(data):
55 | # your hash code here
56 | ```
57 |
58 | 5. Double check your Python style, we use Flake8 on Python 3.9. You can try the following lint commands locally from the root of the git repository.
59 |
60 | ```
61 | pip install flake8
62 | flake8 ./algorithms --count --select=E9,F63,F7,F82 --show-source --statistics
63 | ```
64 |
65 | 6. Test your code locally using our test suite. Run the following commands locally from the root of the git repository. Note that you must run pytest as a module rather than directly or it won't pick up our test directory.
66 |
67 | ```
68 | pip install pytest
69 | python -m pytest
70 | ```
71 |
72 | 7. Issue a pull request — your new algorithm will be automatically queued for testing and if successful it will be merged.
73 |
74 | That’s it! Not only will your new hash be available in the HashDB library but a new hash table will be generated for the [HashDB Lookup Service](https://hashdb.openanalysis.net) and you can start reversing hashes immediately!
75 |
76 | ### ❗Rules For New Hashes
77 |
78 | PRs with changes outside of the `/algorithms` directory are not part of our automated CI and will be subjected to extra scrutiny.
79 |
80 | All hashes must have a valid description in the `DESCRIPTION` field.
81 |
82 | All hashes must have a type of either `unsigned_int` or `unsigned_long` in the `TYPE` field. HashDB currently only accepts unsigned 32bit or 64bit hashes.
83 |
84 | All hashes must have the hash of the string __ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789__ in the `TEST_1` field.
85 |
86 | All hashes must include a function `hash(data)` that accepts a byte string and returns a hash of the string.
87 |
88 | ### Adding Custom API Hashes
89 |
90 | Some hash algorithms hash the module name and API separately and combine the hashes to create a single module+API hash. An example of this is the standard [Metasploit ROR13 hash](https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/hash.py). These algorithms will not work with the standard wordlist and require a custom wordlist that includes both the module name and API. To handle these we allow custom algorithms that will only return a valid hash for some words.
91 |
92 | Adding a custom API hash requires the following additional components.
93 |
94 | 1. The `TEST_1` field must be set to 4294967294 (-1).
95 |
96 | 2. The hash algorithm must return the value 4294967294 for all invalid hashes.
97 |
98 | 3. An additional `TEST_API_DATA_1` field must be added with an example word that is valid for the algorithm.
99 |
100 | 4. An additional `TEST_API_1` field must be added with the hash of the `TEST_API_DATA_1` field.
101 |
102 | ## Standing On The Shoulders of Giants
103 |
104 | A big shout out to the FLARE team for their efforts with [shellcode_hashes](https://github.com/fireeye/flare-ida/tree/master/shellcode_hashes). Many years ago this project set the bar for quick and easy malware hash reversing and it’s still an extremely useful tool. So why duplicate it?
105 |
106 | Frankly, it’s all about the wordlist and accessibility. We have seen a dramatic shift towards using hashes for all sorts of strings in malware now, and the old method of hashing all the Windows’ DLL exports just isn’t good enough. We wanted a solution that could continuously process millions of registry keys and values, filenames, and process names. And we wanted that data available via a REST API so that we could use it our automation workflows, not just our static analysis tools. That being said, we wouldn’t exist without shellcode_hashes, so credit where credit is due 🙌
107 |
108 | ---
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/algorithms/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Stores a list of module string names in __all__
5 | import os
6 | import glob
7 | from importlib import import_module
8 | files = glob.glob(os.path.dirname(__file__) + "/*.py")
9 | __all__ = [os.path.basename(f)[:-3] for f in files if "__init__" not in f]
10 | modules = {}
11 | for module_name in __all__:
12 | modules[module_name] = import_module(f"{__name__}.{module_name}")
13 |
--------------------------------------------------------------------------------
/algorithms/add1501_shl5.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ADD 0x1505 and SHIFT LEFT 5"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 205455184
26 |
27 |
28 | def hash(data):
29 | val = 0x1505
30 | for ch in data:
31 | val += (val << 5)
32 | val &= 0xFFFFFFFF
33 | val += ch
34 | val &= 0xFFFFFFFF
35 | return val
36 |
--------------------------------------------------------------------------------
/algorithms/add_65599.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "ADD 65599 and MULTIPLY"
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 2480409887
5 |
6 | def hash(data):
7 | result = 0
8 | for c in data:
9 | tmp = c + 32
10 | if(((c - ord('A')) & 0xFFFF) > 26):
11 | tmp = c
12 | result = (tmp + 0x1003F * result) & 0xFFFFFFFF
13 |
14 | return result
15 |
--------------------------------------------------------------------------------
/algorithms/add_hiword_add_lowword.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Sum of characters in hi word and low word combined to DWORD.
5 | Used in Darkside ransomware API hash."""
6 | TYPE = 'unsigned_int'
7 | TEST_1 = 2383353113
8 |
9 |
10 | def hash(data):
11 | hash_high = 0xffff
12 | hash_low = 0xffff
13 | for ptr in range(len(data)):
14 | hash_low = (hash_low + data[ptr])
15 | hash_high = (hash_high + hash_low)
16 | hash_high %= 0xFFF1
17 | hash_low %= 0xFFF1
18 | return (hash_high << 16) + hash_low
19 |
--------------------------------------------------------------------------------
/algorithms/add_rol5_hash_again.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ADD and ROL 5 and ROL 5 the result"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3853345759
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val += i
52 | val = rol(val, 0x5, 32)
53 | val = rol(val, 0x5, 32)
54 | return val
55 |
--------------------------------------------------------------------------------
/algorithms/add_ror13.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ADD and ROR 13"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3953483048
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val += i
52 | val = ror(val, 0xd, 32)
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/add_ror13_hash_again.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ADD and ROR 13 and ROR 13 the result"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3913768234
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val += i
52 | val = ror(val, 0xd, 32)
53 | val = ror(val, 0xd, 32)
54 | return val
55 |
--------------------------------------------------------------------------------
/algorithms/add_ror4.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ADD and ROR 4"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 234261009
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = (val & 0xffffff00) + ((val + i) & 0xff)
52 | val = ror(val, 0x4, 32)
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/adler32_666.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | import zlib
24 |
25 | DESCRIPTION = "Adler-32 checksum with 666 seed."
26 | TYPE = 'unsigned_int'
27 | TEST_1 = 737679269
28 |
29 |
30 | def hash(data):
31 | return zlib.adler32(data, 666) & 0xffffffff
32 |
--------------------------------------------------------------------------------
/algorithms/babbleloader.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 |
5 | Author = 0x0d4y
6 |
7 | This hashing algorithm was found during my analysis of a BabbleLoader sample, with the goal of validating that the correct API function was obtained.
8 |
9 | Sample MD5:FA3D03C319A7597712EEFF1338DABF92
10 |
11 | Reference: https://0x0d4y.blog/babbleloader-deep-dive-into-edr-and-machine-learning-based-endpoint-protection-evasion/
12 |
13 | """
14 | TYPE = 'unsigned_int'
15 |
16 | TEST_1 = 4238996181
17 |
18 | def hash(data):
19 | if isinstance(data, bytes):
20 | data = data.decode('utf-8')
21 |
22 | final_hash = 0
23 | for char in data:
24 | char_orded = ord(char)
25 | final_hash = (final_hash + char_orded) * (char_orded + 0x4af1e366)
26 | final_hash &= 0xFFFFFFFF
27 |
28 | return final_hash
29 |
30 |
--------------------------------------------------------------------------------
/algorithms/babbleloader_0125.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 |
5 | Author = 0x0d4y
6 |
7 | Description = This new algorithm was discovered during ongoing monitoring of BabbleLoader, which implements it to obfuscate APIs.
8 |
9 | Sample_I MD5: 06e1c0ee8a7f340d77c95be867c49284
10 | Sample_II MD5: 7d1a15fd3c17ad226b3516bea26d7a94
11 |
12 | Reference: https://0x0d4y.blog/babbleloader-deep-dive-into-edr-and-machine-learning-based-endpoint-protection-evasion/
13 |
14 | """
15 | TYPE = 'unsigned_int'
16 |
17 | TEST_1 = 3847507269
18 |
19 | def hash(data):
20 | if isinstance(data, bytes):
21 | data = data.decode('utf-8')
22 |
23 | final_hash = 0
24 | for char in data:
25 | char_orded = ord(char)
26 | final_hash = (final_hash + char_orded) * (char_orded + 0x1c9943d2)
27 | final_hash &= 0xFFFFFFFF
28 |
29 | return final_hash
30 |
31 |
--------------------------------------------------------------------------------
/algorithms/blister2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Blister loader v2 api hash"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 0x6d223692
6 |
7 |
8 | def hash(data):
9 | h = 0x78f1e5bf
10 | for c in data:
11 | h = (((c ^ h) & 0xffffffff) * 0x5bd1e995) & 0xffffffff
12 | h = (h ^ ((h >> 15) & 0xffffffff)) & 0xffffffff
13 | return h
14 |
--------------------------------------------------------------------------------
/algorithms/brc4_1_4_5.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Hash algorithm used in BRC4 1.4.5"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 3471553803
8 |
9 |
10 | def hash(data):
11 | result = 0
12 | for c in data:
13 | temp = 2049 * result
14 | temp |= 0x2800000
15 | temp += c
16 | result = temp & 0xFFFFFFFF
17 |
18 | return result
19 |
--------------------------------------------------------------------------------
/algorithms/brc4_joaat.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Jenkins One At A Time (JOAAT) Hashing Algorithm Used by BRC4"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 4059668722
8 |
9 |
10 | def hash(data):
11 | val = 0
12 | for c in data:
13 | v1 = c + val
14 | v2 = (1025 * v1) & 0xffffffff
15 | v3 = v2 >> 6
16 | val = v2 ^ v3
17 |
18 | val = (val + val * 8) & 0xffffffff
19 | r1 = val >> 11
20 | r2 = val ^ r1
21 | result = r2 * 32769 & 0xffffffff
22 |
23 | return result
24 |
--------------------------------------------------------------------------------
/algorithms/carbanak.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "Carbanak API hashing used by CARBON SPIDER aka FIN7"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 204821865
26 |
27 |
28 | def hash(data):
29 | ctr = 0
30 | for i in data:
31 | ctr = (ctr << 4) + i
32 | if (ctr & 0xF0000000):
33 | ctr = (((ctr & 0xF0000000) >> 24) ^ ctr) & 0x0FFFFFFF
34 | return ctr
35 |
--------------------------------------------------------------------------------
/algorithms/ch_add_rol8.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "XOR and ROL 8 and SLICE hex"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 377121536
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = val ^ (i * 256)
52 | val = rol(val, 0x8, 32)
53 | val_hex = "%08x" % val
54 | valh_str = val_hex[4:6]
55 | valh = int(valh_str, 16)
56 | val = val ^ valh
57 | return val
58 |
--------------------------------------------------------------------------------
/algorithms/conti.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "Conti ransomware api hash"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2524534739
26 |
27 |
28 | def hash(data):
29 | API_buffer = []
30 |
31 | i = len(data) >> 3
32 |
33 | count = 0
34 | while i != 0:
35 | for index in range(0, 8):
36 | API_buffer.append(data[index + count])
37 | count += 8
38 | i -= 1
39 |
40 | if len(data) & 7 != 0:
41 | v8 = len(data) & 7
42 |
43 | while v8 != 0:
44 | API_buffer.append(data[count])
45 | count += 1
46 | v8 -= 1
47 |
48 | hash_val = 0
49 |
50 | for i in range(0, len(API_buffer)):
51 | API_buffer[i] = ord(chr(API_buffer[i]))
52 |
53 | v15 = 0xFF889912
54 | string_length_2 = len(data)
55 | API_buffer_count = 0
56 | if len(data) >= 4:
57 | count = string_length_2 >> 2
58 | string_length_2 = (string_length_2 - 4 *
59 | (string_length_2 >> 2)) & 0xFFFFFFFF
60 |
61 | while True:
62 | temp_buffer_val = API_buffer[API_buffer_count +
63 | 3] << 24 | API_buffer[API_buffer_count +
64 | 2] << 16 | API_buffer[API_buffer_count +
65 | 1] << 8 | API_buffer[API_buffer_count]
66 |
67 | temp = (0x5BD1E995 * temp_buffer_val) & 0xFFFFFFFF
68 | API_buffer_count += 4
69 | v15 = ((0x5BD1E995 * (temp ^
70 | (temp >> 0x18))) & 0xFFFFFFFF) ^ ((0x5BD1E995 * v15) & 0xFFFFFFFF)
71 | count -= 1
72 | if count == 0:
73 | break
74 |
75 | v18 = string_length_2 - 1
76 |
77 | v19 = v18 - 1
78 |
79 | if v18 == 0:
80 | hash_val ^= API_buffer[API_buffer_count]
81 | elif v19 == 0:
82 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
83 | hash_val ^= API_buffer[API_buffer_count]
84 | elif v19 == 1:
85 | hash_val ^= API_buffer[API_buffer_count + 2] << 16
86 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
87 | hash_val ^= API_buffer[API_buffer_count]
88 |
89 | v20 = (0x5BD1E995 * hash_val) & 0xFFFFFFFF
90 | edi = (0x5BD1E995 * len(data)) & 0xFFFFFFFF
91 |
92 | eax = v20 >> 0x18
93 | eax ^= v20
94 |
95 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
96 | eax = (0x5BD1E995 * v15) & 0xFFFFFFFF
97 |
98 | ecx ^= eax
99 |
100 | eax = edi
101 | eax >>= 0x18
102 | eax ^= edi
103 |
104 | edx = (0x5BD1E995 * ecx) & 0xFFFFFFFF
105 | eax = (0x5BD1E995 * eax) & 0xFFFFFFFF
106 | edx ^= eax
107 | eax = edx
108 |
109 | eax >>= 0xD
110 | eax ^= edx
111 |
112 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
113 | eax = ecx
114 | eax >>= 0xF
115 | eax ^= ecx
116 |
117 | return eax
118 |
--------------------------------------------------------------------------------
/algorithms/conti_5b2d.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Conti ransomware api hash with seed 0x5B2D"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3350281850
6 |
7 |
8 | def hash(data):
9 | API_buffer = []
10 |
11 | i = len(data) >> 3
12 |
13 | count = 0
14 | while i != 0:
15 | for index in range(0, 8):
16 | API_buffer.append(data[index + count])
17 | count += 8
18 | i -= 1
19 |
20 | if len(data) & 7 != 0:
21 | v8 = len(data) & 7
22 |
23 | while v8 != 0:
24 | API_buffer.append(data[count])
25 | count += 1
26 | v8 -= 1
27 |
28 | hash_val = 0
29 |
30 | for i in range(0, len(API_buffer)):
31 | API_buffer[i] = ord(chr(API_buffer[i]))
32 |
33 | v15 = 0x5B2D
34 | string_length_2 = len(data)
35 | API_buffer_count = 0
36 | if len(data) >= 4:
37 | count = string_length_2 >> 2
38 | string_length_2 = (string_length_2 - 4 *
39 | (string_length_2 >> 2)) & 0xFFFFFFFF
40 |
41 | while True:
42 | temp_buffer_val = API_buffer[API_buffer_count +
43 | 3] << 24 | API_buffer[API_buffer_count +
44 | 2] << 16 | API_buffer[API_buffer_count +
45 | 1] << 8 | API_buffer[API_buffer_count]
46 |
47 | temp = (0x5BD1E995 * temp_buffer_val) & 0xFFFFFFFF
48 | API_buffer_count += 4
49 | v15 = ((0x5BD1E995 * (temp ^
50 | (temp >> 0x18))) & 0xFFFFFFFF) ^ ((0x5BD1E995 * v15) & 0xFFFFFFFF)
51 | count -= 1
52 | if count == 0:
53 | break
54 |
55 | v18 = string_length_2 - 1
56 |
57 | v19 = v18 - 1
58 |
59 | if v18 == 0:
60 | hash_val ^= API_buffer[API_buffer_count]
61 | elif v19 == 0:
62 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
63 | hash_val ^= API_buffer[API_buffer_count]
64 | elif v19 == 1:
65 | hash_val ^= API_buffer[API_buffer_count + 2] << 16
66 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
67 | hash_val ^= API_buffer[API_buffer_count]
68 |
69 | v20 = (0x5BD1E995 * hash_val) & 0xFFFFFFFF
70 | edi = (0x5BD1E995 * len(data)) & 0xFFFFFFFF
71 |
72 | eax = v20 >> 0x18
73 | eax ^= v20
74 |
75 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
76 | eax = (0x5BD1E995 * v15) & 0xFFFFFFFF
77 |
78 | ecx ^= eax
79 |
80 | eax = edi
81 | eax >>= 0x18
82 | eax ^= edi
83 |
84 | edx = (0x5BD1E995 * ecx) & 0xFFFFFFFF
85 | eax = (0x5BD1E995 * eax) & 0xFFFFFFFF
86 | edx ^= eax
87 | eax = edx
88 |
89 | eax >>= 0xD
90 | eax ^= edx
91 |
92 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
93 | eax = ecx
94 | eax >>= 0xF
95 | eax ^= ecx
96 |
97 | return eax
98 |
--------------------------------------------------------------------------------
/algorithms/conti_b801fcda.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Conti ransomware api hash with seed 0xB801FCDA"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 384343055
6 |
7 |
8 | def hash(data):
9 | API_buffer = []
10 |
11 | i = len(data) >> 3
12 |
13 | count = 0
14 | while i != 0:
15 | for index in range(0, 8):
16 | API_buffer.append(data[index + count])
17 | count += 8
18 | i -= 1
19 |
20 | if len(data) & 7 != 0:
21 | v8 = len(data) & 7
22 |
23 | while v8 != 0:
24 | API_buffer.append(data[count])
25 | count += 1
26 | v8 -= 1
27 |
28 | hash_val = 0
29 |
30 | for i in range(0, len(API_buffer)):
31 | API_buffer[i] = ord(chr(API_buffer[i]))
32 |
33 | v15 = 0xB801FCDA
34 | string_length_2 = len(data)
35 | API_buffer_count = 0
36 | if len(data) >= 4:
37 | count = string_length_2 >> 2
38 | string_length_2 = (string_length_2 - 4 *
39 | (string_length_2 >> 2)) & 0xFFFFFFFF
40 |
41 | while True:
42 | temp_buffer_val = API_buffer[API_buffer_count +
43 | 3] << 24 | API_buffer[API_buffer_count +
44 | 2] << 16 | API_buffer[API_buffer_count +
45 | 1] << 8 | API_buffer[API_buffer_count]
46 |
47 | temp = (0x5BD1E995 * temp_buffer_val) & 0xFFFFFFFF
48 | API_buffer_count += 4
49 | v15 = ((0x5BD1E995 * (temp ^
50 | (temp >> 0x18))) & 0xFFFFFFFF) ^ ((0x5BD1E995 * v15) & 0xFFFFFFFF)
51 | count -= 1
52 | if count == 0:
53 | break
54 |
55 | v18 = string_length_2 - 1
56 |
57 | v19 = v18 - 1
58 |
59 | if v18 == 0:
60 | hash_val ^= API_buffer[API_buffer_count]
61 | elif v19 == 0:
62 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
63 | hash_val ^= API_buffer[API_buffer_count]
64 | elif v19 == 1:
65 | hash_val ^= API_buffer[API_buffer_count + 2] << 16
66 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
67 | hash_val ^= API_buffer[API_buffer_count]
68 |
69 | v20 = (0x5BD1E995 * hash_val) & 0xFFFFFFFF
70 | edi = (0x5BD1E995 * len(data)) & 0xFFFFFFFF
71 |
72 | eax = v20 >> 0x18
73 | eax ^= v20
74 |
75 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
76 | eax = (0x5BD1E995 * v15) & 0xFFFFFFFF
77 |
78 | ecx ^= eax
79 |
80 | eax = edi
81 | eax >>= 0x18
82 | eax ^= edi
83 |
84 | edx = (0x5BD1E995 * ecx) & 0xFFFFFFFF
85 | eax = (0x5BD1E995 * eax) & 0xFFFFFFFF
86 | edx ^= eax
87 | eax = edx
88 |
89 | eax >>= 0xD
90 | eax ^= edx
91 |
92 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
93 | eax = ecx
94 | eax >>= 0xF
95 | eax ^= ecx
96 |
97 | return eax
98 |
--------------------------------------------------------------------------------
/algorithms/conti_e9ff0077.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Conti ransomware api hash with seed 0xE9FF0077"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3760887415
6 |
7 |
8 | def hash(data):
9 | API_buffer = []
10 |
11 | i = len(data) >> 3
12 |
13 | count = 0
14 | while i != 0:
15 | for index in range(0, 8):
16 | API_buffer.append(data[index + count])
17 | count += 8
18 | i -= 1
19 |
20 | if len(data) & 7 != 0:
21 | v8 = len(data) & 7
22 |
23 | while v8 != 0:
24 | API_buffer.append(data[count])
25 | count += 1
26 | v8 -= 1
27 |
28 | hash_val = 0
29 |
30 | for i in range(0, len(API_buffer)):
31 | API_buffer[i] = ord(chr(API_buffer[i]))
32 |
33 | v15 = 0xE9FF0077
34 | string_length_2 = len(data)
35 | API_buffer_count = 0
36 | if len(data) >= 4:
37 | count = string_length_2 >> 2
38 | string_length_2 = (string_length_2 - 4 *
39 | (string_length_2 >> 2)) & 0xFFFFFFFF
40 |
41 | while True:
42 | temp_buffer_val = API_buffer[API_buffer_count +
43 | 3] << 24 | API_buffer[API_buffer_count +
44 | 2] << 16 | API_buffer[API_buffer_count +
45 | 1] << 8 | API_buffer[API_buffer_count]
46 |
47 | temp = (0x5BD1E995 * temp_buffer_val) & 0xFFFFFFFF
48 | API_buffer_count += 4
49 | v15 = ((0x5BD1E995 * (temp ^
50 | (temp >> 0x18))) & 0xFFFFFFFF) ^ ((0x5BD1E995 * v15) & 0xFFFFFFFF)
51 | count -= 1
52 | if count == 0:
53 | break
54 |
55 | v18 = string_length_2 - 1
56 |
57 | v19 = v18 - 1
58 |
59 | if v18 == 0:
60 | hash_val ^= API_buffer[API_buffer_count]
61 | elif v19 == 0:
62 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
63 | hash_val ^= API_buffer[API_buffer_count]
64 | elif v19 == 1:
65 | hash_val ^= API_buffer[API_buffer_count + 2] << 16
66 | hash_val ^= API_buffer[API_buffer_count + 1] << 8
67 | hash_val ^= API_buffer[API_buffer_count]
68 |
69 | v20 = (0x5BD1E995 * hash_val) & 0xFFFFFFFF
70 | edi = (0x5BD1E995 * len(data)) & 0xFFFFFFFF
71 |
72 | eax = v20 >> 0x18
73 | eax ^= v20
74 |
75 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
76 | eax = (0x5BD1E995 * v15) & 0xFFFFFFFF
77 |
78 | ecx ^= eax
79 |
80 | eax = edi
81 | eax >>= 0x18
82 | eax ^= edi
83 |
84 | edx = (0x5BD1E995 * ecx) & 0xFFFFFFFF
85 | eax = (0x5BD1E995 * eax) & 0xFFFFFFFF
86 | edx ^= eax
87 | eax = edx
88 |
89 | eax >>= 0xD
90 | eax ^= edx
91 |
92 | ecx = (0x5BD1E995 * eax) & 0xFFFFFFFF
93 | eax = ecx
94 | eax >>= 0xF
95 | eax ^= ecx
96 |
97 | return eax
98 |
--------------------------------------------------------------------------------
/algorithms/conti_mm3.py:
--------------------------------------------------------------------------------
1 | '''
2 | pymmh3 was written by Fredrik Kihlander and enhanced by Swapnil Gusani, and is placed in the public
3 | domain. The authors hereby disclaim copyright to this source code.
4 |
5 | pure python implementation of the murmur3 hash algorithm
6 |
7 | https://code.google.com/p/smhasher/wiki/MurmurHash3
8 |
9 | This was written for the times when you do not want to compile c-code and install modules,
10 | and you only want a drop-in murmur3 implementation.
11 |
12 | As this is purely python it is FAR from performant and if performance is anything that is needed
13 | a proper c-module is suggested!
14 |
15 | This module is written to have the same format as mmh3 python package found here for simple conversions:
16 |
17 | https://pypi.python.org/pypi/mmh3/2.3.1
18 | '''
19 |
20 | DESCRIPTION = "Conti ransomware Murmur3 API hashing"
21 | TYPE = 'unsigned_int'
22 | TEST_1 = 60915229
23 |
24 | import sys as _sys
25 | if (_sys.version_info > (3, 0)):
26 | def xrange( a, b, c ):
27 | return range( a, b, c )
28 | def xencode(x):
29 | if isinstance(x, bytes) or isinstance(x, bytearray):
30 | return x
31 | else:
32 | return x.encode()
33 | else:
34 | def xencode(x):
35 | return x
36 | del _sys
37 |
38 |
39 | def hash( key ):
40 | seed = 0xe9ff0077
41 | ''' Implements 32bit murmur3 hash. '''
42 |
43 | key = bytearray( xencode(key.lower()) )
44 |
45 | def fmix( h ):
46 | h ^= h >> 16
47 | h = ( h * 0x85ebca6b ) & 0xFFFFFFFF
48 | h ^= h >> 13
49 | h = ( h * 0xc2b2ae35 ) & 0xFFFFFFFF
50 | h ^= h >> 16
51 | return h
52 |
53 | length = len( key )
54 | nblocks = int( length / 4 )
55 |
56 | h1 = seed
57 |
58 | c1 = 0xcc9e2d51
59 | c2 = 0x1b873593
60 |
61 | # body
62 | for block_start in xrange( 0, nblocks * 4, 4 ):
63 | # ??? big endian?
64 | k1 = key[ block_start + 3 ] << 24 | \
65 | key[ block_start + 2 ] << 16 | \
66 | key[ block_start + 1 ] << 8 | \
67 | key[ block_start + 0 ]
68 |
69 | k1 = ( c1 * k1 ) & 0xFFFFFFFF
70 | k1 = ( k1 << 15 | k1 >> 17 ) & 0xFFFFFFFF # inlined ROTL32
71 | k1 = ( c2 * k1 ) & 0xFFFFFFFF
72 |
73 | h1 ^= k1
74 | h1 = ( h1 << 13 | h1 >> 19 ) & 0xFFFFFFFF # inlined ROTL32
75 | h1 = ( h1 * 5 + 0xe6546b64 ) & 0xFFFFFFFF
76 |
77 | # tail
78 | tail_index = nblocks * 4
79 | k1 = 0
80 | tail_size = length & 3
81 |
82 | if tail_size >= 3:
83 | k1 ^= key[ tail_index + 2 ] << 16
84 | if tail_size >= 2:
85 | k1 ^= key[ tail_index + 1 ] << 8
86 | if tail_size >= 1:
87 | k1 ^= key[ tail_index + 0 ]
88 |
89 | if tail_size > 0:
90 | k1 = ( k1 * c1 ) & 0xFFFFFFFF
91 | k1 = ( k1 << 15 | k1 >> 17 ) & 0xFFFFFFFF # inlined ROTL32
92 | k1 = ( k1 * c2 ) & 0xFFFFFFFF
93 | h1 ^= k1
94 |
95 | #finalization
96 | unsigned_val = fmix( h1 ^ length )
97 |
98 | # convert to unsigned int
99 | return unsigned_val & 0xffffffff
100 |
101 |
102 |
--------------------------------------------------------------------------------
/algorithms/crc32.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import zlib
3 |
4 | DESCRIPTION = "Standard crc32 hash."
5 | TYPE = 'unsigned_int'
6 | TEST_1 = 532866770
7 |
8 |
9 | def hash(data):
10 | return 0xffffffff & zlib.crc32(data)
11 |
--------------------------------------------------------------------------------
/algorithms/crc32_bzip2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | # def gen_table():
22 | # crc32_table = [0] * 256
23 | # for i in range(256):
24 | # v = i << 24
25 | # for j in range(8):
26 | # if (v & 0x80000000) == 0:
27 | # v = (2 * v) & 0xffffffff
28 | # else:
29 | # v = ((2 * v) ^ 0x4C11DB7) & 0xffffffff
30 | # crc32_table[i] = v
31 | # return crc32_table
32 | #
33 | ########################################################################
34 |
35 | DESCRIPTION = "bzip2 version of crc32"
36 | TYPE = 'unsigned_int'
37 | TEST_1 = 2691965320
38 |
39 |
40 | def hash(data):
41 | crc32_table = [0, 79764919, 159529838, 222504665, 319059676, 398814059, 445009330, 507990021, 638119352, 583659535, 797628118, 726387553, 890018660, 835552979, 1015980042, 944750013, 1276238704, 1221641927, 1167319070, 1095957929, 1595256236, 1540665371, 1452775106, 1381403509, 1780037320, 1859660671, 1671105958, 1733955601, 2031960084, 2111593891, 1889500026, 1952343757, 2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653, 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357, 3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109, 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269, 881225847, 809987520, 1023691545, 969234094, 662832811, 591600412, 771767749, 717299826, 311336399, 374308984, 453813921, 533576470, 25881363, 88864420, 134795389, 214552010, 2023205639, 2086057648, 1897238633, 1976864222, 1804852699, 1867694188, 1645340341, 1724971778, 1587496639, 1516133128, 1461550545, 1406951526, 1302016099, 1230646740, 1142491917, 1087903418, 2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130, 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922, 3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050, 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242, 1762451694, 1842216281, 1619975040, 1682949687, 2047383090, 2127137669, 1938468188, 2001449195, 1325665622, 1271206113, 1183200824, 1111960463, 1543535498, 1489069629, 1434599652, 1363369299, 622672798, 568075817, 748617968, 677256519, 907627842, 853037301, 1067152940, 995781531, 51762726, 131386257, 177728840, 240578815, 269590778, 349224269, 429104020, 491947555, 4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915, 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211, 3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763, 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779, 1569362073, 1498123566, 1409854455, 1355396672, 1317987909, 1246755826, 1192025387, 1137557660, 2072149281, 2135122070, 1912620623, 1992383480, 1753615357, 1816598090, 1627664531, 1707420964, 295390185, 358241886, 404320391, 483945776, 43990325, 106832002, 186451547, 266083308, 932423249, 861060070, 1041341759, 986742920, 613929101, 542559546, 756411363, 701822548, 3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204, 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804, 2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596, 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188]
42 | result = 0xffffffff
43 | for c in data:
44 | result = (crc32_table[c ^ ((result >> 24) & 0xff)] ^ (result << 8)) & 0xffffffff
45 | return (result ^ 0xffffffff) & 0xffffffff
46 |
--------------------------------------------------------------------------------
/algorithms/crc32_mpeg_2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "MPEG-2 version of CRC-32."
4 | TYPE = "unsigned_int"
5 | TEST_1 = 1603001975
6 |
7 |
8 | def hash(data):
9 | crc = 0xFFFFFFFF
10 | for val in data:
11 | crc ^= val << 24
12 | for _ in range(8):
13 | crc = crc << 1 if (crc & 0x80000000) == 0 else (crc << 1) ^ 0x104C11DB7
14 | return crc
15 |
--------------------------------------------------------------------------------
/algorithms/crc64_ecma_182.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from ctypes import c_uint64
3 | from ctypes import c_ubyte
4 |
5 | DESCRIPTION = "crc64 has crc64_ecma_182"
6 | TYPE = 'unsigned_long'
7 | TEST_1 = 6674762932123621561
8 |
9 |
10 | def bytes_to_int(data):
11 |
12 | """
13 | Convert bytes to integer
14 | :param data: bytes of data
15 | :return: result int
16 | """
17 |
18 | result = 0
19 | for b in data:
20 | result = result * 256 + int(b)
21 | return result
22 |
23 |
24 | def ref_bits(x):
25 |
26 | """
27 | :param x: byte to reverse
28 | :return: reversed byte
29 | """
30 |
31 | b = bin(x)[2::].zfill(8)
32 | b = b[8::-1]
33 | return int(b, 2)
34 |
35 |
36 | def ref(data):
37 |
38 | """
39 | :param data: input bytes to reverse
40 | :return: reversed data bytes
41 | """
42 |
43 | tmp = []
44 | for byte in data:
45 | byte_r = ref_bits(byte)
46 | tmp.append(byte_r)
47 |
48 | data = bytes(tmp)
49 | return data
50 |
51 |
52 | TABLE_42F0E1EBA9EA3693 = [
53 | 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C,
54 | 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
55 | 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C,
56 | 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
57 | 0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D,
58 | 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
59 | 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3,
60 | 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
61 | 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D,
62 | 0x66952C92ECB40FC8, 0x2465CD79455E395B, 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
63 | 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xDA050215EA6C212F, 0x98F5E3FE438617BC,
64 | 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
65 | 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD,
66 | 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
67 | 0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED,
68 | 0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
69 | 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD,
70 | 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
71 | 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D,
72 | 0xF5A348C2089AC238, 0xB753A929A170F4AB, 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
73 | 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC,
74 | 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
75 | 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0,
76 | 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
77 | 0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E,
78 | 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
79 | 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, 0x3A80143F5CF17F13, 0x7870F5D4F51B4980,
80 | 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
81 | 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1,
82 | 0x64347D271DE22754, 0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
83 | 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1,
84 | 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
85 | 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE,
86 | 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
87 | 0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E,
88 | 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
89 | 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, 0x919735E51578E56C, 0xD367D40EBC92D3FF,
90 | 0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
91 | 0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111,
92 | 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
93 | 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, 0xCF8B0890283E370C, 0x8D7BE97B81D4019F,
94 | 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
95 | 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507]
96 |
97 |
98 | def crc64_fast(data: bytes, table: list, init_val=0, final_xor=0, in_ref=False, out_ref=False):
99 | """
100 | Function to calculating CRC16 with values from pre-calculated table
101 | :param data: Input data as bytes
102 | :param table: Pre-calculated table for polynomial used
103 | :param init_val: CRC initial value
104 | :param final_xor: Value that will be XORed to result crc
105 | :param in_ref: Flag to reflect input
106 | :param out_ref: Flag to reflect output
107 | :return: CRC as unsigned int32 value
108 | """
109 | if not isinstance(data, bytes):
110 | raise TypeError("Expected bytes, got %s" % (type(data),))
111 | if not isinstance(table, list):
112 | raise TypeError("Expected list, got %s" % (type(table),))
113 | if not isinstance(init_val, int):
114 | raise TypeError("Expected int, got %s" % (type(init_val),))
115 | if not isinstance(final_xor, int):
116 | raise TypeError("Expected int, got %s" % (type(final_xor),))
117 | if not isinstance(in_ref, bool):
118 | raise TypeError("Expected bool, got %s" % (type(in_ref),))
119 | if not isinstance(out_ref, bool):
120 | raise TypeError("Expected bool, got %s" % (type(out_ref),))
121 | crc = c_uint64(0) if init_val == 0 else c_uint64(init_val)
122 | if in_ref:
123 | data = ref(data)
124 | for b in data:
125 | p = c_ubyte((crc.value ^ (b << 56)) >> 56)
126 | crc.value = (crc.value << 8) ^ table[p.value]
127 | if (out_ref):
128 | crc_bytes = bytes(crc)
129 | crc_bytes = ref(crc_bytes)
130 | return c_uint64(bytes_to_int(crc_bytes)).value ^ final_xor
131 | else:
132 | return crc.value ^ final_xor
133 |
134 |
135 | def crc64_ecma_182(data: bytes):
136 | return crc64_fast(data=data, table=TABLE_42F0E1EBA9EA3693)
137 |
138 |
139 | def hash(data):
140 | return crc64_ecma_182(data)
141 |
--------------------------------------------------------------------------------
/algorithms/cryptbot_ror13_add_10.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python
2 |
3 | DESCRIPTION = "Add 10 to ror13 shift on data"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3425182094
6 |
7 |
8 | rol = lambda val, r_bits, max_bits: \
9 | (val << r_bits%max_bits) & (2**max_bits-1) | \
10 | ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
11 |
12 | ror = lambda val, r_bits, max_bits: \
13 | ((val & (2**max_bits-1)) >> r_bits%max_bits) | \
14 | (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
15 |
16 | def hash(data):
17 |
18 |
19 | GENERATED_HASH = 0
20 | for character in data:
21 |
22 | segment_1 = ror(GENERATED_HASH, 13, 32) & 0xffffffff
23 | segment_2 = character
24 | if segment_2 >= 97:
25 | segment_2 -= 32
26 | GENERATED_HASH = segment_1 + segment_2
27 | return GENERATED_HASH + 10
28 |
29 |
--------------------------------------------------------------------------------
/algorithms/d0nut.py:
--------------------------------------------------------------------------------
1 | DESCRIPTION = 'API Hashing as used by d0nut'
2 |
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 2349756695
5 |
6 | rol = lambda val, r_bits, max_bits: \
7 | (val << r_bits % max_bits) & (2 ** max_bits-1) | \
8 | ((val & (2 ** max_bits-1)) >> (max_bits-(r_bits % max_bits)))
9 |
10 |
11 | def hash(data):
12 | hashcalc = 75569
13 |
14 | for pointer in range(0, len(data), 4):
15 | if len(data) - pointer < 4:
16 | break
17 | shift_calc = data[pointer+0] | (data[pointer+1] << 8) | (data[pointer+2] << 16) | data[pointer+3] << 24
18 | hashcalc = (5 * rol(hashcalc ^ (0x27D4EB4F * ((0xE5438000 * shift_calc) | ((0x85EBCA87 * shift_calc & 0xFFFFFFFF) >> 17))), 13, 32))-1640531463 & 0xFFFFFFFF
19 | else:
20 | pointer = len(data)
21 | remainder = len(data) - pointer
22 |
23 | if remainder:
24 | remainder_bytes = int.from_bytes(data[-remainder:], 'little')
25 | else:
26 | remainder_bytes = 0
27 |
28 | rem_or = (0x27D4EB4F * ((0xE5438000 * remainder_bytes & 0xFFFFFFFF) | ((0x85EBCA87 * remainder_bytes & 0xFFFFFFFF) >> 17))) & 0xFFFFFFFF ^ (hashcalc ^ len(data))
29 |
30 | rem_hash = (0x165667C5 * ((0xC2B2AE63 * (rem_or ^ (rem_or >> 16)) & 0xFFFFFFFF) ^ ((0xC2B2AE63 * (rem_or ^ (rem_or >> 16)) & 0xFFFFFFFF) >> 13)) & 0xFFFFFFFF)
31 | rem_hash = rem_hash ^ (rem_hash >> 16)
32 |
33 | return rem_hash
--------------------------------------------------------------------------------
/algorithms/danabot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Danabot API hashing algorithm.
5 |
6 | Reference: https://malwareandstuff.com/deobfuscating-danabots-api-hashing/
7 | """
8 | TYPE = 'unsigned_int'
9 | TEST_1 = 41476489
10 |
11 |
12 | def hash(data):
13 | hash_val = 0
14 |
15 | i = 0
16 | data_len = len(data)
17 | while i < data_len:
18 | begin_chr = data[i]
19 | begin_chr_upper = ord(chr(begin_chr).upper())
20 |
21 | if i == data_len - 1:
22 | end_chr = data[0]
23 | else:
24 | end_chr = data[data_len - i - 2]
25 | end_chr_upper = ord(chr(end_chr).upper())
26 |
27 | v16 = (begin_chr ^ data_len) & 0xffffffff
28 | v18 = (end_chr ^ data_len) & 0xffffffff
29 | v17 = (begin_chr_upper ^ data_len) & 0xffffffff
30 | v15 = (end_chr_upper ^ data_len) & 0xffffffff
31 |
32 | hash_val = (v15 ^ (hash_val + v17 * v18 * v16)) & 0xffffffff
33 |
34 | i += 1
35 |
36 | return hash_val
37 |
--------------------------------------------------------------------------------
/algorithms/deedrat.py:
--------------------------------------------------------------------------------
1 | # Created by Still Hsu
2 |
3 | DESCRIPTION = "Hashing algorithm used by newer variants of DeedRAT."
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 1761596967
6 |
7 |
8 | def hash(data):
9 | i = 0
10 | ecx = 0
11 | eax = 0
12 | edi = 0
13 | esi = 0
14 | for c in data:
15 | i = i+1
16 | if c < 0x61:
17 | edi = c+0x20
18 | else:
19 | edi = c
20 | ecx = esi
21 | eax = esi
22 | if i & 1 != 0:
23 | ecx = (ecx << 0x5) & 0xffffffff
24 | eax = (eax >> 0x1) & 0xffffffff
25 | ecx = ecx ^ eax
26 | ecx = ecx ^ edi
27 | else:
28 | ecx = (ecx << 0x9) & 0xffffffff
29 | eax = (eax >> 0x3) & 0xffffffff
30 | ecx = ecx ^ eax
31 | ecx = ecx ^ edi
32 | ecx = ~(ecx) & 0xffffffff
33 | esi = esi ^ ecx
34 | return esi
35 |
--------------------------------------------------------------------------------
/algorithms/deedrat_export_name.py:
--------------------------------------------------------------------------------
1 | # Created by Still Hsu
2 |
3 | DESCRIPTION = "Hashing algorithm for library export name used by DeedRAT."
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 1493252751
6 |
7 |
8 | def hash(data):
9 | i = 0
10 | ecx = 0
11 | eax = 0
12 | edi = 0
13 | esi = 0
14 | for c in data:
15 | i = i+1
16 | edi = c
17 | ecx = esi
18 | eax = esi
19 | if i & 1 != 0:
20 | ecx = (ecx << 0x5) & 0xffffffff
21 | eax = (eax >> 0x1) & 0xffffffff
22 | ecx = ecx ^ eax
23 | ecx = ecx ^ edi
24 | else:
25 | ecx = (ecx << 0x9) & 0xffffffff
26 | eax = (eax >> 0x3) & 0xffffffff
27 | ecx = ecx ^ eax
28 | ecx = ecx ^ edi
29 | ecx = ~(ecx) & 0xffffffff
30 | esi = esi ^ ecx
31 | return esi & 0x7fffffff
32 |
--------------------------------------------------------------------------------
/algorithms/djb2_lowercase.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "A variant of the DJB2 hash algorithm that converts uppercase letters to lowercase"
4 |
5 | TYPE = 'unsigned_int'
6 |
7 | TEST_1 = 0xd87d4bef
8 |
9 |
10 | def hash(data):
11 | hash_value = 0x624
12 | for char in data:
13 | if 0x41 <= char <= 0x5A:
14 | char += 0x20
15 | hash_value = (hash_value * 33 + char) & 0xFFFFFFFF
16 | return hash_value
17 |
--------------------------------------------------------------------------------
/algorithms/djb2_nokoyawa.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Variant of djb2 hash in use by Nokoyawa ransomware"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 3792689168
8 |
9 |
10 | def hash(data):
11 | generated_hash = 5381
12 | for b in data:
13 | generated_hash = (generated_hash * 33 + (b if b < 0x61 else (b - 0x20))) & 0xFFFFFFFF
14 | return generated_hash
15 |
--------------------------------------------------------------------------------
/algorithms/djb2_uppercase.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "A variant of the DJB2 hash algorithm that converts lowercase letters to uppercase"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 0x07AB31C2
6 |
7 | def hash(data):
8 | hash_value = 4919
9 | for char in data:
10 | if isinstance(char, int):
11 | char = chr(char)
12 | if ord('a') <= ord(char) <= ord('z'):
13 | char = chr(ord(char) - 32)
14 | hash_value = (hash_value * 33) + ord(char)
15 | return hash_value & 0xFFFFFFFF
16 |
--------------------------------------------------------------------------------
/algorithms/djb2_vohuk_ransomware_dec_2022.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Vohuk Ransomware's variant of DJB2 as of December 2022"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 1274984080
6 |
7 |
8 | def hash(data: bytearray) -> int:
9 | hash = 0x1505
10 | for b in data:
11 | if ((b - 0x41) & 0xFFFFFFFF) < 0x20:
12 | b += 0x20
13 | hash += b + ((0x20 * hash) & 0xFFFFFFFF)
14 | hash &= 0xFFFFFFFF
15 | return hash
16 |
--------------------------------------------------------------------------------
/algorithms/dualacc_modfff1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "DUALACC and MOD 0xfff1"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2329613580
26 |
27 |
28 | def hash(data):
29 | v4, v8 = 0, 1
30 | for ltr in data:
31 | v8 = (ltr + v8) % 0x0FFF1
32 | v4 = (v4 + v8) % 0x0FFF1
33 | return (v4 << 0x10) | v8
34 |
--------------------------------------------------------------------------------
/algorithms/emotet.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "Emotet November 2021"
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 3172443423
5 |
6 |
7 | def hash(data):
8 | hash_value = 0
9 | for i in range(len(data)):
10 | hash_value = (((hash_value << 16) & 0xffffffff)
11 | + ((hash_value << 6) & 0xffffffff)
12 | + data[i] - hash_value) & 0xffffffff
13 | return hash_value
14 |
--------------------------------------------------------------------------------
/algorithms/emotet_mul_65599_xor_19ad760.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 |
5 | Author = rfLENtlr
6 |
7 | This algorithm was used by Emotet.
8 |
9 | Sample SHA256: 5d267403191a8786db2062584f298478ba59aa7b4d23adcf850a2c14a55c6d97
10 |
11 | """
12 | TYPE = 'unsigned_int'
13 | TEST_1 = 3163386495
14 |
15 | def hash(data):
16 | hash_value = 0
17 | for c in data:
18 | hash_value = (c + hash_value * 0x1003f) & 0xFFFFFFFF
19 | return hash_value ^ 0x19ad760
--------------------------------------------------------------------------------
/algorithms/fnv1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "FNV1 hash"
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 116207608
5 |
6 |
7 | def hash(data):
8 | val = 0x811c9dc5
9 | for c in data:
10 | val = ((0x1000193 * val) ^ c) & 0xffffffff
11 | return val
12 |
--------------------------------------------------------------------------------
/algorithms/fnv1_64.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "FNV1 hash (64-bit)"
3 | TYPE = 'unsigned_long'
4 | TEST_1 = 10612290624328353880
5 |
6 |
7 | def hash(data):
8 | val = 0xcbf29ce484222325
9 | for c in data:
10 | val = ((0x100000001b3 * val) ^ c) & 0xffffffffffffffff
11 | return val
12 |
--------------------------------------------------------------------------------
/algorithms/fnv1_xor67f.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "FNV1 and XOR 67 observed in Neutrino Bot launcher"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2603337777
26 |
27 |
28 | def hash(data):
29 | val = 0x811c9dc5
30 | for c in data:
31 | val = (0x1000193 * (c ^ val)) & 0xffffffff
32 | return val ^ 0x67f
33 |
--------------------------------------------------------------------------------
/algorithms/fnv1a.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "FNV1a hash"
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 2603339342
5 |
6 |
7 | def hash(data):
8 | val = 0x811c9dc5
9 | for c in data:
10 | val = (0x1000193 * (c ^ val)) & 0xffffffff
11 | return val
12 |
--------------------------------------------------------------------------------
/algorithms/fnv1a_64.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "FNV1a hash (64-bit)"
3 | TYPE = 'unsigned_long'
4 | TEST_1 = 14074705352429455374
5 |
6 |
7 | def hash(data):
8 | val = 0xcbf29ce484222325
9 | for c in data:
10 | val = (0x100000001b3 * (c ^ val)) & 0xffffffffffffffff
11 | return val
12 |
--------------------------------------------------------------------------------
/algorithms/guloader_3C389ABC.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Guloader hash with seed 0x1505 and XOR 0x3C389ABC"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 2819429408
6 |
7 |
8 | def hash(data):
9 | out_hash = 0x1505
10 | for c in data:
11 | out_hash = ((c + 33 * out_hash) ^ 0x3C389ABC) & 0xffffffff
12 | return out_hash
13 |
--------------------------------------------------------------------------------
/algorithms/lockbit3_C8B32494_s0.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Modified ROR13 add algo used in the Lockbit 3.0 with a seed of 0x0
5 | and a hard coded hash start of 0xC8B32494
6 |
7 | Reference: https://c3rb3ru5d3d53c.github.io/malware-blog/lockbit-v3-api-hashing/
8 | """
9 | TYPE = 'unsigned_int'
10 | TEST_1 = 4294967294
11 | TEST_API_DATA_1 = b'kernel32.dllFindFirstFileExW'
12 | TEST_API_1 = 0xaae0cefb ^ 0x29009fe6
13 |
14 |
15 | def ror(n, rotations=1, width=32):
16 | return (2**width-1) & (n >> rotations | n << (width-rotations))
17 |
18 |
19 | def hash_algo(string, seed):
20 | string = string + b'\x00'
21 | result = 0xC8B32494 ^ seed
22 | for c in string:
23 | result = ror(result, rotations=0x0d, width=32)
24 | result = (result + c) & 0xffffffff
25 | if c == 0x00:
26 | break
27 | return result
28 |
29 |
30 | def hash(data):
31 | # This selects for only the wordlist in hashdb with
32 | # the format _
33 | if len(data.split(b'.dll')) != 2:
34 | return 0xfffffffe
35 | dll_name, api_name = data.split(b'.dll')
36 | dll_name = dll_name + b'.dll'
37 | print(f"dll: {dll_name}, api: {api_name}")
38 | seed = 0
39 | dll_hash = hash_algo(dll_name, seed)
40 | tmp_hash = hash_algo(api_name, dll_hash)
41 | return ~tmp_hash & 0xffffffff
42 |
--------------------------------------------------------------------------------
/algorithms/lockbit3_C8B32494_string.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Modified ROR13 add algo used in the Lockbit 3.0 with a seed of 0x0
5 | and a hard coded hash start of 0xC8B32494 this is for strings only
6 |
7 | Reference: https://c3rb3ru5d3d53c.github.io/malware-blog/lockbit-v3-api-hashing/
8 | """
9 | TYPE = 'unsigned_int'
10 | TEST_1 = 1345844799
11 |
12 |
13 | def ror(n, rotations=1, width=32):
14 | return (2**width-1) & (n >> rotations | n << (width-rotations))
15 |
16 |
17 | def hash_algo(string, seed):
18 | result = 0xC8B32494 ^ seed
19 | string += b'\x00'
20 | for c in string:
21 | result = ror(result, rotations=0x0d, width=32)
22 | result = (result + c) & 0xffffffff
23 | if c == 0x00:
24 | break
25 | return result
26 |
27 |
28 | def hash(data):
29 | seed = 0
30 | string_hash = hash_algo(data, seed)
31 | return string_hash
32 |
--------------------------------------------------------------------------------
/algorithms/lockbit4_0225.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Author = 0x0d4y
5 | Description: This is the Hash algorithm that was implemented in the new version of Lockbit, Lockbit Green or Lockbit4.0, with the aim of resolving DLLs and APIs dynamically.
6 | Sample MD5: 15796971D60F9D71AD162060F0F76A02
7 | The value of the Hash contained in TEST_1, was the result of the string: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
8 | Reference: https://0x0d4y.blog/lockbit4-0-evasion-tales/
9 | """
10 | TYPE = 'unsigned_int'
11 | TEST_1 = 3370265577
12 |
13 | def hash(data):
14 | if isinstance(data, bytes):
15 | data = data.decode('utf-8')
16 |
17 | MASK_32BIT = 0xffffffff
18 | hash_value = 0x14bf
19 | char_index = 0
20 |
21 | for char in data:
22 | char_code = ord(char)
23 |
24 | if 0x41 <= char_code <= 0x5A:
25 | normalized_char = (char_code + 0x20) & MASK_32BIT
26 | else:
27 | normalized_char = char_code
28 |
29 | if char_index == 0:
30 | index_modifier = 0
31 | else:
32 | index_modifier = (char_index ^ 0x14bf) & MASK_32BIT
33 |
34 | hash_value = (index_modifier * (((char_index + 0x14bf) * normalized_char + (hash_value ^ normalized_char)) & MASK_32BIT) + normalized_char) & MASK_32BIT
35 |
36 | char_index += 1
37 |
38 | return hash_value
--------------------------------------------------------------------------------
/algorithms/lokibot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Author= IlFranz
5 |
6 | This algorithm was used by Loki/LokiBot for API hashing
7 |
8 | Sample SHA256: 75af30d10a4a60bb1b260a0f4f9e3410448bd81328737678937145aa88eee108
9 | """
10 | TYPE = 'unsigned_int'
11 |
12 | TEST_1 = 4064566081
13 |
14 |
15 | def hash(data):
16 | hash_value = 0xFFFFFFFF
17 | for char in data:
18 | hash_value ^= char
19 | for _ in range(8):
20 | if hash_value & 1:
21 | hash_value ^= 0x4358AD54
22 | hash_value >>= 1
23 | return ~hash_value & 0xFFFFFFFF
--------------------------------------------------------------------------------
/algorithms/lumma_fnv1a.py:
--------------------------------------------------------------------------------
1 | DESCRIPTION = "FNV1a hash with LummaStealer offset, seen in 0cf55c7e1a19a0631b0248fb0e699bbec1d321240208f2862e37f6c9e75894e7"
2 | TYPE = 'unsigned_int'
3 | TEST_1 = 2983287169
4 |
5 | def hash(data):
6 | val = 0x268c190a
7 | for c in data:
8 | val = ((val ^ c) * 0x1000193) & 0xffffffff
9 |
10 | return val
11 |
--------------------------------------------------------------------------------
/algorithms/mamon_hash.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | DESCRIPTION = "Custom hash used in mamon ransomware"
3 | TYPE = 'unsigned_int'
4 | TEST_1 = 3726794573
5 |
6 | def hash(data):
7 | hash_value = 0x42
8 |
9 | for b in data:
10 | hash_value = ((hash_value * 33) + b) & 0xFFFFFFFF # Keep it 32-bit
11 |
12 | return hash_value
13 |
--------------------------------------------------------------------------------
/algorithms/metasploit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | Metasploit ROR13 hash used in a lot of shellcode.
5 | Reference https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/hash.py
6 | """
7 | TYPE = 'unsigned_int'
8 | TEST_1 = 4294967294
9 | TEST_API_DATA_1 = 'K\x00E\x00R\x00N\x00E\x00L\x003\x002\x00.\x00D\x00L\x00L\x00\x00\x00LoadLibraryA\x00'
10 | TEST_API_1 = 119961420
11 |
12 |
13 | def ror(dword, bits):
14 | return (dword >> bits | dword << (32 - bits)) & 0xFFFFFFFF
15 |
16 |
17 | def hash(data):
18 | if b'\x00\x00\x00' not in data:
19 | return 0xfffffffe
20 | module, api = data.split(b'\x00\x00\x00')
21 | module += b'\x00\x00\x00'
22 | module_hash = 0
23 | api_hash = 0
24 | for c in module:
25 | module_hash = ror(module_hash, 13)
26 | module_hash += c
27 | for c in api:
28 | api_hash = ror(api_hash, 13)
29 | api_hash += c
30 | h = module_hash + api_hash & 0xFFFFFFFF
31 | return h
32 |
--------------------------------------------------------------------------------
/algorithms/mul21_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "MULTIPLY 21 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1555243728
26 |
27 |
28 | def hash(data):
29 | val = 0x1505
30 | for i in data:
31 | val = (val * 0x21) & 0xFFFFFFFF
32 | val = (val + (i & 0xFFFFFFDF)) & 0xFFFFFFFF
33 | return val
34 |
--------------------------------------------------------------------------------
/algorithms/mul21_add_seed_8952.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "MULTIPLY 0x21 and ADD (seed 8952), used in PikaBot in February 2024"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 0xDD4DE543
8 |
9 |
10 | def hash(data):
11 | h = 8952
12 | for c in data:
13 | if c > 96:
14 | c -= 0x20
15 | h = (c + 0x21*h) & 0xFFFFFFFF
16 | return h
17 |
--------------------------------------------------------------------------------
/algorithms/mul7_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2022 quangnh89
4 | #
5 | # Win32/Tinba API hashing algorithm.
6 | #
7 | # https://www.virustotal.com/gui/file/ce9483f6284903d8d76d60f1a96b3ade33c77ded0cac1d1c2dc8979879d6f91e
8 | #
9 | ########################################################################
10 |
11 | DESCRIPTION = """
12 | MULTIPLY 7 and ADD.
13 | Used in Darkside Win32/Tinba API hash."""
14 | TYPE = 'unsigned_int'
15 | TEST_1 = 2894658687
16 |
17 |
18 | def hash(data):
19 | val = 0x0
20 | for i in data:
21 | val = (val * 0x7) & 0xFFFFFFFF
22 | val = (val + (i & 0xFF)) & 0xFFFFFFFF
23 | return val
24 |
--------------------------------------------------------------------------------
/algorithms/mul83_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "MULTIPLY 0x83 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 150583839
26 |
27 |
28 | def hash(data):
29 | val = 0
30 | for i in data:
31 | val = val * 131
32 | val += i
33 | val = val & 0xFFFFFFFF
34 | return val
35 |
--------------------------------------------------------------------------------
/algorithms/mult21_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "MULTIPLY 21 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 749094795
26 |
27 |
28 | def hash(data):
29 | acc = 0
30 | for i in data:
31 | acc = 0xffffffff & (acc * 0x21)
32 | acc = 0xffffffff & (acc + i)
33 | return acc
34 |
--------------------------------------------------------------------------------
/algorithms/mult21_add_170f.py:
--------------------------------------------------------------------------------
1 | DESCRIPTION = "MULTIPLY 21 and ADD (0x170F base)"
2 | TYPE = 'unsigned_int'
3 | TEST_1 = 4233774810
4 |
5 |
6 | def hash(data):
7 | hash_value = 0x170F
8 | for byte in data:
9 | hash_value = (hash_value * 0x21 + byte) & 0xFFFFFFFF
10 | return hash_value
11 |
--------------------------------------------------------------------------------
/algorithms/mult3_add_init_9C.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "MULTIPLY 3 and ADD, starting key 0x9C"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3481051867
6 |
7 |
8 | def hash(data):
9 | key = 0x9C
10 | for byte in data:
11 | dword = byte & 0xffffffff
12 | key = (key * 3) & 0xffffffff
13 | key = (key + dword) & 0xffffffff
14 | return key
15 |
--------------------------------------------------------------------------------
/algorithms/murmur2_lummas_v3.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = """
4 | MurMurhash2 used in LummaStealer v3.0
5 | seed 0x20
6 | Reference: https://github.com/abrandoned/murmur2/blob/master/MurmurHash2.c"
7 | """
8 |
9 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
10 | TYPE = 'unsigned_int'
11 | # Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
12 | TEST_1 = 1874473983
13 |
14 |
15 | def hash(data):
16 | fun_len = len(data)
17 | seed = 0x20
18 | new_index = 0
19 | i = 0
20 | seeded_len = (fun_len ^ seed)
21 | if fun_len > 4:
22 | shifted_len = fun_len >> 2 & 0xFFFFFFFF
23 | fun_len = fun_len - (4 * (fun_len >> 2)) & 0xFFFFFFFF
24 | for i in range(0, len(data), 4):
25 | if shifted_len != 0:
26 | shifted_len = shifted_len - 1
27 | seeded_len = (seeded_len * 0x5BD1E995) & 0xFFFFFFFF
28 | ecx = ((((((data[i+3] << 8) | data[i+2]) << 8) | data[i+1]) << 8 | data[i]) * 0x5BD1E995) & 0xFFFFFFFF
29 | eax = ecx
30 | eax = eax >> 0x18 & 0xFFFFFFFF
31 | eax = (eax ^ ecx) & 0xFFFFFFFF
32 | ecx = (eax * 0x5BD1E995) & 0xFFFFFFFF
33 | seeded_len = (seeded_len ^ ecx) & 0xFFFFFFFF
34 | new_index = i
35 | if (fun_len - 1) == 0:
36 | eax = (data[new_index] ^ seeded_len) & 0xFFFFFFFF
37 | seeded_len = (eax * 0x5BD1E995) & 0xFFFFFFFF
38 | return eax
39 | elif (fun_len - 2) == 0:
40 | eax = (data[new_index+1] << 8) & 0xFFFFFFFF
41 | seeded_len = seeded_len ^ eax
42 | eax = data[new_index]
43 | eax = eax ^ seeded_len
44 | seeded_len = (eax * 0x5BD1E995) & 0xFFFFFFFF
45 |
46 | elif (fun_len - 3) != 0:
47 | pass
48 | else:
49 | eax = data[new_index+2]
50 | eax = eax << 0x10 & 0xFFFFFFFF
51 | seeded_len = (seeded_len ^ eax) & 0xFFFFFFFF
52 | eax = data[new_index+1]
53 | eax = (eax << 8) & 0xFFFFFFFF
54 | seeded_len = (seeded_len ^ eax) & 0xFFFFFFFF
55 | eax = data[new_index]
56 | eax = eax ^ seeded_len
57 | seeded_len = (eax * 0x5BD1E995) & 0xFFFFFFFF
58 | eax = seeded_len
59 | eax = eax >> 0xD & 0xFFFFFFFF
60 | eax = eax ^ seeded_len
61 | ecx = (eax * 0x5BD1E995) & 0xFFFFFFFF
62 | eax = ecx
63 | eax = (eax >> 0xF) & 0xFFFFFFFF
64 | eax = eax ^ ecx
65 | return eax
66 |
--------------------------------------------------------------------------------
/algorithms/mythic_unknown.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "API hash find in an unknown Mythic agent, need a XOR key"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = "unsigned_int"
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 3762100525
8 |
9 |
10 | def hash(data):
11 | crc = 0xffffffff
12 | for val in data:
13 | for _ in range(8):
14 | tmp = crc
15 | crc = crc >> 1 & 0xffffffff
16 | if (val ^ tmp) & 1 != 0:
17 | crc ^= 0xedb88320
18 | val = val >> 1 & 0xffffffff
19 | return crc
20 |
--------------------------------------------------------------------------------
/algorithms/or20_xor_rol19.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "OR 0x20 and XOR and ROL 19"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 0x186f3f38
6 |
7 |
8 | ROTATE_BITMASK = {
9 | 8: 0xff,
10 | 16: 0xffff,
11 | 32: 0xffffffff,
12 | 64: 0xffffffffffffffff,
13 | }
14 |
15 |
16 | def rol(inVal, numShifts, dataSize=32):
17 | '''rotate left instruction emulation'''
18 | if numShifts == 0:
19 | return inVal
20 | if (numShifts < 0) or (numShifts > dataSize):
21 | raise ValueError('Bad numShifts')
22 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
23 | raise ValueError('Bad dataSize')
24 | bitMask = ROTATE_BITMASK[dataSize]
25 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
26 |
27 |
28 | def hash(data):
29 | val = 0xffffffff
30 | ors = 0
31 | for i in data:
32 | ors = i | 32
33 | val = ors ^ rol(val, 19, 32)
34 | return val
35 |
--------------------------------------------------------------------------------
/algorithms/or21_xor_rol11.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "OR 0x21 and XOR and ROL 11"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1303693098
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | ors = 0
51 | for i in data:
52 | ors = i | 33
53 | val = val ^ ors
54 | val = rol(val, 0xb, 32)
55 | return val
56 |
--------------------------------------------------------------------------------
/algorithms/or23_xor_rol17.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "OR 0x23 and XOR and ROL 17"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2135044757
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | ors = 0
51 | for i in data:
52 | ors = i | 35
53 | val = val ^ ors
54 | val = rol(val, 0x11, 32)
55 | return val
56 |
--------------------------------------------------------------------------------
/algorithms/paradise_murmurhash3.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Paradise ransomware implementation of MurmurHash3 with custom seed (0xDEADC0DE) - adapted from https://github.com/wc-duck/pymmh3"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 1653390361
8 |
9 |
10 | def hash(data):
11 |
12 | import sys as _sys
13 | if (_sys.version_info > (3, 0)):
14 | def xrange(a, b, c):
15 | return range(a, b, c)
16 |
17 | def xencode(x):
18 | if isinstance(x, bytes) or isinstance(x, bytearray):
19 | return x
20 | else:
21 | return x.encode()
22 | else:
23 |
24 | def xencode(x):
25 | return x
26 | del _sys
27 |
28 | data = bytearray(xencode(data))
29 |
30 | def fmix(h):
31 | h ^= h >> 16
32 | h = (h * 0x85ebca6b) & 0xFFFFFFFF
33 | h ^= h >> 13
34 | h = (h * 0xc2b2ae35) & 0xFFFFFFFF
35 | h ^= h >> 16
36 | return h
37 |
38 | length = len(data)
39 | nblocks = int(length / 4)
40 |
41 | seed = 0xDEADC0DE
42 | h1 = seed
43 |
44 | c1 = 0xcc9e2d51
45 | c2 = 0x1b873593
46 |
47 | # body
48 | for block_start in xrange(0, nblocks * 4, 4):
49 | # ??? big endian?
50 | k1 = data[block_start + 3] << 24 | \
51 | data[block_start + 2] << 16 | \
52 | data[block_start + 1] << 8 | \
53 | data[block_start + 0]
54 |
55 | k1 = (c1 * k1) & 0xFFFFFFFF
56 | k1 = (k1 << 15 | k1 >> 17) & 0xFFFFFFFF # inlined ROTL32
57 | k1 = (c2 * k1) & 0xFFFFFFFF
58 |
59 | h1 ^= k1
60 | h1 = (h1 << 13 | h1 >> 19) & 0xFFFFFFFF # inlined ROTL32
61 | h1 = (h1 * 5 + 0xe6546b64) & 0xFFFFFFFF
62 |
63 | # tail
64 | tail_index = nblocks * 4
65 | k1 = 0
66 | tail_size = length & 3
67 |
68 | if tail_size >= 3:
69 | k1 ^= data[tail_index + 2] << 16
70 | if tail_size >= 2:
71 | k1 ^= data[tail_index + 1] << 8
72 | if tail_size >= 1:
73 | k1 ^= data[tail_index + 0]
74 |
75 | if tail_size > 0:
76 | k1 = (k1 * c1) & 0xFFFFFFFF
77 | k1 = (k1 << 15 | k1 >> 17) & 0xFFFFFFFF # inlined ROTL32
78 | k1 = (k1 * c2) & 0xFFFFFFFF
79 | h1 ^= k1
80 |
81 | unsigned_val = fmix(h1 ^ length)
82 | return unsigned_val
83 |
--------------------------------------------------------------------------------
/algorithms/permutations_82f63b78.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "SHIFT and XOR with 0x82F63B78"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1838188878
26 |
27 |
28 | def hash(data):
29 | val = 0
30 | for i in data:
31 | v1 = ((((i | 0x20) ^ val) >> 1) ^ (0x82F63B78 * (((i | 0x20) ^ val) & 1))) & 0xffffffff
32 | v2 = ((((v1 >> 1) ^ (0x82F63B78 * (v1 & 1))) >> 1) ^ (0x82F63B78 * (((v1 >> 1) ^ (0x78 * (v1 & 1))) & 1))) & 0xffffffff
33 | v3 = ((((v2 >> 1) ^ (0x82F63B78 * (v2 & 1))) >> 1) ^ (0x82F63B78 * (((v2 >> 1) ^ (0x78 * (v2 & 1))) & 1))) & 0xffffffff
34 | v4 = ((((v3 >> 1) ^ (0x82F63B78 * (v3 & 1))) >> 1) ^ (0x82F63B78 * (((v3 >> 1) ^ (0x78 * (v3 & 1))) & 1))) & 0xffffffff
35 | val = ((v4 >> 1) ^ (0x82F63B78 * (v4 & 1))) & 0xffffffff
36 | return val ^ 0xBC
37 |
--------------------------------------------------------------------------------
/algorithms/permutations_e8677835.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "Multiple permutations of 0xe8677835"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3113210072
26 |
27 |
28 | def hash(data):
29 | val = 0xFFFFFFFF
30 | for i in data:
31 | val ^= i
32 | for j in range(0, 8):
33 | if (val & 0x1) == 1:
34 | val ^= 0xe8677835
35 | val >>= 1
36 | return val ^ 0xFFFFFFFF
37 |
--------------------------------------------------------------------------------
/algorithms/revil_010F.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # REvil API hashing observed in the following samples:
3 | # 12d8bfa1aeb557c146b98f069f3456cc8392863a2f4ad938722cd7ca1a773b39
4 | # 5f56d5748940e4039053f85978074bde16d64bd5ba97f6f0026ba8172cb29e93
5 | # This highly complex Python code is generously placed in the public domain.
6 | # The authors Lars Wallenborn and Jesko Huettenhain yield all copyrights.
7 | # Please use this code responsibly.
8 |
9 | DESCRIPTION = "Lower 21 bits of an LFS with seed 0x2B and multiplier 0x10F"
10 | TYPE = 'unsigned_int'
11 | TEST_1 = 385258
12 |
13 |
14 | def hash(data):
15 | result = 0x2b
16 | for byte in data:
17 | result = result * 0x010F + byte
18 | return result & 0x1fffff
19 |
--------------------------------------------------------------------------------
/algorithms/rol3_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 3 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 831512572
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x3, 32)
52 | val = val ^ i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol3_xor_eax.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 3 and XOR EAX"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1420031752
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | ecx = 0
50 | eax = 0
51 | for i in data:
52 | eax = eax | i
53 | ecx = ecx ^ eax
54 | ecx = rol(ecx, 0x3, 32)
55 | ecx += 1
56 | eax = 0xffffffff & (eax << 8)
57 | return ecx
58 |
--------------------------------------------------------------------------------
/algorithms/rol5_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 5 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 4160318296
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x5, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol5_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 5 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2079179548
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x5, 32)
52 | ors = i | 32
53 | val = val ^ ors
54 | return val
55 |
--------------------------------------------------------------------------------
/algorithms/rol7_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 7 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2379854656
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x7, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol7_add_xor2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 7 and ADD and XOR 2"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2445849446
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x7, 32)
52 | val += (i ^ 2)
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol7_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 7 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2845590054
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x7, 32)
52 | val = val ^ (0xff & i)
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol8_xor_b0d4d06.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 8 and XOR 0xB0D4D06 used in smoke bot"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2567160022
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = val ^ (i & 0xDF)
52 | val = rol(val, 0x8, 32)
53 | val = val + (i & 0xDF)
54 | return (val ^ 0xB0D4D06) & 0xffffffff
55 |
--------------------------------------------------------------------------------
/algorithms/rol9_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 9 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1175244391
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x9, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/rol9_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 9 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 433466918
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = rol(val, 0x9, 32)
52 | val = val ^ i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/ror11_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 11 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1347818236
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0xb, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/ror13_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 13 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2879724916
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0xd, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/ror13_add_negative_seed.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "ROR 13 and ADD with negative seed"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 2879724788
6 |
7 |
8 | def ROR4(val, r_bits, max_bits):
9 | return ((val & (2**max_bits - 1)) >> r_bits % max_bits) | (val << (max_bits - (r_bits % max_bits)) & (2**max_bits - 1))
10 |
11 |
12 | def hash(data):
13 | val = 0xffffffff
14 | for i in data:
15 | val = ROR4(val, 0xd, 32)
16 | val += i
17 | return val
18 |
--------------------------------------------------------------------------------
/algorithms/ror13_add_sub1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 13 and ADD and SUB 1"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2879724915
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0xd, 32)
52 | val += i
53 | return (val - 1) & 0xffffffff
54 |
--------------------------------------------------------------------------------
/algorithms/ror13_add_sub20.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 13 and ADD and SUB 0x20"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3425182084
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0xd, 32)
52 | if i < 97:
53 | val = (val & 0xffffffff) + i
54 | else:
55 | val = ((val & 0xffffffff) + i - 32) & 0xffffffff
56 | return val
57 |
--------------------------------------------------------------------------------
/algorithms/ror7_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 7 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1892787106
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0x7, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/ror8_add_xor_ab832e83.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Hash based on ror8, add, xor with initial state 0x832E83AB"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 0x828E7DBD
8 |
9 |
10 | ROTATE_BITMASK = {
11 | 8: 0xff,
12 | 16: 0xffff,
13 | 32: 0xffffffff,
14 | 64: 0xffffffffffffffff,
15 | }
16 |
17 |
18 | def ror(inVal, numShifts, dataSize=32):
19 | '''rotate right instruction emulation'''
20 | if numShifts == 0:
21 | return inVal
22 | if (numShifts < 0) or (numShifts > dataSize):
23 | raise ValueError('Bad numShifts')
24 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
25 | raise ValueError('Bad dataSize')
26 | bitMask = ROTATE_BITMASK[dataSize]
27 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
28 |
29 |
30 | def hash(data):
31 | state = 0x832E83AB
32 | for i in range(len(data)):
33 | val = ror(state, 8)
34 | if i < len(data) - 1:
35 | val += data[i] | data[i + 1] << 8
36 | else:
37 | val += data[i]
38 | state ^= val
39 | return state
40 |
--------------------------------------------------------------------------------
/algorithms/ror9_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROR 9 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 3168699451
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def ror(inVal, numShifts, dataSize=32):
37 | '''rotate right instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal >> numShifts) | (inVal << (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = ror(val, 0x9, 32)
52 | val += i
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/sdbm_65599_x64.py:
--------------------------------------------------------------------------------
1 | DESCRIPTION = "The original SDBM hash function with the constant 65599. Used by Emotet malware."
2 | TYPE = 'unsigned_long'
3 | TEST_1 = 18326187587583583519
4 |
5 |
6 | def hash(data):
7 | hsh = 0
8 | for d in data:
9 | hsh = d + 0x1003f * hsh
10 | return hsh & 0xffffffffffffffff
11 |
--------------------------------------------------------------------------------
/algorithms/shl1_add.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "SHIFT LEFT 1 and ADD"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 4294944522
26 |
27 |
28 | def hash(data):
29 | val = 0
30 | for i in data:
31 | b = i
32 | b = 0xff & (b | 0x60)
33 | val = val + b
34 | val = val << 1
35 | val = 0xffffffff & val
36 | return val
37 |
--------------------------------------------------------------------------------
/algorithms/shl7_shr19_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "SHIFT LEFT 7 and SHIFT RIGHT 19 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1112293927
26 |
27 |
28 | def hash(data):
29 | val = 0
30 | for i in data:
31 | edx = 0xffffffff & (val << 7)
32 | ecx = 0xffffffff & (val >> 0x19)
33 | eax = edx | ecx
34 | t = 0xff & (i ^ 0xf4)
35 | val = eax ^ t
36 | return val
37 |
--------------------------------------------------------------------------------
/algorithms/shl7_sub.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "SHIFT LEFT 7 and SUB used in DoublePulsar backdoor"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2493113697
26 |
27 |
28 | def hash(data):
29 | eax = 0
30 | edi = 0
31 | for i in data:
32 | edi = 0xffffffff & (eax << 7)
33 | eax = 0xffffffff & (edi - eax)
34 | eax = eax + (0xff & i)
35 | edi = 0xffffffff & (eax << 7)
36 | eax = 0xffffffff & (edi - eax)
37 | return eax
38 |
--------------------------------------------------------------------------------
/algorithms/shr1_shl7_2326.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "Seed 0x2326 shift right 1 shift left 7"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 0x9bfc4734
6 |
7 |
8 | def hash(data):
9 | out = 0x2326
10 | for c in data:
11 | out = (out + c + ((out >> 1) | (out << 7))) & 0xffffffff
12 | return out
13 |
--------------------------------------------------------------------------------
/algorithms/shr2_shl5_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "SHIFT RIGHT 2 and SHIFT LEFT 5 and XOR"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 629383115
26 |
27 |
28 | def hash(data):
29 | result = 0x4e67c6a7
30 | if data.startswith(b"Nt") or data.startswith(b"Zw"):
31 | data = data[2:]
32 | for i in data:
33 | result ^= (i + (result >> 2) + (result << 5)) & 0xffffffff
34 | return result
35 |
--------------------------------------------------------------------------------
/algorithms/shr2_shl5_xor_init_c4d5a97a_stealbit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "SHIFT RIGHT 2 and SHIFT LEFT 5 and XOR with initialization constant 0xc4d5a97a used in Stealbit malware."
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 4099635895
8 |
9 |
10 | def hash(data):
11 |
12 | # Initialize the hash value to 0xc4d5a97a
13 | func_hash = 0xc4d5a97a
14 |
15 | # Iterate through input string bytes and update the
16 | # hash value
17 | for b in data:
18 | func_hash ^= ((func_hash >> 2) + ((func_hash << 5) + b)) & 0xFFFFFFFF
19 |
20 | return func_hash
21 |
--------------------------------------------------------------------------------
/algorithms/smokeloader_rol8_xor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "ROL 8 and XOR used in smoke bot"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2450427344
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = val ^ (i & 0xDF)
52 | val = rol(val, 0x8, 32)
53 | val = val + (i & 0xDF)
54 | return val & 0xffffffff
55 |
--------------------------------------------------------------------------------
/algorithms/tonepipeshell.py:
--------------------------------------------------------------------------------
1 | # Created by Still Hsu
2 |
3 | DESCRIPTION = "TOnePipeShell hash with seed 0xC85E31 (13131313)"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3454880715
6 |
7 | def hash(data):
8 | out_hash = 0
9 | for c in data:
10 | out_hash = (c + 0xC85E31 * out_hash) & 0xffffffff
11 | return out_hash
--------------------------------------------------------------------------------
/algorithms/tonepipeshell_alt.py:
--------------------------------------------------------------------------------
1 | # Created by Still Hsu
2 |
3 | DESCRIPTION = "TOnePipeShell hash with seed 0x4E44CB31 (1313131313)"
4 | TYPE = 'unsigned_int'
5 | TEST_1 = 3702427595
6 |
7 | def hash(data):
8 | out_hash = 0
9 | for c in data:
10 | out_hash = (c + 0x4E44CB31 * out_hash) & 0xffffffff
11 | return out_hash
12 |
--------------------------------------------------------------------------------
/algorithms/tonepipeshell_feb_2025.py:
--------------------------------------------------------------------------------
1 | DESCRIPTION = "TOnePipeShell hash with seed 0x14096B (1313131)"
2 | TYPE = 'unsigned_int'
3 | TEST_1 = 734769215
4 |
5 | def hash(data):
6 | out_hash = 0
7 | for c in data:
8 | out_hash = (c + 0x14096B * out_hash) & 0xffffffff
9 | return out_hash
--------------------------------------------------------------------------------
/algorithms/xor_rol9.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "XOR and ROL 9"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 2891729971
26 |
27 |
28 | ROTATE_BITMASK = {
29 | 8: 0xff,
30 | 16: 0xffff,
31 | 32: 0xffffffff,
32 | 64: 0xffffffffffffffff,
33 | }
34 |
35 |
36 | def rol(inVal, numShifts, dataSize=32):
37 | '''rotate left instruction emulation'''
38 | if numShifts == 0:
39 | return inVal
40 | if (numShifts < 0) or (numShifts > dataSize):
41 | raise ValueError('Bad numShifts')
42 | if (dataSize != 8) and (dataSize != 16) and (dataSize != 32) and (dataSize != 64):
43 | raise ValueError('Bad dataSize')
44 | bitMask = ROTATE_BITMASK[dataSize]
45 | return bitMask & ((inVal << numShifts) | (inVal >> (dataSize-numShifts)))
46 |
47 |
48 | def hash(data):
49 | val = 0
50 | for i in data:
51 | val = val ^ i
52 | val = rol(val, 0x9, 32)
53 | return val
54 |
--------------------------------------------------------------------------------
/algorithms/xor_shr8.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ########################################################################
3 | # Copyright 2012 Mandiant
4 | # Copyright 2014 FireEye
5 | #
6 | # Mandiant licenses this file to you under the Apache License, Version
7 | # 2.0 (the "License"); you may not use this file except in compliance with the
8 | # License. You may obtain a copy of the License at:
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 | # implied. See the License for the specific language governing
16 | # permissions and limitations under the License.
17 | #
18 | # Reference:
19 | # https://github.com/mandiant/flare-ida/blob/master/shellcode_hashes/make_sc_hash_db.py
20 | #
21 | ########################################################################
22 |
23 | DESCRIPTION = "XOR and SHIFT RIGHT 21"
24 | TYPE = 'unsigned_int'
25 | TEST_1 = 1054536684
26 |
27 |
28 | def hash(data):
29 | val = 0xFFFFFFFF
30 | for i in data:
31 | ci = i
32 | ci = ci ^ val
33 | ci = ci * val
34 | ci_hex = "%16x" % ci
35 | ci_hex = ci_hex[8:16]
36 | ci_hex = int(ci_hex, 16)
37 | shr8 = val >> 8
38 | val = ci_hex ^ shr8
39 | return val & 0xffffffff
40 |
--------------------------------------------------------------------------------
/algorithms/zloader_bot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | DESCRIPTION = "API hashing used by the zloader bot on 2021-10-21"
4 | # Type can be either 'unsigned_int' (32bit) or 'unsigned_long' (64bit)
5 | TYPE = 'unsigned_int'
6 | # Test must match the exact has of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
7 | TEST_1 = 3694482793
8 |
9 |
10 | def hash(data):
11 | generated_hash = 0
12 | for i in range(len(data)):
13 | current_char = data[i]
14 | v17 = (current_char + (generated_hash << 4)) & 0xFFFFFFFF
15 | if v17 & 0xF0000000 != 0:
16 | v10 = (v17 & 0xF0000000) >> 0x18
17 | v18 = v17 & 0xFFFFFFFF
18 | v11 = v18 ^ 0x0FFFFFFF
19 | generated_hash = (v18 & ~v10) | (v10 & v11)
20 | else:
21 | generated_hash = v17
22 |
23 | return generated_hash
24 |
--------------------------------------------------------------------------------
/hashdb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """Malware hash library.
5 | """
6 | import algorithms
7 |
8 | class AlgorithmError(Exception):
9 | pass
10 |
11 | def list_algorithms():
12 | return list(algorithms.modules.keys())
13 |
14 | def hash(algorithm_name, data):
15 | if algorithm_name not in list(algorithms.modules.keys()):
16 | raise AlgorithmError("Algorithm not found")
17 | if type(data) == str:
18 | data = data.encode('utf-8')
19 | return algorithms.modules[algorithm_name].hash(data)
20 |
--------------------------------------------------------------------------------
/tests/test_algorithms.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | def test_sanity():
5 | import hashdb
6 |
7 |
8 | def test_algorithm_attributes():
9 | from hashdb import algorithms
10 | for algorithm_name in list(algorithms.modules.keys()):
11 | assert(algorithms.modules[algorithm_name].DESCRIPTION != None)
12 | assert(algorithms.modules[algorithm_name].DESCRIPTION != '')
13 | assert(algorithms.modules[algorithm_name].TYPE != None)
14 | assert(algorithms.modules[algorithm_name].TYPE != '')
15 | assert(algorithms.modules[algorithm_name].TEST_1 != None)
16 | assert(algorithms.modules[algorithm_name].TEST_1 != '')
17 |
18 |
19 | def test_algorithm_hash():
20 | from hashdb import algorithms
21 | for algorithm_name in list(algorithms.modules.keys()):
22 | assert(algorithms.modules[algorithm_name].TEST_1 == algorithms.modules[algorithm_name].hash(b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'))
23 |
24 |
25 | def test_algorithm_duplicates():
26 | from hashdb import algorithms
27 | hash_list = []
28 | for algorithm_name in list(algorithms.modules.keys()):
29 | # Skip custom API hashes
30 | if 'TEST_API_1' not in dir(algorithms.modules[algorithm_name]):
31 | hash_list.append(algorithms.modules[algorithm_name].TEST_1)
32 | assert(len(hash_list) == len(set(hash_list)))
33 |
34 |
35 | def test_custom_api_algorithms():
36 | from hashdb import algorithms
37 | hash_list = []
38 | for algorithm_name in list(algorithms.modules.keys()):
39 | # Custom API hashes must have a custom hash and data field
40 | if 'TEST_API_1' in dir(algorithms.modules[algorithm_name]):
41 | assert(algorithms.modules[algorithm_name].TEST_API_1 != None)
42 | assert(algorithms.modules[algorithm_name].TEST_API_1 != '')
43 | assert(algorithms.modules[algorithm_name].TEST_API_DATA_1 != None)
44 | assert(algorithms.modules[algorithm_name].TEST_API_DATA_1 != '')
45 | assert((type(algorithms.modules[algorithm_name].TEST_API_DATA_1) == bytes) or
46 | (type(algorithms.modules[algorithm_name].TEST_API_DATA_1) == str))
47 | if type(algorithms.modules[algorithm_name].TEST_API_DATA_1) == str:
48 | data = algorithms.modules[algorithm_name].TEST_API_DATA_1.encode('utf-8')
49 | else:
50 | data = algorithms.modules[algorithm_name].TEST_API_DATA_1
51 | assert(algorithms.modules[algorithm_name].TEST_API_1 == algorithms.modules[algorithm_name].hash(data))
52 |
--------------------------------------------------------------------------------