Skip to content

Commit

Permalink
Merge branch 'ui-integration'
Browse files Browse the repository at this point in the history
# Conflicts:
#	.github/workflows/release.yml
#	README.md
#	SpotifyOggDumper/Hooks.cpp
#	SpotifyOggDumper/Hooks.h
#	SpotifyOggDumper/SpotifyOggDumper.vcxproj
  • Loading branch information
Rafiuth committed Dec 29, 2021
2 parents 739df28 + 0c9c760 commit aad2982
Show file tree
Hide file tree
Showing 51 changed files with 7,083 additions and 975 deletions.
52 changes: 42 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,64 @@ name: Release

on:
push:
tags:
- 'v*'
tags: [ 'v*' ]
workflow_dispatch:

jobs:
build:
runs-on: windows-latest

steps:
- uses: actions/checkout@v2
- uses: microsoft/[email protected]
- uses: actions/setup-node@v2
with:
node-version: 16
cache: 'npm'
cache-dependency-path: Sprinkles/package-lock.json

- name: Fetch external dependencies
run: ./fetch_external_deps.bat

- name: Add msbuild to PATH
uses: microsoft/[email protected]

- name: Build
- name: Build Natives
run: |
vcpkg install --triplet x86-windows-static-md
vcpkg integrate install
msbuild /p:Configuration=Release
- name: Build TypeScript
run: |
cd Sprinkles/
$Env:NODE_ENV = "production"
$Env:VERSION_INFO = $Env:GITHUB_REF_NAME + "-" + $Env:GITHUB_SHA.Substring(0, 8);
npm install
npm run build
Copy-Item dist/bundle.js ../build/Release/Soggfy.js
Copy-Item dist/bundle.js.map ../build/Release/Soggfy.js.map
cd ../
$ver = $Env:GITHUB_REF -replace "refs/.*/v", ""
- name: Create Zip
run: |
echo $Env:GITHUB_REF_NAME;
if ($Env:GITHUB_REF_TYPE -eq "tag") {
$ver = $Env:GITHUB_REF_NAME -replace "^v", "";
} else {
$ver = $Env:GITHUB_SHA.Substring(0, 8) + "-pre";
}
Rename-Item -Path ./build/Release -NewName Soggfy-$ver
7z a "-xr!*.lib" "-xr!*.exp" "-xr!*.pdb" build/Soggfy-$ver.zip ./build/Soggfy-$ver
- name: Upload binaries
- name: Upload Binaries
uses: softprops/action-gh-release@v1
if: ${{ github.ref_type == 'tag' }}
with:
draft: false
prerelease: ${{ contains(github.ref, '-pre') }}
files: 'build/*.zip'
prerelease: ${{ contains(github.ref_name, '-pre') }}
files: 'build/*.zip'

