Exe_unpacker / app.py
euler314's picture
Update app.py
c99b4e2 verified
raw
history blame
8.99 kB
import streamlit as st
import os
import zipfile
import tempfile
import pefile
import shutil
from pathlib import Path
st.set_page_config(page_title="File Analyzer", page_icon="πŸ”")
st.title("File Analysis Tool")
st.markdown("""
This tool allows you to analyze various file types:
- Extract and view contents of .zip files
- Unpack .exe files to examine their contents
- View information about .dll files
""")
# No size limit
def unpack_exe(file_path, output_dir):
"""Extract information from an EXE file using pefile"""
try:
pe = pefile.PE(file_path)
# Create a basic info dictionary
info = {
"Machine": hex(pe.FILE_HEADER.Machine),
"TimeDateStamp": pe.FILE_HEADER.TimeDateStamp,
"NumberOfSections": pe.FILE_HEADER.NumberOfSections,
"Sections": []
}
# Get section information
for section in pe.sections:
section_name = section.Name.decode('utf-8', errors='ignore').strip('\x00')
info["Sections"].append({
"Name": section_name,
"VirtualAddress": hex(section.VirtualAddress),
"SizeOfRawData": section.SizeOfRawData,
"Entropy": section.get_entropy()
})
# Get imports
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
info["Imports"] = []
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll_name = entry.dll.decode('utf-8', errors='ignore')
imports = []
for imp in entry.imports:
if imp.name:
imports.append(imp.name.decode('utf-8', errors='ignore'))
info["Imports"].append({
"DLL": dll_name,
"Functions": imports
})
# Extract resources if present
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
resource_dir = os.path.join(output_dir, "resources")
os.makedirs(resource_dir, exist_ok=True)
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if hasattr(resource_type, 'directory'):
for resource_id in resource_type.directory.entries:
if hasattr(resource_id, 'directory'):
for resource_lang in resource_id.directory.entries:
data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size)
resource_filename = f"resource_{resource_type.id}_{resource_id.id}_{resource_lang.id}"
with open(os.path.join(resource_dir, resource_filename), 'wb') as f:
f.write(data)
return info
except Exception as e:
return {"Error": str(e)}
def analyze_dll(file_path):
"""Extract information from a DLL file using pefile"""
try:
pe = pefile.PE(file_path)
# Create a basic info dictionary
info = {
"Machine": hex(pe.FILE_HEADER.Machine),
"TimeDateStamp": pe.FILE_HEADER.TimeDateStamp,
"NumberOfSections": pe.FILE_HEADER.NumberOfSections,
"Characteristics": hex(pe.FILE_HEADER.Characteristics),
"DllCharacteristics": hex(pe.OPTIONAL_HEADER.DllCharacteristics),
"Sections": []
}
# Get section information
for section in pe.sections:
section_name = section.Name.decode('utf-8', errors='ignore').strip('\x00')
info["Sections"].append({
"Name": section_name,
"VirtualAddress": hex(section.VirtualAddress),
"SizeOfRawData": section.SizeOfRawData,
"Entropy": section.get_entropy()
})
# Get exports if present
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
info["Exports"] = []
for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
if exp.name:
info["Exports"].append(exp.name.decode('utf-8', errors='ignore'))
# Get imports
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
info["Imports"] = []
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll_name = entry.dll.decode('utf-8', errors='ignore')
imports = []
for imp in entry.imports:
if imp.name:
imports.append(imp.name.decode('utf-8', errors='ignore'))
info["Imports"].append({
"DLL": dll_name,
"Functions": imports
})
return info
except Exception as e:
return {"Error": str(e)}
def process_zip_file(file_path, temp_dir):
"""Process a ZIP file and extract its contents"""
try:
with zipfile.ZipFile(file_path, 'r') as zip_ref:
# Get file list before extraction
file_list = zip_ref.namelist()
# Extract to temp directory
zip_ref.extractall(temp_dir)
# Check for nested executables
nested_files = {}
for root, _, files in os.walk(temp_dir):
for file in files:
full_path = os.path.join(root, file)
rel_path = os.path.relpath(full_path, temp_dir)
if file.endswith('.exe'):
exe_output_dir = os.path.join(temp_dir, f"{file}_unpacked")
os.makedirs(exe_output_dir, exist_ok=True)
nested_files[rel_path] = {
'type': 'exe',
'info': unpack_exe(full_path, exe_output_dir)
}
elif file.endswith('.dll'):
nested_files[rel_path] = {
'type': 'dll',
'info': analyze_dll(full_path)
}
return {
'file_list': file_list,
'nested_files': nested_files
}
except Exception as e:
return {'error': str(e)}
# Main app logic
uploaded_file = st.file_uploader("Upload a file (.zip, .exe, or .dll)", type=["zip", "exe", "dll"])
if uploaded_file is not None:
# Process file without size check
with tempfile.TemporaryDirectory() as temp_dir:
# Save the uploaded file to the temporary directory
file_path = os.path.join(temp_dir, uploaded_file.name)
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
st.success(f"File uploaded: {uploaded_file.name}")
# Process based on file type
if uploaded_file.name.lower().endswith('.zip'):
st.subheader("ZIP File Contents")
output_dir = os.path.join(temp_dir, "extracted")
os.makedirs(output_dir, exist_ok=True)
result = process_zip_file(file_path, output_dir)
if 'error' in result:
st.error(f"Error processing ZIP file: {result['error']}")
else:
with st.expander("ZIP Contents", expanded=True):
st.write(f"Total files: {len(result['file_list'])}")
st.json(result['file_list'])
if result['nested_files']:
st.subheader("Detected Executable Files")
for file_path, file_info in result['nested_files'].items():
with st.expander(f"{file_path} ({file_info['type'].upper()})"):
st.json(file_info['info'])
elif uploaded_file.name.lower().endswith('.exe'):
st.subheader("EXE File Analysis")
output_dir = os.path.join(temp_dir, "exe_unpacked")
os.makedirs(output_dir, exist_ok=True)
try:
exe_info = unpack_exe(file_path, output_dir)
st.json(exe_info)
# Check if resources were extracted
resource_dir = os.path.join(output_dir, "resources")
if os.path.exists(resource_dir) and os.listdir(resource_dir):
st.subheader("Extracted Resources")
for resource_file in os.listdir(resource_dir):
st.text(f"Resource: {resource_file}")
except Exception as e:
st.error(f"Error analyzing EXE file: {str(e)}")
elif uploaded_file.name.lower().endswith('.dll'):
st.subheader("DLL File Information")
try:
dll_info = analyze_dll(file_path)
st.json(dll_info)
except Exception as e:
st.error(f"Error analyzing DLL file: {str(e)}")