Created
April 18, 2024 19:47
-
-
Save X-Junior/31e8fccf159631ccbe1bdf8d1f8dd781 to your computer and use it in GitHub Desktop.
Wineloader Static String Decryptor
This file contains hidden or 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
from Crypto.Cipher import ARC4 | |
from capstone import * | |
from capstone.x86 import * | |
import pefile , sys , os | |
''' | |
Author: Mohamed Ashraf (@X__Junior) | |
make sure you are passing wineloader and not the loader of wineloader, if you suspect it's the loader then use https://raw.githubusercontent.com/tccontre/KnowledgeBase/main/malware_re_tools/wineloader_dll_side_load/wineloader_extractor.py , to extract the shellcode | |
tested samples: | |
27c0935a22862475bb3fd516f93bd466f8021f77727e83f53d67d76978b439ee | |
1f123f8e82310161e2e0ebf0420d3b5f3dd932f26b93eedb2b01f5abe77450d7 | |
f5cb3234eff0dbbd653d5cdce1d4b1026fa9574ebeaf16aaae3d4e921b6a7f9d | |
''' | |
def extract_strings(encrypted_strings_table): | |
flag = 0 | |
counter = 0 | |
extracted_strings = [] | |
string_length = encrypted_strings_table[0] | |
while counter < len(encrypted_strings_table): | |
if encrypted_strings_table[counter] == 0: | |
counter += 1 | |
elif encrypted_strings_table[counter] != 0 and flag == 0: | |
string_length = encrypted_strings_table[counter] | |
counter += 1 | |
flag = 1 | |
elif encrypted_strings_table[counter] != 0 and flag == 1: | |
encrypted_string = encrypted_strings_table[counter : counter + string_length] | |
extracted_strings.append(encrypted_string) | |
flag = 0 | |
counter += string_length | |
return extracted_strings | |
def decrypt_strings(encrypted_strings , rc4_key): | |
for encrypted_string in encrypted_strings: | |
try: | |
cipher = ARC4.new(rc4_key) | |
decrypted_string = cipher.decrypt(encrypted_string) | |
print(decrypted_string.decode()) | |
except: | |
continue | |
def extract_rc4_key (md ,text_addr ,pe ,file_data ,text): | |
inst = list(md.disasm(text.get_data(), text_addr)) | |
for i in range(len(inst)): | |
try : | |
if inst[i].mnemonic == "xor" and inst[i+1].mnemonic == "mov" and inst[i+2].mnemonic == "mov" and inst[i+3].mnemonic == "lea" and inst[i+4].mnemonic == "mov" and inst[i+5].mnemonic == "xor": | |
last_4_bytes_inst = inst[i+3].operands[1].value.mem.disp | |
instruction_size = inst[i+3].size | |
instruction_addr = inst[i+3].address | |
rc4_key_rva = instruction_addr + instruction_size + last_4_bytes_inst | |
break | |
except: | |
continue | |
for s in pe.sections: | |
if b'.text' in s.Name: | |
rc4_key_offset = rc4_key_rva - s.VirtualAddress + s.PointerToRawData - pe.OPTIONAL_HEADER.ImageBase | |
rc4_key = file_data[rc4_key_offset : rc4_key_offset + 0x100] | |
return rc4_key , rc4_key_offset | |
def main(): | |
# Check if the correct number of arguments are provided | |
if len(sys.argv) != 2: | |
# python3 WineLoader_String_Decryptor.py WineLoader.dll(WineLoader_Shellcode) | |
print("Usage: python WineLoader_String_Decryptor.py [filename]") | |
exit() | |
# Check if the file exists | |
if not os.path.isfile(sys.argv[1]): | |
print(f"The file {sys.argv[1]} does not exist.") | |
exit() | |
else: | |
file_data = open(sys.argv[1], "rb").read() | |
try: | |
pe = pefile.PE(sys.argv[1]) | |
md = Cs(CS_ARCH_X86, CS_MODE_64) | |
md.skipdata = True | |
md.detail = True | |
text = pe.sections[0] | |
text_addr = pe.OPTIONAL_HEADER.ImageBase + text.VirtualAddress | |
rc4_key , rc4_key_offset = extract_rc4_key(md , text_addr , pe , file_data , text) | |
encrypted_strings_table = file_data[rc4_key_offset + 0x100: rc4_key_offset + 0x1100] | |
except: | |
# if only the shellcode is passed | |
# Use splunk wineloader shellcode extractor : https://raw.githubusercontent.com/tccontre/KnowledgeBase/main/malware_re_tools/wineloader_dll_side_load/wineloader_extractor.py | |
rc4_key = file_data[0x20:0x120] | |
encrypted_strings_table = file_data[0x120:0x1000] | |
extracted_strings = extract_strings(encrypted_strings_table) | |
decrypt_strings(extracted_strings , rc4_key) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment