initial push
This commit is contained in:
commit
88a0261880
17
.clang-format
Normal file
17
.clang-format
Normal file
|
@ -0,0 +1,17 @@
|
|||
IndentWidth: 4
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
UseTab: Never
|
||||
ColumnLimit: 0
|
||||
SpaceAfterCStyleCast: true
|
||||
PointerAlignment: Right
|
||||
NamespaceIndentation: All
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
IndentPPDirectives: AfterHash
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
.vs
|
||||
.temp
|
||||
|
||||
build
|
6
README.md
Normal file
6
README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# osu-auth-reader
|
||||
Read portions of the raw token from osu's anticheat.
|
||||
|
||||
That's all really!
|
||||
|
||||
![Demo Image](https://i.imgur.com/pmTf8Y0.png)
|
25
ac_checker.sln
Normal file
25
ac_checker.sln
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32505.173
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ac_checker", "ac_checker\ac_checker.vcxproj", "{4FA0ACF4-DC50-4201-82BD-3A11664286AC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4FA0ACF4-DC50-4201-82BD-3A11664286AC}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4FA0ACF4-DC50-4201-82BD-3A11664286AC}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4FA0ACF4-DC50-4201-82BD-3A11664286AC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4FA0ACF4-DC50-4201-82BD-3A11664286AC}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {43EE6F3D-E5C7-4D8E-868F-4EF339262E61}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
103
ac_checker/ac_checker.vcxproj
Normal file
103
ac_checker/ac_checker.vcxproj
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{4fa0acf4-dc50-4201-82bd-3a11664286ac}</ProjectGuid>
|
||||
<RootNamespace>acchecker</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\.temp\$(Configuration)\</IntDir>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include;</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\.temp\$(Configuration)\</IntDir>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include;</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="source\util\hooklib.cpp" />
|
||||
<ClCompile Include="source\util\memory.cpp" />
|
||||
<ClCompile Include="source\util\pe.cpp" />
|
||||
<ClCompile Include="source\vendor\hde.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\util\hooklib.hpp" />
|
||||
<ClInclude Include="include\util\memory.hpp" />
|
||||
<ClInclude Include="include\util\pe.hpp" />
|
||||
<ClInclude Include="include\vendor\hde.hpp" />
|
||||
<ClInclude Include="include\vendor\small_vector.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
51
ac_checker/ac_checker.vcxproj.filters
Normal file
51
ac_checker/ac_checker.vcxproj.filters
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?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>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\util\memory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\util\hooklib.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\vendor\hde.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\util\pe.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\vendor\small_vector.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\util\memory.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\util\hooklib.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\vendor\hde.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\util\pe.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
6
ac_checker/ac_checker.vcxproj.user
Normal file
6
ac_checker/ac_checker.vcxproj.user
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>true</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
</Project>
|
31
ac_checker/include/util/hooklib.hpp
Normal file
31
ac_checker/include/util/hooklib.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util {
|
||||
|
||||
struct Hook {
|
||||
uintptr_t _bytes = 0;
|
||||
uintptr_t _target = 0;
|
||||
uintptr_t _detour = 0;
|
||||
uintptr_t _tramp = 0;
|
||||
|
||||
bool enable(uintptr_t target, uintptr_t detour);
|
||||
void disable();
|
||||
|
||||
template <typename Target, typename Detour>
|
||||
inline bool enable(Target target, Detour detour) {
|
||||
return enable((uintptr_t) target, (uintptr_t) detour);
|
||||
}
|
||||
|
||||
template <typename Func, typename... Args>
|
||||
inline auto invoke(Args &&...args) const {
|
||||
return ((Func) _tramp)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
#define define_hook(name, ret, call_conv, ...) \
|
||||
inline util::Hook name; \
|
||||
ret call_conv name##_hook(__VA_ARGS__);
|
16
ac_checker/include/util/memory.hpp
Normal file
16
ac_checker/include/util/memory.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace signatures {
|
||||
|
||||
constexpr static auto s_token_log_ref = "558BEC83EC08C645FC01C745";
|
||||
|
||||
}
|
||||
|
||||
namespace util {
|
||||
|
||||
uint8_t *find_pattern(std::string_view pattern, uint8_t *begin, size_t size, ptrdiff_t offset = 0x0);
|
||||
uint8_t *scan_module(std::string_view module_name, std::string_view pattern, ptrdiff_t offset = 0x0);
|
||||
|
||||
} // namespace util
|
17
ac_checker/include/util/pe.hpp
Normal file
17
ac_checker/include/util/pe.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
// <3 mr polish man
|
||||
|
||||
namespace util {
|
||||
|
||||
struct ModuleInfo {
|
||||
uintptr_t base;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
ModuleInfo get_module(std::string_view module_name);
|
||||
uintptr_t get_export(std::string_view module_name, std::string_view export_name);
|
||||
|
||||
} // namespace util
|
104
ac_checker/include/vendor/hde.hpp
vendored
Normal file
104
ac_checker/include/vendor/hde.hpp
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define C_NONE 0x00
|
||||
#define C_MODRM 0x01
|
||||
#define C_IMM8 0x02
|
||||
#define C_IMM16 0x04
|
||||
#define C_IMM_P66 0x10
|
||||
#define C_REL8 0x20
|
||||
#define C_REL32 0x40
|
||||
#define C_GROUP 0x80
|
||||
#define C_ERROR 0xff
|
||||
|
||||
#define PRE_ANY 0x00
|
||||
#define PRE_NONE 0x01
|
||||
#define PRE_F2 0x02
|
||||
#define PRE_F3 0x04
|
||||
#define PRE_66 0x08
|
||||
#define PRE_67 0x10
|
||||
#define PRE_LOCK 0x20
|
||||
#define PRE_SEG 0x40
|
||||
#define PRE_ALL 0xff
|
||||
|
||||
#define DELTA_OPCODES 0x4a
|
||||
#define DELTA_FPU_REG 0xf1
|
||||
#define DELTA_FPU_MODRM 0xf8
|
||||
#define DELTA_PREFIXES 0x130
|
||||
#define DELTA_OP_LOCK_OK 0x1a1
|
||||
#define DELTA_OP2_LOCK_OK 0x1b9
|
||||
#define DELTA_OP_ONLY_MEM 0x1cb
|
||||
#define DELTA_OP2_ONLY_MEM 0x1da
|
||||
|
||||
#define F_MODRM 0x00000001
|
||||
#define F_SIB 0x00000002
|
||||
#define F_IMM8 0x00000004
|
||||
#define F_IMM16 0x00000008
|
||||
#define F_IMM32 0x00000010
|
||||
#define F_DISP8 0x00000020
|
||||
#define F_DISP16 0x00000040
|
||||
#define F_DISP32 0x00000080
|
||||
#define F_RELATIVE 0x00000100
|
||||
#define F_2IMM16 0x00000800
|
||||
#define F_ERROR 0x00001000
|
||||
#define F_ERROR_OPCODE 0x00002000
|
||||
#define F_ERROR_LENGTH 0x00004000
|
||||
#define F_ERROR_LOCK 0x00008000
|
||||
#define F_ERROR_OPERAND 0x00010000
|
||||
#define F_PREFIX_REPNZ 0x01000000
|
||||
#define F_PREFIX_REPX 0x02000000
|
||||
#define F_PREFIX_REP 0x03000000
|
||||
#define F_PREFIX_66 0x04000000
|
||||
#define F_PREFIX_67 0x08000000
|
||||
#define F_PREFIX_LOCK 0x10000000
|
||||
#define F_PREFIX_SEG 0x20000000
|
||||
#define F_PREFIX_ANY 0x3f000000
|
||||
|
||||
#define PREFIX_SEGMENT_CS 0x2e
|
||||
#define PREFIX_SEGMENT_SS 0x36
|
||||
#define PREFIX_SEGMENT_DS 0x3e
|
||||
#define PREFIX_SEGMENT_ES 0x26
|
||||
#define PREFIX_SEGMENT_FS 0x64
|
||||
#define PREFIX_SEGMENT_GS 0x65
|
||||
#define PREFIX_LOCK 0xf0
|
||||
#define PREFIX_REPNZ 0xf2
|
||||
#define PREFIX_REPX 0xf3
|
||||
#define PREFIX_OPERAND_SIZE 0x66
|
||||
#define PREFIX_ADDRESS_SIZE 0x67
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t p_rep;
|
||||
uint8_t p_lock;
|
||||
uint8_t p_seg;
|
||||
uint8_t p_66;
|
||||
uint8_t p_67;
|
||||
uint8_t opcode;
|
||||
uint8_t opcode2;
|
||||
uint8_t modrm;
|
||||
uint8_t modrm_mod;
|
||||
uint8_t modrm_reg;
|
||||
uint8_t modrm_rm;
|
||||
uint8_t sib;
|
||||
uint8_t sib_scale;
|
||||
uint8_t sib_index;
|
||||
uint8_t sib_base;
|
||||
union {
|
||||
uint8_t imm8;
|
||||
uint16_t imm16;
|
||||
uint32_t imm32;
|
||||
} imm;
|
||||
union {
|
||||
uint8_t disp8;
|
||||
uint16_t disp16;
|
||||
uint32_t disp32;
|
||||
} disp;
|
||||
uint32_t flags;
|
||||
} hde32s;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
unsigned int hde32_disasm(const void *code, hde32s *hs);
|
371
ac_checker/include/vendor/small_vector.hpp
vendored
Normal file
371
ac_checker/include/vendor/small_vector.hpp
vendored
Normal file
|
@ -0,0 +1,371 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace vendor {
|
||||
|
||||
template <class T, std::size_t N, class Allocator = std::allocator<T>>
|
||||
class small_vector {
|
||||
std::array<T, N> stack_;
|
||||
std::vector<T, Allocator> heap_;
|
||||
std::size_t size_{0};
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef value_type &reference;
|
||||
typedef const value_type &const_reference;
|
||||
typedef Allocator allocator_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
|
||||
small_vector() = default;
|
||||
|
||||
explicit small_vector(size_type count, const T &value = T(), const Allocator &alloc = Allocator()) {
|
||||
if (count == N) {
|
||||
stack_.fill(value);
|
||||
} else if (count < N) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
stack_[i] = value;
|
||||
}
|
||||
} else {
|
||||
// use heap
|
||||
heap_ = std::move(std::vector<T>(count, value, alloc));
|
||||
}
|
||||
size_ = count;
|
||||
}
|
||||
|
||||
small_vector(const small_vector &other, const Allocator &alloc = Allocator())
|
||||
: stack_(other.stack_), heap_(other.heap_, alloc), size_(other.size_) {
|
||||
}
|
||||
|
||||
small_vector(small_vector &&other, const Allocator &alloc = Allocator())
|
||||
: stack_(std::move(other.stack_)), heap_(std::move(other.heap_), alloc), size_(std::move(other.size_)) {
|
||||
}
|
||||
|
||||
small_vector(std::initializer_list<T> initlist, const Allocator &alloc = Allocator()) {
|
||||
const auto input_size = initlist.size();
|
||||
if (input_size <= N) {
|
||||
std::copy(initlist.begin(), initlist.end(), stack_.begin());
|
||||
} else {
|
||||
heap_ = std::move(std::vector<T>(initlist, alloc));
|
||||
}
|
||||
size_ = input_size;
|
||||
}
|
||||
|
||||
small_vector &operator=(const small_vector &rhs) {
|
||||
stack_ = rhs.stack_;
|
||||
heap_ = rhs.heap_;
|
||||
size_ = rhs.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
small_vector &operator=(small_vector &&rhs) {
|
||||
stack_ = std::move(rhs.stack_);
|
||||
heap_ = std::move(rhs.heap_);
|
||||
size_ = rhs.size_;
|
||||
rhs.size_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
small_vector &operator=(std::initializer_list<value_type> rhs) {
|
||||
if (rhs.size() <= N) {
|
||||
stack_ = rhs;
|
||||
} else {
|
||||
heap_ = rhs;
|
||||
}
|
||||
size_ = rhs.size();
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const noexcept {
|
||||
return heap_.get_allocator();
|
||||
}
|
||||
|
||||
reference at(size_type pos) {
|
||||
if (size_ < N) {
|
||||
return stack_.at(pos);
|
||||
} else {
|
||||
return heap_.at(pos);
|
||||
}
|
||||
}
|
||||
|
||||
const_reference at(size_type pos) const {
|
||||
if (size_ < N) {
|
||||
return stack_.at(pos);
|
||||
} else {
|
||||
return heap_.at(pos);
|
||||
}
|
||||
}
|
||||
|
||||
reference operator[](size_type pos) {
|
||||
if (size_ < N) {
|
||||
return stack_[pos];
|
||||
} else {
|
||||
return heap_[pos];
|
||||
}
|
||||
}
|
||||
|
||||
const_reference operator[](size_type pos) const {
|
||||
if (size_ < N) {
|
||||
return stack_[pos];
|
||||
} else {
|
||||
return heap_[pos];
|
||||
}
|
||||
}
|
||||
|
||||
reference front() {
|
||||
if (size_ < N) {
|
||||
return stack_.front();
|
||||
} else {
|
||||
return heap_.front();
|
||||
}
|
||||
}
|
||||
|
||||
const_reference front() const {
|
||||
if (size_ < N) {
|
||||
return stack_.front();
|
||||
} else {
|
||||
return heap_.front();
|
||||
}
|
||||
}
|
||||
|
||||
reference back() {
|
||||
if (size_ < N) {
|
||||
return stack_[size_ - 1];
|
||||
} else {
|
||||
return heap_[size_ - 1];
|
||||
}
|
||||
}
|
||||
|
||||
const_reference back() const {
|
||||
if (size_ < N) {
|
||||
return stack_[size_ - 1];
|
||||
} else {
|
||||
return heap_[size_ - 1];
|
||||
}
|
||||
}
|
||||
|
||||
pointer data() noexcept {
|
||||
if (size_ < N) {
|
||||
return stack_.data();
|
||||
} else {
|
||||
return heap_.data();
|
||||
}
|
||||
}
|
||||
|
||||
const_pointer data() const noexcept {
|
||||
if (size_ < N) {
|
||||
return stack_.data();
|
||||
} else {
|
||||
return heap_.data();
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
void shrink_to_fit() {
|
||||
if (size_ >= N) {
|
||||
heap_.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(const T &value) {
|
||||
if (size_ < N) {
|
||||
stack_[size_] = value;
|
||||
} else {
|
||||
if (size_ == N) {
|
||||
// move everything to heap
|
||||
std::move(stack_.begin(), stack_.end(), std::back_inserter(heap_));
|
||||
}
|
||||
heap_.push_back(value);
|
||||
}
|
||||
size_ += 1;
|
||||
}
|
||||
|
||||
void push_back(T &&value) {
|
||||
if (size_ < N) {
|
||||
stack_[size_] = std::move(value);
|
||||
} else {
|
||||
if (size_ == N) {
|
||||
// move everything to heap
|
||||
std::move(stack_.begin(), stack_.end(), std::back_inserter(heap_));
|
||||
}
|
||||
heap_.push_back(std::move(value));
|
||||
}
|
||||
size_ += 1;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
if (size_ == 0) {
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (size_ < N) {
|
||||
size_ -= 1;
|
||||
} else {
|
||||
// currently using heap
|
||||
heap_.pop_back();
|
||||
size_ -= 1;
|
||||
|
||||
// now check if all data can fit on stack
|
||||
// if so, move back to stack
|
||||
if (size_ < N) {
|
||||
std::move(heap_.begin(), heap_.end(), stack_.begin());
|
||||
heap_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resizes the container to contain count elements.
|
||||
void resize(size_type count, T value = T()) {
|
||||
if (count <= N) {
|
||||
// new `count` of elements completely fit on stack
|
||||
if (size_ >= N) {
|
||||
// currently, all data on heap
|
||||
// move back to stack
|
||||
std::move(heap_.begin(), heap_.end(), stack_.begin());
|
||||
} else {
|
||||
// all data already on stack
|
||||
// just update size
|
||||
}
|
||||
} else {
|
||||
// new `count` of data is going to be on the heap
|
||||
// check if data is currently on the stack
|
||||
if (size_ < N) {
|
||||
// move to heap
|
||||
std::move(stack_.begin(), stack_.end(), std::back_inserter(heap_));
|
||||
}
|
||||
heap_.resize(count, value);
|
||||
}
|
||||
size_ = count;
|
||||
}
|
||||
|
||||
void swap(small_vector &other) noexcept {
|
||||
std::swap(stack_, other.stack_);
|
||||
std::swap(heap_, other.heap_);
|
||||
std::swap(size_, other.size_);
|
||||
};
|
||||
|
||||
// Assigns the given value value to all elements in the container
|
||||
void fill(const_reference value) {
|
||||
if (size_ < N) {
|
||||
stack_.fill(value);
|
||||
} else {
|
||||
std::fill(heap_.begin(), heap_.end(), value);
|
||||
}
|
||||
}
|
||||
|
||||
class iterator {
|
||||
pointer ptr_;
|
||||
|
||||
public:
|
||||
typedef iterator self_type;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef T *pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
iterator(pointer ptr)
|
||||
: ptr_(ptr) {
|
||||
}
|
||||
self_type operator++() {
|
||||
ptr_++;
|
||||
return *this;
|
||||
}
|
||||
self_type operator++(int) {
|
||||
self_type i = *this;
|
||||
ptr_++;
|
||||
return i;
|
||||
}
|
||||
reference operator*() {
|
||||
return *ptr_;
|
||||
}
|
||||
pointer operator->() {
|
||||
return ptr_;
|
||||
}
|
||||
bool operator==(const self_type &rhs) {
|
||||
return ptr_ == rhs.ptr_;
|
||||
}
|
||||
bool operator!=(const self_type &rhs) {
|
||||
return ptr_ != rhs.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
class const_iterator {
|
||||
pointer ptr_;
|
||||
|
||||
public:
|
||||
typedef const_iterator self_type;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef T *pointer;
|
||||
typedef int difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
const_iterator(pointer ptr)
|
||||
: ptr_(ptr) {
|
||||
}
|
||||
self_type operator++() {
|
||||
ptr_++;
|
||||
return *this;
|
||||
}
|
||||
self_type operator++(int) {
|
||||
self_type i = *this;
|
||||
ptr_++;
|
||||
return i;
|
||||
}
|
||||
const value_type &operator*() {
|
||||
return *ptr_;
|
||||
}
|
||||
const pointer operator->() {
|
||||
return ptr_;
|
||||
}
|
||||
bool operator==(const self_type &rhs) {
|
||||
return ptr_ == rhs.ptr_;
|
||||
}
|
||||
bool operator!=(const self_type &rhs) {
|
||||
return ptr_ != rhs.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin() {
|
||||
if (size_ < N) {
|
||||
return iterator(stack_.data());
|
||||
} else {
|
||||
return iterator(heap_.data());
|
||||
}
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
if (size_ < N) {
|
||||
return iterator(stack_.data() + size_);
|
||||
} else {
|
||||
return iterator(heap_.data() + size_);
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (size_ < N) {
|
||||
return const_iterator(stack_.data());
|
||||
} else {
|
||||
return const_iterator(heap_.data());
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
if (size_ < N) {
|
||||
return const_iterator(stack_.data() + size_);
|
||||
} else {
|
||||
return const_iterator(heap_.data() + size_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace vendor
|
49
ac_checker/main.cpp
Normal file
49
ac_checker/main.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#include <util/hooklib.hpp>
|
||||
#include <util/memory.hpp>
|
||||
|
||||
define_hook(log_token, int, __fastcall, uintptr_t, uintptr_t, char *, size_t);
|
||||
|
||||
template <typename T>
|
||||
constexpr auto x86_abs_addr(T source, ptrdiff_t disp, size_t length) {
|
||||
return (uintptr_t) (source + disp + length);
|
||||
}
|
||||
|
||||
static int __fastcall log_token_hook(uintptr_t ecx, uintptr_t edx, char *text, size_t size) {
|
||||
if (size == 4 /*A trash value representing a flag has been pushed; do not print it.*/) {
|
||||
fprintf(stdout, "[!] flag detected!\n");
|
||||
} else {
|
||||
fprintf(stdout, "[~] %s\n", text);
|
||||
}
|
||||
|
||||
return log_token.invoke<decltype(&log_token_hook)>(ecx, edx, text, size);
|
||||
}
|
||||
|
||||
bool __stdcall DllMain(uintptr_t instance, uint32_t reason, uintptr_t reserved) {
|
||||
if (reason == 1) {
|
||||
std::thread([]() {
|
||||
AllocConsole();
|
||||
SetConsoleTitleA("1337 h4x0r ac checker");
|
||||
freopen_s((FILE **) stdout, "CONOUT$", "w", stdout);
|
||||
|
||||
fprintf(stdout, "iroha // pushfq\n");
|
||||
|
||||
if (auto addr = util::scan_module("osu!auth.dll", signatures::s_token_log_ref, 0x1A)) {
|
||||
log_token.enable(x86_abs_addr(addr, *(ptrdiff_t *) (addr + 0x1), 0x5), log_token_hook);
|
||||
}
|
||||
// The user is likely using a targeted build. (TODO: perhaps add support for this where possible?)
|
||||
else {
|
||||
MessageBoxA(nullptr, "Unsupported target.", "osu!", MB_OK | MB_TOPMOST);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stdout, "initialized.\n");
|
||||
}).detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
76
ac_checker/source/util/hooklib.cpp
Normal file
76
ac_checker/source/util/hooklib.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <Windows.h>
|
||||
#include <util/hooklib.hpp>
|
||||
#include <vendor/hde.hpp>
|
||||
|
||||
namespace util {
|
||||
|
||||
constexpr uint8_t target_shellcode[] = {
|
||||
0x8D, 0x64, 0x24, 0xFC, // lea esp, [esp-0x4]
|
||||
0xC7, 0x04, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, // mov DWORD PTR [esp], ADDRESS
|
||||
0xC3 // ret
|
||||
};
|
||||
|
||||
constexpr uint8_t tramp_shellcode[] = {
|
||||
0x68, 0xFF, 0xFF, 0xFF, 0xFF, // push imm32
|
||||
0xC3, // ret
|
||||
};
|
||||
|
||||
bool Hook::enable(uintptr_t target, uintptr_t detour) {
|
||||
hde32s hde_state;
|
||||
|
||||
while (_bytes < sizeof(target_shellcode)) {
|
||||
_bytes += hde32_disasm((const void *) (target + _bytes), &hde_state);
|
||||
|
||||
if (hde_state.opcode == 0xC3) {
|
||||
_bytes = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto tramp = VirtualAlloc(nullptr, _bytes + sizeof(tramp_shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
if (!tramp) {
|
||||
_bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long old_prot;
|
||||
|
||||
VirtualProtect((void *) target, _bytes, PAGE_EXECUTE_READWRITE, &old_prot);
|
||||
|
||||
_target = target;
|
||||
_detour = detour;
|
||||
_tramp = (uintptr_t) tramp;
|
||||
|
||||
memcpy((uint8_t *) _tramp, (const uint8_t *) _target, _bytes);
|
||||
memcpy((uint8_t *) _tramp + _bytes, tramp_shellcode, sizeof(tramp_shellcode));
|
||||
memcpy((uint8_t *) _target, target_shellcode, sizeof(target_shellcode));
|
||||
|
||||
*(uintptr_t *) (_target + 7) = _detour;
|
||||
*(uintptr_t *) (_tramp + _bytes + 1) = _target + _bytes;
|
||||
|
||||
VirtualProtect((void *) target, _bytes, old_prot, &old_prot);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Hook::disable() {
|
||||
if (!_bytes)
|
||||
return;
|
||||
|
||||
unsigned long old_prot;
|
||||
|
||||
VirtualProtect((void *) _target, _bytes, PAGE_EXECUTE_READWRITE, &old_prot);
|
||||
|
||||
memcpy((uint8_t *) _target, (const uint8_t *) _tramp + _bytes, _bytes);
|
||||
|
||||
VirtualFree((void *) _tramp, 0, MEM_RELEASE);
|
||||
VirtualProtect((void *) _target, _bytes, old_prot, &old_prot);
|
||||
|
||||
_bytes = 0;
|
||||
_target = 0;
|
||||
_detour = 0;
|
||||
_tramp = 0;
|
||||
}
|
||||
|
||||
} // namespace util
|
64
ac_checker/source/util/memory.cpp
Normal file
64
ac_checker/source/util/memory.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <util/memory.hpp>
|
||||
#include <util/pe.hpp>
|
||||
#include <vendor/small_vector.hpp>
|
||||
|
||||
namespace util {
|
||||
|
||||
constexpr uint8_t hex_to_byte(char ch) {
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
return ch - '0';
|
||||
} else if (ch >= 'a' && ch <= 'f') {
|
||||
return ch - 'a' + 10;
|
||||
} else if (ch >= 'A' && ch <= 'F') {
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
|
||||
// >.<
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
constexpr uint8_t stich_byte(char x, char y) {
|
||||
return hex_to_byte(x) << 4 | hex_to_byte(y);
|
||||
}
|
||||
|
||||
uint8_t *find_pattern(std::string_view pattern, uint8_t *begin, size_t size, ptrdiff_t offset) {
|
||||
vendor::small_vector<uint8_t, 0x20> vec;
|
||||
|
||||
for (auto i = 0u; i < pattern.size(); i++) {
|
||||
auto &ch = pattern[i];
|
||||
|
||||
if (ch == '?') {
|
||||
vec.push_back(0xCC);
|
||||
} else if (std::isxdigit(ch)) {
|
||||
vec.push_back(stich_byte(ch, pattern[++i]));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto mem = begin; mem < begin + size; mem++) {
|
||||
bool is_found = true;
|
||||
|
||||
for (auto i = 0u; i < vec.size(); i++) {
|
||||
if (vec[i] != 0xCC && vec[i] != mem[i]) {
|
||||
is_found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_found) {
|
||||
return mem + offset;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t *scan_module(std::string_view module_name, std::string_view pattern, ptrdiff_t offset) {
|
||||
auto module_info = util::get_module(module_name);
|
||||
|
||||
if (!module_info.base)
|
||||
return nullptr;
|
||||
|
||||
return util::find_pattern(pattern, (uint8_t *) module_info.base, module_info.size, offset);
|
||||
}
|
||||
|
||||
} // namespace util
|
70
ac_checker/source/util/pe.cpp
Normal file
70
ac_checker/source/util/pe.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <Windows.h>
|
||||
#include <Winternl.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <util/pe.hpp>
|
||||
|
||||
struct LdrEntry {
|
||||
LIST_ENTRY InLoadOrderLinks;
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
LIST_ENTRY InInitializationOrderLinks;
|
||||
uintptr_t DllBase;
|
||||
uintptr_t EntryPoint;
|
||||
uint32_t SizeOfImage;
|
||||
UNICODE_STRING FullDllName;
|
||||
UNICODE_STRING BaseDllName;
|
||||
};
|
||||
|
||||
namespace util {
|
||||
|
||||
ModuleInfo get_module(std::string_view module_name) {
|
||||
auto peb = ((_TEB *) __readfsdword(0x18))->ProcessEnvironmentBlock;
|
||||
auto list = &peb->Ldr->InMemoryOrderModuleList;
|
||||
|
||||
size_t wide_name_length = 0;
|
||||
wchar_t wide_name[256] = {0};
|
||||
|
||||
mbstowcs_s(&wide_name_length, wide_name, 256, module_name.data(), module_name.size());
|
||||
|
||||
for (auto iter = list->Flink; iter != list; iter = iter->Flink) {
|
||||
auto entry = CONTAINING_RECORD(iter, LdrEntry, InMemoryOrderLinks);
|
||||
|
||||
if (entry->BaseDllName.Buffer && _wcsnicmp(entry->BaseDllName.Buffer, wide_name, wide_name_length) == 0) {
|
||||
return {
|
||||
.base = entry->DllBase,
|
||||
.size = entry->SizeOfImage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
uintptr_t get_export(std::string_view module_name, std::string_view export_name) {
|
||||
auto module_info = get_module(module_name);
|
||||
auto module_base = module_info.base;
|
||||
|
||||
if (!module_base)
|
||||
return 0u;
|
||||
|
||||
auto dos_hdr = (IMAGE_DOS_HEADER *) module_base;
|
||||
auto nt_hdrs = (IMAGE_NT_HEADERS *) (module_base + dos_hdr->e_lfanew);
|
||||
|
||||
auto exports_va = nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
auto exports_size = nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
auto exports = (IMAGE_EXPORT_DIRECTORY *) (module_base + exports_va);
|
||||
|
||||
auto names = (uintptr_t *) (module_base + exports->AddressOfNames);
|
||||
auto functions = (uintptr_t *) (module_base + exports->AddressOfFunctions);
|
||||
auto name_ordinals = (uint16_t *) (module_base + exports->AddressOfNameOrdinals);
|
||||
|
||||
for (auto i = 0u; i < exports->NumberOfNames; i++) {
|
||||
if (export_name.compare((const char *) (module_base + names[i])) == 0)
|
||||
return module_base + functions[name_ordinals[i]];
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
} // namespace util
|
340
ac_checker/source/vendor/hde.cpp
vendored
Normal file
340
ac_checker/source/vendor/hde.cpp
vendored
Normal file
|
@ -0,0 +1,340 @@
|
|||
#include <string.h>
|
||||
#include <vendor/hde.hpp>
|
||||
|
||||
static unsigned char hde32_table[] = {
|
||||
0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xa3, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xac, 0xaa, 0xb2, 0xaa, 0x9f, 0x9f, 0x9f, 0x9f, 0xb5, 0xa3, 0xa3, 0xa4, 0xaa, 0xaa, 0xba, 0xaa, 0x96, 0xaa, 0xa8, 0xaa,
|
||||
0xc3, 0xc3, 0x96, 0x96, 0xb7, 0xae, 0xd6, 0xbd, 0xa3, 0xc5, 0xa3, 0xa3, 0x9f, 0xc3, 0x9c, 0xaa, 0xaa, 0xac, 0xaa, 0xbf, 0x03, 0x7f,
|
||||
0x11, 0x7f, 0x01, 0x7f, 0x01, 0x3f, 0x01, 0x01, 0x90, 0x82, 0x7d, 0x97, 0x59, 0x59, 0x59, 0x59, 0x59, 0x7f, 0x59, 0x59, 0x60, 0x7d,
|
||||
0x7f, 0x7f, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x9a, 0x88, 0x7d, 0x59, 0x50, 0x50, 0x50, 0x50,
|
||||
0x59, 0x59, 0x59, 0x59, 0x61, 0x94, 0x61, 0x9e, 0x59, 0x59, 0x85, 0x59, 0x92, 0xa3, 0x60, 0x60, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x9f, 0x01, 0x03, 0x01, 0x04, 0x03, 0xd5, 0x03, 0xcc, 0x01, 0xbc, 0x03, 0xf0, 0x10, 0x10, 0x10, 0x10,
|
||||
0x50, 0x50, 0x50, 0x50, 0x14, 0x20, 0x20, 0x20, 0x20, 0x01, 0x01, 0x01, 0x01, 0xc4, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
|
||||
0xc0, 0xc2, 0x10, 0x11, 0x02, 0x03, 0x11, 0x03, 0x03, 0x04, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x00, 0xc6, 0xc8, 0x02, 0x02, 0x02,
|
||||
0x02, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xca, 0x01, 0x01, 0x01, 0x00, 0x06, 0x00, 0x04, 0x00, 0xc0, 0xc2,
|
||||
0x01, 0x01, 0x03, 0x01, 0xff, 0xff, 0x01, 0x00, 0x03, 0xc4, 0xc4, 0xc6, 0x03, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xc8, 0x40,
|
||||
0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbf, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x4a, 0x4a, 0x4a, 0x4a,
|
||||
0x4b, 0x52, 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4c, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x55, 0x45, 0x40, 0x4a, 0x4a, 0x4a,
|
||||
0x45, 0x59, 0x4d, 0x46, 0x4a, 0x5d, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x61, 0x63,
|
||||
0x67, 0x4e, 0x4a, 0x4a, 0x6b, 0x6d, 0x4a, 0x4a, 0x45, 0x6d, 0x4a, 0x4a, 0x44, 0x45, 0x4a, 0x4a, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x06,
|
||||
0x06, 0x06, 0x06, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x02, 0x06, 0x00, 0x0a, 0x0a, 0x07, 0x07, 0x06,
|
||||
0x02, 0x05, 0x05, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x06, 0x06, 0x06, 0x01, 0x06, 0x00,
|
||||
0x00, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, 0x80, 0x01, 0x82, 0x01, 0x86, 0x00, 0xf6, 0xcf, 0xfe,
|
||||
0x3f, 0xab, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0xb3, 0x00, 0xba, 0xf8, 0xbb, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc7, 0xbf, 0x62, 0xff, 0x00,
|
||||
0x8d, 0xff, 0x00, 0xc4, 0xff, 0x00, 0xc5, 0xff, 0x00, 0xff, 0xff, 0xeb, 0x01, 0xff, 0x0e, 0x12, 0x08, 0x00, 0x13, 0x09, 0x00, 0x16,
|
||||
0x08, 0x00, 0x17, 0x09, 0x00, 0x2b, 0x09, 0x00, 0xae, 0xff, 0x07, 0xb2, 0xff, 0x00, 0xb4, 0xff, 0x00, 0xb5, 0xff, 0x00, 0xc3, 0x01,
|
||||
0x00, 0xc7, 0xff, 0xbf, 0xe7, 0x08, 0x00, 0xf0, 0x02, 0x00 //
|
||||
};
|
||||
|
||||
unsigned int hde32_disasm(const void *code, hde32s *hs) {
|
||||
uint8_t x, c, *p = (uint8_t *) code, cflags, opcode, pref = 0;
|
||||
uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
|
||||
|
||||
memset(hs, 0, sizeof(hde32s));
|
||||
|
||||
for (x = 16; x; x--)
|
||||
switch (c = *p++) {
|
||||
case 0xf3:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F3;
|
||||
break;
|
||||
case 0xf2:
|
||||
hs->p_rep = c;
|
||||
pref |= PRE_F2;
|
||||
break;
|
||||
case 0xf0:
|
||||
hs->p_lock = c;
|
||||
pref |= PRE_LOCK;
|
||||
break;
|
||||
case 0x26:
|
||||
case 0x2e:
|
||||
case 0x36:
|
||||
case 0x3e:
|
||||
case 0x64:
|
||||
case 0x65:
|
||||
hs->p_seg = c;
|
||||
pref |= PRE_SEG;
|
||||
break;
|
||||
case 0x66:
|
||||
hs->p_66 = c;
|
||||
pref |= PRE_66;
|
||||
break;
|
||||
case 0x67:
|
||||
hs->p_67 = c;
|
||||
pref |= PRE_67;
|
||||
break;
|
||||
default: goto pref_done;
|
||||
}
|
||||
pref_done:
|
||||
|
||||
hs->flags = (uint32_t) pref << 23;
|
||||
|
||||
if (!pref)
|
||||
pref |= PRE_NONE;
|
||||
|
||||
if ((hs->opcode = c) == 0x0f) {
|
||||
hs->opcode2 = c = *p++;
|
||||
ht += DELTA_OPCODES;
|
||||
} else if (c >= 0xa0 && c <= 0xa3) {
|
||||
if (pref & PRE_67)
|
||||
pref |= PRE_66;
|
||||
else
|
||||
pref &= ~PRE_66;
|
||||
}
|
||||
|
||||
opcode = c;
|
||||
cflags = ht[ht[opcode / 4] + (opcode % 4)];
|
||||
|
||||
if (cflags == C_ERROR) {
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
cflags = 0;
|
||||
if ((opcode & -3) == 0x24)
|
||||
cflags++;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
if (cflags & C_GROUP) {
|
||||
uint16_t t;
|
||||
t = *(uint16_t *) (ht + (cflags & 0x7f));
|
||||
cflags = (uint8_t) t;
|
||||
x = (uint8_t) (t >> 8);
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_PREFIXES;
|
||||
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (cflags & C_MODRM) {
|
||||
hs->flags |= F_MODRM;
|
||||
hs->modrm = c = *p++;
|
||||
hs->modrm_mod = m_mod = c >> 6;
|
||||
hs->modrm_rm = m_rm = c & 7;
|
||||
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
|
||||
|
||||
if (x && ((x << m_reg) & 0x80))
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
|
||||
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
|
||||
uint8_t t = opcode - 0xd9;
|
||||
if (m_mod == 3) {
|
||||
ht = hde32_table + DELTA_FPU_MODRM + t * 8;
|
||||
t = ht[m_reg] << m_rm;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_FPU_REG;
|
||||
t = ht[t] << m_reg;
|
||||
}
|
||||
if (t & 0x80)
|
||||
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||
}
|
||||
|
||||
if (pref & PRE_LOCK) {
|
||||
if (m_mod == 3) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
} else {
|
||||
uint8_t *table_end, op = opcode;
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_OP2_LOCK_OK;
|
||||
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_OP_LOCK_OK;
|
||||
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
|
||||
op &= -2;
|
||||
}
|
||||
for (; ht != table_end; ht++)
|
||||
if (*ht++ == op) {
|
||||
if (!((*ht << m_reg) & 0x80))
|
||||
goto no_lock_error;
|
||||
else
|
||||
break;
|
||||
}
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
no_lock_error:;
|
||||
}
|
||||
}
|
||||
|
||||
if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x20:
|
||||
case 0x22:
|
||||
m_mod = 3;
|
||||
if (m_reg > 4 || m_reg == 1)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x21:
|
||||
case 0x23:
|
||||
m_mod = 3;
|
||||
if (m_reg == 4 || m_reg == 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
} else {
|
||||
switch (opcode) {
|
||||
case 0x8c:
|
||||
if (m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
case 0x8e:
|
||||
if (m_reg == 1 || m_reg > 5)
|
||||
goto error_operand;
|
||||
else
|
||||
goto no_error_operand;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mod == 3) {
|
||||
uint8_t *table_end;
|
||||
if (hs->opcode2) {
|
||||
ht = hde32_table + DELTA_OP2_ONLY_MEM;
|
||||
table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
|
||||
} else {
|
||||
ht = hde32_table + DELTA_OP_ONLY_MEM;
|
||||
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
|
||||
}
|
||||
for (; ht != table_end; ht += 2)
|
||||
if (*ht++ == opcode) {
|
||||
if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
|
||||
goto error_operand;
|
||||
else
|
||||
break;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else if (hs->opcode2) {
|
||||
switch (opcode) {
|
||||
case 0x50:
|
||||
case 0xd7:
|
||||
case 0xf7:
|
||||
if (pref & (PRE_NONE | PRE_66))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xd6:
|
||||
if (pref & (PRE_F2 | PRE_F3))
|
||||
goto error_operand;
|
||||
break;
|
||||
case 0xc5: goto error_operand;
|
||||
}
|
||||
goto no_error_operand;
|
||||
} else
|
||||
goto no_error_operand;
|
||||
|
||||
error_operand:
|
||||
hs->flags |= F_ERROR | F_ERROR_OPERAND;
|
||||
no_error_operand:
|
||||
|
||||
c = *p++;
|
||||
if (m_reg <= 1) {
|
||||
if (opcode == 0xf6)
|
||||
cflags |= C_IMM8;
|
||||
else if (opcode == 0xf7)
|
||||
cflags |= C_IMM_P66;
|
||||
}
|
||||
|
||||
switch (m_mod) {
|
||||
case 0:
|
||||
if (pref & PRE_67) {
|
||||
if (m_rm == 6)
|
||||
disp_size = 2;
|
||||
} else if (m_rm == 5)
|
||||
disp_size = 4;
|
||||
break;
|
||||
case 1: disp_size = 1; break;
|
||||
case 2:
|
||||
disp_size = 2;
|
||||
if (!(pref & PRE_67))
|
||||
disp_size <<= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
|
||||
hs->flags |= F_SIB;
|
||||
p++;
|
||||
hs->sib = c;
|
||||
hs->sib_scale = c >> 6;
|
||||
hs->sib_index = (c & 0x3f) >> 3;
|
||||
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
|
||||
disp_size = 4;
|
||||
}
|
||||
|
||||
p--;
|
||||
switch (disp_size) {
|
||||
case 1:
|
||||
hs->flags |= F_DISP8;
|
||||
hs->disp.disp8 = *p;
|
||||
break;
|
||||
case 2:
|
||||
hs->flags |= F_DISP16;
|
||||
hs->disp.disp16 = *(uint16_t *) p;
|
||||
break;
|
||||
case 4:
|
||||
hs->flags |= F_DISP32;
|
||||
hs->disp.disp32 = *(uint32_t *) p;
|
||||
break;
|
||||
}
|
||||
p += disp_size;
|
||||
} else if (pref & PRE_LOCK)
|
||||
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||
|
||||
if (cflags & C_IMM_P66) {
|
||||
if (cflags & C_REL32) {
|
||||
if (pref & PRE_66) {
|
||||
hs->flags |= F_IMM16 | F_RELATIVE;
|
||||
hs->imm.imm16 = *(uint16_t *) p;
|
||||
p += 2;
|
||||
goto disasm_done;
|
||||
}
|
||||
goto rel32_ok;
|
||||
}
|
||||
if (pref & PRE_66) {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->imm.imm16 = *(uint16_t *) p;
|
||||
p += 2;
|
||||
} else {
|
||||
hs->flags |= F_IMM32;
|
||||
hs->imm.imm32 = *(uint32_t *) p;
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (cflags & C_IMM16) {
|
||||
if (hs->flags & F_IMM32) {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->disp.disp16 = *(uint16_t *) p;
|
||||
} else if (hs->flags & F_IMM16) {
|
||||
hs->flags |= F_2IMM16;
|
||||
hs->disp.disp16 = *(uint16_t *) p;
|
||||
} else {
|
||||
hs->flags |= F_IMM16;
|
||||
hs->imm.imm16 = *(uint16_t *) p;
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
if (cflags & C_IMM8) {
|
||||
hs->flags |= F_IMM8;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
if (cflags & C_REL32) {
|
||||
rel32_ok:
|
||||
hs->flags |= F_IMM32 | F_RELATIVE;
|
||||
hs->imm.imm32 = *(uint32_t *) p;
|
||||
p += 4;
|
||||
} else if (cflags & C_REL8) {
|
||||
hs->flags |= F_IMM8 | F_RELATIVE;
|
||||
hs->imm.imm8 = *p++;
|
||||
}
|
||||
|
||||
disasm_done:
|
||||
|
||||
if ((hs->len = (uint8_t) (p - (uint8_t *) code)) > 15) {
|
||||
hs->flags |= F_ERROR | F_ERROR_LENGTH;
|
||||
hs->len = 15;
|
||||
}
|
||||
|
||||
return (unsigned int) hs->len;
|
||||
}
|
Loading…
Reference in New Issue
Block a user