- name: Upload Artifacts
uses: actions/upload-artifact@v2
if: ${{ github.ref_type != 'tag' }}
with:
path: build/*.zip
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
*.aps
build/
obj/
vcpkg_installed/
vcpkg_installed/
external/
20 changes: 20 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22000.0",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}
84 changes: 84 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, PointerAlignment: Left, ColumnLimit: 0 }",
"files.associations": {
"regex": "cpp",
"array": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"deque": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"unordered_map": "cpp",
"valarray": "cpp",
"vector": "cpp",
"xstring": "cpp",
"xutility": "cpp",
"filesystem": "cpp",
"algorithm": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"format": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"set": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_set": "cpp",
"utility": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp",
"xtree": "cpp"
}
}
119 changes: 69 additions & 50 deletions Injector/Injector.cpp
Original file line number Diff line number Diff line change
@@ -1,52 +1,28 @@
#include <Windows.h>
#include <TlHelp32.h>
#include <psapi.h>
#include <shlobj_core.h>
#include <iostream>
#include <filesystem>
#include <functional>
#include <unordered_set>

std::wstring NormalizePath(const std::wstring& path)
{
DWORD finalLen = GetFullPathName(path.c_str(), 0, NULL, NULL);
std::wstring fullPath;
fullPath.resize(finalLen - 1);

GetFullPathName(path.c_str(), finalLen, (LPWSTR)fullPath.c_str(), NULL);
return fullPath;
}
#include <Windows.h>
#include <winternl.h>
#include <TlHelp32.h>
#include <psapi.h>
#include <shlobj_core.h>

BOOL FileExists(LPCTSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
namespace fs = std::filesystem;

return dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
}
LPVOID GetRemoteProcAddress(HANDLE hProc, LPCWSTR moduleName, LPCSTR procName)
{
//This is fine for a small hack, as kernel32 is always on the same address for all processes.
//A more arch independent way to do this is to scan the target process modules for the specified
//moduleName, find the entry point of procName in the PE exports, then return mod.lpBaseOfDll + export.EntryPoint.
//https://stackoverflow.com/a/22750425
HMODULE module = LoadLibrary(moduleName);
return GetProcAddress(module, procName);
}
void InjectDll(HANDLE hProc, const std::wstring& dllPath)
void InjectDll(HANDLE hProc, const fs::path& dllPath)
{
std::wstring fullPath = NormalizePath(dllPath);
LPCWSTR path = fullPath.c_str();
DWORD pathLenBytes = (fullPath.size() + 1) * 2;
fs::path path = fs::absolute(dllPath);
std::wstring pathW = path.wstring();
DWORD pathLenBytes = (pathW.size() + 1) * 2;

if (!FileExists(path)) {
throw std::exception("DLL file does not exist");
}
HANDLE loadLibAddr = GetRemoteProcAddress(hProc, L"Kernel32.dll", "LoadLibraryW");
HANDLE loadLibAddr = GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryW");
LPVOID pathArgAddr = VirtualAllocEx(hProc, NULL, pathLenBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!pathArgAddr) {
throw std::exception("Could not allocate memory on target process");
}
WriteProcessMemory(hProc, pathArgAddr, path, pathLenBytes, NULL);
WriteProcessMemory(hProc, pathArgAddr, pathW.data(), pathLenBytes, NULL);

HANDLE thread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibAddr, pathArgAddr, 0, NULL);
if (!thread) {
Expand Down Expand Up @@ -85,6 +61,49 @@ void EnumWindowsEx(std::function<BOOL(HWND)> visitor)
}, (LPARAM)&visitor);
}

std::wstring GetProcessCommandLine(HANDLE hProc)
{
typedef NTSTATUS(NTAPI* NtQueryInformationProcess_FuncType)(
IN HANDLE ProcessHandle,
ULONG ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
static const auto _QueryProcInfo = (NtQueryInformationProcess_FuncType)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess");

PROCESS_BASIC_INFORMATION info;
if (!NT_SUCCESS(_QueryProcInfo(hProc, ProcessBasicInformation, &info, sizeof(info), NULL))) {
throw std::exception("Failed to get process information");
}
PEB peb;
RTL_USER_PROCESS_PARAMETERS procParams;
ReadProcessMemory(hProc, info.PebBaseAddress, &peb, sizeof(peb), NULL);
ReadProcessMemory(hProc, peb.ProcessParameters, &procParams, sizeof(procParams), NULL);

std::wstring cmdLine(procParams.CommandLine.Length, '\0');
ReadProcessMemory(hProc, procParams.CommandLine.Buffer, cmdLine.data(), cmdLine.size(), NULL);
return cmdLine;
}

void KillCrashpadProcess()
{
EnumProcessesEx([&](auto proc) {
if (_wcsicmp(proc.szExeFile, L"Spotify.exe") == 0) {
DWORD accFlags =
PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE;
HANDLE hProc = OpenProcess(accFlags, false, proc.th32ProcessID);
std::wstring cmdLine = GetProcessCommandLine(hProc);
if (cmdLine.find(L"--type=crashpad-handler") != std::wstring::npos) {
TerminateProcess(hProc, 0);
std::cout << "Spotify crash reporter process killed successfully (" << proc.th32ProcessID << ")\n";
}
CloseHandle(hProc);
}
});
}

HANDLE FindMainProcess()
{
//Find spotify processes
Expand Down Expand Up @@ -119,11 +138,10 @@ HANDLE FindMainProcess()
false, actualProcId
);
}
bool FindSpotifyExePath(std::wstring& exePath)
bool FindSpotifyExePath(fs::path& exePath)
{
//Check current directory
exePath = NormalizePath(L"Spotify.exe");
if (FileExists(exePath.c_str())) {
if (fs::exists(exePath.c_str())) {
return true;
}
//Check %appdata%/Spotify/Spotify.exe
Expand All @@ -132,7 +150,7 @@ bool FindSpotifyExePath(std::wstring& exePath)
exePath = std::wstring(appdataPath) + L"\\Spotify\\Spotify.exe";
CoTaskMemFree(appdataPath);

if (FileExists(exePath.c_str())) {
if (fs::exists(exePath)) {
return true;
}
return false;
Expand All @@ -146,12 +164,11 @@ PROCESS_INFORMATION FindTargetProcess()
if (!target.hProcess) {
std::cout << "Spotify process not found, creating a new one...\n";

std::wstring exePath;
std::wstring workDir;
fs::path exePath;
if (!FindSpotifyExePath(exePath)) {
throw std::exception("Could not find Spotify exe path");
}
workDir = exePath.substr(0, exePath.find_last_of('\\'));
fs::path workDir = exePath.parent_path();

STARTUPINFO startInfo = {};
startInfo.cb = sizeof(STARTUPINFO);
Expand All @@ -162,7 +179,7 @@ PROCESS_INFORMATION FindTargetProcess()
}
return target;
}
void CleanupTargetProcess(PROCESS_INFORMATION& target)
void CloseProcess(PROCESS_INFORMATION& target)
{
if (target.hThread) {
CloseHandle(target.hThread);
Expand All @@ -182,14 +199,16 @@ int main()
std::cout << "Injecting dumper dll into process " << GetProcessId(targetProc.hProcess) << "...\n";

InjectDll(targetProc.hProcess, L"SpotifyOggDumper.dll");
KillCrashpadProcess();
std::cout << "Injection succeeded!\n";
} catch (std::exception& ex) {
std::cout << "Error: " << ex.what() << "\n";
for (int i = 5; i > 0; i--) {
std::cout << "Exiting in " << i << "s...\r";
Sleep(1000);
}
}
CleanupTargetProcess(targetProc);
CloseProcess(targetProc);

for (int i = 3; i > 0; i--) {
std::cout << "Exiting in " << i << "s...\r";
Sleep(1000);
}
return 0;
}
Loading

0 comments on commit aad2982

Please sign in to comment.