From c9fc208207da04d8ea4fb3c469bc0f1765ac6b29 Mon Sep 17 00:00:00 2001 From: Zeno Date: Mon, 11 May 2026 20:00:06 +0900 Subject: [PATCH 1/5] Add padding after section data if needed --- neolite_unpack.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/neolite_unpack.py b/neolite_unpack.py index a56dade..9b4ab8e 100755 --- a/neolite_unpack.py +++ b/neolite_unpack.py @@ -533,6 +533,10 @@ def fixup(data): if offset > len(new_data): new_data += bytes(offset - len(new_data)) new_data += sdata + if len(sdata) < section.SizeOfRawData: + new_data += bytes(section.SizeOfRawData - len(sdata)) + elif len(sdata) > section.SizeOfRawData: + raise Exception(f'Section {section_name} overflowed') section.PointerToRawData = offset if imports_offset >= section.VirtualAddress and imports_offset < section.VirtualAddress + section.SizeOfRawData: From d74886bce9ec09e699abb0138c916ca671462213 Mon Sep 17 00:00:00 2001 From: Zeno Date: Mon, 11 May 2026 20:01:46 +0900 Subject: [PATCH 2/5] Add support for ExeLock Executable File Protector NeoLite variant that uses Deflate64 and one extra obfuscation step --- neolite_unpack.py | 59 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/neolite_unpack.py b/neolite_unpack.py index 9b4ab8e..34c777f 100755 --- a/neolite_unpack.py +++ b/neolite_unpack.py @@ -9,6 +9,7 @@ import pefile import struct import zlib +from zipfile_deflate64.deflate64 import Deflate64 def hexdump(src, length=16, sep='.'): FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)]) @@ -165,7 +166,7 @@ def next_command(self): if command < 2: self.back(0, command + 3) else: - self.back_base(command * 256, 3) + self.back_base(command << 8, 3) case 5: self.back_extend16(4) case 6: self.back_extend16(5) case 7: self.back_offset0(6) @@ -246,6 +247,17 @@ def zlib_uncompress(data, usize): return ret +def deflate64_uncompress(data, usize): + obj = Deflate64() + ret = obj.decompress(data) + + if len(ret) > usize: + raise Exception(f'{len(ret)=:x} {usize=:x}') + + if not obj.eof: + raise Exception + + return ret def is_neolite(data): pe = pefile.PE(data=data) @@ -312,6 +324,38 @@ def print_info(data): v = f'0x{val:x}' print(f'rev.{key:22} {v:>10}') +def fixup_calls(buf): + data = bytearray(buf) + size = len(data) + + i = 0 + while i < size - 4: + if data[i] == 0xE8: # CALL rel32 + i += 1 + addr = int.from_bytes(data[i:i+4], 'little', signed=True) + + # Equivalent to ExeLock runtime logic: + # + # if target is inside section range: + # if addr < 0: + # new = size + addr + # else: + # new = addr - current_position + # + if i + addr >= 0 and addr < size: + if addr < 0: + new = size + addr + else: + new = addr - i + + data[i:i+4] = int(new).to_bytes(4, 'little', signed=True) + + i += 4 + else: + i += 1 + + return bytes(data) + def fixup(data): pe = pefile.PE(data=data) @@ -349,6 +393,7 @@ def fixup(data): zpos_start = pos zpos = zpos_start + exelock = hdr.use_zlib == 2 if hdr.use_zlib: # Decompress the included decompressor. It's just zlib, so we just use # python's zlib, but we need to advance the pos value. @@ -360,7 +405,7 @@ def fixup(data): zpos += hdr.zlib_relocations_sz - uncompress = zlib_uncompress + uncompress = deflate64_uncompress if exelock else zlib_uncompress else: uncompress = neo_uncompress @@ -532,7 +577,10 @@ def fixup(data): if offset > len(new_data): new_data += bytes(offset - len(new_data)) - new_data += sdata + if exelock and section.Characteristics & 0x20000000: # IMAGE_SCN_MEM_EXECUTE + new_data += fixup_calls(sdata) + else: + new_data += sdata if len(sdata) < section.SizeOfRawData: new_data += bytes(section.SizeOfRawData - len(sdata)) elif len(sdata) > section.SizeOfRawData: @@ -603,7 +651,10 @@ def fixup(data): # Copy data at end of file to end of file. if hdr.extra_data_csize: if hdr.use_zlib: - udata = zlib.decompress(data[extra_data_offset:extra_data_offset+extra_data_size]) + if exelock: + udata = Deflate64().decompress(data[extra_data_offset:extra_data_offset+extra_data_size]) + else: + udata = zlib.decompress(data[extra_data_offset:extra_data_offset+extra_data_size]) if len(udata) != hdr.extra_data_usize: raise Exception else: From 4f8722f18a1a97a70cba68870cc77b27284207a7 Mon Sep 17 00:00:00 2001 From: Zeno Date: Mon, 11 May 2026 21:00:20 +0900 Subject: [PATCH 3/5] Pass in the section size instead of determining it from the array size --- neolite_unpack.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/neolite_unpack.py b/neolite_unpack.py index 34c777f..007cc1f 100755 --- a/neolite_unpack.py +++ b/neolite_unpack.py @@ -324,12 +324,11 @@ def print_info(data): v = f'0x{val:x}' print(f'rev.{key:22} {v:>10}') -def fixup_calls(buf): +def fixup_calls(buf, section_size): data = bytearray(buf) - size = len(data) i = 0 - while i < size - 4: + while i < len(data) - 4: if data[i] == 0xE8: # CALL rel32 i += 1 addr = int.from_bytes(data[i:i+4], 'little', signed=True) @@ -338,13 +337,13 @@ def fixup_calls(buf): # # if target is inside section range: # if addr < 0: - # new = size + addr + # new = section_size + addr # else: # new = addr - current_position # - if i + addr >= 0 and addr < size: + if i + addr >= 0 and addr < section_size: if addr < 0: - new = size + addr + new = section_size + addr else: new = addr - i @@ -578,7 +577,7 @@ def fixup(data): if offset > len(new_data): new_data += bytes(offset - len(new_data)) if exelock and section.Characteristics & 0x20000000: # IMAGE_SCN_MEM_EXECUTE - new_data += fixup_calls(sdata) + new_data += fixup_calls(sdata, section.SizeOfRawData) else: new_data += sdata if len(sdata) < section.SizeOfRawData: From af501004da393867c784ecc34df58ba93976a295 Mon Sep 17 00:00:00 2001 From: Zeno Date: Mon, 11 May 2026 21:21:16 +0900 Subject: [PATCH 4/5] Add requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..64452fb --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +zipfile-deflate64==0.2.0 From 4c8e0166af65f4a5410cd6a011489e04ffee1bbd Mon Sep 17 00:00:00 2001 From: Zeno Date: Mon, 11 May 2026 21:25:32 +0900 Subject: [PATCH 5/5] Add pefile to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 64452fb..acb6c2a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ +pefile==2023.2.7 zipfile-deflate64==0.2.0