Exetools

Exetools (https://forum.exetools.com/index.php)
-   Community Tools (https://forum.exetools.com/forumdisplay.php?f=47)
-   -   MD5 replace tool (https://forum.exetools.com/showthread.php?t=18999)

Elesty 10-22-2018 19:26

MD5 replace tool
 
1 Attachment(s)
Hi,

I just wrote a quick tool to patch all occurrences of a file inside a program folder (no matter the file name) given an MD5 checksum.
It is useful when the original files may have different names and are present in multiple sub directories.

Usage:
python replace.py FOLDER MD5_SUM CRACKED_FILE_PATH

Example:
python replace.py 098f6bcd4621d373cade4e832627b4f6 c:\mysoftware license.dll

Where:
-> 098f6bcd4621d373cade4e832627b4f6: is the MD5 of the original files to be replaced by the cracked file. You can get the MD5 checksum by using powershell with the function Get-FileHash -alg md5 ORIGINAL_FILE
-> c:\mysoftware is the folder of the software
-> license.dll is the path to the cracked file

You can also edit the file and set DEBUG_MODE=True to only print the occurrence of the files instead of replacing them.

Compiled version is also available attached.


Code:

import os
import sys
import hashlib
import shutil

DEBUG_MODE=False

if len(sys.argv) < 4:
  print("Usage: python replace.py FOLDER MD5_SUM FILE_PATH_TO_REPLACE_BY")
  sys.exit(-1)

g_path = sys.argv[1]
md5_to_find = sys.argv[2]
to_replace_by = sys.argv[3]

if not os.path.isfile(to_replace_by):
  print("Error: the path of the file to replace by does not exists")
  sys.exit(-1)

def md5sum(fname):
  try:
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
      for chunk in iter(lambda: f.read(4096), b""):
        hash_md5.update(chunk)
    return hash_md5.hexdigest()
  except:
    pass
  return "ERROR"

for root, directories, filenames in os.walk(g_path):
  for filename in filenames:
    full_path = os.path.join(root, filename)
    checksum = md5sum(full_path)
    #print(full_path, md5sum(full_path))
    if not DEBUG_MODE and checksum == md5_to_find:
      print("Replacing [%s] by [%s]" % (full_path, to_replace_by))
      shutil.copy(to_replace_by, full_path)
    elif checksum == md5_to_find:
      print("Should replace [%s] by [%s]" %  (full_path, to_replace_by))


tigerfish 10-23-2018 20:21

can it be uploaded to other site? thx

chants 10-26-2018 18:11

Probably you would include the file size as a pre-filter before filtering based on MD5 checksum. Otherwise this is the sort of inelegance that grinds away hard drives especially when huge files might be in that same directory. Since MD5 requires disk reading and is generally thereby expensive, it should not be treated so lightly. It should only be done when absolutely needed. Hence file size hint.

ranadharm 10-29-2018 01:52

any chance to upload elsewhere ?

Elesty 11-05-2018 00:58

1 Attachment(s)
@chants: Thank you for your feedbacks

Version 2 with the following changelog:
-> Added a 4th optional argument MAX_FILE_SIZE_IN_MB, the md5 wont be computed is the file size in MB is larger than the MAX_FILE_SIZE_IN_MB specified.
-> If the 4th argument is not specified, all files md5 will be computed.

Code:

import os
import sys
import hashlib
import shutil

DEBUG_MODE=False

def get_filesize_mb(file_path):
  size_b = os.path.getsize(file_path)
  return size_b / 1048576

def md5sum(fname):
  try:
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
      for chunk in iter(lambda: f.read(4096), b""):
        hash_md5.update(chunk)
    return hash_md5.hexdigest()
  except:
    pass
  return "ERROR"

if len(sys.argv) < 4:
  print("Usage: python replace.py FOLDER MD5_SUM_TO_FIND FILE_PATH_TO_REPLACE_BY [MAX_FILE_SIZE_IN_MB]")
  sys.exit(-1)

g_path = sys.argv[1]
md5_to_find = sys.argv[2].lower()
to_replace_by = sys.argv[3]

max_file_size = None
if len(sys.argv) >= 5:
  max_file_size = int(sys.argv[4])
  print("Maximum file size to check is %s MB" % sys.argv[4])

if not os.path.isfile(to_replace_by):
  print("Error: the path of the file to replace by does not exists")
  sys.exit(-1)

if __name__ == '__main__':
  for root, directories, filenames in os.walk(g_path):
    for filename in filenames:
      full_path = os.path.join(root, filename)
      fsize = get_filesize_mb(full_path)
      if max_file_size and get_filesize_mb(full_path) > max_file_size:
        # The current file size is too big, skipping it
        print("Skipping file [%s] with size %sMB" % (full_path, str(fsize)))
        continue
      # No maximum filesize specified, processing all files
      if max_file_size is None:
        checksum = md5sum(full_path)
        #print(full_path, md5sum(full_path))
        if not DEBUG_MODE and checksum == md5_to_find:
          print("Replacing [%s] by [%s]" % (full_path, to_replace_by))
          shutil.copy(to_replace_by, full_path)
        elif checksum == md5_to_find:
          print("Should replace [%s] by [%s]" %  (full_path, to_replace_by))


athapa 11-29-2018 03:19

If you include file size (in bytes) then the script would be even faster!

afeng 07-07-2019 20:44

replace all file type?

icscrew 09-30-2019 10:28

can @Elesty upload to other site.
cant download from attachment forum.(you do not have permission to access this page)

Stingered 01-23-2020 03:46

Quote:

Originally Posted by icscrew (Post 118403)
can @Elesty upload to other site.
cant download from attachment forum.(you do not have permission to access this page)

Download compiled exe HERE

fyi: Compiled using existing code in this thread.

Stingered 01-23-2020 04:35

Quote:

Originally Posted by Stingered (Post 119213)
Download compiled exe HERE

fyi: Compiled using existing code in this thread.

Updated D/L link HERE


All times are GMT +8. The time now is 20:39.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX