Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.

Commit 104f2c7

Browse files
committed
Version 0.2.1
Made CLI arguments backwards compatible with pre-0.2.0 versions. Added example usage to README.
1 parent 378c9eb commit 104f2c7

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

README.md

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Supports both built-in files and external packages
1111
- Supports compressed mode
1212

13-
# Tested Versions
13+
## Tested Versions
1414
| Packer Version | Notes | Unpack with Flags |
1515
| - | - | - |
1616
| 10.70 | Automatically tested in CI for x86/x64 binaries. | None |
@@ -27,7 +27,9 @@
2727

2828
## Usage
2929

30-
usage: evbunpack [-h] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-l] [--ignore-fs] [--ignore-pe] [--legacy-fs] [--legacy-pe] [--out-dir OUT_DIR] [--out-pe OUT_PE] file
30+
usage: evbunpack [-h] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-l] [--ignore-fs] [--ignore-pe]
31+
[--legacy-fs] [--legacy-pe] [--out-pe OUT_PE]
32+
file output
3133

3234
Enigma Virtual Box Unpacker
3335

@@ -43,12 +45,35 @@
4345
--legacy-fs Use legacy mode for filesystem extraction
4446
--legacy-pe Use legacy mode for PE restoration
4547

46-
Output:
47-
--out-dir OUT_DIR Output folder
48-
--out-pe OUT_PE (If the executable is to be recovered) Where the unpacked EXE is saved. Leave as-is to save it in the output folder.
48+
Overrides:
49+
--out-pe OUT_PE (If the executable is to be recovered) Where the unpacked EXE is saved. Leave as-is
50+
to save it in the output folder.
4951

5052
Input:
5153
file File to be unpacked
54+
output Output folder
55+
56+
### Example Usage ([test file available here](https://github.com/mos9527/evbunpack/blob/main/tests/x64_PackerTestApp_packed_20240522.exe))
57+
Input:
58+
```bash
59+
evbunpack x64_PackerTestApp_packed_20240522.exe output
60+
```
61+
Output:
62+
```bash
63+
INFO: Enigma Virtual Box Unpacker v0.2.1
64+
INFO: Extracting virtual filesystem
65+
Filesystem:
66+
└─── output
67+
└─── output/README.txt
68+
Writing File [size=0x11, offset=0x3465]: total= 11h read= 0h
69+
INFO: Extraction complete
70+
INFO: Restoring executable
71+
INFO: Using default executable save path: output\x64_PackerTestApp_packed_20240522.exe
72+
Saving PE: total= 3211h read= 0h
73+
INFO: Unpacked PE saved: output\x64_PackerTestApp_packed_20240522.exe
74+
```
75+
## TODO
76+
- Automatically detect packer version
5277

5378
## Credits
5479
- [evb-extractor](https://github.com/EVBExtractor/evb-extractor)

evbunpack/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#-*- coding: utf-8 --
2-
__version__ = '0.2.0'
2+
__version__ = '0.2.1'
33
__author__ = 'mos9527'

evbunpack/__main__.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ def restore_pe(input_file : str, output_file : str, legcay_pe : bool):
203203
find_data_directory('IMPORT').Size = hdr['IMPORT_SIZE']
204204
find_data_directory('RELOC').VirtualAddress = hdr['RELOC_ADDRESS']
205205
find_data_directory('RELOC').Size = hdr['RELOC_SIZE']
206-
logger.info('Import -> VA=0x%x Size=0x%x' % (hdr['IMPORT_ADDRESS'],hdr['IMPORT_SIZE']))
207-
logger.info('Reloc -> VA=0x%x Size=0x%x' % (hdr['RELOC_ADDRESS'],hdr['RELOC_SIZE']))
206+
logger.debug('Import -> VA=0x%x Size=0x%x' % (hdr['IMPORT_ADDRESS'],hdr['IMPORT_SIZE']))
207+
logger.debug('Reloc -> VA=0x%x Size=0x%x' % (hdr['RELOC_ADDRESS'],hdr['RELOC_SIZE']))
208208
if hdr['RELOC_SIZE'] == 0 or hdr['IMPORT_SIZE'] == 0:
209209
warnings_issued += 1
210210
logger.warning('Import/Reloc table size is zero. This may indicate that the header is incorrectly parsed.')
@@ -269,7 +269,7 @@ def restore_pe(input_file : str, output_file : str, legcay_pe : bool):
269269
new_file_data = pe.write()
270270
with open(output_file,'wb+') as f:
271271
write_bytes(BytesIO(new_file_data),f,len(new_file_data),desc='Saving PE')
272-
logger.info('Original PE saved: %s' % output_file)
272+
logger.info('Unpacked PE saved: %s' % output_file)
273273
if warnings_issued:
274274
logger.warning('There were %d warning(s) issued during the restoration process.' % warnings_issued)
275275
logger.warning('Please try toggling the --legacy-pe flag if the unpacked EXE is corrupt.')
@@ -332,9 +332,9 @@ def traverse_next_node(node,pfx=out_dir,depth=0):
332332
return
333333
logger.info('Extraction complete')
334334

335-
def main(file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = False, ignore_pe: bool = False, legacy_fs: bool = False, legacy_pe: bool = False, fs_listing_only: bool = False):
335+
def main(in_file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = False, ignore_pe: bool = False, legacy_fs: bool = False, legacy_pe: bool = False, fs_listing_only: bool = False):
336336
logger.info('Enigma Virtual Box Unpacker v%s' % __version__)
337-
logger.debug('File: %s' % file)
337+
logger.debug('File: %s' % in_file)
338338
os.makedirs(out_dir,exist_ok=True)
339339
if legacy_fs:
340340
logger.warning('Legacy mode for filesystem extraction enabled')
@@ -347,7 +347,7 @@ def main(file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = F
347347
else:
348348
logger.info('Extracting virtual filesystem')
349349
try:
350-
unpack_files(file,out_dir,legacy_fs,fs_listing_only)
350+
unpack_files(in_file,out_dir,legacy_fs,fs_listing_only)
351351
except Exception as e:
352352
logger.error('Unhandled exception occured while extracting virtual filesystem: %s' % e)
353353
raise e
@@ -356,10 +356,10 @@ def main(file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = F
356356
else:
357357
logger.info('Restoring executable')
358358
if not out_pe:
359-
out_pe = os.path.join(out_dir, os.path.basename(file))
360-
logger.warning('Using default executable save path: %s' % out_pe)
359+
out_pe = os.path.join(out_dir, os.path.basename(in_file))
360+
logger.info('Using default executable save path: %s' % out_pe)
361361
try:
362-
restore_pe(file,out_pe,legacy_pe)
362+
restore_pe(in_file,out_pe,legacy_pe)
363363
except Exception as e:
364364
logger.error('Unhandled exception occured while restoring executable: %s' % e)
365365

@@ -372,14 +372,14 @@ def __main__():
372372
group.add_argument('--ignore-pe',help='Don\'t restore the executable',action='store_true')
373373
group.add_argument('--legacy-fs',help='Use legacy mode for filesystem extraction',action='store_true')
374374
group.add_argument('--legacy-pe',help='Use legacy mode for PE restoration',action='store_true')
375-
group = parser.add_argument_group('Output')
376-
group.add_argument('--out-dir', help='Output folder',default='.')
375+
group = parser.add_argument_group('Overrides')
377376
group.add_argument('--out-pe', help='(If the executable is to be recovered) Where the unpacked EXE is saved. Leave as-is to save it in the output folder.',default='')
378377
group = parser.add_argument_group('Input')
379378
group.add_argument('file', help='File to be unpacked')
379+
group.add_argument('output', help='Output folder')
380380
args = parser.parse_args()
381-
logging.basicConfig(level=args.log_level)
382-
sys.exit(main(args.file,args.out_dir,args.out_pe,args.ignore_fs,args.ignore_pe,args.legacy_fs,args.legacy_pe,args.list))
381+
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
382+
sys.exit(main(args.file,args.output,args.out_pe,args.ignore_fs,args.ignore_pe,args.legacy_fs,args.legacy_pe,args.list))
383383

384384
if __name__ == "__main__":
385385
__main__()

0 commit comments

Comments
 (0)