Last active
March 10, 2025 04:22
-
-
Save alex-spataru/b187bdc3d987a0fcb1cae4e9b17c0e9e to your computer and use it in GitHub Desktop.
Brute-force OEM code/password guesser for Android phones
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Based on https://github.com/haexhub/huaweiBootloaderHack | |
# | |
# Usage: | |
# python android-bootloader-unlock.py <YOUR_IMEI_CODE> | |
# | |
# Please enable USB debugging on your phone before using this | |
# tool, hope it helps you :) | |
# | |
import sys | |
import json | |
import math | |
import subprocess | |
def get_attempts(): | |
''' | |
Reads the list of failed passwords and returns them as a set. | |
In case the attempts.json file does not exist (or is invalid), | |
this function will return an empty set. | |
''' | |
try: | |
with open('attempts.json', 'r') as file: | |
attempts = json.load(file) | |
if type(attempts) == list: | |
return set(attempts) | |
else: | |
return set([]) | |
except: | |
return set([]) | |
def save_attempts(attempts = []): | |
''' | |
Writes the current failed password attempts to an external file, | |
which is later used to continue trying even more passwords... | |
''' | |
with open('attempts.json', 'w') as file: | |
json.dump(attempts, file) | |
def string_to_int_array(n): | |
''' | |
Converts an array of characters to an array of integers | |
''' | |
return [int(d) for d in str(n)] | |
def luhn_checksum(imei): | |
''' | |
Obtains the checksum of the IMEI string using Luhn's algorithm | |
''' | |
digits = string_to_int_array(imei) | |
odd_digits = digits[-1::-2] | |
even_digits = digits[-2::-2] | |
checksum = 0 | |
checksum = sum(odd_digits) | |
for digit in even_digits: | |
checksum += sum(string_to_int_array(digit * 2)) | |
return checksum % 10 | |
def unlock_bootloader(imei, checksum, failed_attempts = set([])): | |
''' | |
Generates new OEM codes/passwords and tries running "fastboot oem unlock" | |
until it succeeds. | |
@note The function automatically reboots the Android device every 4 | |
failed attempts in order to avoid a lock-up. | |
''' | |
# Initialize parameters | |
unlocked = False | |
attempt_count = 0 | |
oem_code = 1000000000000000 | |
# Execute loop until we get it right | |
while not unlocked: | |
# Increment attempt count | |
attempt_count += 1 | |
# Generate new OEM code/password if needed | |
while oem_code in failed_attempts: | |
oem_code += int(checksum + math.sqrt(imei) * 1024) | |
# Print status | |
print(f'Shot {len(failed_attempts) + 1} with OEM code/password {oem_code}...') | |
# Try to unlock the bootloader | |
answer = subprocess.run( | |
['fastboot', 'oem', 'unlock', str(oem_code)], | |
stdout = subprocess.DEVNULL, | |
stderr = subprocess.DEVNULL | |
) | |
# Check if bootloader unlock succeeded | |
if answer.returncode == 0: | |
unlocked = True | |
return oem_code | |
# Bootloader unlock failed, register failed attempt code | |
else: | |
failed_attempts.add(oem_code) | |
# Reboot device every 4 failed attempts | |
if attempt_count >= 4: | |
# Save current attempts to JSON file | |
attempt_count = 0 | |
save_attempts(list(failed_attempts)) | |
# Reboot device | |
print('Restarting device...\n') | |
subprocess.run( | |
['fastboot', 'reboot', 'bootloader'], | |
stdout = subprocess.DEVNULL, | |
stderr = subprocess.DEVNULL | |
) | |
# Generate new OEM password attempt | |
oem_code += int(checksum + math.sqrt(imei) * 1024) | |
if __name__ == '__main__': | |
''' | |
Main entry point function of the application | |
''' | |
# Get IMEI code from the user | |
args = sys.argv | |
if len(sys.argv) > 1: | |
imei = int(sys.argv[1]) | |
else: | |
imei = int(input('Please type your IMEI code: ')) | |
# Get Luhn checksum of the IMEI | |
checksum = luhn_checksum(imei) | |
# Print IMEI & checksum | |
print(f'Using IMEI: {imei}') | |
print(f'IMEI checksum (Luhn): {checksum}') | |
# Reboot device into fastboot | |
print('Rebooting device...') | |
subprocess.run( | |
['adb', 'reboot', 'bootloader'], | |
stdout = subprocess.DEVNULL, | |
stderr = subprocess.DEVNULL | |
) | |
# Wait for user confirmation | |
input('Press any key when your device is in fastboot mode...\n') | |
# Read failed attempts & continue brute force attack | |
failed_attempts = get_attempts() | |
oem_code = unlock_bootloader(imei, checksum, failed_attempts) | |
# Validate unlocked status & reboot device | |
subprocess.run(['fastboot', 'getvar', 'unlocked']) | |
subprocess.run(['fastboot', 'reboot']) | |
# Print obtained key | |
print('\n\n') | |
print(f'Device unlocked! OEM code/password: {oem_code}') | |
sys.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have a Zebra TC510K, with no SIM, so there is no IMEI. Only a serial-number with 14 digits. Which value should I use for IMEI then?