-
Notifications
You must be signed in to change notification settings - Fork 628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Any way to replace a file? #60
Comments
pyinstxtractor doesn't support replacing files. I've a tool which supports replace & repacking pyinstaller exe files but its not open source at the moment and requires more improvements. If you're familiar with internal pyinstaller format you can replace the file manually. The cacert.pem will be stored in the CArchive and likely zlib compressed. You can search and replace the zlib compressed original cacert bytes with your patched & compressed cacert using a hex editor. Also ensure the patched bytes are smaller or equal in size to the original. |
I have the same problem and have followed your advice, with the following source: import zlib
target_file = 'installed.exe'
source_cert_file = 'cacert.pem'
replacement_cert_file = 'cert.pem'
with open(target_file, 'rb') as f:
file_data = f.read()
for compression_level in range(-1, 10):
# zlib compress source
with open(source_cert_file, 'rb') as f:
source_zlib_data = zlib.compress(f.read(), level=compression_level)
pos = file_data.find(source_zlib_data)
if pos != -1:
print("Compression level:", compression_level)
print("Found position:", pos)
break
print("Compressing at level", compression_level)
with open(replacement_cert_file, 'rb') as f:
target_zlib_data = zlib.compress(f.read(), level=compression_level)
print("Source len: ", len(source_zlib_data), "replacement len: ", len(target_zlib_data))
assert len(source_zlib_data) >= len(target_zlib_data)
print(target_zlib_data)
target_zlib_data = target_zlib_data + b'\0'*(len(source_zlib_data)-len(target_zlib_data))
output_data = file_data.replace(source_zlib_data, target_zlib_data)
with open("replaced_" + target_file, 'wb') as f:
f.write(output_data) As You can see, I have padded the compressed zlib with binary zeros. If i don't pad, I end up with Edit: the folder doesn't show up if I pad with space (' '), and pyinxtractor throws To no avail I have also tried using compression level 0 and just appending newlines until the compressed size was equal: while len(target_zlib_data) != len(source_zlib_data):
if len(target_zlib_data) < len(source_zlib_data):
target_zlib_source += "\n".encode('utf-8') * (len(source_zlib_data)-len(target_zlib_data))
target_zlib_data = zlib.compress(target_zlib_source, level=0)
if len(target_zlib_data) > len(source_zlib_data):
target_zlib_source = target_zlib_source[:-1]
target_zlib_data = zlib.compress(target_zlib_source, level=0) I am sure my problem is no longer related to this software, but It would be great if You could further elaborate on this subject. |
@Szustarol Hi, added a wiki article which describes the process of replacing a file in the CArchive. https://github.com/extremecoders-re/pyinstxtractor/wiki/Replacing-files-inside-the-CArchive |
Thank you so much for this article! Not only does it solve an important problem but is actually very insightful of pysintaller and the extractor itself. |
thank you, that's very helpful |
Hi, is there a way to replace a file in PYZarchive? |
It is possible. The PYZArchive has its own table of contents (toc) which is stored as a marshalled list. The toc stores the filename, offset and size of the items. The individual items in the PYZArchive are Zlib Compressed. To replace a file, its the same as overwriting the original bytes with the new data. Both the original and new data are Zlib Compressed. If the size of compressed new data is exactly the same as original, no further changes need to be done. If the new size is less than the original, the toc also needs to be updated with the new size. There will be some extra bytes at the end but that is fine and will be ignored. If the new size is more than original, it will require further invasive modifications. Like shifting all the succeeding files and also updating the toc with the new offset for all files that are affected. |
I appreciate your answer very much. I know some golang. I can make some references from your golang project, right? |
@sparklive You can. I will also add a wiki article later about replacing files in the PYZArchive. |
looking forward to your article |
Hello!Good job! And how to replace *.pyc file (main.pyc) |
Please try pyipx, hope it helps you |
Have you finished the article? |
Ok so basically the program i'm trying to mess with is from 3.9, using pyinstaller 4.8, i managed to extract it just fine, but since i can't decompile the files anyways, i just wanted to replace the cacert.pem from certifi to use my own fiddler signed cert, is there any way i can just replace that file on the .exe or any way to recompile the .exe with it replaced? (straight up running pyinstaller main.pyc throw me errors)
The text was updated successfully, but these errors were encountered: