├── .prettierrc.json ├── .gitignore ├── config.example.json ├── src ├── utils │ ├── oemCode.mjs │ ├── index.mjs │ ├── rebootDevice.mjs │ ├── registerShutdownHandler.mjs │ ├── exceptions.mjs │ ├── const.mjs │ ├── misc.mjs │ ├── platform.mjs │ └── exec.mjs ├── Bootloader.mjs ├── Adb.mjs ├── Fastboot.mjs ├── FileDownload.mjs └── Bruteforce.mjs ├── package.json ├── LICENSE ├── scripts ├── unlock-bootloader.mjs ├── lock-bootloader.mjs ├── download-platform-tools.mjs └── bruteforce-bootloader.mjs ├── yarn.lock └── README.md /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | 4 | # some local stuff 5 | misc 6 | 7 | config.json 8 | 9 | saved_state_*.txt 10 | code_*.txt -------------------------------------------------------------------------------- /config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "imei": "Please enter your device's IMEI.", 3 | "autoreboot": true, 4 | "autorebootAfterAttempts": 4 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/oemCode.mjs: -------------------------------------------------------------------------------- 1 | let oemCode = parseInt(args[0]); 2 | 3 | if (!oemCode || oemCode === NaN || String(oemCode).length !== 16) { 4 | console.error("Invalid OEM code specified."); 5 | throw new Error(`Correct command usage: node path/to/script.mjs `); 6 | } 7 | 8 | export { oemCode }; 9 | -------------------------------------------------------------------------------- /src/utils/index.mjs: -------------------------------------------------------------------------------- 1 | export * from "./const.mjs"; 2 | export * from "./exceptions.mjs"; 3 | export * from "./exec.mjs"; 4 | export * from "./misc.mjs"; 5 | export * from "./oemCode.mjs"; 6 | export * from "./platform.mjs"; 7 | export * from "./rebootDevice.mjs"; 8 | export * from "./registerShutdownHandler.mjs"; 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "huawei-bootloader-tools", 3 | "version": "1.0.0", 4 | "main": "unlock.mjs", 5 | "repository": "git@github.com:VottusCode/huawei-honor-bootloader-bruteforce.git", 6 | "author": "Mia ", 7 | "license": "MIT", 8 | "private": false, 9 | "dependencies": { 10 | "better-exec": "^1.0.0", 11 | "node-fetch": "^3.2.3", 12 | "zip-local": "^0.3.5" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/rebootDevice.mjs: -------------------------------------------------------------------------------- 1 | import { Adb } from "../Adb.mjs"; 2 | import { Fastboot } from "../Fastboot.mjs"; 3 | 4 | /** 5 | * Reboot a device using either adb or fastboot, 6 | * depending on which one detects the device. 7 | * 8 | * @param {string} mode 9 | * @return {Promise} 10 | */ 11 | export const rebootDevice = async (mode = "bootloader") => { 12 | if (await Fastboot.hasDevices()) { 13 | return await Fastboot.rebootDevice(mode); 14 | } 15 | 16 | return await Adb.rebootDevice(mode); 17 | }; 18 | -------------------------------------------------------------------------------- /src/utils/registerShutdownHandler.mjs: -------------------------------------------------------------------------------- 1 | import { win } from "./platform.mjs"; 2 | import rl from "readline"; 3 | 4 | /** 5 | * Register a shutdown handler. 6 | * 7 | * The registered shutdown handler will get called 8 | * when Ctrl+C is pressed (SIGINT/SIGTERM) 9 | * 10 | * @param {*} shutdownHandler 11 | */ 12 | export const registerShutdownHandler = (shutdownHandler) => { 13 | // Windows workaround, cause fuck windows, fuck these mfs and their 14 | // bigass corporate offices, fucking bigots sitting with their asses shitting 15 | // out shit code more smelly than their disgusting armpits. 16 | let rline = null; 17 | if (win) { 18 | rline = rl.createInterface({ 19 | input: process.stdin, 20 | output: process.stdout, 21 | }); 22 | } 23 | 24 | ["SIGINT", "SIGTERM"].forEach((signal) => { 25 | if (rline) { 26 | console.log("readline fallback for winsmells"); 27 | rline.on(signal, shutdownHandler); 28 | } 29 | process.on(signal, shutdownHandler); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mia Lilian Morningstar 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 | -------------------------------------------------------------------------------- /src/Bootloader.mjs: -------------------------------------------------------------------------------- 1 | export class Bootloader { 2 | /** 3 | * Send an fastboot oem command 4 | * 5 | * @param {*} command 6 | * @return {boolean} Success 7 | * 8 | * @private 9 | */ 10 | static async _sendOemCommand(command) { 11 | const fastbootOutput = (await Fastboot.command(`oem ${command}`)).toLowerCase().trim(); 12 | 13 | console.log(fastbootOutput); 14 | 15 | if (fastbootOutput.includes(fastbootMessages.commandInvalid)) { 16 | throw new CommandInvalidException("fastboot does not recognize the unlock command."); 17 | } 18 | 19 | if (fastbootOutput.includes(fastbootMessages.oemUnlockFail)) { 20 | return false; 21 | } 22 | 23 | if (fastbootOutput.includes(fastbootMessages.oemSuccess)) { 24 | return true; 25 | } 26 | 27 | if (throwOnUnknownErrors) { 28 | throw new UnknownOutputException(); 29 | } 30 | 31 | return false; 32 | } 33 | 34 | /** 35 | * Unlocks the device's bootloader. 36 | * 37 | * Returns true if it was successful, 38 | * otherwise it returns false (eg. invalid code) 39 | * 40 | * @param {string} code 41 | * @return {Promise} 42 | */ 43 | static async unlock(code) { 44 | return await this._sendOemCommand(`unlock ${code}`); 45 | } 46 | 47 | /** 48 | * Locks the device's bootloader. 49 | * 50 | * Returns true if it was successful, 51 | * otherwise it returns false (eg. invalid code) 52 | * 53 | * @param {string} code 54 | * @return {Promise} 55 | */ 56 | static async relock(code) { 57 | return await this._sendOemCommand(`relock ${code}`); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Adb.mjs: -------------------------------------------------------------------------------- 1 | import { adb, execWithString } from "./utils/index.mjs"; 2 | 3 | export class Adb { 4 | /** 5 | * Executes an adb command. 6 | * 7 | * @param {string} command 8 | * @return {string} Command output 9 | */ 10 | static async command(command = "help") { 11 | return (await execWithString([adb, command].join(" "))) 12 | .replace(/\* daemon not running; starting now at (.*)/g, "") 13 | .replace("* daemon started successfully", ""); 14 | } 15 | 16 | /** 17 | * Checks whether there is any devices detected by adb. 18 | * 19 | * @return {Promise} 20 | */ 21 | static async hasDevices() { 22 | const out = await Adb.command("devices"); 23 | return out.trim().length - "List of devices attached".length >= 1; 24 | } 25 | 26 | /** 27 | * Returns a promise that resolves when at least 28 | * one device is detected by adb. 29 | * 30 | * @return {Promise} 31 | */ 32 | static async waitForDevice() { 33 | const out = (await Adb.command("wait-for-device")).trim().toLowerCase(); 34 | 35 | if (out.startsWith("error")) { 36 | verboseLog("Adb.waitForDevice(): error occurred (can be ok):", out); 37 | verboseLog("Adb.waitForDevice(): waiting for 5 seconds, then attempting again...."); 38 | 39 | wait(5000); 40 | 41 | return await this.adbWaitForDevice(); 42 | } 43 | } 44 | 45 | /** 46 | * Reboots the device and waits until it is detected by adb again. 47 | * 48 | * @return {Promise} 49 | */ 50 | static async rebootDevice(mode = "bootloader") { 51 | await Adb.command(["reboot", mode].join(" ")); 52 | await Adb.waitForDevice(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scripts/unlock-bootloader.mjs: -------------------------------------------------------------------------------- 1 | import { Bootloader } from "../src/Bootloader.mjs"; 2 | import { Fastboot } from "../src/Fastboot.mjs"; 3 | import { skipWarning, wait, rebootDevice, oemCode } from "../src/utils/index.mjs"; 4 | 5 | const run = async () => { 6 | if (!skipWarning) { 7 | console.log( 8 | [ 9 | "", 10 | "This script unlocks your device's bootloader which can be used for rooting,", 11 | "flashing custom ROMs, etc.", 12 | "", 13 | "Authors of this script are not responsible for any kind of damage that may occur", 14 | "by using this script - run at your own risk.", 15 | "", 16 | "Only connect one device at a time, otherwise this script will not work properly.", 17 | "", 18 | "This script will start in 10 seconds - if you don't want to continue, press Ctrl+C.", 19 | "", 20 | ].join("\n") 21 | ); 22 | 23 | await wait(10000); 24 | } 25 | 26 | console.log("Unlock Bootloader - github.com/VottusCode/huawei-honor-bootloader-bruteforce\n"); 27 | 28 | await rebootDevice("bootloader"); 29 | 30 | if (await Fastboot.isUnlocked()) { 31 | console.log( 32 | `The device is already unlocked. Are you sure you didn't want to run lock-bootloader.mjs instead?` 33 | ); 34 | } 35 | 36 | const unlock = await Bootloader.unlock(oemCode); 37 | 38 | if (!unlock) { 39 | console.log("The unlock process has failed. Please try locking manually."); 40 | return; 41 | } 42 | 43 | console.log("The unlock was successful."); 44 | console.log("fastboot getvar unlocked ->", await Fastboot.command("getvar unlocked")); 45 | 46 | console.log("Rebooting deivce..."); 47 | await rebootDevice(); 48 | }; 49 | 50 | run(); 51 | -------------------------------------------------------------------------------- /scripts/lock-bootloader.mjs: -------------------------------------------------------------------------------- 1 | import { Bootloader } from "../src/Bootloader.mjs"; 2 | import { Fastboot } from "../src/Fastboot.mjs"; 3 | import { skipWarning, wait, rebootDevice, oemCode } from "../src/utils/index.mjs"; 4 | 5 | const run = async () => { 6 | if (!skipWarning) { 7 | console.log( 8 | [ 9 | "", 10 | "This script locks your device's bootloader, restricting you from ability", 11 | "to customize your android device. This is usually done when the device is serviced,", 12 | "given or sold to someone else.", 13 | "", 14 | "Authors of this script are not responsible for any kind of damage that may occur", 15 | "by using this script - run at your own risk.", 16 | "", 17 | "Only connect one device at a time, otherwise this script will not work properly.", 18 | "", 19 | "This script will start in 10 seconds - if you don't want to continue, press Ctrl+C.", 20 | "", 21 | ].join("\n") 22 | ); 23 | 24 | await wait(10000); 25 | } 26 | 27 | console.log("Lock Bootloader - github.com/VottusCode/huawei-honor-bootloader-bruteforce\n"); 28 | 29 | await rebootDevice("bootloader"); 30 | 31 | if (await Fastboot.isLocked()) { 32 | console.log( 33 | `The device is already locked. Are you sure you didn't want to run unlock-bootloader.mjs instead?` 34 | ); 35 | } 36 | 37 | const relock = await Bootloader.relock(oemCode); 38 | 39 | if (!relock) { 40 | console.log("The relock process has failed. Please try locking manually."); 41 | return; 42 | } 43 | 44 | console.log("The lock was successful."); 45 | console.log("fastboot getvar unlocked ->", await Fastboot.command("getvar unlocked")); 46 | 47 | console.log("Rebooting deivce..."); 48 | await rebootDevice(); 49 | }; 50 | 51 | run(); 52 | -------------------------------------------------------------------------------- /src/Fastboot.mjs: -------------------------------------------------------------------------------- 1 | import { fastboot } from "./utils/const.mjs"; 2 | import { execWithString } from "./utils/exec.mjs"; 3 | 4 | export class Fastboot { 5 | /** 6 | * Executes a fastboot command. 7 | * 8 | * @param {string} command 9 | * @return {string} Command output 10 | */ 11 | static async command(command = "help") { 12 | return await execWithString([fastboot, command].join(" ")); 13 | } 14 | 15 | /** 16 | * Checks whether there is any devices detected by fastboot. 17 | * 18 | * @return {Promise} 19 | */ 20 | static async hasDevices() { 21 | const out = await Fastboot.command("devices"); 22 | return out.trim().length >= 1; 23 | } 24 | 25 | /** 26 | * Returns a promise that resolves when at least 27 | * one device is detected by fastboot. 28 | * 29 | * This is similar to adb's wait-for-device command, 30 | * however fastboot does not have such command, so this is 31 | * an abstraction that checks for the output of the `devices` command. 32 | * 33 | * @return {Promise} 34 | */ 35 | static async waitForDevice() { 36 | if (!(await this.hasDevices())) { 37 | return await Fastboot.waitForDevice(); 38 | } 39 | 40 | verboseLog("Fastboot.waitForDevice(): device detected, wait finished"); 41 | } 42 | 43 | /** 44 | * Reboots the device and waits until it is detected by fastboot again. 45 | * 46 | * @return {Promise} 47 | */ 48 | static async rebootDevice(mode = "bootloader") { 49 | await Fastboot.command(["reboot", mode].join(" ")); 50 | await Fastboot.waitForDevice(); 51 | } 52 | 53 | static async isLocked() { 54 | return (await Fastboot.command("getvar unlocked")).trim().toLowerCase().includes("no"); 55 | } 56 | 57 | static async isUnlocked() { 58 | return (await Fastboot.command("getvar unlocked")).trim().toLowerCase().includes("yes"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/utils/exceptions.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | export class CommandInvalidException extends Error { 31 | constructor() { 32 | super(); 33 | this.name = "CommandInvalidException"; 34 | } 35 | } 36 | 37 | export class UnknownOutputException extends Error { 38 | constructor() { 39 | super(); 40 | this.name = "UnknownOutputException"; 41 | } 42 | } 43 | 44 | export class CodeNotFoundException extends Error { 45 | constructor() { 46 | super(); 47 | this.name = "CodeNotFoundException"; 48 | } 49 | } 50 | 51 | export class InvalidImeiException extends Error { 52 | constructor() { 53 | super(); 54 | this.name = "InvalidImeiException"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/utils/const.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import path from "path"; 31 | import { fileURLToPath } from "url"; 32 | import { platform, win } from "./platform.mjs"; 33 | 34 | const __filename = fileURLToPath(import.meta.url); 35 | 36 | export const __root = path.join(path.dirname(__filename), "..", ".."); 37 | 38 | export const bin = path.join(__root, "bin"); 39 | 40 | export const adb = path.join(__root, "bin", platform, "platform-tools", win ? "adb.exe" : "adb"); 41 | 42 | export const fastboot = path.join( 43 | __root, 44 | "bin", 45 | platform, 46 | "platform-tools", 47 | win ? "fastboot.exe" : "fastboot" 48 | ); 49 | 50 | export const fastbootMessages = { 51 | oemSuccess: "success", 52 | oemUnlockReboot: "reboot", 53 | oemUnlockFail: "check password failed", 54 | commandInvalid: "command invalid", 55 | }; 56 | -------------------------------------------------------------------------------- /src/utils/misc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import { readFileSync } from "fs"; 31 | import path from "path"; 32 | import { __root } from "./const.mjs"; 33 | 34 | export const wait = (num) => new Promise((res) => setTimeout(() => res(), num)); 35 | 36 | export const rawArgs = process.argv.slice(2); 37 | 38 | export const args = rawArgs.filter((arg) => !arg.startsWith("--")); 39 | 40 | export const params = rawArgs 41 | .filter((arg) => arg.startsWith("--")) 42 | .map((param) => param.substring("--".length, param.length)); 43 | 44 | export const verbose = params.includes("verbose"); 45 | 46 | export const skipWarning = params.includes("skip-warning"); 47 | 48 | export const { 49 | imei, 50 | autorebootAfter = 4, 51 | throwOnUnknownErrors = false, 52 | saveStateAfter = 200, 53 | } = JSON.parse(readFileSync(path.join(__root, "config.json"), "utf-8")); 54 | 55 | export const verboseLog = (...args) => verbose && console.log(...args); 56 | -------------------------------------------------------------------------------- /src/utils/platform.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | export const platformTools = { 31 | win32: "https://dl.google.com/android/repository/platform-tools-latest-windows.zip", 32 | linux: "https://dl.google.com/android/repository/platform-tools-latest-linux.zip", 33 | darwin: "https://dl.google.com/android/repository/platform-tools-latest-darwin.zip", 34 | }; 35 | 36 | let platform = process.platform; 37 | 38 | /** 39 | * Checks the compatibility by makign sure there is a download link 40 | * for the OS running this script. 41 | * 42 | * If not, it shows a warning message and defaults to linux. 43 | */ 44 | if (!Object.keys(platformTools).includes(platform)) { 45 | console.warn( 46 | "You are running on an unsupported OS. You may encounter issues with this script.\n" + 47 | "Linux binaries will be used.\n\n" 48 | ); 49 | 50 | platform = "linux"; 51 | } 52 | 53 | export const win = platform === "win32"; 54 | export const linux = platform === "linux"; 55 | export const darwin = platform === "darwin"; 56 | 57 | export { platform }; 58 | -------------------------------------------------------------------------------- /scripts/download-platform-tools.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import path from "path"; 31 | import zip from "zip-local"; 32 | import { rmSync } from "fs"; 33 | import { FileDownload } from "../src/FileDownload.mjs"; 34 | import { bin, platform, platformTools } from "../src/utils/index.mjs"; 35 | 36 | const run = async () => { 37 | console.log(`downloading binaries for ${platform}...`); 38 | 39 | const downloadLink = platformTools[process.platform]; 40 | const downloadFolder = path.join(bin, platform); 41 | 42 | const filePath = path.join(downloadFolder, "tools.zip"); 43 | 44 | /** 45 | * Downloads the file to bin/{os}/tools.zip 46 | */ 47 | console.log(`downloading platform tools (${downloadLink})...`); 48 | await FileDownload.downloadFile(downloadLink, filePath); 49 | 50 | /** 51 | * Unzips the platform tools. 52 | */ 53 | console.log("unzipping contents..."); 54 | zip.sync.unzip(filePath).save(downloadFolder); 55 | 56 | /** 57 | * Deletes the downloaded file. 58 | */ 59 | console.log("cleaning up..."); 60 | rmSync(filePath); 61 | }; 62 | 63 | run(); 64 | -------------------------------------------------------------------------------- /scripts/bruteforce-bootloader.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import { Bruteforce } from "../src/Bruteforce.mjs"; 31 | import { wait, skipWarning } from "../src/utils/index.mjs"; 32 | 33 | const run = async () => { 34 | if (!skipWarning) { 35 | console.log( 36 | [ 37 | "", 38 | "This script unlocks your deivce's bootloader by bruteforcing the unlock code.", 39 | "Unlocked bootloader can be used for rooting, flashing custom ROMs, etc.", 40 | "", 41 | "Authors of this script are not responsible for any kind of damage that may occur", 42 | "by using this script - run at your own risk.", 43 | "", 44 | "Only connect one device at a time, otherwise this script will not work properly.", 45 | "", 46 | "This script will start in 10 seconds - if you don't want to continue, press Ctrl+C.", 47 | "", 48 | ].join("\n") 49 | ); 50 | 51 | await wait(10000); 52 | } 53 | 54 | console.log( 55 | "Unlock Bootloader (bruteforce) - github.com/VottusCode/huawei-honor-bootloader-bruteforce\n" 56 | ); 57 | await new Bruteforce().start(); 58 | }; 59 | 60 | run(); 61 | -------------------------------------------------------------------------------- /src/utils/exec.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import { exec as _exec } from "child_process"; 31 | 32 | export const execStream = (cmd) => { 33 | const stream = _exec(cmd); 34 | if (!stream.stdout) throw new Error("There's no stdout."); 35 | 36 | return stream; 37 | }; 38 | 39 | export const exec = (cmd, pipeStdout = null) => 40 | new Promise((resolve, reject) => { 41 | const stream = execStream(cmd); 42 | 43 | if (pipeStdout) stream.stdout.pipe(pipeStdout); 44 | 45 | stream.stdout.on("error", reject); 46 | stream.stdout.on("end", resolve); 47 | }); 48 | 49 | export const execWithOut = (cmd, lineCb) => 50 | new Promise((resolve, reject) => { 51 | const stream = execStream(cmd); 52 | 53 | stream.stdout.on("data", lineCb); 54 | stream.stdout.on("error", reject); 55 | stream.stdout.on("end", resolve); 56 | 57 | stream.stderr.on("data", lineCb); 58 | stream.stderr.on("error", reject); 59 | }); 60 | 61 | /** 62 | * @param {string} 63 | * @return {Promise} 64 | */ 65 | export const execWithString = async (cmd) => { 66 | let str = ""; 67 | 68 | await execWithOut(cmd, (line) => { 69 | str += line; 70 | }); 71 | 72 | return str; 73 | }; 74 | -------------------------------------------------------------------------------- /src/FileDownload.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import fetch from "node-fetch"; 31 | import { createWriteStream, mkdirSync, ReadStream, WriteStream } from "fs"; 32 | import path from "path"; 33 | 34 | /** 35 | * Utility class for downloading files. 36 | * 37 | * @class 38 | */ 39 | export class FileDownload { 40 | /** 41 | * Creates a new HTTP request. 42 | * 43 | * @param {string|URL} url 44 | * @return {Promise} 45 | * 46 | * @private 47 | */ 48 | static _createRequest(url) { 49 | if (!(url instanceof URL)) { 50 | try { 51 | url = new URL(url); 52 | } catch { 53 | throw new Error("invalid url"); 54 | } 55 | } 56 | 57 | return fetch(url, { 58 | headers: { 59 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0", 60 | }, 61 | }); 62 | } 63 | 64 | /** 65 | * Promisify stream piping. 66 | * 67 | * @param {ReadStream} from 68 | * @param {WriteStream} where 69 | * @return {Promise} 70 | * 71 | * @private 72 | */ 73 | static _pipe(from, where) { 74 | if (!from || !where) { 75 | throw new TypeError("from and where must be read/write streams."); 76 | } 77 | 78 | return new Promise((res, rej) => { 79 | const stream = from.pipe(where); 80 | 81 | stream.on("finish", () => { 82 | where.close(); 83 | res(); 84 | }); 85 | 86 | stream.on("error", (e) => rej(e)); 87 | }); 88 | } 89 | 90 | /** 91 | * Downloads a file to a specified path. 92 | * 93 | * @param {string} url 94 | * @param {destination} string 95 | * @return {void} 96 | */ 97 | static async downloadFile(url, destination) { 98 | if (!url || !destination) { 99 | throw new TypeError("url and destination must be a string."); 100 | } 101 | 102 | const request = this._createRequest(url); 103 | const response = await request; 104 | 105 | /** 106 | * Ensure the parents folders for the destination file exist. 107 | */ 108 | mkdirSync(path.dirname(destination), { recursive: true }); 109 | 110 | /** 111 | * Pipe the response stream into the new file stream. 112 | */ 113 | await this._pipe(response.body, createWriteStream(destination)); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | async@^1.4.2: 6 | version "1.5.2" 7 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 8 | integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= 9 | 10 | better-exec@^1.0.0: 11 | version "1.0.0" 12 | resolved "https://registry.yarnpkg.com/better-exec/-/better-exec-1.0.0.tgz#2db3df88c3df464e718afb8a8dc88df981f894e9" 13 | integrity sha512-XAIfx/o6F+pdlS5Mp/t4v0twtUzoZvEJyrE2plR8nItgniTjh2G20tLiowNb7MyZ2w0MNPJbWNsUtiypXCVFxQ== 14 | 15 | data-uri-to-buffer@^4.0.0: 16 | version "4.0.0" 17 | resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" 18 | integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== 19 | 20 | fetch-blob@^3.1.2, fetch-blob@^3.1.4: 21 | version "3.1.5" 22 | resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863" 23 | integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg== 24 | dependencies: 25 | node-domexception "^1.0.0" 26 | web-streams-polyfill "^3.0.3" 27 | 28 | formdata-polyfill@^4.0.10: 29 | version "4.0.10" 30 | resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" 31 | integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== 32 | dependencies: 33 | fetch-blob "^3.1.2" 34 | 35 | graceful-fs@^4.1.3: 36 | version "4.2.9" 37 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" 38 | integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== 39 | 40 | jszip@^2.6.1: 41 | version "2.6.1" 42 | resolved "https://registry.yarnpkg.com/jszip/-/jszip-2.6.1.tgz#b88f3a7b2e67a2a048152982c7a3756d9c4828f0" 43 | integrity sha1-uI86ey5noqBIFSmCx6N1bZxIKPA= 44 | dependencies: 45 | pako "~1.0.2" 46 | 47 | node-domexception@^1.0.0: 48 | version "1.0.0" 49 | resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" 50 | integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== 51 | 52 | node-fetch@^3.2.3: 53 | version "3.2.3" 54 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.3.tgz#a03c9cc2044d21d1a021566bd52f080f333719a6" 55 | integrity sha512-AXP18u4pidSZ1xYXRDPY/8jdv3RAozIt/WLNR/MBGZAz+xjtlr90RvCnsvHQRiXyWliZF/CpytExp32UU67/SA== 56 | dependencies: 57 | data-uri-to-buffer "^4.0.0" 58 | fetch-blob "^3.1.4" 59 | formdata-polyfill "^4.0.10" 60 | 61 | pako@~1.0.2: 62 | version "1.0.11" 63 | resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" 64 | integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== 65 | 66 | q@^1.4.1: 67 | version "1.5.1" 68 | resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" 69 | integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= 70 | 71 | web-streams-polyfill@^3.0.3: 72 | version "3.2.0" 73 | resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" 74 | integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== 75 | 76 | zip-local@^0.3.5: 77 | version "0.3.5" 78 | resolved "https://registry.yarnpkg.com/zip-local/-/zip-local-0.3.5.tgz#566c099d0903df1f6bbdd5c060bd62a96a7ad10a" 79 | integrity sha512-GRV3D5TJY+/PqyeRm5CYBs7xVrKTKzljBoEXvocZu0HJ7tPEcgpSOYa2zFIsCZWgKWMuc4U3yMFgFkERGFIB9w== 80 | dependencies: 81 | async "^1.4.2" 82 | graceful-fs "^4.1.3" 83 | jszip "^2.6.1" 84 | q "^1.4.1" 85 | -------------------------------------------------------------------------------- /src/Bruteforce.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Huawei Bootloader Utils by VottusCode 3 | * Set of scripts to help you with bootloader (un)locking. 4 | * 5 | * Warning: The author nor any contributors are responsible for any kind of damage 6 | * or loss of data that may encounter. You may use these scripts at your own risk. 7 | * Do not use unless you know what you're doing. 8 | * 9 | * Copyright (c) 2022 Mia Lilian Morningstar 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | import { readFileSync, writeFileSync } from "fs"; 31 | import { Bootloader } from "./Bootloader.mjs"; 32 | import { Fastboot } from "./Fastboot.mjs"; 33 | import { 34 | registerShutdownHandler, 35 | rebootDevice, 36 | imei, 37 | autorebootAfter, 38 | throwOnUnknownErrors, 39 | saveStateAfter, 40 | verboseLog, 41 | CodeNotFoundException, 42 | CommandInvalidException, 43 | UnknownOutputException, 44 | fastbootMessages, 45 | } from "./utils/index.mjs"; 46 | 47 | export class Bruteforce { 48 | attempt = 0; 49 | currentCode = 1000000000000000; 50 | lastSavedAttempt = 0; 51 | lastRebootAttempt = 0; 52 | 53 | constructor() { 54 | registerShutdownHandler(this.shutdownHandler.bind(this)); 55 | } 56 | 57 | /** 58 | * Returns a last saved state if available, otherwise null is returned. 59 | * 60 | * @return {number|null} 61 | */ 62 | getLastSavedState() { 63 | try { 64 | const content = readFileSync(`saved_state_${imei}.txt`, "utf-8"); 65 | if (!content || content.trim() <= 0) return null; 66 | 67 | verboseLog("getLastSavedState(): found saved state, content:", content); 68 | return Number(content); 69 | } catch { 70 | return null; 71 | } 72 | } 73 | 74 | /** 75 | * Starts the bruteforcing process. 76 | */ 77 | async start() { 78 | verboseLog("start(): called"); 79 | 80 | this.attempt = 0; 81 | this.currentCode = this.getLastSavedState() ?? 1000000000000000; 82 | 83 | /** 84 | * Boot the device into bootloader mode. If the device 85 | * is already in bootloader mode, it reboots it again, just in 86 | * case there were already unlock attempts made (for devices without such 87 | * protection it's not necessary, but it doesn't take much time). 88 | */ 89 | await rebootDevice("bootloader"); 90 | 91 | this.currentCode = this.nextCode(); 92 | await this.bruteforce(); 93 | } 94 | 95 | /** 96 | * If an exit signal is received, the last code is saved before 97 | * exiting the script. 98 | */ 99 | shutdownHandler() { 100 | console.info("Exit signal received, saving last state."); 101 | 102 | this.saveLastState(this.currentCode); 103 | process.exit(); 104 | } 105 | 106 | /** 107 | * This is a recursive function that runs itself until 108 | * it finds the code. It is the heart of this whole script. 109 | * 110 | * @return {Promise} 111 | */ 112 | async bruteforce() { 113 | this.attempt++; 114 | 115 | console.log("\nattempt:", this.attempt, "code:", this.currentCode); 116 | const result = await this.attemptCode(this.currentCode); 117 | 118 | /** 119 | * If true is returned, the current code is the correct unlock code. 120 | * It's printed out, saved and returned and the recursion ends. 121 | */ 122 | if (result) { 123 | console.log("Success! The code is:", result); 124 | this.saveBootloaderCode(this.currentCode); 125 | return this.currentCode; 126 | } 127 | 128 | /** 129 | * If enabled, the device is automatically rebooted every X attempts. 130 | * This is useful for devices that reboot every 5 attempts as a protection. 131 | */ 132 | if (autorebootAfter) { 133 | if (this.attempt - this.lastRebootAttempt >= autorebootAfter) { 134 | this.lastRebootAttempt = this.attempt; 135 | 136 | console.log("autoreboot after", autorebootAfter, "attempts"); 137 | await rebootDevice("bootloader"); 138 | } 139 | } 140 | 141 | /** 142 | * If enabled, the last attempted code is saved every X attempts 143 | * in case the script is interrupted. 144 | * 145 | * Should not be set too low to prevent wearout of the drive. 146 | */ 147 | if (saveStateAfter) { 148 | if (this.attempt - this.lastSavedAttempt >= saveStateAfter - 1) { 149 | this.lastSavedAttempt = this.attempt; 150 | this.saveLastState(this.currentCode); 151 | } 152 | } 153 | 154 | /** 155 | * Creates the next code and runs this function again. 156 | */ 157 | this.currentCode = this.nextCode(); 158 | 159 | /** 160 | * At this point no OEM code was found because all combinations 161 | * were tried and the next one would be too big. 162 | */ 163 | if (this.currentCode >= 10000000000000000) { 164 | throw new CodeNotFoundException("No combination found"); 165 | } 166 | 167 | return await this.bruteforce(); 168 | } 169 | 170 | // todo: tbd 171 | nextCode() { 172 | const nextCode = Math.round( 173 | Number(String(this.currentCode + Math.sqrt(imei) * 1024).padStart(16, "0")) 174 | ); 175 | verboseLog("nextCode(): next code is:", nextCode); 176 | 177 | return nextCode; 178 | } 179 | 180 | /** 181 | * Attempts to use a specified code on the device. 182 | * 183 | * @param {number} code 184 | * @throws {CommandInvalidException} 185 | * @throws {UnknownOutputException} 186 | * @return {Promise} 187 | */ 188 | async attemptCode(code) { 189 | return await Bootloader.unlock(code); 190 | } 191 | 192 | /** 193 | * Saves the bootloader code into a file. 194 | * The file name is code_{imei}.txt 195 | * 196 | * @param {number} code 197 | */ 198 | async saveBootloaderCode(code) { 199 | verboseLog(`saveBootloaderCode(${code}): called, imei: ${imei}`); 200 | 201 | writeFileSync( 202 | `code_${imei}.txt`, 203 | `The bootloader code for the device with IMEI ${imei} is: ${code}` 204 | ); 205 | } 206 | 207 | /** 208 | * Saves the last state. 209 | * The file name is saved_state_{imei}.txt 210 | * 211 | * @param {number} code 212 | */ 213 | async saveLastState(code) { 214 | verboseLog(`saveLastState(${code}): called, imei: ${imei}`); 215 | 216 | writeFileSync(`saved_state_${imei}.txt`, String(code)); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Disclaimer 2 | 3 | Everything you do with these scripts you do at your own risk. Me nor the contributors are responsible 4 | for any damage that may occur. Please go away if you don't know what you're doing. 5 | 6 | # Huawei Bootloader Tools 7 | 8 | This repository contains a set of scripts that can help you (un)lock the bootloader. 9 | 10 | ### Success rate 11 | 12 | The success rate depends on the region where you bought the device. You will have most luck with devices 13 | bought in Europe, as they only contain numbers in their bootloader unlock code. You can try with other regions 14 | as well, but you have way smaller chance of succeeding. 15 | 16 | ### Tested devices 17 | 18 | Devices which have been tested with the original Python script: 19 | 20 | (see: [SkyEmie/huawei-honor-unlock-bootloader#summary](https://github.com/SkyEmie/huawei-honor-unlock-bootloader#summary)) 21 | 22 | - Honor 5x, 8x, 9x 23 | - Honor view 10 and 20 24 | - Honor 10 lite 25 | - Huawei P20 lite 26 | - Huawei Y6 2019 27 | - Huawei P30 28 | 29 | ## :warning: For users who came to bruteforce :warning: 30 | 31 | There may be other (easier/faster) ways to acquire your device's code. 32 | 33 | ### PotatoNV 34 | 35 | https://github.com/mashed-potatoes/PotatoNV 36 | 37 | If your device has a Kirin CPU and you are okay with disassembling the device (usually it's just removing the back of the device and maybe taking off a motherboard shield), you should try PotatoNV first! 38 | 39 | PotatoNV utilizes what is called the "software testpoint". 40 | By shorting it out you boot into a "testpoint" mode which can perform actions like rewriting the unlock code, which is what PotatoNV does. 41 | 42 | It took me around 10 minutes (maybe less) to get the unlock code on my P20 lite (granted, it may take bit longer as my device was opened previously). 43 | 44 | ## Requirements 45 | 46 | - EMUI 9 or lower 47 | 48 | Unfortunetely, with EMUI 10 and later the `oem unlock` command required for bootloader unlocking has been removed by Huawei, meaning 49 | that there is no way for consumers to unlock their device, regardless of whether they do have the code or not. 50 | 51 | - USB Cable 52 | 53 | To connect the device to your computer 54 | 55 | - Internet connection (optional) 56 | 57 | The latest platform tools (containing fastboot and adb required by this script) are downloaded using the `download-platform-tools.mjs` script which required internet connection. To manually include these scripts, put the binaries into {directory_with_scripts}/bin/{distro - win32/linux/darwin}/platform-tools/ 58 | 59 | - Node.js 14 or later (older are not tested) 60 | 61 | These scripts are written in JavaScript which require Node.js to run. 62 | You can download it here: https://nodejs.org/en/ 63 | 64 | ## OS Support 65 | 66 | The scripts are written to support all operating systems, however if the device is not detected, additional drivers may be necessary. 67 | 68 | ## Configuration 69 | 70 | Before running any (un)locking scripts, you must create a config.json file and fill it out. 71 | Do so by renaming `config.example.json` to `config.json` and fill out everything to your needs. 72 | 73 | `imei` (number) - IMEI of your device. You may find it in your device's settings or on your phone's box. 74 | 75 | `autorebootAfter` (number) - How many attempts until the device will be automatically restarted. Most Huawei/Honor devices also have a protection which restarts the phone after few attempts. This would significantly slow down the process and would require your intervention. It's recommended to try without this option (remove this field from the config) and see if such behavior occurs. If so, set it to 1 less than the amount of attempts that trigger the restart (eg. restart after 5 seconds - set to 4 - this is the most usual). 76 | 77 | `saveStateAfter` (number) - How many attempts until the current state (last attempted number) is saved. In case 78 | the script gets interrupted, it can recover from the last saved state. Do not set this number too lower to prevent damaging/wearing out your computer's drive. 79 | 80 | `throwOnUnknownErrors` (boolean) - If an unexpected output from adb/fastboot is received, should the script throw an error (= end)? Usually, this is set to false, but in some cases it might be usefull. 81 | 82 | ### Recommended configuration 83 | 84 | ```json 85 | { 86 | "imei": xxxxxxxxxxxxxxx, 87 | "autorebootAfter": 4, 88 | "throwOnUnknownErrors": false, 89 | "saveStateAfter": 200 90 | } 91 | ``` 92 | 93 | ## Before running the scripts 94 | 95 | Before running the scripts for the first time, make sure to read through these steps: 96 | 97 | ### Installing dependencies 98 | 99 | You need to install all dependencies by the scripts so everything works as intended (or at all). 100 | 101 | You can do that by running this command (Node.js is required): 102 | 103 | ```shell 104 | $ npm install 105 | ``` 106 | 107 | ### Downloading Platform tools 108 | 109 | For using the (un)lock scripts, you must run the `download-platform-tools.mjs` script first. 110 | 111 | ```shell 112 | $ node download-platform-tools.mjs 113 | ``` 114 | 115 | Alternatively, if you're not connected to the internet but have platform tools downloaded, you may 116 | place them here: `{directory_with_scripts}/bin/{distro - win32/linux/darwin}/platform-tools/` 117 | 118 | ### Setting platform tools as executable (Linux/macOS) 119 | 120 | You will only need `adb` and `fastboot`: 121 | 122 | ``` 123 | chmod +x bin/{distro - win32/linux/darwin}/platform-tools/adb 124 | chmod +x bin/{distro - win32/linux/darwin}/platform-tools/fastboot 125 | ``` 126 | 127 | ### Enabling USB debugging 128 | 129 | First, you need to go to Settings > Developer options (not enable by default, to enable, 130 | go to `About phone` and tap the `Build number` field 7 times, then go back and it should appear) 131 | and enable `USB Debugging` and `OEM unlocking`. Then, connect your device to the computer 132 | (if it's not already) and it will ask you to allow usb/adb debugging. Allow it and make sure 133 | to check `Always allow from this computer`. 134 | 135 | ## Running the scripts 136 | 137 | Please make sure that the device is connected already. It doesn't matter 138 | whether if it's in fastboot/bootloader mode or not. 139 | 140 | ### Bruteforce bootloader 141 | 142 | You can run this script by using this command: 143 | 144 | ```shell 145 | $ node scripts/bruteforce-bootloader.mjs 146 | ``` 147 | 148 | It takes a lot of time as the script attempts to bruteforce the code (= attempts lots of combinations). This will take ~~hours~~ days, depends purely on your luck. 149 | 150 | **Warning:** When the correct code is found, the phone is instantly unlocked, which means that 151 | all your data will be **ERASED**. Sometimes the device may prompt you before unlocking the phone, 152 | however make sure to back up your data regardless. 153 | 154 | ### Lock bootloader 155 | 156 | You can run this script by using this command: 157 | 158 | ```shell 159 | $ node scripts/lock-bootloader.mjs 160 | ``` 161 | 162 | This takes usually just few seconds. After that, your device will reboot. 163 | 164 | ### Unlock bootloader 165 | 166 | You can run this script by using this command: 167 | 168 | ```shell 169 | $ node scripts/unlock-bootloader.mjs 170 | ``` 171 | 172 | This takes usually just few seconds. After that, your device will reboot. 173 | 174 | ### Download Platform tools 175 | 176 | You can run this script by using this command: 177 | 178 | ```shell 179 | $ node scripts/download-platform-tools.mjs 180 | ``` 181 | 182 | The platform tools are downloaded into the bin/{os}/platform-tools folder. 183 | 184 | # Credits 185 | 186 | [SkyEmie/huawei-honor-unlock-bootloader](https://github.com/SkyEmie/huawei-honor-unlock-bootloader) - The original Python script from which this project has been forked and rewritten. 187 | 188 |
189 |
190 | 191 | 2022 © Mia Lilian Morningstar – Available under the MIT license, see [LICENSE](LICENSE). 192 | --------------------------------------------------------------------------------