diff --git a/README.md b/README.md index 77ae231..8a886db 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ This Python script extracts the DLL dependencies of a Windows executable file and filters out DLLs that are commonly included with the operating system. +![preview](image-1.png) + ## Features - Identifies all DLLs required by a specified `.exe` file. - Filters out DLLs that are part of the standard Windows OS (e.g., `KERNEL32.dll`, `USER32.dll`). diff --git a/image.png b/image.png new file mode 100644 index 0000000..bc65c84 Binary files /dev/null and b/image.png differ diff --git a/main.py b/main.py index 223e487..09ad063 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,8 @@ import os import pefile -import sys import shutil +import tkinter as tk +from tkinter import filedialog, messagebox, ttk # Common DLLs that come with the OS OS_DLLS = { @@ -11,60 +12,146 @@ OS_DLLS = { "WININET.dll", "WS2_32.dll", "CRYPT32.dll", "OPENGL32.dll" } -def get_dll_dependencies(exe_path): - """Extract DLL dependencies from an executable file.""" - try: - pe = pefile.PE(exe_path) +class DLLExtractorApp: + def __init__(self, root): + self.root = root + self.root.title("DLL Extractor") + self.root.geometry("700x500") + self.root.minsize(700, 500) - # Check for the IMPORT_DIRECTORY entry - if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): - dlls = [entry.dll.decode('utf-8') for entry in pe.DIRECTORY_ENTRY_IMPORT] - return dlls - else: - print("No DLL dependencies found in the executable.") - return [] - except FileNotFoundError: - print(f"File not found: {exe_path}") - return [] - except pefile.PEFormatError: - print(f"The file is not a valid PE executable: {exe_path}") - return [] - except Exception as e: - print(f"An error occurred: {e}") - return [] + # Configure Dark Mode + style = ttk.Style() + style.theme_use("clam") + style.configure("TFrame", background="#2b2b2b") + style.configure("TLabel", background="#2b2b2b", foreground="#ffffff", font=("Arial", 10)) + style.configure("TButton", background="#0078d7", foreground="#ffffff", font=("Arial", 10), borderwidth=1) + style.configure("TEntry", font=("Arial", 10), fieldbackground="#3c3c3c", foreground="#ffffff") + style.configure("TScrollbar", background="#3c3c3c", troughcolor="#3c3c3c", arrowcolor="#ffffff") + style.configure("Listbox", background="#3c3c3c", foreground="#ffffff", font=("Arial", 10)) + style.map("TButton", background=[("active", "#005499")]) + + self.exe_path = tk.StringVar() + self.dependencies = [] + + self.setup_ui() + + def setup_ui(self): + frame = ttk.Frame(self.root, padding="10") + frame.pack(fill=tk.BOTH, expand=True) + + # File Selection + file_frame = ttk.Frame(frame) + file_frame.pack(fill=tk.X, pady=10) + + ttk.Label(file_frame, text="Select EXE File:").grid(row=0, column=0, sticky="w", padx=5) + ttk.Entry(file_frame, textvariable=self.exe_path, width=60, state="readonly").grid(row=0, column=1, padx=5) + ttk.Button(file_frame, text="Browse", command=self.browse_file).grid(row=0, column=2, padx=5) + + # Dependencies List + ttk.Label(frame, text="Non-OS DLL Dependencies:").pack(anchor="w", pady=(10, 5)) + + list_frame = ttk.Frame(frame) + list_frame.pack(fill=tk.BOTH, expand=True, pady=5) + + self.dependencies_list = tk.Listbox(list_frame, height=15, selectmode=tk.SINGLE, bg="#3c3c3c", fg="#ffffff", font=("Arial", 10)) + self.dependencies_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5) + + scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.dependencies_list.yview) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y) + self.dependencies_list.config(yscrollcommand=scrollbar.set) + + # Buttons + button_frame = ttk.Frame(frame) + button_frame.pack(fill=tk.X, pady=(10, 0)) + + ttk.Button(button_frame, text="Extract DLLs", command=self.extract_dlls).pack(side=tk.LEFT, padx=5) + ttk.Button(button_frame, text="Export DLLs", command=self.export_dlls).pack(side=tk.LEFT, padx=5) + + # Log Section + ttk.Label(frame, text="Operation Log:").pack(anchor="w", pady=(10, 5)) + + self.log = tk.Text(frame, height=6, state="disabled", bg="#3c3c3c", fg="#ffffff", font=("Arial", 10), wrap=tk.WORD) + self.log.pack(fill=tk.BOTH, expand=False, padx=5) + + def log_message(self, message): + """Log a message to the log box.""" + self.log.config(state="normal") + self.log.insert(tk.END, message + "\n") + self.log.config(state="disabled") + self.log.see(tk.END) + + def browse_file(self): + """Browse for an executable file.""" + file_path = filedialog.askopenfilename( + title="Select an Executable", + filetypes=[("Executable Files", "*.exe"), ("All Files", "*.*")] + ) + if file_path: + self.exe_path.set(file_path) + self.log_message(f"Selected EXE: {file_path}") + self.get_dll_dependencies(file_path) + + def get_dll_dependencies(self, exe_path): + """Extract DLL dependencies from the selected executable.""" + self.dependencies = [] + self.dependencies_list.delete(0, tk.END) + try: + pe = pefile.PE(exe_path) + if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): + all_dlls = [entry.dll.decode('utf-8') for entry in pe.DIRECTORY_ENTRY_IMPORT] + self.dependencies = [dll for dll in all_dlls if dll.upper() not in OS_DLLS] + self.log_message("Extracted DLL dependencies.") + for dll in self.dependencies: + self.dependencies_list.insert(tk.END, dll) + else: + self.log_message("No DLL dependencies found.") + except Exception as e: + messagebox.showerror("Error", f"Failed to read the executable: {e}") + self.log_message(f"Error reading executable: {e}") + + def extract_dlls(self): + """Extract and copy found DLLs to a folder.""" + if not self.dependencies: + messagebox.showwarning("Warning", "No DLL dependencies to extract.") + return + + folder = "found_dlls" + os.makedirs(folder, exist_ok=True) + copied_dlls = [] + for dll in self.dependencies: + for path in os.environ['PATH'].split(os.pathsep): + dll_path = os.path.join(path, dll) + if os.path.exists(dll_path): + shutil.copy(dll_path, os.path.join(folder, dll)) + copied_dlls.append(dll) + break + + self.log_message(f"Copied {len(copied_dlls)} DLLs to {folder}.") + messagebox.showinfo("Success", f"Copied {len(copied_dlls)} DLLs to {folder}.") + + def export_dlls(self): + """Export DLL dependencies to a file.""" + if not self.dependencies: + messagebox.showwarning("Warning", "No DLL dependencies to export.") + return + + export_file = filedialog.asksaveasfilename( + title="Export DLL List", + defaultextension=".txt", + filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")] + ) + if export_file: + try: + with open(export_file, "w") as f: + f.write("\n".join(self.dependencies)) + self.log_message(f"Exported DLL dependencies to {export_file}.") + messagebox.showinfo("Success", f"Exported DLL dependencies to {export_file}.") + except Exception as e: + messagebox.showerror("Error", f"Failed to export DLL dependencies: {e}") + self.log_message(f"Error exporting DLL dependencies: {e}") -def find_and_copy_dlls(dlls, output_folder): - """Find DLL files and copy them to the output folder.""" - os.makedirs(output_folder, exist_ok=True) - found = [] - for dll in dlls: - for path in os.environ['PATH'].split(os.pathsep): - dll_path = os.path.join(path, dll) - if os.path.exists(dll_path): - shutil.copy(dll_path, os.path.join(output_folder, dll)) - found.append(dll) - break - return found if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python get_dll_dependencies.py ") - else: - exe_path = sys.argv[1] - dependencies = get_dll_dependencies(exe_path) - - if dependencies: - non_os_dependencies = [dll for dll in dependencies if dll.upper() not in OS_DLLS] - print("Non-OS DLL Dependencies:") - for dll in non_os_dependencies: - print(f" {dll}") - - if non_os_dependencies: - found_dlls = find_and_copy_dlls(non_os_dependencies, "found_dlls") - print("\nCopied DLLs:") - for dll in found_dlls: - print(f" {dll}") - else: - print("No non-OS DLL dependencies found.") - else: - print("No DLL dependencies found or failed to retrieve dependencies.") + root = tk.Tk() + app = DLLExtractorApp(root) + root.mainloop()