mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
100 lines
4.1 KiB
C++
100 lines
4.1 KiB
C++
#include <array>
|
|
#include <cstdio>
|
|
#include <filesystem>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#else
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
void Require(bool condition, const char* message) {
|
|
if (!condition) throw std::runtime_error(message);
|
|
}
|
|
|
|
struct Import {
|
|
const char* name;
|
|
const char* nid;
|
|
};
|
|
|
|
constexpr std::array<Import, 8> imports{{
|
|
{"Aps5HttpClient_Create", "Xa86mkDT770"},
|
|
{"Aps5HttpClient_Destroy", "FcAd67QjrVw"},
|
|
{"Aps5HttpClient_Open", "T+Un3eukNLs"},
|
|
{"Aps5HttpClient_Read", "mh7PrvIiVtk"},
|
|
{"Aps5HttpClient_Seek", "WN6ypk6qEnU"},
|
|
{"Aps5HttpClient_GetSize", "T8if7aGBDYs"},
|
|
{"Aps5HttpClient_Start", "7EfcZqAehgI"},
|
|
{"Aps5HttpClient_Stop", "M3Qx8MdigHk"}
|
|
}};
|
|
|
|
std::string Utf8(const std::filesystem::path& path) {
|
|
const auto bytes = path.u8string();
|
|
return {reinterpret_cast<const char*>(bytes.data()), bytes.size()};
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
std::filesystem::path ModulePath(HMODULE module) {
|
|
std::wstring buffer(1024, L'\0');
|
|
for (;;) {
|
|
const auto size = GetModuleFileNameW(module, buffer.data(), static_cast<DWORD>(buffer.size()));
|
|
Require(size != 0, "GetModuleFileNameW failed");
|
|
if (size < buffer.size()) {
|
|
buffer.resize(size);
|
|
return std::filesystem::canonical(buffer);
|
|
}
|
|
Require(buffer.size() < 32768, "module path is too long");
|
|
buffer.resize(buffer.size() * 2);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
try {
|
|
Require(argc == 3, "expected module directory and AvPlayer module name");
|
|
const auto directory = std::filesystem::canonical(std::filesystem::u8path(argv[1]));
|
|
const auto player = directory / std::filesystem::u8path(argv[2]);
|
|
const auto expected = std::filesystem::canonical(directory / "libSceHttp.prx");
|
|
#ifdef _WIN32
|
|
const auto consumer = LoadLibraryW(player.c_str());
|
|
Require(consumer != nullptr, "loading patched AvPlayer failed");
|
|
const auto provider = GetModuleHandleW(L"libSceHttp.prx");
|
|
Require(provider != nullptr && ModulePath(provider) == expected, "AvPlayer did not load the staged HTTP provider");
|
|
for (const auto& entry : imports) {
|
|
const auto address = GetProcAddress(provider, entry.nid);
|
|
Require(address != nullptr, "patched HTTP helper is missing");
|
|
Require(GetProcAddress(consumer, entry.nid) == nullptr, "HTTP helper was defined in AvPlayer");
|
|
HMODULE owner{};
|
|
Require(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
|
reinterpret_cast<LPCWSTR>(address), &owner) != 0, "HTTP helper owner lookup failed");
|
|
Require(owner == provider && ModulePath(owner) == expected, "HTTP helper resolved outside libSceHttp");
|
|
std::printf("HTTP provider %s %s %s\n", entry.name, entry.nid, Utf8(expected).c_str());
|
|
}
|
|
#else
|
|
const auto consumer = dlopen(player.c_str(), RTLD_NOW | RTLD_LOCAL);
|
|
if (!consumer) throw std::runtime_error(dlerror());
|
|
const auto provider = dlopen(expected.c_str(), RTLD_NOW | RTLD_NOLOAD);
|
|
Require(provider != nullptr, "AvPlayer did not load libSceHttp as a dependency");
|
|
for (const auto& entry : imports) {
|
|
const auto address = dlsym(consumer, entry.nid);
|
|
Require(address != nullptr && address == dlsym(provider, entry.nid), "AvPlayer HTTP helper lookup failed");
|
|
Dl_info owner{};
|
|
Require(dladdr(address, &owner) != 0 && owner.dli_fname != nullptr, "HTTP helper owner lookup failed");
|
|
Require(std::filesystem::canonical(owner.dli_fname) == expected, "HTTP helper resolved outside libSceHttp");
|
|
std::printf("HTTP provider %s %s %s\n", entry.name, entry.nid, Utf8(expected).c_str());
|
|
}
|
|
#endif
|
|
std::printf("patched %s imports all HTTP helpers from libSceHttp\n", argv[2]);
|
|
return 0;
|
|
} catch (const std::exception& error) {
|
|
std::fprintf(stderr, "patched HTTP modules: %s\n", error.what());
|
|
return 1;
|
|
}
|
|
}
|