Skip to content

Instantly share code, notes, and snippets.

@ivanpu
Last active June 1, 2024 08:03
Show Gist options
  • Save ivanpu/c5347bf107fa900ac79f1fcf2f056e7c to your computer and use it in GitHub Desktop.
Save ivanpu/c5347bf107fa900ac79f1fcf2f056e7c to your computer and use it in GitHub Desktop.
Jar Infection Checker (python)
# Adapted by @ivanpu to Python from Overwolf's scanner, because I couldn't launch it
# Original code: https://github.com/overwolf/jar-infection-scanner/
# Check for updates to this script: https://gist.github.com/ivanpu/c5347bf107fa900ac79f1fcf2f056e7c
from __future__ import annotations
import zipfile
from argparse import ArgumentParser
from pathlib import Path
SIGNATURES: list[bytes] = [
b"\x38\x54\x59\x04\x10\x35\x54\x59\x05\x10\x2E\x54\x59\x06\x10\x32\x54\x59\x07\x10\x31\x54\x59\x08\x10\x37\x54\x59\x10\x06\x10\x2E\x54\x59\x10\x07\x10\x31\x54\x59\x10\x08\x10\x34\x54\x59\x10\x09\x10\x34\x54\x59\x10\x0A\x10\x2E\x54\x59\x10\x0B\x10\x31\x54\x59\x10\x0C\x10\x33\x54\x59\x10\x0D\x10\x30\x54\xB7",
b"\x68\x54\x59\x04\x10\x74\x54\x59\x05\x10\x74\x54\x59\x06\x10\x70\x54\x59\x07\x10\x3a\x54\x59\x08\x10\x2f\x54\x59\x10\x06\x10\x2f\x54\x59\x10\x07\x10\x66\x54\x59\x10\x08\x10\x69\x54\x59\x10\x09\x10\x6c\x54\x59\x10\x0a\x10\x65\x54\x59\x10\x0b\x10\x73\x54\x59\x10\x0c\x10\x2e\x54\x59\x10\x0a\x10\x73\x54\x59\x10\x0e\x10\x6b\x54\x59\x10\x0f\x10\x79\x54\x59\x10\x10\x10\x72\x54\x59\x10\x11\x10\x61\x54\x59\x10\x12\x10\x67\x54\x59\x10\x13\x10\x65\x54\x59\x10\x14\x10\x2e\x54\x59\x10\x15\x10\x64",
b"\x2d\x54\x59\x04\x10\x6a\x54\x59\x05\x10\x61\x54\x59\x06\x10\x72",
]
def check_jar_file(jar_file_path: Path) -> bool:
def check_zip_dir(path: zipfile.Path) -> bool:
for entry in path.iterdir():
if entry.is_file() and entry.name.endswith(".class"):
buffer = entry.read_bytes()
if any(sig in buffer for sig in SIGNATURES):
return True
elif entry.is_dir():
if check_zip_dir(entry):
return True
return False
try:
return check_zip_dir(zipfile.Path(jar_file_path))
except Exception as e:
print(f"Error while extracting {jar_file_path}: {e}")
return False
def main():
parser = ArgumentParser()
parser.add_argument("directories", nargs="+", type=Path, help="directories to scan", metavar="directory")
args = parser.parse_args()
for path in args.directories: # type: Path
jars = path.rglob("*.[jJ][aA][rR]")
for jar in jars:
if check_jar_file(jar):
print("!!! INFECTED:", jar)
if __name__ == "__main__":
main()
@ivanpu
Copy link
Author

ivanpu commented Jun 9, 2023

DISCLAIMER:
It didn't find any infected jars on my computer, so I can't guarantee that it actually finds stage-0 infection.
I assume that this code is correct if the original Overwolf's scanner is correct.

@MentalHolyGlobe
Copy link

This script does not work, because it doesn't recursively check inside the jar files. When it finds a folder it skips the entry instead of checking all the entries within that folder.

@ivanpu
Copy link
Author

ivanpu commented Jun 9, 2023

@MentalHolyGlobe
Thanks, fixed.

@MentalHolyGlobe
Copy link

Looks like it's working now, thanks.

@silmaril42
Copy link

Thank you very much, @ivanpu for turning this into a Python script!

Unfortunately, I was getting a lot of errors 'Path' object has no attribute 'suffix' (using Python 3.10.6).

I made it work by replacing

if entry.is_file() and entry.suffix == ".class":

with

if entry.is_file() and str(entry).endswith(".class"):

This is slightly less elegant and probably a bit slower, but it works.

I guess this has something to do with the python version, but didn't dig any deeper.

@ivanpu
Copy link
Author

ivanpu commented Jun 11, 2023

While I did try to make the code backwards compatible as much as possible (I was assuming python 3.7+), I missed to check the zipfile documentation thoroughly:
zipfile.Path was added in Python 3.8
zipfile.Path.suffix was added in Python 3.11

@silmaril42
If you want something a bit more elegant than you currently have, you can use this:

if entry.is_file() and entry.name.endswith(".class"):

Which I think I'll actually update into the script, to lower the Python dependency to 3.8.

@silmaril42
Copy link

Yes, this looks much nicer! 😃 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment