This commit is contained in:
Ploosh
2024-06-06 10:28:48 -04:00
commit 7e9cab52fd
47 changed files with 3553 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
x64/
*/x64
Starfall/Starfall
*/*.vcxproj.user
.vs
*/Release
*/Debug
+28
View File
@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2024, Starfall
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+22
View File
@@ -0,0 +1,22 @@
# Starfall
Starfall is a universal SSL bypass / redirect for native UE HTTP games, made for Fortnite. <br>
# Configuring Starfall
## Changing Starfall's Backend URL.
To change Starfall's backend URL to your's go to ``Starfall/opts.h`` and change the ``Backend`` variable to your Backend URL.
## Build for a Hybrid
Go to ``Starfall/opts.h`` and change ``UrlSet`` to Hybrid.
## Build for a Dev
Go to ``Starfall/opts.h`` and change ``UrlSet`` to Dev.
## Redirecting every URL
Go to ``Starfall/opts.h`` and change ``UrlSet`` to All.
## Enabling Console for debugging
Go to ``Starfall/opts.h`` and change ``Console`` to true.
# Other
If you use Starfall for a project please credit me.
+34
View File
@@ -0,0 +1,34 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34616.47
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plooshfinder", "plooshfinder\plooshfinder.vcxproj", "{1EFDB154-D3B5-43BC-8733-F3D6941C9E36}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Starfall", "Starfall\Starfall.vcxproj", "{9C02D0A1-F786-4B04-B466-8D58C5B74FD1}"
ProjectSection(ProjectDependencies) = postProject
{1EFDB154-D3B5-43BC-8733-F3D6941C9E36} = {1EFDB154-D3B5-43BC-8733-F3D6941C9E36}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1EFDB154-D3B5-43BC-8733-F3D6941C9E36}.Debug|x64.ActiveCfg = Debug|x64
{1EFDB154-D3B5-43BC-8733-F3D6941C9E36}.Debug|x64.Build.0 = Debug|x64
{1EFDB154-D3B5-43BC-8733-F3D6941C9E36}.Release|x64.ActiveCfg = Release|x64
{1EFDB154-D3B5-43BC-8733-F3D6941C9E36}.Release|x64.Build.0 = Release|x64
{9C02D0A1-F786-4B04-B466-8D58C5B74FD1}.Debug|x64.ActiveCfg = Debug|x64
{9C02D0A1-F786-4B04-B466-8D58C5B74FD1}.Debug|x64.Build.0 = Debug|x64
{9C02D0A1-F786-4B04-B466-8D58C5B74FD1}.Release|x64.ActiveCfg = Release|x64
{9C02D0A1-F786-4B04-B466-8D58C5B74FD1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2BE449DA-BD65-4FB2-9582-A7FCB41F1393}
EndGlobalSection
EndGlobal
+118
View File
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<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>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{9c02d0a1-f786-4b04-b466-8d58c5b74fd1}</ProjectGuid>
<RootNamespace>Starfall</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</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" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;STARFALL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;STARFALL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<IntelJCCErratum>false</IntelJCCErratum>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<EntryPointSymbol>
</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="base.h" />
<ClInclude Include="exit.h" />
<ClInclude Include="hooking.h" />
<ClInclude Include="opts.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="redirection.h" />
<ClInclude Include="request.h" />
<ClInclude Include="ue.h" />
<ClInclude Include="url.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="base.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="exit.cpp" />
<ClCompile Include="hooking.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="redirection.cpp" />
<ClCompile Include="request.cpp" />
<ClCompile Include="ue.cpp" />
<ClCompile Include="url.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+75
View File
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="opts.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="redirection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="url.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hooking.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="exit.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="base.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="request.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="exit.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="base.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hooking.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="redirection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="url.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="request.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+14
View File
@@ -0,0 +1,14 @@
#include "pch.h"
#include "base.h"
namespace Starfall {
namespace Globals {
void* buf;
void* tbuf;
size_t tsize;
void* rbuf;
size_t rsize;
}
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "opts.h"
#include "pch.h"
namespace Starfall {
namespace Globals {
extern void* buf;
//extern size_t size;
extern void* tbuf;
extern size_t tsize;
extern void* rbuf;
extern size_t rsize;
}
using namespace Globals;
};
using namespace Starfall;
#define Log(type, ...) if (Console) printf("LogStarfall: " #type ": " __VA_ARGS__)
+54
View File
@@ -0,0 +1,54 @@
#include "pch.h"
#include "base.h"
#include "request.h"
#include "exit.h"
#include "opts.h"
namespace Starfall {
void Init() {
if (Console) {
AllocConsole();
FILE* fptr;
freopen_s(&fptr, "CONOUT$", "w+", stdout);
SetConsoleTitleA("Starfall - https://github.com/ParadiseFN/Starfall");
}
if (UseBackendParam) {
FString cmd = GetCommandLineW();
auto pos = cmd.find(L"-backend=");
if (pos != std::wstring::npos) {
backend = cmd.substr(pos + 9);
}
else {
backend = Backend;
}
}
buf = *(void**)(__readgsqword(0x60) + 0x10);
auto section = pe_get_section((char*)buf, ".text");
auto rsection = pe_get_section((char*)buf, ".rdata");
tbuf = (void*)(__int64(buf) + section->virtualAddress);
tsize = section->virtualSize;
rbuf = (void*)(__int64(buf) + rsection->virtualAddress);
rsize = rsection->virtualSize;
FindProcessRequest();
if (Game == Fortnite) FindPushWidget();
return;
}
}
BOOL APIENTRY DllMain( HMODULE dllBase,
DWORD callReason,
LPVOID lpReserved
)
{
if (callReason == 1) ManualMapping ? Init() : (void) CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Init, 0, 0, 0);
return TRUE;
}
+90
View File
@@ -0,0 +1,90 @@
#include "pch.h"
#include "hooking.h"
#include "base.h"
#include "exit.h"
namespace Starfall {
int dontExit = 0;
namespace Hooks {
void RequestExitWithStatusHook(bool Force, unsigned char Code)
{
if (dontExit == 0) {
TerminateProcess(GetCurrentProcess(), Code);
}
else {
dontExit--;
}
}
void UnsafeEnvironmentPopupHook(wchar_t** unknown1, unsigned __int8 _case, __int64 unknown2, char unknown3)
{
dontExit++;
}
}
namespace Callbacks {
bool RequestExitWithStatusCallback(struct pf_patch_t* patch, void* stream) {
AsmHook(stream, Hooks::RequestExitWithStatusHook);
return true;
}
bool UnsafeEnvironmentPopupCallback(struct pf_patch_t* patch, void* stream) {
AsmHook(stream, Hooks::UnsafeEnvironmentPopupHook);
return true;
}
bool PushWidgetCallback(struct pf_patch_t* patch, void* stream) {
FindExit();
return true;
}
}
namespace Finders {
void FindExit() {
constexpr static struct pf_patch_t patch = pf_construct_patch_sig("48 89 5C 24 ? 57 48 83 EC 40 41 B9 ? ? ? ? 0F B6 F9 44 38 0D ? ? ? ? 0F B6 DA 72 24 89 5C 24 30 48 8D 05 ? ? ? ? 89 7C 24 28 4C 8D 05 ? ? ? ? 33 D2 48 89 44 24 ? 33 C9 E8 ? ? ? ?", RequestExitWithStatusCallback);
constexpr static struct pf_patch_t patch2 = pf_construct_patch_sig("48 8B C4 48 89 58 18 88 50 10 88 48 08 57 48 83 EC 30", RequestExitWithStatusCallback);
constexpr static struct pf_patch_t patch3 = pf_construct_patch_sig("4C 8B DC 49 89 5B 08 49 89 6B 10 49 89 73 18 49 89 7B 20 41 56 48 83 EC 30 80 3D ? ? ? ? ? 49 8B", RequestExitWithStatusCallback);
constexpr static struct pf_patch_t patch4 = pf_construct_patch_sig("4C 8B DC 55 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 49 89 73 F0 49 89 7B E8 48 8B F9 4D 89 63 E0 4D 8B E0 4D 89 6B D8", Ret0Callback); // 17.30
constexpr static struct pf_patch_t patch5 = pf_construct_patch_sig("4C 8B DC 55 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 49 89 5B 20 48 8B D9 4D 89 63 E0 4D 89 6B D8", Ret0Callback); // 19.10
constexpr static struct pf_patch_t patch6 = pf_construct_patch_sig("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 80 B9 ? ? ? ? ? 48 8B DA 48 8B F1", Ret0Callback); // 28.00
constexpr static struct pf_patch_t patch7 = pf_construct_patch_sig("40 55 53 56 57 41 54 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? ? 0F B6 ?", Ret0Callback); // 29.00/22.40
constexpr static struct pf_patch_t patch8 = pf_construct_patch_sig("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? ? 0F B6 ? 44 88 44 24 ?", Ret0Callback); // 30.00
constexpr static struct pf_patch_t patches2[] = {
patch,
patch2,
patch3,
patch4,
patch5,
patch6,
patch7,
patch8
};
constexpr static struct pf_patchset_t patchset2 = pf_construct_patchset(patches2, sizeof(patches2) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
pf_patchset_emit(tbuf, tsize, patchset2);
}
void FindPushWidget()
{
constexpr static auto patch = pf_construct_patch_sig("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 30 48 8B E9 49 8B D9 48 8D 0D ? ? ? ? 49 8B F8 48 8B F2 E8 ? ? ? ? 4C 8B CF 48 89 5C 24 ? 4C 8B C6 48 8B D5 48 8B 48 78", PushWidgetCallback);
constexpr static auto patch2 = pf_construct_patch_sig("48 8B C4 4C 89 40 18 48 89 50 10 48 89 48 08 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 B8 48 81 EC ? ? ? ? 65 48 8B 04 25", PushWidgetCallback); // 26.00
constexpr static auto patch3 = pf_construct_patch_sig("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 65 48 8B 04 25 ? ? ? ? 48 8B F9 B9 ? ? ? ? 49", PushWidgetCallback); // 28.00
constexpr static auto patch4 = pf_construct_patch_sig("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 65 48 8B 04 25 ? ? ? ? 48 8B F9 B9 ? ? ? ? 48", PushWidgetCallback); // 30.00
constexpr static struct pf_patch_t patches[] = {
patch,
patch2,
patch3,
patch4
};
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
pf_patchset_emit(tbuf, tsize, patchset);
}
}
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "pch.h"
namespace Starfall {
namespace Callbacks {
bool RequestExitWithStatusCallback(struct pf_patch_t* patch, void* stream);
bool PushWidgetCallback(struct pf_patch_t* patch, void* stream);
}
using namespace Callbacks;
namespace Finders {
void FindExit();
void FindPushWidget();
}
using namespace Finders;
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include "pch.h"
#include "hooking.h"
namespace Starfall {
namespace Hooking {
__forceinline void AsmHook(uint64_t ptr, void* detour) {
AsmHook((void*)ptr, detour);
}
bool Ret0Callback(struct pf_patch_t* patch, void* stream) {
DWORD og;
VirtualProtect(stream, 1, PAGE_EXECUTE_READWRITE, &og);
*(uint8_t*)stream = (uint8_t)0xC3;
VirtualProtect(stream, 1, og, &og);
return true;
}
void VTHook(void** addr, void* detour, void** orig) {
DWORD oldProt;
VirtualProtect(addr, sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProt);
if (orig) *orig = *addr;
*addr = detour;
VirtualProtect(addr, sizeof(void*), oldProt, &oldProt);
}
}
__declspec(noinline) bool InternalCheckBytes(void* base, int ind, const uint8_t* bytes, size_t sz, bool upwards) {
auto offBase = (uint8_t*)(upwards ? __int64(base) - ind : __int64(base) + ind);
for (int i = 0; i < sz; i++) {
if (*(offBase + i) != bytes[i]) return false;
}
return true;
}
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include "pch.h"
namespace Starfall {
namespace Hooking {
__forceinline void AsmHook(void* ptr, void* detour) {
if (!ptr || !detour) return;
uint8_t data[] = {
0x41, 0x52, // push r10
0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, detour
0x41, 0xFF, 0xD2, // call r10
0x41, 0x5A, // pop r10
0xC3 // ret
};
DWORD oldProt;
VirtualProtect(ptr, sizeof(data), PAGE_EXECUTE_READWRITE, &oldProt);
memcpy(ptr, data, sizeof(data));
*(uint64_t*)(__int64(ptr) + 4) = (uint64_t)detour;
VirtualProtect(ptr, sizeof(data), oldProt, &oldProt);
}
__forceinline void AsmHook(uint64_t ptr, void* detour);
bool Ret0Callback(struct pf_patch_t* patch, void* stream);
void VTHook(void** addr, void* detour, void** orig = nullptr);
}
using namespace Hooking;
bool InternalCheckBytes(void* base, int ind, const uint8_t* bytes, size_t sz, bool upwards = false);
template <uint8_t... Data>
class CheckBytes {
public:
constexpr static uint8_t bytes[sizeof...(Data)] = { Data... };
void* Base;
int Ind;
bool Upwards;
CheckBytes(void* base, int ind, bool upwards = false) {
Base = base;
Ind = ind;
Upwards = upwards;
}
operator bool() {
return InternalCheckBytes(Base, Ind, bytes, sizeof...(Data), Upwards);
}
};
}
//#define CheckBytes(base, ind, bytes, upwards) CheckBytesInternal(base, ind, bytes.data(), bytes.size(), upwards)
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "ue.h"
constexpr bool Console = false; // if the console window should be created
constexpr StarfallURLSet URLSet = Default;
constexpr inline FString Backend = L"http://127.0.0.1:3551"; // your backend url
constexpr UEGame Game = Fortnite; // use Generic for any UE game other than fortnite
// misc options, don't change unless you know what you're doing
constexpr bool UseBackendParam = false; // for phoenix/paradise launcher
constexpr bool ManualMapping = false; // if you're using EAC & a manual mapper, then enable this for the dll to work
constexpr bool FixMemLeak = true; // memory leak fix
+1
View File
@@ -0,0 +1 @@
#include "pch.h"
+36
View File
@@ -0,0 +1,36 @@
#ifndef PCH_H
#define PCH_H
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <array>
#include <psapi.h>
#include <string_view>
namespace Plooshfinder {
#include "../plooshfinder/include/plooshfinder_sig.h"
#include "../plooshfinder/include/plooshfinder.h"
#include "../plooshfinder/include/formats/pe.h"
};
using namespace Plooshfinder;
namespace Starfall {
namespace Types {
enum StarfallURLSet {
Default, // default, private server
Hybrid, // redirect profile, version, and content pages to private server, otherwise use official
Dev, // redirect profile & content pages to private server, otherwise use official
All, // redirect every single request to private server
};
enum UEGame {
Generic,
Fortnite
};
}
using namespace Types;
}
using namespace Starfall;
#endif
+58
View File
@@ -0,0 +1,58 @@
#include "pch.h"
#include "redirection.h"
#include "opts.h"
namespace Starfall {
namespace Redirection {
bool shouldRedirect(URL* uri) {
switch (URLSet) {
case ::Hybrid: {
constexpr static const wchar_t* redirectedPaths[] = {
L"/fortnite/api/v2/versioncheck/",
L"/fortnite/api/game/v2/profile/",
L"/content/api/pages/",
L"/affiliate/api/public/affiliates/slug",
L"/socialban/api/public/v1",
L"/fortnite/api/cloudstorage/system"
};
for (int i = 0; i < sizeof(redirectedPaths) / sizeof(wchar_t*); i++) {
if (uri->Path.starts_with(redirectedPaths[i])) return true;
}
break;
}
case ::Dev: {
constexpr static const wchar_t* redirectedPathsDev[] = {
L"/fortnite/api/game/v2/profile/",
L"/affiliate/api/public/affiliates/slug",
L"/content/api/pages/"
};
for (int i = 0; i < sizeof(redirectedPathsDev) / sizeof(wchar_t*); i++) {
if (uri->Path.starts_with(redirectedPathsDev[i])) return true;
}
break;
}
case ::Default: {
static constexpr const wchar_t *redirectedUrls[] = {
L"ol.epicgames.com",
L"ol.epicgames.net",
//L".akamaized.net", // if you have your own blurl
L"on.epicgames.com",
L"game-social.epicgames.com",
L"ak.epicgames.com",
//L"cdn2.unrealengine.com" // only needed if you have fixed friend images in friends list
};
for (int i = 0; i < sizeof(redirectedUrls) / sizeof(wchar_t *); i++) {
if (uri->Domain.ends_with(redirectedUrls[i])) return true;
}
break;
}
case ::All:
return true;
}
return false;
}
}
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include "pch.h"
#include "url.h"
namespace Starfall {
namespace Redirection {
bool shouldRedirect(URL* uri);
}
using namespace Redirection;
}
+225
View File
@@ -0,0 +1,225 @@
#include "pch.h"
#include "base.h"
#include "hooking.h"
#include "url.h"
#include "request.h"
#include "redirection.h"
#include <array>
#include "opts.h"
#include <time.h>
#include <sys/timeb.h>
#define CallVirt(T, vt, offset, ...) ((T) vt[offset])(__VA_ARGS__)
namespace Unreal {
FString FCurlHttpRequest::GetURL()
{
return GetURLFunc(this, FString());
}
void FCurlHttpRequest::SetURL(URL& URL)
{
FString str = URL;
SetURLFunc(this, str);
free(str.String);
}
}
namespace Starfall {
bool setupMemLeak = false;
void SetupRequest(FCurlHttpRequest* Request) {
if (FCurlHttpRequest::SetURLFunc == nullptr) {
void* GetFunc = *Request->VTable;
FCurlHttpRequest::GetURLFunc = (decltype(FCurlHttpRequest::GetURLFunc)) *Request->VTable;
uint32_t URLOffset = 0;
for (int i = 0; i < 100; i++) {
// this is only needed for latest
if (CheckBytes<0x48, 0x8D, 0x91>(GetFunc, i)) {
URLOffset = *(uint32_t*)(__int64(GetFunc) + i + 3);
break;
}
}
if (URLOffset == 0) goto def;
for (int64_t i = 0; i < ((__int64(FCurlHttpRequest::ProcessRequestVT) - __int64(Request->VTable)) / 8) /* search radius */; i++) {
auto func = Request->VTable[i];
for (int j = 0; j < 100; j++) {
if (CheckBytes<0x48, 0x81, 0xC1>(func, j)) {
if (*(uint32_t*)(__int64(func) + j + 3) == URLOffset) {
FCurlHttpRequest::SetURLFunc = (void (*)(FCurlHttpRequest*, FString)) Request->VTable[i];
return;
}
}
}
}
def:
FCurlHttpRequest::SetURLFunc = (void (*)(FCurlHttpRequest*, FString)) Request->VTable[10];
}
// this works bc the first request is a datarouter request, and the second request should be after engine init
else if (!setupMemLeak && Game == Fortnite) {
constexpr static struct pf_patch_t ml_patch = pf_construct_patch_sig("4C 8B DC 55 57 41 56 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 48 8B 01 41 B6", Ret0Callback);
constexpr static struct pf_patch_t patches[] = {
ml_patch
};
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
pf_patchset_emit(tbuf, tsize, patchset);
setupMemLeak = true;
}
}
FString backend;
namespace Hooks {
bool (*ProcessRequestOG)(FCurlHttpRequest* Request);
bool ProcessRequestHook(FCurlHttpRequest* Request) {
SetupRequest(Request);
auto urlS = Request->GetURL();
auto url = (URL *) malloc(sizeof(URL));
if (!url) return false;
__stosb((uint8_t*)url, 0, sizeof(URL));
url->Construct(urlS);
Log(Display, "URL: %ls\n", static_cast<wchar_t *>(urlS));
if (shouldRedirect(url)) {
Request->SetURL(UseBackendParam ? url->SetHost(backend) : url->SetHost<Backend>());
UseBackendParam ? url->Dealloc() : url->DeallocPathQuery();
}
else {
url->Dealloc();
}
free(url);
return ProcessRequestOG(Request);
}
}
namespace Callbacks {
bool PtrCallback(struct pf_patch_t* patch, void* stream) {
FCurlHttpRequest::ProcessRequestVT = (void**)stream;
VTHook((void**)stream, ProcessRequestHook, (void **) &ProcessRequestOG);
return true;
}
bool StringCallback(struct pf_patch_t* patch, void* stream) {
void* saddr = (void*)((__int64(stream) + 7) + *(int32_t*)(__int64(stream) + 3));
if (__int64(saddr) >= __int64(rbuf) && __int64(saddr) < (__int64(rbuf) + (int64_t)rsize)) {
if (wcscmp((wchar_t*)saddr, L"Could not set libcurl options for easy handle, processing HTTP request failed. Increase verbosity for additional information.") == 0) {
for (int i = 0; i < 2048; i++) {
if (CheckBytes<0x48, 0x81, 0xEC>(stream, i, true)) {
for (int x = 0; x < 50; x++) {
if (CheckBytes<0x40>(stream, i + x, true)) {
Log(Display, "Found using 4.24 & lower method\n");
stream = (uint8_t*)stream - i - x;
goto HookVT;
}
}
}
}
}
else if (wcscmp((wchar_t*)saddr, L"STAT_FCurlHttpRequest_ProcessRequest") == 0) {
for (int i = 0; i < 2048; i++) {
if (CheckBytes<0x4C, 0x8B, 0xDC>(stream, i, true)) {
Log(Display, "Found using 4.25 & 4.26 method\n");
goto setStream;
}
else if (CheckBytes<0x48, 0x8B, 0xC4>(stream, i, true)) {
Log(Display, "Found using UE 4.27 - 5.3 method\n");
setStream:
stream = (uint8_t*)stream - i;
goto HookVT;
}
else if (CheckBytes<0x48, 0x81, 0xEC>(stream, i, true) || CheckBytes<0x48, 0x83, 0xEC>(stream, i, true)) {
for (int x = 0; x < 50; x++) {
if (CheckBytes<0x40>(stream, i + x, true)) {
Log(Display, "Found using UE 4.25, 4.26 & 5.4+ method\n");
stream = (uint8_t*)stream - i - x;
goto HookVT;
} else if (CheckBytes<0x4C, 0x8B, 0xDC>(stream, i + x, true) || CheckBytes<0x4C, 0x8B, 0xC4>(stream, i + x, true)) break;
}
}
}
}
}
return false;
HookVT:
Log(Display, "ProcessRequest: 0x%llx\n", __int64(stream) - __int64(buf));
char* ptrMatches = (char*)&stream;
#ifndef _DEBUG
constexpr static char ptrMasks[] = {
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff
};
constexpr static auto patch2 = pf_construct_patch_dynmatch((void*)ptrMasks, 8, PtrCallback);
constexpr static struct pf_patch_t patches2[] = {
patch2
};
constexpr static struct pf_patchset_t patchset2 = pf_construct_patchset(patches2, sizeof(patches2) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
auto& patchToMod = (pf_patch_t &) patch2;
DWORD og;
VirtualProtect((void*)&(patchToMod.matches), sizeof(void*), PAGE_READWRITE, &og);
patchToMod.matches = ptrMatches;
VirtualProtect((void*)&(patchToMod.matches), sizeof(void*), og, &og);
#else
char ptrMasks[] = {
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff,
(char)0xff
};
auto patch2 = pf_construct_patch(ptrMatches, (void*)ptrMasks, 8, PtrCallback);
struct pf_patch_t patches2[] = {
patch2
};
struct pf_patchset_t patchset2 = pf_construct_patchset(patches2, sizeof(patches2) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
#endif
while (!pf_patchset_emit(rbuf, rsize, patchset2));
return true;
}
}
namespace Finders {
void FindProcessRequest() {
constexpr static std::array<uint8_t, 2> matches = {
0x48,
0x8d
};
constexpr static std::array<uint8_t, 2> masks = {
0xfb,
0xff
};
constexpr static auto patch = pf_construct_patch((void*)matches.data(), (void*)masks.data(), 2, StringCallback);
constexpr static pf_patch_t patches[] = {
patch
};
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), pf_find_maskmatch);
while (!pf_patchset_emit(tbuf, tsize, patchset));
}
}
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include "pch.h"
#include "ue.h"
#include "url.h"
#define CallVirt(T, vt, offset, ...) ((T) vt[offset])(__VA_ARGS__)
namespace Unreal {
class FCurlHttpRequest
{
public:
void** VTable;
static inline FString& (*GetURLFunc)(FCurlHttpRequest*, FString) = nullptr;
static inline void (*SetURLFunc)(FCurlHttpRequest*, FString) = nullptr;
static inline void** ProcessRequestVT = nullptr;
FString GetURL();
void SetURL(URL& URL);
};
}
namespace Starfall {
extern FString backend; // for phoenix/paradise launcher
void SetupRequest(FCurlHttpRequest* Request);
namespace Hooks {
bool ProcessRequestHook(FCurlHttpRequest* Request);
}
using namespace Hooks;
namespace Callbacks {
bool PtrCallback(struct pf_patch_t* patch, void* stream);
bool StringCallback(struct pf_patch_t* patch, void* stream);
}
using namespace Callbacks;
namespace Finders {
void FindProcessRequest();
}
using namespace Finders;
}
+172
View File
@@ -0,0 +1,172 @@
#include "pch.h"
#include "base.h"
#include "ue.h"
namespace Starfall {
template <typename T>
__forceinline T* Alloc(size_t sz) {
return (T*)malloc(sz);
}
}
namespace Unreal {
FString::FString()
{
String = nullptr;
Length = MaxSize = 0;
}
FString::FString(const char* Other)
{
if (Other)
{
MaxSize = Length = (int)strlen(Other) + 1;
AllocString();
size_t ConvertedChars = 0;
mbstowcs_s(&ConvertedChars, String, Length, Other, _TRUNCATE);
}
}
FString::FString(wchar_t* Other)
{
if (Other) {
MaxSize = Length = (int)wcslen(Other) + 1;
AllocString();
__movsb((PBYTE)String, (const PBYTE)Other, Length * sizeof(wchar_t));
}
}
FString::FString(uint32_t len) {
MaxSize = Length = len + 1;
AllocString();
}
__declspec(noinline) FString FString::operator+(FString other) {
if (!String || !other.String) return *this;
auto sLen = Length - 1;
auto oLen = other.Length - 1;
FString nStr((uint32_t)(sLen + oLen));
__movsb((PBYTE)nStr.String, (const PBYTE)String, sLen * sizeof(wchar_t));
__movsb((PBYTE)nStr.String + sLen * sizeof(wchar_t), (const PBYTE)other.String, oLen * sizeof(wchar_t));
nStr.String[nStr.Length - 1] = 0;
return nStr;
}
__declspec(noinline) void FString::operator+=(FString other) {
if (!String || !other.String) return;
auto sLen = Length - 1;
auto oLen = other.Length - 1;
Length = (uint32_t)(sLen + oLen + 1);
auto os = String;
AllocString();
__movsb((PBYTE)String, (const PBYTE)os, sLen * sizeof(wchar_t));
__movsb((PBYTE)String + sLen * sizeof(wchar_t), (const PBYTE)other.String, oLen * sizeof(wchar_t));
String[Length - 1] = 0;
free(os);
}
__declspec(noinline) FString FString::substr(size_t off, size_t count) {
if (count == -1) count = Length - off - 1;
else if (count > Length) return *this;
FString nStr((uint32_t)count);
__movsb((PBYTE) nStr.String, (const PBYTE) (String + off), count * sizeof(wchar_t));
nStr.String[count] = 0;
return nStr;
}
__declspec(noinline) size_t FString::find(wchar_t c) {
for (uint32_t i = 0; i < Length; i++) {
if (String[i] == c) return i;
}
return -1;
}
size_t FString::find(char c) {
return find((wchar_t)c);
}
size_t FString::find(const wchar_t* c) {
for (uint32_t i = 0; i < Length; i++) {
bool found = true;
for (int x = 0; x < wcslen(c); x++) {
if (String[i + x] != c[x]) {
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
bool FString::contains(wchar_t c) {
for (uint32_t i = 0; i < Length; i++) {
if (String[i] == c) return true;
}
return false;
}
bool FString::contains(const wchar_t* c) {
for (uint32_t i = 0; i < Length; i++) {
bool found = true;
for (int x = 0; x < wcslen(c); x++) {
if (String[i + x] != c[x]) {
found = false;
break;
}
}
if (found) return true;
}
return false;
}
bool FString::starts_with(const wchar_t* c) {
for (int x = 0; x < wcslen(c); x++) {
if (String[x] != c[x]) {
return false;
}
}
return true;
}
bool FString::ends_with(const wchar_t* c) {
auto cLen = wcslen(c);
auto start = ((size_t) Length - 1) - cLen;
for (size_t x = 0; x < cLen; x++) {
if (String[start + x] != c[x]) {
return false;
}
}
return true;
}
size_t FString::find_first_of(char c) {
return find(c);
}
size_t FString::find_first_of(wchar_t c) {
return find(c);
}
wchar_t* FString::c_str() {
return String;
}
FString::operator wchar_t* () {
return String;
}
__declspec(noinline) void FString::Dealloc() {
free(String);
String = nullptr;
MaxSize = Length = 0;
}
inline void FString::AllocString() {
String = Alloc<wchar_t>(Length * sizeof(wchar_t));
}
}
+113
View File
@@ -0,0 +1,113 @@
#pragma once
#include "pch.h"
namespace Unreal {
class FString
{
public:
wchar_t* String;
uint32_t Length;
uint32_t MaxSize;
inline static const size_t npos = -1;
FString();
FString(const char* Other);
FString(wchar_t* Other);
consteval FString(const wchar_t* Other) {
if (Other) {
MaxSize = Length = (int)std::wstring_view(Other).size() + 1;
String = (wchar_t*)Other;
}
}
consteval FString(const wchar_t* Other, size_t len) {
if (Other) {
MaxSize = Length = (uint32_t) len;
String = (wchar_t*)Other;
}
}
FString(uint32_t len);
FString operator+(FString other);
void operator+=(FString other);
FString substr(size_t off, size_t count = -1);
size_t find(wchar_t c);
size_t find(char c);
size_t find(const wchar_t* c);
bool contains(wchar_t c);
bool contains(const wchar_t* c);
bool starts_with(const wchar_t* c);
bool ends_with(const wchar_t* c);
size_t find_first_of(char c);
size_t find_first_of(wchar_t c);
wchar_t* c_str();
operator wchar_t* ();
void Dealloc();
private:
inline void AllocString();
};
class FStringUtil {
public:
consteval static size_t find_const(const FString s, const wchar_t c) {
for (uint32_t i = 0; i < s.Length; i++) {
if (s.String[i] == c) return i;
}
return -1;
}
template<FString s, size_t off, size_t count = -1>
consteval static std::array<wchar_t, count == -1 ? s.Length - off : count + 1> substr() {
std::array<wchar_t, count == -1 ? s.Length - off : count + 1> arr;
for (size_t i = 0; i < (count == -1 ? (s.Length - off) : count + 1); i++) {
arr[i] = (s.String + off)[i];
}
arr[(count == -1 ? s.Length - off - 1 : count)] = 0;
return arr;
}
};
class CPPArrayUtil {
public:
template<size_t S, std::array<wchar_t, S> s, size_t off, size_t count = -1>
consteval static std::array<wchar_t, count == -1 ? S - off : count + 1> substr() {
if (off == FString::npos) return {};
std::array<wchar_t, count == -1 ? S - off : count + 1> arr;
for (size_t i = 0; i < (count == -1 ? (S - off) : count + 1); i++) {
arr[i] = (s.data() + off)[i];
}
arr[(count == -1 ? S - off - 1 : count)] = 0;
return arr;
}
template<size_t S, std::array<wchar_t, S> a>
consteval static size_t find(const wchar_t c) {
for (uint32_t i = 0; i < a.size(); i++) {
if (a[i] == c) return i;
}
return -1;
}
};
}
using namespace Unreal;
+32
View File
@@ -0,0 +1,32 @@
#include "pch.h"
#include "url.h"
namespace Starfall {
URL::StrType URL::GetUrl() {
StrType v1 = Protocol.substr(0, Protocol.Length - 1);
v1 += Seperator;
v1 += Domain;
v1 += Port;
v1 += Path;
v1 += Query;
return v1;
}
URL::operator StrType() {
return GetUrl();
}
void URL::DeallocPathQuery() {
Path.Dealloc();
Query.Dealloc();
}
void URL::Dealloc() {
Protocol.Dealloc();
Seperator.Dealloc();
Domain.Dealloc();
Port.Dealloc();
Path.Dealloc();
Query.Dealloc();
}
}
+88
View File
@@ -0,0 +1,88 @@
#pragma once
#include "pch.h"
#include "ue.h"
namespace Starfall {
class URL {
public:
using StrType = FString;
StrType Protocol, Seperator, Domain, Port, Path, Query;
void Construct(StrType& url) {
auto ProtoEnd = url.find(':');
Protocol = url.substr(0, ProtoEnd);
auto ProtoSize = (url[ProtoEnd + 1] == '/' && url[ProtoEnd + 2] == '/') ? 3 : 1;
Seperator = url.substr(ProtoEnd, ProtoSize);
auto DomainAndPortStart = url.substr(ProtoEnd + ProtoSize);
auto PathEnd = DomainAndPortStart.find_first_of('/');
auto DomainAndPort = DomainAndPortStart.substr(0, PathEnd);
auto PathStart = DomainAndPortStart.substr(PathEnd);
DomainAndPortStart.Dealloc();
auto PortOff = DomainAndPort.find_first_of(':');
Domain = DomainAndPort.substr(0, PortOff);
if (PortOff != StrType::npos) Port = DomainAndPort.substr(PortOff);
DomainAndPort.Dealloc();
auto QueryOff = PathStart.find_first_of('?');
Path = PathStart.substr(0, QueryOff);
if (QueryOff != StrType::npos) Query = PathStart.substr(QueryOff);
PathStart.Dealloc();
}
URL& SetHost(FString host) {
auto ProtoEnd = host.find(':');
Protocol = host.substr(0, ProtoEnd);
auto ProtoSize = (host[ProtoEnd + 1] == '/' && host[ProtoEnd + 2] == '/') ? 3 : 1;
Seperator.Dealloc();
Seperator = host.substr(ProtoEnd, ProtoSize);
auto DomainAndPortStart = host.substr(ProtoEnd + ProtoSize);
auto PathEnd = DomainAndPortStart.find_first_of('/');
auto DomainAndPort = DomainAndPortStart.substr(0, PathEnd);
DomainAndPortStart.Dealloc();
auto PortOff = DomainAndPort.find_first_of(':');
Domain.Dealloc();
Domain = DomainAndPort.substr(0, PortOff);
if (PortOff != StrType::npos) {
Port.Dealloc();
Port = DomainAndPort.substr(PortOff);
}
DomainAndPort.Dealloc();
return *this;
}
template <FString host>
URL& SetHost() {
constexpr auto ProtoEnd = FStringUtil::find_const(host, ':');
Protocol.Dealloc();
constexpr static auto ProtocolS = FStringUtil::substr<host, 0, ProtoEnd>();
constexpr static FString ProtocolV = ProtocolS.data();
Protocol = ProtocolV;
constexpr auto ProtoSize = (host.String[ProtoEnd + 1] == '/' && host.String[ProtoEnd + 2] == '/') ? 3 : 1;
Seperator.Dealloc();
constexpr static auto SeperatorS = FStringUtil::substr<host, ProtoEnd, ProtoSize>();
constexpr static FString SeperatorV = SeperatorS.data();
Seperator = SeperatorV;
constexpr auto DomainAndPortStart = FStringUtil::substr<host, ProtoEnd + ProtoSize>();
constexpr auto PathEnd = CPPArrayUtil::find<DomainAndPortStart.size(), DomainAndPortStart>('/');
constexpr auto DomainAndPort = CPPArrayUtil::substr<DomainAndPortStart.size(), DomainAndPortStart, 0, PathEnd>();
constexpr auto PortOff = CPPArrayUtil::find<DomainAndPort.size(), DomainAndPort>(':');
Domain.Dealloc();
constexpr static auto DomainS = CPPArrayUtil::substr<DomainAndPort.size(), DomainAndPort, 0, PortOff>();
constexpr static FString DomainV = DomainS.data();
Domain = DomainV;
if (PortOff != FString::npos) {
Port.Dealloc();
constexpr static auto PortS = CPPArrayUtil::substr<DomainAndPort.size(), DomainAndPort, PortOff>();
constexpr static FString PortV = PortS.data();
Port = PortV;
}
return *this;
}
StrType GetUrl();
operator StrType();
void Dealloc();
void DeallocPathQuery();
};
}
+4
View File
@@ -0,0 +1,4 @@
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
// such as names of functions and macros.
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
#define PF_C
+10
View File
@@ -0,0 +1,10 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C uint32_t arm64_branch(void *caller, void *target, bool link);
@@ -0,0 +1,69 @@
#ifndef _ELF_DEFS_H
#define _ELF_DEFS_H
#include <stdint.h>
#define SHT_SYMTAB 0x2
#define SHT_DYNSYM 0xb
#define PT_LOAD 0x1
struct elf_ident_64 {
char signature[4];
uint8_t file_class;
uint8_t encoding;
uint8_t version;
uint8_t os;
uint8_t abi_version;
char pad[7];
};
struct elf_header_64 {
struct elf_ident_64 ident;
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t ph_off;
uint64_t sh_off;
uint32_t flags;
uint16_t head_size;
uint16_t ph_size;
uint16_t ph_count;
uint16_t sh_size;
uint16_t sh_count;
uint16_t sect_table_index;
};
struct elf_pheader_64 {
uint32_t type;
uint32_t flags;
uint64_t offset;
uint64_t virtual_address;
uint64_t physical_address;
uint64_t file_size;
uint64_t memory_size;
uint64_t align;
};
struct elf_sheader_64 {
uint32_t name_off;
uint32_t type;
uint64_t flags;
uint64_t address;
uint64_t offset;
uint64_t size;
uint32_t link;
uint32_t info;
uint64_t align;
uint64_t entry_count;
};
struct elf_symbol_64 {
uint32_t name;
unsigned char info;
unsigned char other;
uint16_t sh_index;
uint64_t offset;
uint64_t size;
};
#endif
@@ -0,0 +1,129 @@
#ifndef _MACHO_DEFS_H
#define _MACHO_DEFS_H
#include <stdint.h>
#define LC_SEGMENT_64 0x19
#define LC_BUILD_VERSION 0x32
#define LC_SYMTAB 0x2
#define CPU_TYPE_ARM64 0xc000001
#define LC_FILESET_ENTRY 0x80000035
struct mach_header_64 {
uint32_t magic;
uint32_t cputype;
uint32_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
struct fat_header {
uint32_t magic;
uint32_t nfat_arch;
};
struct fat_arch {
uint32_t cputype;
uint32_t cpusubtype;
uint32_t offset;
uint32_t size;
uint32_t align;
};
struct section_64 {
char sectname[16];
char segname[16];
uint64_t addr;
uint64_t size;
uint32_t offset;
uint32_t align;
uint32_t reloff;
uint32_t nreloc;
uint32_t flags;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
};
struct segment_command_64 {
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
uint64_t vmaddr;
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
uint32_t maxprot;
uint32_t initprot;
uint32_t nsects;
uint32_t flags;
};
struct load_command_64 {
uint32_t cmd;
uint32_t cmdsize;
};
struct build_version_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t platform;
uint32_t minos;
uint32_t sdk;
uint32_t ntools;
};
struct symtab_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t symoff;
uint32_t nsyms;
uint32_t stroff;
uint32_t strsize;
};
struct nlist_64 {
union {
uint32_t str_index;
} un;
uint8_t type;
uint8_t nsect;
uint16_t desc;
uint64_t offset;
};
struct kmod_info {
struct kmod_info *next;
int32_t info_version;
uint32_t id;
char name[64];
char version[64];
int32_t reference_count;
struct kmod_reference *reference_list;
uint64_t address;
uint64_t size;
uint64_t hdr_size;
void *start;
void *stop;
};
struct kmod_reference {
struct kmod_reference *next;
struct kmod_info *info;
};
struct fileset_entry_command {
uint32_t cmd;
uint32_t cmdsize;
uint64_t vmaddr;
uint64_t fileoff;
uint32_t entry_id;
uint32_t reserved;
};
#endif
+119
View File
@@ -0,0 +1,119 @@
#ifndef _PE_DEFS_H
#define _PE_DEFS_H
#include <stdint.h>
struct DOS_Header {
char e_magic[0x2];
uint16_t e_cblp;
uint16_t e_cp;
uint16_t e_crlc;
uint16_t e_cparhdr;
uint16_t e_minalloc;
uint16_t e_maxalloc;
uint16_t e_ss;
uint16_t e_sp;
uint16_t e_csum;
uint16_t e_ip;
uint16_t e_cs;
uint16_t e_lfarlc;
uint16_t e_ovno;
char e_res1[0x8];
uint16_t e_oemid;
uint16_t e_oeminfo;
char e_res2[0x14];
uint32_t e_lfanew;
};
struct COFF_Header {
char magic[0x4];
uint16_t machine;
uint16_t numberOfSections;
uint32_t timeDateStamp;
uint32_t pointerToSymbolTable;
uint32_t numberOfSymbols;
uint16_t sizeOfOptionalHeader;
uint16_t characteristics;
};
struct Section_Header {
char name[0x8];
uint32_t virtualSize;
uint32_t virtualAddress;
uint32_t sizeOfRawData;
uint32_t pointerToRawData;
uint32_t pointerToRelocations;
uint32_t pointerToLineNumbers;
uint16_t numberOfRelocations;
uint16_t numberOfLineNumbers;
uint32_t characteristics;
};
struct Symbol_Header {
union {
char name[0x8];
struct {
uint32_t zeros;
uint32_t strtab_off;
} over_8b;
} name;
uint32_t value;
int16_t nsect;
uint16_t type;
uint8_t s_class;
uint8_t n_aux;
};
struct PE_Data_Directory_Entry {
uint32_t virtualAddress;
uint32_t size;
};
struct PE64_Optional_Header {
uint16_t magic;
uint8_t majorLinkerVersion;
uint8_t minorLinkerVersion;
uint32_t sizeOfCode;
uint32_t sizeOfInitializedData;
uint32_t sizeOfUninitializedData;
uint32_t addressOfEntryPoint;
uint32_t baseOfCode;
uint64_t imageBase;
uint32_t sectionAlignment;
uint32_t fileAlignment;
uint16_t majorOperatingSystemVersion;
uint16_t minorOperatingSystemVersion;
uint16_t majorImageVersion;
uint16_t minorImageVersion;
uint16_t majorSubsystemVersion;
uint16_t minorSubsystemVersion;
uint32_t win32VersionValue;
uint32_t sizeOfImage;
uint32_t sizeOfHeaders;
uint32_t checkSum;
uint16_t subsystem;
uint16_t dllCharacteristics;
uint64_t sizeOfStackReserve;
uint64_t sizeOfStackCommit;
uint64_t sizeOfHeapReserve;
uint64_t sizeOfHeapCommit;
uint32_t loaderFlags;
uint32_t numberOfRvaAndSizes;
struct PE_Data_Directory_Entry exportTableEntry;
struct PE_Data_Directory_Entry importTableEntry;
struct PE_Data_Directory_Entry resourceTableEntry;
struct PE_Data_Directory_Entry exceptionTableEntry;
struct PE_Data_Directory_Entry certificateTableEntry;
struct PE_Data_Directory_Entry baseRelocationTableEntry;
struct PE_Data_Directory_Entry debugEntry;
struct PE_Data_Directory_Entry architectureEntry;
struct PE_Data_Directory_Entry globalPtrEntry;
struct PE_Data_Directory_Entry tlsTableEntry;
struct PE_Data_Directory_Entry loadConfigTableEntry;
struct PE_Data_Directory_Entry boundImportEntry;
struct PE_Data_Directory_Entry iatEntry;
struct PE_Data_Directory_Entry delayImportDescriptorEntry;
struct PE_Data_Directory_Entry clrRuntimeHeaderEntry;
struct PE_Data_Directory_Entry reservedEntry;
};
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef _ELF_H
#define _ELF_H
#include <stdbool.h>
#include <stdint.h>
#include "defs/elf_defs.h"
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C bool elf_check(char *buf);
PF_C bool is_elf(char *buf);
PF_C struct elf_sheader_64 *elf_get_section(char *buf, char *name);
PF_C char *elf_va_to_ptr(char *buf, uint64_t addr);
PF_C uint64_t elf_ptr_to_va(char *buf, char *ptr);
PF_C struct elf_symbol_64 *elf_find_symbol_stype(char *buf, char *name, uint32_t type);
PF_C struct elf_symbol_64 *elf_find_symbol(char *buf, char *name);
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef _MACHO_H
#define _MACHO_H
#include <stdbool.h>
#include <stdint.h>
#include "defs/macho_defs.h"
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C uint32_t macho_get_magic(char *buf);
PF_C bool macho_check(char *buf);
PF_C char *macho_find_arch(char *buf, uint32_t arch);
PF_C uint32_t macho_get_platform(char *buf);
PF_C struct segment_command_64 *macho_get_segment(char *buf, char *name);
PF_C struct section_64 *macho_get_section(char *buf, struct segment_command_64 *segment, char *name);
PF_C struct section_64 *macho_get_last_section(struct segment_command_64 *segment);
PF_C struct section_64 *macho_find_section(char *buf, char *segment_name, char *section_name);
PF_C struct fileset_entry_command *macho_get_fileset(char *buf, char *name);
PF_C struct segment_command_64 *macho_get_segment_for_va(char *buf, uint64_t addr);
PF_C struct section_64 *macho_get_section_for_va(struct segment_command_64 *segment, uint64_t addr);
PF_C struct section_64 *macho_find_section_for_va(char *buf, uint64_t addr);
PF_C char *macho_va_to_ptr(char *buf, uint64_t addr);
PF_C struct segment_command_64 *macho_get_segment_for_ptr(char *buf, char *ptr);
PF_C struct section_64 *macho_get_section_for_ptr(struct segment_command_64 *segment, char *buf, char *ptr);
PF_C struct section_64 *macho_find_section_for_ptr(char *buf, char *ptr);
PF_C uint64_t macho_ptr_to_va(char *buf, char *ptr);
PF_C struct nlist_64 *macho_find_symbol(char *buf, char *name);
PF_C uint64_t macho_get_symbol_size(struct nlist_64 *symbol);
PF_C uint64_t macho_parse_plist_integer(char *key);
PF_C struct mach_header_64 *macho_parse_prelink_info(char *buf, struct section_64 *kmod_info, char *bundle_name);
PF_C uint64_t macho_xnu_untag_va(uint64_t addr);
PF_C struct mach_header_64 *macho_parse_kmod_info(char *buf, struct section_64 *kmod_info, struct section_64 *kmod_start, char *bundle_name);
PF_C struct mach_header_64 *macho_find_kext(char *buf, char *name);
PF_C void macho_run_each_kext(char *buf, void (*function)(char *real_buf, char *kextbuf, uint64_t kext_size));
PF_C char *fileset_va_to_ptr(char *buf, char *kext, uint64_t addr);
PF_C struct segment_command_64 *fileset_get_segment_for_ptr(char *buf, char *kext, char *ptr);
PF_C struct section_64 *fileset_find_section_for_ptr(char *buf, char *kext, char *ptr);
PF_C uint64_t fileset_ptr_to_va(char *buf, char *kext, char *ptr);
PF_C struct nlist_64 *fileset_find_symbol(char *buf, char *kext, char *name);
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _MULTI_H
#define _MULTI_H
#include <stdint.h>
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C void *pf_va_to_ptr(void *buf, uint64_t addr);
PF_C uint64_t pf_ptr_to_va(void *buf, void *ptr);
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef _PE_H
#define _PE_H
#include <stdbool.h>
#include <stdint.h>
#include "defs/pe_defs.h"
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C bool dos_check(char *buf);
PF_C struct COFF_Header *get_pe_header(char *buf);
PF_C bool pe_check(char *buf);
PF_C bool is_pe(char *buf);
PF_C struct PE64_Optional_Header *get_pe_opt_header(char *buf);
PF_C struct Symbol_Header *pe_get_symtab(char *buf);
PF_C char *pe_get_strtab(char *buf);
PF_C struct Section_Header *pe_get_section(char *buf, const char *name);
PF_C char *pe_va_to_ptr(char *buf, uint64_t addr);
PF_C uint64_t pe_ptr_to_va(char *buf, char *ptr);
PF_C struct Symbol_Header *pe_find_symbol(char *buf, char *name);
#endif
+89
View File
@@ -0,0 +1,89 @@
#ifndef _PLOOSHFINDER_H
#define _PLOOSHFINDER_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#ifndef _DEBUG
#pragma comment(lib, "../x64/Release/plooshfinder.lib")
#else
#pragma comment(lib, "../x64/Debug/plooshfinder.lib")
#endif
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
#pragma pack(push, 0x1)
struct pf_patch_t {
void *matches;
void *masks;
bool disabled;
uint32_t count;
bool (*callback)(struct pf_patch_t *patch, void *stream);
};
struct pf_patchset_t {
struct pf_patch_t *patches;
uint32_t count;
bool (*handler)(void *buf, size_t size, struct pf_patchset_t patch);
};
#pragma pack(pop)
// patch utils
#ifdef __cplusplus
constexpr pf_patch_t pf_construct_patch(void* matches, void* masks, uint32_t count, bool (*callback)(struct pf_patch_t* patch, void* stream)) {
struct pf_patch_t patch;
// construct the patch
patch.matches = matches;
patch.masks = masks;
patch.disabled = false;
patch.count = count;
patch.callback = callback;
return patch;
}
constexpr pf_patch_t pf_construct_patch_dynmatch(void* masks, uint32_t count, bool (*callback)(struct pf_patch_t* patch, void* stream)) {
struct pf_patch_t patch;
// construct the patch
patch.matches = nullptr;
patch.masks = masks;
patch.disabled = false;
patch.count = count;
patch.callback = callback;
return patch;
}
constexpr struct pf_patchset_t pf_construct_patchset(struct pf_patch_t* patches, uint32_t count, bool (*handler)(void *buf, size_t size, struct pf_patchset_t patchset)) {
struct pf_patchset_t patchset;
patchset.patches = patches;
patchset.count = count;
patchset.handler = handler;
return patchset;
}
__forceinline constexpr struct pf_patchset_t pf_construct_patchset(const struct pf_patch_t* patches, uint32_t count, bool (*handler)(void* buf, size_t size, struct pf_patchset_t patchset)) {
return pf_construct_patchset((struct pf_patch_t*)patches, count, handler);
}
#else
PF_C struct pf_patch_t pf_construct_patch(void *matches, void *masks, uint32_t count, bool (*callback)(struct pf_patch_t *patch, void *stream));
PF_C struct pf_patchset_t pf_construct_patchset(struct pf_patch_t* patches, uint32_t count, bool (*handler)(void* buf, size_t size, struct pf_patchset_t patchset));
#endif
PF_C bool pf_patchset_emit(void *buf, size_t size, struct pf_patchset_t patchset);
PF_C void pf_disable_patch(struct pf_patch_t *patch);
// utils for finding
PF_C uint8_t *pf_find_next(uint8_t *stream, uint32_t count, uint8_t match, uint8_t mask);
PF_C uint8_t *pf_find_prev(uint8_t *stream, uint32_t count, uint8_t match, uint8_t mask);
PF_C uint8_t* pf_find_next_multiple(uint8_t* stream, uint32_t count, uint8_t* matches, uint8_t* masks, uint32_t mmc);
PF_C uint8_t* pf_find_prev_multiple(uint8_t* stream, uint32_t count, uint8_t* matches, uint8_t* masks, uint32_t mmc);
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef _PLOOSHFINDER8_H
#define _PLOOSHFINDER8_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
#pragma pack(push, 0x1)
struct pf_patch8_t {
uint8_t *matches;
uint8_t *masks;
bool disabled;
uint32_t count;
bool (*callback)(struct pf_patch8_t *patch, void *stream);
};
struct pf_patchset8_t {
struct pf_patch8_t *patches;
uint32_t count;
bool (*handler)(void *buf, size_t size, struct pf_patchset8_t patch);
};
#pragma pack(pop)
// patch utils
PF_C bool pf_maskmatch(uint8_t insn, uint8_t match, uint8_t mask);
PF_C bool pf_find_maskmatch(void *buf, size_t size, struct pf_patchset_t patchset);
// utils for finding
PF_C int8_t pf_signextend(int8_t val, uint8_t bits);
#endif
+86
View File
@@ -0,0 +1,86 @@
#ifndef _PLOOSHFINDER_SIG_H
#define _PLOOSHFINDER_SIG_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "plooshfinder8.h"
#include "plooshfinder.h"
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
#ifdef __cplusplus
// compile-time processed implementation of sig patch
constexpr int PatternCount(std::string_view s) {
int c = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') c++;
}
return c + 1; // last i think
}
constexpr uint32_t parsePatternPart(std::string_view s) {
uint32_t val = 0;
for (int i = 0; i < s.size(); i++) {
uint8_t byte = s[i];
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <= 'f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <= 'F') byte = byte - 'A' + 10;
else if (byte == '?') byte = 0;
val = (val << 4) | (byte & 0xF);
}
return val;
}
constexpr uint32_t parsePatternMask(std::string_view s) {
uint32_t val = 0;
for (int i = 0; i < s.size(); i++) {
uint8_t byte = s[i];
if (byte >= '0' && byte <= '9' || byte >= 'a' && byte <= 'f' || byte >= 'A' && byte <= 'F') byte = 0xf;
else if (byte == '?') byte = 0x0;
val = (val << 4) | (byte & 0xF);
}
return val;
}
template <size_t sz, std::array<uint8_t, sz> match, std::array<uint8_t, sz> mask, bool (*call)(struct pf_patch_t* patch, void* stream)>
class pf_constexpr_patch_data_t {
public:
static constexpr std::array<uint8_t, sz> matches = match;
static constexpr std::array<uint8_t, sz> masks = mask;
static constexpr size_t arrsz = sz;
static constexpr bool (*cb)(struct pf_patch_t* patch, void* stream) = call;
};
#define pf_construct_patch_sig(sig, callback) []() consteval { \
constexpr pf_constexpr_patch_data_t<PatternCount(sig), ([]() consteval { \
constexpr auto st = std::string_view(sig); \
constexpr auto arrsz = PatternCount(st); \
std::array<uint8_t, arrsz> matches = { 0 }; \
size_t cInd = 0; \
for (int i = 0; i < arrsz; i++) { \
auto part = st.substr(cInd, st.find_first_of(' ', cInd) == std::string_view::npos ? st.size() - cInd : (st.find_first_of(' ', cInd) + 1) - cInd - 1); \
matches[i] = parsePatternPart(part); \
cInd = st.find_first_of(' ', cInd) + 1; \
} \
return matches; \
})(), ([]() consteval { \
constexpr auto st = std::string_view(sig); \
constexpr auto arrsz = PatternCount(st); \
std::array<uint8_t, arrsz> masks = { 0 }; \
size_t cInd = 0; \
for (int i = 0; i < arrsz; i++) { \
auto part = st.substr(cInd, st.find_first_of(' ', cInd) == std::string_view::npos ? st.size() - cInd : (st.find_first_of(' ', cInd) + 1) - cInd - 1); \
masks[i] = parsePatternMask(part); \
cInd = st.find_first_of(' ', cInd) + 1; \
} \
return masks; \
})(), callback> d; \
return pf_construct_patch((void *) d.matches.data(), (void *) d.masks.data(), d.arrsz, d.cb); \
}()
#else
PF_C struct pf_patch_t pf_construct_patch_sig(const char *sig, bool (*callback)(struct pf_patch_t *patch, void *stream));
#endif
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _UTILS_H
#define _UTILS_H
#include <stdint.h>
#ifdef __cplusplus
#define PF_C extern "C"
#else
#define PF_C
#endif
PF_C uint32_t convert_endianness32(uint32_t val);
#define Cast(T, expr) (T) (expr)
#endif
+111
View File
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\formats\elf.c" />
<ClCompile Include="src\formats\macho.c" />
<ClCompile Include="src\formats\multi.c" />
<ClCompile Include="src\formats\pe.c" />
<ClCompile Include="src\plooshfinder.c" />
<ClCompile Include="src\plooshfinder8.c" />
<ClCompile Include="src\plooshfinder_sig.c" />
<ClCompile Include="src\utils.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\formats\defs\elf_defs.h" />
<ClInclude Include="include\formats\defs\macho_defs.h" />
<ClInclude Include="include\formats\defs\pe_defs.h" />
<ClInclude Include="include\formats\elf.h" />
<ClInclude Include="include\formats\macho.h" />
<ClInclude Include="include\formats\multi.h" />
<ClInclude Include="include\formats\pe.h" />
<ClInclude Include="include\plooshfinder.h" />
<ClInclude Include="include\plooshfinder8.h" />
<ClInclude Include="include\plooshfinder_sig.h" />
<ClInclude Include="include\utils.h" />
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{1efdb154-d3b5-43bc-8733-f3d6941c9e36}</ProjectGuid>
<RootNamespace>plooshfinder</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</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" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NOLOG;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+90
View File
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headers">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Source\Formats">
<UniqueIdentifier>{49b1533c-7528-46c5-840c-71827da7395a}</UniqueIdentifier>
</Filter>
<Filter Include="Headers\Formats">
<UniqueIdentifier>{358939c8-87b9-480a-a5c2-4510332a1f55}</UniqueIdentifier>
</Filter>
<Filter Include="Headers\Formats\Defs">
<UniqueIdentifier>{a89650b4-9dcb-4857-9a4c-c85711680efc}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\plooshfinder.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\plooshfinder_sig.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\plooshfinder8.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\utils.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\formats\multi.c">
<Filter>Source\Formats</Filter>
</ClCompile>
<ClCompile Include="src\formats\pe.c">
<Filter>Source\Formats</Filter>
</ClCompile>
<ClCompile Include="src\formats\elf.c">
<Filter>Source\Formats</Filter>
</ClCompile>
<ClCompile Include="src\formats\macho.c">
<Filter>Source\Formats</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\plooshfinder.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\plooshfinder8.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\utils.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\formats\elf.h">
<Filter>Headers\Formats</Filter>
</ClInclude>
<ClInclude Include="include\formats\macho.h">
<Filter>Headers\Formats</Filter>
</ClInclude>
<ClInclude Include="include\formats\multi.h">
<Filter>Headers\Formats</Filter>
</ClInclude>
<ClInclude Include="include\formats\pe.h">
<Filter>Headers\Formats</Filter>
</ClInclude>
<ClInclude Include="include\formats\defs\elf_defs.h">
<Filter>Headers\Formats\Defs</Filter>
</ClInclude>
<ClInclude Include="include\formats\defs\macho_defs.h">
<Filter>Headers\Formats\Defs</Filter>
</ClInclude>
<ClInclude Include="include\formats\defs\pe_defs.h">
<Filter>Headers\Formats\Defs</Filter>
</ClInclude>
<ClInclude Include="include\plooshfinder_sig.h">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
</Project>
+162
View File
@@ -0,0 +1,162 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "../../include/formats/elf.h"
#include "../../include/utils.h"
bool elf_check(char *buf) {
struct elf_header_64 *hdr = (struct elf_header_64 *) buf;
char elf_magic[5] = { 0x7f, 'E', 'L', 'F' };
if (strncmp(hdr->ident.signature, elf_magic, 4) == 0) {
return true;
}
return false;
}
bool is_elf(char *buf) {
bool elf = elf_check(buf);
if (!elf) {
printf("%s: Not an ELF!\n", __FUNCTION__);
}
return elf;
}
struct elf_sheader_64 *elf_get_section(char *buf, char *name) {
if (!elf_check(buf)) {
return NULL;
}
struct elf_header_64 *hdr = (struct elf_header_64 *) buf;
struct elf_sheader_64 *section_hdr = Cast(struct elf_sheader_64*, buf + hdr->sh_off);
struct elf_sheader_64 *sname_hdr = section_hdr + hdr->sect_table_index;
char *sname_tbl = buf + sname_hdr->offset;
for (uint16_t i = 0; i < hdr->sh_count; i++) {
struct elf_sheader_64 *section = section_hdr + i;
char *sect_name = sname_tbl + section->name_off;
if (strcmp(sect_name, name) == 0) {
return section;
}
}
return NULL;
}
char *elf_va_to_ptr(char *buf, uint64_t addr) {
if (!elf_check(buf)) {
return 0;
}
struct elf_header_64 *hdr = (struct elf_header_64 *) buf;
struct elf_pheader_64 *program_hdr = Cast(struct elf_pheader_64*, buf + hdr->ph_off);
for (int i = 0; i < hdr->ph_count; i++) {
struct elf_pheader_64 *phdr = program_hdr + i;
if (phdr->type == PT_LOAD) {
uint64_t segment_start = phdr->virtual_address;
uint64_t segment_end = segment_start + phdr->file_size;
if (segment_start <= addr && segment_end > addr) {
uint64_t offset = addr - segment_start;
return buf + phdr->offset + offset;
}
}
}
return 0;
}
uint64_t elf_ptr_to_va(char *buf, char *ptr) {
if (!elf_check(buf)) {
return 0;
}
struct elf_header_64 *hdr = (struct elf_header_64 *) buf;
struct elf_pheader_64 *program_hdr = Cast(struct elf_pheader_64*, buf + hdr->ph_off);
uint64_t ptr_addr = (uint64_t) ptr;
for (int i = 0; i < hdr->ph_count; i++) {
struct elf_pheader_64 *phdr = program_hdr + i;
if (phdr->type == PT_LOAD) {
uint64_t segment_start = (uint64_t) buf + phdr->offset;
uint64_t segment_end = segment_start + phdr->file_size;
uint64_t segment_va = phdr->virtual_address;
if (segment_start <= ptr_addr && segment_end > ptr_addr) {
uint64_t offset = ptr_addr - segment_start;
return segment_va + offset;
}
}
}
return 0;
}
struct elf_symbol_64 *elf_find_symbol_stype(char *buf, char *name, uint32_t type) {
if (!elf_check(buf)) {
return NULL;
}
struct elf_header_64 *hdr = (struct elf_header_64 *) buf;
struct elf_sheader_64* section_hdr = Cast(struct elf_sheader_64*, buf + hdr->sh_off);
struct elf_sheader_64 *sect = NULL;
struct elf_sheader_64 *strtab_sect;
for (uint16_t i = 0; i < hdr->sh_count; i++) {
struct elf_sheader_64 *section = section_hdr + i;
if (section->type == type) {
sect = section;
}
}
if (!sect) {
return NULL;
}
strtab_sect = section_hdr + sect->link;
struct elf_symbol_64 *symtab = Cast(struct elf_symbol_64*, buf + sect->offset);
char *strtab = buf + strtab_sect->offset;
uint64_t count = sect->size / sizeof(struct elf_symbol_64);
for (int i = 0; i < count; i++) {
struct elf_symbol_64 *symbol = symtab + i;
char *sym_name = strtab + symbol->name;
if (strcmp(sym_name, name) == 0) {
return symbol;
}
}
return NULL;
}
struct elf_symbol_64 *elf_find_symbol(char *buf, char *name) {
if (!elf_check(buf)) {
return NULL;
}
struct elf_symbol_64 *symbol = elf_find_symbol_stype(buf, name, SHT_SYMTAB);
if (!symbol) {
symbol = elf_find_symbol_stype(buf, name, SHT_DYNSYM);
}
if (!symbol) {
printf("%s: Failed to find symbol %s!\n", __FUNCTION__, name);
return NULL;
}
return symbol;
}
+658
View File
@@ -0,0 +1,658 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../../include/formats/macho.h"
#include "../../include/utils.h"
uint32_t macho_get_magic(char *buf) {
uint32_t *buf_ptr = (uint32_t *) buf;
uint32_t magic = buf_ptr[0];
if (magic == 0xfeedfacf || magic == 0xbebafeca) {
return magic;
} else {
printf("%s: Not a mach-o!\n", __FUNCTION__);
}
return 0;
}
bool macho_check(char *buf) {
uint32_t magic = macho_get_magic(buf);
if (magic == 0xfeedfacf || magic == 0xbebafeca) {
return true;
}
return false;
}
char *macho_find_arch(char *buf, uint32_t arch) {
uint32_t magic = macho_get_magic(buf);
if (magic == 0xbebafeca) {
struct fat_header *header = (struct fat_header *) buf;
struct fat_arch *farch = (struct fat_arch *) ((char *) buf + sizeof(struct fat_header));
for (uint32_t i = 0; i < convert_endianness32(header->nfat_arch); i++) {
if (farch->cputype == arch) {
return buf + convert_endianness32(farch->offset);
}
farch = (struct fat_arch *) ((char *) farch + sizeof(struct fat_arch));
}
printf("%s: Universal mach-o does not contain a slice for the arch requested!\n", __FUNCTION__);
}
return buf;
}
uint32_t macho_get_platform(char *buf) {
if (!macho_check(buf)) {
return 0;
}
struct load_command_64 *after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64 *header = Cast(struct mach_header_64*, buf);
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_BUILD_VERSION) {
struct build_version_command *cmd = (struct build_version_command *) after_header;
if (cmd->platform > 5) {
printf("%s: Invalid platform!\n", __FUNCTION__);
return 0;
}
return cmd->platform;
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
printf("%s: Unable to get platform!\n", __FUNCTION__);
return 0;
}
struct segment_command_64 *macho_get_segment(char *buf, char *name) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64* after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64* header = Cast(struct mach_header_64*, buf);
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SEGMENT_64) {
struct segment_command_64 *segment = (struct segment_command_64 *) after_header;
if (strcmp(segment->segname, name) == 0) {
return segment;
}
} else {
break;
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
return NULL;
}
struct section_64 *macho_get_section(char *buf, struct segment_command_64 *segment, char *name) {
if (!segment || !macho_check(buf)) {
return NULL;
}
struct section_64 *section = (struct section_64 *) ((char *) segment + sizeof(struct segment_command_64));
for (uint32_t i = 0; i < segment->nsects; i++) {
if (strcmp(section->sectname, name) == 0) {
return section;
}
section = (struct section_64 *) ((char *) section + sizeof(struct section_64));
}
return NULL;
}
struct section_64 *macho_get_last_section(struct segment_command_64 *segment) {
uint32_t index = segment->nsects - 1;
struct section_64 *sections = (struct section_64 *) ((char *) segment + sizeof(struct segment_command_64));
return sections + index;
}
struct section_64 *macho_find_section(char *buf, char *segment_name, char *section_name) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = macho_get_segment(buf, segment_name);
if (!segment) {
return NULL;
}
struct section_64 *section = macho_get_section(buf, segment, section_name);
if (!section) {
return NULL;
}
return section;
}
struct fileset_entry_command *macho_get_fileset(char *buf, char *name) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64* after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64* header = Cast(struct mach_header_64*, buf);
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_FILESET_ENTRY) {
struct fileset_entry_command *entry = (struct fileset_entry_command *) after_header;
char *entry_name = (char *) entry + entry->entry_id;
if (strcmp(entry_name, name) == 0) {
return entry;
}
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
return 0;
}
struct segment_command_64 *macho_get_segment_for_va(char *buf, uint64_t addr) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64* after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64* header = Cast(struct mach_header_64*, buf);
struct segment_command_64 *segment = NULL;
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SEGMENT_64) {
segment = (struct segment_command_64 *) after_header;
uint64_t segment_start = segment->vmaddr;
uint64_t segment_end = segment_start + segment->vmsize;
if (segment_start <= addr && segment_end > addr) {
// segment's range contains the addr
return segment;
}
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
printf("%s: Unable to find segment containing 0x%llx!\n", __FUNCTION__, addr);
return NULL;
}
struct section_64 *macho_get_section_for_va(struct segment_command_64 *segment, uint64_t addr) {
struct section_64 *section = (struct section_64 *) ((char *) segment + sizeof(struct segment_command_64));
for (uint32_t i = 0; i < segment->nsects; i++) {
uint64_t section_start = section->addr;
uint64_t section_end = section_start + section->size;
if (section_start <= addr && section_end > addr) {
// section's range contains the addr
return section;
}
section = (struct section_64 *) ((char *) section + sizeof(struct section_64));
}
printf("%s: Unable to find section containing 0x%llx?\n", __FUNCTION__, addr);
return NULL;
}
struct section_64 *macho_find_section_for_va(char *buf, uint64_t addr) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = macho_get_segment_for_va(buf, addr);
if (!segment) {
return NULL;
}
struct section_64 *section = macho_get_section_for_va(segment, addr);
if (!section) {
return NULL;
}
return section;
}
char *macho_va_to_ptr(char *buf, uint64_t addr) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = macho_get_segment_for_va(buf, addr);
if (!segment) {
return NULL;
} else if (segment->vmaddr == addr) {
return buf + segment->fileoff;
}
struct section_64 *section = macho_get_section_for_va(segment, addr);
uint64_t offset = addr - section->addr;
return buf + section->offset + offset;
}
struct segment_command_64 *macho_get_segment_for_ptr(char *buf, char *ptr) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64* after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64* header = Cast(struct mach_header_64*, buf);
struct segment_command_64 *segment = NULL;
uint64_t ptr_addr = (uint64_t) ptr;
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SEGMENT_64) {
segment = (struct segment_command_64 *) after_header;
uint64_t segment_start = (uint64_t) buf + segment->fileoff;
uint64_t segment_end = segment_start + segment->filesize;
if (segment_start <= ptr_addr && segment_end > ptr_addr) {
// segment's range contains the ptr
return segment;
}
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
printf("%s: Unable to find segment containing ptr %p!\n", __FUNCTION__, ptr);
return NULL;
}
struct section_64 *macho_get_section_for_ptr(struct segment_command_64 *segment, char *buf, char *ptr) {
struct section_64 *section = (struct section_64 *) ((char *) segment + sizeof(struct segment_command_64));
uint64_t ptr_addr = (uint64_t) ptr;
for (uint32_t i = 0; i < segment->nsects; i++) {
uint64_t section_start = (uint64_t) buf + section->offset;
uint64_t section_end = section_start + section->size;
if (section_start <= ptr_addr && section_end > ptr_addr) {
// section's range contains the ptr
return section;
}
section = (struct section_64 *) ((char *) section + sizeof(struct section_64));
}
printf("%s: Unable to find section containing %p?\n", __FUNCTION__, ptr);
return NULL;
}
struct section_64 *macho_find_section_for_ptr(char *buf, char *ptr) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = macho_get_segment_for_ptr(buf, ptr);
if (!segment) {
return NULL;
}
struct section_64 *section = macho_get_section_for_ptr(segment, buf, ptr);
if (!section) {
return NULL;
}
return section;
}
uint64_t macho_ptr_to_va(char *buf, char *ptr) {
if (!macho_check(buf)) {
return 0;
}
struct section_64 *section = macho_find_section_for_ptr(buf, ptr);
uint64_t offset = ptr - buf - section->offset;
return section->addr + offset;
}
struct nlist_64 *macho_find_symbol(char *buf, char *name) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64* after_header = Cast(struct load_command_64*, buf + sizeof(struct mach_header_64));
struct mach_header_64* header = Cast(struct mach_header_64*, buf);
struct symtab_command *symtab_cmd = NULL;
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SYMTAB) {
symtab_cmd = (struct symtab_command *) after_header;
break;
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
if (!symtab_cmd) {
printf("%s: Unable to find symbol table!\n", __FUNCTION__);
return NULL;
}
struct nlist_64 *symtab = Cast(struct nlist_64 *, buf + symtab_cmd->symoff);
char *strtab = buf + symtab_cmd->stroff;
for (uint32_t i = 0; i < symtab_cmd->nsyms; i++) {
struct nlist_64 *symbol_nlist = symtab + i;
char *sym_name = strtab + symbol_nlist->un.str_index;
if (strcmp(sym_name, name) == 0) {
return symbol_nlist;
}
}
//printf("%s: Unable to find symbol %s!\n", __FUNCTION__, name);
return NULL;
}
uint64_t macho_get_symbol_size(struct nlist_64 *symbol) {
// this is not very reliable, as symtab doesn't include stripped symbols and can be in a weird order.
struct nlist_64 *next_symbol = symbol + 1;
if (next_symbol->offset < symbol->offset) {
// symtab is in a weird order. can't really do anything about this, return 0.
printf("%s: Symtab is in a weird order!\n", __FUNCTION__);
return 0;
}
return next_symbol->offset - symbol->offset;
}
uint64_t macho_parse_plist_integer(char *key) {
char *key_value = strstr(key, "<integer");
if (key_value) {
key_value = strstr(key_value, ">");
if (key_value) {
return strtoull(key_value + 1, 0, 0);
}
}
return 0;
}
struct mach_header_64 *macho_parse_prelink_info(char *buf, struct section_64 *kmod_info, char *bundle_name) {
if (!macho_check(buf)) {
return NULL;
}
char kext_name[256];
struct mach_header_64 *kext = NULL;
char *start = buf + kmod_info->offset;
char *info_dict = strstr(start, "PrelinkInfoDictionary");
char *last_dict = strstr(info_dict, "<array>") + 7;
while (last_dict) {
char *dict_end = strstr(last_dict, "</dict>");
if (!dict_end) break;
char *dict2 = strstr(last_dict + 1, "<dict>");
while (dict2) {
if (dict2 > dict_end) break;
dict2 = strstr(dict2 + 1, "<dict>");
dict_end = strstr(dict_end + 1, "</dict>");
}
char *identifier = strstr(last_dict, "CFBundleIdentifier");
if (identifier) {
char *value_key = strstr(identifier, "<string>");
if (value_key) {
value_key += strlen("<string>");
char *key_end = strstr(value_key, "</string>");
if (key_end) {
__int64 key_len = key_end - value_key;
memcpy(kext_name, value_key, key_len);
kext_name[key_len] = 0;
if (strcmp(kext_name, bundle_name) == 0) {
char *addr_key = strstr(last_dict, "_PrelinkExecutableLoadAddr");
if (addr_key) {
kext = (struct mach_header_64 *) macho_va_to_ptr(buf, macho_parse_plist_integer(addr_key));
break;
}
}
}
}
}
last_dict = strstr(dict_end, "<dict>");
}
return kext;
}
uint64_t macho_xnu_untag_va(uint64_t addr) {
if (((addr >> 32) & 0xffff) == 0xfff0) {
return (0xffffULL << 48) | addr;
} else {
return addr;
}
}
struct mach_header_64 *macho_parse_kmod_info(char *buf, struct section_64 *kmod_info, struct section_64 *kmod_start, char *bundle_name) {\
if (!macho_check(buf)) {
return NULL;
}
struct mach_header_64 *kext = NULL;
uint64_t kmod_count = kmod_info->size >> 3;
uint64_t *info_start = Cast(uint64_t *, buf + kmod_info->offset);
uint64_t *start = Cast(uint64_t*, buf + kmod_start->offset);
for (uint64_t i = 0; i < kmod_count; i++) {
struct kmod_info *info = Cast(struct kmod_info *, macho_va_to_ptr(buf, macho_xnu_untag_va(info_start[i])));
if (strcmp(info->name, bundle_name) == 0) {
kext = (struct mach_header_64 *) macho_va_to_ptr(buf, macho_xnu_untag_va(start[i]));
}
}
return kext;
}
struct mach_header_64 *macho_find_kext(char *buf, char *name) {
struct mach_header_64 *kext = NULL;
struct segment_command_64 *prelink_info = macho_get_segment(buf, "__PRELINK_INFO");
if (!prelink_info) return NULL;
struct section_64 *kmod_info = macho_get_section(buf, prelink_info, "__kmod_info");
if (!kmod_info) {
struct section_64 *info = macho_get_section(buf, prelink_info, "__info");
if (!info) return NULL;
kext = macho_parse_prelink_info(buf, info, name);
} else {
struct section_64 *kmod_start = macho_get_section(buf, prelink_info, "__kmod_start");
if (!kmod_start) return NULL;
kext = macho_parse_kmod_info(buf, kmod_info, kmod_start, name);
}
return kext;
}
void macho_run_each_kext(char *buf, void (*function)(char *real_buf, char *kextbuf, uint64_t kext_size)) {
struct segment_command_64 *prelink_info = macho_get_segment(buf, "__PRELINK_INFO");
if (!prelink_info) return;
struct section_64 *kmod_start = macho_get_section(buf, prelink_info, "__kmod_start");
if (!kmod_start) {
struct section_64 *kexts_text = macho_find_section(buf, "__PLK_TEXT_EXEC", "__text");
if (!kexts_text) return;
function(buf, buf + kexts_text->offset, kexts_text->size);
} else {
uint64_t kmod_count = kmod_start->size >> 3;
uint64_t *start = Cast(uint64_t*, buf + kmod_start->offset);
for (uint32_t i = 0; i < kmod_count; i++) {
struct mach_header_64 *kext = Cast(struct mach_header_64*, macho_va_to_ptr(buf, macho_xnu_untag_va(start[i])));
struct section_64 *kext_text = macho_find_section(Cast(char *, kext), "__TEXT_EXEC", "__text");
function(buf, macho_va_to_ptr(buf, macho_xnu_untag_va(kext_text->addr)), kext_text->size);
}
}
}
char *fileset_va_to_ptr(char *buf, char *kext, uint64_t addr) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = macho_get_segment_for_va(kext, addr);
if (!segment) {
return NULL;
} else if (segment->vmaddr == addr) {
return buf + segment->fileoff;
}
struct section_64 *section = macho_get_section_for_va(segment, addr);
uint64_t offset = addr - section->addr;
return buf + section->offset + offset;
}
struct segment_command_64 *fileset_get_segment_for_ptr(char *buf, char *kext, char *ptr) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64 *after_header = Cast(struct load_command_64 *, kext + sizeof(struct mach_header_64));
struct mach_header_64 *header = Cast(struct mach_header_64*, kext);
struct segment_command_64 *segment = NULL;
uint64_t ptr_addr = (uint64_t) ptr;
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SEGMENT_64) {
segment = (struct segment_command_64 *) after_header;
uint64_t segment_start = (uint64_t) buf + segment->fileoff;
uint64_t segment_end = segment_start + segment->filesize;
if (segment_start <= ptr_addr && segment_end > ptr_addr) {
// segment's range contains the ptr
return segment;
}
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
printf("%s: Unable to find segment containing ptr %p!\n", __FUNCTION__, ptr);
return NULL;
}
struct section_64 *fileset_find_section_for_ptr(char *buf, char *kext, char *ptr) {
if (!macho_check(buf)) {
return NULL;
}
struct segment_command_64 *segment = fileset_get_segment_for_ptr(buf, kext, ptr);
if (!segment) {
return NULL;
}
struct section_64 *section = macho_get_section_for_ptr(segment, buf, ptr);
if (!section) {
return NULL;
}
return section;
}
uint64_t fileset_ptr_to_va(char *buf, char *kext, char *ptr) {
if (!macho_check(buf)) {
return 0;
}
struct section_64 *section = fileset_find_section_for_ptr(buf, kext, ptr);
uint64_t offset = ptr - buf - section->offset;
return section->addr + offset;
}
struct nlist_64 *fileset_find_symbol(char *buf, char *kext, char *name) {
if (!macho_check(buf)) {
return NULL;
}
struct load_command_64 *after_header = Cast(struct load_command_64*, kext + sizeof(struct mach_header_64));
struct mach_header_64 *header = Cast(struct mach_header_64*, kext);
struct symtab_command *symtab_cmd = NULL;
for (uint32_t i = 0; i < header->ncmds; i++) {
if (after_header->cmd == LC_SYMTAB) {
symtab_cmd = (struct symtab_command *) after_header;
break;
}
after_header = (struct load_command_64 *) ((char *) after_header + after_header->cmdsize);
}
if (!symtab_cmd) {
printf("%s: Unable to find symbol table!\n", __FUNCTION__);
return NULL;
}
struct nlist_64 *symtab = Cast(struct nlist_64*, buf + symtab_cmd->symoff);
char *strtab = buf + symtab_cmd->stroff;
for (uint32_t i = 0; i < symtab_cmd->nsyms; i++) {
struct nlist_64 *symbol_nlist = symtab + i;
char *sym_name = strtab + symbol_nlist->un.str_index;
if (strcmp(sym_name, name) == 0) {
return symbol_nlist;
}
}
//printf("%s: Unable to find symbol %s!\n", __FUNCTION__, name);
return NULL;
}
+42
View File
@@ -0,0 +1,42 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../../include/formats/macho.h"
#include "../../include/formats/elf.h"
#include "../../include/formats/pe.h"
#include "../../include/utils.h"
// right now this is just ptr & virtual address conversion
char *pf_va_to_ptr(char *buf, uint64_t addr) {
char *ptr = NULL;
if (macho_check(buf)) {
ptr = macho_va_to_ptr(buf, addr);
} else if (elf_check(buf)) {
ptr = elf_va_to_ptr(buf, addr);
} else if (pe_check(buf)) {
ptr = pe_va_to_ptr(buf, addr);
} else {
printf("%s: Unknown binary format!\n", __FUNCTION__);
}
return ptr;
}
uint64_t pf_ptr_to_va(char *buf, char *ptr) {
uint64_t va = 0;
if (macho_check(buf)) {
va = macho_ptr_to_va(buf, ptr);
} else if (elf_check(buf)) {
va = elf_ptr_to_va(buf, ptr);
} else if (pe_check(buf)) {
va = pe_ptr_to_va(buf, ptr);
} else {
printf("%s: Unknown binary format!\n", __FUNCTION__);
}
return va;
}
+180
View File
@@ -0,0 +1,180 @@
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "../../include/formats/pe.h"
#include "../../include/utils.h"
bool dos_check(char *buf) {
/*struct DOS_Header* dos_hdr = Cast(struct DOS_Header*, buf);
if (strncmp(dos_hdr->e_magic, "MZ", 2) == 0) {
return true;
}
return false;*/
return true;
}
struct COFF_Header *get_pe_header(char *buf) {
if (!dos_check(buf)) {
#ifndef NOLOG
printf("No DOS stub!\n");
#endif
return NULL;
}
struct DOS_Header *dos_hdr = Cast(struct DOS_Header*, buf);
return Cast(struct COFF_Header *, buf + dos_hdr->e_lfanew);
}
bool pe_check(char *buf) {
/*struct COFF_Header* pe_hdr = get_pe_header(buf);
if (!pe_hdr) {
return false;
}
if (strcmp(pe_hdr->magic, "PE") == 0) {
return true;
}
return false;*/
return true;
}
bool is_pe(char *buf) {
bool pe = pe_check(buf);
if (!pe) {
#ifndef NOLOG
printf("%s: Not a PE!\n", __FUNCTION__);
#endif
}
return pe;
}
struct PE64_Optional_Header *get_pe_opt_header(char *buf) {
if (!dos_check(buf)) {
#ifndef NOLOG
printf("No DOS stub!\n");
#endif
return NULL;
}
if (!pe_check(buf)) return NULL;
struct COFF_Header *pe_hdr = get_pe_header(buf);
return Cast(struct PE64_Optional_Header*, (char *) pe_hdr + sizeof(struct COFF_Header));
}
struct Symbol_Header *pe_get_symtab(char *buf) {
if (!pe_check(buf)) return NULL;
struct COFF_Header *pe_hdr = get_pe_header(buf);
return Cast(struct Symbol_Header*, buf + pe_hdr->pointerToSymbolTable);
}
char *pe_get_strtab(char *buf) {
if (!pe_check(buf)) return NULL;
struct COFF_Header *pe_hdr = get_pe_header(buf);
char *symtab = Cast(char *, pe_get_symtab(buf));
return symtab + (pe_hdr->numberOfSymbols * 18); // 18 is the correct size, but struct alignment makes it 20.
}
struct Section_Header *pe_get_section(char *buf, const char *name) {
if (!pe_check(buf)) return NULL;
struct COFF_Header *pe_hdr = get_pe_header(buf);
struct Section_Header *sects_start = Cast(struct Section_Header *, (char *) pe_hdr + sizeof(struct COFF_Header) + pe_hdr->sizeOfOptionalHeader);
char *strtab = pe_get_strtab(buf);
for (int i = 0; i < pe_hdr->numberOfSections; i++) {
struct Section_Header *section = sects_start + i;
char *real_name = section->name;
if (real_name[0] == '/') {
real_name = strtab + strtoul(real_name + 1, 0, 0);
}
if (strncmp(real_name, name, 8) == 0) {
return section;
}
}
return NULL;
}
char *pe_va_to_ptr(char *buf, uint64_t addr) {
if (!pe_check(buf)) return NULL;
struct COFF_Header *pe_hdr = get_pe_header(buf);
struct PE64_Optional_Header *opt_hdr = get_pe_opt_header(buf);
struct Section_Header *sects_start = Cast(struct Section_Header*, (char *) opt_hdr + pe_hdr->sizeOfOptionalHeader);
for (int i = 0; i < pe_hdr->numberOfSections; i++) {
struct Section_Header *section = sects_start + i;
uint64_t section_start = opt_hdr->imageBase + section->virtualAddress;
uint64_t section_end = section_start + section->virtualSize;
if (section_start <= addr && section_end > addr) {
uint64_t offset = addr - section_start;
return buf + section->pointerToRawData + offset;
}
}
return NULL;
}
uint64_t pe_ptr_to_va(char *buf, char *ptr) {
if (!pe_check(buf)) return 0;
struct COFF_Header *pe_hdr = get_pe_header(buf);
struct PE64_Optional_Header *opt_hdr = get_pe_opt_header(buf);
struct Section_Header *sects_start = Cast(struct Section_Header*, (char*)opt_hdr + pe_hdr->sizeOfOptionalHeader);
uint64_t ptr_addr = (uint64_t) ptr;
for (int i = 0; i < pe_hdr->numberOfSections; i++) {
struct Section_Header *section = sects_start + i;
uint64_t section_start = (uint64_t) buf + section->pointerToRawData;
uint64_t section_end = section_start + section->sizeOfRawData;
if (section_start <= ptr_addr && section_end > ptr_addr) {
uint64_t offset = ptr_addr - section_start;
return opt_hdr->imageBase + section->virtualAddress + offset;
}
}
return 0;
}
struct Symbol_Header *pe_find_symbol(char *buf, char *name) {
if (!pe_check(buf)) return 0;
struct COFF_Header *pe_hdr = get_pe_header(buf);
char *symtab = Cast(char *, pe_get_symtab(buf));
char *strtab = pe_get_strtab(buf);
for (uint32_t i = 0; i < pe_hdr->numberOfSymbols; i++) {
struct Symbol_Header *symbol = Cast(struct Symbol_Header *, symtab + (i * 18)); // 18 is the correct size, but struct alignment makes it 20.
char *real_name = symbol->name.name;
if (symbol->name.over_8b.zeros == 0 && symbol->name.over_8b.strtab_off != 0) {
real_name = strtab + symbol->name.over_8b.strtab_off;
}
if (strcmp(real_name, name) == 0) {
return symbol;
}
}
return NULL;
}
+146
View File
@@ -0,0 +1,146 @@
// plooshfinder
// WIP patchfinder
// Made by Ploosh
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "../include/plooshfinder.h"
#include "../include/plooshfinder_sig.h"
#include "../include/formats/pe.h"
void *pf_zero_buf;
struct pf_patch_t pf_construct_patch(void *matches, void *masks, uint32_t count, bool (*callback)(struct pf_patch_t *patch, void *stream)) {
struct pf_patch_t patch;
// construct the patch
patch.matches = matches;
patch.masks = masks;
patch.disabled = false;
patch.count = count;
patch.callback = callback;
return patch;
}
struct pf_patchset_t pf_construct_patchset(struct pf_patch_t *patches, uint32_t count, bool (*handler)(void *buf, size_t size, struct pf_patchset_t patchset)) {
struct pf_patchset_t patchset;
patchset.patches = patches;
patchset.count = count;
patchset.handler = handler;
return patchset;
}
bool pf_patchset_emit(void *buf, size_t size, struct pf_patchset_t patchset) {
return patchset.handler(buf, size, patchset);
}
void pf_disable_patch(struct pf_patch_t *patch) {
patch->disabled = true;
}
uint8_t *pf_find_next(uint8_t *stream, uint32_t count, uint8_t match, uint8_t mask) {
uint8_t *find_stream = 0;
for (int i = 0; (uint32_t) i < count; i++) {
if (pf_maskmatch(stream[i], match, mask)) {
find_stream = stream + i;
break;
}
}
return find_stream;
}
uint8_t *pf_find_prev(uint8_t *stream, uint32_t count, uint8_t match, uint8_t mask) {
uint8_t *find_stream = 0;
for (int neg_count = -(int)count; count > 0; count--) {
int ind = neg_count + count;
if (pf_maskmatch(stream[ind], match, mask)) {
find_stream = stream + ind;
break;
}
}
return find_stream;
}
uint8_t* pf_find_next_multiple(uint8_t* stream, uint32_t count, uint8_t* matches, uint8_t* masks, uint32_t mmc) {
uint8_t* find_stream = 0;
for (int i = 0; (uint32_t)i < count; i++) {
bool cont = false;
for (uint32_t i2 = 0; i2 < mmc; i2++) {
if (!pf_maskmatch(stream[i + i2], matches[i2], masks[i2])) {
cont = true;
break;
}
}
if (cont) continue;
find_stream = stream + i;
break;
}
return find_stream;
}
uint8_t* pf_find_prev_multiple(uint8_t* stream, uint32_t count, uint8_t *matches, uint8_t *masks, uint32_t mmc) {
uint8_t* find_stream = 0;
for (int neg_count = -(int)count; count > 0; count--) {
int ind = neg_count + count;
bool cont = false;
for (uint32_t i = 0; i < mmc; i++) {
if (!pf_maskmatch(stream[ind], matches[i], masks[i])) {
cont = true;
break;
}
}
if (cont) continue;
find_stream = stream + ind;
break;
}
return find_stream;
}
bool pf_set_zero_buf(struct pf_patch_t *patch, uint8_t *stream) {
pf_zero_buf = stream;
pf_disable_patch(patch);
return true;
}
void *pf_find_zero_buf(void *buf, size_t size, size_t shc_count) {
pf_zero_buf = NULL;
uint8_t *matches = (uint8_t *) malloc(shc_count);
uint8_t *masks = (uint8_t *) malloc(shc_count);
for (size_t i = 0; i < shc_count; i++) {
matches[i] = 0;
masks[i] = 0xff;
}
struct pf_patch_t patch = pf_construct_patch(matches, masks, sizeof(matches) / sizeof(uint8_t), (bool (*)(struct pf_patch_t *, void *stream)) pf_set_zero_buf);
struct pf_patch_t patches[] = {
patch
};
struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), (bool (*)(void *, size_t, struct pf_patchset_t)) pf_find_maskmatch);
pf_patchset_emit(buf, size, patchset);
#ifndef NOLOG
if (!pf_zero_buf) {
printf("%s: Unable to find zero buf!\n", __FUNCTION__);
}
#endif
return pf_zero_buf;
}
+59
View File
@@ -0,0 +1,59 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "../include/plooshfinder.h"
#include "../include/plooshfinder8.h"
#include <Windows.h>
bool pf_maskmatch(uint8_t insn, uint8_t match, uint8_t mask) {
return (insn & mask) == match;
}
bool pf_find_maskmatch(void *buf, size_t size, struct pf_patchset_t patchset) {
uint8_t *stream = buf;
for (uint64_t i = 0; i < size; i++) {
for (uint32_t p = 0; p < patchset.count; p++) {
struct pf_patch8_t *patch = (struct pf_patch8_t *) patchset.patches + p;
if (patch->disabled) continue;
uint32_t x;
for (x = 0; x < patch->count; x++) {
if (!pf_maskmatch(stream[i + x], patch->matches[x], patch->masks[x])) {
break;
}
}
if (x == patch->count) {
if (patch->callback(patch, stream + i)) {
uint32_t disabled = 0;
for (uint32_t p = 0; p < patchset.count; p++) {
struct pf_patch8_t* pt = (struct pf_patch8_t *) patchset.patches + p;
if (pt->disabled) {
disabled++;
continue;
}
if (patch->callback == pt->callback) {
DWORD og;
VirtualProtect(pt + offsetof(struct pf_patch8_t, disabled), sizeof(bool), PAGE_READWRITE, &og); // this is only needed bc constexpr lmao
pt->disabled = true; // disable patches that have already been found
VirtualProtect(pt + offsetof(struct pf_patch8_t, disabled), sizeof(bool), og, &og);
disabled++;
}
}
if (disabled == patchset.count) return true; // if all are done, return
}
}
}
}
return false;
}
int8_t pf_signextend(int8_t val, uint8_t bits) {
val = (uint8_t) val << (8 - bits);
val >>= 8 - bits;
return val;
}
+68
View File
@@ -0,0 +1,68 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "../include/plooshfinder.h"
#include "../include/plooshfinder8.h"
#include <stdio.h>
struct pf_patch_t pf_construct_patch_sig(const char *sig, bool (*callback)(struct pf_patch_t *patch, void *stream)) {
struct pf_patch_t patch;
char *temp_sig = malloc(strlen(sig) + 1);
strcpy_s(temp_sig, strlen(sig) + 1, sig);
void *orig_ts = temp_sig;
uint8_t temp_match, temp_mask;
char *part;
uint32_t count = 0;
part = strtok(temp_sig, " ");
while (part != NULL) {
count++;
part = strtok(NULL, " ");
}
strcpy_s((char *) orig_ts, strlen(sig) + 1, sig);
temp_sig = orig_ts;
uint8_t *matches = malloc(count);
uint8_t *masks = malloc(count);
uint32_t index = 0;
part = strtok(temp_sig, " ");
while (part != NULL) {
size_t len = strlen(part);
temp_match = 0x0;
temp_mask = 0x0;
for (size_t i = 0; i < len; i++) {
if (part[i] != '?') {
char hc[2] = {
part[i],
0
};
uint8_t hex = (uint8_t) strtoul(hc, NULL, 16);
uint8_t shift = (uint8_t) ((len - i - 1) * 4);
temp_match |= hex << shift;
temp_mask |= 0xf << shift;
}
}
matches[index] = temp_match;
masks[index] = temp_mask;
index++;
part = strtok(NULL, " ");
}
free(orig_ts);
// construct the patch
patch.matches = matches;
patch.masks = masks;
patch.disabled = false;
patch.count = count;
patch.callback = callback;
return patch;
}
+13
View File
@@ -0,0 +1,13 @@
#include "../include/utils.h"
// the compiler will just use a bswap (optimizations) if possible
// but it's here if it's needed (i.e. there's no intrinsic)
uint32_t convert_endianness32(uint32_t val) {
uint32_t swapped = 0;
for (uint32_t i = 0; i < 4; i++) {
uint32_t sh = i << 3;
swapped |= ((val >> sh) & 0xff) << (sh ^ 24);
}
return swapped;
}