commit 8038b0b8075ed1bf80b9c483fbf5063b9c6b7a75
Author: Michael <20937441+KMikeeU@users.noreply.github.com>
Date: Tue Mar 26 02:41:02 2024 +0100
Initial Commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8450b1b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+
+cmake-build-*/*
+library/lib/*.lib
+library/include/*.h
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..a9d7db9
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# GitHub Copilot persisted chat sessions
+/copilot/chatSessions
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..79b3c94
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..16be807
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/rekordunbox.iml b/.idea/rekordunbox.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/rekordunbox.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..03ea8b1
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.26)
+project(rekordunbox)
+
+set(CMAKE_CXX_STANDARD 17)
+
+
+add_library(library SHARED library/library.cpp library/library.h)
+target_include_directories(library PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/library/include/MinHook.h")
+target_link_libraries(library PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/library/lib/libMinHook-x64-v141-md.lib")
+
+add_executable(application application/application.cpp)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..29491f4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# RekordUnbox
+
+## Installation
+
+1. MinHook
+ 1. Download [MinHook Release](https://github.com/TsudaKageyu/minhook/releases/latest)
+ 2. Extract `MinHook.h` to `library/include`
+ 3. Extract `libMinHook-x64-v141-md.lib` to `library/lib`
diff --git a/application/application.cpp b/application/application.cpp
new file mode 100644
index 0000000..0982ba5
--- /dev/null
+++ b/application/application.cpp
@@ -0,0 +1,174 @@
+//
+// Created by Michael on 25/03/2024.
+//
+
+#include
+#include
+#include
+#include
+
+#include "application.h"
+
+int main() {
+ std::string libraryPath = "library.dll";
+
+ // find the "library.dll" either in "./" or in "./lib" or in "./cmake-build-release"
+ std::vector libraryPaths = {
+ libraryPath,
+ "lib\\" + libraryPath,
+ "cmake-build-release\\" + libraryPath,
+ "../" + libraryPath,
+ "../lib/" + libraryPath,
+ "../cmake-build-release/" + libraryPath
+ };
+
+ std::string libraryFullPath;
+ for(const std::string& path : libraryPaths) {
+ if(GetFileAttributesA(path.c_str()) != INVALID_FILE_ATTRIBUTES) {
+ libraryFullPath = path;
+ break;
+ }
+ }
+
+ if(libraryFullPath.empty()) {
+ printf("Library not found\n");
+ return 1;
+ }
+
+
+ // In this directory, find all directories that start with "rekordbox" and end with a number.
+ std::string programPath = R"(C:\Program Files\Pioneer\)";
+
+ // Find all matching directories
+ std::vector directories;
+ WIN32_FIND_DATAA findData;
+ HANDLE hFind = FindFirstFileA((programPath + "rekordbox*").c_str(), &findData);
+ if(hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ std::string directoryName = findData.cFileName;
+ if(directoryName.find("rekordbox") == 0 && isdigit(directoryName.back())) {
+ directories.push_back(directoryName);
+ }
+ }
+ } while(FindNextFileA(hFind, &findData));
+ FindClose(hFind);
+ }
+
+ // If there are no directories, exit
+ if(directories.empty()) {
+ MessageBoxA(NULL, "No rekordbox installation found.", "Error", MB_OK | MB_ICONERROR);
+ return 1;
+ }
+
+ // Print all directories to stdout
+
+ printf("Found rekordbox installations: \n");
+
+ for(const std::string& directory : directories) {
+ printf(" %s\n", directory.c_str());
+ }
+
+ // Out of all the directories, find the latest version
+ // Versions are semver
+ int latestVersion[3] = {0, 0, 0};
+
+ for(const std::string& directory : directories) {
+ // Extract the version from the directory name
+ std::string version_str = directory.substr(sizeof("rekordbox ")-1);
+
+
+ // Split into major, minor, patch
+ int version[3];
+ sscanf_s(version_str.c_str(), "%d.%d.%d", &version[0], &version[1], &version[2]);
+
+ // Compare to latest version
+ // If it's a newer major version, replace
+ if(version[0] > latestVersion[0]) {
+ latestVersion[0] = version[0];
+ latestVersion[1] = version[1];
+ latestVersion[2] = version[2];
+ continue;
+ }
+
+ // If it's the same major, but newer minor, replace
+ if(version[0] == latestVersion[0] && version[1] > latestVersion[1]) {
+ latestVersion[1] = version[1];
+ latestVersion[2] = version[2];
+ continue;
+ }
+
+ // If it's the same major and minor, but newer patch, replace
+ if(version[0] == latestVersion[0] && version[1] == latestVersion[1] && version[2] > latestVersion[2]) {
+ latestVersion[2] = version[2];
+ continue;
+ }
+ }
+
+
+ // Convert the latest version back to a string like "1.2.3"
+ std::string latestVersion_str = std::to_string(latestVersion[0]) + "." + std::to_string(latestVersion[1]) + "." + std::to_string(latestVersion[2]);
+
+
+ // Get the full path to the latest version
+ std::string latestVersionPath = programPath + "rekordbox " + latestVersion_str + "\\rekordbox.exe";
+ printf("Choosing latest version (v%s) at: %s\n", latestVersion_str.c_str(), latestVersionPath.c_str());
+
+
+
+ // Start the executable with the library injected
+ PROCESS_INFORMATION pi = { 0 };
+ STARTUPINFOW si = { 0 };
+ si.cb = sizeof( si );
+
+
+ std::wstring latestVersionPathw = std::wstring(latestVersionPath.begin(), latestVersionPath.end());
+ LPCWSTR latestVersionPathW = latestVersionPathw.c_str();
+
+
+ DWORD flags = CREATE_SUSPENDED;
+
+ if (!CreateProcessW(latestVersionPathW, nullptr, nullptr, nullptr, FALSE, flags, nullptr, nullptr, &si, &pi )) {
+ printf("Failed to start rekordbox\n");
+ // Get error
+ DWORD error = GetLastError();
+ LPSTR messageBuffer = nullptr;
+ size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+ printf("Error %lu: %s\n", error, messageBuffer);
+ return 1;
+ }
+
+ // Make the stdout of the process the same as the current stdout
+
+
+ LPVOID loc = VirtualAllocEx(pi.hProcess, nullptr, libraryFullPath.size() + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ BOOL result = WriteProcessMemory(pi.hProcess, loc, libraryFullPath.c_str(), libraryFullPath.size() + 1, nullptr);
+
+ if(!result) {
+ printf("Failed to inject DLL. Couldn't write process memory\n");
+ return 1;
+ }
+
+ HANDLE hThread = CreateRemoteThread(pi.hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE) LoadLibraryA, loc, 0, nullptr);
+
+ if(hThread == nullptr) {
+ printf("Failed to inject DLL. Couldn't create remote thread\n");
+ return 1;
+ }
+
+ ResumeThread(pi.hThread);
+
+ printf("Started rekordbox, goodbye!\n");
+
+
+ // Cleanup
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+
+ // Sleep for 5 seconds
+ Sleep(5000);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/application/application.h b/application/application.h
new file mode 100644
index 0000000..025fd21
--- /dev/null
+++ b/application/application.h
@@ -0,0 +1,11 @@
+//
+// Created by Michael on 25/03/2024.
+//
+
+#ifndef REKORDUNBOX_APPLICATION_H
+#define REKORDUNBOX_APPLICATION_H
+
+int main();
+
+
+#endif //REKORDUNBOX_APPLICATION_H
diff --git a/library/include/.gitkeep b/library/include/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/library/lib/.gitkeep b/library/lib/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/library/library.cpp b/library/library.cpp
new file mode 100644
index 0000000..c607def
--- /dev/null
+++ b/library/library.cpp
@@ -0,0 +1,142 @@
+
+#include
+#include
+
+#include "library.h"
+#include "include/MinHook.h"
+
+// f3 0f 11 8f 98 0b 00 00
+
+byte orig_place[] = {0xf3, 0x0f, 0x11, 0x8f, 0x98, 0x0b, 0x00, 0x00};
+
+byte* rekordbox_base;
+
+
+
+struct ChannelInfo {
+ byte unk[288];
+ double bpm;
+ UINT64 unk2[2];
+ double secondsElapsed;
+ UINT64 unk3;
+ double beat; // 328 + 8 = 336
+ double beatRounded; // 336 + 8 = 344
+ byte unk4[76];
+ byte isPlaying;
+};
+
+typedef INT64(*updateChannelInfo)(ChannelInfo* channelInfo);
+updateChannelInfo pUpdateChannelInfo = nullptr;
+
+UINT64 count = 0;
+BOOL shouldPrint = false;
+INT64 detourUpdateChannelInfo(ChannelInfo* channelInfo) {
+ count++;
+
+ if(shouldPrint && count % 101 == 0) {
+ printf("Channel: 0x%llx\n", (UINT64)channelInfo);
+ printf("BPM: %f\n", channelInfo->bpm );
+ printf("Time: %f\n", channelInfo->secondsElapsed );
+ printf("Beat: %f\n", channelInfo->beat );
+ printf("~Beat: %f\n", channelInfo->beatRounded );
+ printf("RelBeat: %i/4\n", ((int)channelInfo->beatRounded) % 4);
+ printf("RelBeatF: %f\n", (channelInfo->beat - channelInfo->beatRounded) + ((int)channelInfo->beatRounded) % 4 );
+ printf("isPlaying: %i\n", channelInfo->isPlaying );
+ printf("--------------------\n");
+ }
+
+ INT64 result = pUpdateChannelInfo(channelInfo);
+ return result;
+}
+
+
+// Hook SyncManager? function
+typedef UINT64(*syncManager)(UINT64* param1);
+syncManager pSyncManager = nullptr;
+
+ChannelInfo* master = nullptr;
+
+UINT64 detourSyncManager(UINT64* param1) {
+ auto new_master = (ChannelInfo*)param1[0x1e];
+
+ if(master != new_master && new_master != nullptr) {
+ master = new_master;
+ printf("--------------------\n");
+ printf("New master: %llx\n", (UINT64)master);
+ printf("--------------------\n");
+ }
+
+ UINT64 result = pSyncManager(param1);
+ return result;
+}
+
+
+
+BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
+ if (dwReason == DLL_PROCESS_ATTACH) {
+ DisableThreadLibraryCalls(hModule); //disables attach and detach notifications
+ CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) entry, NULL, NULL, NULL); //creates a new thread and starts at function entry()
+ }
+ else if (dwReason == DLL_PROCESS_DETACH) {
+ printf("Unloading RekordUnBox\n");
+ MH_Uninitialize();
+ }
+ return TRUE;
+}
+
+
+void entry() {
+ AllocConsole();
+ FILE* fp;
+ freopen_s(&fp, "CONOUT$", "w", stdout);
+
+ rekordbox_base = (byte*) GetModuleHandleA("rekordbox.exe");
+
+ printf("Injected RekordUnBox\n");\
+ printf("Rekordbox Base: 0x%ux\n", (unsigned long)rekordbox_base);
+
+ // Print 8 bytes at rekordbox.exe+0x193c8b0
+ byte* updateChannelInfo_location = (byte*)(rekordbox_base + 0x1acd290);
+
+ if (MH_Initialize() != MH_OK) {
+ printf("Failed to initialize MinHook\n");
+ fclose(fp);
+ return;
+ }
+
+ printf("Successfully initialized MinHook\n");
+
+
+ MH_STATUS status;
+
+ // Update loop
+ status = MH_CreateHook(updateChannelInfo_location, &detourUpdateChannelInfo, reinterpret_cast(&pUpdateChannelInfo));
+ if(status != MH_OK) {
+ printf("Error: Couldn't hook updateChannelInfo!\nError: %s", MH_StatusToString(status));
+ fclose(fp);
+ return;
+ }
+
+ // SyncManager
+ status = MH_CreateHook((byte*)(rekordbox_base + 0x18f7630), &detourSyncManager, reinterpret_cast(&pSyncManager));
+ if(status != MH_OK) {
+ printf("Error: Couldn't hook syncManager!\nError: %s", MH_StatusToString(status));
+ fclose(fp);
+ return;
+ }
+
+
+ if(MH_EnableHook(MH_ALL_HOOKS) != MH_OK) {
+ printf("Error: Couldn't enable hooks!\n");
+ fclose(fp);
+ return;
+ }
+
+ while (true) {
+ if (master != nullptr) {
+ printf("Master: %f\n", master->beat);
+ }
+
+ Sleep(1000);
+ }
+}
diff --git a/library/library.h b/library/library.h
new file mode 100644
index 0000000..852ff09
--- /dev/null
+++ b/library/library.h
@@ -0,0 +1,6 @@
+#ifndef REKORDUNBOX_LIBRARY_H
+#define REKORDUNBOX_LIBRARY_H
+
+void entry();
+
+#endif //REKORDUNBOX_LIBRARY_H