Last active
July 15, 2022 14:34
-
-
Save c3rb3ru5d3d53c/4f2c984d81ef64e5f133e37726619c64 to your computer and use it in GitHub Desktop.
Lockbit MultiTool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys | |
import struct | |
try: | |
import pefile | |
except ImportError or ModuleNotFoundError: | |
print('missing pefile module', file=sys.stderr) | |
sys.exit(1) | |
import pickle | |
import argparse | |
from glob import glob | |
from pprint import pprint | |
from os.path import basename | |
from os import name as os_name | |
logo = """ .:^ | |
^ / : | |
'`. /;/ / / | |
\ \ /;/ / / | |
\\ \ /;/ / /// | |
\\ \ /;/ / /// | |
\ \/_/____________________/ / | |
`/ \ / | |
{ o o }' | |
\_________________________/""" | |
__version__ = '1.0.0' | |
__author__ = '@c3rb3ru5d3d53c' | |
def ror(n,rotations=1,width=32): | |
return (2**width-1)&(n>>rotations|n<<(width-rotations)) | |
def rol(n,rotations=1,width=32): | |
return (2**width-1)&(n<<rotations|n>>(width-rotations)) | |
def encrypt_ptr(data, key): | |
return ror((~data & 0xffffffff), rotations=key, width=32) | |
def decrypt_ptr(data, key): | |
return rol((~data & 0xffffffff), rotations=key, width=32) | |
def hash_mod(string, xmod): | |
# 004010ec | |
string = bytes(string, 'ascii') + b'\x00' | |
result = 0xc8b32494 ^ xmod | |
for c in string: | |
if c > 0x41 and c < 0x5a: c = c | 0x20 | |
result = ror(result, rotations=0x0d, width=32) | |
result += c | |
if c == 0x00: break | |
return result | |
def hash_fnc(string, mod_hash): | |
# 004010b8 | |
string = bytes(string, 'ascii') + b'\x00' | |
result = 0xc8b32494 ^ mod_hash | |
for c in string: | |
result = ror(result, rotations=0x0d, width=32) | |
result += c | |
if c == 0x00: break | |
return result | |
def hash_fin(fnc_hash): | |
# Finalize Hash | |
return (~fnc_hash & 0xffffffff) ^ 0x29009fe6 | |
def hash_all(module, function, xmod): | |
# Hash Module and Function | |
return hash_fin(hash_fnc(function, hash_mod(module, xmod))) | |
def get_exports(dll): | |
pe = pefile.PE(dll) | |
d = [pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_EXPORT"]] | |
pe.parse_data_directories(directories=d) | |
exports = [] | |
for export in pe.DIRECTORY_ENTRY_EXPORT.symbols: | |
if export.name is not None: exports.append(export.name.decode()) | |
return list(set(exports)) | |
def create_hash_table(file_path): | |
hashmap = {} | |
dlls = glob('C:\Windows\System32\*.dll') | |
for dll in dlls: | |
try: | |
print('[-] ' + dll) | |
exports = get_exports(dll) | |
for export in exports: | |
fnc_hash = hash_all(basename(dll), export, 0x00000000) | |
fnc_name = basename(dll)[:-4] + '.' + export | |
hashmap[fnc_hash] = fnc_name | |
hashmap[hash_fin(hash_mod(basename(dll), 0x00000000))] = basename(dll) | |
print('[+] ' + dll) | |
except KeyboardInterrupt: | |
pickle.dump(hashmap, open(file_path, 'wb'), protocol=pickle.HIGHEST_PROTOCOL) | |
sys.exit(0) | |
except: | |
pass | |
pickle.dump(hashmap, open(file_path, 'wb'), protocol=pickle.HIGHEST_PROTOCOL) | |
def decrypt_str(data): | |
# 00401010 | |
data = bytes.fromhex(data) | |
result = b'' | |
if (len(data) % 4)!= 0: return None | |
for i in range(0, len(data), 4): | |
dword = struct.unpack('<I', data[i:i+4])[0] | |
dword = (~(dword ^ 0x29009fe6) & 0xffffffff) | |
result += dword.to_bytes(4, byteorder='little') | |
return result.decode('utf-16') | |
def check_windows(): | |
if os_name != 'nt': return False | |
return True | |
def main(): | |
parser = argparse.ArgumentParser( | |
prog=f'lbmt v{__version__}', | |
description='A Lockbit Multi-Tool', | |
epilog=f'Author: {__author__}' | |
) | |
parser.add_argument( | |
'--version', | |
action='version', | |
version=f'v{__version__}' | |
) | |
parser.add_argument( | |
'--create-hashmap', | |
type=str, | |
default=None, | |
help='Create Hash Table (Windows Only)', | |
required=False | |
) | |
parser.add_argument( | |
'--decrypt-string', | |
type=str, | |
default=None, | |
help='Decrypt Hex String', | |
required=False | |
) | |
parser.add_argument( | |
'--encrypt-ptr', | |
type=str, | |
default=None, | |
help='Encrypt Pointer', | |
required=False | |
) | |
parser.add_argument( | |
'--decrypt-ptr', | |
type=str, | |
default=None, | |
help='Decrypt Pointer', | |
required=False | |
) | |
parser.add_argument( | |
'--ptr-key', | |
type=str, | |
default=None, | |
required=False | |
) | |
for arg in sys.argv: | |
if arg in ['-h', '--help']: | |
print(logo) | |
if len(sys.argv) == 1: | |
print(logo) | |
parser.print_help(sys.stdout) | |
sys.exit(0) | |
args = parser.parse_args() | |
if args.create_hashmap is not None: | |
if check_windows() is False: | |
print('Windows OS is required for this feature', file=sys.stderr) | |
sys.exit(1) | |
create_hash_table(args.create_hashmap) | |
elif args.decrypt_string is not None: | |
print(decrypt_str(args.decrypt_string)) | |
elif args.encrypt_ptr is not None and args.ptr_key is not None: | |
print(hex(encrypt_ptr(int(args.encrypt_ptr, base=16), int(args.ptr_key, base=16)))) | |
elif args.decrypt_ptr is not None and args.ptr_key is not None: | |
print(hex(decrypt_ptr(int(args.decrypt_ptr, base=16), int(args.ptr_key, base=16)))) | |
if __name__ in '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment