Skip to content

Commit

Permalink
Version 0.2.1
Browse files Browse the repository at this point in the history
Made CLI arguments backwards compatible with pre-0.2.0 versions.
Added example usage to README.
  • Loading branch information
mos9527 committed Jun 11, 2024
1 parent 378c9eb commit 104f2c7
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 19 deletions.
35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- Supports both built-in files and external packages
- Supports compressed mode

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

## Usage

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
usage: evbunpack [-h] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-l] [--ignore-fs] [--ignore-pe]
[--legacy-fs] [--legacy-pe] [--out-pe OUT_PE]
file output

Enigma Virtual Box Unpacker

Expand All @@ -43,12 +45,35 @@
--legacy-fs Use legacy mode for filesystem extraction
--legacy-pe Use legacy mode for PE restoration

Output:
--out-dir OUT_DIR Output folder
--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.
Overrides:
--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.

Input:
file File to be unpacked
output Output folder

### Example Usage ([test file available here](https://github.com/mos9527/evbunpack/blob/main/tests/x64_PackerTestApp_packed_20240522.exe))
Input:
```bash
evbunpack x64_PackerTestApp_packed_20240522.exe output
```
Output:
```bash
INFO: Enigma Virtual Box Unpacker v0.2.1
INFO: Extracting virtual filesystem
Filesystem:
└─── output
└─── output/README.txt
Writing File [size=0x11, offset=0x3465]: total= 11h read= 0h
INFO: Extraction complete
INFO: Restoring executable
INFO: Using default executable save path: output\x64_PackerTestApp_packed_20240522.exe
Saving PE: total= 3211h read= 0h
INFO: Unpacked PE saved: output\x64_PackerTestApp_packed_20240522.exe
```
## TODO
- Automatically detect packer version

## Credits
- [evb-extractor](https://github.com/EVBExtractor/evb-extractor)
Expand Down
2 changes: 1 addition & 1 deletion evbunpack/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#-*- coding: utf-8 --
__version__ = '0.2.0'
__version__ = '0.2.1'
__author__ = 'mos9527'
26 changes: 13 additions & 13 deletions evbunpack/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ def restore_pe(input_file : str, output_file : str, legcay_pe : bool):
find_data_directory('IMPORT').Size = hdr['IMPORT_SIZE']
find_data_directory('RELOC').VirtualAddress = hdr['RELOC_ADDRESS']
find_data_directory('RELOC').Size = hdr['RELOC_SIZE']
logger.info('Import -> VA=0x%x Size=0x%x' % (hdr['IMPORT_ADDRESS'],hdr['IMPORT_SIZE']))
logger.info('Reloc -> VA=0x%x Size=0x%x' % (hdr['RELOC_ADDRESS'],hdr['RELOC_SIZE']))
logger.debug('Import -> VA=0x%x Size=0x%x' % (hdr['IMPORT_ADDRESS'],hdr['IMPORT_SIZE']))
logger.debug('Reloc -> VA=0x%x Size=0x%x' % (hdr['RELOC_ADDRESS'],hdr['RELOC_SIZE']))
if hdr['RELOC_SIZE'] == 0 or hdr['IMPORT_SIZE'] == 0:
warnings_issued += 1
logger.warning('Import/Reloc table size is zero. This may indicate that the header is incorrectly parsed.')
Expand Down Expand Up @@ -269,7 +269,7 @@ def restore_pe(input_file : str, output_file : str, legcay_pe : bool):
new_file_data = pe.write()
with open(output_file,'wb+') as f:
write_bytes(BytesIO(new_file_data),f,len(new_file_data),desc='Saving PE')
logger.info('Original PE saved: %s' % output_file)
logger.info('Unpacked PE saved: %s' % output_file)
if warnings_issued:
logger.warning('There were %d warning(s) issued during the restoration process.' % warnings_issued)
logger.warning('Please try toggling the --legacy-pe flag if the unpacked EXE is corrupt.')
Expand Down Expand Up @@ -332,9 +332,9 @@ def traverse_next_node(node,pfx=out_dir,depth=0):
return
logger.info('Extraction complete')

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):
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):
logger.info('Enigma Virtual Box Unpacker v%s' % __version__)
logger.debug('File: %s' % file)
logger.debug('File: %s' % in_file)
os.makedirs(out_dir,exist_ok=True)
if legacy_fs:
logger.warning('Legacy mode for filesystem extraction enabled')
Expand All @@ -347,7 +347,7 @@ def main(file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = F
else:
logger.info('Extracting virtual filesystem')
try:
unpack_files(file,out_dir,legacy_fs,fs_listing_only)
unpack_files(in_file,out_dir,legacy_fs,fs_listing_only)
except Exception as e:
logger.error('Unhandled exception occured while extracting virtual filesystem: %s' % e)
raise e
Expand All @@ -356,10 +356,10 @@ def main(file : str, out_dir : str = '.', out_pe : str = '', ignore_fs: bool = F
else:
logger.info('Restoring executable')
if not out_pe:
out_pe = os.path.join(out_dir, os.path.basename(file))
logger.warning('Using default executable save path: %s' % out_pe)
out_pe = os.path.join(out_dir, os.path.basename(in_file))
logger.info('Using default executable save path: %s' % out_pe)
try:
restore_pe(file,out_pe,legacy_pe)
restore_pe(in_file,out_pe,legacy_pe)
except Exception as e:
logger.error('Unhandled exception occured while restoring executable: %s' % e)

Expand All @@ -372,14 +372,14 @@ def __main__():
group.add_argument('--ignore-pe',help='Don\'t restore the executable',action='store_true')
group.add_argument('--legacy-fs',help='Use legacy mode for filesystem extraction',action='store_true')
group.add_argument('--legacy-pe',help='Use legacy mode for PE restoration',action='store_true')
group = parser.add_argument_group('Output')
group.add_argument('--out-dir', help='Output folder',default='.')
group = parser.add_argument_group('Overrides')
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='')
group = parser.add_argument_group('Input')
group.add_argument('file', help='File to be unpacked')
group.add_argument('output', help='Output folder')
args = parser.parse_args()
logging.basicConfig(level=args.log_level)
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))
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
sys.exit(main(args.file,args.output,args.out_pe,args.ignore_fs,args.ignore_pe,args.legacy_fs,args.legacy_pe,args.list))

if __name__ == "__main__":
__main__()

0 comments on commit 104f2c7

Please sign in to comment.