Compare commits
No commits in common. "main" and "main" have entirely different histories.
110
.clang-format
110
.clang-format
|
@ -1,110 +0,0 @@
|
|||
# es3n1n's clang-format, last upd 13 aug 2022 23:07:09
|
||||
---
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BasedOnStyle: WebKit
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: None
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeConceptDeclarations: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 155
|
||||
CommentPragmas: true
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth : 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
EmptyLineBeforeAccessModifier: Never
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: Indent
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentRequires: false
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
Language: Cpp
|
||||
NamespaceIndentation: All
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: false
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
|
@ -20,10 +20,6 @@ Open the folder where Spotify is installed (%APPDATA%/Spotify) and rename Spotif
|
|||
|
||||
[![Watch the video](https://img.youtube.com/vi/_TStlwGfBpo/maxresdefault.jpg)](https://youtu.be/_TStlwGfBpo)
|
||||
|
||||
## Community
|
||||
|
||||
[Official discord server](https://discord.gg/U7X9kKcJzF)
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
|
|
|
@ -2,64 +2,65 @@
|
|||
#include <TlHelp32.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define INJECTOR_FAIL(s) \
|
||||
{ \
|
||||
util::logger::error(s " Error code: %d\n", GetLastError()); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define INJECTOR_FAIL(s) { util::logger::error(s " Error code: %d\n", GetLastError( ) ); return false; }
|
||||
|
||||
|
||||
namespace injector {
|
||||
namespace detail {
|
||||
void* get_process_by_name(const wchar_t* name) {
|
||||
void* thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (thSnapShot == INVALID_HANDLE_VALUE)
|
||||
return nullptr;
|
||||
namespace detail {
|
||||
void* get_process_by_name( const wchar_t* name ) {
|
||||
void* thSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
|
||||
if ( thSnapShot == INVALID_HANDLE_VALUE )
|
||||
return nullptr;
|
||||
|
||||
PROCESSENTRY32W pe;
|
||||
pe.dwSize = sizeof(PROCESSENTRY32W);
|
||||
PROCESSENTRY32W pe;
|
||||
pe.dwSize = sizeof( PROCESSENTRY32W );
|
||||
|
||||
unsigned long ret = 0;
|
||||
for (bool proc = Process32FirstW(thSnapShot, &pe); proc; proc = Process32NextW(thSnapShot, &pe)) {
|
||||
if (wcscmp(pe.szExeFile, name))
|
||||
continue;
|
||||
ret = pe.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
unsigned long ret = 0;
|
||||
for ( bool proc = Process32FirstW( thSnapShot, &pe ); proc; proc = Process32NextW( thSnapShot, &pe ) ) {
|
||||
if ( wcscmp( pe.szExeFile, name ) )
|
||||
continue;
|
||||
ret = pe.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
|
||||
CloseHandle(thSnapShot);
|
||||
CloseHandle( thSnapShot );
|
||||
|
||||
return ret ? OpenProcess(PROCESS_ALL_ACCESS, false, ret) : nullptr;
|
||||
}
|
||||
} // namespace detail
|
||||
return ret ? OpenProcess( PROCESS_ALL_ACCESS, false, ret ) : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool inject(const wchar_t* proc, const char* path) { return ::injector::inject(detail::get_process_by_name(proc), path); }
|
||||
bool inject( const wchar_t* proc, const char* path ) {
|
||||
return ::injector::inject( detail::get_process_by_name( proc ), path );
|
||||
}
|
||||
|
||||
bool inject(HANDLE proc, const char* path) {
|
||||
if (!proc)
|
||||
INJECTOR_FAIL("Failed to open a process. Make sure injector is running as an admin.");
|
||||
bool inject( HANDLE proc, const char* path ) {
|
||||
if ( !proc )
|
||||
INJECTOR_FAIL( "Failed to open a process. Make sure injector is running as an admin." );
|
||||
|
||||
char full_path[260];
|
||||
if (!GetFullPathNameA(path, sizeof(full_path), full_path, nullptr))
|
||||
INJECTOR_FAIL("Failed to find a dll.");
|
||||
char full_path[ 260 ];
|
||||
if ( !GetFullPathNameA( path, sizeof( full_path ), full_path, nullptr ) )
|
||||
INJECTOR_FAIL( "Failed to find a dll." );
|
||||
|
||||
HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
if (!kernel32)
|
||||
INJECTOR_FAIL("Failed to get kernel32.dll handle.");
|
||||
HMODULE kernel32 = GetModuleHandleW( L"kernel32.dll" );
|
||||
if ( !kernel32 )
|
||||
INJECTOR_FAIL( "Failed to get kernel32.dll handle." );
|
||||
|
||||
void* lla = reinterpret_cast<void*>(GetProcAddress(kernel32, "LoadLibraryA"));
|
||||
if (!lla)
|
||||
INJECTOR_FAIL("Failed to find LoadLibraryA function.");
|
||||
void* lla = reinterpret_cast< void* >( GetProcAddress( kernel32, "LoadLibraryA" ) );
|
||||
if ( !lla )
|
||||
INJECTOR_FAIL( "Failed to find LoadLibraryA function." );
|
||||
|
||||
void* str = VirtualAllocEx(proc, nullptr, strlen(full_path), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
if (!str)
|
||||
INJECTOR_FAIL("Failed to allocate memory region for str.");
|
||||
void* str = VirtualAllocEx( proc, nullptr, strlen( full_path ), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
if ( !str )
|
||||
INJECTOR_FAIL( "Failed to allocate memory region for str." );
|
||||
|
||||
WriteProcessMemory(proc, str, full_path, strlen(full_path), nullptr);
|
||||
CreateRemoteThread(proc, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(lla), str, 0, nullptr);
|
||||
WriteProcessMemory( proc, str, full_path, strlen( full_path ), nullptr );
|
||||
CreateRemoteThread( proc, nullptr, 0, reinterpret_cast< LPTHREAD_START_ROUTINE >( lla ), str, 0, nullptr );
|
||||
|
||||
CloseHandle( proc );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(proc);
|
||||
return true;
|
||||
}
|
||||
} // namespace injector
|
||||
|
||||
#undef INJECTOR_FAIL
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#pragma once
|
||||
#include "shared/logo.h"
|
||||
#include <Windows.h>
|
||||
#include "shared/logo.h"
|
||||
|
||||
|
||||
namespace injector {
|
||||
namespace detail {
|
||||
void* get_process_by_name(const wchar_t* name);
|
||||
}
|
||||
namespace detail {
|
||||
void* get_process_by_name( const wchar_t* name );
|
||||
}
|
||||
|
||||
bool inject(const wchar_t* proc, const char* path);
|
||||
bool inject(HANDLE proc, const char* path);
|
||||
} // namespace injector
|
||||
bool inject( const wchar_t* proc, const char* path );
|
||||
bool inject( HANDLE proc, const char* path );
|
||||
}
|
||||
|
|
|
@ -1,38 +1,30 @@
|
|||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include "injector/injector.h"
|
||||
|
||||
int main() {
|
||||
util::logo::create_console_and_draw_logo();
|
||||
|
||||
STARTUPINFOA si = { .cb = sizeof(si) };
|
||||
PROCESS_INFORMATION pi = {};
|
||||
int main( ) {
|
||||
util::logo::create_console_and_draw_logo( );
|
||||
STARTUPINFO si = { .cb = sizeof( STARTUPINFO ) };
|
||||
PROCESS_INFORMATION pi = {};
|
||||
|
||||
constexpr const char* exe_path = "oSpotify.exe";
|
||||
|
||||
// Creating process
|
||||
//
|
||||
util::logger::debug("Spawning %s", exe_path);
|
||||
if (!CreateProcessA(exe_path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
|
||||
util::logger::error("Unable to create process, error code: %d", GetLastError());
|
||||
system("pause");
|
||||
goto END;
|
||||
}
|
||||
|
||||
// Injecting Unspotify
|
||||
//
|
||||
util::logger::debug("Injecting spotify-reverse.dll");
|
||||
if (!injector::inject(pi.hProcess, "spotify-reverse.dll")) {
|
||||
util::logger::error("Unable to inject module, error code: %d", GetLastError());
|
||||
TerminateProcess(pi.hProcess, 0x0);
|
||||
system("pause");
|
||||
goto END;
|
||||
}
|
||||
|
||||
ResumeThread(pi.hThread);
|
||||
util::logger::debug( "Spawning oSpotify.exe" );
|
||||
if ( !CreateProcessW( L"oSpotify.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi ) ) {
|
||||
util::logger::error( "Unable to create process, error code: %d", GetLastError( ) );
|
||||
system( "pause" );
|
||||
goto END;
|
||||
}
|
||||
|
||||
util::logger::debug( "Injecting spotify-reverse.dll" );
|
||||
if ( !injector::inject( pi.hProcess, "spotify-reverse.dll" ) ) {
|
||||
util::logger::error( "Unable to inject module, error code: %d", GetLastError( ) );
|
||||
TerminateProcess( pi.hProcess, 0x0 );
|
||||
system( "pause" );
|
||||
goto END;
|
||||
}
|
||||
|
||||
ResumeThread(pi.hThread);
|
||||
END:
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -9,6 +9,14 @@
|
|||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
|
@ -21,9 +29,9 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>12.0.0</LLVMToolsVersion>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
|
@ -31,7 +39,22 @@
|
|||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>15.0.1</LLVMToolsVersion>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
@ -45,6 +68,12 @@
|
|||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
|
@ -58,6 +87,18 @@
|
|||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
<TargetName>Spotify</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
<TargetName>Spotify</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
<TargetName>Spotify</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnabled>false</VcpkgEnabled>
|
||||
</PropertyGroup>
|
||||
|
@ -69,12 +110,13 @@
|
|||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
@ -89,14 +131,13 @@
|
|||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED /pdbaltpath:%_PDB% %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
|
@ -107,12 +148,13 @@
|
|||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
@ -127,7 +169,6 @@
|
|||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -143,7 +184,6 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="injector\injector.h" />
|
||||
<ClInclude Include="util\util.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -26,8 +26,5 @@
|
|||
<ClInclude Include="injector\injector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,101 +1,84 @@
|
|||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <stdio.h>
|
||||
#include <Windows.h>
|
||||
#include <functional>
|
||||
|
||||
#define L_ERROR(...) util::logger::error(__FUNCTION__ "(): " __VA_ARGS__);
|
||||
#define TRACE_FN util::logger::debug("%s()", __FUNCTION__);
|
||||
#define TRACE_FN util::logger::debug( "%s()", __FUNCTION__ );
|
||||
|
||||
#define LOGGER_PARSE_FMT \
|
||||
char buf[2048]; \
|
||||
va_list va; \
|
||||
va_start(va, fmt); \
|
||||
_vsnprintf_s(buf, 1024, fmt, va); \
|
||||
va_end(va);
|
||||
#define LOGGER_PARSE_FMT char buf[1024]; va_list va; va_start( va, fmt ); _vsnprintf_s( buf, 1024, fmt, va ); va_end( va );
|
||||
#define CREATE_LOGGER_METHOD(n) inline void n(const char* fmt, ...) { LOGGER_PARSE_FMT; log( #n, e_level_color::level_color_ ##n, buf ); }
|
||||
|
||||
#define CREATE_LOGGER_METHOD(n) \
|
||||
inline void n(const char* fmt, ...) { \
|
||||
LOGGER_PARSE_FMT; \
|
||||
log(#n, e_level_color::level_color_##n, buf); \
|
||||
}
|
||||
|
||||
namespace util {
|
||||
namespace logger {
|
||||
enum class e_level_color : uint32_t {
|
||||
level_color_none = 15, // black bg and white fg
|
||||
level_color_debug = 8,
|
||||
level_color_info = 10,
|
||||
level_color_warn = 14,
|
||||
level_color_error = 12
|
||||
};
|
||||
namespace logger {
|
||||
enum class e_level_color : uint32_t {
|
||||
level_color_none = 15, // black bg and white fg
|
||||
level_color_debug = 8,
|
||||
level_color_info = 10,
|
||||
level_color_warn = 14,
|
||||
level_color_error = 12
|
||||
};
|
||||
|
||||
namespace _colors {
|
||||
inline void* m_console_handle = nullptr;
|
||||
namespace _colors {
|
||||
inline void* m_console_handle = nullptr;
|
||||
|
||||
inline bool ensure_handle() {
|
||||
if (!m_console_handle)
|
||||
m_console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
return static_cast<bool>(m_console_handle);
|
||||
}
|
||||
inline bool ensure_handle( ) {
|
||||
if ( !m_console_handle )
|
||||
m_console_handle = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||
return static_cast< bool >( m_console_handle );
|
||||
}
|
||||
|
||||
inline void apply(uint32_t clr) {
|
||||
if (!ensure_handle())
|
||||
return;
|
||||
SetConsoleTextAttribute(m_console_handle, clr);
|
||||
}
|
||||
inline void apply( uint32_t clr ) {
|
||||
if ( !ensure_handle( ) ) return;
|
||||
SetConsoleTextAttribute( m_console_handle, clr );
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
apply(static_cast<uint32_t>(e_level_color::level_color_none));
|
||||
}
|
||||
inline void reset( ) {
|
||||
apply( static_cast< uint32_t >( e_level_color::level_color_none ) );
|
||||
}
|
||||
|
||||
inline void colorify(uint32_t clr, std::function<void()> cb) {
|
||||
apply(clr);
|
||||
cb();
|
||||
reset();
|
||||
}
|
||||
} // namespace _colors
|
||||
inline void colorify( uint32_t clr, std::function<void( )> cb ) {
|
||||
apply( clr );
|
||||
cb( );
|
||||
reset( );
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline std::mutex _mtx;
|
||||
}
|
||||
inline void log( const char* prefix, e_level_color level, const char* message ) {
|
||||
_colors::colorify( static_cast< uint32_t >( level ), [ prefix ] ( ) -> void {
|
||||
printf( "%s >> ", prefix );
|
||||
} );
|
||||
|
||||
inline void log(const char* prefix, e_level_color level, const char* message) {
|
||||
std::lock_guard<std::mutex> _lock(_mtx);
|
||||
printf( "%s\n", message );
|
||||
}
|
||||
|
||||
_colors::colorify(static_cast<uint32_t>(level), [prefix]() -> void { printf("%s >> ", prefix); });
|
||||
#ifdef _DEBUG
|
||||
CREATE_LOGGER_METHOD( debug );
|
||||
#else
|
||||
__forceinline void debug( const char* fmt, ... ) { }
|
||||
#endif
|
||||
CREATE_LOGGER_METHOD( info );
|
||||
CREATE_LOGGER_METHOD( warn );
|
||||
CREATE_LOGGER_METHOD( error );
|
||||
inline void fatal( const char* fmt, ... ) {
|
||||
LOGGER_PARSE_FMT;
|
||||
MessageBoxA( NULL, buf, "Unspotify", MB_OK );
|
||||
}
|
||||
|
||||
printf("%s\n", message);
|
||||
}
|
||||
__forceinline void startup( ) {
|
||||
::AllocConsole( );
|
||||
freopen_s( reinterpret_cast< FILE** >( stdin ), "CONIN$", "r", stdin );
|
||||
freopen_s( reinterpret_cast< FILE** >( stdout ), "CONOUT$", "w", stdout );
|
||||
::SetConsoleTitleA( "Unspotify" );
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
CREATE_LOGGER_METHOD(debug);
|
||||
#else
|
||||
__forceinline void debug(const char* fmt, ...) { }
|
||||
#endif
|
||||
CREATE_LOGGER_METHOD(info);
|
||||
CREATE_LOGGER_METHOD(warn);
|
||||
CREATE_LOGGER_METHOD(error);
|
||||
inline void fatal(const char* fmt, ...) {
|
||||
LOGGER_PARSE_FMT;
|
||||
error("Fatal error: %s", buf);
|
||||
MessageBoxA(NULL, buf, "Unspotify fatal error", MB_OK);
|
||||
ExitProcess(-1);
|
||||
}
|
||||
|
||||
__forceinline void startup() {
|
||||
::AllocConsole();
|
||||
freopen_s(reinterpret_cast<FILE**>(stdin), "CONIN$", "r", stdin);
|
||||
freopen_s(reinterpret_cast<FILE**>(stdout), "CONOUT$", "w", stdout);
|
||||
::SetConsoleTitleA("Unspotify");
|
||||
}
|
||||
|
||||
__forceinline void detach() {
|
||||
::ShowWindow(::GetConsoleWindow(), SW_HIDE);
|
||||
::FreeConsole();
|
||||
}
|
||||
} // namespace logger
|
||||
} // namespace util
|
||||
__forceinline void detach( ) {
|
||||
::ShowWindow( ::GetConsoleWindow( ), SW_HIDE );
|
||||
::FreeConsole( );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef CREATE_LOGGER_METHOD
|
|
@ -1,28 +1,25 @@
|
|||
#pragma once
|
||||
#include "logger.h"
|
||||
|
||||
#define UNSPOTIFY_GIT_URL "https://git.tcp.direct/dg/Unspotify"
|
||||
#define UNSPOTIFY_DISCORD_URL "https://discord.gg/U7X9kKcJzF"
|
||||
|
||||
namespace util {
|
||||
namespace logo {
|
||||
inline void create_console_and_draw_logo() {
|
||||
util::logger::startup();
|
||||
util::logger::info(" d8, ,d8888b ");
|
||||
util::logger::info(" d8P `8P 88P' ");
|
||||
util::logger::info(" d888888P d888888P ");
|
||||
util::logger::info("?88 d8P 88bd88b .d888b,?88,.d88b, d8888b ?88' 88b ?88' ?88 d8P ");
|
||||
util::logger::info("d88 88 88P' ?8b ?8b, `?88' ?88d8P' ?88 88P 88P 88P d88 88 ");
|
||||
util::logger::info("?8( d88 d88 88P `?8b 88b d8P88b d88 88b d88 d88 ?8( d88 ");
|
||||
util::logger::info("`?88P'?8bd88' 88b`?888P' 888888P'`?8888P' `?8b d88' d88' `?88P'?8b ");
|
||||
util::logger::info(" 88P' )88");
|
||||
util::logger::info(" d88 ,d8P");
|
||||
util::logger::info(" ?8P `?888P ");
|
||||
util::logger::info(" compiled at %s %s", __DATE__, __TIME__);
|
||||
util::logger::info(" git: %s", UNSPOTIFY_GIT_URL);
|
||||
util::logger::info(" join our discord: %s", UNSPOTIFY_DISCORD_URL);
|
||||
util::logger::info("");
|
||||
util::logger::info("");
|
||||
inline void create_console_and_draw_logo( ) {
|
||||
util::logger::startup( );
|
||||
util::logger::info( " d8, ,d8888b " );
|
||||
util::logger::info( " d8P `8P 88P' " );
|
||||
util::logger::info( " d888888P d888888P " );
|
||||
util::logger::info( "?88 d8P 88bd88b .d888b,?88,.d88b, d8888b ?88' 88b ?88' ?88 d8P " );
|
||||
util::logger::info( "d88 88 88P' ?8b ?8b, `?88' ?88d8P' ?88 88P 88P 88P d88 88 " );
|
||||
util::logger::info( "?8( d88 d88 88P `?8b 88b d8P88b d88 88b d88 d88 ?8( d88 " );
|
||||
util::logger::info( "`?88P'?8bd88' 88b`?888P' 888888P'`?8888P' `?8b d88' d88' `?88P'?8b " );
|
||||
util::logger::info( " 88P' )88" );
|
||||
util::logger::info( " d88 ,d8P" );
|
||||
util::logger::info( " ?8P `?888P " );
|
||||
util::logger::info( " by es3n.in | compiled at %s %s", __DATE__, __TIME__ );
|
||||
util::logger::info( " git: https://git.tcp.direct/dg/Unspotify" );
|
||||
util::logger::info( "" );
|
||||
util::logger::info( "" );
|
||||
}
|
||||
} // namespace logo
|
||||
} // namespace util
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32210.238
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31515.178
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spotify-reverse", "spotify-reverse\spotify-reverse.vcxproj", "{930F56C2-377E-4C4D-815D-B0BB2C7DDFC9}"
|
||||
EndProject
|
||||
|
@ -9,12 +9,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spotify-reverse-launcher",
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spotify-reverse-shared", "spotify-reverse-shared\spotify-reverse-shared.vcxitems", "{80C10288-CFBD-49D7-84DE-BF83B13E3B24}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{C6266EFA-749F-4905-80BB-F71B4ECE4595}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.clang-format = .clang-format
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{0b43a5fb-d64c-45cb-b87d-af45d7d67932}*SharedItemsImports = 4
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{80c10288-cfbd-49d7-84de-bf83b13e3b24}*SharedItemsImports = 9
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{930f56c2-377e-4c4d-815d-b0bb2c7ddfc9}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
|
@ -35,9 +35,4 @@ Global
|
|||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4464B17F-3892-49EA-B9CF-52D3AC9C0DD8}
|
||||
EndGlobalSection
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{0b43a5fb-d64c-45cb-b87d-af45d7d67932}*SharedItemsImports = 4
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{80c10288-cfbd-49d7-84de-bf83b13e3b24}*SharedItemsImports = 9
|
||||
spotify-reverse-shared\spotify-reverse-shared.vcxitems*{930f56c2-377e-4c4d-815d-b0bb2c7ddfc9}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,51 +1,43 @@
|
|||
#include "bootstrap.h"
|
||||
#include "exceptions/exceptions.h"
|
||||
#include "hooks/hooks.h"
|
||||
#include "../util/util.h"
|
||||
#include "../spotify/spotify.h"
|
||||
#include "../hooks/hooks.h"
|
||||
#include "shared/logo.h"
|
||||
#include "spotify/spotify.h"
|
||||
#include "updates/updates.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace bootstrap {
|
||||
DWORD __stdcall _initial_routine(HANDLE) {
|
||||
util::logo::create_console_and_draw_logo();
|
||||
DWORD __stdcall _initial_routine( HANDLE ) {
|
||||
util::logo::create_console_and_draw_logo( );
|
||||
spotify::init( );
|
||||
hooks::init( );
|
||||
|
||||
exceptions::subscribe();
|
||||
util::logger::warn( "press any key to close this console" );
|
||||
_getwch( );
|
||||
util::logger::detach( );
|
||||
|
||||
#ifdef CHECK_FOR_UPDATES
|
||||
std::thread(updates::do_job).detach();
|
||||
#endif
|
||||
#ifndef _DEBUG
|
||||
for ( ;;) {
|
||||
#else
|
||||
while ( !GetAsyncKeyState( VK_DELETE ) ) {
|
||||
#endif
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||
}
|
||||
|
||||
spotify::init();
|
||||
hooks::init();
|
||||
_shutdown( );
|
||||
return 1; // unreachable but whatever
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
while (!GetAsyncKeyState(VK_DELETE)) {
|
||||
#else
|
||||
util::logger::warn("press any key to close this console");
|
||||
_getwch();
|
||||
util::logger::detach();
|
||||
bool startup( HINSTANCE dll_handle ) {
|
||||
_::dll_handle = dll_handle;
|
||||
CreateThread( nullptr, 0, _initial_routine, 0, 0, nullptr );
|
||||
return true;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
#endif
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
_shutdown();
|
||||
return 1; // unreachable but whatever
|
||||
}
|
||||
|
||||
bool startup(HINSTANCE dll_handle) {
|
||||
detail::dll_handle = dll_handle;
|
||||
detail::region_size = util::mem::module_t(uintptr_t(dll_handle)).get_nt_headers()->OptionalHeader.SizeOfImage;
|
||||
CreateThread(nullptr, 0, _initial_routine, 0, 0, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void _shutdown() {
|
||||
hooks::shutdown();
|
||||
FreeLibraryAndExitThread(reinterpret_cast<HMODULE>(detail::dll_handle), 0x1);
|
||||
}
|
||||
} // namespace bootstrap
|
||||
void _shutdown( ) {
|
||||
hooks::shutdown( );
|
||||
FreeLibraryAndExitThread( reinterpret_cast< HMODULE >( _::dll_handle ), 0x1 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#pragma once
|
||||
#include <condition_variable>
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
namespace bootstrap {
|
||||
namespace detail {
|
||||
inline HINSTANCE dll_handle;
|
||||
inline DWORD region_size;
|
||||
} // namespace detail
|
||||
namespace _ {
|
||||
inline HINSTANCE dll_handle;
|
||||
}
|
||||
|
||||
DWORD __stdcall _initial_routine(HANDLE);
|
||||
DWORD __stdcall _initial_routine( HANDLE );
|
||||
|
||||
bool startup( HINSTANCE handle );
|
||||
void _shutdown( );
|
||||
}
|
||||
|
||||
bool startup(HINSTANCE handle);
|
||||
void _shutdown();
|
||||
} // namespace bootstrap
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// autoupdates
|
||||
|
||||
// @note: es3n1n: v1.1.1 = 111
|
||||
#define UNSPOTIFY_VERSION 111
|
||||
|
||||
#define AUTOUPDATER_DOMAIN "es3n.in"
|
||||
#define AUTOUPDATER_URL "unspotify.json"
|
||||
|
||||
#ifndef _DEBUG
|
||||
#define CHECK_FOR_UPDATES
|
||||
#endif
|
|
@ -1,9 +1,8 @@
|
|||
#include "bootstrap/bootstrap.h"
|
||||
#include <cstdint>
|
||||
|
||||
BOOL __stdcall DllMain(std::uintptr_t hinstDll, std::uint32_t fdwReason, std::uintptr_t) {
|
||||
if (fdwReason != DLL_PROCESS_ATTACH)
|
||||
return 1;
|
||||
|
||||
return bootstrap::startup(reinterpret_cast<HINSTANCE>(hinstDll));
|
||||
BOOL __stdcall DllMain( std::uintptr_t hinstDll, std::uint32_t fdwReason, std::uintptr_t ) {
|
||||
if ( fdwReason != DLL_PROCESS_ATTACH ) return 1;
|
||||
|
||||
return bootstrap::startup( reinterpret_cast< HINSTANCE >( hinstDll ) );
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "bootstrap/bootstrap.h"
|
||||
#include "exceptions/exceptions.h"
|
||||
#include "shared/logger.h"
|
||||
|
||||
namespace exceptions {
|
||||
LONG __stdcall handler(EXCEPTION_POINTERS* info) {
|
||||
static bool logged{false};
|
||||
|
||||
if (logged)
|
||||
return EXCEPTION_CONTINUE_SEARCH; // @note: es3n1n: log exceptions only once
|
||||
|
||||
auto exc_addr = reinterpret_cast<uintptr_t>(info->ExceptionRecord->ExceptionAddress);
|
||||
|
||||
if ((exc_addr < reinterpret_cast<uintptr_t>(bootstrap::detail::dll_handle) ||
|
||||
exc_addr > (reinterpret_cast<uintptr_t>(bootstrap::detail::dll_handle) + bootstrap::detail::region_size))) {
|
||||
return EXCEPTION_CONTINUE_SEARCH; // @note: es3n1n: log exceptions only from our mod
|
||||
}
|
||||
|
||||
std::stringstream log_msg;
|
||||
log_msg << "Module base: " << std::hex << std::showbase << bootstrap::detail::dll_handle << std::endl;
|
||||
log_msg << "Module size: " << std::hex << std::showbase << bootstrap::detail::region_size << std::endl;
|
||||
log_msg << "Exception address: " << std::hex << std::showbase << exc_addr << std::endl;
|
||||
log_msg << "Exception code: " << std::hex << std::showbase << info->ExceptionRecord->ExceptionCode << std::endl;
|
||||
log_msg << "EAX: " << std::hex << std::showbase << info->ContextRecord->Eax << " | EBX: " << info->ContextRecord->Ebx << std::endl;
|
||||
log_msg << "ECX: " << std::hex << std::showbase << info->ContextRecord->Ecx << " | EDX: " << info->ContextRecord->Edx << std::endl;
|
||||
log_msg << "EBP: " << std::hex << std::showbase << info->ContextRecord->Ebp << " | ESP: " << info->ContextRecord->Esp << std::endl;
|
||||
log_msg << "ESI: " << std::hex << std::showbase << info->ContextRecord->Esi << " | EDI: " << info->ContextRecord->Edi << std::endl;
|
||||
log_msg << std::endl << "PLEASE PRESS CTRL+C AND REPORT THIS ERROR IN OUR DISCORD" << std::endl;
|
||||
|
||||
util::logger::fatal(log_msg.str().c_str());
|
||||
|
||||
logged = true;
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void subscribe() {
|
||||
AddVectoredExceptionHandler(1, handler);
|
||||
}
|
||||
} // namespace exceptions
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace exceptions {
|
||||
LONG __stdcall handler(EXCEPTION_POINTERS* info);
|
||||
void subscribe();
|
||||
} // namespace exceptions
|
|
@ -1,21 +0,0 @@
|
|||
#include "hooks/hooks.h"
|
||||
|
||||
namespace hooks {
|
||||
namespace hooked {
|
||||
/*
|
||||
@xref: " Creating track player for track (playback_id %s)"
|
||||
*/
|
||||
void __fastcall create_track(void* pthis, void* pedx, spotify::structs::player_meta_t* player_meta,
|
||||
spotify::structs::player_track_meta_t* track_meta, double speed, int normalization, int urgency,
|
||||
int track_select_flag, int flag, int stream_type) {
|
||||
player_meta->m_should_skip = static_cast<std::uint32_t>(static_cast<bool>(strstr(track_meta->m_track_uri, "spotify:ad:")));
|
||||
|
||||
util::logger::info("Playing %s | should_skip: %s", track_meta->m_track_uri, player_meta->m_should_skip ? "true" : "false");
|
||||
|
||||
if (player_meta->m_should_skip)
|
||||
speed = 29.0;
|
||||
|
||||
original::create_track(pthis, pedx, player_meta, track_meta, speed, normalization, urgency, track_select_flag, flag, stream_type);
|
||||
}
|
||||
} // namespace hooked
|
||||
} // namespace hooks
|
|
@ -1,19 +1,19 @@
|
|||
#include "hooks/hooks.h"
|
||||
#include "../hooks.h"
|
||||
|
||||
|
||||
namespace hooks {
|
||||
namespace hooked {
|
||||
#ifdef _DEBUG
|
||||
std::uintptr_t __cdecl debug_msg(std::uint32_t, std::uint32_t, const char* win, const char* flag, std::uint32_t size, std::uint32_t,
|
||||
const char* fmt, ...) { // @xref: "Path provided in --%s '%s' (resolved to '%s') does not exist."
|
||||
LOGGER_PARSE_FMT;
|
||||
namespace hooked {
|
||||
std::uintptr_t __cdecl debug_msg( std::uint32_t, std::uint32_t, const char* win, const char* flag, std::uint32_t size, std::uint32_t, const char* fmt, ... ) { // @xref: "Path provided in --%s '%s' (resolved to '%s') does not exist."
|
||||
#ifdef _DEBUG
|
||||
LOGGER_PARSE_FMT;
|
||||
|
||||
for (std::size_t i = 0; i < strlen(buf); i++)
|
||||
buf[i] = buf[i] == '\n' ? ' ' : buf[i];
|
||||
for ( int i = 0; i < strlen( buf ); i++ )
|
||||
buf[ i ] = buf[ i ] == '\n' ? ' ' : buf[ i ];
|
||||
|
||||
printf("[spotify::debug_msg] %s\n", buf);
|
||||
printf( "[spotify::debug_msg] %s\n", buf );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
} // namespace hooked
|
||||
} // namespace hooks
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
#include "hooks/hooks.h"
|
||||
#include "../hooks.h"
|
||||
|
||||
|
||||
namespace hooks {
|
||||
namespace hooked {
|
||||
std::uintptr_t __cdecl get_ad(int a1, int a2) { // @xref: "advertiser"
|
||||
return 0;
|
||||
}
|
||||
} // namespace hooked
|
||||
} // namespace hooks
|
||||
namespace hooked {
|
||||
std::uintptr_t __cdecl get_ad( int a1, int a2 ) { // @xref: "advertiser"
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#include "../hooks.h"
|
||||
|
||||
|
||||
namespace hooks {
|
||||
namespace hooked {
|
||||
/*
|
||||
@note: es3n1n:
|
||||
First of all find xref "Creating track player for track", then at the end
|
||||
there would be a call to a function with 13 params, this is it ;)
|
||||
*/
|
||||
|
||||
std::uintptr_t __fastcall play_track(
|
||||
std::uintptr_t pthis,
|
||||
std::uintptr_t pEDX,
|
||||
spotify::structs::player_meta_t* player_meta,
|
||||
spotify::structs::player_track_meta_t* track_meta,
|
||||
char a4, int a5, char a6, int a7, int a8, char a9, char a10, int a11, char a12, int a13
|
||||
) {
|
||||
player_meta->m_should_skip = static_cast< std::uint32_t >( static_cast< bool >( strstr( track_meta->m_track_uri, "spotify:ad:" ) ) );
|
||||
util::logger::info( "Playing %s | should_skip: %s", track_meta->m_track_uri, player_meta->m_should_skip ? "true" : "false" );
|
||||
return original::play_track( pthis, pEDX, player_meta, track_meta, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,16 @@
|
|||
#include "hooks.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define CREATE_HOOK(n) \
|
||||
if (!util::hooking::detour::create(spotify::addr::##n, hooked::##n, reinterpret_cast<void**>(&original::##n))) \
|
||||
util::logger::fatal("Unable to hook %s", #n);
|
||||
|
||||
namespace hooks {
|
||||
void init() {
|
||||
if (!util::hooking::detour::init())
|
||||
util::logger::fatal("Unable to init minhook");
|
||||
#pragma warning(disable:5103)
|
||||
#ifdef _DEBUG
|
||||
CREATE_HOOK(debug_msg);
|
||||
#endif
|
||||
CREATE_HOOK(get_ad);
|
||||
CREATE_HOOK(create_track);
|
||||
#pragma warning(default:5103)
|
||||
}
|
||||
void init( ) {
|
||||
util::hooking::detour::init( );
|
||||
util::hooking::detour::create( spotify::addr::debug_msg, hooked::debug_msg, reinterpret_cast< void** >( &original::debug_msg ) );
|
||||
util::hooking::detour::create( spotify::addr::get_ad, hooked::get_ad, reinterpret_cast< void** >( &original::get_ad ) );
|
||||
util::hooking::detour::create( spotify::addr::play_track, hooked::play_track, reinterpret_cast< void** >( &original::play_track ) );
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
util::hooking::detour::remove();
|
||||
}
|
||||
} // namespace hooks
|
||||
|
||||
#undef CREATE_HOOK
|
||||
void shutdown( ) {
|
||||
util::hooking::detour::remove( );
|
||||
}
|
||||
}
|
|
@ -1,26 +1,20 @@
|
|||
#pragma once
|
||||
#include "spotify/spotify.h"
|
||||
#include "util/util.h"
|
||||
#include "../util/util.h"
|
||||
#include "../spotify/spotify.h"
|
||||
|
||||
|
||||
namespace hooks {
|
||||
namespace hooked {
|
||||
#ifdef _DEBUG
|
||||
std::uintptr_t __cdecl debug_msg(std::uint32_t, std::uint32_t, const char* win, const char* flag, std::uint32_t size, std::uint32_t,
|
||||
const char* fmt, ...);
|
||||
#endif
|
||||
std::uintptr_t __cdecl get_ad(int a1, int a2);
|
||||
void __fastcall create_track(void* pthis, void* pedx, spotify::structs::player_meta_t* player_meta,
|
||||
spotify::structs::player_track_meta_t* track_meta, double speed, int normalization, int urgency,
|
||||
int track_select_flag, int flag, int stream_type);
|
||||
} // namespace hooked
|
||||
namespace original {
|
||||
#ifdef _DEBUG
|
||||
inline decltype(&hooked::debug_msg) debug_msg;
|
||||
#endif
|
||||
inline decltype(&hooked::get_ad) get_ad;
|
||||
inline decltype(&hooked::create_track) create_track;
|
||||
} // namespace original
|
||||
namespace hooked {
|
||||
std::uintptr_t __cdecl debug_msg( std::uint32_t, std::uint32_t, const char* win, const char* flag, std::uint32_t size, std::uint32_t, const char* fmt, ... );
|
||||
std::uintptr_t __cdecl get_ad( int a1, int a2 );
|
||||
std::uintptr_t __fastcall play_track( std::uintptr_t pthis, std::uintptr_t pEDX, spotify::structs::player_meta_t* player_meta, spotify::structs::player_track_meta_t* track_meta, char a4, int a5, char a6, int a7, int a8, char a9, char a10, int a11, char a12, int a13 );
|
||||
}
|
||||
namespace original {
|
||||
inline decltype( &hooked::debug_msg ) debug_msg;
|
||||
inline decltype( &hooked::get_ad ) get_ad;
|
||||
inline decltype( &hooked::play_track ) play_track;
|
||||
}
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
} // namespace hooks
|
||||
void init( );
|
||||
void shutdown( );
|
||||
}
|
|
@ -9,6 +9,14 @@
|
|||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
|
@ -21,9 +29,9 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>13.0.1</LLVMToolsVersion>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
|
@ -31,7 +39,22 @@
|
|||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>15.0.1</LLVMToolsVersion>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LLVMToolsVersion>13.0.0</LLVMToolsVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
@ -45,18 +68,32 @@
|
|||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)output\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)intermediates\$(Configuration)\$(MSBuildProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnabled>false</VcpkgEnabled>
|
||||
|
@ -70,15 +107,12 @@
|
|||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
@ -87,47 +121,80 @@
|
|||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_HAS_STATIC_RTTI=0;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalOptions>-Xclang -fno-rtti -Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-int-to-void-pointer-cast -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-sign-compare -Wno-multichar -Wno-unused-parameter -Wno-microsoft-enum-forward-reference </AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED /pdbaltpath:%_PDB% %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalOptions>-Xclang -Ofast -Xclang -fno-threadsafe-statics -Xclang -fdelayed-template-parsing -fcf-protection=none -mllvm -pgso -Wno-missing-braces -Wno-deprecated-volatile -Wno-missing-field-initializers -Wno-ignored-pragma-optimize /clang:-fno-unwind-tables /clang:-ffast-math /clang:-fno-builtin -Wno-gnu-string-literal-operator-template -Wno-unused-private-field -Wno-invalid-token-paste -Wno-microsoft-cast -Wno-unused-command-line-argument -Wno-pragma-once-outside-header %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalOptions>/MAP /MERGE:.voltbl=.data /MERGE:.retplne=.data /MERGE:.gehcont=.data /MERGE:.00cfg=.data /MERGE:_RDATA=.rdata /FORCE:UNRESOLVED %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bootstrap\bootstrap.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="exceptions\exceptions.cpp" />
|
||||
<ClCompile Include="hooks\hooked\debug_msg.cpp" />
|
||||
<ClCompile Include="hooks\hooked\get_ad.cpp" />
|
||||
<ClCompile Include="hooks\hooked\create_track.cpp" />
|
||||
<ClCompile Include="hooks\hooked\play_track.cpp" />
|
||||
<ClCompile Include="hooks\hooks.cpp" />
|
||||
<ClCompile Include="spotify\spotify.cpp" />
|
||||
<ClCompile Include="updates\updates.cpp" />
|
||||
<ClCompile Include="util\hooking\detours\detours.cpp" />
|
||||
<ClCompile Include="util\hooking\detours\mh\buffer.c" />
|
||||
<ClCompile Include="util\hooking\detours\mh\hde\hde32.c" />
|
||||
<ClCompile Include="util\hooking\detours\mh\hde\hde64.c" />
|
||||
<ClCompile Include="util\hooking\detours\mh\hook.c" />
|
||||
<ClCompile Include="util\hooking\detours\mh\trampoline.c" />
|
||||
<ClCompile Include="util\networking\networking.cpp" />
|
||||
<ClCompile Include="util\hooking\vmt\vmt.cpp" />
|
||||
<ClCompile Include="util\mem\module.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="bootstrap\bootstrap.h" />
|
||||
<ClInclude Include="exceptions\exceptions.h" />
|
||||
<ClInclude Include="hooks\hooks.h" />
|
||||
<ClInclude Include="spotify\spotify.h" />
|
||||
<ClInclude Include="updates\updates.h" />
|
||||
<ClInclude Include="util\hooking\detours\detours.h" />
|
||||
<ClInclude Include="util\hooking\detours\mh\buffer.h" />
|
||||
<ClInclude Include="util\hooking\detours\mh\hde\hde32.h" />
|
||||
|
@ -138,11 +205,8 @@
|
|||
<ClInclude Include="util\hooking\detours\mh\minhook.h" />
|
||||
<ClInclude Include="util\hooking\detours\mh\trampoline.h" />
|
||||
<ClInclude Include="util\hooking\hooking.h" />
|
||||
<ClInclude Include="util\hooking\vmt\vmt.h" />
|
||||
<ClInclude Include="util\mem\addr.h" />
|
||||
<ClInclude Include="defines.h" />
|
||||
<ClInclude Include="util\mem\module.h" />
|
||||
<ClInclude Include="util\networking\ext\json.hpp" />
|
||||
<ClInclude Include="util\networking\networking.h" />
|
||||
<ClInclude Include="util\util.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\mem\module.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bootstrap\bootstrap.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -42,6 +45,9 @@
|
|||
<ClCompile Include="util\hooking\detours\detours.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\hooking\vmt\vmt.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hooks\hooks.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -51,16 +57,7 @@
|
|||
<ClCompile Include="hooks\hooked\debug_msg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hooks\hooked\create_track.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\networking\networking.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="updates\updates.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="exceptions\exceptions.cpp">
|
||||
<ClCompile Include="hooks\hooked\play_track.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -104,29 +101,14 @@
|
|||
<ClInclude Include="util\hooking\detours\detours.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\hooking\vmt\vmt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\hooking\hooking.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hooks\hooks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\networking\networking.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\networking\ext\json.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="defines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="updates\updates.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="exceptions\exceptions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\mem\module.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -4,7 +4,7 @@
|
|||
<ShowAllFiles>true</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommand>Spotify.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerCommand>oSpotify.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerAttach>true</LocalDebuggerAttach>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
|
@ -13,4 +13,14 @@
|
|||
<LocalDebuggerAttach>true</LocalDebuggerAttach>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommand>oSpotify.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerAttach>true</LocalDebuggerAttach>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommand>Spotify.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerAttach>true</LocalDebuggerAttach>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -1,75 +1,29 @@
|
|||
#include "spotify.h"
|
||||
|
||||
#define ASSERT_PATTERN(s) \
|
||||
if (!addr::##s.valid()) \
|
||||
util::logger::fatal("Pattern %s not found. Please update your Unspotify version", #s);
|
||||
#define ASSERT_PATTERN_STEP(s) \
|
||||
if (!s) \
|
||||
util::logger::fatal("Unable to find %s at %d", #s, __LINE__)
|
||||
|
||||
namespace spotify {
|
||||
void init() {
|
||||
#pragma warning(disable:5103)
|
||||
TRACE_FN;
|
||||
void init( ) {
|
||||
TRACE_FN;
|
||||
|
||||
modules::spotify = util::mem::module_t(nullptr);
|
||||
util::logger::debug("module::spotify = 0x%p", modules::spotify);
|
||||
modules::spotify = util::mem::module_t( nullptr );
|
||||
util::logger::debug( "module::spotify = 0x%p", modules::spotify );
|
||||
|
||||
uint32_t str;
|
||||
util::mem::addr_t sig;
|
||||
std::vector<int> pattern = {};
|
||||
addr::debug_msg =
|
||||
modules::spotify.sig( "6A 24 B8 ? ? ? ? E8 ? ? ? ? 8B 7D 10 33 C0 8B 75 14 89 45 D8 89 45 E8 C7 45 ? ? ? ? ? 88 45 D8 89 45 FC 8D 45 24" );
|
||||
util::logger::debug( "addr::debug_msg = 0x%p", addr::debug_msg );
|
||||
|
||||
#ifdef _DEBUG
|
||||
// "Could not create stream reader for file: %s"
|
||||
str = modules::spotify.sig(
|
||||
"43 6F 75 6C 64 20 6E 6F 74 20 63 72 65 61 74 65 20 73 74 72 65 61 6D 20 72 65 61 64 65 72 20 66 6F 72 20 66 69 6C 65 3A 20 25 73");
|
||||
ASSERT_PATTERN_STEP(str);
|
||||
pattern.clear();
|
||||
pattern.emplace_back(0x68 /* push offset */);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pattern.emplace_back((int)(((uint8_t*)(&str))[i]));
|
||||
sig = modules::spotify.sig(pattern);
|
||||
ASSERT_PATTERN_STEP(sig);
|
||||
addr::debug_msg = sig.walk_until(0x6A /* push 02 */).walk_until(0xE8 /* call */).rel(1);
|
||||
util::logger::debug("addr::debug_msg = 0x%p", addr::debug_msg);
|
||||
ASSERT_PATTERN(debug_msg);
|
||||
#endif
|
||||
addr::get_ad =
|
||||
modules::spotify.sig( "68 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 8B 5D 08 8D 8D ? ? ? ? 8B 7D 0C 53 89 9D ? ? ? ? 89 BD ? ? ? ? E8 ? ? ? ? 83 65 FC 00 8D 47 04 89 85 ? ? ? ?" );
|
||||
util::logger::debug( "addr::get_ad = 0x%p", addr::get_ad );
|
||||
|
||||
// "ad_type"
|
||||
str = modules::spotify.sig("61 64 5F 74 79 70 65 00");
|
||||
ASSERT_PATTERN_STEP(str);
|
||||
pattern.clear();
|
||||
for (int i = 0; i < 4; i++)
|
||||
pattern.emplace_back((int)(((uint8_t*)(&str))[i]));
|
||||
sig = modules::spotify.sig(pattern);
|
||||
ASSERT_PATTERN_STEP(sig);
|
||||
do {
|
||||
sig = sig.walk_back_until(0xC2 /* retn */);
|
||||
} while (sig.offset(-5).read<uint8_t>() != 0xE8 && sig.offset(-8).read<uint8_t>() != 0xE8 && sig.offset(-9).read<uint8_t>() != 0xE8);
|
||||
addr::get_ad = sig.add(1).read<uint8_t>() == 0x68 /* push */ ? sig.add(1) : sig.walk_until(0x68 /* push 0D4h */);
|
||||
util::logger::debug("addr::get_ad = 0x%p", addr::get_ad);
|
||||
ASSERT_PATTERN(get_ad);
|
||||
|
||||
// " Creating track player for track (playback_id %s)"
|
||||
str = modules::spotify.sig("20 20 20 20 43 72 65 61 74 69 6E 67 20 74 72 61 63 6B 20 70 6C 61 79 65 72 20 66 6F 72 20 74 72 61 63 6B 20 28 70 6C "
|
||||
"61 79 62 61 63 6B 5F 69 64 20 25 73 29");
|
||||
ASSERT_PATTERN_STEP(sig);
|
||||
pattern.clear();
|
||||
pattern.emplace_back(0x68 /* push offset */);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pattern.emplace_back((int)(((uint8_t*)(&str))[i]));
|
||||
sig = modules::spotify.sig(pattern);
|
||||
ASSERT_PATTERN_STEP(sig);
|
||||
addr::create_track = sig.walk_back_until(0xC2 /* retn */).offset(3 /* C2 04 00 */);
|
||||
while (addr::create_track.read<uint8_t>() == 0xE8 /* call */)
|
||||
addr::create_track = addr::create_track.add(5); // E8 + 4 bytes addr
|
||||
while (addr::create_track.read<uint8_t>() == 0xCC)
|
||||
addr::create_track = addr::create_track.add(1); // skip aligns
|
||||
util::logger::debug("addr::create_track = 0x%p", addr::create_track);
|
||||
ASSERT_PATTERN(create_track);
|
||||
#pragma warning(default:5103)
|
||||
}
|
||||
} // namespace spotify
|
||||
|
||||
#undef ASSERT_PATTERN
|
||||
#undef ASSERT_PATTERN_STEP
|
||||
addr::play_track_table_mov =
|
||||
modules::spotify.sig( "C7 03 ? ? ? ? 89 43 08 89 55 FC 89 11 89 51 04 E8 ? ? ? ? 8B 75 14 8D 7B 14 8B 45 18 8D 4B 28 FF 75 1C " );
|
||||
util::logger::debug( "addr::play_track_table_mov = 0x%p", addr::play_track_table_mov );
|
||||
addr::play_track_table = addr::play_track_table_mov.add( 2 ).self_get( );
|
||||
util::logger::debug( "addr::play_track_table = 0x%p", addr::play_track_table );
|
||||
addr::play_track_fn_addr = addr::play_track_table.add( 4 );
|
||||
util::logger::debug( "addr::play_track_fn_addr = 0x%p", addr::play_track_fn_addr );
|
||||
addr::play_track = addr::play_track_fn_addr.self_get( );
|
||||
util::logger::debug( "addr::play_track = 0x%p", addr::play_track );
|
||||
}
|
||||
}
|
|
@ -1,35 +1,33 @@
|
|||
#pragma once
|
||||
#include "util/util.h"
|
||||
|
||||
#include "../util/util.h"
|
||||
|
||||
namespace spotify {
|
||||
namespace structs {
|
||||
struct player_meta_t {
|
||||
private:
|
||||
char __pad[0x74];
|
||||
public:
|
||||
std::uint32_t m_should_skip;
|
||||
};
|
||||
namespace structs {
|
||||
struct player_meta_t {
|
||||
private: char __pad[ 0x74 ];
|
||||
public: std::uint32_t m_should_skip;
|
||||
};
|
||||
|
||||
struct player_track_meta_t {
|
||||
private:
|
||||
char __pad[0xB0];
|
||||
public:
|
||||
const char* m_track_uri;
|
||||
};
|
||||
} // namespace structs
|
||||
struct player_track_meta_t {
|
||||
private: char __pad[ 0x48 ];
|
||||
public: const char* m_track_uri;
|
||||
};
|
||||
}
|
||||
|
||||
namespace modules {
|
||||
inline util::mem::module_t spotify;
|
||||
}
|
||||
namespace modules {
|
||||
inline util::mem::module_t spotify;
|
||||
}
|
||||
|
||||
namespace addr {
|
||||
#ifdef _DEBUG
|
||||
inline util::mem::addr_t debug_msg;
|
||||
#endif
|
||||
inline util::mem::addr_t get_ad;
|
||||
inline util::mem::addr_t create_track;
|
||||
inline util::mem::addr_t should_show_ad;
|
||||
} // namespace addr
|
||||
namespace addr {
|
||||
inline util::mem::addr_t debug_msg;
|
||||
inline util::mem::addr_t get_ad;
|
||||
|
||||
void init();
|
||||
} // namespace spotify
|
||||
inline util::mem::addr_t play_track;
|
||||
inline util::mem::addr_t play_track_table_mov;
|
||||
inline util::mem::addr_t play_track_table;
|
||||
inline util::mem::addr_t play_track_fn_addr;
|
||||
}
|
||||
|
||||
void init( );
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#include "updates.h"
|
||||
|
||||
namespace updates {
|
||||
update_info_t poll_info() {
|
||||
auto [data, error] = util::networking::get(AUTOUPDATER_DOMAIN, AUTOUPDATER_URL);
|
||||
if (error)
|
||||
return update_info_t{.m_error = true, .m_error_desc = "Internal server/app error :shrug:"};
|
||||
|
||||
return update_info_t{.m_error = false,
|
||||
.m_version = data["version"].get<uint32_t>(),
|
||||
.m_changelog = data["changelog"].get<std::string>(),
|
||||
.m_is_required = data["required"].get<bool>(),
|
||||
.m_download_url = data["download_url"].get<std::string>()};
|
||||
}
|
||||
|
||||
void do_job() {
|
||||
auto update_info = poll_info();
|
||||
if (update_info.m_error) {
|
||||
util::logger::error("Failed to poll newest version info: %s", update_info.m_error_desc.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (update_info.m_version <= UNSPOTIFY_VERSION) // @note: es3n1n: if we are up2date
|
||||
return;
|
||||
|
||||
if (update_info.m_is_required) {
|
||||
util::logger::fatal("New version is available!\n\nChangelog:\n%s\nDownload url: %s", update_info.m_changelog.c_str(),
|
||||
update_info.m_download_url.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
util::logger::info("New version is available!");
|
||||
util::logger::info("");
|
||||
util::logger::info("");
|
||||
util::logger::info("Changelog:");
|
||||
printf("%s\n", update_info.m_changelog.c_str());
|
||||
util::logger::info("");
|
||||
util::logger::info("");
|
||||
util::logger::info("Download url: %s", update_info.m_download_url.c_str());
|
||||
}
|
||||
} // namespace updates
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
#include "defines.h"
|
||||
#include "shared/logger.h"
|
||||
#include "util/networking/networking.h"
|
||||
|
||||
namespace updates {
|
||||
struct update_info_t {
|
||||
bool m_error = false;
|
||||
std::string m_error_desc = "Unable to connect to server";
|
||||
|
||||
uint32_t m_version = UNSPOTIFY_VERSION;
|
||||
std::string m_changelog = "Failed to request update info";
|
||||
bool m_is_required = false;
|
||||
std::string m_download_url = "https://git.tcp.direct/dg/unspotify";
|
||||
};
|
||||
|
||||
update_info_t poll_info();
|
||||
void do_job();
|
||||
} // namespace updates
|
|
@ -1,15 +1,21 @@
|
|||
#include "detours.h"
|
||||
|
||||
|
||||
namespace util::hooking::detour {
|
||||
bool init() {
|
||||
return !MH_Initialize();
|
||||
}
|
||||
void init( ) {
|
||||
MH_Initialize( );
|
||||
}
|
||||
|
||||
bool create(void* target, void* detour, void** orig) {
|
||||
return MH_CreateHook(target, detour, orig) == MH_STATUS::MH_OK && MH_EnableHook(target) == MH_STATUS::MH_OK;
|
||||
}
|
||||
void create( mem::addr_t& target, void* detour, void** orig ) {
|
||||
return create( target.cast<void*>( ), detour, orig );
|
||||
}
|
||||
|
||||
bool remove(void* target) {
|
||||
return MH_DisableHook(target) == MH_STATUS::MH_OK;
|
||||
}
|
||||
} // namespace util::hooking::detour
|
||||
void create( void* target, void* detour, void** orig ) {
|
||||
if ( MH_CreateHook( target, detour, orig ) != MH_OK ) __debugbreak( );
|
||||
if ( MH_EnableHook( target ) != MH_OK ) __debugbreak( );
|
||||
}
|
||||
|
||||
void remove( void* target ) {
|
||||
if ( MH_DisableHook( target ) != MH_OK ) __debugbreak( );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "mh/minhook.h"
|
||||
#include "util/mem/addr.h"
|
||||
#include "../../mem/addr.h"
|
||||
|
||||
|
||||
namespace util::hooking::detour {
|
||||
bool init();
|
||||
bool create(void* target, void* detour, void** orig);
|
||||
bool remove(void* target = nullptr /* nullptr = MH_ALL_HOOKS */);
|
||||
} // namespace util::hooking::detour
|
||||
void init( );
|
||||
void create( mem::addr_t& target, void* detour, void** orig );
|
||||
void create( void* target, void* detour, void** orig );
|
||||
void remove( void* target = nullptr /* nullptr = MH_ALL_HOOKS */ );
|
||||
}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
#pragma once
|
||||
#include "vmt/vmt.h"
|
||||
#include "detours/detours.h"
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include "vmt.h"
|
||||
|
||||
|
||||
namespace util::hooking {
|
||||
namespace detail {
|
||||
region_protector::region_protector( void* base, size_t len, std::uint32_t flags ) {
|
||||
_base = base;
|
||||
_length = len;
|
||||
VirtualProtect( base, len, flags, ( PDWORD )&_old );
|
||||
}
|
||||
region_protector::~region_protector( ) {
|
||||
VirtualProtect( _base, _length, _old, ( PDWORD )&_old );
|
||||
}
|
||||
}
|
||||
|
||||
vmt::vmt( ) : class_base( nullptr ), vftbl_len( 0 ), new_vftbl( nullptr ), old_vftbl( nullptr ) {}
|
||||
vmt::vmt( void* base ) : class_base( base ), vftbl_len( 0 ), new_vftbl( nullptr ), old_vftbl( nullptr ) {}
|
||||
vmt::~vmt( ) {
|
||||
unhook( );
|
||||
delete[ ] new_vftbl;
|
||||
}
|
||||
|
||||
void vmt::setup( void* base ) {
|
||||
if ( base != nullptr )
|
||||
class_base = base;
|
||||
|
||||
old_vftbl = *reinterpret_cast< std::uintptr_t** >( class_base );
|
||||
vftbl_len = estimate_vftbl_length( old_vftbl ) * sizeof( std::uintptr_t );
|
||||
|
||||
new_vftbl = new std::uintptr_t[ vftbl_len + 1 ]( );
|
||||
|
||||
std::memcpy( &new_vftbl[ 1 ], old_vftbl, vftbl_len * sizeof( std::uintptr_t ) );
|
||||
|
||||
auto guard = detail::region_protector { class_base, sizeof( std::uintptr_t ), PAGE_READWRITE };
|
||||
new_vftbl[ 0 ] = old_vftbl[ -1 ];
|
||||
*reinterpret_cast< std::uintptr_t** >( class_base ) = &new_vftbl[ 1 ];
|
||||
}
|
||||
|
||||
std::size_t vmt::estimate_vftbl_length( std::uintptr_t* vftbl_start ) {
|
||||
MEMORY_BASIC_INFORMATION memInfo = { NULL };
|
||||
int m_nSize = -1;
|
||||
do {
|
||||
m_nSize++;
|
||||
VirtualQuery( reinterpret_cast< LPCVOID >( vftbl_start[ m_nSize ] ), &memInfo, sizeof( memInfo ) );
|
||||
} while ( memInfo.Protect == PAGE_EXECUTE_READ || memInfo.Protect == PAGE_EXECUTE_READWRITE );
|
||||
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
void vmt::unhook( ) {
|
||||
if ( old_vftbl == nullptr ) return;
|
||||
|
||||
auto guard = detail::region_protector { class_base, sizeof( std::uintptr_t ), PAGE_READWRITE };
|
||||
*reinterpret_cast< std::uintptr_t** >( class_base ) = old_vftbl;
|
||||
old_vftbl = nullptr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
#include "../../mem/addr.h"
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace util::hooking {
|
||||
namespace detail {
|
||||
class region_protector {
|
||||
public:
|
||||
region_protector( void* base, size_t len, std::uint32_t flags );
|
||||
~region_protector( );
|
||||
|
||||
private:
|
||||
void* _base;
|
||||
size_t _length;
|
||||
std::uint32_t _old;
|
||||
};
|
||||
}
|
||||
|
||||
class vmt {
|
||||
public:
|
||||
vmt( );
|
||||
vmt( void* base );
|
||||
~vmt( );
|
||||
|
||||
void setup( void* base = nullptr );
|
||||
|
||||
template<typename T>
|
||||
void hook( int index, T fun ) {
|
||||
new_vftbl[ index + 1 ] = reinterpret_cast< std::uintptr_t >( fun );
|
||||
}
|
||||
|
||||
void unhook( );
|
||||
|
||||
template<typename T>
|
||||
T original( int index ) {
|
||||
return reinterpret_cast< T >( old_vftbl[ index ] );
|
||||
}
|
||||
|
||||
private:
|
||||
static inline std::size_t estimate_vftbl_length( std::uintptr_t* vftbl_start );
|
||||
|
||||
void* class_base;
|
||||
std::size_t vftbl_len;
|
||||
std::uintptr_t* new_vftbl;
|
||||
std::uintptr_t* old_vftbl;
|
||||
};
|
||||
}
|
|
@ -1,137 +1,103 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace util::mem {
|
||||
template <typename ptr_type = std::uintptr_t>
|
||||
struct memory_address_t {
|
||||
public:
|
||||
//
|
||||
// constructors etc...
|
||||
memory_address_t(): m_ptr(ptr_type(0)){};
|
||||
memory_address_t(ptr_type v): m_ptr(v){};
|
||||
memory_address_t(void* v): m_ptr(ptr_type(v)){};
|
||||
memory_address_t(const void* v): m_ptr(ptr_type(v)){};
|
||||
~memory_address_t() = default;
|
||||
template< typename ptr_type = std::uintptr_t >
|
||||
struct memory_address_t {
|
||||
public:
|
||||
//
|
||||
// constructors etc...
|
||||
memory_address_t( ) : m_ptr( ptr_type( 0 ) ) { };
|
||||
memory_address_t( ptr_type v ) : m_ptr( v ) { };
|
||||
memory_address_t( void* v ) : m_ptr( ptr_type( v ) ) { };
|
||||
memory_address_t( const void* v ) : m_ptr( ptr_type( v ) ) { };
|
||||
~memory_address_t( ) = default;
|
||||
|
||||
//
|
||||
// operators
|
||||
inline operator ptr_type() {
|
||||
return m_ptr;
|
||||
}
|
||||
//
|
||||
// operators
|
||||
inline operator ptr_type( ) {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
inline operator void*() {
|
||||
return reinterpret_cast<void*>(m_ptr);
|
||||
}
|
||||
inline operator void* ( ) {
|
||||
return reinterpret_cast< void* >( m_ptr );
|
||||
}
|
||||
|
||||
inline memory_address_t& operator+=(ptr_type offset) {
|
||||
m_ptr += offset;
|
||||
return *this;
|
||||
}
|
||||
inline memory_address_t& operator+=( ptr_type offset ) {
|
||||
m_ptr += offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline memory_address_t& operator-=(ptr_type offset) {
|
||||
m_ptr -= offset;
|
||||
return *this;
|
||||
}
|
||||
inline memory_address_t& operator-=( ptr_type offset ) {
|
||||
m_ptr -= offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline memory_address_t operator-(ptr_type offset) {
|
||||
return memory_address_t<ptr_type>(m_ptr - offset);
|
||||
}
|
||||
inline memory_address_t operator-( ptr_type offset ) {
|
||||
return memory_address_t<ptr_type>( m_ptr - offset );
|
||||
}
|
||||
|
||||
inline memory_address_t operator+(ptr_type offset) {
|
||||
return add(offset);
|
||||
}
|
||||
inline memory_address_t operator+( ptr_type offset ) {
|
||||
return add( offset );
|
||||
}
|
||||
|
||||
inline bool operator>(ptr_type v2) {
|
||||
return m_ptr > v2;
|
||||
}
|
||||
inline bool operator>( ptr_type v2 ) {
|
||||
return m_ptr > v2;
|
||||
}
|
||||
|
||||
inline bool operator>=(ptr_type v2) {
|
||||
return m_ptr >= v2;
|
||||
}
|
||||
inline bool operator>=( ptr_type v2 ) {
|
||||
return m_ptr >= v2;
|
||||
}
|
||||
|
||||
inline bool operator<(ptr_type v2) {
|
||||
return m_ptr < v2;
|
||||
}
|
||||
inline bool operator<( ptr_type v2 ) {
|
||||
return m_ptr < v2;
|
||||
}
|
||||
|
||||
inline bool operator<=(ptr_type v2) {
|
||||
return m_ptr <= v2;
|
||||
}
|
||||
inline bool operator<=( ptr_type v2 ) {
|
||||
return m_ptr <= v2;
|
||||
}
|
||||
|
||||
inline memory_address_t add(ptr_type offset) {
|
||||
return memory_address_t<ptr_type>(m_ptr + offset);
|
||||
}
|
||||
inline memory_address_t add( ptr_type offset ) {
|
||||
return memory_address_t<ptr_type>( m_ptr + offset );
|
||||
}
|
||||
|
||||
template <typename t = uint32_t>
|
||||
inline memory_address_t rel(ptr_type offset) {
|
||||
return this->add(this->add(offset).template read<t>()).add(offset + sizeof(t));
|
||||
}
|
||||
template <typename t = uint32_t>
|
||||
inline memory_address_t relative_asm_address( ptr_type offset ) {
|
||||
return this->add( this->add( offset ).read<t>( ) ).add( offset + sizeof( t ) );
|
||||
}
|
||||
|
||||
//
|
||||
// utils
|
||||
memory_address_t<ptr_type> offset(ptr_type off) {
|
||||
return memory_address_t<ptr_type>(m_ptr + off);
|
||||
}
|
||||
//
|
||||
// utils
|
||||
memory_address_t<ptr_type> offset( ptr_type off ) { return memory_address_t<ptr_type>( m_ptr + off ); }
|
||||
|
||||
template <typename T>
|
||||
T read() {
|
||||
return *ptr<T>();
|
||||
}
|
||||
template <typename T>
|
||||
T read( ) { return *ptr<T>( ); }
|
||||
|
||||
template <typename T>
|
||||
T* read_ptr() {
|
||||
return read<T*>();
|
||||
}
|
||||
template <typename T>
|
||||
T* read_ptr( ) { return read<T*>( ); }
|
||||
|
||||
template <typename T>
|
||||
void write(T value) {
|
||||
*ptr<T>() = value;
|
||||
}
|
||||
template <typename T>
|
||||
void write( T value ) { *ptr<T>( ) = value; }
|
||||
|
||||
template <typename T>
|
||||
T* ptr() {
|
||||
return reinterpret_cast<T*>(m_ptr);
|
||||
}
|
||||
template<typename T>
|
||||
T* ptr( ) { return reinterpret_cast< T* >( m_ptr ); }
|
||||
|
||||
template <typename T>
|
||||
T cast() {
|
||||
return reinterpret_cast<T>(m_ptr);
|
||||
}
|
||||
template <typename T>
|
||||
T cast( ) { return reinterpret_cast< T >( m_ptr ); }
|
||||
|
||||
memory_address_t<ptr_type>& self_get(ptr_type count = 1) {
|
||||
for (ptr_type i = 0; i < count; i++)
|
||||
m_ptr = *reinterpret_cast<ptr_type*>(m_ptr);
|
||||
return *this;
|
||||
}
|
||||
memory_address_t<ptr_type>& self_get( ptr_type count = 1 ) {
|
||||
for ( ptr_type i = 0; i < count; i++ )
|
||||
m_ptr = *reinterpret_cast< ptr_type* >( m_ptr );
|
||||
return *this;
|
||||
}
|
||||
|
||||
memory_address_t<ptr_type> walk_until(uint8_t byte) {
|
||||
constexpr int max_iterations = 1000;
|
||||
for (int i = 0; i < max_iterations; i++) {
|
||||
if (offset(i).template read<uint8_t>() != byte)
|
||||
continue;
|
||||
return offset(i);
|
||||
}
|
||||
return memory_address_t<ptr_type>();
|
||||
}
|
||||
inline bool valid( ) { return static_cast< bool >( m_ptr ); }
|
||||
|
||||
memory_address_t<ptr_type> walk_back_until(uint8_t byte) {
|
||||
constexpr int max_iterations = 1000;
|
||||
for (int i = 1; i < max_iterations; i++) {
|
||||
if (offset(-i).template read<uint8_t>() != byte)
|
||||
continue;
|
||||
return offset(-i);
|
||||
}
|
||||
return memory_address_t<ptr_type>();
|
||||
}
|
||||
ptr_type raw( ) { return m_ptr; }
|
||||
|
||||
inline bool valid() {
|
||||
return static_cast<bool>(m_ptr) && m_ptr > 15;
|
||||
}
|
||||
|
||||
ptr_type raw() {
|
||||
return m_ptr;
|
||||
}
|
||||
private:
|
||||
ptr_type m_ptr;
|
||||
};
|
||||
using addr_t = mem::memory_address_t<std::uintptr_t>;
|
||||
} // namespace util::mem
|
||||
private:
|
||||
ptr_type m_ptr;
|
||||
};
|
||||
using addr_t = mem::memory_address_t< std::uintptr_t >;
|
||||
}
|
|
@ -1,92 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/mem/addr.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
#include "../mem/addr.h"
|
||||
|
||||
|
||||
namespace util::mem {
|
||||
struct module_t {
|
||||
public:
|
||||
//
|
||||
// constructors, etc...
|
||||
module_t(): m_addr(){};
|
||||
module_t(uintptr_t s): m_addr(s){};
|
||||
module_t(const char* module_name): m_addr(GetModuleHandleA(module_name)){};
|
||||
~module_t() = default;
|
||||
public:
|
||||
//
|
||||
// exports related
|
||||
mem::addr_t get_export(const char* name) {
|
||||
return mem::addr_t(reinterpret_cast<void*>(GetProcAddress(m_addr.cast<HMODULE>(), name)));
|
||||
}
|
||||
struct module_t {
|
||||
public:
|
||||
//
|
||||
// constructors, etc...
|
||||
module_t( ) : m_addr( ) { };
|
||||
module_t( const char* module_name ) : m_addr( GetModuleHandleA( module_name ) ) { };
|
||||
~module_t( ) = default;
|
||||
|
||||
//
|
||||
// pattern scan related
|
||||
public:
|
||||
mem::addr_t sig(std::string_view pattern) {
|
||||
return sig(pattern_to_byte(pattern));
|
||||
}
|
||||
public:
|
||||
//
|
||||
// exports related
|
||||
mem::addr_t get_export( const char* name ) {
|
||||
return mem::addr_t( reinterpret_cast< void* >( GetProcAddress( m_addr.cast<HMODULE>( ), name ) ) );
|
||||
}
|
||||
|
||||
mem::addr_t sig(std::vector<int> pattern_bytes) {
|
||||
unsigned long image_size = get_nt_headers()->OptionalHeader.SizeOfImage;
|
||||
int* pattern_data = pattern_bytes.data();
|
||||
size_t pattern_size = pattern_bytes.size();
|
||||
//
|
||||
// pattern scan related
|
||||
public:
|
||||
mem::addr_t sig( std::string_view pattern ) {
|
||||
unsigned long image_size = get_nt_headers( )->OptionalHeader.SizeOfImage;
|
||||
|
||||
for (unsigned long i = 0ul; i < image_size - pattern_size; i++) {
|
||||
bool found = true;
|
||||
std::vector<int> pattern_bytes = pattern_to_byte( pattern );
|
||||
int* pattern_data = pattern_bytes.data( );
|
||||
size_t pattern_size = pattern_bytes.size( );
|
||||
|
||||
for (unsigned long j = 0ul; j < pattern_size; j++) {
|
||||
if (pattern_data[j] == -1)
|
||||
continue;
|
||||
if (m_addr.offset(i + j).read<std::uint8_t>() == pattern_data[j])
|
||||
continue;
|
||||
for ( unsigned long i = 0ul; i < image_size - pattern_size; i++ ) {
|
||||
bool found = true;
|
||||
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
for ( unsigned long j = 0ul; j < pattern_size; j++ ) {
|
||||
if ( pattern_data[ j ] == -1 )
|
||||
continue;
|
||||
if ( m_addr.offset( i + j ).read<std::uint8_t>( ) == pattern_data[ j ] )
|
||||
continue;
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return m_addr.offset(i);
|
||||
}
|
||||
if ( !found )
|
||||
continue;
|
||||
|
||||
return mem::addr_t();
|
||||
}
|
||||
public:
|
||||
bool safe(std::uintptr_t ptr) {
|
||||
return ptr >= m_addr && ptr <= m_addr.add(get_nt_headers()->OptionalHeader.SizeOfImage);
|
||||
}
|
||||
public:
|
||||
IMAGE_DOS_HEADER* get_dos_headers() {
|
||||
return m_addr.ptr<IMAGE_DOS_HEADER>();
|
||||
}
|
||||
return m_addr.offset( i );
|
||||
}
|
||||
|
||||
IMAGE_NT_HEADERS* get_nt_headers() {
|
||||
return m_addr.offset(get_dos_headers()->e_lfanew).ptr<IMAGE_NT_HEADERS>();
|
||||
}
|
||||
protected:
|
||||
std::vector<int> pattern_to_byte(std::string_view pattern) {
|
||||
auto bytes = std::vector<int>{};
|
||||
auto start = const_cast<char*>(pattern.data());
|
||||
auto end = const_cast<char*>(start) + pattern.length();
|
||||
return mem::addr_t( );
|
||||
}
|
||||
public:
|
||||
bool safe( std::uintptr_t ptr ) {
|
||||
return ptr >= m_addr && ptr <= m_addr.add( get_nt_headers( )->OptionalHeader.SizeOfImage );
|
||||
}
|
||||
protected:
|
||||
IMAGE_DOS_HEADER* get_dos_headers( ) {
|
||||
return m_addr.ptr<IMAGE_DOS_HEADER>( );
|
||||
}
|
||||
|
||||
for (auto current = start; current < end; ++current) {
|
||||
if (*current == '?') {
|
||||
++current;
|
||||
IMAGE_NT_HEADERS* get_nt_headers( ) {
|
||||
return m_addr.offset( get_dos_headers( )->e_lfanew ).ptr< IMAGE_NT_HEADERS >( );
|
||||
}
|
||||
protected:
|
||||
std::vector< int > pattern_to_byte( std::string_view pattern ) {
|
||||
auto bytes = std::vector<int> {};
|
||||
auto start = const_cast< char* >( pattern.data( ) );
|
||||
auto end = const_cast< char* >( start ) + pattern.length( );
|
||||
|
||||
if (*current == '?')
|
||||
++current;
|
||||
for ( auto current = start; current < end; ++current ) {
|
||||
if ( *current == '?' ) {
|
||||
++current;
|
||||
|
||||
bytes.emplace_back(-1);
|
||||
} else
|
||||
bytes.emplace_back(strtoul(current, ¤t, 16));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
private:
|
||||
mem::addr_t m_addr;
|
||||
};
|
||||
} // namespace util::mem
|
||||
if ( *current == '?' )
|
||||
++current;
|
||||
|
||||
bytes.emplace_back( -1 );
|
||||
} else
|
||||
bytes.emplace_back( strtoul( current, ¤t, 16 ) );
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private:
|
||||
mem::addr_t m_addr;
|
||||
};
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,47 +0,0 @@
|
|||
#include "networking.h"
|
||||
|
||||
namespace util {
|
||||
namespace networking {
|
||||
errorable_json_result get(const char* domain, const char* url) {
|
||||
std::string response_data = err_json_data;
|
||||
|
||||
auto internet_session = InternetOpenA("Unspotify/1.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||
|
||||
if (!internet_session)
|
||||
return {nlohmann::json::parse(response_data), true};
|
||||
|
||||
auto http_session = InternetConnectA(internet_session, domain, 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
|
||||
|
||||
if (!http_session)
|
||||
return {nlohmann::json::parse(response_data), true};
|
||||
|
||||
HINTERNET http_req = HttpOpenRequestA(http_session, "GET", url, 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
|
||||
|
||||
if (!http_session)
|
||||
return nlohmann::json::parse(response_data);
|
||||
|
||||
const char* szHeaders = "Content-Type: application/json\r\nUser-Agent: Unspotify/1.0";
|
||||
|
||||
if (!HttpSendRequestA(http_req, szHeaders, strlen(szHeaders), NULL, NULL))
|
||||
return {response_data, true};
|
||||
|
||||
response_data.clear();
|
||||
|
||||
CHAR temp_buffer[1024] = {0};
|
||||
DWORD read_ret = 0;
|
||||
|
||||
while (InternetReadFile(http_req, temp_buffer, sizeof(temp_buffer) - 1, &read_ret) && read_ret)
|
||||
response_data.append(temp_buffer, read_ret);
|
||||
|
||||
InternetCloseHandle(http_req);
|
||||
InternetCloseHandle(http_session);
|
||||
InternetCloseHandle(internet_session);
|
||||
|
||||
try {
|
||||
return {nlohmann::json::parse(response_data), false};
|
||||
} catch (const nlohmann::json::parse_error& err [[maybe_unused]]) {
|
||||
return {nlohmann::json::parse(err_json_data), true};
|
||||
}
|
||||
}
|
||||
} // namespace networking
|
||||
} // namespace util
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
// clang-format off
|
||||
#include <Windows.h>
|
||||
#include <WinInet.h>
|
||||
#include <urlmon.h>
|
||||
// clang-format on
|
||||
#include <map>
|
||||
|
||||
#include "ext/json.hpp"
|
||||
|
||||
#pragma comment(lib, "urlmon.lib")
|
||||
#pragma comment(lib, "wininet.lib")
|
||||
|
||||
namespace util {
|
||||
namespace networking {
|
||||
using errorable_json_result = std::pair<nlohmann::json, bool>;
|
||||
constexpr const char* err_json_data = "{\"error\": \"Unable to connect to server\"}";
|
||||
|
||||
errorable_json_result get(const char* domain, const char* url);
|
||||
} // namespace networking
|
||||
} // namespace util
|
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
#include "hooking/hooking.h"
|
||||
#include "shared/logger.h"
|
||||
#include "mem/addr.h"
|
||||
#include "mem/module.h"
|
||||
#include "shared/logger.h"
|
||||
|
||||
namespace util { }
|
||||
|
||||
namespace util {}
|
||||
|
||||
|
|
Loading…
Reference in New Issue