From c93ee314f5cb6ca326a30d04c8856af8ab45b180 Mon Sep 17 00:00:00 2001 From: CLARATION Date: Sat, 27 Jun 2026 19:48:40 -0700 Subject: [PATCH] feat(windows): bundle libusbK driver --- .github/workflows/build.yml | 15 +++- .gitignore | 1 + CMakeLists.txt | 55 ++++++++---- Makefile | 8 ++ src/m8/run.c | 1 + src/main.cpp | 41 +++++++-- src/usb/driver.c | 161 ++++++++++++++++++++++++++++++++++++ src/usb/driver.h | 22 +++++ src/usb/driver/.gitkeep | 0 src/utils.c | 23 +++++- 10 files changed, 304 insertions(+), 23 deletions(-) create mode 100644 src/usb/driver.c create mode 100644 src/usb/driver.h delete mode 100644 src/usb/driver/.gitkeep diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e903488..92fae0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -159,6 +159,12 @@ jobs: runs-on: windows-latest needs: [build-pongo, build-ramdisk] + env: + LIBUSBK_VERSION: libusbK-3.0.5.16-bin.7z + LIBUSBK_URL: https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/usb-travis/${{ env.LIBUSBK_VERSION }} + LIBUSBK_WDFCOINSTALLER: libusbK/bin/sys/WdfCoInstaller01009.dll + LIBUSBK_WDFCOINSTALLER_RENAMED: libusbK/bin/sys/WdfCoInstaller1011.dll + steps: - uses: actions/checkout@v4 @@ -168,12 +174,19 @@ jobs: name: pongo path: payloads/ - - name : Download embedded artifacts + - name: Download embedded artifacts uses: actions/download-artifact@v4 with: name: embedded path: payloads/ + - name: Download libusbK drivers + run: | + curl -LO $LIBUSBK_URL + 7z x $LIBUSBK_VERSION -olibusbK + # libwdi doesn't like "9"s in the filename lol + mv $LIBUSBK_WDFCOINSTALLER $LIBUSBK_WDFCOINSTALLER_RENAMED + - name: Set up MSYS2 uses: msys2/setup-msys2@v2 with: diff --git a/.gitignore b/.gitignore index 365f1f7..3b164ff 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ payloads/Pongo.bin payloads/checkra1n-kpf-pongo payloads/ramdisk.dmg payloads/binpack.dmg +libusbK/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a6d300a..cda112f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) option(WITH_GUI "Build with wxWidgets GUI" OFF) option(WITH_STATIC "Build with static wxWidgets / deps" OFF) +option(WITH_TUI "Build with TUI" OFF) +option(WITH_ARTIFACTS "Build with embedded artifacts" OFF) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -179,25 +181,44 @@ if(WITH_STATIC) ) endif() + if(MINGW) + #========================= + # libwdi + #========================= + ExternalProject_Add(libwdi_ep + GIT_REPOSITORY https://github.com/pbatard/libwdi.git + GIT_TAG v1.5.1 + UPDATE_COMMAND "" + + CONFIGURE_COMMAND + ${PKG_ENV} + sh -lc "./bootstrap.sh && ./configure --prefix=${DEPS_PREFIX} --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --disable-32bit --with-wdfver=1011 --with-libusbk=${CMAKE_SOURCE_DIR}/libusbK/bin" + + BUILD_COMMAND make -j + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + ) + endif() + if(NOT MINGW) - # ========================= - # mbedTLS - # ========================= - ExternalProject_Add(mbedtls_ep - GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git - GIT_TAG mbedtls-3.5.2 - UPDATE_COMMAND "" + # ========================= + # mbedTLS + # ========================= + ExternalProject_Add(mbedtls_ep + GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git + GIT_TAG mbedtls-3.5.2 + UPDATE_COMMAND "" - PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patches/mbedtls/0001-Allow-empty-x509-cert-issuer.patch + PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patches/mbedtls/0001-Allow-empty-x509-cert-issuer.patch - CMAKE_ARGS - -DCMAKE_INSTALL_PREFIX=${DEPS_PREFIX} - -DENABLE_TESTING=OFF - -DENABLE_PROGRAMS=OFF - -DBUILD_SHARED_LIBS=OFF + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${DEPS_PREFIX} + -DENABLE_TESTING=OFF + -DENABLE_PROGRAMS=OFF + -DBUILD_SHARED_LIBS=OFF - INSTALL_DIR ${DEPS_PREFIX} - ) + INSTALL_DIR ${DEPS_PREFIX} + ) endif() if(LINUX OR MINGW) @@ -406,6 +427,8 @@ if(WITH_STATIC) if(NOT MINGW) add_dependencies(palera1n mbedtls_ep) + else() + add_dependencies(palera1n libwdi_ep) endif() if(LINUX) @@ -436,6 +459,7 @@ if(WITH_STATIC) plist-2.0 imobiledevice-glue-1.0 usb-1.0 + libwdi ) set(DLLS @@ -450,6 +474,7 @@ if(WITH_STATIC) libplist-2.0.dll libusbmuxd-2.0.dll libusb-1.0.dll + libwdi.dll ) execute_process( diff --git a/Makefile b/Makefile index 9243605..670fcc8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ .PHONY: payloads palera1n palera1n_xcode clean WITH_GUI ?= 0 +WITH_TUI ?= 0 +WITH_ARTIFACTS ?= 1 WITH_STATIC ?= 0 BUILD_TYPE ?= Debug @@ -28,6 +30,8 @@ palera1n: payloads @cmake -S . -B build \ -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \ -DWITH_GUI=$(WITH_GUI) \ + -DWITH_TUI=$(WITH_TUI) \ + -DWITH_ARTIFACTS=$(WITH_ARTIFACTS) \ -DWITH_STATIC=$(WITH_STATIC) && \ cmake --build build @@ -36,6 +40,8 @@ palera1n_xcode: payloads -G Xcode \ -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \ -DWITH_GUI=$(WITH_GUI) \ + -DWITH_TUI=$(WITH_TUI) \ + -DWITH_ARTIFACTS=$(WITH_ARTIFACTS) \ -DWITH_STATIC=$(WITH_STATIC) palera1n_mingw: payloads @@ -43,6 +49,8 @@ palera1n_mingw: payloads -G "MinGW Makefiles" \ -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \ -DWITH_GUI=$(WITH_GUI) \ + -DWITH_TUI=$(WITH_TUI) \ + -DWITH_ARTIFACTS=$(WITH_ARTIFACTS) \ -DWITH_STATIC=$(WITH_STATIC) && \ cmake --build build diff --git a/src/m8/run.c b/src/m8/run.c index 3d7ee99..45b91ab 100644 --- a/src/m8/run.c +++ b/src/m8/run.c @@ -11,6 +11,7 @@ #include "../utils.h" #include "../usb/shim.h" #include "../usb/pongo_helper.h" +#include "../usb/driver/driver.h" #include "checkm8.h" #include "dfu.h" diff --git a/src/main.cpp b/src/main.cpp index 7a96182..5de46ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,6 +13,9 @@ #include "utils.h" #include "paleinfo.h" +#ifdef _WIN32 +# include "usb/driver.h" +#endif void print_credits() { printf( @@ -21,16 +24,16 @@ void print_credits() { "::\n" ":: (c) 2026\n" "::\n" - ":: ======== Made by ======== ::\n" + ":: ======== Made by =======>\n" ":: Made by: asdfugil, kok3shidoll, claration, mineek\n" ":: nekohaxx, plooshi, staturnz\n" - ":: ======== Thanks to ======== ::\n" + ":: ======== Thanks to =======>\n" ":: Thanks to: llsc12, itsnebulalol, lrdsnow, kirb, ehilwyma\n" ":: opa334, 0x7ff, sbingner, nikias (libimobiledevice)\n" ":: dedbeddedbed, tihmstar\n" ":: Checkra1n (Siguza, axi0mx, littlelailo et al.)\n" ":: Procursus (Hayden Seay, Cameron Katri, Keto et al.)\n" - ":: =========================== ::\n\n" + ":: ==========================>\n\n" ); } @@ -52,6 +55,10 @@ void print_usage(char* argv) { " -s, --safe-mode Enable safe mode\n" " -T, --telnetd Enable TELNET daemon on port 46 (insecure)\n" " -V, --verbose-boot Enable verbose booting\n" + #ifdef _WIN32 + " --install-drivers Install libusbK drivers for PID\n" + " --remove-drivers Remove libusbK drivers for PID\n" + #endif , argv ); } @@ -75,6 +82,10 @@ void parse_arguments(int argc, char* argv[]) { {"safe-mode", no_argument, NULL, 's'}, {"telnetd", no_argument, NULL, 'T'}, {"verbose-boot", no_argument, NULL, 'V'}, + #ifdef _WIN32 + {"install-drivers", required_argument, NULL, 2}, + {"remove-drivers", required_argument, NULL, 4}, + #endif {NULL, 0, NULL, 0} }; @@ -93,7 +104,7 @@ void parse_arguments(int argc, char* argv[]) { palerain_flags |= palerain_option_cli; #endif - while ((options = getopt_long(argc, argv, "hvlf:", long_options, &option_index)) != -1) { + while ((options = getopt_long(argc, argv, "hvlfcB:sTV", long_options, &option_index)) != -1) { switch (options) { case 'h': // --help print_usage(argv[0]); @@ -138,8 +149,28 @@ void parse_arguments(int argc, char* argv[]) { case 'V': // --verbose-boot palerain_flags |= palerain_option_verbose_boot; break; + #ifdef _WIN32 + case 2: { // --install-drivers + unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16); + if (parsed_pid == 0) { + LOG_ERROR("Invalid PID value provided\n"); + exit(1); + } + install_libusbk_target(0x05AC, parsed_pid); + exit(0); + } + case 4: { // --remove-drivers + unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16); + if (parsed_pid == 0) { + LOG_ERROR("Invalid PID value provided\n"); + exit(1); + } + uninstall_libusbk_target(0x05AC, parsed_pid); + exit(0); + } + #endif case '?': - LOG_ERROR("Unknown option"); + LOG_ERROR("Unknown option\n"); print_usage(argv[0]); exit(1); default: break; diff --git a/src/usb/driver.c b/src/usb/driver.c new file mode 100644 index 0000000..8fda6e0 --- /dev/null +++ b/src/usb/driver.c @@ -0,0 +1,161 @@ +#ifdef _WIN32 + +#include "driver.h" + +#include +#include +#include +#include +#include + +#include "../utils.h" + +#define MAX_MATCHING_DRIVERS 16 + +static void add_target_driver(char list[MAX_MATCHING_DRIVERS][64], int *count, const char *inf) +{ + if (*count >= MAX_MATCHING_DRIVERS || strlen(inf) == 0) return; + + for (int i = 0; i < *count; i++) { + if (strcmp(list[i], inf) == 0) return; + } + + strncpy(list[*count], inf, 63); + list[*count][63] = '\0'; + (*count)++; +} + +int install_libusbk_target(unsigned short vid, unsigned short pid) +{ + struct wdi_device_info *list = NULL; + struct wdi_options_create_list cl = { .list_all = TRUE }; + struct wdi_options_prepare_driver prep = { .driver_type = WDI_LIBUSBK, .vendor_name = "libusbK" }; + struct wdi_options_install_driver inst = {0}; + + LOG_VERBOSE("Target: VID:%04X PID:%04X", vid, pid); + + if (wdi_create_list(&list, &cl) != WDI_SUCCESS) { + LOG_ERROR("wdi_create_list failed\n"); + return 1; + } + + char temp_path[MAX_PATH], driver_path[MAX_PATH]; + if (GetTempPathA(MAX_PATH, temp_path) == 0) { + LOG_ERROR("GetTempPathA failed\n"); + wdi_destroy_list(list); + return 1; + } + + snprintf(driver_path, sizeof(driver_path), "%slibusbk_driver\\", temp_path); + CreateDirectoryA(driver_path, NULL); + + int found = 0; + for (struct wdi_device_info *d = list; d; d = d->next) { + if (d->vid != vid || d->pid != pid) continue; + + found = 1; + LOG("Found device %04X:%04X. Preparing & installing driver...", vid, pid); + + if (wdi_prepare_driver(d, driver_path, "libusbk_driver.inf", &prep) != WDI_SUCCESS || + wdi_install_driver(d, driver_path, "libusbk_driver.inf", &inst) != WDI_SUCCESS) { + LOG_ERROR("Driver management pipeline failed for instance node."); + } else { + LOG_SUCCESS("Driver successfully installed!"); + } + } + + wdi_destroy_list(list); + return found ? 0 : 2; +} + +int uninstall_libusbk_target(unsigned short vid, unsigned short pid) +{ + char hwid_u[64], hwid_l[64]; + snprintf(hwid_u, sizeof(hwid_u), "USB\\VID_%04X&PID_%04X", vid, pid); + snprintf(hwid_l, sizeof(hwid_l), "usb\\vid_%04x&pid_%04x", vid, pid); + + LOG_VERBOSE("Target Signature: %s (libusbK)", hwid_u); + + char temp_path[MAX_PATH], log_path[MAX_PATH], cmd[512]; + if (GetTempPathA(MAX_PATH, temp_path) == 0) return 1; + snprintf(log_path, sizeof(log_path), "%spnputil_drivers.txt", temp_path); + + // Strip active instances first + snprintf(cmd, sizeof(cmd), "pnputil /remove-device /deviceid \"%s\" >nul 2>&1", hwid_u); + system(cmd); + + // Dump staging tables + snprintf(cmd, sizeof(cmd), "pnputil /enum-drivers > \"%s\"", log_path); + system(cmd); + + FILE *fp = fopen(log_path, "r"); + char line[256], current_oem_inf[64] = {0}; + char target_drivers_list[MAX_MATCHING_DRIVERS][64]; + int target_count = 0, is_libusbk = 0, matches_hwid = 0; + + if (fp) { + while (fgets(line, sizeof(line), fp)) { + if (strstr(line, "Published Name:") || strstr(line, "Published name:")) { + if (is_libusbk && matches_hwid) { + add_target_driver(target_drivers_list, &target_count, current_oem_inf); + } + is_libusbk = matches_hwid = 0; + current_oem_inf[0] = '\0'; + + char *inf_ptr = strstr(line, "oem"); + if (inf_ptr) sscanf(inf_ptr, "%63s", current_oem_inf); + } + + if (strstr(line, "libusbK") || strstr(line, "libusbk")) is_libusbk = 1; + if (strstr(line, hwid_u) || strstr(line, hwid_l) || strstr(line, "libusbk_driver.inf")) matches_hwid = 1; + } + if (is_libusbk && matches_hwid) { + add_target_driver(target_drivers_list, &target_count, current_oem_inf); + } + fclose(fp); + DeleteFileA(log_path); + } + + if (target_count > 0) { + for (int i = 0; i < target_count; i++) { + LOG("Purging driver package (%d/%d): %s", i + 1, target_count, target_drivers_list[i]); + snprintf(cmd, sizeof(cmd), "pnputil /delete-driver %s /uninstall /force >nul 2>&1", target_drivers_list[i]); + system(cmd); + } + snprintf(cmd, sizeof(cmd), "pnputil /scan-devices >nul 2>&1"); + system(cmd); + LOG_SUCCESS("All %d libusbK driver instances fully uninstalled.", target_count); + return 0; + } + + LOG_ERROR("No matching libusbK driver package found in system store."); + return 2; +} + +bool is_installed_with_libusbk(unsigned short vid, unsigned short pid) +{ + struct wdi_device_info *list = NULL; + struct wdi_options_create_list cl = { .list_all = TRUE }; + bool has_libusbk = false; + + LOG_VERBOSE("Checking driver allocation for VID:%04X PID:%04X", vid, pid); + + if (wdi_create_list(&list, &cl) != WDI_SUCCESS) { + LOG_ERROR("wdi_create_list failed during driver status check"); + return false; + } + + for (struct wdi_device_info *d = list; d; d = d->next) { + if (d->vid == vid && d->pid == pid) { + if (d->driver && (stricmp(d->driver, "libusbK") == 0)) { + has_libusbk = true; + break; + } + } + } + + wdi_destroy_list(list); + return has_libusbk; +} + +#endif \ No newline at end of file diff --git a/src/usb/driver.h b/src/usb/driver.h new file mode 100644 index 0000000..88937fc --- /dev/null +++ b/src/usb/driver.h @@ -0,0 +1,22 @@ +#ifdef _WIN32 + +#ifndef DRIVER_MOD_H +#define DRIVER_MOD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int install_libusbk_target(unsigned short vid, unsigned short pid); +int uninstall_libusbk_target(unsigned short vid, unsigned short pid); +bool is_installed_with_libusbk(unsigned short vid, unsigned short pid); + +#ifdef __cplusplus +} +#endif + +#endif // DRIVER_MOD_H + +#endif // _WIN32 \ No newline at end of file diff --git a/src/usb/driver/.gitkeep b/src/usb/driver/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/utils.c b/src/utils.c index 2d25287..3c6e295 100644 --- a/src/utils.c +++ b/src/utils.c @@ -33,11 +33,30 @@ static const char* level_name(log_level_t level) { } } +static const char* get_timestamp(void) { + static char buffer[32]; + time_t raw_time = time(NULL); + struct tm *time_info = localtime(&raw_time); + + if (time_info) { + // YYYY-MM-DD HH:MM:SS + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info); + } else { + snprintf(buffer, sizeof(buffer), "0000-00-00 00:00:00"); + } + return buffer; +} + void log_write(log_level_t level, const char *fmt, ...) { va_list args; va_start(args, fmt); - printf("%s[%s]%s [%s] => ", level_color(level), level_name(level), RESET_COLOR, time_now()); + char tag_buf[32]; + snprintf(tag_buf, sizeof(tag_buf), "<%s>", level_name(level)); + + printf(" %s%-9s%s [%s%s%s] => ", + level_color(level), tag_buf, RESET_COLOR, + GRAY_COLOR, get_timestamp(), RESET_COLOR); vprintf(fmt, args); printf("\n"); @@ -57,4 +76,4 @@ void sleep_ms(unsigned ms) { #endif } -uint64_t palerain_flags = 0; +uint64_t palerain_flags = 0; \ No newline at end of file