mirror of
https://git.collinwebdesigns.de/vgpu/gridd-unlock-patcher.git
synced 2025-12-22 05:20:00 +00:00
refactorings
This commit is contained in:
55
src/CMakeLists.txt
Normal file
55
src/CMakeLists.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(gridd-unlock-patcher CXX)
|
||||
|
||||
include(ExternalProject)
|
||||
include(cmake/FetchCPM.cmake)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME LIEF_SRC
|
||||
GITHUB_REPOSITORY lief-project/LIEF
|
||||
GIT_TAG 0.16.4
|
||||
DOWNLOAD_ONLY YES
|
||||
)
|
||||
|
||||
if (LIEF_SRC_ADDED)
|
||||
set(LIEF_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/LIEF")
|
||||
set(LIEF_INSTALL_DIR "${LIEF_PREFIX}")
|
||||
set(LIEF_INCLUDE_DIRS "${LIEF_PREFIX}/include")
|
||||
|
||||
set(LIEF_LIBRARIES
|
||||
"${LIEF_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LIEF${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
)
|
||||
|
||||
set(LIEF_CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
-DLIEF_EXAMPLES=off
|
||||
-DLIEF_ENABLE_JSON=off
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
)
|
||||
|
||||
ExternalProject_Add(LIEF
|
||||
PREFIX "${LIEF_PREFIX}"
|
||||
SOURCE_DIR ${LIEF_SRC_SOURCE_DIR}
|
||||
INSTALL_DIR ${LIEF_INSTALL_DIR}
|
||||
CMAKE_ARGS ${LIEF_CMAKE_ARGS}
|
||||
BUILD_BYPRODUCTS ${LIEF_LIBRARIES}
|
||||
UPDATE_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "LIEF include directory: ${LIEF_INCLUDE_DIRS}")
|
||||
message(STATUS "LIEF library: ${LIEF_LIBRARIES}")
|
||||
|
||||
add_executable(gridd-unlock-patcher gridd-unlock-patcher.cpp)
|
||||
|
||||
add_dependencies(gridd-unlock-patcher LIEF)
|
||||
|
||||
target_include_directories(gridd-unlock-patcher PRIVATE ${LIEF_INCLUDE_DIRS})
|
||||
target_link_libraries(gridd-unlock-patcher PRIVATE ${LIEF_LIBRARIES})
|
||||
|
||||
set_target_properties(gridd-unlock-patcher PROPERTIES LINK_FLAGS_RELEASE -s)
|
||||
install(TARGETS gridd-unlock-patcher)
|
||||
11
src/build.sh
Executable file
11
src/build.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$1" == "clean" ] || [ "$1" == "rebuild" ]; then
|
||||
rm -rf build gridd-unlock-patcher
|
||||
fi
|
||||
|
||||
if [ "$1" == "rebuild" ] || [ "$1" != "clean" ]; then
|
||||
mkdir -p build; cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .. && make -j$(nproc) && mv gridd-unlock-patcher ..
|
||||
cd ..
|
||||
fi
|
||||
24
src/cmake/FetchCPM.cmake
Normal file
24
src/cmake/FetchCPM.cmake
Normal file
@@ -0,0 +1,24 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
|
||||
|
||||
set(CPM_DOWNLOAD_VERSION 0.40.8)
|
||||
set(CPM_HASH_SUM "78ba32abdf798bc616bab7c73aac32a17bbd7b06ad9e26a6add69de8f3ae4791")
|
||||
|
||||
if(CPM_SOURCE_CACHE)
|
||||
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
|
||||
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
else()
|
||||
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
endif()
|
||||
|
||||
# Expand relative path. This is important if the provided path contains a tilde (~)
|
||||
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
|
||||
|
||||
file(DOWNLOAD
|
||||
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
||||
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
|
||||
)
|
||||
|
||||
include(${CPM_DOWNLOAD_LOCATION})
|
||||
137
src/gridd-unlock-patcher.cpp
Normal file
137
src/gridd-unlock-patcher.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <LIEF/ELF.hpp>
|
||||
#include "nls-root_ca-certificates.hpp"
|
||||
|
||||
using namespace LIEF::ELF;
|
||||
|
||||
FILE *gridd_filep = NULL;
|
||||
uint8_t *gridd_data = NULL;
|
||||
FILE *cert_fp = NULL;
|
||||
void *user_root_ca = NULL;
|
||||
|
||||
void usage(char *program_name)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS]\n", program_name);
|
||||
printf("\n"
|
||||
" -h\n"
|
||||
" -g <nvidia-gridd binary>\n"
|
||||
" -c <root CA certificate>\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
int parse_args(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "hg:c:")) != -1) {
|
||||
// Required parameter is in global "optarg"
|
||||
switch (opt) {
|
||||
case '?':
|
||||
/* fall through */
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
case 'g':
|
||||
gridd_filep = fopen(optarg, "rb+");
|
||||
break;
|
||||
case 'c':
|
||||
cert_fp = fopen(optarg, "rb");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gridd_filep == NULL || cert_fp == NULL) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void cleanup(void)
|
||||
{
|
||||
if (user_root_ca)
|
||||
free(user_root_ca);
|
||||
if (gridd_data)
|
||||
free(gridd_data);
|
||||
if (cert_fp)
|
||||
fclose(cert_fp);
|
||||
if (gridd_filep)
|
||||
fclose(gridd_filep);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct stat gridd_fp_stats, cert_fp_stats;
|
||||
size_t status;
|
||||
|
||||
if (parse_args(argc, argv) == -1) {
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the hardcoded certificates */
|
||||
// Read the nvidia-gridd binary
|
||||
fstat(fileno(gridd_filep), &gridd_fp_stats);
|
||||
gridd_data = (uint8_t *)malloc(gridd_fp_stats.st_size);
|
||||
assert(gridd_data != NULL);
|
||||
|
||||
status = fread((void *)gridd_data, gridd_fp_stats.st_size, 1, gridd_filep);
|
||||
assert(status > 0);
|
||||
|
||||
// Parse the ELF
|
||||
std::vector<uint8_t> gridd_vec(gridd_data, gridd_data + gridd_fp_stats.st_size);
|
||||
auto gridd_bin = Parser::parse(gridd_vec);
|
||||
auto s_rodata = gridd_bin->get_section(".rodata");
|
||||
auto s_data = gridd_bin->get_section(".data");
|
||||
|
||||
// There are two hardcoded certificates
|
||||
size_t cert_one_offset = s_rodata->search(gridd_hardcoded_cert_one);
|
||||
size_t cert_two_offset = s_rodata->search(gridd_hardcoded_cert_two);
|
||||
printf("Found the two hardcoded NLS certificates at 0x%x and 0x%x.\n", cert_one_offset, cert_two_offset);
|
||||
|
||||
/* Validate the size of the provided root CA */
|
||||
fstat(fileno(cert_fp), &cert_fp_stats);
|
||||
// FIXME: Align up to cover the padding?
|
||||
size_t total_cert_size = cert_two_offset + (strlen(gridd_hardcoded_cert_two) + 1) - cert_one_offset;
|
||||
if (cert_fp_stats.st_size > total_cert_size) {
|
||||
printf("The provided certificate (size %d) is larger than the available space (size %d)!\n",
|
||||
cert_fp_stats.st_size, total_cert_size);
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Patch in the provided certificate */
|
||||
// Read the provided root CA
|
||||
user_root_ca = malloc(cert_fp_stats.st_size);
|
||||
assert(user_root_ca != NULL);
|
||||
|
||||
status = fread(user_root_ca, cert_fp_stats.st_size, 1, cert_fp);
|
||||
assert(status > 0);
|
||||
|
||||
// Overwrite the first certificate, NULL the second
|
||||
uint8_t *cert_start = gridd_data + s_rodata->offset() + cert_one_offset;
|
||||
memcpy((void *)cert_start, user_root_ca, cert_fp_stats.st_size);
|
||||
memset((void *)(cert_start + cert_fp_stats.st_size), 0, total_cert_size - cert_fp_stats.st_size);
|
||||
|
||||
printf("Replaced the hardcoded certificates with the provided one.\n");
|
||||
|
||||
// Erase the XREF to the second certificate
|
||||
size_t cert_xrefs_array = s_data->offset() + s_data->search(s_rodata->virtual_address() + cert_one_offset);
|
||||
memset((void *)(gridd_data + cert_xrefs_array + sizeof(uint64_t)), 0, sizeof(uint64_t));
|
||||
|
||||
printf("Fixed up the list of certificates. Done!\n");
|
||||
|
||||
// Write the nvidia-gridd binary
|
||||
FILE *test = fopen("gridd_bin", "wb");
|
||||
fwrite((void *)gridd_data, gridd_fp_stats.st_size, 1, test);
|
||||
fclose(test);
|
||||
|
||||
cleanup();
|
||||
return 0;
|
||||
}
|
||||
73
src/nls-root_ca-certificates.hpp
Normal file
73
src/nls-root_ca-certificates.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
const char *gridd_hardcoded_cert_one =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"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\n"
|
||||
"bBj+W2v1REPS\n"
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
const char *gridd_hardcoded_cert_two =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"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\n"
|
||||
"JQ6S82i+o497\n"
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
Reference in New Issue
Block a user