#!/usr/bin/env python3
"""
Memory dump script to find hardcoded password in peace.com
Analyzes the binary to find password comparison logic and extract the password
"""

import sys

def find_password_in_memory(binary_path):
    """Read binary and search for password using multiple techniques"""
    
    with open(binary_path, 'rb') as f:
        data = f.read()
    
    print("[*] Loaded binary: {} bytes".format(len(data)))
    print()
    
    # Method 1: Look for 4-char sequences near comparison code (0xEC0-0xF40)
    print("=" * 60)
    print("METHOD 1: Analyzing password comparison area (0xEC0-0xF40)")
    print("=" * 60)
    
    comp_start = 0xEC0
    comp_end = 0xF40
    
    # The comparison pushes addresses 0xD3B8, 0xD3B9, 0xD3BA, 0xD3BB
    # These are 4 individual byte addresses - the password!
    print("\n[*] Password bytes from comparison logic:")
    password_chars = []
    for offset in [0xD3B8, 0xD3B9, 0xD3BA, 0xD3BB]:
        byte = data[offset]
        char = chr(byte) if 0x20 <= byte <= 0x7E else '.'
        password_chars.append(char)
        print("  Offset 0x{:04X}: 0x{:02X} = '{}'".format(offset, byte, char))
    
    pwd1 = ''.join(password_chars)
    print("\n[+] Extracted password: '{}'".format(pwd1))
    
    # Method 2: Search for null-terminated 4-char strings
    print("\n" + "=" * 60)
    print("METHOD 2: Searching for NULL-terminated 4-char strings")
    print("=" * 60)
    
    candidates = []
    for i in range(0xC000, 0xE000):
        if i + 5 >= len(data):
            break
            
        # Check if we have 4 lowercase letters followed by null or space
        if (0x61 <= data[i] <= 0x7A and 
            0x61 <= data[i+1] <= 0x7A and 
            0x61 <= data[i+2] <= 0x7A and 
            0x61 <= data[i+3] <= 0x7A):
            
            before = data[i-1] if i > 0 else 0
            after = data[i+4]
            
            # Look for isolated strings (null, unprintable, or space before/after)
            if (before == 0 or before > 0x7E) and (after == 0 or after > 0x7E or after == 0x20):
                word = data[i:i+4].decode('ascii')
                candidates.append((i, word))
                print("  Found '{}' at offset 0x{:04X}".format(word, i))
    
    if candidates:
        print("\n[+] Most likely password: '{}'".format(candidates[0][1]))
    
    # Method 3: Extract strings near "ACCESS GRANTED"
    print("\n" + "=" * 60)
    print("METHOD 3: Analyzing area near 'ACCESS GRANTED' message")
    print("=" * 60)
    
    access_granted = b'ACCESS GRANTED'
    idx = data.find(access_granted)
    if idx != -1:
        print("\n[*] Found 'ACCESS GRANTED' at offset 0x{:04X}".format(idx))
        
        # Check 200 bytes before for password
        start = max(0, idx - 200)
        region = data[start:idx]
        
        print("\n[*] Searching for 4-letter words in nearby region...")
        for i in range(len(region) - 3):
            if all(0x61 <= region[i+j] <= 0x7A for j in range(4)):
                word = region[i:i+4].decode('ascii')
                offset = start + i
                print("  '{}' at 0x{:04X}".format(word, offset))
    
    # Method 4: Look at data section after code
    print("\n" + "=" * 60)
    print("METHOD 4: Scanning data section (0xC000-0xD000)")
    print("=" * 60)
    
    # Common CTF/Megadeth related passwords
    common_passwords = [
        b'rust', b'holy', b'wars', b'take', b'dawn', b'five', 
        b'kind', b'nuke', b'dave', b'mega', b'deth', b'peace',
        b'hangar', b'tornado', b'poison', b'vic', b'mustaine'
    ]
    
    print("\n[*] Checking for common passwords in binary:")
    for pwd in common_passwords:
        idx = data.find(pwd)
        if idx != -1:
            # Check context
            before = data[idx-5:idx].hex() if idx >= 5 else ''
            after = data[idx+len(pwd):idx+len(pwd)+5].hex() if idx+len(pwd)+5 < len(data) else ''
            
            # Check if it's isolated (likely a password, not part of string)
            before_byte = data[idx-1] if idx > 0 else 0
            after_byte = data[idx+len(pwd)] if idx+len(pwd) < len(data) else 0
            
            isolated = (before_byte == 0 or before_byte > 0x7E) and (after_byte == 0 or after_byte > 0x7E)
            
            status = "[ISOLATED]" if isolated else "[in string]"
            print("  {} '{}' at 0x{:04X} {}".format(status, pwd.decode(), idx, 
                  "LIKELY PASSWORD!" if isolated and len(pwd) == 4 else ""))
    
    # Method 5: Disassembly hints - look at pushed addresses
    print("\n" + "=" * 60)
    print("METHOD 5: Following comparison addresses")
    print("=" * 60)
    
    # At 0xED2, 0xEE2, 0xF02, 0xF22 the code pushes password char addresses
    # Let's read what's being pushed
    push_locations = [0xED2, 0xEE2, 0xF02, 0xF22]
    
    print("\n[*] Extracting pushed address values from comparison code:")
    pushed_addresses = []
    for loc in push_locations:
        # Read the 16-bit address being pushed (little endian)
        if loc + 2 < len(data):
            # Skip the push opcode, read the address
            addr_low = data[loc + 1]
            addr_high = data[loc + 2]
            addr = (addr_high << 8) | addr_low
            pushed_addresses.append(addr)
            print("  At 0x{:04X}: pushes address 0x{:04X}".format(loc, addr))
    
    if pushed_addresses:
        print("\n[*] Reading characters at pushed addresses:")
        password = []
        for addr in pushed_addresses:
            if addr < len(data):
                byte = data[addr]
                char = chr(byte) if 0x20 <= byte <= 0x7E else '?'
                password.append(char)
                print("  0x{:04X}: 0x{:02X} = '{}'".format(addr, byte, char))
        
        final_pwd = ''.join(password)
        print("\n" + "=" * 60)
        print("[+] FINAL PASSWORD: '{}'".format(final_pwd))
        print("=" * 60)
        return final_pwd
    
    return pwd1

if __name__ == '__main__':
    binary = r'C:\Users\Roose\Downloads\peace.com'
    
    print("""
╔════════════════════════════════════════════════════════════╗
║  PEACE.COM Password Memory Dump & Analysis Tool           ║
║  Rust In Peace - Post-Apocalyptic Disk Manager CTF        ║
╚════════════════════════════════════════════════════════════╝
""")
    
    try:
        password = find_password_in_memory(binary)
        
        print("\n" + "=" * 60)
        print("RECOMMENDED PASSWORDS TO TRY:")
        print("=" * 60)
        print("1. {}".format(password))
        print("2. kind")
        print("3. rust")
        print("4. holy")
        print("5. wars")
        print("6. nuke")
        
    except FileNotFoundError:
        print("[!] Error: Could not find peace.com")
        sys.exit(1)
    except Exception as e:
        print("[!] Error: {}".format(e))
        sys.exit(1)
