77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
### Ne marche que sur LINUX, puisque dépendant de ELF.
|
|
|
|
import subprocess
|
|
import sys
|
|
import string
|
|
from pwn import context, ELF
|
|
|
|
context.binary = './crackme_esdi'
|
|
|
|
def auto_extract_candidates(binary_path):
|
|
"""
|
|
Analyse le binaire et extrait TOUTES les suites d'octets qui,
|
|
après un XOR 0x42, donnent une chaîne imprimable de 14 caractères.
|
|
"""
|
|
candidates = []
|
|
try:
|
|
elf = ELF(binary_path, checksec=False)
|
|
rodata = elf.get_section_by_name('.rodata')
|
|
data_bytes = rodata.data()
|
|
except Exception:
|
|
with open(binary_path, 'rb') as f:
|
|
data_bytes = f.read()
|
|
|
|
password_length = 14
|
|
xor_key = 0x42
|
|
printable_charset = set(string.printable.encode('ascii'))
|
|
|
|
# Correction du Off-By-One : ajout du + 1 pour inclure le dernier bloc du fichier
|
|
for i in range(len(data_bytes) - password_length + 1):
|
|
window = data_bytes[i : i + password_length]
|
|
candidate_bytes = bytes(b ^ xor_key for b in window)
|
|
|
|
# Validation des caractères ASCII lisibles
|
|
if all(b in printable_charset and 32 <= b <= 126 for b in candidate_bytes):
|
|
try:
|
|
candidate_str = candidate_bytes.decode('ascii').strip()
|
|
if len(candidate_str) == password_length:
|
|
candidates.append(candidate_str)
|
|
except UnicodeDecodeError:
|
|
continue
|
|
|
|
return list(set(candidates))
|
|
|
|
def verify_and_run(binary_path, password):
|
|
"""
|
|
Exécute le binaire avec la valeur trouvée et valide la sortie.
|
|
"""
|
|
result = subprocess.run(
|
|
[binary_path, password],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
output = result.stdout + result.stderr
|
|
|
|
if "Incorrect length" not in output and "Checksum failed" not in output:
|
|
return True
|
|
return False
|
|
|
|
def main():
|
|
binary_path = './crackme_esdi'
|
|
print(f"[*] Démarrage de la résolution automatique de {binary_path}...")
|
|
|
|
candidates = auto_extract_candidates(binary_path)
|
|
print(f"[+] {len(candidates)} candidats potentiels identifiés.")
|
|
|
|
print("[*] Validation dynamique des candidats via exécution...")
|
|
for candidate in candidates:
|
|
if verify_and_run(binary_path, candidate):
|
|
print(f"[+] Crackme résolu : valeur = {candidate}")
|
|
sys.exit(0)
|
|
|
|
print("[-] Échec : Aucun candidat n'a réussi à déverrouiller le binaire.")
|
|
sys.exit(1)
|
|
|
|
if __name__ == '__main__':
|
|
main() |