Last active
May 16, 2024 14:02
-
-
Save yarienkiva/f2e94d93c0a79f744ed6399fe7f32b76 to your computer and use it in GitHub Desktop.
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
| import base64 | |
| import sys | |
| import os | |
| import io | |
| from PIL import Image | |
| from pythonnet import load | |
| load("coreclr") | |
| import clr | |
| clr.AddReference("dnlib") | |
| import dnlib | |
| from dnlib.DotNet import * | |
| """ | |
| rule musicexpresspacker { | |
| meta: | |
| description = "Some shit dotnet packer I found (used to pack Njrat)" | |
| author = "yarienkiva" | |
| strings: | |
| $a1 = "1973c.png" ascii wide fullword | |
| $a2 = "26fc2.resources" ascii fullword | |
| $m1 = "MusicExpressMain" ascii fullword | |
| $m2 = "MusicReader" ascii fullword | |
| condition: | |
| uint16(0) == 0x5A4D | |
| and (uint32(uint32(0x3C)) == 0x00004550) | |
| and ((uint16(uint32(0x3C)+24) == 0x010B and uint32(uint32(0x3C)+232) > 0) | |
| or (uint16(uint32(0x3C)+24) == 0x020B and uint32(uint32(0x3C)+248) > 0)) | |
| and filesize < 200KB | |
| and ((all of a*) or (all of m*)) | |
| } | |
| """ | |
| xor = lambda a, b: bytes([a[i] ^ b[i % len(b)] for i in range(len(a))]) | |
| def extract(file: str) -> dict: | |
| mod = dnlib.DotNet.ModuleDefMD.Load(file) | |
| res = [*mod.Resources][0] | |
| dat = bytes(res.CreateReader().ToArray()) | |
| # PNG magic bytes b'\x89PNG\r\n\x1a' | |
| # PNG IEND bytes b'\x00\x00\x00\x00IEND\xaeB`\x82' | |
| dat = dat[ | |
| dat.find(bytes.fromhex("89 50 4E 47 0D 0A 1A")) : | |
| dat.find(bytes.fromhex("00 00 00 00 49 45 4E 44 AE 42 60 82")) + 12 | |
| ] | |
| img = Image.open(io.BytesIO(dat)) | |
| dat = [*img.getdata()] | |
| arr = [] | |
| for i in range(img.width): | |
| for j in range(img.width): | |
| a = dat[j * img.width + i] | |
| arr.append(a[2]) | |
| arr.append(a[1]) | |
| arr.append(a[0]) | |
| arr.append(a[3]) | |
| size = arr[3] << 24 | arr[2] << 16 | arr[1] << 8 | arr[0] | |
| arr = xor(arr[4:size], base64.b64decode("iA0GysvC1ZIOOytcecH4i6PzSas=")) | |
| with open(file + "_unpacked", "wb") as f: | |
| f.write(arr) | |
| return arr[:2] == b"MZ" | |
| if __name__ == "__main__": | |
| # Take files from both ARGV and STDIN | |
| files = sys.argv[1:] | |
| if not sys.stdin.isatty(): | |
| files += [f.strip() for f in sys.stdin] | |
| if not files: | |
| print("Usage:\n Files : ARGV + STDIN") | |
| sys.exit(1) | |
| for file in files: | |
| # Resolve the actual path of the file | |
| file = os.path.abspath(os.path.expanduser(os.path.expandvars(file))) | |
| try: | |
| print("Processing,", file, file=sys.stderr) | |
| # Write the config to STDOUT | |
| assert extract(file) | |
| except Exception as e: | |
| print("Failed to extract from", file, "because", e, file=sys.stderr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment