1
0
mirror of synced 2024-11-11 22:07:09 +01:00

Initial Commit

This commit is contained in:
Reaver 2018-09-09 01:13:03 +03:00
parent a3145bd1f8
commit 329e263b1c
82 changed files with 25023 additions and 0 deletions

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
*.sln
*.vcxproj
*.vcxproj.filters
.vs/
build/
Debug/
ParrotLoader/Release/
Release/
TeknoParrot\.sdf
TeknoParrot\.v12\.suo
TeknoParrot/TeknoParrot\.vcxproj\.user
ParrotLoader/ParrotLoader\.vcxproj\.user
*.user

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,364 @@
/*==========================================================================;
*
* Copyright (C) Microsoft Corporation. All Rights Reserved.
*
* File: d3d8caps.h
* Content: Direct3D capabilities include file
*
***************************************************************************/
#ifndef _D3D8CAPS_H
#define _D3D8CAPS_H
#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION 0x0800
#endif //DIRECT3D_VERSION
// include this file content only if compiling for DX8 interfaces
#if(DIRECT3D_VERSION >= 0x0800)
#if defined(_X86_) || defined(_IA64_)
#pragma pack(4)
#endif
typedef struct _D3DCAPS8
{
/* Device Info */
D3DDEVTYPE DeviceType;
UINT AdapterOrdinal;
/* Caps from DX7 Draw */
DWORD Caps;
DWORD Caps2;
DWORD Caps3;
DWORD PresentationIntervals;
/* Cursor Caps */
DWORD CursorCaps;
/* 3D Device Caps */
DWORD DevCaps;
DWORD PrimitiveMiscCaps;
DWORD RasterCaps;
DWORD ZCmpCaps;
DWORD SrcBlendCaps;
DWORD DestBlendCaps;
DWORD AlphaCmpCaps;
DWORD ShadeCaps;
DWORD TextureCaps;
DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture8's
DWORD CubeTextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DCubeTexture8's
DWORD VolumeTextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DVolumeTexture8's
DWORD TextureAddressCaps; // D3DPTADDRESSCAPS for IDirect3DTexture8's
DWORD VolumeTextureAddressCaps; // D3DPTADDRESSCAPS for IDirect3DVolumeTexture8's
DWORD LineCaps; // D3DLINECAPS
DWORD MaxTextureWidth, MaxTextureHeight;
DWORD MaxVolumeExtent;
DWORD MaxTextureRepeat;
DWORD MaxTextureAspectRatio;
DWORD MaxAnisotropy;
float MaxVertexW;
float GuardBandLeft;
float GuardBandTop;
float GuardBandRight;
float GuardBandBottom;
float ExtentsAdjust;
DWORD StencilCaps;
DWORD FVFCaps;
DWORD TextureOpCaps;
DWORD MaxTextureBlendStages;
DWORD MaxSimultaneousTextures;
DWORD VertexProcessingCaps;
DWORD MaxActiveLights;
DWORD MaxUserClipPlanes;
DWORD MaxVertexBlendMatrices;
DWORD MaxVertexBlendMatrixIndex;
float MaxPointSize;
DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call
DWORD MaxVertexIndex;
DWORD MaxStreams;
DWORD MaxStreamStride; // max stride for SetStreamSource
DWORD VertexShaderVersion;
DWORD MaxVertexShaderConst; // number of vertex shader constant registers
DWORD PixelShaderVersion;
float MaxPixelShaderValue; // max value of pixel shader arithmetic component
} D3DCAPS8;
//
// BIT DEFINES FOR D3DCAPS8 DWORD MEMBERS
//
//
// Caps
//
#define D3DCAPS_READ_SCANLINE 0x00020000L
//
// Caps2
//
#define D3DCAPS2_NO2DDURING3DSCENE 0x00000002L
#define D3DCAPS2_FULLSCREENGAMMA 0x00020000L
#define D3DCAPS2_CANRENDERWINDOWED 0x00080000L
#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L
#define D3DCAPS2_RESERVED 0x02000000L
#define D3DCAPS2_CANMANAGERESOURCE 0x10000000L
#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L
//
// Caps3
//
#define D3DCAPS3_RESERVED 0x8000001fL
// Indicates that the device can respect the ALPHABLENDENABLE render state
// when fullscreen while using the FLIP or DISCARD swap effect.
// COPY and COPYVSYNC swap effects work whether or not this flag is set.
#define D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD 0x00000020L
//
// PresentationIntervals
//
#define D3DPRESENT_INTERVAL_DEFAULT 0x00000000L
#define D3DPRESENT_INTERVAL_ONE 0x00000001L
#define D3DPRESENT_INTERVAL_TWO 0x00000002L
#define D3DPRESENT_INTERVAL_THREE 0x00000004L
#define D3DPRESENT_INTERVAL_FOUR 0x00000008L
#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L
//
// CursorCaps
//
// Driver supports HW color cursor in at least hi-res modes(height >=400)
#define D3DCURSORCAPS_COLOR 0x00000001L
// Driver supports HW cursor also in low-res modes(height < 400)
#define D3DCURSORCAPS_LOWRES 0x00000002L
//
// DevCaps
//
#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */
#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */
#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */
#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */
#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */
#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */
#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */
#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */
#define D3DDEVCAPS_DRAWPRIMITIVES2 0x00002000L /* Device can support DrawPrimitives2 */
#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */
#define D3DDEVCAPS_DRAWPRIMITIVES2EX 0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/
#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */
#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */
#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */
#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */
#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */
#define D3DDEVCAPS_RTPATCHES 0x00400000L /* Device supports Rect and Tri patches */
#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */
#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */
//
// PrimitiveMiscCaps
//
#define D3DPMISCCAPS_MASKZ 0x00000002L
#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L
#define D3DPMISCCAPS_CULLNONE 0x00000010L
#define D3DPMISCCAPS_CULLCW 0x00000020L
#define D3DPMISCCAPS_CULLCCW 0x00000040L
#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L
#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */
#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */
#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */
#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */
#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */
//
// LineCaps
//
#define D3DLINECAPS_TEXTURE 0x00000001L
#define D3DLINECAPS_ZTEST 0x00000002L
#define D3DLINECAPS_BLEND 0x00000004L
#define D3DLINECAPS_ALPHACMP 0x00000008L
#define D3DLINECAPS_FOG 0x00000010L
//
// RasterCaps
//
#define D3DPRASTERCAPS_DITHER 0x00000001L
#define D3DPRASTERCAPS_PAT 0x00000008L
#define D3DPRASTERCAPS_ZTEST 0x00000010L
#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L
#define D3DPRASTERCAPS_FOGTABLE 0x00000100L
#define D3DPRASTERCAPS_ANTIALIASEDGES 0x00001000L
#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L
#define D3DPRASTERCAPS_ZBIAS 0x00004000L
#define D3DPRASTERCAPS_ZBUFFERLESSHSR 0x00008000L
#define D3DPRASTERCAPS_FOGRANGE 0x00010000L
#define D3DPRASTERCAPS_ANISOTROPY 0x00020000L
#define D3DPRASTERCAPS_WBUFFER 0x00040000L
#define D3DPRASTERCAPS_WFOG 0x00100000L
#define D3DPRASTERCAPS_ZFOG 0x00200000L
#define D3DPRASTERCAPS_COLORPERSPECTIVE 0x00400000L /* Device iterates colors perspective correct */
#define D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE 0x00800000L
//
// ZCmpCaps, AlphaCmpCaps
//
#define D3DPCMPCAPS_NEVER 0x00000001L
#define D3DPCMPCAPS_LESS 0x00000002L
#define D3DPCMPCAPS_EQUAL 0x00000004L
#define D3DPCMPCAPS_LESSEQUAL 0x00000008L
#define D3DPCMPCAPS_GREATER 0x00000010L
#define D3DPCMPCAPS_NOTEQUAL 0x00000020L
#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L
#define D3DPCMPCAPS_ALWAYS 0x00000080L
//
// SourceBlendCaps, DestBlendCaps
//
#define D3DPBLENDCAPS_ZERO 0x00000001L
#define D3DPBLENDCAPS_ONE 0x00000002L
#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L
#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L
#define D3DPBLENDCAPS_SRCALPHA 0x00000010L
#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L
#define D3DPBLENDCAPS_DESTALPHA 0x00000040L
#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L
#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L
#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L
#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L
#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L
#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L
//
// ShadeCaps
//
#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L
#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L
#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L
#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L
//
// TextureCaps
//
#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L /* Perspective-correct texturing is supported */
#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */
#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */
#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */
#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L /* Texture indices are not scaled by the texture size prior to interpolation */
#define D3DPTEXTURECAPS_ALPHAPALETTE 0x00000080L /* Device can draw alpha from texture palettes */
// Device can use non-POW2 textures if:
// 1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage
// 2) D3DRS_WRAP(N) is zero for this texture's coordinates
// 3) mip mapping is not enabled (use magnification filter only)
#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L
#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */
#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */
#define D3DPTEXTURECAPS_VOLUMEMAP 0x00002000L /* Device can do volume textures */
#define D3DPTEXTURECAPS_MIPMAP 0x00004000L /* Device can do mipmapped textures */
#define D3DPTEXTURECAPS_MIPVOLUMEMAP 0x00008000L /* Device can do mipmapped volume textures */
#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */
#define D3DPTEXTURECAPS_CUBEMAP_POW2 0x00020000L /* Device requires that cubemaps be power-of-2 dimension */
#define D3DPTEXTURECAPS_VOLUMEMAP_POW2 0x00040000L /* Device requires that volume maps be power-of-2 dimension */
//
// TextureFilterCaps
//
#define D3DPTFILTERCAPS_MINFPOINT 0x00000100L /* Min Filter */
#define D3DPTFILTERCAPS_MINFLINEAR 0x00000200L
#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L
#define D3DPTFILTERCAPS_MIPFPOINT 0x00010000L /* Mip Filter */
#define D3DPTFILTERCAPS_MIPFLINEAR 0x00020000L
#define D3DPTFILTERCAPS_MAGFPOINT 0x01000000L /* Mag Filter */
#define D3DPTFILTERCAPS_MAGFLINEAR 0x02000000L
#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L
#define D3DPTFILTERCAPS_MAGFAFLATCUBIC 0x08000000L
#define D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC 0x10000000L
//
// TextureAddressCaps
//
#define D3DPTADDRESSCAPS_WRAP 0x00000001L
#define D3DPTADDRESSCAPS_MIRROR 0x00000002L
#define D3DPTADDRESSCAPS_CLAMP 0x00000004L
#define D3DPTADDRESSCAPS_BORDER 0x00000008L
#define D3DPTADDRESSCAPS_INDEPENDENTUV 0x00000010L
#define D3DPTADDRESSCAPS_MIRRORONCE 0x00000020L
//
// StencilCaps
//
#define D3DSTENCILCAPS_KEEP 0x00000001L
#define D3DSTENCILCAPS_ZERO 0x00000002L
#define D3DSTENCILCAPS_REPLACE 0x00000004L
#define D3DSTENCILCAPS_INCRSAT 0x00000008L
#define D3DSTENCILCAPS_DECRSAT 0x00000010L
#define D3DSTENCILCAPS_INVERT 0x00000020L
#define D3DSTENCILCAPS_INCR 0x00000040L
#define D3DSTENCILCAPS_DECR 0x00000080L
//
// TextureOpCaps
//
#define D3DTEXOPCAPS_DISABLE 0x00000001L
#define D3DTEXOPCAPS_SELECTARG1 0x00000002L
#define D3DTEXOPCAPS_SELECTARG2 0x00000004L
#define D3DTEXOPCAPS_MODULATE 0x00000008L
#define D3DTEXOPCAPS_MODULATE2X 0x00000010L
#define D3DTEXOPCAPS_MODULATE4X 0x00000020L
#define D3DTEXOPCAPS_ADD 0x00000040L
#define D3DTEXOPCAPS_ADDSIGNED 0x00000080L
#define D3DTEXOPCAPS_ADDSIGNED2X 0x00000100L
#define D3DTEXOPCAPS_SUBTRACT 0x00000200L
#define D3DTEXOPCAPS_ADDSMOOTH 0x00000400L
#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA 0x00000800L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHA 0x00001000L
#define D3DTEXOPCAPS_BLENDFACTORALPHA 0x00002000L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 0x00004000L
#define D3DTEXOPCAPS_BLENDCURRENTALPHA 0x00008000L
#define D3DTEXOPCAPS_PREMODULATE 0x00010000L
#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 0x00020000L
#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 0x00040000L
#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 0x00080000L
#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 0x00100000L
#define D3DTEXOPCAPS_BUMPENVMAP 0x00200000L
#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 0x00400000L
#define D3DTEXOPCAPS_DOTPRODUCT3 0x00800000L
#define D3DTEXOPCAPS_MULTIPLYADD 0x01000000L
#define D3DTEXOPCAPS_LERP 0x02000000L
//
// FVFCaps
//
#define D3DFVFCAPS_TEXCOORDCOUNTMASK 0x0000ffffL /* mask for texture coordinate count field */
#define D3DFVFCAPS_DONOTSTRIPELEMENTS 0x00080000L /* Device prefers that vertex elements not be stripped */
#define D3DFVFCAPS_PSIZE 0x00100000L /* Device can receive point size */
//
// VertexProcessingCaps
//
#define D3DVTXPCAPS_TEXGEN 0x00000001L /* device can do texgen */
#define D3DVTXPCAPS_MATERIALSOURCE7 0x00000002L /* device can do DX7-level colormaterialsource ops */
#define D3DVTXPCAPS_DIRECTIONALLIGHTS 0x00000008L /* device can do directional lights */
#define D3DVTXPCAPS_POSITIONALLIGHTS 0x00000010L /* device can do positional lights (includes point and spot) */
#define D3DVTXPCAPS_LOCALVIEWER 0x00000020L /* device can do local viewer */
#define D3DVTXPCAPS_TWEENING 0x00000040L /* device can do vertex tweening */
#define D3DVTXPCAPS_NO_VSDT_UBYTE4 0x00000080L /* device does not support D3DVSDT_UBYTE4 */
#pragma pack()
#endif /* (DIRECT3D_VERSION >= 0x0800) */
#endif /* _D3D8CAPS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
/*
* Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#ifndef LINB_INI_PARSER_HPP
#define LINB_INI_PARSER_HPP
/*
* STL-like INI Container
*/
#include <string> // for std::string
#include <map> // for std::map
#include <cstdio> // for std::FILE
#include <algorithm> // for std::find_if
#include <functional> // for std::function
namespace linb
{
template<
class CharT = char, /* Not compatible with other type here, since we're using C streams */
class StringType = std::basic_string<CharT>,
class KeyContainer = std::map<StringType, StringType>,
class SectionContainer = std::map<StringType, KeyContainer>
> class basic_ini
{
public:
typedef CharT char_type;
typedef StringType string_type;
typedef KeyContainer key_container;
typedef SectionContainer section_container;
// Typedef container values types
typedef typename section_container::value_type value_type;
typedef typename section_container::key_type key_type;
typedef typename section_container::mapped_type mapped_type;
// Typedef common types
typedef typename section_container::size_type size_type;
typedef typename section_container::difference_type difference_type;
// Typedef iterators
typedef typename section_container::iterator iterator;
typedef typename section_container::const_iterator const_iterator;
typedef typename section_container::reverse_iterator reverse_iterator;
typedef typename section_container::const_reverse_iterator const_reverse_iterator;
// typedef References and pointers
typedef typename section_container::reference reference;
typedef typename section_container::const_reference const_reference;
typedef typename section_container::pointer pointer;
typedef typename section_container::const_pointer const_pointer;
private:
section_container data;
public:
basic_ini()
{ }
basic_ini(const char_type* filename)
{ this->read_file(filename); }
/* Iterator methods */
iterator begin()
{ return data.begin(); }
const_iterator begin() const
{ return data.begin(); }
iterator end()
{ return data.end(); }
const_iterator end() const
{ return data.end(); }
const_iterator cbegin() const
{ return data.cbegin(); }
const_iterator cend() const
{ return data.cend(); }
/* Reverse iterator methods */
reverse_iterator rbegin()
{ return data.rbegin(); }
const_reverse_iterator rbegin() const
{ return data.rbegin(); }
reverse_iterator rend()
{ return data.rend(); }
const_reverse_iterator rend() const
{ return data.rend(); }
const_reverse_iterator crbegin() const
{ return data.crbegin(); }
const_reverse_iterator crend() const
{ return data.crend(); }
/* Acessing index methods */
mapped_type& operator[](const string_type& sect)
{ return data[sect]; }
mapped_type& operator[](string_type&& sect)
{ return data[std::forward<string_type>(sect)]; }
mapped_type& at( const string_type& sect)
{ return data.at(sect); }
const mapped_type& at(const string_type& sect) const
{ return data.at(sect); }
/* Capacity information */
bool empty() const
{ return data.empty(); }
size_type size() const
{ return data.size(); }
size_type max_size() const
{ return data.max_size(); }
/* Modifiers */
void clear()
{ return data.clear(); }
/* Lookup */
size_type count(const string_type& sect)
{ return data.count(sect); }
iterator find(const string_type& sect)
{ return data.find(sect); }
/* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */
string_type get(const string_type& sect, const key_type& key, const string_type& default_value)
{
auto it = this->find(sect);
if(it != this->end())
{
auto itv = it->second.find(key);
if(itv != it->second.end())
return itv->second;
}
return default_value;
}
/* Sets the value of a value in the ini */
void set(const string_type& sect, const key_type& key, const string_type& value)
{
(*this)[sect][key] = value; // no emplace since overwrite!
}
/* Too lazy to continue this container... If you need more methods, just add it */
#if 1
bool read_file(const char_type* filename)
{
/* Using C stream in a STL-like container, funny?
*/
if(FILE* f = fopen(filename, "r"))
{
key_container* keys = nullptr;
char_type buf[2048];
string_type line;
string_type key;
string_type value;
string_type null_string;
size_type pos;
// Trims an string
auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type&
{
if(s.size())
{
// Ignore UTF-8 BOM
while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF))
s.erase(s.begin(), s.begin() + 3);
if(trimLeft)
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace))));
if(trimRight)
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end());
}
return s;
};
// Start parsing
while(fgets(buf, sizeof(buf), f))
{
// What a thing, reading into a char buffer and then putting in the string...
line = buf;
// Find comment and remove anything after it from the line
if((pos = line.find_first_of(';')) != line.npos)
line.erase(pos);
// Trim the string, and if it gets empty, skip this line
if(trim(line, true, true).empty())
continue;
// Find section name
if(line.front() == '[' && line.back() == ']')
{
pos = line.length() - 1; //line.find_first_of(']');
if(pos != line.npos)
{
trim(key.assign(line, 1, pos-1), true, true);
keys = &data[std::move(key)]; // Create section
}
else
keys = nullptr;
}
else
{
// Find key and value positions
pos = line.find_first_of('=');
if(pos == line.npos)
{
// There's only the key
key = line; // No need for trim, line is already trimmed
value.clear();
}
else
{
// There's the key and the value
trim(key.assign(line, 0, pos), false, true); // trim the right
trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left
}
// Put the key/value into the current keys object, or into the section "" if no section has been found
#if __cplusplus >= 201103L || _MSC_VER >= 1800
(keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value));
#else
(keys ? *keys : data[null_string])[key] = value;
key.clear(); value.clear();
#endif
}
}
fclose(f);
return true;
}
return false;
}
/*
* Dumps the content of this container into an ini file
*/
bool write_file(const char_type* filename)
{
if(FILE* f = fopen(filename, "w"))
{
bool first = true;
for(auto& sec : this->data)
{
fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str());
first = false;
for(auto& kv : sec.second)
{
if(kv.second.empty())
fprintf(f, "%s\n", kv.first.c_str());
else
fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str());
}
}
fclose(f);
return true;
}
return false;
}
/*
*/
bool load_file(const char_type* filename)
{
return read_file(filename);
}
bool load_file(const StringType& filename)
{
return load_file(filename.c_str());
}
bool write_file(const StringType& filename)
{
return write_file(filename.c_str());
}
#endif
};
/* Use default basic_ini
*
* Limitations:
* * Not unicode aware
* * Case sensitive
* * Sections must have unique keys
*/
typedef basic_ini<> ini;
}
#endif

View File

@ -0,0 +1,178 @@
/*
* Injectors - Useful Assembly Stuff
*
* Copyright (C) 2012-2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
// This header is very restrict about compiler and architecture
#ifndef _MSC_VER // MSVC is much more flexible when we're talking about inline assembly
#error Cannot use this header in another compiler other than MSVC
#endif
#ifndef _M_IX86
#error Supported only in x86
#endif
//
#include "injector.hpp"
namespace injector
{
struct reg_pack
{
// The ordering is very important, don't change
// The first field is the last to be pushed and first to be poped
// PUSHFD / POPFD
uint32_t ef;
// PUSHAD/POPAD -- must be the lastest fields (because of esp)
union
{
uint32_t arr[8];
struct { uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; };
};
enum reg_name {
reg_edi, reg_esi, reg_ebp, reg_esp, reg_ebx, reg_edx, reg_ecx, reg_eax
};
enum ef_flag {
carry_flag = 0, parity_flag = 2, adjust_flag = 4, zero_flag = 6, sign_flag = 7,
direction_flag = 10, overflow_flag = 11
};
uint32_t& operator[](size_t i)
{ return this->arr[i]; }
const uint32_t& operator[](size_t i) const
{ return this->arr[i]; }
template<uint32_t bit> // bit starts from 0, use ef_flag enum
bool flag()
{
return (this->ef & (1 << bit)) != 0;
}
bool jnb()
{
return flag<carry_flag>() == false;
}
};
// Lowest level stuff (actual assembly) goes on the following namespace
// PRIVATE! Skip this, not interesting for you.
namespace injector_asm
{
// Wrapper functor, so the assembly can use some templating
template<class T>
struct wrapper
{
static void call(reg_pack* regs)
{
T fun; fun(*regs);
}
};
// Constructs a reg_pack and calls the wrapper functor
template<class W> // where W is of type wrapper
inline void __declspec(naked) make_reg_pack_and_call()
{
_asm
{
// Construct the reg_pack structure on the stack
pushad // Pushes general purposes registers to reg_pack
add [esp+12], 4 // Add 4 to reg_pack::esp 'cuz of our return pointer, let it be as before this func is called
pushfd // Pushes EFLAGS to reg_pack
// Call wrapper sending reg_pack as parameter
push esp
call W::call
add esp, 4
// Destructs the reg_pack from the stack
sub [esp+12+4], 4 // Fix reg_pack::esp before popping it (doesn't make a difference though) (+4 because eflags)
popfd // Warning: Do not use any instruction that changes EFLAGS after this (-> sub affects EF!! <-)
popad
// Back to normal flow
ret
}
}
};
/*
* MakeInline
* Makes inline assembly (but not assembly, an actual functor of type FuncT) at address
*/
template<class FuncT>
void MakeInline(memory_pointer_tr at)
{
typedef injector_asm::wrapper<FuncT> functor;
if(false) functor::call(nullptr); // To instantiate the template, if not done _asm will fail
MakeCALL(at, injector_asm::make_reg_pack_and_call<functor>);
}
/*
* MakeInline
* Same as above, but it NOPs everything between at and end (exclusive), then performs MakeInline
*/
template<class FuncT>
void MakeInline(memory_pointer_tr at, memory_pointer_tr end)
{
MakeRangedNOP(at, end);
MakeInline<FuncT>(at);
}
/*
* MakeInline
* Same as above, but (at,end) are template parameters.
* On this case the functor can be passed as argument since there will be one func instance for each at,end not just for each FuncT
*/
template<uintptr_t at, uintptr_t end, class FuncT>
void MakeInline(FuncT func)
{
static FuncT static_func = func; // Stores the func object
static_func = func; //
// Encapsulates the call to static_func
struct Caps
{
void operator()(reg_pack& regs)
{ static_func(regs); }
};
// Does the actual MakeInline
return MakeInline<Caps>(lazy_pointer<at>::get(), lazy_pointer<end>::get());
}
/*
* MakeInline
* Same as above, but (end) is calculated by the length of a call instruction
*/
template<uintptr_t at, class FuncT>
void MakeInline(FuncT func)
{
return MakeInline<at, at+5, FuncT>(func);
}
};

View File

@ -0,0 +1,127 @@
/*
* Injectors - Function Calls Using Variadic Templates
*
* Copyright (C) 2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
#include "injector.hpp"
#include <utility>
#include <tuple>
#if __cplusplus >= 201103L || _MSC_VER >= 1800 // MSVC 2013
#else
#error "This feature is not supported on this compiler"
#endif
namespace injector
{
template<class Prototype>
struct cstd;
template<class Ret, class ...Args>
struct cstd<Ret(Args...)>
{
// Call function at @p returning @Ret with args @Args
static Ret call(memory_pointer_tr p, Args... a)
{
auto fn = (Ret(*)(Args...)) p.get<void>();
return fn(std::forward<Args>(a)...);
}
template<uintptr_t addr> // Uses lazy pointer
static Ret call(Args... a)
{
return call(lazy_pointer<addr>::get(), std::forward<Args>(a)...);
}
};
template<class Prototype>
struct stdcall;
template<class Ret, class ...Args>
struct stdcall<Ret(Args...)>
{
// Call function at @p returning @Ret with args @Args
static Ret call(memory_pointer_tr p, Args... a)
{
auto fn = (Ret(__stdcall *)(Args...)) p.get<void>();
return fn(std::forward<Args>(a)...);
}
template<uintptr_t addr> // Uses lazy pointer
static Ret call(Args... a)
{
return call(lazy_pointer<addr>::get(), std::forward<Args>(a)...);
}
};
template<class Prototype>
struct fastcall;
template<class Ret, class ...Args>
struct fastcall<Ret(Args...)>
{
// Call function at @p returning @Ret with args @Args
static Ret call(memory_pointer_tr p, Args... a)
{
auto fn = (Ret(__fastcall *)(Args...)) p.get<void>();;
return fn(std::forward<Args>(a)...);
}
template<uintptr_t addr> // Uses lazy pointer
static Ret call(Args... a)
{
return call(lazy_pointer<addr>::get(), std::forward<Args>(a)...);
}
};
template<class Prototype>
struct thiscall;
template<class Ret, class ...Args>
struct thiscall<Ret(Args...)>
{
// Call function at @p returning @Ret with args @Args
static Ret call(memory_pointer_tr p, Args... a)
{
auto fn = (Ret(__thiscall *)(Args...)) p.get<void>();
return fn(std::forward<Args>(a)...);
}
// Call function at the index @i from the vtable of the object @a[0]
template<size_t i>
static Ret vtbl(Args... a)
{
auto obj = raw_ptr(std::get<0>(std::forward_as_tuple(a...)));
auto p = raw_ptr( (*obj.template get<void**>()) [i] );
return call(p, std::forward<Args>(a)...);
}
template<uintptr_t addr> // Uses lazy pointer
static Ret call(Args... a)
{
return call(lazy_pointer<addr>::get(), std::forward<Args>(a)...);
}
};
}

View File

@ -0,0 +1,229 @@
/*
* Injectors - Base Header
*
* Copyright (C) 2012-2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
#include <windows.h>
#include <cstdint>
#include <cstdio>
namespace injector
{
#if 1 // GVM and Address Translator, Not very interesting for the users, so skip reading those...
/*
* game_version_manager
* Detects the game, the game version and the game region
* This assumes the executable is decrypted, so, Silent's ASI Loader is recommended.
*/
#ifndef INJECTOR_OWN_GVM
#ifndef INJECTOR_GVM_DUMMY
class game_version_manager
{
public:
// Set this if you would like that MessagesBox contain PluginName as caption
const char* PluginName;
private:
char game, region, major, minor, majorRevision, minorRevision, cracker, steam;
public:
game_version_manager()
{
#ifdef INJECTOR_GVM_PLUGIN_NAME
PluginName = INJECTOR_GVM_PLUGIN_NAME;
#else
PluginName = "Unknown Plugin Name";
#endif
this->Clear();
}
// Clear any information about game version
void Clear()
{
game = region = major = minor = majorRevision = minorRevision = cracker = steam = 0;
}
// Checks if I don't know the game we are attached to
bool IsUnknown() { return game == 0; }
// Checks if this is the steam version
bool IsSteam() { return steam != 0; }
// Gets the game we are attached to (0, '3', 'V', 'S', 'I', 'E')
char GetGame() { return game; }
// Gets the region from the game we are attached to (0, 'U', 'E');
char GetRegion() { return region; }
// Get major and minor version of the game (e.g. [major = 1, minor = 0] = 1.0)
int GetMajorVersion() { return major; }
int GetMinorVersion() { return minor; }
int GetMajorRevisionVersion() { return majorRevision; }
int GetMinorRevisionVersion() { return minorRevision; }
bool IsHoodlum() { return cracker == 'H'; }
// Region conditions
bool IsUS() { return region == 'U'; }
bool IsEU() { return region == 'E'; }
// Game Conditions
bool IsIII() { return game == '3'; }
bool IsVC () { return game == 'V'; }
bool IsSA () { return game == 'S'; }
bool IsIV () { return game == 'I'; }
bool IsEFLC(){ return game == 'E'; }
// Detects game, region and version; returns false if could not detect it
bool Detect();
// Gets the game version as text, the buffer must contain at least 32 bytes of space.
char* GetVersionText(char* buffer)
{
if(this->IsUnknown())
{
strcpy(buffer, "UNKNOWN GAME");
return buffer;
}
const char* g = this->IsIII() ? "III" : this->IsVC() ? "VC" : this->IsSA() ? "SA" : this->IsIV() ? "IV" : this->IsEFLC() ? "EFLC" : "UNK";
const char* r = this->IsUS()? "US" : this->IsEU()? "EURO" : "UNK_REGION";
const char* s = this->IsSteam()? "Steam" : "";
sprintf(buffer, "GTA %s %d.%d.%d.%d %s%s", g, major, minor, majorRevision, minorRevision, r, s);
return buffer;
}
public:
// Raises a error saying that you could not detect the game version
void RaiseCouldNotDetect()
{
MessageBoxA(0,
"Could not detect the game version\nContact the mod creator!",
PluginName, MB_ICONERROR
);
}
// Raises a error saying that the exe version is incompatible (and output the exe name)
void RaiseIncompatibleVersion()
{
char buf[128], v[32];
sprintf(buf,
"An incompatible exe version has been detected! (%s)\nContact the mod creator!",
GetVersionText(v)
);
MessageBoxA(0, buf, PluginName, MB_ICONERROR);
}
};
#else // INJECTOR_GVM_DUMMY
class game_version_manager
{
public:
bool Detect() { return true; }
};
#endif // INJECTOR_GVM_DUMMY
#endif // INJECTOR_OWN_GVM
/*
* address_manager
* Address translator from 1.0 executables to other executables offsets
* Inherits from game_version_manager ;)
*/
class address_manager : public game_version_manager
{
private:
address_manager()
{
this->Detect();
}
// You could implement your translator for the address your plugin uses
// If not implemented, the translator won't translate anything, just return the samething as before
#ifdef INJECTOR_GVM_HAS_TRANSLATOR
void* translator(void* p);
#else
void* translator(void* p) { return p; }
#endif
public:
// Translates address p to the running executable pointer
void* translate(void* p)
{
return translator(p);
}
public:
// Address manager singleton
static address_manager& singleton()
{
static address_manager m;
return m;
}
// Static version of translate()
static void* translate_address(void* p)
{
return singleton().translate(p);
}
//
static void set_name(const char* modname)
{
singleton().PluginName = modname;
}
public:
// Functors for memory translation:
// Translates aslr translator
struct fn_mem_translator_aslr
{
void* operator()(void* p) const
{
static uintptr_t module = (uintptr_t)GetModuleHandle(NULL);
return (void*)((uintptr_t)(p)-(0x400000 - module));
}
};
// Translates nothing translator
struct fn_mem_translator_nop
{
void* operator()(void* p) const
{ return p; }
};
// Real translator
struct fn_mem_translator
{
void* operator()(void* p) const
{ return translate_address(p); }
};
};
#endif // #if 1
}

View File

@ -0,0 +1,203 @@
/*
* Injectors - Address Translation Management
*
* Copyright (C) 2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
#if !defined(INJECTOR_GVM_HAS_TRANSLATOR)
#error Missing INJECTOR_GVM_HAS_TRANSLATOR on compiler definitions
#endif
/*
* This is a quick solution for address translations if you're too lazy to implement a proper address_manager::translator by yourself
* So, just call address_translator_manager::singleton().translate(p) from your address_manager::translator and that's it.
* It'll translate addresses based on 'address_translator' objects, when one gets constructed it turns into a possible translator.
* At the constructor of your derived 'address_translator' make the map object to have [addr_to_translate] = translated_addr;
* There's also the virtual method 'fallback' that will get called when the translation wasn't possible, you can do some fallback stuff here
* (such as return the pointer as is or output a error message)
*/
#include "../injector.hpp"
#include <list>
#include <map>
#include <algorithm>
namespace injector
{
/*
* address_translator
* Base for an address translator
*/
class address_translator
{
private:
bool enabled;
void add();
void remove();
protected:
friend class address_translator_manager;
std::map<memory_pointer_raw, memory_pointer_raw> map;
public:
address_translator() : enabled(true)
{
// Must have bounds filled with min ptr and max ptr to have search working properly
map.insert(std::make_pair(raw_ptr(0x00000000u), raw_ptr(0x00000000u)));
map.insert(std::make_pair(raw_ptr(0xffffffffu), raw_ptr(0xffffffffu)));
add();
}
~address_translator()
{
remove();
}
virtual void* fallback(void*) const
{
return nullptr;
}
// Enables or disables this translator
void enable(bool enable_it)
{
if(enable_it) this->enable();
else this->disable();
}
// Enables this translator
void enable()
{
this->enabled = true;
}
// Disables this translator
void disable()
{
this->enabled = false;
}
// Checks if this translator is enabled
bool is_enabled() const
{
return enabled;
}
};
/*
* address_translator_manager
* Manages the address_translator objects
*/
class address_translator_manager
{
protected:
friend class address_manager;
friend class address_translator;
std::list<const address_translator*> translators;
void add(const address_translator& t)
{
translators.push_front(&t);
}
void remove(const address_translator& t)
{
translators.remove(&t);
}
public:
// Translates the address p
void* translator(void* p);
// Singleton object
static address_translator_manager& singleton()
{
static address_translator_manager mgr;
return mgr;
}
};
inline void* address_translator_manager::translator(void* p_)
{
static const size_t max_ptr_dist = 7;
// Tries to find an address in a translator map
auto try_map = [](const std::map<memory_pointer_raw, memory_pointer_raw>& map, memory_pointer_raw p) -> memory_pointer_raw
{
memory_pointer_raw result = nullptr;
// Find first element in the map that is greater than or equal to p
auto it = map.lower_bound(p);
if(it != map.end())
{
// If it's not exactly the address, get back one position on the table
if(it->first != p) --it;
auto diff = (p - it->first).as_int(); // What's the difference between p and that address?
if(diff <= max_ptr_dist) // Could we live with this difference in hands?
result = it->second + raw_ptr(diff); // Yes, we can!
}
return result;
};
//
memory_pointer_raw result = nullptr;
// Try to find translation for this pointer
auto& mgr = address_translator_manager::singleton().translators;
for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it)
{
auto& t = **it;
if(t.is_enabled()) result = try_map(t.map, p_);
}
// If we couldn't translate the address, notify and try to fallback
if(result.is_null())
{
for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it)
{
auto& t = **it;
if(t.is_enabled()) result = t.fallback(p_);
}
}
return result.get();
}
inline void address_translator::add()
{
address_translator_manager::singleton().add(*this);
}
inline void address_translator::remove()
{
address_translator_manager::singleton().remove(*this);
}
}

View File

@ -0,0 +1,687 @@
/*
* Injectors - Classes for making your hooking life easy
*
* Copyright (C) 2013-2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
#include "injector.hpp"
#include <cassert>
#include <functional>
#include <memory> // for std::shared_ptr
#include <list>
namespace injector
{
/*
* scoped_base
* Base for any scoped hooking type
* !!!! NOTICE !!!! --> Any derived which implements/reimplements restore() should implement a destructor calling it
*/
class scoped_base
{
public:
virtual ~scoped_base() {}
virtual void restore() = 0;
};
/*
* scoped_basic
* Base for scoped types which will need a buffer to save/restore stuff
*/
template<size_t bufsize> // TODO specialize bufsize=0 to be dynamic
class scoped_basic : public scoped_base
{
private:
uint8_t buf[bufsize];// Saved content
memory_pointer_raw addr; // Data saved from this address
size_t size; // Size saved
bool saved; // Something saved?
bool vp; // Virtual protect?
public:
static const bool is_dynamic = false;
// Restore the previosly saved data
// Problems may arise if someone else hooked the same place using the same method
virtual void restore()
{
#ifndef INJECTOR_SCOPED_NOSAVE_NORESTORE
if(this->saved)
{
WriteMemoryRaw(this->addr, this->buf, this->size, this->vp);
this->saved = false;
}
#endif
}
// Save buffer at @addr with @size and virtual protect @vp
virtual void save(memory_pointer_tr addr, size_t size, bool vp)
{
#ifndef INJECTOR_SCOPED_NOSAVE_NORESTORE
assert(size <= bufsize); // Debug Safeness
this->restore(); // Restore anything we have saved
this->saved = true; // Mark that we have data save
this->addr = addr.get<void>(); // Save address
this->size = size; // Save size
this->vp = vp; // Save virtual protect
ReadMemoryRaw(addr, buf, size, vp); // Save buffer
#endif
}
public:
// Constructor, initialises
scoped_basic() : saved(false)
{}
~scoped_basic()
{
this->restore();
}
// No copy construction, we can't do this! Sure we can move construct :)
scoped_basic(const scoped_basic&) = delete;
scoped_basic(scoped_basic&& rhs)
{
*this = std::move(rhs);
}
scoped_basic& operator=(const scoped_basic& rhs) = delete;
scoped_basic& operator=(scoped_basic&& rhs)
{
if(this->saved = rhs.saved)
{
assert(bufsize >= rhs.size);
this->addr = rhs.addr;
this->size = rhs.size;
this->vp = rhs.vp;
memcpy(buf, rhs.buf, rhs.size);
rhs.saved = false;
}
return *this;
}
};
/*
* RAII wrapper for memory writes
* Can save only basic and POD types
*/
template<size_t bufsize_ = 10>
class scoped_write : public scoped_basic<bufsize_>
{
public:
// Save buffer at @addr with @size and virtual protect @vp and then overwrite it with @value
void write(memory_pointer_tr addr, void* value, size_t size, bool vp)
{
this->save(addr, size, vp);
return WriteMemoryRaw(addr, value, size, vp);
}
// Save buffer at @addr with size sizeof(@value) and virtual protect @vp and then overwrite it with @value
template<class T>
void write(memory_pointer_tr addr, T value, bool vp = false)
{
this->save(addr, sizeof(T), vp);
return WriteMemory<T>(addr, value, vp);
}
// Constructors, move constructors, assigment operators........
scoped_write() = default;
scoped_write(const scoped_write&) = delete;
scoped_write(scoped_write&& rhs) : scoped_basic<bufsize_>(std::move(rhs)) {}
scoped_write& operator=(const scoped_write& rhs) = delete;
scoped_write& operator=(scoped_write&& rhs)
{ scoped_basic<bufsize_>::operator=(std::move(rhs)); return *this; }
};
/*
* RAII wrapper for filling
*/
template<size_t bufsize_ = 5>
class scoped_fill : public scoped_basic<bufsize_>
{
public:
// Fills memory at @addr with value @value and size @size and virtual protect @vp
void fill(memory_pointer_tr addr, uint8_t value, size_t size, bool vp)
{
this->save(addr, size, vp);
return MemoryFill(addr, value, size, vp);
}
// Constructors, move constructors, assigment operators........
scoped_fill() = default;
scoped_fill(const scoped_fill&) = delete;
scoped_fill(scoped_fill&& rhs) : scoped_basic<bufsize_>(std::move(rhs)) {}
scoped_fill& operator=(const scoped_fill& rhs) = delete;
scoped_fill& operator=(scoped_fill&& rhs)
{ scoped_basic<bufsize_>::operator=(std::move(rhs)); return *this; }
scoped_fill(memory_pointer_tr addr, uint8_t value, size_t size, bool vp)
{ fill(addr, value, vp); }
};
/*
* RAII wrapper for nopping
*/
template<size_t bufsize_>
class scoped_nop : public scoped_basic<bufsize_>
{
public:
// Makes NOP at @addr with value @value and size @size and virtual protect @vp
void make_nop(memory_pointer_tr addr, size_t size = 1, bool vp = true)
{
this->save(addr, size, vp);
return MakeNOP(addr, size, vp);
}
// Constructors, move constructors, assigment operators........
scoped_nop() = default;
scoped_nop(const scoped_nop&) = delete;
scoped_nop(scoped_nop&& rhs) : scoped_basic<bufsize_>(std::move(rhs)) {}
scoped_nop& operator=(const scoped_nop& rhs) = delete;
scoped_nop& operator=(scoped_nop&& rhs)
{ scoped_basic<bufsize_>::operator=(std::move(rhs)); return *this; }
scoped_nop(memory_pointer_tr addr, size_t size = 1, bool vp = true)
{ make_nop(addr, size, vp); }
};
/*
* RAII wrapper for MakeJMP
*/
class scoped_jmp : public scoped_basic<5>
{
public:
// Makes NOP at @addr with value @value and size @size and virtual protect @vp
memory_pointer_raw make_jmp(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{
this->save(at, 5, vp);
return MakeJMP(at, dest, vp);
}
// Constructors, move constructors, assigment operators........
scoped_jmp() = default;
scoped_jmp(const scoped_jmp&) = delete;
scoped_jmp(scoped_jmp&& rhs) : scoped_basic<5>(std::move(rhs)) {}
scoped_jmp& operator=(const scoped_jmp& rhs) = delete;
scoped_jmp& operator=(scoped_jmp&& rhs)
{ scoped_basic<5>::operator=(std::move(rhs)); return *this; }
scoped_jmp(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{ make_jmp(at, dest, vp); }
};
/*
* RAII wrapper for MakeCALL
*/
class scoped_call : public scoped_basic<5>
{
public:
// Makes NOP at @addr with value @value and size @size and virtual protect @vp
memory_pointer_raw make_call(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{
this->save(at, 5, vp);
return MakeCALL(at, dest, vp);
}
// Constructors, move constructors, assigment operators........
scoped_call() = default;
scoped_call(const scoped_call&) = delete;
scoped_call(scoped_call&& rhs) : scoped_basic<5>(std::move(rhs)) {}
scoped_call& operator=(const scoped_call& rhs) = delete;
scoped_call& operator=(scoped_call&& rhs)
{ scoped_basic<5>::operator=(std::move(rhs)); return *this; }
scoped_call(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{ make_call(at, dest, vp); }
};
#if __cplusplus >= 201103L || _MSC_VER >= 1800 // C++11 or MSVC 2013 required for variadic templates
/*
* function_hooker_manager
* Manages many function_hookers that points to the same address
* The need for this function arises because otherwise we would only be able to allow one hook per address using function_hookers
* This manager takes care of the amount of hooks placed in a particular address, calls the hooks and unhooks when necessary.
*/
template<class ToManage, class Ret, class ...Args>
class function_hooker_manager : protected scoped_call
{
private:
using func_type_raw = typename ToManage::func_type_raw;
using func_type = typename ToManage::func_type;
using functor_type = typename ToManage::functor_type;
using assoc_type = std::list<std::pair<const ToManage*, functor_type>>;
// Only construction is allowed... by myself ofcourse...
function_hooker_manager() = default;
function_hooker_manager(const function_hooker_manager&) = delete;
function_hooker_manager(function_hooker_manager&&) = delete;
//
func_type_raw original; // Pointer to the original function we've replaced
assoc_type assoc; // Association between owners of a hook and the hook (map)
bool has_hooked = false; // Is the hook already in place?
// Find assoc iterator for the content owned by 'owned'
typename assoc_type::iterator find_assoc(const ToManage& owner)
{
for(auto it = assoc.begin(); it != assoc.end(); ++it)
if(it->first == &owner) return it;
return assoc.end();
}
// Adds a new item to the association map (or override if already in the map)
void add(const ToManage& hooker, functor_type functor)
{
auto it = find_assoc(hooker);
if(it != assoc.end())
it->second = std::move(functor);
else
assoc.emplace_back(&hooker, std::move(functor));
}
public:
// Forwards the call to all the installed hooks
static Ret call_hooks(Args&... args)
{
auto& manager = *instance();
if(manager.assoc.size() == 0) // This may be uncommon but may happen (?), no hook installed
return manager.original(args...);
// Functor for the original call
func_type original = [&manager](Args... args) -> Ret {
return manager.original(args...);
};
if(manager.assoc.size() == 1)
{
// We have only one hook, just use it directly no need to go further in complexity
auto& functor = manager.assoc.begin()->second;
return functor(std::move(original), args...);
}
else
{
// Build a serie of functors which captures the previous functor sending it to the next functor,
// that's what would happen if the hooks took place independent of the template staticness (AAAAAAA)
func_type next = std::move(original);
for(auto it = manager.assoc.begin(); it != manager.assoc.end(); ++it)
{
auto& functor = it->second;
next = [functor, next](Args... args) -> Ret
{
return functor(next, args...);
};
}
return next(args...);
}
}
public:
// Installs a hook associated with the function_hooker 'hooker' which would call the specified 'functor'
// We need an auxiliar function pointer 'ptr' (to abstract calling conventions) which should forward itself to ^call_hooks
void make_call(const ToManage& hooker, functor_type functor, memory_pointer_raw ptr)
{
this->add(hooker, std::move(functor));
// Make sure we only hook this address for the manager once
if(!this->has_hooked)
{
// (the following cast is needed for __thiscall functions)
this->original = (func_type_raw) (void*) scoped_call::make_call(hooker.addr, ptr).get();
this->has_hooked = true;
}
}
// Restores the state of the call we've replaced in the game code
// All installed hooks gets uninstalled after this
void restore()
{
if(this->has_hooked)
{
this->has_hooked = false;
this->assoc.clear();
return scoped_call::restore();
}
}
// Replaces the hook associated with 'from' to be associated with 'to'
// After this call the 'from' object has no association in this manager
void replace(const ToManage& from, const ToManage& to)
{
auto it = find_assoc(from);
if(it != assoc.end())
{
auto functor = std::move(it->second);
assoc.erase(it);
this->add(to, std::move(functor));
}
}
// Removes the hook associated with the specified 'hooker'
// If the number of hooks reaches zero after the remotion, a restore will take place
void remove(const ToManage& hooker)
{
auto it = find_assoc(hooker);
if(it != assoc.end())
{
assoc.erase(it);
if(assoc.size() == 0) this->restore();
}
}
// The instance of this specific manager
// This work as a shared pointer to avoid the static destruction of the manager even when a static function_hooker
// still wants to use it.
static std::shared_ptr<function_hooker_manager> instance()
{
static auto fm_ptr = std::shared_ptr<function_hooker_manager>(new function_hooker_manager());
return fm_ptr;
}
};
/*
* function_hooker_base
* Base for any function_hooker, this class manages the relationship with the function hooker manager
*/
template<uintptr_t addr1, class FuncType, class Ret, class ...Args>
class function_hooker_base : public scoped_base
{
public:
static const uintptr_t addr = addr1;
using func_type_raw = FuncType;
using func_type = std::function<Ret(Args...)>;
using functor_type = std::function<Ret(func_type, Args&...)>;
using manager_type = function_hooker_manager<function_hooker_base, Ret, Args...>;
public:
// Constructors, move constructors, assigment operators........
function_hooker_base(const function_hooker_base&) = delete;
function_hooker_base& operator=(const function_hooker_base& rhs) = delete;
function_hooker_base() : manager(manager_type::instance())
{}
//
virtual ~function_hooker_base()
{
this->restore();
}
// The move constructor should do a replace in the manager
function_hooker_base(function_hooker_base&& rhs)
: scoped_base(std::move(rhs)), has_call(rhs.has_call),
manager(rhs.manager) // (don't move the manager!, every function_hooker should own one)
{
manager->replace(rhs, *this);
}
// The move assignment operator should also do a replace in the manager
function_hooker_base& operator=(function_hooker_base&& rhs)
{
scoped_base::operator=(std::move(rhs));
manager->replace(rhs, *this);
this->has_call = rhs.has_call;
this->manager = rhs.manager; // (don't move the manager! every function_hooker should own one)
return *this;
}
// Deriveds should implement a proper make_call (yeah it's virtual so derived-deriveds can do some fest)
virtual void make_call(functor_type functor) = 0;
// Restores the state of the call we've replaced in the game code
virtual void restore()
{
this->has_call = false;
manager->remove(*this);
}
// Checkers whether a hook is installed
bool has_hooked()
{
return this->has_call;
}
private:
bool has_call = false; // Has a hook installed?
std::shared_ptr<manager_type> manager; // **EVERY** function_hooker should have a ownership over it's manager_type
// this prevents the static destruction of the manager_type while it may be still needed.
protected: // Forwarders to the function hooker manager
void make_call(functor_type functor, memory_pointer_raw ptr)
{
this->has_call = true;
manager->make_call(*this, std::move(functor), ptr);
}
static Ret call_hooks(Args&... a)
{
return manager_type::call_hooks(a...);
}
};
/*
* function_hooker
* For standard conventions (usually __cdecl)
*/
template<uintptr_t addr1, class Prototype>
struct function_hooker;
template<uintptr_t addr1, class Ret, class ...Args>
class function_hooker<addr1, Ret(Args...)>
: public function_hooker_base<addr1, Ret(*)(Args...), Ret, Args...>
{
private:
using base = function_hooker_base<addr1, Ret(*)(Args...), Ret, Args...>;
// The hook caller
static Ret call(Args... a)
{
return base::call_hooks(a...);
}
public:
// Constructors, move constructors, assigment operators........
function_hooker() = default;
function_hooker(const function_hooker&) = delete;
function_hooker(function_hooker&& rhs) : base(std::move(rhs)) {}
function_hooker& operator=(const function_hooker& rhs) = delete;
function_hooker& operator=(function_hooker&& rhs)
{ base::operator=(std::move(rhs)); return *this; }
// Makes the hook
void make_call(typename base::functor_type functor)
{
return base::make_call(std::move(functor), raw_ptr(call));
}
};
/*
* function_hooker_stdcall
* For stdcall conventions (__stdcall)
*/
template<uintptr_t addr1, class Prototype>
struct function_hooker_stdcall;
template<uintptr_t addr1, class Ret, class ...Args>
struct function_hooker_stdcall<addr1, Ret(Args...)>
: public function_hooker_base<addr1, Ret(__stdcall*)(Args...), Ret, Args...>
{
private:
using base = function_hooker_base<addr1, Ret(__stdcall*)(Args...), Ret, Args...>;
// The hook caller
static Ret __stdcall call(Args... a)
{
return base::call_hooks(a...);
}
public:
// Constructors, move constructors, assigment operators........
function_hooker_stdcall() = default;
function_hooker_stdcall(const function_hooker_stdcall&) = delete;
function_hooker_stdcall(function_hooker_stdcall&& rhs) : base(std::move(rhs)) {}
function_hooker_stdcall& operator=(const function_hooker_stdcall& rhs) = delete;
function_hooker_stdcall& operator=(function_hooker_stdcall&& rhs)
{ base::operator=(std::move(rhs)); return *this; }
// Makes the hook
void make_call(typename base::functor_type functor)
{
return base::make_call(std::move(functor), raw_ptr(call));
}
};
/*
* function_hooker_fastcall
* For fastcall conventions (__fastcall)
*/
template<uintptr_t addr1, class Prototype>
struct function_hooker_fastcall;
template<uintptr_t addr1, class Ret, class ...Args>
struct function_hooker_fastcall<addr1, Ret(Args...)>
: public function_hooker_base<addr1, Ret(__fastcall*)(Args...), Ret, Args...>
{
private:
using base = function_hooker_base<addr1, Ret(__fastcall*)(Args...), Ret, Args...>;
// The hook caller
static Ret __fastcall call(Args... a)
{
return base::call_hooks(a...);
}
public:
// Constructors, move constructors, assigment operators........
function_hooker_fastcall() = default;
function_hooker_fastcall(const function_hooker_fastcall&) = delete;
function_hooker_fastcall(function_hooker_fastcall&& rhs) : base(std::move(rhs)) {}
function_hooker_fastcall& operator=(const function_hooker_fastcall& rhs) = delete;
function_hooker_fastcall& operator=(function_hooker_fastcall&& rhs)
{ base::operator=(std::move(rhs)); return *this; }
// Makes the hook
void make_call(typename base::functor_type functor)
{
return base::make_call(std::move(functor), raw_ptr(call));
}
};
/*
* function_hooker_thiscall
* For thiscall conventions (__thiscall, class methods)
*/
template<uintptr_t addr1, class Prototype>
struct function_hooker_thiscall;
template<uintptr_t addr1, class Ret, class ...Args>
struct function_hooker_thiscall<addr1, Ret(Args...)>
: public function_hooker_base<addr1, Ret(__thiscall*)(Args...), Ret, Args...>
{
private:
using base = function_hooker_base<addr1, Ret(__thiscall*)(Args...), Ret, Args...>;
// The hook caller
static Ret __thiscall call(Args... a)
{
return base::call_hooks(a...);
}
public:
// Constructors, move constructors, assigment operators........
function_hooker_thiscall() = default;
function_hooker_thiscall(const function_hooker_thiscall&) = delete;
function_hooker_thiscall(function_hooker_thiscall&& rhs) : base(std::move(rhs)) {}
function_hooker_thiscall& operator=(const function_hooker_thiscall& rhs) = delete;
function_hooker_thiscall& operator=(function_hooker_thiscall&& rhs)
{ base::operator=(std::move(rhs)); return *this; }
// Makes the hook
void make_call(typename base::functor_type functor)
{
return base::make_call(std::move(functor), raw_ptr(call));
}
};
/******************* HELPERS ******************/
/*
* Adds a hook to be alive for the entire program lifetime
* That means the hook received will be alive until the program dies.
* Note: Parameter must be a rvalue
*/
template<class T> inline
T& add_static_hook(T&& hooker)
{
static std::list<T> a;
return *a.emplace(a.end(), std::move(hooker));
}
/*
* Makes a hook which is alive until it gets out of scope
* 'T' must be any function_hooker object
*/
template<class T, class F> inline
T make_function_hook(F functor)
{
T a;
a.make_call(std::move(functor));
return a;
}
/*
* Makes a hook which is alive for the entire lifetime of this program
* 'T' must be any function_hooker object
*/
template<class T, class F> inline
T& make_static_hook(F functor)
{
return add_static_hook(make_function_hook<T>(std::move(functor)));
}
// TODO when we have access to C++14 add a make_function_hook, make_stdcall_function_hook, and so on
// the problem behind implement it with C++11 is that lambdas cannot be generic and the first param of a hook is a functor pointing
// to the previous call pointer
#endif
}

View File

@ -0,0 +1,752 @@
/*
* Injectors - Base Header
*
* Copyright (C) 2012-2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
#define INJECTOR_HAS_INJECTOR_HPP
#include <windows.h>
#include <cstdint>
#include <cstdio>
#include "gvm/gvm.hpp"
/*
The following macros (#define) are relevant on this header:
INJECTOR_GVM_HAS_TRANSLATOR
If defined, the user should provide their own address_manager::translator function.
That function is responssible for translating a void pointer (that mayn't be an actual pointer) into an actual address.
The meaning of that void pointer will be made by YOU when you send it to the functions that receive pointers on this library.
The default translator does nothing but returns that void pointer as the address.
INJECTOR_GVM_OWN_DETECT
If defined, the user should provide it's own game detection function thought game_version_manager::Detect
By default it provide an good detection for the Grand Theft Auto series.
INJECTOR_GVM_PLUGIN_NAME
If this is defined, it will be used as the plugin name used at error messages.
By default it will use ""Unknown Plugin Name"
INJECTOR_GVM_DUMMY
If defined, the game_version_manager will be a dummy object
By default it provides a nice gvm for Grand Theft Auto series
INJECTOR_OWN_GVM
If defined, the game_version_manager should be implemented by the user before including this library.
By default it provides a nice gvm for Grand Theft Auto series
*/
#include "gvm/gvm.hpp"
namespace injector
{
/*
* auto_pointer
* Casts itself to another pointer type in the lhs
*/
union auto_pointer
{
protected:
friend union memory_pointer_tr;
template<class T> friend union basic_memory_pointer;
void* p;
uintptr_t a;
public:
auto_pointer() : p(0) {}
auto_pointer(const auto_pointer& x) : p(x.p) {}
explicit auto_pointer(void* x) : p(x) {}
explicit auto_pointer(uint32_t x) : a(x) {}
bool is_null() const { return this->p != nullptr; }
#if __cplusplus >= 201103L || _MSC_VER >= 1800
explicit operator bool() const { return is_null(); }
#endif
auto_pointer get() const { return *this; }
template<class T> T* get() const { return (T*) this->p; }
template<class T> T* get_raw() const { return (T*) this->p; }
template<class T>
operator T*() const { return reinterpret_cast<T*>(p); }
};
/*
* basic_memory_pointer
* A memory pointer class that is capable of many operations, including address translation
* MemTranslator is the translator functor
*/
template<class MemTranslator>
union basic_memory_pointer
{
protected:
void* p;
uintptr_t a;
// Translates address p to the running executable pointer
static auto_pointer memory_translate(void* p)
{
return auto_pointer(MemTranslator()(p));
}
public:
basic_memory_pointer() : p(nullptr) {}
basic_memory_pointer(std::nullptr_t) : p(nullptr) {}
basic_memory_pointer(uintptr_t x) : a(x) {}
basic_memory_pointer(const auto_pointer& x) : p(x.p) {}
basic_memory_pointer(const basic_memory_pointer& rhs) : p(rhs.p) {}
template<class T>
basic_memory_pointer(T* x) : p((void*)x) {}
// Gets the translated pointer (plus automatic casting to lhs)
auto_pointer get() const { return memory_translate(p); }
// Gets the translated pointer (casted to T*)
template<class T> T* get() const { return get(); }
// Gets the raw pointer, without translation (casted to T*)
template<class T> T* get_raw() const { return auto_pointer(p); }
// This type can get assigned from void* and uintptr_t
basic_memory_pointer& operator=(void* x) { return p = x, *this; }
basic_memory_pointer& operator=(uintptr_t x) { return a = x, *this; }
/* Arithmetic */
basic_memory_pointer operator+(const basic_memory_pointer& rhs) const
{ return basic_memory_pointer(this->a + rhs.a); }
basic_memory_pointer operator-(const basic_memory_pointer& rhs) const
{ return basic_memory_pointer(this->a - rhs.a); }
basic_memory_pointer operator*(const basic_memory_pointer& rhs) const
{ return basic_memory_pointer(this->a * rhs.a); }
basic_memory_pointer operator/(const basic_memory_pointer& rhs) const
{ return basic_memory_pointer(this->a / rhs.a); }
/* Comparision */
bool operator==(const basic_memory_pointer& rhs) const
{ return this->a == rhs.a; }
bool operator!=(const basic_memory_pointer& rhs) const
{ return this->a != rhs.a; }
bool operator<(const basic_memory_pointer& rhs) const
{ return this->a < rhs.a; }
bool operator<=(const basic_memory_pointer& rhs) const
{ return this->a <= rhs.a; }
bool operator>(const basic_memory_pointer& rhs) const
{ return this->a > rhs.a; }
bool operator>=(const basic_memory_pointer& rhs) const
{ return this->a >=rhs.a; }
bool is_null() const { return this->p == nullptr; }
uintptr_t as_int() const { return this->a; } // does not perform translation
#if __cplusplus >= 201103L || _MSC_VER >= 1800 // MSVC 2013
/* Conversion to other types */
explicit operator uintptr_t() const
{ return this->a; } // does not perform translation
explicit operator bool() const
{ return this->p != nullptr; }
#else
//operator bool() -------------- Causes casting problems because of implicitness, use !is_null()
//{ return this->p != nullptr; }
#endif
};
// Typedefs including memory translator for the above type
typedef basic_memory_pointer<address_manager::fn_mem_translator> memory_pointer;
typedef basic_memory_pointer<address_manager::fn_mem_translator_nop> memory_pointer_raw;
typedef basic_memory_pointer<address_manager::fn_mem_translator_aslr> memory_pointer_aslr;
/*
* memory_pointer_tr
* Stores a basic_memory_pointer<Tr> as a raw pointer from translated pointer
*/
union memory_pointer_tr
{
protected:
void* p;
uintptr_t a;
public:
template<class Tr>
memory_pointer_tr(const basic_memory_pointer<Tr>& ptr)
: p(ptr.get())
{} // Constructs from a basic_memory_pointer
memory_pointer_tr(const auto_pointer& ptr)
: p(ptr.p)
{} // Constructs from a auto_pointer, probably comming from basic_memory_pointer::get
memory_pointer_tr(const memory_pointer_tr& rhs)
: p(rhs.p)
{} // Constructs from my own type, copy constructor
memory_pointer_tr(uintptr_t x)
: p(memory_pointer(x).get())
{} // Constructs from a integer, translating the address
memory_pointer_tr(void* x)
: p(memory_pointer(x).get())
{} // Constructs from a void pointer, translating the address
// Just to be method-compatible with basic_memory_pointer ...
auto_pointer get() { return auto_pointer(p); }
template<class T> T* get() { return get(); }
template<class T> T* get_raw() { return get(); }
memory_pointer_tr operator+(const uintptr_t& rhs) const
{ return memory_pointer_raw(this->a + rhs); }
memory_pointer_tr operator-(const uintptr_t& rhs) const
{ return memory_pointer_raw(this->a - rhs); }
memory_pointer_tr operator*(const uintptr_t& rhs) const
{ return memory_pointer_raw(this->a * rhs); }
memory_pointer_tr operator/(const uintptr_t& rhs) const
{ return memory_pointer_raw(this->a / rhs); }
bool is_null() const { return this->p == nullptr; }
uintptr_t as_int() const { return this->a; }
#if __cplusplus >= 201103L
explicit operator uintptr_t() const
{ return this->a; }
#else
#endif
};
/*
* ProtectMemory
* Makes the address @addr have a protection of @protection
*/
inline bool ProtectMemory(memory_pointer_tr addr, size_t size, DWORD protection)
{
return VirtualProtect(addr.get(), size, protection, &protection) != 0;
}
/*
* UnprotectMemory
* Unprotect the memory at @addr with size @size so it have all accesses (execute, read and write)
* Returns the old protection to out_oldprotect
*/
inline bool UnprotectMemory(memory_pointer_tr addr, size_t size, DWORD& out_oldprotect)
{
return VirtualProtect(addr.get(), size, PAGE_EXECUTE_READWRITE, &out_oldprotect) != 0;
}
/*
* scoped_unprotect
* RAII wrapper for UnprotectMemory
* On construction unprotects the memory, on destruction reprotects the memory
*/
struct scoped_unprotect
{
memory_pointer_raw addr;
size_t size;
DWORD dwOldProtect;
bool bUnprotected;
scoped_unprotect(memory_pointer_tr addr, size_t size)
{
if(size == 0) bUnprotected = false;
else bUnprotected = UnprotectMemory(this->addr = addr.get<void>(), this->size = size, dwOldProtect);
}
~scoped_unprotect()
{
if(bUnprotected) ProtectMemory(this->addr.get(), this->size, this->dwOldProtect);
}
};
/*
* WriteMemoryRaw
* Writes into memory @addr the content of @value with a sizeof @size
* Does memory unprotection if @vp is true
*/
inline void WriteMemoryRaw(memory_pointer_tr addr, void* value, size_t size, bool vp)
{
scoped_unprotect xprotect(addr, vp? size : 0);
memcpy(addr.get(), value, size);
}
/*
* ReadMemoryRaw
* Reads the memory at @addr with a sizeof @size into address @ret
* Does memory unprotection if @vp is true
*/
inline void ReadMemoryRaw(memory_pointer_tr addr, void* ret, size_t size, bool vp)
{
scoped_unprotect xprotect(addr, vp? size : 0);
memcpy(ret, addr.get(), size);
}
/*
* MemoryFill
* Fills the memory at @addr with the byte @value doing it @size times
* Does memory unprotection if @vp is true
*/
inline void MemoryFill(memory_pointer_tr addr, uint8_t value, size_t size, bool vp)
{
scoped_unprotect xprotect(addr, vp? size : 0);
memset(addr.get(), value, size);
}
/*
* WriteObject
* Assigns the object @value into the same object type at @addr
* Does memory unprotection if @vp is true
*/
template<class T>
inline T& WriteObject(memory_pointer_tr addr, const T& value, bool vp = false)
{
scoped_unprotect xprotect(addr, vp? sizeof(value) : 0);
return (*addr.get<T>() = value);
}
/*
* ReadObject
* Assigns the object @value with the value of the same object type at @addr
* Does memory unprotection if @vp is true
*/
template<class T>
inline T& ReadObject(memory_pointer_tr addr, T& value, bool vp = false)
{
scoped_unprotect xprotect(addr, vp? sizeof(value) : 0);
return (value = *addr.get<T>());
}
/*
* WriteMemory
* Writes the object of type T into the address @addr
* Does memory unprotection if @vp is true
*/
template<class T>
inline void WriteMemory(memory_pointer_tr addr, T value, bool vp = false)
{
WriteObject(addr, value, vp);
}
/*
* ReadMemory
* Reads the object type T at address @addr
* Does memory unprotection if @vp is true
*/
template<class T>
inline T ReadMemory(memory_pointer_tr addr, bool vp = false)
{
T value;
return ReadObject(addr, value, vp);
}
/*
* AdjustPointer
* Searches in the range [@addr, @addr + @max_search] for a pointer in the range [@default_base, @default_end] and replaces
* it with the proper offset in the pointer @replacement_base.
* Does memory unprotection if @vp is true.
*/
inline memory_pointer_raw AdjustPointer(memory_pointer_tr addr,
memory_pointer_raw replacement_base, memory_pointer_tr default_base, memory_pointer_tr default_end,
size_t max_search = 8, bool vp = true)
{
scoped_unprotect xprotect(addr, vp? max_search + sizeof(void*) : 0);
for(size_t i = 0; i < max_search; ++i)
{
memory_pointer_raw ptr = ReadMemory<void*>(addr + i);
if(ptr >= default_base.get() && ptr <= default_end.get())
{
auto result = replacement_base + (ptr - default_base.get());
WriteMemory<void*>(addr + i, result.get());
return result;
}
}
return nullptr;
}
/*
* GetAbsoluteOffset
* Gets absolute address based on relative offset @rel_value from instruction that ends at @end_of_instruction
*/
inline memory_pointer_raw GetAbsoluteOffset(int rel_value, memory_pointer_tr end_of_instruction)
{
return end_of_instruction.get<char>() + rel_value;
}
/*
* GetRelativeOffset
* Gets relative offset based on absolute address @abs_value for instruction that ends at @end_of_instruction
*/
inline int GetRelativeOffset(memory_pointer_tr abs_value, memory_pointer_tr end_of_instruction)
{
return uintptr_t(abs_value.get<char>() - end_of_instruction.get<char>());
}
/*
* ReadRelativeOffset
* Reads relative offset from address @at
*/
inline memory_pointer_raw ReadRelativeOffset(memory_pointer_tr at, size_t sizeof_addr = 4, bool vp = true)
{
switch(sizeof_addr)
{
case 1: return (GetAbsoluteOffset(ReadMemory<int8_t> (at, vp), at+sizeof_addr));
case 2: return (GetAbsoluteOffset(ReadMemory<int16_t>(at, vp), at+sizeof_addr));
case 4: return (GetAbsoluteOffset(ReadMemory<int32_t>(at, vp), at+sizeof_addr));
}
return nullptr;
}
/*
* MakeRelativeOffset
* Writes relative offset into @at based on absolute destination @dest
*/
inline void MakeRelativeOffset(memory_pointer_tr at, memory_pointer_tr dest, size_t sizeof_addr = 4, bool vp = true)
{
switch(sizeof_addr)
{
case 1: WriteMemory<int8_t> (at, static_cast<int8_t> (GetRelativeOffset(dest, at+sizeof_addr)), vp);
case 2: WriteMemory<int16_t>(at, static_cast<int16_t>(GetRelativeOffset(dest, at+sizeof_addr)), vp);
case 4: WriteMemory<int32_t>(at, static_cast<int32_t>(GetRelativeOffset(dest, at+sizeof_addr)), vp);
}
}
/*
* GetBranchDestination
* Gets the destination of a branch instruction at address @at
* *** Works only with JMP and CALL for now ***
*/
inline memory_pointer_raw GetBranchDestination(memory_pointer_tr at, bool vp = true)
{
switch(ReadMemory<uint8_t>(at, vp))
{
// We need to handle other instructions (and prefixes) later...
case 0xE8: // call rel
case 0xE9: // jmp rel
return ReadRelativeOffset(at + 1, 4, vp);
case 0xFF:
switch(ReadMemory<uint8_t>(at + 1, vp))
{
case 0x15: // call dword ptr [addr]
case 0x25: // jmp dword ptr [addr]
return *(ReadMemory<uintptr_t*>(at + 2, vp));
}
break;
}
return nullptr;
}
/*
* MakeJMP
* Creates a JMP instruction at address @at that jumps into address @dest
* If there was already a branch instruction there, returns the previosly destination of the branch
*/
inline memory_pointer_raw MakeJMP(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{
auto p = GetBranchDestination(at, vp);
WriteMemory<uint8_t>(at, 0xE9, vp);
MakeRelativeOffset(at+1, dest, 4, vp);
return p;
}
/*
* MakeCALL
* Creates a CALL instruction at address @at that jumps into address @dest
* If there was already a branch instruction there, returns the previosly destination of the branch
*/
inline memory_pointer_raw MakeCALL(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{
auto p = GetBranchDestination(at, vp);
WriteMemory<uint8_t>(at, 0xE8, vp);
MakeRelativeOffset(at+1, dest, 4, vp);
return p;
}
/*
* MakeJA
* Creates a JA instruction at address @at that jumps if above into address @dest
* If there was already a branch instruction there, returns the previosly destination of the branch
*/
inline void MakeJA(memory_pointer_tr at, memory_pointer_raw dest, bool vp = true)
{
WriteMemory<uint16_t>(at, 0x87F0, vp);
MakeRelativeOffset(at+2, dest, 4, vp);
}
/*
* MakeNOP
* Creates a bunch of NOP instructions at address @at
*/
inline void MakeNOP(memory_pointer_tr at, size_t count = 1, bool vp = true)
{
MemoryFill(at, 0x90, count, vp);
}
/*
* MakeRangedNOP
* Creates a bunch of NOP instructions at address @at until address @until
*/
inline void MakeRangedNOP(memory_pointer_tr at, memory_pointer_tr until, bool vp = true)
{
return MakeNOP(at, size_t(until.get_raw<char>() - at.get_raw<char>()), vp);
}
/*
* MakeRET
* Creates a RET instruction at address @at popping @pop values from the stack
* If @pop is equal to 0 it will use the 1 byte form of the instruction
*/
inline void MakeRET(memory_pointer_tr at, uint16_t pop = 0, bool vp = true)
{
WriteMemory(at, pop? 0xC2 : 0xC3, vp);
if(pop) WriteMemory(at+1, pop, vp);
}
/*
* lazy_pointer
* Lazy pointer, where it's final value will get evaluated only once when finally needed.
*/
template<uintptr_t addr>
struct lazy_pointer
{
public:
// Returns the final raw pointer
static auto_pointer get()
{
return xget().get();
}
template<class T>
static T* get()
{
return get().get<T>();
}
private:
// Returns the final pointer
static memory_pointer_raw xget()
{
static void* ptr = nullptr;
if(!ptr) ptr = memory_pointer(addr).get();
return memory_pointer_raw(ptr);
}
};
/*
* lazy_object
* Lazy object, where it's final object will get evaluated only once when finally needed.
*/
template<uintptr_t addr, class T>
struct lazy_object
{
static T& get()
{
static T data;
static bool has_data = false;
if(!has_data)
{
ReadObject<T>(addr, data, true);
has_data = true;
}
return data;
}
};
/*
Helpers
*/
template<class T>
inline memory_pointer mem_ptr(T p)
{
return memory_pointer(p);
}
template<class T>
inline memory_pointer_raw raw_ptr(T p)
{
return memory_pointer_raw(p);
}
template<class Tr>
inline memory_pointer_raw raw_ptr(basic_memory_pointer<Tr> p)
{
return raw_ptr(p.get());
}
template<uintptr_t addr>
inline memory_pointer_raw lazy_ptr()
{
return lazy_pointer<addr>::get();
}
template<class T>
inline memory_pointer_aslr aslr_ptr(T p)
{
return memory_pointer_aslr(p);
}
#ifndef INJECTOR_GVM_OWN_DETECT // Should we implement our detection method?
// Detects game, region and version; returns false if could not detect it
inline bool game_version_manager::Detect()
{
// Cleanup data
this->Clear();
// Find NT header
uintptr_t base = (uintptr_t) GetModuleHandleA(NULL);
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)(base);
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(base + dos->e_lfanew);
// Look for game and version thought the entry-point
// Thanks to Silent for many of the entry point offsets
switch (base + nt->OptionalHeader.AddressOfEntryPoint + (0x400000 - base))
{
case 0x5C1E70: // GTA III 1.0
game = '3', major = 1, minor = 0, region = 0, steam = false;
return true;
case 0x5C2130: // GTA III 1.1
game = '3', major = 1, minor = 1, region = 0, steam = false;
return true;
case 0x5C6FD0: // GTA III 1.1 (Cracked Steam Version)
case 0x9912ED: // GTA III 1.1 (Encrypted Steam Version)
game = '3', major = 1, minor = 1, region = 0, steam = true;
return true;
case 0x667BF0: // GTA VC 1.0
game = 'V', major = 1, minor = 0, region = 0, steam = false;
return true;
case 0x667C40: // GTA VC 1.1
game = 'V', major = 1, minor = 1, region = 0, steam = false;
return true;
case 0x666BA0: // GTA VC 1.1 (Cracked Steam Version)
case 0xA402ED: // GTA VC 1.1 (Encrypted Steam Version)
game = 'V', major = 1, minor = 1, region = 0, steam = true;
return true;
case 0x82457C: // GTA SA 1.0 US Cracked
case 0x824570: // GTA SA 1.0 US Compact
game = 'S', major = 1, minor = 0, region = 'U', steam = false;
cracker = injector::ReadMemory<uint8_t>(raw_ptr(0x406A20), true) == 0xE9? 'H' : 0;
return true;
case 0x8245BC: // GTA SA 1.0 EU Cracked (??????)
case 0x8245B0: // GTA SA 1.0 EU Cracked
game = 'S', major = 1, minor = 0, region = 'E', steam = false;
cracker = injector::ReadMemory<uint8_t>(raw_ptr(0x406A20), true) == 0xE9? 'H' : 0; // just to say 'securom'
return true;
case 0x8252FC: // GTA SA 1.1 US Cracked
game = 'S', major = 1, minor = 1, region = 'U', steam = false;
return true;
case 0x82533C: // GTA SA 1.1 EU Cracked
game = 'S', major = 1, minor = 1, region = 'E', steam = false;
return true;
case 0x85EC4A: // GTA SA 3.0 (Cracked Steam Version)
case 0xD3C3DB: // GTA SA 3.0 (Encrypted Steam Version)
game = 'S', major = 3, minor = 0, region = 0, steam = true;
return true;
case 0xC965AD: // GTA IV 1.0.0.4 US
game = 'I', major = 1, minor = 0, majorRevision = 0, minorRevision = 4, region = 'U', steam = false;
return true;
case 0xD0D011: // GTA IV 1.0.0.7 US
game = 'I', major = 1, minor = 0, majorRevision = 0, minorRevision = 7, region = 'U', steam = false;
return true;
case 0xD0AF06: // GTA EFLC 1.1.2.0 US
game = 'E', major = 1, minor = 1, majorRevision = 2, minorRevision = 0, region = 'U', steam = false;
return true;
case 0x1415FF790: // GTA 5 v1.0.350.2 Non-Steam US
game = '5', major = 1, minor = 0, majorRevision = 350, minorRevision = 2, region = 'U', steam = false;
return true;
default:
return false;
}
}
#endif
} // namespace

View File

@ -0,0 +1,56 @@
/*
* Injectors - Utility / Helpers
*
* Copyright (C) 2014 LINK/2012 <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#pragma once
namespace injector
{
template<class T, T value>
T return_value()
{
return value;
}
template<class T>
void* force_ptr(const T& fun)
{
auto ptr = fun;
return *(void**)&ptr;
}
// Helper structure to help calling back what was there before a hook
// e.g. hb.fun = MakeCALL(0x0, raw_ptr(my_hook));
template<class FuncType>
struct hook_back
{
typedef FuncType func_type;
func_type fun;
hook_back() : fun(nullptr)
{}
};
};

25
OpenParrot/premake5.lua Normal file
View File

@ -0,0 +1,25 @@
project "OpenParrot"
targetname "OpenParrot"
language "C++"
kind "SharedLib"
files
{
"src/**.cpp", "src/**.h",
"deps/cpp/**.cpp", "deps/inc/**.h"
}
includedirs { "src", "deps/inc/" }
libdirs { "deps/lib/" }
--pchheader 'StdInc.h'
--pchsource 'src/StdInc.cpp'
links { "MinHook", "udis86" }
postbuildcommands { }
filter "platforms:x64"
files { "src/win64init.asm" }
targetsuffix "64"

View File

@ -0,0 +1,23 @@
#if _M_IX86
#include <StdInc.h>
#include "Utility/InitFunction.h"
#include "Functions/Global.h"
extern LPCSTR hookPort;
static InitFunction MachStormFunc([]()
{
DWORD imageBase = (DWORD)GetModuleHandleA(0);
// Patch to ignore all errors
injector::WriteMemory<DWORD>(imageBase + 0x7071E, 0x90909090, true);
// Patch to skip extra device strange init (also delays game start on real cabinet several minutes!!!)
injector::WriteMemory<DWORD>(imageBase + 0x76430, 0xC340C033, true);
injector::WriteMemory<DWORD>(imageBase + 0x76870, 0xC340C033, true);
// Patch test menu etc
injector::WriteMemoryRaw(imageBase + 0x544BB0, (char*)".\\%c%s.dat", 12, true);
hookPort = "COM3";
}, GameID::MachStorm);
#endif

View File

@ -0,0 +1,53 @@
#include <StdInc.h>
#include "Utility/InitFunction.h"
#include "Functions/Global.h"
#if _M_IX86
signed int FordRacingControlInit()
{
// start input thread
((void(*)(int, int, int))0x4E0803)(0x4DE030, 0, 0);
// set input initialized
*(DWORD*)0x6B02A0 = 1;
// device count
*(DWORD*)0x6B0290 = 1;
// set joystick
*(char**)0x6A9AF4 = "JOYSTICK";
// create mutex
*(DWORD*)0x6A9A74 = (DWORD)CreateMutex(NULL, FALSE, NULL);
return 1;
}
extern int* ffbOffset;
int __stdcall FordRacingFfbFunc(DWORD device, DWORD data)
{
if(device == 0x378)
{
*ffbOffset = data;
}
return 0;
}
static InitFunction fordRacingFunc([]()
{
DWORD oldprot = 0;
DWORD oldprot2 = 0;
VirtualProtect((LPVOID)0x401000, 0xEE000, 0x40, &oldprot);
// readfile call
static DWORD source = (DWORD)(LPVOID)&ReadFileHooked;
*(DWORD *)0x4DE005 = (DWORD)(LPVOID)&source;
VirtualProtect((LPVOID)0x401000, 0xEE000, oldprot, &oldprot2);
// replace input init
injector::MakeJMP(0x4DE1F0, FordRacingControlInit);
// Hook FFB calls
injector::MakeJMP(0x00467C9A, FordRacingFfbFunc);
}, GameID::FordRacing);
#endif

View File

@ -0,0 +1,42 @@
#include <StdInc.h>
#include "Utility/InitFunction.h"
#include "Functions/Global.h"
#if _M_IX86
extern int* ffbOffset;
int __stdcall Sr3FfbFunc(DWORD device, DWORD data)
{
*ffbOffset = data;
return 0;
}
static InitFunction sr3Func([]()
{
DWORD oldprot = 0;
DWORD oldprot2 = 0;
VirtualProtect((LPVOID)0x401000, 0x273000, 0x40, &oldprot);
// force controller init
//injector::MakeJMP(0x57B2F0, ReturnTrue);
memcpy((LPVOID)0x57B2F0, "\x33\xC0\x40\xC3", 4);
// disable checks for controller pointer
memset((LPVOID)0x57B670, 0x90, 15);
// dereference
memset((LPVOID)0x57B684, 0x90, 3);
// Hook FFB
// Remove loading of inpout32.dll
injector::MakeNOP(0x006582A8, 0x17);
// Give our own pointer to the FFB func
injector::WriteMemory<uint8_t>(0x006582A8, 0xB8, true);
injector::WriteMemory<DWORD>(0x006582A9, (DWORD)Sr3FfbFunc, true);
//
// ReadFile call
static DWORD source = (DWORD)(LPVOID)&ReadFileHooked;
*(DWORD *)0x57B696 = (DWORD)(LPVOID)&source;
VirtualProtect((LPVOID)0x401000, 0x273000, oldprot, &oldprot2);
}, GameID::SR3);
#endif

View File

@ -0,0 +1,41 @@
#include <StdInc.h>
#include "Utility/GameDetect.h"
#include "Utility/InitFunction.h"
#include "Functions/Nesica_Libs/CryptoPipe.h"
#include "Functions/Nesica_Libs/FastIoEmu.h"
#include "Functions/Nesica_Libs/RfidEmu.h"
#include "Functions/Nesica_Libs/NesysEmu.h"
static InitFunction initFunction([]()
{
init_FastIoEmu();
init_RfidEmu(X2Type::RFID);
init_NesysEmu();
#if _M_IX86
if(GameDetect::NesicaKey != NesicaKey::None)
init_CryptoPipe(GameDetect::NesicaKey);
#endif
}, GameID::Nesica);
static int ReturnTrue()
{
return 1;
}
static InitFunction initFunction_SOR([]()
{
uintptr_t imageBase = (uintptr_t)GetModuleHandleA(0);
init_FastIoEmu();
init_RfidEmu(X2Type::RFID);
safeJMP(imageBase + 0xFA350, ReturnTrue);
safeJMP(imageBase + 0xF8FC0, ReturnTrue);
// Patch data dir to game dir pls D:/ -> .\\
//
injector::WriteMemory<DWORD>(imageBase + 0x21B9AC0, 0x2F002E002E, true);
init_NesysEmu();
if (ToBool(config["General"]["Windowed"]))
{
injector::WriteMemory<LONGLONG>(imageBase + 0xFF703C, 0xF633C1FFC1FFC933, true);
injector::WriteMemory<DWORD>(imageBase + 0xFF703C+0x08, 0xC6FFC6FF, true);
}
}, GameID::SchoolOfRagnarok);

View File

@ -0,0 +1,385 @@
#pragma optimize("", off)
// ============================================================================
// ttx_monitor: Opensource TaitoTypeX loader
// by Romhack
// ============================================================================
// Fake API do DirectInput, assim impedimos que os jogos tenham acesso aos controles.
#include <string.h>
#include "StdInc.h"
#include "Utility/InitFunction.h"
#define DIRECTINPUT_VERSION 0x800
#include <dinput.h>
#pragma comment(lib, "dxguid.lib")
#define COM_NO_WINDOWS_H
#include <objbase.h>
#include "Utility/GameDetect.h"
typedef HRESULT(__stdcall *LPDirectInput8Create)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID * ppvOut, LPUNKNOWN punkOuter);
LPDirectInput8Create __DirectInput8Create;
static DIDEVICEINSTANCEA devi;
#pragma pack(4)
struct FAR HookIUnknown
{
virtual HRESULT QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj);
virtual ULONG AddRef(LPVOID _this);
virtual ULONG Release(LPVOID _this);
};
static HookIUnknown UnknownInfo, *pUnknownInfo = &UnknownInfo;
HRESULT HookIUnknown::QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj)
{
*ppvObj = NULL;
return DIERR_UNSUPPORTED;
}
ULONG HookIUnknown::AddRef(LPVOID _this)
{
return 0;
}
ULONG HookIUnknown::Release(LPVOID _this)
{
return 0;
}
#pragma pack(4)
struct FAR HookIDirectInputDevice
{
virtual HRESULT QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj);
virtual ULONG AddRef(LPVOID _this);
virtual ULONG Release(LPVOID _this);
virtual HRESULT GetCapabilities(LPVOID _this, LPDIDEVCAPS lpDIDevCaps);
virtual HRESULT EnumObjects(LPVOID _this, LPDIENUMDEVICEOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags);
virtual HRESULT GetProperty(LPVOID _this, REFGUID rguidProp, LPDIPROPHEADER pdiph);
virtual HRESULT SetProperty(LPVOID _this, REFGUID rguidProp, LPCDIPROPHEADER pdiph);
virtual HRESULT Acquire(LPVOID _this);
virtual HRESULT Unacquire(LPVOID _this);
virtual HRESULT GetDeviceState(LPVOID _this, DWORD cbData, LPVOID lpvData);
virtual HRESULT GetDeviceData(LPVOID _this, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags);
virtual HRESULT SetDataFormat(LPVOID _this, LPCDIDATAFORMAT lpdf);
virtual HRESULT SetEventNotification(LPVOID _this, HANDLE hEvent);
virtual HRESULT SetCooperativeLevel(LPVOID _this, HWND hwnd, DWORD dwFlags);
virtual HRESULT GetObjectInfo(LPVOID _this, LPDIDEVICEOBJECTINSTANCE pdidoi, DWORD dwObj, DWORD dwHow);
virtual HRESULT GetDeviceInfo(LPVOID _this, LPDIDEVICEINSTANCE pdidi);
virtual HRESULT RunControlPanel(LPVOID _this, HWND hwndOwner, DWORD dwFlags);
virtual HRESULT Initialize(LPVOID _this, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid);
virtual HRESULT CreateEffect(LPVOID _this, REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter);
virtual HRESULT EnumEffects(LPVOID _this, LPDIENUMEFFECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwEffType);
virtual HRESULT GetEffectInfo(LPVOID _this, LPDIEFFECTINFOA pdei, REFGUID rguid);
virtual HRESULT GetForceFeedbackState(LPVOID _this, LPDWORD pdwOut);
virtual HRESULT SendForceFeedbackCommand(LPVOID _this, DWORD dwFlags);
virtual HRESULT EnumCreatedEffectObjects(LPVOID _this, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl);
virtual HRESULT Escape(LPVOID _this, LPDIEFFESCAPE pesc);
virtual HRESULT Poll(LPVOID _this);
virtual HRESULT SendDeviceData(LPVOID _this, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl);
virtual HRESULT EnumEffectsInFile(LPVOID _this, LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags);
virtual HRESULT WriteEffectToFile(LPVOID _this, LPCSTR lpszFileName, DWORD dwEntries, LPCDIFILEEFFECT rgDiFileEft, DWORD dwFlags);
virtual HRESULT BuildActionMap(LPVOID _this, LPDIACTIONFORMAT lpdiaf, LPCTSTR lpszUserName, DWORD dwFlags);
virtual HRESULT SetActionMap(LPVOID _this, LPCDIACTIONFORMAT lpdiActionFormat, LPCTSTR lptszUserName, DWORD dwFlags);
virtual HRESULT GetImageInfo(LPVOID _this, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader);
};
static HookIDirectInputDevice FakeDevice, *pFakeDevice = &FakeDevice;
HRESULT HookIDirectInputDevice::QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj)
{
*ppvObj = NULL;
return 0;
}
ULONG HookIDirectInputDevice::AddRef(LPVOID _this)
{
return 2;
}
ULONG HookIDirectInputDevice::Release(LPVOID _this)
{
return 0;
}
HRESULT HookIDirectInputDevice::GetCapabilities(LPVOID _this, LPDIDEVCAPS lpDIDevCaps)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::EnumObjects(LPVOID _this, LPDIENUMDEVICEOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::GetProperty(LPVOID _this, REFGUID rguidProp, LPDIPROPHEADER pdiph)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::SetProperty(LPVOID _this, REFGUID rguidProp, LPCDIPROPHEADER pdiph)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::Acquire(LPVOID _this)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::Unacquire(LPVOID _this)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::GetDeviceState(LPVOID _this, DWORD cbData, LPVOID lpvData)
{
if (lpvData)
{
ZeroMemory(lpvData, cbData);
}
return DI_OK;
}
HRESULT HookIDirectInputDevice::GetDeviceData(LPVOID _this, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
{
if (rgdod)
{
ZeroMemory(rgdod, cbObjectData * (*pdwInOut));
}
return DI_OK;
}
HRESULT HookIDirectInputDevice::SetDataFormat(LPVOID _this, LPCDIDATAFORMAT lpdf)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::SetEventNotification(LPVOID _this, HANDLE hEvent)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::SetCooperativeLevel(LPVOID _this, HWND hwnd, DWORD dwFlags)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::GetObjectInfo(LPVOID _this, LPDIDEVICEOBJECTINSTANCE pdidoi, DWORD dwObj, DWORD dwHow)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::GetDeviceInfo(LPVOID _this, LPDIDEVICEINSTANCE pdidi)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::RunControlPanel(LPVOID _this, HWND hwndOwner, DWORD dwFlags)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::Initialize(LPVOID _this, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid)
{
return DI_OK;
}
HRESULT HookIDirectInputDevice::CreateEffect(LPVOID _this, REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff,LPUNKNOWN punkOuter)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::EnumEffects(LPVOID _this, LPDIENUMEFFECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwEffType)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::GetEffectInfo(LPVOID _this, LPDIEFFECTINFOA pdei, REFGUID rguid)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::GetForceFeedbackState(LPVOID _this, LPDWORD pdwOut)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::SendForceFeedbackCommand(LPVOID _this, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::EnumCreatedEffectObjects(LPVOID _this, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::Escape(LPVOID _this, LPDIEFFESCAPE pesc)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::Poll(LPVOID _this)
{
return DI_NOEFFECT;
}
HRESULT HookIDirectInputDevice::SendDeviceData(LPVOID _this, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::EnumEffectsInFile(LPVOID _this, LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::WriteEffectToFile(LPVOID _this, LPCSTR lpszFileName, DWORD dwEntries, LPCDIFILEEFFECT rgDiFileEft, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::BuildActionMap(LPVOID _this, LPDIACTIONFORMAT lpdiaf, LPCTSTR lpszUserName, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::SetActionMap(LPVOID _this, LPCDIACTIONFORMAT lpdiActionFormat, LPCTSTR lptszUserName, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInputDevice::GetImageInfo(LPVOID _this, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader)
{
return DIERR_UNSUPPORTED;
}
#pragma pack(4)
struct FAR HookIDirectInput8
{
virtual HRESULT QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj);
virtual ULONG AddRef(LPVOID _this);
virtual ULONG Release(LPVOID _this);
virtual HRESULT CreateDevice(LPVOID _this, REFGUID rguid, LPDIRECTINPUTDEVICE8A * lplpDirectInputDevice, LPUNKNOWN pUnkOuter);
virtual HRESULT EnumDevices(LPVOID _this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags);
virtual HRESULT GetDeviceStatus(LPVOID _this, REFGUID rguidInstance);
virtual HRESULT RunControlPanel(LPVOID _this, HWND hwndOwner, DWORD dwFlags);
virtual HRESULT Initialize(LPVOID _this, HINSTANCE hinst, DWORD dwVersion);
virtual HRESULT FindDevice(LPVOID _this, REFGUID rguidClass, LPCTSTR ptszName, LPGUID pguidInstance);
virtual HRESULT EnumDevicesBySemantics(LPVOID _this, LPCTSTR ptszUserName, LPDIACTIONFORMAT lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCB lpCallback, LPVOID pvRef, DWORD dwFlags);
virtual HRESULT ConfigureDevices(LPVOID _this, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMS lpdiCDParams, DWORD dwFlags, LPVOID pvRefData);
};
static HookIDirectInput8 FakeInterface, *pFakeInterface = &FakeInterface;
HRESULT HookIDirectInput8::QueryInterface(LPVOID _this, REFIID riid, LPVOID *ppvObj)
{
*ppvObj = NULL;
return DIERR_UNSUPPORTED;
}
ULONG HookIDirectInput8::AddRef(LPVOID _this)
{
return 0;
}
ULONG HookIDirectInput8::Release(LPVOID _this)
{
return 0;
}
HRESULT HookIDirectInput8::CreateDevice(LPVOID _this, REFGUID rguid, LPDIRECTINPUTDEVICE8A * lplpDirectInputDevice, LPUNKNOWN pUnkOuter)
{
if (rguid == GUID_SysKeyboard)
{
// info(true, V("DirectInput8::CreateDevice: Device is keyboard"));
}
else if (rguid == GUID_SysMouse)
{
// info(true, V("DirectInput8::CreateDevice: Device is mouse"));
}
else if (rguid == GUID_Joystick)
{
// info(true, V("DirectInput8::CreateDevice: Device is joypad"));
}
*lplpDirectInputDevice = (LPDIRECTINPUTDEVICE8A)pFakeDevice;
if (pUnkOuter)
{
pUnkOuter = (LPUNKNOWN)NULL;
}
return DI_OK;
}
HRESULT HookIDirectInput8::EnumDevices(LPVOID _this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags)
{
return DI_OK;
}
HRESULT HookIDirectInput8::GetDeviceStatus(LPVOID _this, REFGUID rguidInstance)
{
return DI_OK;
}
HRESULT HookIDirectInput8::RunControlPanel(LPVOID _this, HWND hwndOwner, DWORD dwFlags)
{
return DIERR_UNSUPPORTED;
}
HRESULT HookIDirectInput8::Initialize(LPVOID _this, HINSTANCE hinst, DWORD dwVersion)
{
return DI_OK;
}
HRESULT HookIDirectInput8::FindDevice(LPVOID _this, REFGUID rguidClass, LPCTSTR ptszName, LPGUID pguidInstance)
{
return DI_OK;
}
HRESULT HookIDirectInput8::EnumDevicesBySemantics(LPVOID _this, LPCTSTR ptszUserName, LPDIACTIONFORMAT lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCB lpCallback, LPVOID pvRef, DWORD dwFlags)
{
return DI_OK;
}
HRESULT HookIDirectInput8::ConfigureDevices(LPVOID _this, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMS lpdiCDParams, DWORD dwFlags, LPVOID pvRefData)
{
return DI_OK;
}
HRESULT __stdcall Hook_DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID * ppvOut, LPUNKNOWN punkOuter)
{
*ppvOut = (LPVOID)pFakeInterface;
return DI_OK;
}
static InitFunction initFunc([]()
{
MH_Initialize();
MH_CreateHookApi(L"DINPUT8.dll", "DirectInput8Create", &Hook_DirectInput8Create, (void**)&__DirectInput8Create);
MH_EnableHook(MH_ALL_HOOKS);
});
#pragma optimize("", on)

View File

@ -0,0 +1,238 @@
#pragma optimize("", off)
#include <StdInc.h>
#include "Utility/GameDetect.h"
#include "Utility/InitFunction.h"
#include "Functions/Global.h"
#if _M_IX86
using namespace std::string_literals;
void AddCommOverride(HANDLE hFile);
static HANDLE __stdcall CreateFileAWrap(LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (GameDetect::X2Type == X2Type::BG4 && lpFileName[1] == ':' && lpFileName[2] == '\\')
{
lpFileName += 3;
}
if (strnicmp(lpFileName, "D:\\", 3) == 0)
{
if (GetFileAttributesA(lpFileName) == INVALID_FILE_ATTRIBUTES)
{
wchar_t pathRoot[MAX_PATH];
GetModuleFileNameW(GetModuleHandle(nullptr), pathRoot, _countof(pathRoot));
wcsrchr(pathRoot, L'\\')[0] = L'\0';
// assume just ASCII
std::string fn = lpFileName;
std::wstring wfn(fn.begin(), fn.end());
CreateDirectoryW((pathRoot + L"\\TeknoParrot\\"s).c_str(), nullptr);
return CreateFileW((pathRoot + L"\\TeknoParrot\\"s + wfn.substr(3)).c_str(),
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
}
if (GameDetect::X2Type == X2Type::BG4 || GameDetect::X2Type == X2Type::VRL)
{
if (strncmp(lpFileName, "COM1", 4) == 0)
{
HANDLE hFile = (HANDLE)0x8001;
AddCommOverride(hFile);
return hFile;
}
}
return CreateFileA(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
#include <deque>
static std::map<HANDLE, std::deque<BYTE>> g_replyBuffers;
static BOOL __stdcall ReadFileWrap(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped)
{
if (hFile == (HANDLE)0x8001)
{
auto& outQueue = g_replyBuffers[hFile];
int toRead = min(outQueue.size(), nNumberOfBytesToRead);
std::copy(outQueue.begin(), outQueue.begin() + toRead, reinterpret_cast<uint8_t*>(lpBuffer));
outQueue.erase(outQueue.begin(), outQueue.begin() + toRead);
*lpNumberOfBytesRead = toRead;
return TRUE;
}
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
static DWORD __stdcall GetFileAttributesAWrap(LPCSTR lpFileName)
{
if (GameDetect::X2Type == X2Type::BG4 && lpFileName[1] == ':' && lpFileName[2] == '\\')
{
lpFileName += 3;
}
return GetFileAttributesA(lpFileName);
}
extern int* wheelSection;
BOOL __stdcall WriteFileWrap(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
{
if (hFile == (HANDLE)0x8001)
{
DWORD pos = 0;
char bytes[2] = { 0 };
uint8_t* taskBuffer = (uint8_t*)lpBuffer;
while (pos < nNumberOfBytesToWrite)
{
switch (taskBuffer[pos])
{
case 0x20:
g_replyBuffers[hFile].push_back(1);
pos += 2;
break;
case 0x1F:
case 0x00:
case 0x04:
{
int wheelValue = *wheelSection;
if (GameDetect::X2Type == X2Type::VRL)
{
wheelValue = 255 - wheelValue;
}
wheelValue = (int)((wheelValue / 256.0f) * 1024.0f);
wheelValue += 1024;
g_replyBuffers[hFile].push_back(HIBYTE(wheelValue));
g_replyBuffers[hFile].push_back(LOBYTE(wheelValue));
pos += 2;
break;
}
default:
pos += 2;
break;
}
}
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return TRUE;
}
return WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}
static InitFunction initFunction([]()
{
DWORD imageBase = (DWORD)GetModuleHandleA(0);
if (GameDetect::X2Type == X2Type::None)
{
return;
}
iatHook("kernel32.dll", CreateFileAWrap, "CreateFileA");
switch (GameDetect::X2Type)
{
case X2Type::VRL:
{
//injector::MakeNOP(0x0040E22E, 2, true);
injector::WriteMemory<DWORD>(0x0041C800, 0x08C2C033, true);
injector::WriteMemory<BYTE>(0x0041C804, 0x00, true);
iatHook("kernel32.dll", ReadFileWrap, "ReadFile");
iatHook("kernel32.dll", WriteFileWrap, "WriteFile");
break;
}
case X2Type::Raiden4:
{
//injector::WriteMemory<uint32_t>(0x49DDB0, 0xC3C301B0, true);
injector::WriteMemory<BYTE>(0x00496EA0, 0xEB, true);
break;
}
case X2Type::BG4:
{
injector::MakeNOP(0x4CBCB8, 10);
injector::WriteMemory<uint8_t>(0x4CBCB8, 0xB8, true);
injector::WriteMemory<uint32_t>(0x4CBCB9, 1, true);
if (!ToBool(config["General"]["Windowed"]))
{
injector::MakeRET(0x5F21B0, 4);
}
iatHook("kernel32.dll", ReadFileWrap, "ReadFile");
iatHook("kernel32.dll", WriteFileWrap, "WriteFile");
iatHook("kernel32.dll", GetFileAttributesAWrap, "GetFileAttributesA");
break;
}
case X2Type::Lupin3:
{
injector::MakeNOP(0x48C66C, 12);
break;
}
}
if(GameDetect::currentGame == GameID::KOFMIRA)
{
injector::WriteMemory<DWORD>(0x0040447C, 0x000800B8, true);
injector::WriteMemory<WORD>(0x0040447C+4, 0x9000, true);
}
if(GameDetect::currentGame == GameID::TetrisGM3)
{
injector::WriteMemory<DWORD>(0x0046A0AC, 0x00005C2E, true);
}
if(GameDetect::currentGame == GameID::SamuraiSpiritsSen)
{
injector::WriteMemory<DWORD>(0x0040117A, 0x90909090, true);
injector::WriteMemory<BYTE>(0x0040117A+4, 0x90, true);
injector::WriteMemory<WORD>(0x00401188, 0x9090, true);
injector::WriteMemory<WORD>(0x004B73DE, 0x9090, true);
injector::WriteMemory<BYTE>(0x004B73ED, 0xEB, true);
injector::WriteMemory<BYTE>(0x004C640C, 0xEB, true);
injector::WriteMemory<DWORD>(0x004CE1C0, 0xC340C033, true);
}
});
#endif
#pragma optimize("", on)

View File

@ -0,0 +1,197 @@
#include <StdInc.h>
#include <Utility/InitFunction.h>
#include "Global.h"
DWORD dongleRegion = 1;
BYTE pcbModelType = 2;
DWORD sysCRC;
char dongleGameId[4];
#pragma optimize("", off)
void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3)
{
__try
{
memcpy(a1, a2, a3);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return 0;
}
// used in SR3 and Ford Racing
BOOL WINAPI ReadFileHooked(_In_ HANDLE hFile, _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer, _In_ DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead, _Inout_opt_ LPOVERLAPPED lpOverlapped)
{
static HANDLE file = CreateFileA("\\\\.\\pipe\\TeknoParrotPipe", GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, NULL);
ReadFile(file, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
return TRUE;
}
std::wstring utf8_decode(const std::string &str)
{
if (str.empty()) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
DWORD WINAPI QuitGameThread(__in LPVOID lpParameter)
{
while (true)
{
if (GetAsyncKeyState(VK_ESCAPE))
{
#ifndef _DEBUG
TerminateProcess(GetCurrentProcess(), 0);
#endif
//ExitProcess(0);
}
Sleep(300);
}
}
/* WINDOW HOOKS */
DWORD g_windowStyle;
int g_x = 0;
int g_y = 0;
int g_width = 0;
int g_height = 0;
HWND hwndWindowA;
HWND hwndWindowW;
HWND WINAPI CreateWindowExAHk(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
#ifdef _DEBUG
info(true, "CreateWindowExAHk called");
#endif
if (lpWindowName)
{
dwStyle = g_windowStyle;
}
HWND thisWindow = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, g_x, g_y, g_width, g_height, hWndParent, hMenu, hInstance, lpParam);
if (lpWindowName)
{
hwndWindowA = thisWindow;
}
return thisWindow;
}
HWND WINAPI CreateWindowExWHk(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
#ifdef _DEBUG
info(true, "CreateWindowExWHk called");
#endif
if (lpWindowName)
{
dwStyle = g_windowStyle;
}
HWND thisWindow = CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, g_x, g_y, g_width, g_height, hWndParent, hMenu, hInstance, lpParam);
if (lpWindowName)
{
hwndWindowW = thisWindow;
}
return thisWindow;
}
BOOL WINAPI AdjustWindowRectHk(LPRECT lpRect, DWORD dwStyle, BOOL bMenu)
{
#ifdef _DEBUG
info(true, "AdjustWindowRectHk called");
#endif
dwStyle = g_windowStyle;
return AdjustWindowRect(lpRect, dwStyle, bMenu);
}
BOOL WINAPI SetWindowPosHk(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
#ifdef _DEBUG
info(true, "SetWindowPosHk called");
#endif
if (hwndWindowA == hWnd || hwndWindowW == hWnd)
{
X = g_x;
Y = g_y;
}
return SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
}
LONG __stdcall ChangeDisplaySettingsHk(DEVMODEA *lpDevMode, DWORD dwFlags)
{
#ifdef _DEBUG
info(true, "ChangeDisplaySettingsHk called");
#endif
lpDevMode = NULL; // retain original changes instead of applying modified values
return ChangeDisplaySettingsA(lpDevMode, dwFlags);
}
BOOL WINAPI UpdateWindowHk(HWND hWnd)
{
return true;
}
void init_windowHooks(windowHooks* data)
{
g_windowStyle = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
int rx, ry;
GetDesktopResolution(rx, ry);
g_x = (rx / 2) - (g_width / 2);
g_y = (ry / 2) - (g_height / 2);
if (data->createWindowExA != NULL)
{
*(HWND*)data->createWindowExA = (HWND)CreateWindowExAHk;
}
if (data->createWindowExW != NULL)
{
*(HWND*)data->createWindowExW = (HWND)CreateWindowExWHk;
}
if (data->adjustWindowRect != NULL)
{
*(BOOL*)data->adjustWindowRect = (BOOL)AdjustWindowRectHk;
}
if (data->setWindowPos != NULL)
{
*(BOOL*)data->setWindowPos = (BOOL)SetWindowPosHk;
}
if (data->changeDisplaySettings != NULL)
{
*(LONG*)data->changeDisplaySettings = (LONG)ChangeDisplaySettingsHk;
}
if (data->updateWindow != NULL)
{
*(BOOL*)data->updateWindow = (BOOL)UpdateWindowHk;
}
}
/* END WINDOW HOOKS */
static InitFunction globalFunc([]()
{
CreateThread(NULL, 0, QuitGameThread, NULL, 0, NULL);
}, GameID::Global);
#pragma optimize("", on)

View File

@ -0,0 +1,103 @@
#pragma once
BOOL WINAPI ReadFileHooked(_In_ HANDLE hFile, _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer, _In_ DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead, _Inout_opt_ LPOVERLAPPED lpOverlapped);
void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3);
struct windowHooks
{
int createWindowExA;
int createWindowExW;
int adjustWindowRect;
int setWindowPos;
int changeDisplaySettings;
int updateWindow;
};
void init_windowHooks(windowHooks* data);
std::wstring utf8_decode(const std::string &str);
namespace
{
template<typename T>
inline T* getRVA(uintptr_t rva)
{
return (T*)((char*)GetModuleHandle(nullptr) + rva);
}
template<typename TOrdinal>
inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, TOrdinal ordinal)
{
}
template<>
inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, int ordinal)
{
if (IMAGE_SNAP_BY_ORDINAL(*nameTableEntry))
{
return IMAGE_ORDINAL(*nameTableEntry) == ordinal;
}
return false;
}
template<>
inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, const char* ordinal)
{
if (!IMAGE_SNAP_BY_ORDINAL(*nameTableEntry))
{
auto import = getRVA<IMAGE_IMPORT_BY_NAME>(*nameTableEntry);
return !_stricmp(import->Name, ordinal);
}
return false;
}
}
template<typename T, typename TOrdinal>
T iatHook(const char* moduleName, T function, TOrdinal ordinal)
{
IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(GetModuleHandle(nullptr));
IMAGE_NT_HEADERS* ntHeader = getRVA<IMAGE_NT_HEADERS>(imageHeader->e_lfanew);
IMAGE_IMPORT_DESCRIPTOR* descriptor = getRVA<IMAGE_IMPORT_DESCRIPTOR>(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (descriptor->Name)
{
const char* name = getRVA<char>(descriptor->Name);
if (_stricmp(name, moduleName))
{
descriptor++;
continue;
}
if (descriptor->OriginalFirstThunk == 0)
{
return nullptr;
}
auto nameTableEntry = getRVA<uintptr_t>(descriptor->OriginalFirstThunk);
auto addressTableEntry = getRVA<uintptr_t>(descriptor->FirstThunk);
while (*nameTableEntry)
{
if (iat_matches_ordinal(nameTableEntry, ordinal))
{
T origEntry = (T)*addressTableEntry;
injector::WriteMemory(addressTableEntry, (uintptr_t)function, true);
return origEntry;
}
nameTableEntry++;
addressTableEntry++;
}
return nullptr;
}
return nullptr;
}

View File

@ -0,0 +1,311 @@
#include <StdInc.h>
#if _M_IX86
#include "CryptoPipe.h"
#include <wincrypt.h>
#pragma comment(lib, "Advapi32.lib")
// TODO: NEED TO BE PLACED IN FILES!
const char *key_magicalbeat = "0702000000A40000525341320002000001000100411FE010238446E4C51A60E182DD275B6C1D35DE1B3B1392C7F9A70DFB01C8BF2309CC85E74D88ECE52041F985D785BB7CBD3F3A8BFC89E8D2A5A8440796CDD2BD2B2D5FB954F36193AA685E568DC940284E45BBDDFF89E721EBBF670362F8F6D5D73B0CAA16AD31C8F819A0936FAB11BB11A855C213D9C583A8621A97AE82DA7108DC76DAB389CD14A5E577C5E9A1908A0D0EF56A3FE1AA0F6103450F4650C8218FC47412A3ADBDD146E68E5FC49D4D64AD28641941FC6FD057DE15233BAD288FA032390566E9B4FFED0B9F5A31A2A587B3F68405BF1A3A79AE05BA256C8C2C81ADBD14DFAA8EF774684AD6D606574BB426DF079270A0A333E65B281D6FECD260D618F32475ACE360DE3A8CB6540192A94FA00E01109F77BBA9709428C2E3A3";
const char *key_bbcf = "0702000000a400005253413200020000010001008f35cf7db98ccacf0e4586b2bc2816911e6629328edd4678424312e1c698e4a8341232da9a37ef7fe4257185522b618b49d3939b8e83b1a591e0c06d5d0223c50da989e3ab190e4b989ebaee4d04428a00bfb6e7840f17a5e7f6c2e8d5e776eb0b3af84ad026ef84cb69e8e7933a5a99342018764317a73780507cdb5b6154d629b8da775bb09b132e3dfac255b771863809acfa64fea8f07a94801096d9046955d8729eb98779f8561fdf8f6531ad051546aacd74702f486e456e3c0361346ed6033004ee562885912cafdd91d9a4844d267437eee304b4f06c46b75bbe972b31a414972fdb5e0a69999734685e54598f0565f9afc0cd162434fb9d37e983154fefb3080f8ff41ff9be8596fa4042b96a441f6b1f8eb416c127a57f256ff055";
const char *key_persona4arena = "0702000000A40000525341320002000001000100359073C4EF2B8E9556FFDED09E5E1C4374169BA2A2077E9993C34E7FB3B499D9624F620018AFAEEED697D7E72432B488E8E4A2A1B648EE24C9E878D9145A36D87F39DFCFD4AA3751C70039DFB4CE022A85A81D7440287538A41EB3B3D9A0F0FD4B481E274B71AF8BDD36AC6F7A930CC67E41BE6E65628A50F3779082555FF7D97FB45E4D6973BEB316D220BC45E2F20FBD1FD9271CEA65AC14B09136D99A31A179CE1933F5343FE930D858769FD7B861C7BF3ECC187792A9C200856822C1AB2138628CB7183DBCE115589A4A0F213FD77B91758D13D762714666B97A428723895512E57C29AB3C68113120D7CB3269A605AC483601BD6B1BDAC238759D564EA6DA64A445FC502251FBEAA2621BD157040C60637371096A6B261D0FCB767F9F7C";
const char *key_bbcp = "0702000000a400005253413200020000010001008f35cf7db98ccacf0e4586b2bc2816911e6629328edd4678424312e1c698e4a8341232da9a37ef7fe4257185522b618b49d3939b8e83b1a591e0c06d5d0223c50da989e3ab190e4b989ebaee4d04428a00bfb6e7840f17a5e7f6c2e8d5e776eb0b3af84ad026ef84cb69e8e7933a5a99342018764317a73780507cdb5b6154d629b8da775bb09b132e3dfac255b771863809acfa64fea8f07a94801096d9046955d8729eb98779f8561fdf8f6531ad051546aacd74702f486e456e3c0361346ed6033004ee562885912cafdd91d9a4844d267437eee304b4f06c46b75bbe972b31a414972fdb5e0a69999734685e54598f0565f9afc0cd162434fb9d37e983154fefb3080f8ff41ff9be8596fa4042b96a441f6b1f8eb416c127a57f256ff055";
const char *key_kofxiiiclimax = "0702000000A400005253413200020000010001000D20722B0858DCFAE9783F33E67BED82A0C1A3FE17FBB733B056A2337ADA9DAAE028079B07EE25CBCC9C2B72AA6154CEEF898C8CA9F168684D9A3806D6F622D4FF5CFFDDA03325FD7322D1CBF9CD8E45773E116B353871EEF7E5DCAAE3DCE1F8F326C1922DE4B76F1DD075DB788D67B6719126FBB2497FA0CB855F56651334DA152F3AED5D8A53C92A83F08177535B44420FEB2617E932791DC9DB0A26250755FDC37B74BCFF5DDDFDB2E52AE59D7E52042A022D37A9D73339ECA29F0DF60C1F792BCB25A3BCC5ED53D6A0DA2D403246C12EA958C4F5DAE9FFA0D10B7C31ECC3E5DC9A2418104B3A7825FBC527177EE00056176A3176323DE62CC834D36095D26CC9841D331A72814FE0D04BCE0B3A666C6896E0571E77323D5B6797B20168B9";
const char *key_persona4ultimix = "0702000000a40000525341320002000001000100359073c4ef2b8e9556ffded09e5e1c4374169ba2a2077e9993c34e7fb3b499d9624f620018afaeeed697d7e72432b488e8e4a2a1b648ee24c9e878d9145a36d87f39dfcfd4aa3751c70039dfb4ce022a85a81d7440287538a41eb3b3d9a0f0fd4b481e274b71af8bdd36ac6f7a930cc67e41be6e65628a50f3779082555ff7d97fb45e4d6973beb316d220bc45e2f20fbd1fd9271cea65ac14b09136d99a31a179ce1933f5343fe930d858769fd7b861c7bf3ecc187792a9c200856822c1ab2138628cb7183dbce115589a4a0f213fd77b91758d13d762714666b97a428723895512e57c29ab3c68113120d7cb3269a605ac483601bd6b1bdac238759d564ea6da64a445fc502251fbeaa2621bd157040c60637371096a6b261d0fcb767f9f7c";
const char *key_usf4 = "0702000000a40000525341320002000001000100b77cb7dfef27ca5ed4895576c6a68518bab782e60dae9dffad94434fb9366125e46630352261afe960e8401a3c5ee1cfc15ec2b1849e02a3dcc30e47ea3100a5c7175f9207aab497a9c9c0bf19d30a9fbb294a761147607927163685624dced391d3ae2211c6c11350077070386a195a8641f0e7920ddbcb200f990f55c76dc73de119d62751e5cb6cfa3653481d3e711b666c9a6cc9c2a4e50f4e55ce2831a821d75448cda3a2d6f3b359012bff571842c34a844989a4af0a4a5081cb8dc0780173865658cd8b999f9baaa3febc9c95b1477cd6af5060af603e597b3547fd0021a422c3a2cd0028523b5bd12b23bd4a6d2924ca920870cba2f38477631589cc4251590fba955d114f2ce0d6228c4932c1f2d9b753cda2d646591c48e164820e";
DWORD dword_44DEC4;
DWORD dword_44DEC0;
void LogStuff(const char* text, int a)
{
//printf("%s", text);
}
DWORD LinkRC5Data(const char* file, void* buf, int gameId)
{
DWORD num = 0;
char key[308];
if (!buf)
return 308;
switch (gameId)
{
case 0:
for (int i = 0; i < 308; i++)
{
sscanf(&key_magicalbeat[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 1:
for (int i = 0; i < 308; i++)
{
sscanf(&key_bbcf[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 2:
for (int i = 0; i < 308; i++)
{
sscanf(&key_persona4arena[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 3:
for (int i = 0; i < 308; i++)
{
sscanf(&key_bbcp[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 4:
for (int i = 0; i < 308; i++)
{
sscanf(&key_kofxiiiclimax[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 5:
for (int i = 0; i < 308; i++)
{
sscanf(&key_persona4ultimix[i * 2], "%02x", &num);
key[i] = num;
}
break;
case 6:
for (int i = 0; i < 308; i++)
{
sscanf(&key_usf4[i * 2], "%02x", &num);
key[i] = num;
}
break;
default:
break;
}
memcpy(buf, key, 308);
return 308;
}
HCRYPTPROV GenerateKey()
{
HCRYPTPROV result; // eax@2
HCRYPTPROV phProv; // [sp+4h] [bp-4h]@1
phProv = 0;
if (CryptAcquireContextA(&phProv, "TypeXAppCrypt", "Microsoft Base Cryptographic Provider v1.0", 1u, 0)
|| (result = CryptAcquireContextA(&phProv, "TypeXAppCrypt", "Microsoft Base Cryptographic Provider v1.0", 1u, CRYPT_NEWKEYSET)) != 0)
{
result = phProv;
}
return result;
}
bool __cdecl ReadFromPipe_410390(HANDLE hPipe, BYTE** a2, DWORD* a3, bool* pMode)
{
signed int dwSizeBytePos; // esi@1
int dwAllocSizeState; // ebp@1
char i; // bl@2
DWORD dwLastError; // eax@4
//unsigned __int16 v8; // dx@16
int dwAllocSize; // ebp@18
HANDLE hHeap1; // eax@18
BYTE *pResultBuffer; // esi@18
bool bResult; // al@19
HANDLE hHeap2; // eax@21
int v14 = 0; // [sp+0h] [bp-18h]@0
unsigned char Buffer; // [sp+13h] [bp-5h]@3
DWORD NumberOfBytesRead; // [sp+14h] [bp-4h]@3
dwSizeBytePos = 0;
dwAllocSizeState = 0;
while (true)
{
for (i = 0;; i = 1)
{
do
{
readByteLabel:
if (ReadFile(hPipe, &Buffer, 1u, &NumberOfBytesRead, 0))
break;
dwLastError = GetLastError();
if (dwLastError == ERROR_BROKEN_PIPE)
return false;
} while (dwLastError != ERROR_IO_PENDING);
if (Buffer != 0xFF)
break;
if (i)
{
i = 0;
goto LABEL_9;
}
}
if ((Buffer == 0xFE || Buffer == 0xFD) && i)
{
*pMode = Buffer != 0xFE;
dwSizeBytePos = 1;
continue;
}
break;
}
LABEL_9:
switch (dwSizeBytePos)
{
case 1:
dwAllocSizeState |= Buffer;
++dwSizeBytePos;
goto readByteLabel;
case 2:
dwAllocSizeState |= Buffer << 8;
++dwSizeBytePos;
goto readByteLabel;
case 3:
dwAllocSizeState |= Buffer << 16;
++dwSizeBytePos;
goto readByteLabel;
case 4:
dwAllocSize = (Buffer << 24) | dwAllocSizeState;
hHeap1 = GetProcessHeap();
pResultBuffer = (BYTE*)HeapAlloc(hHeap1, 0, dwAllocSize);
if (!pResultBuffer)
{
//LogStuff("Heap Allo\n", v14);
return false;
}
if (!ReadFile(hPipe, pResultBuffer, dwAllocSize, &NumberOfBytesRead, 0))
{
hHeap2 = GetProcessHeap();
HeapFree(hHeap2, 0, pResultBuffer);
return false;
}
*a3 = dwAllocSize;
*a2 = pResultBuffer;
bResult = true;
break;
default:
goto readByteLabel;
}
return bResult;
}
HANDLE PipeStuff_410550(int gameId)
{
HANDLE result; // eax@1
HANDLE hPipe; // edi@1
DWORD dwRC5DataLen; // esi@4
unsigned __int8 *pRC5DataBuf; // ebx@4
BYTE *pbDataTemp; // esi@12
HANDLE hHeap1; // eax@12
BYTE *v6; // esi@13
HANDLE hHeap2; // eax@13
DWORD v8; // ST14_4@17
HANDLE hHeap3; // eax@17
BYTE *v10; // esi@17
HANDLE hHeap4; // eax@17
int v12 = 0; // [sp-Ch] [bp-38h]@1
char v13; // [sp+6h] [bp-26h]@6
bool bMode;
DWORD dwRead;
//char a4[5]; // [sp+7h] [bp-25h]@7
DWORD pdwDataLen; // [sp+Ch] [bp-20h]@15
HCRYPTKEY v16; // [sp+10h] [bp-1Ch]@9
HCRYPTPROV hProv; // [sp+14h] [bp-18h]@3
HCRYPTKEY hKey; // [sp+18h] [bp-14h]@11
DWORD dwDataLen; // [sp+1Ch] [bp-10h]@7
BYTE *pbData; // [sp+20h] [bp-Ch]@7
int Buffer; // [sp+24h] [bp-8h]@8
HCRYPTKEY phKey; // [sp+28h] [bp-4h]@4
hProv = GenerateKey();
result = CreateNamedPipeA("\\\\.\\pipe\\TtxAppCtyptPipe", PIPE_ACCESS_DUPLEX, PIPE_WAIT, 1u, 0x400u, 0x400u, 1000u, 0);
hPipe = result;
if (result != INVALID_HANDLE_VALUE)
{
dwRC5DataLen = LinkRC5Data("C:\\windows\\system32\\8B97D021-071D-45dd-A592-0ABB3BAEF01A", 0, gameId);
pRC5DataBuf = (unsigned __int8 *)malloc(dwRC5DataLen);
LinkRC5Data("C:\\windows\\system32\\8B97D021-071D-45dd-A592-0ABB3BAEF01A", pRC5DataBuf, gameId);
result = (HANDLE)CryptImportKey(hProv, pRC5DataBuf, dwRC5DataLen, 0, 0, &phKey);
if (result)
{
dword_44DEC0 = 1;
ConnectNamedPipe(hPipe, 0);
v13 = 0;
while (true)
{
while (!ReadFromPipe_410390(hPipe, &pbData, &dwDataLen, &bMode))
{
Buffer = 0;
WriteFile(hPipe, &Buffer, 4u, &dwRead, 0);
DisconnectNamedPipe(hPipe);
ConnectNamedPipe(hPipe, 0);
}
//LogStuff("Recieved.\n", v12);
v16 = 0;
if (bMode)
{
if (v13)
CryptDestroyKey(hKey);
pbDataTemp = pbData;
CryptImportKey(hProv, pbData, dwDataLen, 0, 0, &hKey);
v13 = 1;
hHeap1 = GetProcessHeap();
HeapFree(hHeap1, 0, pbDataTemp);
}
else
{
v6 = pbData;
Buffer = CryptImportKey(hProv, pbData, dwDataLen, phKey, 1u, &v16);
hHeap2 = GetProcessHeap();
HeapFree(hHeap2, 0, v6);
if (Buffer)
{
if (CryptExportKey(v16, hKey, 1u, 0, 0, &pdwDataLen))
{
v8 = pdwDataLen;
hHeap3 = GetProcessHeap();
v10 = (BYTE *)HeapAlloc(hHeap3, 0, v8);
CryptExportKey(v16, hKey, 1u, 0, v10, &pdwDataLen);
WriteFile(hPipe, &pdwDataLen, 4u, &dwRead, 0);
WriteFile(hPipe, v10, pdwDataLen, &dwRead, 0);
hHeap4 = GetProcessHeap();
HeapFree(hHeap4, 0, v10);
}
else
{
Buffer = 0;
//LogStuff("It failed in the export of the key. \n", v12);
WriteFile(hPipe, &Buffer, 4u, &dwRead, 0);
}
if (v16)
CryptDestroyKey(v16);
}
else
{
Buffer = 0;
//LogStuff("It failed in the import of the key. \n", v12);
WriteFile(hPipe, &Buffer, 4u, &dwRead, 0);
}
}
}
}
dword_44DEC0 = 2;
}
else
{
dword_44DEC0 = 2;
}
return result;
}
unsigned long __stdcall TXAppCryptThread(LPVOID sId)
{
int id = *static_cast<int*>(sId);
PipeStuff_410550(id);
delete sId;
return 1;
}
void init_CryptoPipe(NesicaKey id)
{
static NesicaKey gameId = id;
CreateThread(nullptr, 0, TXAppCryptThread, &gameId, 0, nullptr);
}
#endif

View File

@ -0,0 +1,14 @@
#pragma once
enum class NesicaKey
{
None = -1,
MagicalBeat = 0,
BlazBlueCentralFriction = 1,
Persona4Arena = 2,
BlazBlueChronoPhantasma = 3,
KOFXIIIClimax = 4,
Persona4Ultimix = 5,
USF4 = 6
};
void init_CryptoPipe(NesicaKey id);

View File

@ -0,0 +1,251 @@
#include <StdInc.h>
#include "Utility/InitFunction.h"
#include <thread>
static uint8_t g_fastIOValues[64];
DWORD __cdecl iDmacDrvOpen(int deviceId, LPVOID outBuffer, LPVOID lpSomeFlag)
{
*(DWORD*)outBuffer = 284;
*(DWORD*)lpSomeFlag = 0;
#ifdef LogFastIO
info(true, "iDmacDrvOpen(deviceId=%d, outBuffer='%08X', lpSomeFlag=%08X) -> result=%08X", deviceId, *(DWORD*)outBuffer, *(DWORD*)lpSomeFlag, 0);
info(true, "--------------------------------------------");
#endif
return 0;
}
DWORD __cdecl iDmacDrvClose(int deviceId, LPVOID lpWriteAccess)
{
#ifdef LogFastIO
info(true, "iDmacDrvClose(deviceId=%d, lpWriteAccess='%08X') -> result=%08X", deviceId, lpWriteAccess, 0);
info(true, "--------------------------------------------");
#endif
return 0;
}
int __cdecl iDmacDrvDmaRead(int a1, LPVOID lp, UINT_PTR ucb, LPVOID a4)
{
return 0;
}
int __cdecl iDmacDrvDmaWrite(int a1, void *lp, UINT_PTR ucb, LPVOID a4)
{
return 0;
}
int __cdecl iDmacDrvRegisterRead(int DeviceId, DWORD CommandCode, LPVOID OutBuffer, LPVOID DeviceResult)
{
DWORD result = 0;
switch (CommandCode)
{
case 0x400:
{
result = 0x00010201;
break;
}
case 0x4000:
result = 0x00FF00FF;
break;
case 0x4004:
// 0x00FF0000;
result = 0x00FF0000;
break;
case 0x4120:
// 0x00000010;
//result = FourPackage;
result = g_fastIOValues[0] + ((DWORD)g_fastIOValues[1] * 0x100) + ((DWORD)g_fastIOValues[2] * 0x10000) + ((DWORD)g_fastIOValues[3] * 0x1000000);
break;
case 0x412C:
// 0x00000001;
result = 0x00000000;
break;
case 0x41A4:
case 0x4124:
// 0x01100000;
result = 0x01100000;
break;
case 0x4140:
case 0x41C0:
result = g_fastIOValues[4];
// For coin not getting stuck. One ping is enough.
//result = CoinPackage;
//if (result != 0)
// CoinPackage = 0;
break;
case 0x4144:
case 0x41C4:
result = g_fastIOValues[5];
// Dual Fast I/O use, not emu'd atm.
//result = CoinPackageSecond;
//if (result != 0)
// CoinPackageSecond = 0;
break;
case 0x41A0:
result = 0;
break;
case 0x41A8:
result = 0;
break;
case 0x4128:
result = g_fastIOValues[8];
result += g_fastIOValues[9] * 0x100;
//result = 0x00FF00FF;
break;
case 0x41AC:
result = 0;
break;
case 0x4180:
result = 0;
break;
case 0x4108:
result = 0;
break;
}
*(DWORD*)OutBuffer = result;
*(DWORD*)DeviceResult = 0;
#ifdef LogFastIO
info(true, "iDmacDrvRegisterRead(DeviceId=%d, CommandCode=%08X, OutBuffer=%08X, DeviceResult=%08X) -> result=%08X", DeviceId, CommandCode, *(DWORD*)OutBuffer, *(DWORD*)DeviceResult, 0);
info(true, "--------------------------------------------");
#endif
return 0;
}
int __cdecl iDmacDrvRegisterWrite(int deviceId, DWORD CommandCode, int unused, DWORD *DeviceResult)
{
#ifdef LogFastIO
info(true, "iDmacDrvRegisterWrite(deviceId=%d, CommandCode='%08X', unused=%08X, DeviceResult=%08X) -> result=%08X", deviceId, CommandCode, unused, *(DWORD*)DeviceResult, 0);
info(true, "--------------------------------------------");
#endif
if (CommandCode <= 0x4100)
{
if (CommandCode != 0x4100 && CommandCode != 0x4000 && CommandCode != 0x4004)
return 0;
*DeviceResult = -1;
return 0;
}
if (CommandCode > 0x410C)
{
switch (CommandCode)
{
case 0x4180:
case 0x4184:
case 0x4188:
case 0x418C:
case 0x410C:
case 0x4104:
{
*DeviceResult = -1;
return 0;
}
case 0x4108:
default:
return 0;
}
}
*DeviceResult = -1;
return 0;
}
int __cdecl iDmacDrvRegisterBufferRead(int a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, LPVOID a5)
{
return 0;
}
int __cdecl iDmacDrvRegisterBufferWrite(int a1, DWORD BytesReturned, void *lp, UINT_PTR ucb, LPVOID a5)
{
return 0;
}
int __cdecl iDmacDrvMemoryRead(int a1, DWORD BytesReturned, LPVOID lp, LPVOID a4)
{
return 0;
}
int __cdecl iDmacDrvMemoryWrite(int a1, DWORD BytesReturned, int a3, LPVOID lp)
{
return 0;
}
int __cdecl iDmacDrvMemoryReadExt(int a1, DWORD BytesReturned, int a3, LPVOID lp, DWORD nOutBufferSize, LPVOID a6)
{
return 0;
}
int __cdecl iDmacDrvMemoryWriteExt(int a1, int a2, int a3, void *Src, rsize_t DstSize, LPVOID lp)
{
return 0;
}
int __cdecl iDmacDrvMemoryBufferRead(int a1, DWORD BytesReturned, LPVOID lp, UINT_PTR ucb, LPVOID a5)
{
return 0;
}
int __cdecl iDmacDrvMemoryBufferWrite(int a1, int a2, void *lp, UINT_PTR ucb, LPVOID a5)
{
return 0;
}
void init_FastIoEmu()
{
MH_Initialize();
#if _M_IX86
const char* libName = "idmacdrv32.dll";
if((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryBufferWrite") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryBufferWrite"), iDmacDrvMemoryBufferWrite);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryBufferRead") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryBufferRead"), iDmacDrvMemoryBufferRead);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryWriteExt") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryWriteExt"), iDmacDrvMemoryWriteExt);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryReadExt") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryReadExt"), iDmacDrvMemoryReadExt);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryWrite") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryWrite"), iDmacDrvMemoryWrite);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryRead") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvMemoryRead"), iDmacDrvMemoryRead);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvRegisterBufferWrite") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvRegisterBufferWrite"), iDmacDrvRegisterBufferWrite);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvRegisterBufferRead") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvRegisterBufferRead"), iDmacDrvRegisterBufferRead);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvDmaWrite") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvDmaWrite"), iDmacDrvDmaWrite);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvDmaRead") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvDmaRead"), iDmacDrvDmaRead);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvClose") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvClose"), iDmacDrvClose);
if ((DWORD)GetProcAddress(GetModuleHandleA(libName), "iDmacDrvOpen") != 0)
injector::MakeJMP(GetProcAddress(GetModuleHandleA(libName), "iDmacDrvOpen"), iDmacDrvOpen);
#else
const wchar_t* libName = L"idmacdrv64.dll";
MH_CreateHookApi(libName, "iDmacDrvClose", &iDmacDrvClose, NULL);
MH_CreateHookApi(libName, "iDmacDrvOpen", &iDmacDrvOpen, NULL);
MH_CreateHookApi(libName, "iDmacDrvRegisterWrite", &iDmacDrvRegisterWrite, NULL);
MH_CreateHookApi(libName, "iDmacDrvRegisterRead", &iDmacDrvRegisterRead, NULL);
#endif
MH_EnableHook(MH_ALL_HOOKS);
memset(g_fastIOValues, 0, 64);
CreateThread(nullptr, 0, [] (LPVOID) -> DWORD
{
HANDLE hPipe = CreateFileA("\\\\.\\pipe\\TeknoParrotPipe", GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
DWORD read;
while (true)
{
ReadFile(hPipe, g_fastIOValues, sizeof(g_fastIOValues), &read, nullptr);
}
}
return 0;
}, nullptr, 0, nullptr);
}

View File

@ -0,0 +1,2 @@
#pragma once
void init_FastIoEmu();

View File

@ -0,0 +1,536 @@
#include "StdInc.h"
#include "NesysEmu.h"
//#if _M_IX86
#include "Utility/Utils.h"
#pragma optimize("", off)
NesysEmu::NesysEmu()
: m_initialized(false)
{
m_commandHandlers[LCOMMAND_CLIENT_START] = [=](const uint8_t* data, size_t length)
{
struct __declspec(align(4)) _LIBRARY_INFO
{
unsigned int pid;
char exePath[261];
char version[33];
};
const _LIBRARY_INFO* linfo = reinterpret_cast<const _LIBRARY_INFO*>(data);
#ifdef _DEBUG
info(true, "NESYS CLIENT START: pid %d, exePath %s, version %s", linfo->pid, linfo->exePath, linfo->version);
#endif
SendResponse(SCOMMAND_CLIENT_START_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_CONNECT_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_CONNECT_REPLY, nullptr);
Sleep(100);
// h
struct __declspec(align(4)) NESYS_TENPO_TABLE
{
int tenpo_id;
char tenpo_name[31];
char tenpo_addr[33];
char ticket[33];
char pref_name[17];
};
struct NESYS_NEWS_TABLE
{
int type;
int size;
char iFilePath[1024];
};
struct nesys_cert_init_response
{
NESYS_TENPO_TABLE tenpo;
NESYS_NEWS_TABLE news;
uint32_t serverSize;
char server[];
};
const char* wat = "card_id=42";
nesys_cert_init_response* response = (nesys_cert_init_response*)malloc(sizeof(nesys_cert_init_response) + strlen(wat));
response->tenpo.tenpo_id = 1337;
strcpy(response->tenpo.tenpo_name, "leet");
strcpy(response->tenpo.tenpo_addr, "l33t");
strcpy(response->tenpo.ticket, "teel");
strcpy(response->tenpo.pref_name, "t33l");
response->news.type = 0;
response->news.size = 1337;
strcpy(response->news.iFilePath, "/wat");
response->serverSize = strlen(wat);
memcpy(response->server, wat, strlen(wat));
SendResponse(SCOMMAND_CERT_INIT_NOTICE, response, sizeof(nesys_cert_init_response) + strlen(wat));
free(response);
};
m_commandHandlers[LCOMMAND_DISCONNECT_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_DISCONNECT_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_GAME_FREE_START_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_GAME_STATUS_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_GAME_FREE_END_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_GAME_STATUS_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_GAME_START_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_GAME_STATUS_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_GAME_END_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_GAME_STATUS_REPLY, nullptr);
};
// get card
m_commandHandlers[LCOMMAND_CARD_SELECT_REQUEST] = [=](const uint8_t* dataa, size_t length)
{
struct __declspec(align(4)) _CARD_GETDATA
{
char cardId[16];
unsigned int dataType;
unsigned int paramSize;
char param[1];
};
const _CARD_GETDATA* card = reinterpret_cast<const _CARD_GETDATA*>(dataa);
FILE* f = fopen(va("card_%.16s_%d.bin", card->cardId, card->dataType), "rb");
size_t dataSize = 0;
char data[16384];
if (f)
{
dataSize = fread(data, 1, 16384, f);
fclose(f);
data[dataSize] = '\0';
++dataSize;
}
struct cardstatus
{
uint32_t status;
uint32_t times;
uint32_t days;
uint32_t size;
char data[];
};
cardstatus* s = (cardstatus*)malloc(sizeof(cardstatus) + dataSize);
s->status = 1;
s->times = 0;
s->days = 0;
s->size = dataSize;
memcpy(s->data, data, s->size);
SendResponse(SCOMMAND_CARD_SELECT_REPLY, s, sizeof(cardstatus) + dataSize);
};
struct __declspec(align(4)) _CARD_SENDDATA
{
char cardId[16];
unsigned int frequency;
unsigned int transferMode;
unsigned int dataType;
unsigned int dataSize;
char data[1];
};
// new card
m_commandHandlers[LCOMMAND_CARD_INSERT_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct cardstatus
{
uint32_t status;
uint32_t times;
uint32_t days;
uint32_t size;
char data[];
};
cardstatus s;
s.status = 1;
s.times = 0;
s.days = 0;
s.size = 0;
SendResponse(SCOMMAND_CARD_INSERT_REPLY, &s);
};
// update card
m_commandHandlers[LCOMMAND_CARD_UPDATE_REQUEST] = [=](const uint8_t* data, size_t length)
{
const _CARD_SENDDATA* card = reinterpret_cast<const _CARD_SENDDATA*>(data);
FILE* f = fopen(va("card_%s_%d.bin", card->cardId, card->dataType), "wb");
if (f)
{
fwrite(card->data, 1, card->dataSize, f);
fclose(f);
}
struct cardstatus
{
uint32_t status;
uint32_t times;
uint32_t days;
uint32_t size;
char data[];
};
cardstatus* s = (cardstatus*)malloc(sizeof(cardstatus) + card->dataSize);
s->status = 1;
s->times = 0;
s->days = 0;
s->size = card->dataSize;
memcpy(s->data, card->data, s->size);
SendResponse(SCOMMAND_CARD_UPDATE_REPLY, s, sizeof(cardstatus) + card->dataSize);
};
m_commandHandlers[LCOMMAND_INCOME_FREE_START_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct reply
{
int playerid;
int status;
} r;
r.playerid = 0;
r.status = 1;
SendResponse(SCOMMAND_INCOME_STATUS_REPLY, &r);
};
m_commandHandlers[LCOMMAND_INCOME_START_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct reply
{
int playerid;
int status;
} r;
r.playerid = 0;
r.status = 1;
SendResponse(SCOMMAND_INCOME_STATUS_REPLY, &r);
};
m_commandHandlers[LCOMMAND_RANKING_DATA_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct ranking
{
uint32_t status;
uint32_t size;
char data[];
};
ranking r;
r.status = 1;
r.size = 0;
SendResponse(SCOMMAND_RANKING_DATA_REPLY, &r);
};
m_commandHandlers[LCOMMAND_UPLOAD_CONFIG_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct __declspec(align(4)) _UPLOAD_CONFIG
{
unsigned int dataType;
unsigned int dataSize;
char data[1];
};
const _UPLOAD_CONFIG* config = reinterpret_cast<const _UPLOAD_CONFIG*>(data);
int status = 1;
SendResponse(SCOMMAND_UPLOAD_CONFIG_REPLY, &status);
};
m_commandHandlers[LCOMMAND_SERVICE_VERSION_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct _SERVICE_VER
{
char version[33];
};
_SERVICE_VER version;
strcpy(version.version, "13.37 1337/01/01");
SendResponse(SCOMMAND_SERVICE_VERSION_REPLY, &version);
};
m_commandHandlers[LCOMMAND_SET_INCOME_MODE_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_SET_INCOME_MODE_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_GAMESTATUS_RESET_REQUEST] = [=](const uint8_t* data, size_t length)
{
SendResponse(SCOMMAND_GAMESTATUS_RESET_REPLY, nullptr);
};
m_commandHandlers[LCOMMAND_LOCALNW_INFO_REQUEST] = [=](const uint8_t* data, size_t length)
{
// may also need 'notice' replies
SendResponse(SCOMMAND_LOCALNW_INFO_REPLY, nullptr);
Sleep(100);
struct nesys_nwinfo_advertise_table_t
{
char mac[16];
char ip[16];
char dhcp[16];
char gateway[16];
int gameid;
int attr;
};
struct nwi
{
int s;
int size;
nesys_nwinfo_advertise_table_t data;
};
nwi nw;
nw.s = 1;
nw.size = sizeof(nw.data);
strcpy(nw.data.ip, config["Network"]["Ip"].c_str());
strcpy(nw.data.gateway, config["Network"]["Gateway"].c_str());
strcpy(nw.data.dhcp, config["Network"]["Dns1"].c_str());
strcpy(nw.data.mac, "DEADBABECAFE");
nw.data.gameid = 42;
nw.data.attr = 0;
SendResponse(SCOMMAND_LOCALNW_INFO_NOTICE, &nw);
};
m_commandHandlers[LCOMMAND_GLOBALADDR_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct nesys_globaladdr_table_t
{
int globaladdrStatus;
int responseTime;
char globaladdrData[32];
};
nesys_globaladdr_table_t globalAddr;
globalAddr.globaladdrStatus = 1;
globalAddr.responseTime = 42;
strcpy(globalAddr.globaladdrData, "127.1.3.37");
SendResponse(SCOMMAND_GLOBALADDR_REPLY, &globalAddr);
};
m_commandHandlers[LCOMMAND_ADAPTER_INFO_REQUEST] = [=](const uint8_t* data, size_t length)
{
struct NNS_LANINTERFACE
{
int Dhcp_Enabled;
char gateway[32];
char ipAddr[32];
char submask[32];
char dhcpServers[32];
char dnsServers[32];
char macAddress[64];
};
struct nesys_laninterface_table_t
{
int interfaceStatus;
NNS_LANINTERFACE interfaceData;
};
nesys_laninterface_table_t lan;
lan.interfaceStatus = 1;
lan.interfaceData.Dhcp_Enabled = strcmp(config["Network"]["Dhcp"].c_str(), "1") == 0;
strcpy(lan.interfaceData.ipAddr, config["Network"]["Ip"].c_str());
strcpy(lan.interfaceData.submask, config["Network"]["Mask"].c_str());
strcpy(lan.interfaceData.gateway, config["Network"]["Gateway"].c_str());
strcpy(lan.interfaceData.dhcpServers, config["Network"]["Dns1"].c_str());
strcpy(lan.interfaceData.dnsServers, config["Network"]["Dns1"].c_str());
strcpy(lan.interfaceData.macAddress, "DEADBABECAFE");
SendResponse(SCOMMAND_ADAPTER_INFO_REPLY, &lan);
};
}
NesysEmu::~NesysEmu()
{
if (m_initialized)
{
Shutdown();
}
}
void NesysEmu::ProcessRequest(const uint8_t* data, size_t length)
{
uintptr_t endData = reinterpret_cast<uintptr_t>(data) + length;
while (reinterpret_cast<uintptr_t>(data) < endData)
{
auto header = reinterpret_cast<const NesysCommandHeader*>(data);
if (header->command != CCOMMAND_NONE)
{
ProcessRequestInternal(header);
}
data += sizeof(header) + header->length + 4;
}
}
void NesysEmu::ProcessRequestInternal(const NesysCommandHeader* header)
{
auto handler = m_commandHandlers.find(header->command);
if (handler != m_commandHandlers.end())
{
#ifdef _DEBUG
info(true, "got nesys command: %d\n", header->command);
#endif
handler->second(header->data, header->length);
return;
}
#ifdef _DEBUG
info(true, "got unhandled nesys command: %d\n", header->command); //
#endif
}
static thread_local HANDLE g_curPipe;
void NesysEmu::ProcessPipe(HANDLE hPipe)
{
uint8_t requestBuffer[8192];
while (true)
{
DWORD bytesRead;
auto success = ReadFile(hPipe, requestBuffer, sizeof(requestBuffer), &bytesRead, nullptr);
if (!success || bytesRead == 0)
{
break;
}
g_curPipe = hPipe;
ProcessRequest(requestBuffer, bytesRead);
Sleep(150);
}
CloseHandle(hPipe);
}
void NesysEmu::SendResponse(nesys_command command, const void* data, size_t dataSize)
{
size_t outSize = (sizeof(NesysCommandHeader) * 1) + dataSize;
uint8_t* buffer = (uint8_t*)malloc(outSize);
((NesysCommandHeader*)buffer)->command = command;
((NesysCommandHeader*)buffer)->length = dataSize;
if (dataSize > 0)
{
memcpy(buffer + sizeof(NesysCommandHeader), data, dataSize);
}
//((NesysCommandHeader*)(buffer + sizeof(NesysCommandHeader) + dataSize))->command = CCOMMAND_NONE;
//((NesysCommandHeader*)(buffer + sizeof(NesysCommandHeader) + dataSize))->length = 0;
DWORD outWritten;
WriteFile(g_curPipe, buffer, outSize, &outWritten, nullptr);
free(buffer);
}
void NesysEmu::Initialize()
{
std::thread([=]()
{
while (true)
{
auto pipe = CreateNamedPipeW(L"\\\\.\\pipe\\nesys_games", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 0, nullptr);
if (pipe == INVALID_HANDLE_VALUE)
{
return;
}
bool connected = ConnectNamedPipe(pipe, nullptr) ? true : GetLastError() == ERROR_PIPE_CONNECTED;
if (!connected)
{
CloseHandle(pipe);
continue;
}
std::thread([=]()
{
ProcessPipe(pipe);
}).detach();
}
}).detach();
m_initialized = true;
}
void NesysEmu::Shutdown()
{
}
static NesysEmu g_nesysEmu;
#include <iphlpapi.h>
static DWORD(WINAPI* g_origGetIfEntry)(PMIB_IFROW ifRow);
DWORD WINAPI GetIfEntryFunc(
_Inout_ PMIB_IFROW pIfRow
)
{
DWORD rv = g_origGetIfEntry(pIfRow);
pIfRow->dwOperStatus = IF_OPER_STATUS_CONNECTED;
return 0;
}
void init_NesysEmu()
{
MH_Initialize();
MH_CreateHookApi(L"iphlpapi.dll", "GetIfEntry", GetIfEntryFunc, (void**)&g_origGetIfEntry);
MH_EnableHook(MH_ALL_HOOKS);
g_nesysEmu.Initialize();
}
#pragma optimize("", on)

View File

@ -0,0 +1,144 @@
#pragma once
#include <thread>
enum nesys_command : uint32_t
{
CCOMMAND_ERROR = 0xFFFFFFFF,
CCOMMAND_NONE = 0x0,
LCOMMAND_CLIENT_START = 0x1,
LCOMMAND_CONNECT_REQUEST = 0x2,
LCOMMAND_DISCONNECT_REQUEST = 0x3,
LCOMMAND_GAME_START_REQUEST = 0x4,
LCOMMAND_GAME_END_REQUEST = 0x5,
LCOMMAND_GAME_CONTINUE_REQUEST = 0x6,
LCOMMAND_EVENT_DOWNLOAD_REQUEST = 0x7,
LCOMMAND_EVENT_REQUEST_REQUEST = 0x8,
LCOMMAND_CARD_SELECT_REQUEST = 0x9,
LCOMMAND_CARD_INSERT_REQUEST = 0xA,
LCOMMAND_CARD_UPDATE_REQUEST = 0xB,
LCOMMAND_CARD_BUYS_ITEM_REQUEST = 0xC,
LCOMMAND_CARD_TAKEOVER_REQUEST = 0xD,
LCOMMAND_CARD_FORCE_TAKEOVER_REQUEST = 0xE,
LCOMMAND_CARD_DECREASE_REQUEST = 0xF,
LCOMMAND_CARD_REISSUE_TEST_REQUEST = 0x10,
LCOMMAND_CARD_REISSUE_REQUEST = 0x11,
LCOMMAND_CARD_PLAYED_LIST_REQUEST = 0x12,
LCOMMAND_RANKING_DATA_REQUEST = 0x13,
LCOMMAND_LOCALNW_INFO_REQUEST = 0x14,
LCOMMAND_GLOBALADDR_REQUEST = 0x15,
LCOMMAND_ECHO_REQUEST = 0x16,
LCOMMAND_ADAPTER_INFO_REQUEST = 0x17,
LCOMMAND_SERVICE_VERSION_REQUEST = 0x18,
LCOMMAND_DHCP_RENEW_REQUEST = 0x19,
LCOMMAND_HTTPACCESS_GET_REQUEST = 0x1A,
LCOMMAND_HTTPACCESS_POST_REQUEST = 0x1B,
LCOMMAND_UPLOAD_CONFIG_REQUEST = 0x1C,
LCOMMAND_INCOME_START_REQUEST = 0x1D,
LCOMMAND_INCOME_END_REQUEST = 0x1E,
LCOMMAND_INCOME_CONTINUE_REQUEST = 0x1F,
LCOMMAND_SET_INCOME_MODE_REQUEST = 0x20,
LCOMMAND_DESTROY_MY_SERVICE = 0x21,
LCOMMAND_INCOME_POINT_REQUEST = 0x22,
LCOMMAND_GAMESTATUS_RESET_REQUEST = 0x23,
LCOMMAND_ROW_EVENTDATA_LIST_REQUEST = 0x24,
LCOMMAND_SHOPPING_REQUEST = 0x25,
LCOMMAND_HTTPSACCESS_GET_REQUEST = 0x26,
LCOMMAND_HTTPSACCESS_POST_REQUEST = 0x27,
LCOMMAND_FREE_TICKET_REQUEST = 0x28,
LCOMMAND_GAME_FREE_START_REQUEST = 0x29,
LCOMMAND_GAME_FREE_END_REQUEST = 0x2A,
LCOMMAND_INCOME_FREE_START_REQUEST = 0x2B,
LCOMMAND_INCOME_FREE_END_REQUEST = 0x2C,
LCOMMAND_CLIENT_END = 0xFF,
SCOMMAND_NW_ERROR = 0x101,
SCOMMAND_CERT_ERROR = 0x102,
SCOMMAND_NWRECOVER_NOTICE = 0x103,
SCOMMAND_SOON_MAINTENANCE_NOTICE = 0x104,
SCOMMAND_LINKUP_NOTICE = 0x105,
SCOMMAND_LINKLOCAL_MODE_NOTICE = 0x106,
SCOMMAND_CERT_INIT_NOTICE = 0x107,
SCOMMAND_CERT_REGULAR_NOTICE = 0x108,
SCOMMAND_EFFECTIVE_EVENT_NOTICE = 0x109,
SCOMMAND_INEFFECTIVE_EVENT_NOTICE = 0x10A,
SCOMMAND_DHCP_RENEW_START = 0x10B,
SCOMMAND_DHCP_COMPLETE_NOTICE = 0x10C,
SCOMMAND_CLIENT_START_REPLY = 0x10D,
SCOMMAND_CONNECT_REPLY = 0x10E,
SCOMMAND_DISCONNECT_REPLY = 0x10F,
SCOMMAND_GAME_STATUS_REPLY = 0x110,
SCOMMAND_CARD_SELECT_REPLY = 0x111,
SCOMMAND_CARD_INSERT_REPLY = 0x112,
SCOMMAND_CARD_UPDATE_REPLY = 0x113,
SCOMMAND_CARD_BUYS_ITEM_REPLY = 0x114,
SCOMMAND_CARD_TAKEOVER_REPLY = 0x115,
SCOMMAND_CARD_DECREASE_REPLY = 0x116,
SCOMMAND_CARD_REISSUE_TEST_REPLY = 0x117,
SCOMMAND_CARD_REISSUE_REPLY = 0x118,
SCOMMAND_CARD_PLAYED_LIST_REPLY = 0x119,
SCOMMAND_RANKING_DATA_REPLY = 0x11A,
SCOMMAND_LOCALNW_INFO_REPLY = 0x11B,
SCOMMAND_LOCALNW_INFO_NOTICE = 0x11C,
SCOMMAND_GLOBALADDR_REPLY = 0x11D,
SCOMMAND_ECHO_REPLY = 0x11E,
SCOMMAND_ADAPTER_INFO_REPLY = 0x11F,
SCOMMAND_SERVICE_VERSION_REPLY = 0x120,
SCOMMAND_HTTPACCESS_START = 0x121,
SCOMMAND_HTTPACCESS_REPLY = 0x122,
SCOMMAND_UPLOAD_CONFIG_REPLY = 0x123,
SCOMMAND_INCOME_STATUS_REPLY = 0x124,
SCOMMAND_SET_INCOME_MODE_REPLY = 0x125,
SCOMMAND_DESTROY_MY_SERVICE = 0x126,
SCOMMAND_GAMESTATUS_RESET_REPLY = 0x127,
SCOMMAND_ROW_EVENTDATA_LIST_REPLY = 0x128,
SCOMMAND_SHOPPING_REPLY = 0x129,
SCOMMAND_FREE_TICKET_REPLY = 0x130,
SCOMMAND_CLIENT_END_REPLY = 0x1FF,
};
struct NesysCommandHeader
{
nesys_command command;
uint32_t length;
uint8_t data[];
};
class NesysEmu
{
public:
NesysEmu();
~NesysEmu();
void Initialize();
void Shutdown();
private:
void ProcessPipe(HANDLE hPipe);
void ProcessRequest(const uint8_t* requestBuffer, size_t length);
void ProcessRequestInternal(const NesysCommandHeader* header);
template<typename T>
void SendResponse(nesys_command command, T data)
{
SendResponse(command, data, sizeof(*data));
}
template<>
void SendResponse<nullptr_t>(nesys_command command, nullptr_t data)
{
SendResponse(command, nullptr, 0);
}
void SendResponse(nesys_command command, const void* data, size_t dataSize);
private:
bool m_initialized;
std::map<nesys_command, std::function<void(const uint8_t*, size_t)>> m_commandHandlers;
};
void init_NesysEmu();

View File

@ -0,0 +1,847 @@
#include <StdInc.h>
// ORIGINALL BASED ON ttx_monitor, modified for RFID. https://github.com/zxmarcos/ttx_monitor
#include "Functions/Types.h"
#include "Utility/InitFunction.h"
#include <queue>
#define JVS_TRUE 0x01
#define JVS_FALSE 0x00
#define JVS_SYNC_CODE 0xE0
#define JVS_REPORT_CODE 0x01
#define JVS_COMMAND_REV 0x13
#define JVS_BOARD_REV 0x30
#define JVS_COMM_REV 0x10
#define JVS_ADDR_MASTER 0x00
#define JVS_STATUS_OK 0x01
#define JVS_STATUS_UNKNOWN_CMD 0x02
#define JVS_STATUS_SUM_ERROR 0x03
#define JVS_STATUS_ACK_OVERFLOW 0x04
#define JVS_REPORT_OK 0x01
#define JVS_REPORT_INVAL_PARAM1 0x02
#define JVS_REPORT_INVAL_PARAM2 0x03
#define JVS_REPORT_BUSY 0x04
#define JVS_STREAM_SIZE 1024
#define JVS_OP_RESET 0xF0
#define JVS_OP_ADDRESS 0xF1
#define JVS_OP_CHECKSUM_ERROR 0x2F
#define JVS_IOFUNC_SWINPUT 0x01
#define JVS_IOFUNC_COINTYPE 0x02
#define JVS_IOFUNC_EXITCODE 0x00
#define JVS_SUPPORT_PLAYERS 2
#define JVS_SUPPORT_SLOTS 2
#define LOG_COMMANDS 1
#if LOG_COMMANDS
#define logcmd logmsg
#else
#define logcmd(str, __VA_LIST__)
#endif
std::queue<BYTE> replyBuffer;
typedef signed char SINT8;
typedef signed short SINT16;
typedef signed short SINT32;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
HANDLE hConnection = (HANDLE)0x1337;
X2Type gameType;
static uint8_t g_jvsIOValues[64];
typedef BOOL(__stdcall *LPCloseHandle)(HANDLE hObject);
static LPCloseHandle __CloseHandle = NULL;
typedef BOOL(__stdcall *LPGetCommModemStatus)(HANDLE hFile, LPDWORD lpModemStat);
static LPGetCommModemStatus __GetCommModemStatus = NULL;
typedef BOOL(__stdcall *LPEscapeCommFunction)(HANDLE hFile, DWORD dwFunc);
static LPEscapeCommFunction __EscapeCommFunction = NULL;
typedef BOOL(__stdcall *LPClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
static LPClearCommError __ClearCommError = NULL;
typedef BOOL(__stdcall *LPSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
static LPSetupComm __SetupComm = NULL;
typedef BOOL(__stdcall *LPGetCommState)(HANDLE hFile, LPDCB lpDCB);
static LPGetCommState __GetCommState = NULL;
typedef BOOL(__stdcall *LPSetCommState)(HANDLE hFile, LPDCB lpDCB);
static LPSetCommState __SetCommState = NULL;
typedef BOOL(__stdcall *LPSetCommMask)(HANDLE hFile, DWORD dwEvtMask);
static LPSetCommMask __SetCommMask = NULL;
typedef BOOL(__stdcall *LPGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
static LPGetCommTimeouts __GetCommTimeouts = NULL;
typedef BOOL(__stdcall *LPSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
static LPSetCommTimeouts __SetCommTimeouts = NULL;
typedef BOOL(__stdcall *LPWriteFile)(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
static LPWriteFile __WriteFile = NULL;
typedef BOOL(__stdcall *LPReadFile)(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped);
typedef BOOL(__stdcall *LPCloseHandle)(HANDLE hObject);
static LPReadFile __ReadFile = NULL;
typedef HANDLE(__stdcall *LPCreateFileA)(LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static LPCreateFileA __CreateFileA = NULL;
typedef HANDLE(__stdcall *LPCreateFileW)(LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static LPCreateFileW __CreateFileW = NULL;
static const char *Rfid_IO_Id = "TAITO CORP.;RFID CTRL P.C.B.;Ver1.00;";
void logmsg(const char *format, ...)
{
}
struct jvs_command_def {
UINT8 params;
UINT8 reports;
};
#define __ARG__(n) ((DWORD) pfunc[n])
class jprot_encoder {
BYTE buffer[1024];
BYTE *ptr;
DWORD statusaddr;
DWORD sizeaddr;
DWORD sumaddr;
DWORD startaddr;
DWORD xpos;
DWORD size_;
DWORD nreplys;
public:
DWORD size() {
return size_;
}
jprot_encoder() {
memset(buffer, 0, 1024);
xpos = 0;
}
~jprot_encoder() {
memset(buffer, 0, 1024);
xpos = 0;
}
void addreply() {
nreplys++;
}
void set_status(BYTE v) {
buffer[statusaddr] = v;
}
void clear()
{
memset(buffer, 0, 1024);
size_ = 0;
xpos = 0;
}
void begin_stream() {
pushz(JVS_SYNC_CODE);
sumaddr = xpos;
pushz(JVS_ADDR_MASTER);
sizeaddr = xpos;
push(0);
statusaddr = xpos;
// STATUS
push(JVS_STATUS_OK);
}
void pushz(BYTE v) {
buffer[xpos++] = v;
}
void push(BYTE v) {
#if 0
buffer[xpos] = v;
++xpos;
#else
if (v == 0xD0) {
buffer[xpos++] = 0xD0;
buffer[xpos++] = 0xCF;
}
else
if (v == 0xE0) {
buffer[xpos++] = 0xD0;
buffer[xpos++] = 0xDF;
}
else
buffer[xpos++] = v;
#endif
}
void report(BYTE v) {
push(v);
}
void end_stream() {
#if 0
if (xpos == (statusaddr + 1)) {
clear();
return;
}
// codifica o tamanho da stream
buffer[sizeaddr] = (BYTE)xpos - sizeaddr;
// calcula o checksum
DWORD sum = 0;
for (DWORD i = sumaddr; i<xpos; i++) {
sum += (DWORD)(buffer[i] & 0xFF);
}
sum &= 0xFF;
if ((sum == 0xD0) || (sum == 0xE0)) {
push(0xD0);
push(sum - 1);
}
else
push(sum);
size_ = xpos;
#else
if (xpos == (statusaddr + 1)) {
clear();
return;
}
DWORD sizeK = 0;
for (DWORD i = sizeaddr; i<xpos; i++)
if (buffer[i] != 0xD0)
++sizeK;
// codifica o tamanho da stream
buffer[sizeaddr] = sizeK;
// calcula o checksum
DWORD sum = 0;
for (DWORD i = sumaddr, inc = 0; i<xpos; i++) {
if (buffer[i] == 0xD0) {
inc = 1;
}
else {
sum += (DWORD)((buffer[i] + inc) & 0xFF);
if (inc)
inc = 0;
}
}
sum &= 0xFF;
push(sum);
size_ = xpos;
#endif
}
void read(BYTE *dst, DWORD size) {
if (size > size_)
size = size_;
memcpy(dst, &buffer[0], size);
}
void print()
{
if (size()) {
#ifdef _DEBUG
logmsg("WR: ");
for (DWORD i = 0; i<size(); i++)
logmsg("%02X ", buffer[i]);
logmsg("\n");
#endif
}
}
};
static int isAddressed = 0;
int is_addressed() {
return isAddressed;
}
void reset_addressed()
{
isAddressed = 0;
}
static WORD p1coin = 0;
static WORD p2coin = 0;
static int coinstate[2] = { 0, 0 };
int handle0xF0()
{
p1coin = 0;
p2coin = 0;
return 2;
}
int handle0xF1(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
isAddressed = 1;
return 2;
}
int handle0x2F()
{
return 1;
}
int handle0x10(jprot_encoder *r)
{
const char *str = NULL;
r->report(JVS_REPORT_OK);
//if(gameType == X2Type::RFID)
str = Rfid_IO_Id;
//else if(gameType == X2Type::Digital)
// str = IO_Id;
while (*str) { r->push(*str++); }
r->push(0);
return 1;
}
int handle0x11(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
r->push(JVS_COMMAND_REV);
return 1;
}
int handle0x12(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
r->push(JVS_BOARD_REV);
return 1;
}
int handle0x13(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
r->push(JVS_COMM_REV);
return 1;
}
int handle0x14(jprot_encoder *r)
{
if (gameType == X2Type::RFID)
{
r->report(JVS_REPORT_OK);
r->push(1);
r->push(7);
r->push(0);
r->push(8);
r->push(0);
r->push(0x12);
r->push(8);
r->push(0);
r->push(0);
r->push(0);
return 1;
}
if(gameType == X2Type::Digital)
{
r->report(JVS_REPORT_OK);
r->push(JVS_IOFUNC_SWINPUT);
{
r->push(JVS_SUPPORT_PLAYERS); // 2 players
r->push(14); // 14 bot<6F>es
r->push(0); // null
}
r->push(JVS_IOFUNC_COINTYPE);
{
r->push(JVS_SUPPORT_SLOTS); // 2 slots
r->push(0); // null
r->push(0); // null
}
r->push(JVS_IOFUNC_EXITCODE);
{
r->push(0);
r->push(0);
r->push(0);
}
}
return 1;
}
int handle0x01(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
r->push(1);
r->push(0);
return 2;
}
int handle0x20(jprot_encoder *r)
{
r->report(JVS_REPORT_OK);
if(gameType == X2Type::Digital)
{
if (g_jvsIOValues[24])
r->push(0x80);
else
r->push(0);
}
else
{
r->push(0);
}
r->push(0);
r->push(0);
r->push(0);
r->push(0);
return 3;
}
int handle0x21(jprot_encoder *r)
{
if(gameType == X2Type::RFID)
{
int currstate = 0;// inputMgr.GetState(P1_COIN);
if (!coinstate[0] && (currstate)) {
++p1coin;
}
coinstate[0] = currstate;
currstate = 0;// inputMgr.GetState(P2_COIN);
if (!coinstate[1] && (currstate)) {
++p2coin;
}
coinstate[1] = currstate;
//logcmd("Lendo o ficheiro... \n");
r->report(JVS_REPORT_OK);
r->push(p1coin >> 8);
r->push(p1coin & 0xFF);
r->push(p2coin >> 8);
r->push(p2coin & 0xFF);
return 2;
}
int currstate = g_jvsIOValues[25];
if (!coinstate[0] && (currstate)) {
++p1coin;
}
coinstate[0] = currstate;
currstate = g_jvsIOValues[26];
if (!coinstate[1] && (currstate)) {
++p2coin;
}
coinstate[1] = currstate;
//logcmd("Lendo o ficheiro... \n");
r->report(JVS_REPORT_OK);
r->push(p1coin >> 8);
r->push(p1coin & 0xFF);
r->push(p2coin >> 8);
r->push(p2coin & 0xFF);
return 2;
}
int handle0x30(jprot_encoder *r, DWORD arg1, DWORD arg2, DWORD arg3)
{
WORD val = ((arg2 & 0xFF) << 8) | (arg3 & 0xFF);
r->report(JVS_REPORT_OK);
#ifdef _DEBUG
logcmd("-coin %d, %d\n", arg1, val);
#endif
switch (arg1)
{
case 1:
if (val > p1coin)
p1coin = 0;
else
p1coin -= val;
break;
case 2:
if (val > p2coin)
p2coin = 0;
else
p2coin -= val;
}
return 4;
}
int handle0x31(jprot_encoder *r, DWORD arg1, DWORD arg2, DWORD arg3)
{
WORD val = ((arg2 & 0xFF) << 8) | (arg3 & 0xFF);
r->report(JVS_REPORT_OK);
#ifdef _DEBUG
logcmd("+coin %d, %d\n", arg1, val);
#endif
switch (arg1)
{
case 1: p1coin += val; break;
case 2: p2coin += val; break;
}
return 4;
}
unsigned long process_stream(unsigned char *stream, unsigned long srcsize, unsigned char *dst, unsigned long dstsize)
{
jprot_encoder r;
BYTE *pstr = stream;
BYTE *pfunc = NULL;
BYTE node = 0;
BYTE pktsize = 0;
int pktcount = 0;
WORD pktaddr = 0;
r.clear();
if (pstr[0] != JVS_SYNC_CODE) {
#ifdef _DEBUG
logmsg("Invalid Sync code!\n");
#endif
}
node = pstr[1];
pktsize = pstr[2];
pfunc = &pstr[3];
pktcount = (int)pktsize - 1;
r.begin_stream();
while (pktcount > 0)
{
int increment = 0;
switch (pfunc[0] & 0xFF)
{
case 0xF0:
increment = handle0xF0();
break;
case 0xF1:
increment = handle0xF1(&r);
break;
case 0x2F:
increment = handle0x2F();
break;
case 0x10:
increment = handle0x10(&r);
break;
case 0x11:
increment = handle0x11(&r);
break;
case 0x12:
increment = handle0x12(&r);
break;
case 0x13:
increment = handle0x13(&r);
break;
case 0x14:
increment = handle0x14(&r);
break;
case 0x01:
increment = handle0x01(&r);
break;
case 0x20:
increment = handle0x20(&r);
break;
case 0x21:
increment = handle0x21(&r);
break;
case 0x30:
increment = handle0x30(&r, __ARG__(1), __ARG__(2), __ARG__(3));
break;
case 0x31:
increment = handle0x31(&r, __ARG__(1), __ARG__(2), __ARG__(3));
break;
default:
#ifdef _DEBUG
logcmd("Unknown command %X\n", __ARG__(0));
#endif
r.report(JVS_REPORT_OK);
increment = 1;
break;
}
pktcount -= increment;
pfunc += increment;
}
r.set_status(JVS_STATUS_OK);
r.end_stream();
r.read(dst, dstsize);
return r.size();
}
#define __XHOOKn(mod, name) \
MH_CreateHookApi(L ## mod, #name, &Hookz_##name, (void**)&__##name)
BOOL __stdcall Hookz_GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
{
if (hFile != hConnection) {
return __GetCommModemStatus(hFile, lpModemStat);
}
if (is_addressed())
*lpModemStat = 0x10;
else
*lpModemStat = 0;
#ifdef LogRFID
info(true, "GetCommModemStatus(hFile=%d, lpModemStat=%p) -> result=%08X", hFile, lpModemStat, TRUE);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
{
if (hFile != hConnection) {
return __EscapeCommFunction(hFile, dwFunc);
}
bool ret = true;// __EscapeCommFunction(hFile, dwFunc);
#ifdef LogRFID
info(true, "EscapeCommFunction(hFile=%d, dwFunc='%08X') -> result=%08X", hFile, dwFunc, ret);
info(true, "--------------------------------------------");
#endif
return ret;
}
BOOL __stdcall Hookz_ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
{
if (hFile != hConnection) {
return __ClearCommError(hFile, lpErrors, lpStat);
}
#ifdef LogRFID
info(true, "ClearCommError(hFile=%d, lpErrors=%p, lpStat=%p) -> result=%08X", hFile, lpErrors, lpStat, 1);
info(true, "--------------------------------------------");
#endif
if (lpStat) {
if (!replyBuffer.empty())
lpStat->cbInQue = replyBuffer.size();
else
lpStat->cbInQue = 0;
}
return true;
}
BOOL __stdcall Hookz_SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
{
if (hFile != hConnection) {
return __SetupComm(hFile, dwInQueue, dwOutQueue);
}
#ifdef LogRFID
info(true, "SetupComm(hFile=%d, dwInQueue='%08X', dwOutQueue='%08X') -> result=%08X", hFile, dwInQueue, dwOutQueue, 1);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_GetCommState(HANDLE hFile, LPDCB lpDCB)
{
if (hFile != hConnection) {
return __GetCommState(hFile, lpDCB);
}
#ifdef LogRFID
info(true, "GetCommState(hFile=%d, lpDCB=%p) -> result=%08X", hFile, lpDCB, 1);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_SetCommState(HANDLE hFile, LPDCB lpDCB)
{
if (hFile != hConnection) {
return __SetCommState(hFile, lpDCB);
}
#ifdef LogRFID
info(true, "SetCommState(hFile=%d, lpDCB=%p) -> result=%08X", hFile, lpDCB, 1);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_SetCommMask(HANDLE hFile, DWORD dwEvtMask)
{
if (hFile != hConnection) {
return __SetCommMask(hFile, dwEvtMask);
}
#ifdef LogRFID
info(true, "SetCommMask(hFile=%d, dwEvtMask='%08X') -> result=%08X", hFile, dwEvtMask, true);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
{
if (hFile != hConnection) {
return __GetCommTimeouts(hFile, lpCommTimeouts);
}
#ifdef LogRFID
info(true, "GetCommTimeouts(hFile=%d, lpCommTimeouts=%p) -> result=%08X", hFile, lpCommTimeouts, TRUE);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
{
if (hFile != hConnection) {
return __SetCommTimeouts(hFile, lpCommTimeouts);
}
#ifdef LogRFID
info(true, "SetCommTimeouts(hFile=%d, lpCommTimeouts=%p) -> result=%08X", hFile, lpCommTimeouts, TRUE);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_WriteFile(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
{
if (hFile != hConnection) {
return __WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}
static BYTE rbuffer[1024];
DWORD sz = process_stream((LPBYTE)lpBuffer, nNumberOfBytesToWrite, rbuffer, 1024);
if (sz != 1) {
for (DWORD i = 0; i < sz; i++)
{
replyBuffer.push(rbuffer[i]);
}
}
#ifdef LogRFID
info(true, "");
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_ReadFile(HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped)
{
if (hFile != hConnection) {
return __ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
#ifdef LogRFID
info(true, "ReadFile(hFile=%d, lpBuffer='%08X', nNumberOfBytesToRead=%08X) -> result=%08X", hFile, lpBuffer, nNumberOfBytesToRead, TRUE);
#endif
if (replyBuffer.size())
{
if (nNumberOfBytesToRead >= replyBuffer.size())
nNumberOfBytesToRead = replyBuffer.size();
*lpNumberOfBytesRead = nNumberOfBytesToRead;
BYTE *ptr = (BYTE*)lpBuffer;
for (DWORD i = 0; i < nNumberOfBytesToRead; i++) {
if (!replyBuffer.empty()) {
*ptr++ = replyBuffer.front();
replyBuffer.pop();
}
else
*ptr++ = 0;
}
}
else {
*lpNumberOfBytesRead = 0;
return TRUE;
}
#ifdef LogRFID
info(true, "");
info(true, "--------------------------------------------");
#endif
return TRUE;
}
BOOL __stdcall Hookz_CloseHandle(HANDLE hObject)
{
if (hObject != hConnection) {
return __CloseHandle(hObject);
}
#ifdef LogRFID
info(true, "CloseHandle(hObject=%d) -> result=%08X", hObject, TRUE);
info(true, "--------------------------------------------");
#endif
return TRUE;
}
DWORD priority = 0;
HANDLE __stdcall Hookz_CreateFileA(LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (!strcmp(lpFileName, "COM2"))
{
#ifdef LogRFID
info(true, "CreateFile(lpFileName=%s) -> result=%08X", lpFileName, hConnection);
info(true, "--------------------------------------------");
#endif
return hConnection;
}
return __CreateFileA(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
#define __XHOOKn(mod, name) \
MH_CreateHookApi(L ## mod, #name, &Hookz_##name, (void**)&__##name)
void init_RfidEmu(X2Type type)
{
MH_Initialize();
gameType = X2Type::RFID;
__XHOOKn("kernel32.dll", CreateFileA);
//__XHOOKn("kernel32.dll", CreateFileW);
__XHOOKn("kernel32.dll", WriteFile);
__XHOOKn("kernel32.dll", ReadFile);
__XHOOKn("kernel32.dll", CloseHandle);
__XHOOKn("kernel32.dll", GetCommModemStatus);
__XHOOKn("kernel32.dll", EscapeCommFunction);
__XHOOKn("kernel32.dll", ClearCommError);
__XHOOKn("kernel32.dll", SetCommMask);
__XHOOKn("kernel32.dll", SetupComm);
__XHOOKn("kernel32.dll", GetCommState);
__XHOOKn("kernel32.dll", SetCommState);
__XHOOKn("kernel32.dll", SetCommTimeouts);
__XHOOKn("kernel32.dll", GetCommTimeouts);
MH_EnableHook(MH_ALL_HOOKS);
}

View File

@ -0,0 +1,5 @@
#pragma once
void reset_addressed();
unsigned long process_stream(unsigned char *stream, unsigned long srcsize, unsigned char *dst, unsigned long dstsize);
unsigned long process_rfid(unsigned char *stream, unsigned long srcsize, unsigned char *dst, unsigned long dstsize);
void init_RfidEmu(X2Type type);

View File

@ -0,0 +1,358 @@
#include <StdInc.h>
#include <Utility/InitFunction.h>
#include <Utility/GameDetect.h>
#include "amJvs.h"
#pragma optimize("", off)
#include <MinHook.h>
typedef BOOL(__stdcall *LPGetCommModemStatus)(HANDLE hFile, LPDWORD lpModemStat);
static LPGetCommModemStatus __GetCommModemStatus = NULL;
typedef BOOL(WINAPI *LPSetCommState)(HANDLE hFile, LPDCB lpDCB);
static LPSetCommState __SetCommState = NULL;
typedef BOOL(WINAPI *LPGetCommState)(HANDLE hFile, LPDCB lpDCB);
static LPGetCommState __GetCommState = NULL;
typedef BOOL(WINAPI *LPGetCommMask)(HANDLE hFile, DWORD* dwEvtMask);
static LPGetCommMask __GetCommMask = NULL;
typedef BOOL(WINAPI *LPSetCommMask)(HANDLE hFile, DWORD dwEvtMask);
static LPSetCommMask __SetCommMask = NULL;
typedef BOOL(WINAPI *LPEscapeCommFunction)(HANDLE hFile, DWORD);
static LPEscapeCommFunction __EscapeCommFunction = NULL;
typedef BOOL(WINAPI *LPSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
static LPSetCommTimeouts __SetCommTimeouts = NULL;
typedef BOOL(WINAPI *LPGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
static LPGetCommTimeouts __GetCommTimeouts = NULL;
typedef BOOL(WINAPI *LPSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
static LPSetupComm __SetupComm = NULL;
typedef BOOL(WINAPI *LPPurgeComm)(HANDLE hFile, DWORD dwFlags);
static LPPurgeComm __PurgeComm = NULL;
typedef BOOL(__stdcall *LPClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
static LPClearCommError __ClearCommError = NULL;
typedef HANDLE(__stdcall *LPCreateFileA)(LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static LPCreateFileA __CreateFileA = NULL;
typedef HANDLE(__stdcall *LPCreateFileW)(LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static LPCreateFileW __CreateFileW = NULL;
LPCSTR emuPort = "\\\\.\\pipe\\teknoparrot_jvs";
LPCWSTR emuPortW = L"\\\\.\\pipe\\teknoparrot_jvs";
LPCSTR hookPort = "COM4";
DWORD amJvsDataOffset = 0;
HANDLE jvsHandle = (HANDLE)-1;
bool JVSAlreadyTaken = false;
HANDLE __stdcall Hook_CreateFileA(LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (strcmp(lpFileName, hookPort) == 0)
{
#ifdef _DEBUG
info(true, "CreateFileA JVS: %s", lpFileName);
info(true, "--------------------------------------------");
#endif
if (jvsHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(jvsHandle);
jvsHandle = INVALID_HANDLE_VALUE;
}
HANDLE hResult = __CreateFileA(emuPort,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
jvsHandle = hResult;
//JVSAlreadyTaken = true;
return hResult;
}
if (strncmp(lpFileName, "Y:\\", 3) == 0)
{
DWORD len = strlen(lpFileName);
char temp[32];
memset(temp, 0, 32);
memcpy(temp, ".\\", 2);
memcpy(temp + 2, lpFileName + 3, len - 3);
#ifdef _DEBUG
info(true, "data drive file redirected: %s -> %s", lpFileName, temp);
#endif
HANDLE hResult = __CreateFileA(temp,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
return hResult;
}
HANDLE hResult = __CreateFileA(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
return hResult;
}
HANDLE __stdcall Hook_CreateFileW(LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (wcscmp(lpFileName, L"COM4") == 0 && !JVSAlreadyTaken)
{
HANDLE hResult = __CreateFileW(emuPortW,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
jvsHandle = hResult;
JVSAlreadyTaken = true;
return hResult;
}
HANDLE hResult = __CreateFileW(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
return hResult;
}
static HANDLE hSection = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 64, L"TeknoParrot_JvsState");
static int* secData = (int*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 64);
// Battle gear
int* wheelSection = &secData[1];
int* ffbOffset = &secData[2];
int* ffbOffset2 = &secData[3];
int* ffbOffset3 = &secData[4];
int* ffbOffset4 = &secData[5];
static bool IsCommHooked(HANDLE hFile);
bool check = false;
BOOL __stdcall Hook_GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
{
if (!IsCommHooked(hFile)) {
return __GetCommModemStatus(hFile, lpModemStat);
}
if (hFile != jvsHandle)
{
return TRUE;
}
if(GameDetect::IsTypeX())
{
if (*secData) // addressed?
{
*lpModemStat = 0x10;
}
else
{
*lpModemStat = 0x0;
}
}
else
{
if (*secData) // addressed?
{
*lpModemStat = 0x30; // 0x10
}
else
{
*lpModemStat = 0x10; // 0x0
}
}
return TRUE;
}
#include <set>
static std::set<HANDLE> g_commOverrides;
static bool IsCommHooked(HANDLE hFile)
{
return (hFile == jvsHandle || g_commOverrides.find(hFile) != g_commOverrides.end());
}
void AddCommOverride(HANDLE hFile)
{
g_commOverrides.insert(hFile);
}
BOOL __stdcall Hook_SetCommState(HANDLE hFile, LPDCB lpDCB)
{
if (!IsCommHooked(hFile)) {
return __SetCommState(hFile, lpDCB);
}
return true;
}
BOOL __stdcall Hook_GetCommState(HANDLE hFile, LPDCB lpDCB)
{
if (!IsCommHooked(hFile)) {
return __GetCommState(hFile, lpDCB);
}
return true;
}
BOOL __stdcall Hook_SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
{
if (!IsCommHooked(hFile)) {
return __SetCommTimeouts(hFile, lpCommTimeouts);
}
return true;
}
BOOL __stdcall Hook_GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
{
if (!IsCommHooked(hFile)) {
return __GetCommTimeouts(hFile, lpCommTimeouts);
}
return true;
}
BOOL __stdcall Hook_SetCommMask(HANDLE hFile, DWORD dwEvtMask)
{
if (!IsCommHooked(hFile)) {
return __SetCommMask(hFile, dwEvtMask);
}
return true;
}
BOOL __stdcall Hook_GetCommMask(HANDLE hFile, DWORD* dwEvtMask)
{
if (!IsCommHooked(hFile)) {
return __GetCommMask(hFile, dwEvtMask);
}
return true;
}
BOOL __stdcall Hook_EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
{
if (!IsCommHooked(hFile)) {
return __EscapeCommFunction(hFile, dwFunc);
}
return true;
}
BOOL WINAPI Hook_SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
{
if (!IsCommHooked(hFile))
{
return __SetupComm(hFile, dwInQueue, dwOutQueue);
}
#if defined(_DEBUG)
info(true, "SetupComm(hFile %x, dwInQueue %x, dwOutQueue %x)", hFile, dwInQueue, dwOutQueue);
#endif
return true;
}
BOOL WINAPI Hook_PurgeComm(HANDLE hFile, DWORD dwFlags)
{
if (!IsCommHooked(hFile))
{
return __PurgeComm(hFile, dwFlags);
}
#if defined(WantPurgeCommLogging)
info(true, "PurgeComm(hFile %x, dwFlags %x)", hFile, dwFlags);
#endif
CancelIoEx(hFile, nullptr);
return true;
}
BOOL __stdcall Hook_ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
{
if (!IsCommHooked(hFile))
{
return __ClearCommError(hFile, lpErrors, lpStat);
}
lpStat->cbInQue = 0x7FFF;
return true;
}
#define __XHOOKn(mod, name) \
MH_CreateHookApi(L ## mod, #name, &Hook_##name, (void**)&__##name)
static InitFunction jvsInit([]()
{
if (GameDetect::IsNesicaGame())
{
return;
}
if (GameDetect::IsTypeX())
hookPort = "COM2";
MH_Initialize();
__XHOOKn("kernel32.dll", GetCommState);
__XHOOKn("kernel32.dll", SetCommState);
__XHOOKn("kernel32.dll", GetCommTimeouts);
__XHOOKn("kernel32.dll", SetCommTimeouts);
__XHOOKn("kernel32.dll", GetCommMask);
__XHOOKn("kernel32.dll", SetCommMask);
__XHOOKn("kernel32.dll", SetupComm);
__XHOOKn("kernel32.dll", PurgeComm);
__XHOOKn("kernel32.dll", EscapeCommFunction);
__XHOOKn("kernel32.dll", ClearCommError);
__XHOOKn("kernel32.dll", CreateFileA);
__XHOOKn("kernel32.dll", CreateFileW);
__XHOOKn("kernel32.dll", GetCommModemStatus);
MH_EnableHook(MH_ALL_HOOKS);
});
#pragma optimize("", on)

View File

@ -0,0 +1 @@
#pragma once

View File

@ -0,0 +1,12 @@
enum class X2Type {
None,
RFID,
Digital,
Analog,
VRL,
Raiden4,
BG4,
Lupin3,
Generic,
GaiaAttack4
};

View File

@ -0,0 +1,88 @@
#define CINTERFACE
#include <StdInc.h>
#include "Utility/InitFunction.h"
#pragma optimize("", off)
#include "dx8/d3d8.h"
#include "Utility/GameDetect.h"
IDirect3D8*(WINAPI* g_origDirect3DCreate8)(UINT SDKVersion);
template<typename T>
T HookVtableFunction(T* functionPtr, T target)
{
if (*functionPtr == target)
{
return nullptr;
}
auto old = *functionPtr;
injector::WriteMemory(functionPtr, target, true);
return old;
}
static HRESULT(WINAPI* g_oldReset)(IDirect3DDevice8* self, D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT WINAPI ResetWrap(IDirect3DDevice8* self, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
pPresentationParameters->Windowed = TRUE;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
pPresentationParameters->BackBufferWidth = 0;
pPresentationParameters->BackBufferHeight = 0;
pPresentationParameters->Flags = 0;
pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
return g_oldReset(self, pPresentationParameters);
}
static HRESULT(WINAPI* g_oldCreateDevice)(IDirect3D8* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface);
HRESULT WINAPI CreateDeviceWrap(IDirect3D8* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface)
{
pPresentationParameters->Windowed = TRUE;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
pPresentationParameters->BackBufferWidth = 0;
pPresentationParameters->BackBufferHeight = 0;
pPresentationParameters->Flags = 0;
pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
HRESULT hr = g_oldCreateDevice(self, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
if (*ppReturnedDeviceInterface)
{
auto old = HookVtableFunction(&(*ppReturnedDeviceInterface)->lpVtbl->Reset, ResetWrap);
g_oldReset = (old) ? old : g_oldReset;
}
return hr;
}
IDirect3D8* WINAPI Direct3DCreate8Wrap(UINT SDKVersion)
{
auto d3d9 = g_origDirect3DCreate8(SDKVersion);
auto old = HookVtableFunction(&d3d9->lpVtbl->CreateDevice, CreateDeviceWrap);
g_oldCreateDevice = (old) ? old : g_oldCreateDevice;
return d3d9;
}
void InitD3D8WindowHook()
{
MH_Initialize();
MH_CreateHookApi(L"d3d8.dll", "Direct3DCreate8", Direct3DCreate8Wrap, (void**)&g_origDirect3DCreate8);
MH_EnableHook(MH_ALL_HOOKS);
}
extern linb::ini config;
static InitFunction initFunc([]()
{
if (GameDetect::currentGame == GameID::BG4)
return;
if (ToBool(config["General"]["Windowed"]))
{
InitD3D8WindowHook();
}
});
#pragma optimize("", on)

View File

@ -0,0 +1,80 @@
#define CINTERFACE
#include <StdInc.h>
#include "Utility/InitFunction.h"
#pragma optimize("", off)
#include "d3d9.h"
#include "Utility/GameDetect.h"
IDirect3D9*(WINAPI* g_origDirect3DCreate9)(UINT SDKVersion);
template<typename T>
T HookVtableFunction(T* functionPtr, T target)
{
if (*functionPtr == target)
{
return nullptr;
}
auto old = *functionPtr;
injector::WriteMemory(functionPtr, target, true);
return old;
}
static HRESULT(WINAPI* g_oldReset)(IDirect3DDevice9* self, D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT WINAPI ResetWrap(IDirect3DDevice9* self, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
pPresentationParameters->Windowed = TRUE;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
return g_oldReset(self, pPresentationParameters);
}
static HRESULT(WINAPI* g_oldCreateDevice)(IDirect3D9* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface);
HRESULT WINAPI CreateDeviceWrap(IDirect3D9* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
{
pPresentationParameters->Windowed = TRUE;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
HRESULT hr = g_oldCreateDevice(self, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
if (*ppReturnedDeviceInterface)
{
auto old = HookVtableFunction(&(*ppReturnedDeviceInterface)->lpVtbl->Reset, ResetWrap);
g_oldReset = (old) ? old : g_oldReset;
}
return hr;
}
IDirect3D9* WINAPI Direct3DCreate9Wrap(UINT SDKVersion)
{
auto d3d9 = g_origDirect3DCreate9(SDKVersion);
auto old = HookVtableFunction(&d3d9->lpVtbl->CreateDevice, CreateDeviceWrap);
g_oldCreateDevice = (old) ? old : g_oldCreateDevice;
return d3d9;
}
void InitD3D9WindowHook()
{
MH_Initialize();
MH_CreateHookApi(L"d3d9.dll", "Direct3DCreate9", Direct3DCreate9Wrap, (void**)&g_origDirect3DCreate9);
MH_EnableHook(MH_ALL_HOOKS);
}
extern linb::ini config;
static InitFunction initFunc([]()
{
if (GameDetect::currentGame == GameID::BG4)
return;
if (ToBool(config["General"]["Windowed"]))
{
InitD3D9WindowHook();
}
});
#pragma optimize("", on)

View File

@ -0,0 +1,251 @@
#define CINTERFACE
#define D3D11_NO_HELPERS
#define INITGUID
#include <StdInc.h>
#ifdef _M_AMD64
#include "Utility/InitFunction.h"
#pragma optimize("", off)
#include "d3d11.h"
#include "dxgi1_6.h"
#include "Utility/GameDetect.h"
HRESULT(WINAPI* g_origCreateDXGIFactory)(REFIID, void**);
template<typename T>
inline T HookVtableFunction(T* functionPtr, T target)
{
if (*functionPtr == target)
{
return nullptr;
}
auto old = *functionPtr;
injector::WriteMemory(functionPtr, target, true);
return old;
}
HRESULT(WINAPI* g_oldCreateSwapChain)(
IDXGIFactory * This,
/* [annotation][in] */
_In_ IUnknown *pDevice,
/* [annotation][in] */
_In_ DXGI_SWAP_CHAIN_DESC *pDesc,
/* [annotation][out] */
_COM_Outptr_ IDXGISwapChain **ppSwapChain);
HRESULT(STDMETHODCALLTYPE *g_oldSetFullscreenState)(
IDXGISwapChain * This,
/* [in] */ BOOL Fullscreen,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pTarget);
HRESULT STDMETHODCALLTYPE SetFullscreenStateWrap(
IDXGISwapChain * This,
/* [in] */ BOOL Fullscreen,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pTarget)
{
return S_OK;
}
HRESULT WINAPI CreateSwapChainWrap(
IDXGIFactory * This,
/* [annotation][in] */
_In_ IUnknown *pDevice,
/* [annotation][in] */
_In_ DXGI_SWAP_CHAIN_DESC *pDesc,
/* [annotation][out] */
_COM_Outptr_ IDXGISwapChain **ppSwapChain)
{
pDesc->Windowed = TRUE;
HRESULT hr = g_oldCreateSwapChain(This, pDevice, pDesc, ppSwapChain);
if (*ppSwapChain)
{
auto old = HookVtableFunction(&(*ppSwapChain)->lpVtbl->SetFullscreenState, SetFullscreenStateWrap);
g_oldSetFullscreenState = (old) ? old : g_oldSetFullscreenState;
}
return hr;
}
HRESULT(STDMETHODCALLTYPE *g_oldSetFullscreenState1)(
IDXGISwapChain1 * This,
/* [in] */ BOOL Fullscreen,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pTarget);
HRESULT STDMETHODCALLTYPE SetFullscreenState1Wrap(
IDXGISwapChain1 * This,
/* [in] */ BOOL Fullscreen,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pTarget)
{
return S_OK;
}
HRESULT(STDMETHODCALLTYPE *g_oldCreateSwapChainForHwnd)(
IDXGIFactory2 * This,
/* [annotation][in] */
_In_ IUnknown *pDevice,
/* [annotation][in] */
_In_ HWND hWnd,
/* [annotation][in] */
_In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc,
/* [annotation][in] */
_In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pRestrictToOutput,
/* [annotation][out] */
_COM_Outptr_ IDXGISwapChain1 **ppSwapChain);
HRESULT STDMETHODCALLTYPE CreateSwapChainForHwndWrap(
IDXGIFactory2 * This,
/* [annotation][in] */
_In_ IUnknown *pDevice,
/* [annotation][in] */
_In_ HWND hWnd,
/* [annotation][in] */
_In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc,
/* [annotation][in] */
_In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc,
/* [annotation][in] */
_In_opt_ IDXGIOutput *pRestrictToOutput,
/* [annotation][out] */
_COM_Outptr_ IDXGISwapChain1 **ppSwapChain)
{
HRESULT hr = g_oldCreateSwapChainForHwnd(This, pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);
if (*ppSwapChain)
{
auto old = HookVtableFunction(&(*ppSwapChain)->lpVtbl->SetFullscreenState, SetFullscreenState1Wrap);
g_oldSetFullscreenState1 = (old) ? old : g_oldSetFullscreenState1;
}
return hr;
}
HRESULT WINAPI CreateDXGIFactoryWrap(REFIID riid, _COM_Outptr_ void **ppFactory)
{
HRESULT hr = g_origCreateDXGIFactory(riid, ppFactory);
if (SUCCEEDED(hr))
{
int factoryType = 0;
if (IsEqualIID(riid, IID_IDXGIFactory1))
{
factoryType = 1;
}
else if (IsEqualIID(riid, IID_IDXGIFactory2))
{
factoryType = 2;
}
else if (IsEqualIID(riid, IID_IDXGIFactory2))
{
factoryType = 2;
}
else if (IsEqualIID(riid, IID_IDXGIFactory3))
{
factoryType = 3;
}
else if (IsEqualIID(riid, IID_IDXGIFactory4))
{
factoryType = 4;
}
else if (IsEqualIID(riid, IID_IDXGIFactory5))
{
factoryType = 5;
}
if (factoryType >= 0)
{
IDXGIFactory* factory = (IDXGIFactory*)*ppFactory;
auto old = HookVtableFunction(&factory->lpVtbl->CreateSwapChain, CreateSwapChainWrap);
g_oldCreateSwapChain = (old) ? old : g_oldCreateSwapChain;
}
if (factoryType >= 2)
{
IDXGIFactory2* factory = (IDXGIFactory2*)*ppFactory;
auto old = HookVtableFunction(&factory->lpVtbl->CreateSwapChainForHwnd, CreateSwapChainForHwndWrap);
g_oldCreateSwapChainForHwnd = (old) ? old : g_oldCreateSwapChainForHwnd;
}
}
return hr;
}
static HRESULT (WINAPI* g_origD3D11CreateDeviceAndSwapChain)(
_In_opt_ IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
_In_opt_ const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
_In_opt_ const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
_Out_opt_ IDXGISwapChain **ppSwapChain,
_Out_opt_ ID3D11Device **ppDevice,
_Out_opt_ D3D_FEATURE_LEVEL *pFeatureLevel,
_Out_opt_ ID3D11DeviceContext **ppImmediateContext
);
static HRESULT WINAPI D3D11CreateDeviceAndSwapChainWrap(
_In_opt_ IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
_In_opt_ const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
_In_opt_ /*const*/ DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
_Out_opt_ IDXGISwapChain **ppSwapChain,
_Out_opt_ ID3D11Device **ppDevice,
_Out_opt_ D3D_FEATURE_LEVEL *pFeatureLevel,
_Out_opt_ ID3D11DeviceContext **ppImmediateContext
)
{
pSwapChainDesc->Windowed = TRUE;
HRESULT hr = g_origD3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
if (ppSwapChain)
{
auto old = HookVtableFunction(&(*ppSwapChain)->lpVtbl->SetFullscreenState, SetFullscreenStateWrap);
g_oldSetFullscreenState = (old) ? old : g_oldSetFullscreenState;
}
return hr;
}
void InitDXGIWindowHook()
{
MH_Initialize();
MH_CreateHookApi(L"dxgi.dll",
"CreateDXGIFactory",
CreateDXGIFactoryWrap,
(void**)&g_origCreateDXGIFactory);
MH_CreateHookApi(L"d3d11.dll",
"D3D11CreateDeviceAndSwapChain", D3D11CreateDeviceAndSwapChainWrap,
(void**)&g_origD3D11CreateDeviceAndSwapChain);
MH_EnableHook(MH_ALL_HOOKS);
}
extern linb::ini config;
static InitFunction initFunc([]()
{
if (GameDetect::currentGame == GameID::SchoolOfRagnarok)
return;
if (ToBool(config["General"]["Windowed"]))
{
InitDXGIWindowHook();
}
});
#endif

View File

@ -0,0 +1 @@
#include <StdInc.h>

19
OpenParrot/src/StdInc.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
// os includes
#define DEVMODE
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ws2tcpip.h>
// lib includes
#include <stdint.h>
// our includes
#include "injector/injector.hpp"
#include "injector/calling.hpp"
#include "Utility/Utils.h"
#include "ini_parser.hpp"
extern linb::ini config;

View File

@ -0,0 +1,256 @@
#include <StdInc.h>
#include "GameDetect.h"
#pragma optimize("", off)
bool GameDetect::isNesica = false;
NesicaKey GameDetect::NesicaKey;
X2Type GameDetect::X2Type = X2Type::None;
void GameDetect::DetectCurrentGame()
{
uint32_t crcResult = GetCRC32(GetModuleHandle(nullptr), 0x400);
NesicaKey = NesicaKey::None;
switch (crcResult)
{
#if _M_IX86
case 0xcb4ab9d6:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::USF4;
isNesica = true;
break;
case 0x1d396bf2:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::MagicalBeat;
isNesica = true;
break;
case 0x6e67076f:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::BlazBlueCentralFriction;
isNesica = true;
break;
case 0xde1b6797:
case 0xaff18f9b:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::BlazBlueChronoPhantasma;
isNesica = true;
break;
case 0x05e53803:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::KOFXIIIClimax;
isNesica = true;
break;
case 0x949efa20:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::Persona4Arena;
isNesica = true;
break;
case 0x6b233485:
case 0xec97cef0:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::Persona4Ultimix;
isNesica = true;
break;
case 0xffe46764: // Akai Katana Shin
case 0x48362a6a:
currentGame = GameID::Nesica;
NesicaKey = NesicaKey::None;
isNesica = true;
break;
case 0x6DA10E60:
currentGame = GameID::FordRacing;
break;
case 0x2B41A7EA:
currentGame = GameID::SR3;
break;
case 0x47da80e5: // Spica Adventure
currentGame = GameID::SpicaAdventure;
X2Type = X2Type::Generic;
break;
//case 0xcdf01376: // Battle Fantasia
case 0xf9297ecb: // BlazBlue
currentGame = GameID::BlazBlue;
X2Type = X2Type::Generic;
break;
case 0xee568daa: // BlazBlue Continuum Shift II
currentGame = GameID::BlazBlueCS2;
X2Type = X2Type::Generic;
break;
case 0x4414288e: // BlazBlue Continuum Shift
currentGame = GameID::BlazBlueCS;
X2Type = X2Type::Generic;
break;
// case 0xea1984ff: // Deathsmiles II
case 0xe064ed48: // Giga Wing Generations
currentGame = GameID::GigaWingGenerations;
X2Type = X2Type::Generic;
break;
case 0xc336abc8: // King of Fighter 98 Unlimited Match
currentGame = GameID::KOF98UM;
X2Type = X2Type::Generic;
break;
case 0x1782f027: // KOF MIRA
currentGame = GameID::KOFMIRA;
X2Type = X2Type::Generic;
break;
case 0x15c690de: // KOF SkyStage
case 0xc0e5e71c: // KOF SkyStage
currentGame = GameID::KOFSkyStage;
X2Type = X2Type::Generic;
break;
case 0x9603cd6e: // KOF XII
currentGame = GameID::KOFXII;
X2Type = X2Type::Generic;
break;
case 0x3de0a15a: // KOF XIII
currentGame = GameID::KOFXIII;
X2Type = X2Type::Generic;
break;
case 0x777df862: // Power Instinct V
currentGame = GameID::PowerInstinctV;
X2Type = X2Type::Generic;
break;
case 0x4aafd08c: // Raiden III
currentGame = GameID::RaidenIII;
X2Type = X2Type::Generic;
break;
case 0x6c2d2657: // Senko No Ronde Duo
currentGame = GameID::SenkoNoRondeDuo;
X2Type = X2Type::Generic;
break;
case 0xb0e19321: // Shigami 3
currentGame = GameID::Shigami3;
X2Type = X2Type::Generic;
break;
case 0xddd19e50: // Street Fighter IV
currentGame = GameID::SF4;
X2Type = X2Type::Generic;
break;
case 0x5a5526b2: // Street Fighter IV Arcade Edition
currentGame = GameID::SSFAE;
X2Type = X2Type::Generic;
break;
case 0x282de00f: // Street Fighter IV Arcade Edition EXP
currentGame = GameID::SSFAE_EXP;
X2Type = X2Type::Generic;
break;
case 0xef843fd1: // Super Street Fighter IV Arcade Edition Ver. 2012
currentGame = GameID::SSFAE2012;
X2Type = X2Type::Generic;
break;
case 0xcb2c2568: // Trouble Witches
currentGame = GameID::TroubleWitches;
X2Type = X2Type::Generic;
break;
case 0xf795d548: // Tetris The Grand Master 3 Terror Instinct
currentGame = GameID::TetrisGM3;
X2Type = X2Type::Generic;
break;
case 0xdca0c880: // Chaos Breaker
currentGame = GameID::ChaosBreaker;
X2Type = X2Type::Generic;
break;
case 0xf2d38452: // Taisen Hot Gimmick 5
currentGame = GameID::TaisenHotGimmick5;
X2Type = X2Type::Generic;
break;
case 0x9646805d: // Samurai Spirits Sen
currentGame = GameID::SamuraiSpiritsSen;
X2Type = X2Type::Generic;
break;
case 0x185fd019: // Wacky Races
currentGame = GameID::WackyRaces;
X2Type = X2Type::Generic;
break;
case 0x1f2f9497: // Chase HQ 2
currentGame = GameID::ChaseHq2;
X2Type = X2Type::Generic;
break;
case 0x45121869: // Virtua R-Limit
currentGame = GameID::VirtuaRLimit;
X2Type = X2Type::VRL;
break;
case 0x7b43b0dc: // Raiden IV
currentGame = GameID::RaidenIV;
X2Type = X2Type::Raiden4;
break;
case 0x14eb3c8a: // Battle Gear 4 Tuned Professional
currentGame = GameID::BG4;
X2Type = X2Type::BG4;
break;
case 0xf5d90f01: // Music GunGun 2
currentGame = GameID::TypeXGeneric;
break;
case 0xabcebc43: // Lupin 3
currentGame = GameID::TypeXGeneric;
X2Type = X2Type::Lupin3;
break;
#endif
default:
auto moduleBase = (uintptr_t)GetModuleHandle(nullptr);
// SPECIAL BYTE PATTERNS (IF PE CHANGES DUE TO DYNAMIC IMAGEBASE)
#if _M_IX86
if (*(uint32_t*)(moduleBase + 0x30E838) == 0x6A50016A)
{
currentGame = GameID::MachStorm;
break;
}
#else
// X64
// School of Ragnarok
if (*(uint32_t *)(moduleBase + 0x396E) == 0x2180B841)
{
currentGame = GameID::SchoolOfRagnarok;
isNesica = true;
}
#endif
#ifdef _DEBUG
info(true, "%08x not implemented", crcResult);
#endif
break;
}
}
bool GameDetect::IsNesicaGame()
{
return isNesica;
}
bool GameDetect::IsTypeX()
{
switch (GameDetect::currentGame)
{
case GameID::TypeXGeneric:
case GameID::SpicaAdventure:
case GameID::BlazBlue:
case GameID::BlazBlueCS:
case GameID::BlazBlueCS2:
case GameID::GigaWingGenerations:
case GameID::KOF98UM:
case GameID::KOFMIRA:
case GameID::KOFSkyStage:
case GameID::KOFXII:
case GameID::KOFXIII:
case GameID::PowerInstinctV:
case GameID::RaidenIII:
case GameID::SenkoNoRondeDuo:
case GameID::Shigami3:
case GameID::SF4:
case GameID::SSFAE:
case GameID::SSFAE_EXP:
case GameID::SSFAE2012:
case GameID::TroubleWitches:
case GameID::TetrisGM3:
case GameID::ChaosBreaker:
case GameID::TaisenHotGimmick5:
case GameID::SamuraiSpiritsSen:
case GameID::WackyRaces:
case GameID::ChaseHq2:
case GameID::BG4:
case GameID::RaidenIV:
case GameID::VirtuaRLimit:
return true;
default:
return false;
}
}
GameID GameDetect::currentGame;
#pragma optimize("", on)

View File

@ -0,0 +1,19 @@
#include "GameID.h"
#include "Functions/Nesica_Libs/CryptoPipe.h"
#include "Functions/Types.h"
class GameDetect
{
public:
static GameID currentGame;
static void DetectCurrentGame();
static X2Type X2Type;
static bool IsTypeX();
static bool IsNesicaGame();
static NesicaKey NesicaKey;
static std::string GetGameName();
static std::string GameDetect::GetGameName(GameID game);
private:
static bool isNesica;
};

View File

@ -0,0 +1,41 @@
#pragma once
enum class GameID
{
Global,
FordRacing,
SR3,
VRL,
MachStorm,
Nesica,
TypeXGeneric,
SpicaAdventure,
BlazBlue,
BlazBlueCS,
BlazBlueCS2,
GigaWingGenerations,
KOF98UM,
KOFMIRA,
KOFSkyStage,
KOFXII,
KOFXIII,
PowerInstinctV,
RaidenIII,
SenkoNoRondeDuo,
Shigami3,
SF4,
SSFAE,
SSFAE_EXP,
SSFAE2012,
TroubleWitches,
TetrisGM3,
ChaosBreaker,
TaisenHotGimmick5,
SamuraiSpiritsSen,
WackyRaces,
ChaseHq2,
BG4,
RaidenIV,
VirtuaRLimit,
SchoolOfRagnarok,
};

View File

@ -0,0 +1,350 @@
/*
* This file is part of the CitizenFX project - http://citizen.re/
*
* See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing.
*/
#include "Hooking.Patterns.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <algorithm>
#if PATTERNS_USE_HINTS
#include <map>
#endif
#if PATTERNS_USE_HINTS
// from boost someplace
template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
struct basic_fnv_1
{
std::uint64_t operator()(const char *text) const
{
std::uint64_t hash = OffsetBasis;
while (*text != 0)
{
hash *= FnvPrime;
hash ^= *(uint8_t *)text;
++text;
}
return hash;
}
};
const std::uint64_t fnv_prime = 1099511628211u;
const std::uint64_t fnv_offset_basis = 14695981039346656037u;
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
#endif
namespace hook
{
ptrdiff_t baseAddressDifference;
// sets the base to the process main base
void set_base()
{
set_base((uintptr_t)GetModuleHandle(nullptr));
}
#if PATTERNS_USE_HINTS
static std::multimap<uint64_t, uintptr_t> g_hints;
#endif
static void TransformPattern(const char *pattern, std::vector<uint8_t>& data, std::vector<uint8_t>& mask)
{
auto tol = [](char ch) -> uint8_t
{
if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10);
if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10);
return uint8_t(ch - '0');
};
auto is_digit = [](char ch) -> bool
{
return (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9');
};
char temp_string[2]{ 0, 0 };
data.clear();
mask.clear();
if (!pattern)
{
return;
}
const char *patit = pattern;
const char *patend = (pattern + strlen(pattern) + 1);
while (patit != patend)
{
char ch = *patit;
if (ch == ' ' || ch == 0)
{
if (!temp_string[0] && !temp_string[1]) //Continous delimiter
{
}
else if (temp_string[0] == '?' && (temp_string[1] == '?' || temp_string[1] == 0)) //??
{
data.push_back(0);
mask.push_back(0u);
}
else if (temp_string[0] == '?' && is_digit(temp_string[1])) //?x
{
data.push_back(tol(temp_string[1]));
mask.push_back(0x0Fu);
}
else if (temp_string[1] == '?' && is_digit(temp_string[0])) //x?
{
data.push_back(tol(temp_string[0]) << 4);
mask.push_back(0xF0u);
}
else if (is_digit(temp_string[0]) && is_digit(temp_string[1])) //xx
{
data.push_back((tol(temp_string[0]) << 4) | tol(temp_string[1]));
mask.push_back(0xFFu);
}
else
{
data.clear();
mask.clear();
return;
}
temp_string[0] = 0;
temp_string[1] = 0;
}
else
{
if (temp_string[0] == 0)
{
temp_string[0] = ch;
}
else if (temp_string[1] == 0)
{
temp_string[1] = ch;
}
else
{
data.clear();
mask.clear();
return;
}
}
++patit;
}
}
class executable_meta
{
private:
uintptr_t m_begin;
uintptr_t m_end;
public:
template<typename TReturn, typename TOffset>
TReturn* getRVA(TOffset rva)
{
return (TReturn*)(m_begin + rva);
}
explicit executable_meta(void* module)
: m_begin((uintptr_t)module), m_end(0)
{
static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER
{
return reinterpret_cast<PIMAGE_SECTION_HEADER>(
(UCHAR*)nt_headers->OptionalHeader.DataDirectory +
nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) +
section * sizeof(IMAGE_SECTION_HEADER));
};
PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0);
PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);
for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++)
{
auto sec = getSection(ntHeader, i);
auto secSize = sec->SizeOfRawData != 0 ? sec->SizeOfRawData : sec->Misc.VirtualSize;
//if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE)
m_end = m_begin + sec->VirtualAddress + secSize;
if ((i == ntHeader->FileHeader.NumberOfSections - 1) && m_end == 0)
m_end = m_begin + sec->PointerToRawData + secSize;
}
}
executable_meta(uintptr_t begin, uintptr_t end)
: m_begin(begin), m_end(end)
{
}
inline uintptr_t begin() const { return m_begin; }
inline uintptr_t end() const { return m_end; }
};
void pattern::Initialize(const char* pattern)
{
// get the hash for the base pattern
#if PATTERNS_USE_HINTS
m_hash = fnv_1()(pattern);
#endif
// transform the base pattern from IDA format to canonical format
TransformPattern(pattern, m_bytes, m_mask);
m_size = m_mask.size();
#if PATTERNS_USE_HINTS
// if there's hints, try those first
if (m_module == GetModuleHandle(nullptr))
{
auto range = g_hints.equal_range(m_hash);
if (range.first != range.second)
{
std::for_each(range.first, range.second, [&] (const std::pair<uint64_t, uintptr_t>& hint)
{
ConsiderMatch(hint.second);
});
// if the hints succeeded, we don't need to do anything more
if (!m_matches.empty())
{
m_matched = true;
return;
}
}
}
#endif
}
void pattern::EnsureMatches(uint32_t maxCount)
{
if (m_matched)
return;
if (!m_rangeStart && !m_rangeEnd && !m_module)
return;
// scan the executable for code
executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_module);
auto matchSuccess = [&] (uintptr_t address)
{
#if PATTERNS_USE_HINTS
g_hints.emplace(m_hash, address);
#else
(void)address;
#endif
return (m_matches.size() == maxCount);
};
ptrdiff_t BadCharacter[256];
std::ptrdiff_t index;
const std::uint8_t *pbytes = m_bytes.data();
const std::uint8_t *pmask = m_mask.data();
for (std::uint32_t bc = 0; bc < 256; ++bc)
{
for (index = m_size - 1; index >= 0; --index)
{
if ((pbytes[index] & pmask[index]) == (bc & pmask[index]))
{
break;
}
}
BadCharacter[bc] = index;
}
__try
{
for (uintptr_t i = executable.begin(), end = executable.end() - m_size; i <= end;)
{
uint8_t* ptr = reinterpret_cast<uint8_t*>(i);
for (index = m_size - 1; index >= 0; --index)
{
if ((pbytes[index] & pmask[index]) != (ptr[index] & pmask[index]))
{
break;
}
}
if (index == -1)
{
m_matches.emplace_back(ptr);
if (matchSuccess(i))
{
break;
}
i += m_size;
}
else
{
i += max(index - BadCharacter[ptr[index]], 1);
}
}
}
__except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{ }
m_matched = true;
}
bool pattern::ConsiderMatch(uintptr_t offset)
{
const uint8_t* pattern = m_bytes.data();
const uint8_t* mask = m_mask.data();
char* ptr = reinterpret_cast<char*>(offset);
for (size_t i = 0; i < m_size; i++)
{
if ((pattern[i] & mask[i]) != (ptr[i] & mask[i]))
{
return false;
}
}
m_matches.emplace_back(ptr);
return true;
}
#if PATTERNS_USE_HINTS
void pattern::hint(uint64_t hash, uintptr_t address)
{
auto range = g_hints.equal_range(hash);
for (auto it = range.first; it != range.second; it++)
{
if (it->second == address)
{
return;
}
}
g_hints.emplace(hash, address);
}
#endif
}

View File

@ -0,0 +1,242 @@
/*
* This file is part of the CitizenFX project - http://citizen.re/
*
* See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing.
*/
#pragma once
#define PATTERNS_USE_HINTS 0
#include <cassert>
#include <vector>
namespace hook
{
extern ptrdiff_t baseAddressDifference;
// sets the base address difference based on an obtained pointer
inline void set_base(uintptr_t address)
{
#ifdef _M_IX86
uintptr_t addressDiff = (address - 0x400000);
#elif defined(_M_AMD64)
uintptr_t addressDiff = (address - 0x140000000);
#endif
// pointer-style cast to ensure unsigned overflow ends up copied directly into a signed value
baseAddressDifference = *(ptrdiff_t*)&addressDiff;
}
// sets the base to the process main base
void set_base();
template<typename T>
inline T* getRVA(uintptr_t rva)
{
set_base();
#ifdef _M_IX86
return (T*)(baseAddressDifference + 0x400000 + rva);
#elif defined(_M_AMD64)
return (T*)(baseAddressDifference + 0x140000000 + rva);
#endif
}
class pattern_match
{
private:
void* m_pointer;
public:
inline pattern_match(void* pointer)
: m_pointer(pointer)
{
}
template<typename T>
T* get(ptrdiff_t offset = 0) const
{
char* ptr = reinterpret_cast<char*>(m_pointer);
return reinterpret_cast<T*>(ptr + offset);
}
};
class pattern
{
private:
std::vector<uint8_t> m_bytes;
std::vector<uint8_t> m_mask;
#if PATTERNS_USE_HINTS
uint64_t m_hash;
#endif
size_t m_size;
std::vector<pattern_match> m_matches;
bool m_matched;
union
{
void* m_module;
struct
{
uintptr_t m_rangeStart;
uintptr_t m_rangeEnd;
};
};
protected:
inline pattern(void* module)
: m_module(module), m_rangeEnd(0), m_matched(false)
{
}
inline pattern(uintptr_t begin, uintptr_t end)
: m_rangeStart(begin), m_rangeEnd(end), m_matched(false)
{
}
void Initialize(const char* pattern);
private:
bool ConsiderMatch(uintptr_t offset);
void EnsureMatches(uint32_t maxCount);
inline const pattern_match& _get_internal(size_t index)
{
return m_matches[index];
}
public:
pattern()
: m_matched(true)
{
}
pattern(const char *pattern)
: pattern(getRVA<void>(0))
{
Initialize(pattern);
}
pattern(std::string& pattern)
: pattern(getRVA<void>(0))
{
Initialize(pattern.c_str());
}
inline pattern& count(uint32_t expected)
{
EnsureMatches(expected);
assert(m_matches.size() == expected);
return *this;
}
inline pattern& count_hint(uint32_t expected)
{
EnsureMatches(expected);
return *this;
}
inline pattern& clear(void* module = nullptr)
{
if (module)
m_module = module;
m_matches.clear();
m_matched = false;
return *this;
}
inline size_t size()
{
EnsureMatches(UINT32_MAX);
return m_matches.size();
}
inline bool empty()
{
return size() == 0;
}
inline const pattern_match& get(size_t index)
{
EnsureMatches(UINT32_MAX);
return _get_internal(index);
}
inline const pattern_match& get_one()
{
return count(1)._get_internal(0);
}
template<typename T = void>
inline auto get_first(ptrdiff_t offset = 0)
{
return get_one().get<T>(offset);
}
template <typename Fn>
pattern &for_each_result(Fn Pr)
{
EnsureMatches(UINT32_MAX);
for (auto &result : this->m_matches)
{
Pr(result);
}
return *this;
}
public:
#if PATTERNS_USE_HINTS
// define a hint
static void hint(uint64_t hash, uintptr_t address);
#endif
};
class module_pattern
: public pattern
{
public:
module_pattern(void* module, const char *pattern)
: pattern(module)
{
Initialize(pattern);
}
module_pattern(void* module, std::string& pattern)
: pattern(module)
{
Initialize(pattern.c_str());
}
};
class range_pattern
: public pattern
{
public:
range_pattern(uintptr_t begin, uintptr_t end, const char *pattern)
: pattern(begin, end)
{
Initialize(pattern);
}
range_pattern(uintptr_t begin, uintptr_t end, std::string& pattern)
: pattern(begin, end)
{
Initialize(pattern.c_str());
}
};
template<typename T = void>
auto get_pattern(const char *pattern_string, ptrdiff_t offset = 0)
{
return pattern(pattern_string).get_first<T>(offset);
}
}

View File

@ -0,0 +1,28 @@
#include <StdInc.h>
#include "InitFunction.h"
#include <forward_list>
std::forward_list<InitFunction*>* g_initFunctions;
InitFunction::InitFunction(void(*callback)(), GameID gameID)
: callback(callback), game(gameID)
{
if (!g_initFunctions)
{
g_initFunctions = new std::forward_list<InitFunction*>();
}
g_initFunctions->push_front(this);
}
void InitFunction::RunFunctions(GameID game)
{
for (auto& it : *g_initFunctions)
{
if (it->game == game)
{
it->callback();
}
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "GameID.h"
class InitFunction
{
public:
InitFunction(void(*callback)(), GameID game = GameID::Global);
static void RunFunctions(GameID game);
private:
void(*callback)();
GameID game;
};

View File

@ -0,0 +1,160 @@
#include <StdInc.h>
#include <string>
#include <vector>
#include <sstream>
#include <codecvt>
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ ((BYTE)octet)) & 0xff] ^ ((crc) >> 8))
uint32_t GetCRC32(const void* pData, int length)
{
uint32_t _crc = 0xFFFFFFFF;
unsigned char* pCur = (unsigned char*)pData;
int remaining = length;
for (; remaining--; ++pCur)
_crc = (_crc >> 8) ^ kCrc32Table[(_crc ^ *pCur) & 0xff];
return _crc ^ 0xFFFFFFFF;
}
#ifdef _DEBUG
void info(bool unused, const char* format, ...)
{
va_list args;
char buffer[1024];
va_start(args, format);
int len = _vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
buffer[len] = '\n';
buffer[len + 1] = '\0';
OutputDebugStringA(buffer);
}
#endif
int strcmp(const char* str1, const char* str2, bool csensitive)
{
return (csensitive ? ::strcmp(str1, str2) : ::_stricmp(str1, str2));
}
int Compare(const std::string& str1, const std::string& str2, bool case_sensitive)
{
if (str1.length() == str2.length())
return strcmp(str1.c_str(), str2.c_str(), case_sensitive);
return (str1.length() < str2.length() ? -1 : 1);
}
bool ToBool(const std::string& s)
{
if (s.empty())
{
return false;
}
if (s.size() == 1) return s.front() != '0';
return !!Compare(s, "false", false);
}
bool IpToByte(const char* ip, char bytes[4])
{
return (sscanf(ip, "%hhu.%hhu.%hhu.%hhu", &bytes[0], &bytes[1], &bytes[2], &bytes[3]) == 4);
}
DWORD crc32buf(unsigned char *buf, size_t len)
{
register DWORD oldcrc32;
oldcrc32 = 0xFFFFFFFF;
for (; len; --len, ++buf)
{
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
void GetDesktopResolution(int& x, int& y)
{
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &desktop);
x = desktop.right;
y = desktop.bottom;
}
#define BUFFER_COUNT 8
#define BUFFER_LENGTH 32768
const char* va(const char* string, ...)
{
static thread_local int currentBuffer;
static thread_local std::vector<char> buffer;
if (!buffer.size())
{
buffer.resize(BUFFER_COUNT * BUFFER_LENGTH);
}
int thisBuffer = currentBuffer;
va_list ap;
va_start(ap, string);
int length = vsnprintf(&buffer[thisBuffer * BUFFER_LENGTH], BUFFER_LENGTH, string, ap);
va_end(ap);
if (length >= BUFFER_LENGTH)
{
//GlobalError("Attempted to overrun string in call to va()!");
return "";
}
buffer[(thisBuffer * BUFFER_LENGTH) + BUFFER_LENGTH - 1] = '\0';
currentBuffer = (currentBuffer + 1) % BUFFER_COUNT;
return &buffer[thisBuffer * BUFFER_LENGTH];
}
const wchar_t* va(const wchar_t* string, ...)
{
static thread_local int currentBuffer;
static thread_local std::vector<wchar_t> buffer;
if (!buffer.size())
{
buffer.resize(BUFFER_COUNT * BUFFER_LENGTH);
}
int thisBuffer = currentBuffer;
va_list ap;
va_start(ap, string);
int length = vswprintf(&buffer[thisBuffer * BUFFER_LENGTH], BUFFER_LENGTH, string, ap);
va_end(ap);
if (length >= BUFFER_LENGTH)
{
//GlobalError("Attempted to overrun string in call to va()!");
return L"";
}
buffer[(thisBuffer * BUFFER_LENGTH) + BUFFER_LENGTH - 1] = '\0';
currentBuffer = (currentBuffer + 1) % BUFFER_COUNT;
return &buffer[thisBuffer * BUFFER_LENGTH];
}
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> m_converter;
std::string ToNarrow(const std::wstring& wide)
{
return m_converter.to_bytes(wide);
}
std::wstring ToWide(const std::string& narrow)
{
return m_converter.from_bytes(narrow);
}

View File

@ -0,0 +1,149 @@
#pragma once
#include <string>
#ifdef _DEBUG
void info(bool unused, const char* format, ...);
#endif
#include <MinHook.h>
inline void safeJMP(injector::memory_pointer_tr at, injector::memory_pointer_raw dest, bool vp = true)
{
if (!at.is_null())
{
#ifdef _M_IX86
injector::MakeJMP(at, dest, vp);
#else
MH_Initialize();
MH_CreateHook((void*)at.as_int(), (void*)dest.as_int(), nullptr);
MH_EnableHook((void*)at.as_int());
#endif
}
}
uint32_t GetCRC32(const void* pData, int length);
DWORD crc32buf(unsigned char *buf, size_t len);
void GetDesktopResolution(int& x, int& y);
static const unsigned int kCrc32Table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
}; // kCrc32Table
static DWORD crc_32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
bool ToBool(const std::string& s);
bool IpToByte(const char* ip, char bytes[4]);
const char* va(const char* string, ...);
const wchar_t* va(const wchar_t* string, ...);
std::wstring ToWide(const std::string& narrow);
std::string ToNarrow(const std::wstring& wide);

114
OpenParrot/src/dllmain.cpp Normal file
View File

@ -0,0 +1,114 @@
#include <StdInc.h>
#include <Utility/InitFunction.h>
#include <Utility/GameDetect.h>
linb::ini config;
#include <Functions/Global.h>
#pragma optimize("", off)
static void RunMain();
static BYTE originalCode[20];
extern "C" PBYTE originalEP = 0;
void Main_UnprotectModule(HMODULE hModule)
{
PIMAGE_DOS_HEADER header = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + header->e_lfanew);
// unprotect the entire PE image
SIZE_T size = ntHeader->OptionalHeader.SizeOfImage;
DWORD oldProtect;
VirtualProtect((LPVOID)hModule, size, PAGE_EXECUTE_READWRITE, &oldProtect);
}
#ifdef _M_AMD64
extern "C" void Main_DoResume();
#endif
static void Main_DoInit()
{
RunMain();
memcpy(originalEP, &originalCode, sizeof(originalCode));
#if _M_IX86
__asm jmp originalEP
#elif defined(_M_AMD64)
Main_DoResume();
#endif
}
static void Main_SetSafeInit()
{
// find the entry point for the executable process, set page access, and replace the EP
HMODULE hModule = GetModuleHandle(NULL);
if (hModule)
{
PIMAGE_DOS_HEADER header = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + header->e_lfanew);
Main_UnprotectModule(hModule);
// back up original code
PBYTE ep = (PBYTE)((DWORD_PTR)hModule + ntHeader->OptionalHeader.AddressOfEntryPoint);
memcpy(originalCode, ep, sizeof(originalCode));
#ifdef _M_IX86
// patch to call our EP
int newEP = (int)Main_DoInit - ((int)ep + 5);
ep[0] = 0xE9; // for some reason this doesn't work properly when run under the debugger
memcpy(&ep[1], &newEP, 4);
#elif defined(_M_AMD64)
ep[0] = 0x48;
ep[1] = 0xB8;
*(uint64_t *)(ep + 2) = (uint64_t)Main_DoInit;
ep[10] = 0xFF;
ep[11] = 0xE0;
#endif
originalEP = ep;
}
}
static void RunMain()
{
static bool initialized;
if (initialized)
{
return;
}
initialized = true;
if (!config.load_file("teknoparrot.ini"))
{
//MessageBoxA(NULL, V("Failed to open config.ini"), V("TeknoParrot",) MB_OK);
//std::_Exit(0);
}
GameDetect::DetectCurrentGame();
InitFunction::RunFunctions(GameID::Global);
InitFunction::RunFunctions(GameDetect::currentGame);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
#ifdef DEVMODE
RunMain();
#else
Main_SetSafeInit();
#endif
}
return TRUE; // false
}
extern "C" __declspec(dllexport) void InitializeASI()
{
RunMain();
}
#pragma optimize("", on)

View File

@ -0,0 +1,17 @@
_TEXT SEGMENT
EXTERN originalEP:qword
PUBLIC Main_DoResume
Main_DoResume PROC
and rsp, 0FFFFFFFFFFFFFFF0h
mov rax, 0FFFFFFFFFFFFFFFFh
push rax
mov rax, qword ptr [originalEP]
jmp rax
Main_DoResume ENDP
_TEXT ENDS
END

View File

@ -0,0 +1,22 @@
project "OpenParrotLoader"
targetname "OpenParrotLoader"
language "C++"
kind "ConsoleApp"
characterset "MBCS"
files
{
"src/**.cpp", "src/**.h",
"deps_inc/**.cpp", "deps_inc/**.h"
}
includedirs { "src", "deps_inc" }
libdirs { }
links { }
postbuildcommands { }
filter "platforms:x64"
targetsuffix "64"

View File

@ -0,0 +1,57 @@
#include "PE.H"
DWORD PEAlign(DWORD dwTarNum, DWORD dwAlignTo);
PEStruct getPEFileInformation(char *filename)
{
HANDLE hFile;
PEStruct pRetnStruct;
pRetnStruct.fileSize = 0;
DWORD dwBytesRead;
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile)
return pRetnStruct;
pRetnStruct.fileSize = GetFileSize(hFile, 0);
if (!pRetnStruct.fileSize)
return pRetnStruct;
pRetnStruct.fileImage = malloc(pRetnStruct.fileSize);
if (!pRetnStruct.fileImage)
return pRetnStruct;
ReadFile(hFile, pRetnStruct.fileImage, pRetnStruct.fileSize, &dwBytesRead, NULL);
CloseHandle(hFile);
if (!dwBytesRead)
return pRetnStruct;
//copy portions to relevant sections
CopyMemory(&pRetnStruct.image_dos_header, pRetnStruct.fileImage, sizeof(IMAGE_DOS_HEADER));
CopyMemory(&pRetnStruct.image_nt_headers,
((BYTE *)pRetnStruct.fileImage + pRetnStruct.image_dos_header.e_lfanew), sizeof(IMAGE_NT_HEADERS));
//address of first section
pRetnStruct.dwRO_first_section = pRetnStruct.image_dos_header.e_lfanew + sizeof(IMAGE_NT_HEADERS);
pRetnStruct.numOfSecs = pRetnStruct.image_nt_headers.FileHeader.NumberOfSections;
CopyMemory(&pRetnStruct.image_section_header, ((BYTE *)pRetnStruct.fileImage + pRetnStruct.dwRO_first_section),
pRetnStruct.numOfSecs*sizeof(IMAGE_SECTION_HEADER));
//now to fill in individual sections (.text .data)
for (int i = 0; i < pRetnStruct.numOfSecs; i++)
{
pRetnStruct.image_section[i] = (char *)malloc(PEAlign(pRetnStruct.image_section_header[i].SizeOfRawData,
pRetnStruct.image_nt_headers.OptionalHeader.FileAlignment));
CopyMemory(pRetnStruct.image_section[i], ((BYTE *)pRetnStruct.fileImage + pRetnStruct.image_section_header[i].PointerToRawData),
pRetnStruct.image_section_header[i].SizeOfRawData);
}
return pRetnStruct;
}
//googled function to correct file alignement in PE header.
//Just makes sure the outputted number will align correctly with the rest of the data.
DWORD PEAlign(DWORD dwTarNum, DWORD dwAlignTo)
{
DWORD dwtemp;
dwtemp = dwTarNum / dwAlignTo;
if ((dwTarNum%dwAlignTo) != 0)
{
dwtemp++;
}
dwtemp = dwtemp*dwAlignTo;
return(dwtemp);
}

18
OpenParrotLoader/src/PE.h Normal file
View File

@ -0,0 +1,18 @@
#include <windows.h>
#include <WinNT.h>
#define MAX_SECTION_NUM 20
typedef struct _PEStruct
{
DWORD dwRO_first_section;
IMAGE_DOS_HEADER image_dos_header;
char *reservedheader;
IMAGE_NT_HEADERS image_nt_headers;
IMAGE_SECTION_HEADER image_section_header[MAX_SECTION_NUM];
char *image_section[MAX_SECTION_NUM];
void *fileImage;
DWORD fileSize;
DWORD numOfSecs;
} PEStruct, *PPEStruct;
PEStruct getPEFileInformation(char *filename);

View File

@ -0,0 +1,263 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
#include <conio.h>
#include "PE.h"
#pragma comment(lib, "ntdll.lib")
#pragma optimize("", off)
STARTUPINFO si;
PROCESS_INFORMATION pi;
_CONTEXT mycontext;
PEStruct FilePEFile;
int RunTo(DWORD_PTR Address, DWORD Mode, DWORD_PTR Eip);
DWORD_PTR MyLoadLibraryA = 0;
#pragma comment (lib, "Advapi32.lib")
int LoadHookDLL(char *dllLocation, DWORD_PTR address)
{
MyLoadLibraryA = (DWORD_PTR)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
DWORD_PTR addy = (DWORD_PTR)VirtualAllocEx(pi.hProcess, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//printf("addy: %08X", addy);
DWORD_PTR OEP = address;
DWORD_PTR TextLocation = addy + 0x30;
DWORD_PTR CallLoadLibraryA = MyLoadLibraryA - (addy + 10);
#ifdef _M_IX86
DWORD addyOffset = 10;
//ReadProcessMemory(pi.hProcess, (LPVOID)OEP, backbuf, 256, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)addy, "\x68\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xEB\xFE", 0x0C, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)(addy + 1), &TextLocation, 4, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)(addy + 6), &CallLoadLibraryA, 4, 0);
//printf("%s\n", dllLocation);
WriteProcessMemory(pi.hProcess, (LPVOID)TextLocation, dllLocation, strlen(dllLocation)+1, 0);
#else
DWORD addyOffset = 30;
WriteProcessMemory(pi.hProcess, (LPVOID)addy, "\x48\x83\xEC\x28\x48\xB9\x00\x00\x00\x00\x00\x00\x00\x00\x48\xB8\x11\x11\x11\x11\x01\x00\x00\x00\xFF\xD0\x48\x83\xC4\x28\xEB\xFE", 32, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)(addy + 6), &TextLocation, 8, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)(addy + 16), &MyLoadLibraryA, 8, 0);
//printf("%s\n", dllLocation);
WriteProcessMemory(pi.hProcess, (LPVOID)TextLocation, dllLocation, strlen(dllLocation) + 1, 0);
#endif
GetThreadContext(pi.hThread, &mycontext);
Sleep(1000);
if (!RunTo(addy + addyOffset, 0, addy))
{
printf("Failed to Load DLL!");
return 0;
}
#ifdef _M_IX86
if (mycontext.Eax == 0)
#elif defined(_M_AMD64)
if (mycontext.Rax == 0)
#endif
{
printf("Failed to Load DLL!");
return 0;
}
GetThreadContext(pi.hThread, &mycontext);
Sleep(100);
#ifdef _M_IX86
mycontext.Eip = OEP;
#else
mycontext.Rip = OEP;
#endif
Sleep(100);
SetThreadContext(pi.hThread, &mycontext);
Sleep(100);
//WriteProcessMemory(pi.hProcess, (LPVOID)OEP, backbuf, 256, 0);
Sleep(100);
printf("DLL Loaded!\n");// %08x\n", mycontext.Eax);
return 1;
}
int RunTo(DWORD_PTR Address, DWORD Mode, DWORD_PTR Eip)
{
char tempbuf[4];
if (Eip != 0)
{
GetThreadContext(pi.hThread, &mycontext);
#ifdef _M_IX86
mycontext.Eip = Eip;
#elif defined(_M_AMD64)
mycontext.Rip = Eip;
#endif
SetThreadContext(pi.hThread, &mycontext);
}
ReadProcessMemory(pi.hProcess, (LPVOID)Address, tempbuf, 4, 0);
WriteProcessMemory(pi.hProcess, (LPVOID)Address, "\xEB\xFE", 2, 0);
ResumeThread(pi.hThread);
while (GetThreadContext(pi.hThread, &mycontext))
{
if (Mode == 1) WriteProcessMemory(pi.hProcess, (LPVOID)Address, "\xEB\xFE", 2, 0);
#ifdef _M_IX86
if (mycontext.Eip == Address) break;
#elif defined(_M_AMD64)
if (mycontext.Rip == Address) break;
#endif
Sleep(100);
}
SuspendThread(pi.hThread);
if (!GetThreadContext(pi.hThread, &mycontext)) return 0;
WriteProcessMemory(pi.hProcess, (LPVOID)Address, tempbuf, 4, 0);
return 1;
}
void lowercase(char string[])
{
int i = 0;
while (string[i])
{
string[i] = tolower(string[i]);
i++;
}
return;
}
DWORD GetVal(HKEY hKey, LPCTSTR lpValue)
{
DWORD data; DWORD size = sizeof(data); DWORD type = REG_DWORD;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
if (nError == ERROR_FILE_NOT_FOUND)
data = 0; // The value will be created and set to data next time SetVal() is called.
else if (nError)
printf("Error: Could not get registry value %s", lpValue);
return data;
}
int main(int argc, char *argv[])
{
if (argc == 1 || argc > 3)
{
printf("Please use the following format: ");
printf("ParrotLoader.exe c:\\games\\id6\\id6.exe <param>");
return 0;
}
char dirBuf[256];
strcpy(dirBuf, argv[1]);
char *p = strrchr(dirBuf, '\\');
if (p) p[0] = 0;
WIN32_FIND_DATA filedata;
HANDLE hFind;
WIN32_FIND_DATA filedata2;
HANDLE hFind2;
char szDir[512];
char szDir2[512];
printf("OpenParrot Loader\n");
printf("http://www.teknogods.com - Modding Gurus!\n");
printf("Supported OS: Windows XP x86 / x64, Windows Vista x86 / x64, Windows 7 x86 / x64, Windows 8 / 8.1 x86 / x64 Windows 10 x86 / x64\n");
printf("Code: Reaver, NTAuthority, avail\n");
GetCurrentDirectoryA(400, szDir);
#if _M_IX86
sprintf_s(szDir2, "%s\\OpenParrot.dll", szDir);
#else
sprintf_s(szDir2, "%s\\OpenParrot64.dll", szDir);
#endif
hFind = FindFirstFile(argv[1], &filedata);
hFind2 = FindFirstFile(szDir2, &filedata2);
if (hFind == INVALID_HANDLE_VALUE)
{
printf("Unable to find %s", argv[1]);
_getch();
return 0;
}
if (hFind2 == INVALID_HANDLE_VALUE)
{
printf("Unable to find %s", szDir2);
_getch();
return 0;
}
FilePEFile = getPEFileInformation(argv[1]);
if (argc == 3)
{
char bb[256];
sprintf(bb, "%s %s", argv[1], argv[2]);
if (!CreateProcess(NULL, // No module name (use command line).
bb, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, // suspended creation flags.
NULL, // Use parent's environment block.
dirBuf, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
{
printf("Failed to load process!");
_getch();
return 1;
}
}
else if (argc == 2)
{
if (!CreateProcess(argv[1], // No module name (use command line).
"", // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, // suspended creation flags.
NULL, // Use parent's environment block.
dirBuf, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
{
printf("Failed to load process!");
_getch();
return 1;
}
}
mycontext.ContextFlags = 0x00010000 + 1 + 2 + 4 + 8 + 0x10;
GetThreadContext(pi.hThread, &mycontext);
PROCESS_BASIC_INFORMATION pbi;
DWORD pbiSize = sizeof(pbi);
if (!NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, pbiSize, &pbiSize)))
{
printf("Failed to get process information!");
_getch();
return 1;
}
DWORD_PTR baseAddress;
SIZE_T read = 0;
ReadProcessMemory(pi.hProcess, (void*)((DWORD_PTR)pbi.PebBaseAddress + (sizeof(DWORD_PTR) * 2)), &baseAddress, sizeof(baseAddress), &read);
if (read != sizeof(DWORD_PTR))
{
printf("Failed to get process environment!");
_getch();
return 1;
}
Sleep(1000);
if (!RunTo(baseAddress + FilePEFile.image_nt_headers.OptionalHeader.AddressOfEntryPoint, 1, 0))
{
printf("Failed to run the process\n");
TerminateProcess(pi.hProcess, 0);
_getch();
return 1;
}
if (!LoadHookDLL(szDir2, baseAddress + FilePEFile.image_nt_headers.OptionalHeader.AddressOfEntryPoint))
{
TerminateProcess(pi.hProcess, 0);
_getch();
return 0;
}
printf("Resuming game!\n");
Sleep(2000);
ResumeThread(pi.hThread);
while (GetThreadContext(pi.hThread, &mycontext)) Sleep(2000);
return 1;
}

334
OpenParrotLoader/src/main.h Normal file
View File

@ -0,0 +1,334 @@
/*
I do not take credit for these stuctures, but rather give all credits to
the NTInternals Team. But, I do take credit for taking the useful things
from the site and putting them into a easy to use place.
thanks and hope someone finds these useful
~sean reed
*/
#pragma once
#include <windows.h>
#include <wchar.h>
typedef void(*PELPEBLOCKROUTINE)(PVOID PebLock);
typedef struct _ELLSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}ELLSA_UNICODE_STRING, *PELLSA_UNICODE_STRING, ELUNICODE_STRING, *PELUNICODE_STRING;
typedef struct _ELLIST_ENTRY
{
struct _ELLIST_ENTRY *Flink;
struct _ELLIST_ENTRY *Blink;
} ELLIST_ENTRY, *PELLIST_ENTRY;
typedef struct _ELPEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
ELLIST_ENTRY InLoadOrderModuleList;
ELLIST_ENTRY InMemoryOrderModuleList;
ELLIST_ENTRY InInitializationOrderModuleList;
} ELPEB_LDR_DATA, *PELPEB_LDR_DATA;
typedef struct _ELRTL_DRIVE_LETTER_CURDIR
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
ELUNICODE_STRING DosPath;
} ELRTL_DRIVE_LETTER_CURDIR, *PELRTL_DRIVE_LETTER_CURDIR;
typedef struct _ELRTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
ELUNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
ELUNICODE_STRING DllPath;
ELUNICODE_STRING ImagePathName;
ELUNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingPositionLeft;
ULONG StartingPositionTop;
ULONG Width;
ULONG Height;
ULONG CharWidth;
ULONG CharHeight;
ULONG ConsoleTextAttributes;
ULONG WindowFlags;
ULONG ShowWindowFlags;
ELUNICODE_STRING WindowTitle;
ELUNICODE_STRING DesktopName;
ELUNICODE_STRING ShellInfo;
ELUNICODE_STRING RuntimeData;
ELRTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} ELRTL_USER_PROCESS_PARAMETERS, *PELRTL_USER_PROCESS_PARAMETERS;
typedef struct _ELPEB_FREE_BLOCK
{
struct _ELPEB_FREE_BLOCK *Next;
ULONG Size;
} ELPEB_FREE_BLOCK, *PELPEB_FREE_BLOCK;
typedef struct _ELLDR_MODULE {
ELLIST_ENTRY InLoadOrderModuleList;
ELLIST_ENTRY InMemoryOrderModuleList;
ELLIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
ELUNICODE_STRING FullDllName;
ELUNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
ELLIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} ELLDR_MODULE, *ELPLDR_MODULE;
typedef struct _ELPEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PELPEB_LDR_DATA LoaderData;
PELRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PELPEBLOCKROUTINE FastPebLockRoutine;
PELPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID *KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PELPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID **ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} ELPEB, *PELPEB;
typedef struct _ELPROCESS_BASIC_INFORMATION
{
PVOID Reserved1;
PELPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} ELPROCESS_BASIC_INFORMATION;
typedef enum _ELPROCESS_INFORMATION_CLASS
{
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
MaxProcessInfoClass
} ELPROCESS_INFORMATION_CLASS, *PELPROCESS_INFORMATION_CLASS;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef struct _ELSYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
LONG Priority;
LONG BasePriority;
ULONG ContextSwitches;
ULONG ThreadState;
ULONG WaitReason;
} ELSYSTEM_THREAD_INFORMATION, *PELSYSTEM_THREAD_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemNextEventIdInformation, SystemEventIdsInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemPlugPlayBusInformation, SystemDockInformation, ELSystemPowerInformation, SystemProcessorSpeedInformation, SystemCurrentTimeZoneInformation, SystemLookasideInformation
} ELSYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
typedef enum _KWAIT_REASON
{
Executive = 0,
FreePage = 1,
PageIn = 2,
PoolAllocation = 3,
DelayExecution = 4,
Suspended = 5,
UserRequest = 6,
WrExecutive = 7,
WrFreePage = 8,
WrPageIn = 9,
WrPoolAllocation = 10,
WrDelayExecution = 11,
WrSuspended = 12,
WrUserRequest = 13,
WrEventPair = 14,
WrQueue = 15,
WrLpcReceive = 16,
WrLpcReply = 17,
WrVirtualMemory = 18,
WrPageOut = 19,
WrRendezvous = 20,
Spare2 = 21,
Spare3 = 22,
Spare4 = 23,
Spare5 = 24,
WrCalloutStack = 25,
WrKernel = 26,
WrResource = 27,
WrPushLock = 28,
WrMutex = 29,
WrQuantumEnd = 30,
WrDispatchInt = 31,
WrPreempted = 32,
WrYieldExecution = 33,
WrFastMutex = 34,
WrGuardedMutex = 35,
WrRundown = 36,
MaximumWaitReason = 37
} KWAIT_REASON;
typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
LONG Priority;
LONG BasePriority;
ULONG ContextSwitchCount;
ULONG State;
KWAIT_REASON WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;
typedef struct _VM_COUNTERS
{
int PeakVirtualSize;
int VirtualSize;
int PageFaultCount;
int PeakWorkingSetSize;
int WorkingSetSize;
int QuotaPeakPagedPoolUsage;
int QuotaPagedPoolUsage;
int QuotaPeakNonPagedPoolUsage;
int QuotaNonPagedPoolUsage;
int PagefileUsage;
int PeakPagefileUsage;
}VM_COUNTERS;
typedef struct _SYSTEM_PROCESS_INFORMATION
{
DWORD NextEntryOffset;
DWORD dThreadCount;
DWORD dReserved01;
DWORD dReserved02;
DWORD dReserved03;
DWORD dReserved04;
DWORD dReserved05;
DWORD dReserved06;
FILETIME ftCreateTime; /* relative to 01-01-1601 */
FILETIME ftUserTime; /* 100 nsec units */
FILETIME ftKernelTime; /* 100 nsec units */
ELUNICODE_STRING ProcessName;
DWORD BasePriority;
DWORD dUniqueProcessId;
DWORD dParentProcessID;
DWORD dHandleCount;
DWORD dReserved07;
DWORD dReserved08;
DWORD VmCounters;
DWORD dCommitCharge;
ELSYSTEM_THREAD_INFORMATION ThreadInfos[1];
} ELSYSTEM_PROCESS_INFORMATION, *PELSYSTEM_PROCESS_INFORMATION;
//Gets the PEB for the current process
PELPEB EL_GetPeb();
//prints out the Loaded Modules for the current Peb
DWORD EL_PrintModules(PELPEB peb);
//hides a module
DWORD EL_HideModule(PELPEB peb, const wchar_t *dll);

186
deps/inc/MinHook.h vendored Normal file
View File

@ -0,0 +1,186 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#pragma once
#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
#error MinHook supports only x86 and x64 systems.
#endif
#include <windows.h>
// MinHook Error Codes.
typedef enum MH_STATUS
{
// Unknown error. Should not be returned.
MH_UNKNOWN = -1,
// Successful.
MH_OK = 0,
// MinHook is already initialized.
MH_ERROR_ALREADY_INITIALIZED,
// MinHook is not initialized yet, or already uninitialized.
MH_ERROR_NOT_INITIALIZED,
// The hook for the specified target function is already created.
MH_ERROR_ALREADY_CREATED,
// The hook for the specified target function is not created yet.
MH_ERROR_NOT_CREATED,
// The hook for the specified target function is already enabled.
MH_ERROR_ENABLED,
// The hook for the specified target function is not enabled yet, or already
// disabled.
MH_ERROR_DISABLED,
// The specified pointer is invalid. It points the address of non-allocated
// and/or non-executable region.
MH_ERROR_NOT_EXECUTABLE,
// The specified target function cannot be hooked.
MH_ERROR_UNSUPPORTED_FUNCTION,
// Failed to allocate memory.
MH_ERROR_MEMORY_ALLOC,
// Failed to change the memory protection.
MH_ERROR_MEMORY_PROTECT,
// The specified module is not loaded.
MH_ERROR_MODULE_NOT_FOUND,
// The specified function is not found.
MH_ERROR_FUNCTION_NOT_FOUND
}
MH_STATUS;
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
// MH_QueueEnableHook or MH_QueueDisableHook.
#define MH_ALL_HOOKS NULL
#ifdef __cplusplus
extern "C" {
#endif
// Initialize the MinHook library. You must call this function EXACTLY ONCE
// at the beginning of your program.
MH_STATUS WINAPI MH_Initialize(VOID);
// Uninitialize the MinHook library. You must call this function EXACTLY
// ONCE at the end of your program.
MH_STATUS WINAPI MH_Uninitialize(VOID);
// Creates a Hook for the specified target function, in disabled state.
// Parameters:
// pTarget [in] A pointer to the target function, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
// Creates a Hook for the specified API function, in disabled state.
// Parameters:
// pszModule [in] A pointer to the loaded module name which contains the
// target function.
// pszTarget [in] A pointer to the target function name, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHookApi(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
// Creates a Hook for the specified API function, in disabled state.
// Parameters:
// pszModule [in] A pointer to the loaded module name which contains the
// target function.
// pszTarget [in] A pointer to the target function name, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
// ppTarget [out] A pointer to the target function, which will be used
// with other functions.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHookApiEx(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
// Removes an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
// Enables an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// enabled in one go.
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
// Disables an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// disabled in one go.
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
// Queues to enable an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// queued to be enabled.
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
// Queues to disable an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// queued to be disabled.
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
// Applies all queued changes in one go.
MH_STATUS WINAPI MH_ApplyQueued(VOID);
// Translates the MH_STATUS to its name as a string.
const char * WINAPI MH_StatusToString(MH_STATUS status);
#ifdef __cplusplus
}
#endif

312
deps/src/buffer.c vendored Normal file
View File

@ -0,0 +1,312 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#include <windows.h>
#include "buffer.h"
// Size of each memory block. (= page size of VirtualAlloc)
#define MEMORY_BLOCK_SIZE 0x1000
// Max range for seeking a memory block. (= 1024MB)
#define MAX_MEMORY_RANGE 0x40000000
// Memory protection flags to check the executable address.
#define PAGE_EXECUTE_FLAGS \
(PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
// Memory slot.
typedef struct _MEMORY_SLOT
{
union
{
struct _MEMORY_SLOT *pNext;
UINT8 buffer[MEMORY_SLOT_SIZE];
};
} MEMORY_SLOT, *PMEMORY_SLOT;
// Memory block info. Placed at the head of each block.
typedef struct _MEMORY_BLOCK
{
struct _MEMORY_BLOCK *pNext;
PMEMORY_SLOT pFree; // First element of the free slot list.
UINT usedCount;
} MEMORY_BLOCK, *PMEMORY_BLOCK;
//-------------------------------------------------------------------------
// Global Variables:
//-------------------------------------------------------------------------
// First element of the memory block list.
PMEMORY_BLOCK g_pMemoryBlocks;
//-------------------------------------------------------------------------
VOID InitializeBuffer(VOID)
{
// Nothing to do for now.
}
//-------------------------------------------------------------------------
VOID UninitializeBuffer(VOID)
{
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
g_pMemoryBlocks = NULL;
while (pBlock)
{
PMEMORY_BLOCK pNext = pBlock->pNext;
VirtualFree(pBlock, 0, MEM_RELEASE);
pBlock = pNext;
}
}
//-------------------------------------------------------------------------
#if defined(_M_X64) || defined(__x86_64__)
static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
{
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
// Round down to the allocation granularity.
tryAddr -= tryAddr % dwAllocationGranularity;
// Start from the previous allocation granularity multiply.
tryAddr -= dwAllocationGranularity;
while (tryAddr >= (ULONG_PTR)pMinAddr)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
break;
if (mbi.State == MEM_FREE)
return (LPVOID)tryAddr;
if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
break;
tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
}
return NULL;
}
#endif
//-------------------------------------------------------------------------
#if defined(_M_X64) || defined(__x86_64__)
static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
{
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
// Round down to the allocation granularity.
tryAddr -= tryAddr % dwAllocationGranularity;
// Start from the next allocation granularity multiply.
tryAddr += dwAllocationGranularity;
while (tryAddr <= (ULONG_PTR)pMaxAddr)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
break;
if (mbi.State == MEM_FREE)
return (LPVOID)tryAddr;
tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
// Round up to the next allocation granularity.
tryAddr += dwAllocationGranularity - 1;
tryAddr -= tryAddr % dwAllocationGranularity;
}
return NULL;
}
#endif
//-------------------------------------------------------------------------
static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
{
PMEMORY_BLOCK pBlock;
#if defined(_M_X64) || defined(__x86_64__)
ULONG_PTR minAddr;
ULONG_PTR maxAddr;
SYSTEM_INFO si;
GetSystemInfo(&si);
minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
// pOrigin ± 512MB
if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
// Make room for MEMORY_BLOCK_SIZE bytes.
maxAddr -= MEMORY_BLOCK_SIZE - 1;
#endif
// Look the registered blocks for a reachable one.
for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
{
#if defined(_M_X64) || defined(__x86_64__)
// Ignore the blocks too far.
if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
continue;
#endif
// The block has at least one unused slot.
if (pBlock->pFree != NULL)
return pBlock;
}
#if defined(_M_X64) || defined(__x86_64__)
// Alloc a new block above if not found.
{
LPVOID pAlloc = pOrigin;
while ((ULONG_PTR)pAlloc >= minAddr)
{
pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
if (pAlloc == NULL)
break;
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pBlock != NULL)
break;
}
}
// Alloc a new block below if not found.
if (pBlock == NULL)
{
LPVOID pAlloc = pOrigin;
while ((ULONG_PTR)pAlloc <= maxAddr)
{
pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
if (pAlloc == NULL)
break;
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pBlock != NULL)
break;
}
}
#else
// In x86 mode, a memory block can be placed anywhere.
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
#endif
if (pBlock != NULL)
{
// Build a linked list of all the slots.
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
pBlock->pFree = NULL;
pBlock->usedCount = 0;
do
{
pSlot->pNext = pBlock->pFree;
pBlock->pFree = pSlot;
pSlot++;
} while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
pBlock->pNext = g_pMemoryBlocks;
g_pMemoryBlocks = pBlock;
}
return pBlock;
}
//-------------------------------------------------------------------------
LPVOID AllocateBuffer(LPVOID pOrigin)
{
PMEMORY_SLOT pSlot;
PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
if (pBlock == NULL)
return NULL;
// Remove an unused slot from the list.
pSlot = pBlock->pFree;
pBlock->pFree = pSlot->pNext;
pBlock->usedCount++;
#ifdef _DEBUG
// Fill the slot with INT3 for debugging.
memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
#endif
return pSlot;
}
//-------------------------------------------------------------------------
VOID FreeBuffer(LPVOID pBuffer)
{
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
PMEMORY_BLOCK pPrev = NULL;
ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
while (pBlock != NULL)
{
if ((ULONG_PTR)pBlock == pTargetBlock)
{
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
#ifdef _DEBUG
// Clear the released slot for debugging.
memset(pSlot, 0x00, sizeof(*pSlot));
#endif
// Restore the released slot to the list.
pSlot->pNext = pBlock->pFree;
pBlock->pFree = pSlot;
pBlock->usedCount--;
// Free if unused.
if (pBlock->usedCount == 0)
{
if (pPrev)
pPrev->pNext = pBlock->pNext;
else
g_pMemoryBlocks = pBlock->pNext;
VirtualFree(pBlock, 0, MEM_RELEASE);
}
break;
}
pPrev = pBlock;
pBlock = pBlock->pNext;
}
}
//-------------------------------------------------------------------------
BOOL IsExecutableAddress(LPVOID pAddress)
{
MEMORY_BASIC_INFORMATION mi;
VirtualQuery(pAddress, &mi, sizeof(mi));
return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
}

42
deps/src/buffer.h vendored Normal file
View File

@ -0,0 +1,42 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#pragma once
// Size of each memory slot.
#if defined(_M_X64) || defined(__x86_64__)
#define MEMORY_SLOT_SIZE 64
#else
#define MEMORY_SLOT_SIZE 32
#endif
VOID InitializeBuffer(VOID);
VOID UninitializeBuffer(VOID);
LPVOID AllocateBuffer(LPVOID pOrigin);
VOID FreeBuffer(LPVOID pBuffer);
BOOL IsExecutableAddress(LPVOID pAddress);

326
deps/src/hde/hde32.c vendored Normal file
View File

@ -0,0 +1,326 @@
/*
* Hacker Disassembler Engine 32 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#if defined(_M_IX86) || defined(__i386__)
#include "hde32.h"
#include "table32.h"
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;
// Avoid using memset to reduce the footprint.
#ifndef _MSC_VER
memset((LPBYTE)hs, 0, sizeof(hde32s));
#else
__stosb((LPBYTE)hs, 0, sizeof(hde32s));
#endif
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;
}
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;
}
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;
}
#endif // defined(_M_IX86) || defined(__i386__)

105
deps/src/hde/hde32.h vendored Normal file
View File

@ -0,0 +1,105 @@
/*
* Hacker Disassembler Engine 32
* Copyright (c) 2006-2009, Vyacheslav Patkov.
* All rights reserved.
*
* hde32.h: C/C++ header file
*
*/
#ifndef _HDE32_H_
#define _HDE32_H_
/* stdint.h - C99 standard header
* http://en.wikipedia.org/wiki/stdint.h
*
* if your compiler doesn't contain "stdint.h" header (for
* example, Microsoft Visual C++), you can download file:
* http://www.azillionmonkeys.com/qed/pstdint.h
* and change next line to:
* #include "pstdint.h"
*/
#include "pstdint.h"
#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)
#ifdef __cplusplus
extern "C" {
#endif
/* __cdecl */
unsigned int hde32_disasm(const void *code, hde32s *hs);
#ifdef __cplusplus
}
#endif
#endif /* _HDE32_H_ */

337
deps/src/hde/hde64.c vendored Normal file
View File

@ -0,0 +1,337 @@
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#if defined(_M_X64) || defined(__x86_64__)
#include "hde64.h"
#include "table64.h"
unsigned int hde64_disasm(const void *code, hde64s *hs)
{
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
uint8_t op64 = 0;
// Avoid using memset to reduce the footprint.
#ifndef _MSC_VER
memset((LPBYTE)hs, 0, sizeof(hde64s));
#else
__stosb((LPBYTE)hs, 0, sizeof(hde64s));
#endif
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 ((c & 0xf0) == 0x40) {
hs->flags |= F_PREFIX_REX;
if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
op64++;
hs->rex_r = (c & 7) >> 2;
hs->rex_x = (c & 3) >> 1;
hs->rex_b = c & 1;
if (((c = *p++) & 0xf0) == 0x40) {
opcode = c;
goto error_opcode;
}
}
if ((hs->opcode = c) == 0x0f) {
hs->opcode2 = c = *p++;
ht += DELTA_OPCODES;
} else if (c >= 0xa0 && c <= 0xa3) {
op64++;
if (pref & PRE_67)
pref |= PRE_66;
else
pref &= ~PRE_66;
}
opcode = c;
cflags = ht[ht[opcode / 4] + (opcode % 4)];
if (cflags == C_ERROR) {
error_opcode:
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 = hde64_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 = hde64_table + DELTA_FPU_MODRM + t*8;
t = ht[m_reg] << m_rm;
} else {
ht = hde64_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 = hde64_table + DELTA_OP2_LOCK_OK;
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
} else {
ht = hde64_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 = hde64_table + DELTA_OP2_ONLY_MEM;
table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
} else {
ht = hde64_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;
}
if (m_mod != 3 && m_rm == 4) {
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;
}
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 (op64) {
hs->flags |= F_IMM64;
hs->imm.imm64 = *(uint64_t *)p;
p += 8;
} else if (!(pref & PRE_66)) {
hs->flags |= F_IMM32;
hs->imm.imm32 = *(uint32_t *)p;
p += 4;
} else
goto imm16_ok;
}
if (cflags & C_IMM16) {
imm16_ok:
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;
}
#endif // defined(_M_X64) || defined(__x86_64__)

112
deps/src/hde/hde64.h vendored Normal file
View File

@ -0,0 +1,112 @@
/*
* Hacker Disassembler Engine 64
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
* hde64.h: C/C++ header file
*
*/
#ifndef _HDE64_H_
#define _HDE64_H_
/* stdint.h - C99 standard header
* http://en.wikipedia.org/wiki/stdint.h
*
* if your compiler doesn't contain "stdint.h" header (for
* example, Microsoft Visual C++), you can download file:
* http://www.azillionmonkeys.com/qed/pstdint.h
* and change next line to:
* #include "pstdint.h"
*/
#include "pstdint.h"
#define F_MODRM 0x00000001
#define F_SIB 0x00000002
#define F_IMM8 0x00000004
#define F_IMM16 0x00000008
#define F_IMM32 0x00000010
#define F_IMM64 0x00000020
#define F_DISP8 0x00000040
#define F_DISP16 0x00000080
#define F_DISP32 0x00000100
#define F_RELATIVE 0x00000200
#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_REX 0x40000000
#define F_PREFIX_ANY 0x7f000000
#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 rex;
uint8_t rex_w;
uint8_t rex_r;
uint8_t rex_x;
uint8_t rex_b;
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;
uint64_t imm64;
} imm;
union {
uint8_t disp8;
uint16_t disp16;
uint32_t disp32;
} disp;
uint32_t flags;
} hde64s;
#pragma pack(pop)
#ifdef __cplusplus
extern "C" {
#endif
/* __cdecl */
unsigned int hde64_disasm(const void *code, hde64s *hs);
#ifdef __cplusplus
}
#endif
#endif /* _HDE64_H_ */

39
deps/src/hde/pstdint.h vendored Normal file
View File

@ -0,0 +1,39 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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.
*/
#pragma once
#include <windows.h>
// Integer types for HDE.
typedef INT8 int8_t;
typedef INT16 int16_t;
typedef INT32 int32_t;
typedef INT64 int64_t;
typedef UINT8 uint8_t;
typedef UINT16 uint16_t;
typedef UINT32 uint32_t;
typedef UINT64 uint64_t;

73
deps/src/hde/table32.h vendored Normal file
View File

@ -0,0 +1,73 @@
/*
* Hacker Disassembler Engine 32 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#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
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
};

74
deps/src/hde/table64.h vendored Normal file
View File

@ -0,0 +1,74 @@
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#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 0xfd
#define DELTA_FPU_MODRM 0x104
#define DELTA_PREFIXES 0x13c
#define DELTA_OP_LOCK_OK 0x1ae
#define DELTA_OP2_LOCK_OK 0x1c6
#define DELTA_OP_ONLY_MEM 0x1d8
#define DELTA_OP2_ONLY_MEM 0x1e7
unsigned char hde64_table[] = {
0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,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,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,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
};

889
deps/src/hook.c vendored Normal file
View File

@ -0,0 +1,889 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#include <windows.h>
#include <tlhelp32.h>
#include <limits.h>
#include "../inc/MinHook.h"
#include "buffer.h"
#include "trampoline.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
// Initial capacity of the HOOK_ENTRY buffer.
#define INITIAL_HOOK_CAPACITY 32
// Initial capacity of the thread IDs buffer.
#define INITIAL_THREAD_CAPACITY 128
// Special hook position values.
#define INVALID_HOOK_POS UINT_MAX
#define ALL_HOOKS_POS UINT_MAX
// Freeze() action argument defines.
#define ACTION_DISABLE 0
#define ACTION_ENABLE 1
#define ACTION_APPLY_QUEUED 2
// Thread access rights for suspending/resuming threads.
#define THREAD_ACCESS \
(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
// Hook information.
typedef struct _HOOK_ENTRY
{
LPVOID pTarget; // Address of the target function.
LPVOID pDetour; // Address of the detour or relay function.
LPVOID pTrampoline; // Address of the trampoline function.
UINT8 backup[8]; // Original prologue of the target function.
UINT8 patchAbove : 1; // Uses the hot patch area.
UINT8 isEnabled : 1; // Enabled.
UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
UINT nIP : 4; // Count of the instruction boundaries.
UINT8 oldIPs[8]; // Instruction boundaries of the target function.
UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
} HOOK_ENTRY, *PHOOK_ENTRY;
// Suspended threads for Freeze()/Unfreeze().
typedef struct _FROZEN_THREADS
{
LPDWORD pItems; // Data heap
UINT capacity; // Size of allocated data heap, items
UINT size; // Actual number of data items
} FROZEN_THREADS, *PFROZEN_THREADS;
//-------------------------------------------------------------------------
// Global Variables:
//-------------------------------------------------------------------------
// Spin lock flag for EnterSpinLock()/LeaveSpinLock().
volatile LONG g_isLocked = FALSE;
// Private heap handle. If not NULL, this library is initialized.
HANDLE g_hHeap = NULL;
// Hook entries.
struct
{
PHOOK_ENTRY pItems; // Data heap
UINT capacity; // Size of allocated data heap, items
UINT size; // Actual number of data items
} g_hooks;
//-------------------------------------------------------------------------
// Returns INVALID_HOOK_POS if not found.
static UINT FindHookEntry(LPVOID pTarget)
{
UINT i;
for (i = 0; i < g_hooks.size; ++i)
{
if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
return i;
}
return INVALID_HOOK_POS;
}
//-------------------------------------------------------------------------
static PHOOK_ENTRY AddHookEntry()
{
if (g_hooks.pItems == NULL)
{
g_hooks.capacity = INITIAL_HOOK_CAPACITY;
g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
if (g_hooks.pItems == NULL)
return NULL;
}
else if (g_hooks.size >= g_hooks.capacity)
{
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
if (p == NULL)
return NULL;
g_hooks.capacity *= 2;
g_hooks.pItems = p;
}
return &g_hooks.pItems[g_hooks.size++];
}
//-------------------------------------------------------------------------
static void DeleteHookEntry(UINT pos)
{
if (pos < g_hooks.size - 1)
g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
g_hooks.size--;
if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
{
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
if (p == NULL)
return;
g_hooks.capacity /= 2;
g_hooks.pItems = p;
}
}
//-------------------------------------------------------------------------
static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
{
UINT i;
if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
return (DWORD_PTR)pHook->pTarget;
for (i = 0; i < pHook->nIP; ++i)
{
if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
}
#if defined(_M_X64) || defined(__x86_64__)
// Check relay function.
if (ip == (DWORD_PTR)pHook->pDetour)
return (DWORD_PTR)pHook->pTarget;
#endif
return 0;
}
//-------------------------------------------------------------------------
static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
{
UINT i;
for (i = 0; i < pHook->nIP; ++i)
{
if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
}
return 0;
}
//-------------------------------------------------------------------------
static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
{
// If the thread suspended in the overwritten area,
// move IP to the proper address.
CONTEXT c;
#if defined(_M_X64) || defined(__x86_64__)
DWORD64 *pIP = &c.Rip;
#else
DWORD *pIP = &c.Eip;
#endif
UINT count;
c.ContextFlags = CONTEXT_CONTROL;
if (!GetThreadContext(hThread, &c))
return;
if (pos == ALL_HOOKS_POS)
{
pos = 0;
count = g_hooks.size;
}
else
{
count = pos + 1;
}
for (; pos < count; ++pos)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
BOOL enable;
DWORD_PTR ip;
switch (action)
{
case ACTION_DISABLE:
enable = FALSE;
break;
case ACTION_ENABLE:
enable = TRUE;
break;
default: // ACTION_APPLY_QUEUED
enable = pHook->queueEnable;
break;
}
if (pHook->isEnabled == enable)
continue;
if (enable)
ip = FindNewIP(pHook, *pIP);
else
ip = FindOldIP(pHook, *pIP);
if (ip != 0)
{
*pIP = ip;
SetThreadContext(hThread, &c);
}
}
}
//-------------------------------------------------------------------------
static VOID EnumerateThreads(PFROZEN_THREADS pThreads)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(THREADENTRY32);
if (Thread32First(hSnapshot, &te))
{
do
{
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
&& te.th32OwnerProcessID == GetCurrentProcessId()
&& te.th32ThreadID != GetCurrentThreadId())
{
if (pThreads->pItems == NULL)
{
pThreads->capacity = INITIAL_THREAD_CAPACITY;
pThreads->pItems
= (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
if (pThreads->pItems == NULL)
break;
}
else if (pThreads->size >= pThreads->capacity)
{
LPDWORD p = (LPDWORD)HeapReAlloc(
g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD));
if (p == NULL)
break;
pThreads->capacity *= 2;
pThreads->pItems = p;
}
pThreads->pItems[pThreads->size++] = te.th32ThreadID;
}
te.dwSize = sizeof(THREADENTRY32);
} while (Thread32Next(hSnapshot, &te));
}
CloseHandle(hSnapshot);
}
}
//-------------------------------------------------------------------------
static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
{
pThreads->pItems = NULL;
pThreads->capacity = 0;
pThreads->size = 0;
EnumerateThreads(pThreads);
if (pThreads->pItems != NULL)
{
UINT i;
for (i = 0; i < pThreads->size; ++i)
{
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
if (hThread != NULL)
{
SuspendThread(hThread);
ProcessThreadIPs(hThread, pos, action);
CloseHandle(hThread);
}
}
}
}
//-------------------------------------------------------------------------
static VOID Unfreeze(PFROZEN_THREADS pThreads)
{
if (pThreads->pItems != NULL)
{
UINT i;
for (i = 0; i < pThreads->size; ++i)
{
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
if (hThread != NULL)
{
ResumeThread(hThread);
CloseHandle(hThread);
}
}
HeapFree(g_hHeap, 0, pThreads->pItems);
}
}
//-------------------------------------------------------------------------
static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
DWORD oldProtect;
SIZE_T patchSize = sizeof(JMP_REL);
LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
if (pHook->patchAbove)
{
pPatchTarget -= sizeof(JMP_REL);
patchSize += sizeof(JMP_REL_SHORT);
}
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
return MH_ERROR_MEMORY_PROTECT;
if (enable)
{
PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
pJmp->opcode = 0xE9;
pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
if (pHook->patchAbove)
{
PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
pShortJmp->opcode = 0xEB;
pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
}
}
else
{
if (pHook->patchAbove)
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
else
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
}
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
// Just-in-case measure.
FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
pHook->isEnabled = enable;
pHook->queueEnable = enable;
return MH_OK;
}
//-------------------------------------------------------------------------
static MH_STATUS EnableAllHooksLL(BOOL enable)
{
MH_STATUS status = MH_OK;
UINT i, first = INVALID_HOOK_POS;
for (i = 0; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != enable)
{
first = i;
break;
}
}
if (first != INVALID_HOOK_POS)
{
FROZEN_THREADS threads;
Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
for (i = first; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != enable)
{
status = EnableHookLL(i, enable);
if (status != MH_OK)
break;
}
}
Unfreeze(&threads);
}
return status;
}
//-------------------------------------------------------------------------
static VOID EnterSpinLock(VOID)
{
SIZE_T spinCount = 0;
// Wait until the flag is FALSE.
while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
{
// No need to generate a memory barrier here, since InterlockedCompareExchange()
// generates a full memory barrier itself.
// Prevent the loop from being too busy.
if (spinCount < 32)
Sleep(0);
else
Sleep(1);
spinCount++;
}
}
//-------------------------------------------------------------------------
static VOID LeaveSpinLock(VOID)
{
// No need to generate a memory barrier here, since InterlockedExchange()
// generates a full memory barrier itself.
InterlockedExchange(&g_isLocked, FALSE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_Initialize(VOID)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap == NULL)
{
g_hHeap = HeapCreate(0, 0, 0);
if (g_hHeap != NULL)
{
// Initialize the internal function buffer.
InitializeBuffer();
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_ALREADY_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_Uninitialize(VOID)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
status = EnableAllHooksLL(FALSE);
if (status == MH_OK)
{
// Free the internal function buffer.
// HeapFree is actually not required, but some tools detect a false
// memory leak without HeapFree.
UninitializeBuffer();
HeapFree(g_hHeap, 0, g_hooks.pItems);
HeapDestroy(g_hHeap);
g_hHeap = NULL;
g_hooks.pItems = NULL;
g_hooks.capacity = 0;
g_hooks.size = 0;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
{
UINT pos = FindHookEntry(pTarget);
if (pos == INVALID_HOOK_POS)
{
LPVOID pBuffer = AllocateBuffer(pTarget);
if (pBuffer != NULL)
{
TRAMPOLINE ct;
ct.pTarget = pTarget;
ct.pDetour = pDetour;
ct.pTrampoline = pBuffer;
if (CreateTrampolineFunction(&ct))
{
PHOOK_ENTRY pHook = AddHookEntry();
if (pHook != NULL)
{
pHook->pTarget = ct.pTarget;
#if defined(_M_X64) || defined(__x86_64__)
pHook->pDetour = ct.pRelay;
#else
pHook->pDetour = ct.pDetour;
#endif
pHook->pTrampoline = ct.pTrampoline;
pHook->patchAbove = ct.patchAbove;
pHook->isEnabled = FALSE;
pHook->queueEnable = FALSE;
pHook->nIP = ct.nIP;
memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
// Back up the target function.
if (ct.patchAbove)
{
memcpy(
pHook->backup,
(LPBYTE)pTarget - sizeof(JMP_REL),
sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
}
else
{
memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
}
if (ppOriginal != NULL)
*ppOriginal = pHook->pTrampoline;
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_UNSUPPORTED_FUNCTION;
}
if (status != MH_OK)
{
FreeBuffer(pBuffer);
}
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_ALREADY_CREATED;
}
}
else
{
status = MH_ERROR_NOT_EXECUTABLE;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
if (g_hooks.pItems[pos].isEnabled)
{
FROZEN_THREADS threads;
Freeze(&threads, pos, ACTION_DISABLE);
status = EnableHookLL(pos, FALSE);
Unfreeze(&threads);
}
if (status == MH_OK)
{
FreeBuffer(g_hooks.pItems[pos].pTrampoline);
DeleteHookEntry(pos);
}
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (pTarget == MH_ALL_HOOKS)
{
status = EnableAllHooksLL(enable);
}
else
{
FROZEN_THREADS threads;
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
if (g_hooks.pItems[pos].isEnabled != enable)
{
Freeze(&threads, pos, ACTION_ENABLE);
status = EnableHookLL(pos, enable);
Unfreeze(&threads);
}
else
{
status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
}
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
{
return EnableHook(pTarget, TRUE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
{
return EnableHook(pTarget, FALSE);
}
//-------------------------------------------------------------------------
static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (pTarget == MH_ALL_HOOKS)
{
UINT i;
for (i = 0; i < g_hooks.size; ++i)
g_hooks.pItems[i].queueEnable = queueEnable;
}
else
{
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
g_hooks.pItems[pos].queueEnable = queueEnable;
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
{
return QueueHook(pTarget, TRUE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
{
return QueueHook(pTarget, FALSE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_ApplyQueued(VOID)
{
MH_STATUS status = MH_OK;
UINT i, first = INVALID_HOOK_POS;
EnterSpinLock();
if (g_hHeap != NULL)
{
for (i = 0; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
{
first = i;
break;
}
}
if (first != INVALID_HOOK_POS)
{
FROZEN_THREADS threads;
Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
for (i = first; i < g_hooks.size; ++i)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[i];
if (pHook->isEnabled != pHook->queueEnable)
{
status = EnableHookLL(i, pHook->queueEnable);
if (status != MH_OK)
break;
}
}
Unfreeze(&threads);
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHookApiEx(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
LPVOID *ppOriginal, LPVOID *ppTarget)
{
HMODULE hModule;
LPVOID pTarget;
hModule = GetModuleHandleW(pszModule);
if (hModule == NULL)
return MH_ERROR_MODULE_NOT_FOUND;
pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
if (pTarget == NULL)
return MH_ERROR_FUNCTION_NOT_FOUND;
if(ppTarget != NULL)
*ppTarget = pTarget;
return MH_CreateHook(pTarget, pDetour, ppOriginal);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHookApi(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal)
{
return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
}
//-------------------------------------------------------------------------
const char * WINAPI MH_StatusToString(MH_STATUS status)
{
#define MH_ST2STR(x) \
case x: \
return #x;
switch (status) {
MH_ST2STR(MH_UNKNOWN)
MH_ST2STR(MH_OK)
MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
MH_ST2STR(MH_ERROR_ALREADY_CREATED)
MH_ST2STR(MH_ERROR_NOT_CREATED)
MH_ST2STR(MH_ERROR_ENABLED)
MH_ST2STR(MH_ERROR_DISABLED)
MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
}
#undef MH_ST2STR
return "(unknown)";
}

316
deps/src/trampoline.c vendored Normal file
View File

@ -0,0 +1,316 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#include <windows.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#if defined(_M_X64) || defined(__x86_64__)
#include "./hde/hde64.h"
typedef hde64s HDE;
#define HDE_DISASM(code, hs) hde64_disasm(code, hs)
#else
#include "./hde/hde32.h"
typedef hde32s HDE;
#define HDE_DISASM(code, hs) hde32_disasm(code, hs)
#endif
#include "trampoline.h"
#include "buffer.h"
// Maximum size of a trampoline function.
#if defined(_M_X64) || defined(__x86_64__)
#define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
#else
#define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
#endif
//-------------------------------------------------------------------------
static BOOL IsCodePadding(LPBYTE pInst, UINT size)
{
UINT i;
if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
return FALSE;
for (i = 1; i < size; ++i)
{
if (pInst[i] != pInst[0])
return FALSE;
}
return TRUE;
}
//-------------------------------------------------------------------------
BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
{
#if defined(_M_X64) || defined(__x86_64__)
CALL_ABS call = {
0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
0xEB, 0x08, // EB 08: JMP +10
0x0000000000000000ULL // Absolute destination address
};
JMP_ABS jmp = {
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
0x0000000000000000ULL // Absolute destination address
};
JCC_ABS jcc = {
0x70, 0x0E, // 7* 0E: J** +16
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
0x0000000000000000ULL // Absolute destination address
};
#else
CALL_REL call = {
0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
0x00000000 // Relative destination address
};
JMP_REL jmp = {
0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
0x00000000 // Relative destination address
};
JCC_REL jcc = {
0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
0x00000000 // Relative destination address
};
#endif
UINT8 oldPos = 0;
UINT8 newPos = 0;
ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
BOOL finished = FALSE; // Is the function completed?
#if defined(_M_X64) || defined(__x86_64__)
UINT8 instBuf[16];
#endif
ct->patchAbove = FALSE;
ct->nIP = 0;
do
{
HDE hs;
UINT copySize;
LPVOID pCopySrc;
ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
if (hs.flags & F_ERROR)
return FALSE;
pCopySrc = (LPVOID)pOldInst;
if (oldPos >= sizeof(JMP_REL))
{
// The trampoline function is long enough.
// Complete the function with the jump to the target function.
#if defined(_M_X64) || defined(__x86_64__)
jmp.address = pOldInst;
#else
jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
#endif
pCopySrc = &jmp;
copySize = sizeof(jmp);
finished = TRUE;
}
#if defined(_M_X64) || defined(__x86_64__)
else if ((hs.modrm & 0xC7) == 0x05)
{
// Instructions using RIP relative addressing. (ModR/M = 00???101B)
// Modify the RIP relative address.
PUINT32 pRelAddr;
// Avoid using memcpy to reduce the footprint.
#ifndef _MSC_VER
memcpy(instBuf, (LPBYTE)pOldInst, copySize);
#else
__movsb(instBuf, (LPBYTE)pOldInst, copySize);
#endif
pCopySrc = instBuf;
// Relative address is stored at (instruction length - immediate value length - 4).
pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
*pRelAddr
= (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
// Complete the function if JMP (FF /4).
if (hs.opcode == 0xFF && hs.modrm_reg == 4)
finished = TRUE;
}
#endif
else if (hs.opcode == 0xE8)
{
// Direct relative CALL
ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
#if defined(_M_X64) || defined(__x86_64__)
call.address = dest;
#else
call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
#endif
pCopySrc = &call;
copySize = sizeof(call);
}
else if ((hs.opcode & 0xFD) == 0xE9)
{
// Direct relative JMP (EB or E9)
ULONG_PTR dest = pOldInst + hs.len;
if (hs.opcode == 0xEB) // isShort jmp
dest += (INT8)hs.imm.imm8;
else
dest += (INT32)hs.imm.imm32;
// Simply copy an internal jump.
if ((ULONG_PTR)ct->pTarget <= dest
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
{
if (jmpDest < dest)
jmpDest = dest;
}
else
{
#if defined(_M_X64) || defined(__x86_64__)
jmp.address = dest;
#else
jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
#endif
pCopySrc = &jmp;
copySize = sizeof(jmp);
// Exit the function If it is not in the branch
finished = (pOldInst >= jmpDest);
}
}
else if ((hs.opcode & 0xF0) == 0x70
|| (hs.opcode & 0xFC) == 0xE0
|| (hs.opcode2 & 0xF0) == 0x80)
{
// Direct relative Jcc
ULONG_PTR dest = pOldInst + hs.len;
if ((hs.opcode & 0xF0) == 0x70 // Jcc
|| (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
dest += (INT8)hs.imm.imm8;
else
dest += (INT32)hs.imm.imm32;
// Simply copy an internal jump.
if ((ULONG_PTR)ct->pTarget <= dest
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
{
if (jmpDest < dest)
jmpDest = dest;
}
else if ((hs.opcode & 0xFC) == 0xE0)
{
// LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
return FALSE;
}
else
{
UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
#if defined(_M_X64) || defined(__x86_64__)
// Invert the condition in x64 mode to simplify the conditional jump logic.
jcc.opcode = 0x71 ^ cond;
jcc.address = dest;
#else
jcc.opcode1 = 0x80 | cond;
jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
#endif
pCopySrc = &jcc;
copySize = sizeof(jcc);
}
}
else if ((hs.opcode & 0xFE) == 0xC2)
{
// RET (C2 or C3)
// Complete the function if not in a branch.
finished = (pOldInst >= jmpDest);
}
// Can't alter the instruction length in a branch.
if (pOldInst < jmpDest && copySize != hs.len)
return FALSE;
// Trampoline function is too large.
if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
return FALSE;
// Trampoline function has too many instructions.
if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
return FALSE;
ct->oldIPs[ct->nIP] = oldPos;
ct->newIPs[ct->nIP] = newPos;
ct->nIP++;
// Avoid using memcpy to reduce the footprint.
#ifndef _MSC_VER
memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
#else
__movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
#endif
newPos += copySize;
oldPos += hs.len;
}
while (!finished);
// Is there enough place for a long jump?
if (oldPos < sizeof(JMP_REL)
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
{
// Is there enough place for a short jump?
if (oldPos < sizeof(JMP_REL_SHORT)
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
{
return FALSE;
}
// Can we place the long jump above the function?
if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
return FALSE;
if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
return FALSE;
ct->patchAbove = TRUE;
}
#if defined(_M_X64) || defined(__x86_64__)
// Create a relay function.
jmp.address = (ULONG_PTR)ct->pDetour;
ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
memcpy(ct->pRelay, &jmp, sizeof(jmp));
#endif
return TRUE;
}

105
deps/src/trampoline.h vendored Normal file
View File

@ -0,0 +1,105 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* 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.
*
* 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.
*/
#pragma once
#pragma pack(push, 1)
// Structs for writing x86/x64 instructions.
// 8-bit relative jump.
typedef struct _JMP_REL_SHORT
{
UINT8 opcode; // EB xx: JMP +2+xx
UINT8 operand;
} JMP_REL_SHORT, *PJMP_REL_SHORT;
// 32-bit direct relative jump/call.
typedef struct _JMP_REL
{
UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
UINT32 operand; // Relative destination address
} JMP_REL, *PJMP_REL, CALL_REL;
// 64-bit indirect absolute jump.
typedef struct _JMP_ABS
{
UINT8 opcode0; // FF25 00000000: JMP [+6]
UINT8 opcode1;
UINT32 dummy;
UINT64 address; // Absolute destination address
} JMP_ABS, *PJMP_ABS;
// 64-bit indirect absolute call.
typedef struct _CALL_ABS
{
UINT8 opcode0; // FF15 00000002: CALL [+6]
UINT8 opcode1;
UINT32 dummy0;
UINT8 dummy1; // EB 08: JMP +10
UINT8 dummy2;
UINT64 address; // Absolute destination address
} CALL_ABS;
// 32-bit direct relative conditional jumps.
typedef struct _JCC_REL
{
UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
UINT8 opcode1;
UINT32 operand; // Relative destination address
} JCC_REL;
// 64bit indirect absolute conditional jumps that x64 lacks.
typedef struct _JCC_ABS
{
UINT8 opcode; // 7* 0E: J** +16
UINT8 dummy0;
UINT8 dummy1; // FF25 00000000: JMP [+6]
UINT8 dummy2;
UINT32 dummy3;
UINT64 address; // Absolute destination address
} JCC_ABS;
#pragma pack(pop)
typedef struct _TRAMPOLINE
{
LPVOID pTarget; // [In] Address of the target function.
LPVOID pDetour; // [In] Address of the detour function.
LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
#if defined(_M_X64) || defined(__x86_64__)
LPVOID pRelay; // [Out] Address of the relay function.
#endif
BOOL patchAbove; // [Out] Should use the hot patch area?
UINT nIP; // [Out] Number of the instruction boundaries.
UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
} TRAMPOLINE, *PTRAMPOLINE;
BOOL CreateTrampolineFunction(PTRAMPOLINE ct);

1266
deps/udis86/libudis86/decode.c vendored Normal file

File diff suppressed because it is too large Load Diff

197
deps/udis86/libudis86/decode.h vendored Normal file
View File

@ -0,0 +1,197 @@
/* udis86 - libudis86/decode.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef UD_DECODE_H
#define UD_DECODE_H
#include "types.h"
#include "udint.h"
#include "itab.h"
#define MAX_INSN_LENGTH 15
/* itab prefix bits */
#define P_none ( 0 )
#define P_inv64 ( 1 << 0 )
#define P_INV64(n) ( ( n >> 0 ) & 1 )
#define P_def64 ( 1 << 1 )
#define P_DEF64(n) ( ( n >> 1 ) & 1 )
#define P_oso ( 1 << 2 )
#define P_OSO(n) ( ( n >> 2 ) & 1 )
#define P_aso ( 1 << 3 )
#define P_ASO(n) ( ( n >> 3 ) & 1 )
#define P_rexb ( 1 << 4 )
#define P_REXB(n) ( ( n >> 4 ) & 1 )
#define P_rexw ( 1 << 5 )
#define P_REXW(n) ( ( n >> 5 ) & 1 )
#define P_rexr ( 1 << 6 )
#define P_REXR(n) ( ( n >> 6 ) & 1 )
#define P_rexx ( 1 << 7 )
#define P_REXX(n) ( ( n >> 7 ) & 1 )
#define P_seg ( 1 << 8 )
#define P_SEG(n) ( ( n >> 8 ) & 1 )
#define P_vexl ( 1 << 9 )
#define P_VEXL(n) ( ( n >> 9 ) & 1 )
#define P_vexw ( 1 << 10 )
#define P_VEXW(n) ( ( n >> 10 ) & 1 )
#define P_str ( 1 << 11 )
#define P_STR(n) ( ( n >> 11 ) & 1 )
#define P_strz ( 1 << 12 )
#define P_STR_ZF(n) ( ( n >> 12 ) & 1 )
/* operand type constants -- order is important! */
enum ud_operand_code {
OP_NONE,
OP_A, OP_E, OP_M, OP_G,
OP_I, OP_F,
OP_R0, OP_R1, OP_R2, OP_R3,
OP_R4, OP_R5, OP_R6, OP_R7,
OP_AL, OP_CL, OP_DL,
OP_AX, OP_CX, OP_DX,
OP_eAX, OP_eCX, OP_eDX,
OP_rAX, OP_rCX, OP_rDX,
OP_ES, OP_CS, OP_SS, OP_DS,
OP_FS, OP_GS,
OP_ST0, OP_ST1, OP_ST2, OP_ST3,
OP_ST4, OP_ST5, OP_ST6, OP_ST7,
OP_J, OP_S, OP_O,
OP_I1, OP_I3, OP_sI,
OP_V, OP_W, OP_Q, OP_P,
OP_U, OP_N, OP_MU, OP_H,
OP_L,
OP_R, OP_C, OP_D,
OP_MR
} UD_ATTR_PACKED;
/*
* Operand size constants
*
* Symbolic constants for various operand sizes. Some of these constants
* are given a value equal to the width of the data (SZ_B == 8), such
* that they maybe used interchangeably in the internals. Modifying them
* will most certainly break things!
*/
typedef uint16_t ud_operand_size_t;
#define SZ_NA 0
#define SZ_Z 1
#define SZ_V 2
#define SZ_Y 3
#define SZ_X 4
#define SZ_RDQ 7
#define SZ_B 8
#define SZ_W 16
#define SZ_D 32
#define SZ_Q 64
#define SZ_T 80
#define SZ_O 12
#define SZ_DQ 128 /* double quad */
#define SZ_QQ 256 /* quad quad */
/*
* Complex size types; that encode sizes for operands of type MR (memory or
* register); for internal use only. Id space above 256.
*/
#define SZ_BD ((SZ_B << 8) | SZ_D)
#define SZ_BV ((SZ_B << 8) | SZ_V)
#define SZ_WD ((SZ_W << 8) | SZ_D)
#define SZ_WV ((SZ_W << 8) | SZ_V)
#define SZ_WY ((SZ_W << 8) | SZ_Y)
#define SZ_DY ((SZ_D << 8) | SZ_Y)
#define SZ_WO ((SZ_W << 8) | SZ_O)
#define SZ_DO ((SZ_D << 8) | SZ_O)
#define SZ_QO ((SZ_Q << 8) | SZ_O)
/* resolve complex size type.
*/
static UD_INLINE ud_operand_size_t
Mx_mem_size(ud_operand_size_t size)
{
return (size >> 8) & 0xff;
}
static UD_INLINE ud_operand_size_t
Mx_reg_size(ud_operand_size_t size)
{
return size & 0xff;
}
/* A single operand of an entry in the instruction table.
* (internal use only)
*/
struct ud_itab_entry_operand
{
enum ud_operand_code type;
ud_operand_size_t size;
};
/* A single entry in an instruction table.
*(internal use only)
*/
struct ud_itab_entry
{
enum ud_mnemonic_code mnemonic;
struct ud_itab_entry_operand operand1;
struct ud_itab_entry_operand operand2;
struct ud_itab_entry_operand operand3;
struct ud_itab_entry_operand operand4;
uint32_t prefix;
};
struct ud_lookup_table_list_entry {
const uint16_t *table;
enum ud_table_type type;
const char *meta;
};
extern struct ud_itab_entry ud_itab[];
extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
#endif /* UD_DECODE_H */
/* vim:cindent
* vim:expandtab
* vim:ts=4
* vim:sw=4
*/

113
deps/udis86/libudis86/extern.h vendored Normal file
View File

@ -0,0 +1,113 @@
/* udis86 - libudis86/extern.h
*
* Copyright (c) 2002-2009, 2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "types.h"
#if defined(_MSC_VER) && defined(_USRDLL)
# ifdef LIBUDIS86_EXPORTS
# define LIBUDIS86_DLLEXTERN __declspec(dllexport)
# else
# define LIBUDIS86_DLLEXTERN __declspec(dllimport)
# endif
#else
# define LIBUDIS86_DLLEXTERN
#endif
/* ============================= PUBLIC API ================================= */
extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t);
extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t);
extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned);
extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t);
extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u);
extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*);
extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u,
const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset));
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* UD_EXTERN_H */

5946
deps/udis86/libudis86/itab.c vendored Normal file

File diff suppressed because it is too large Load Diff

939
deps/udis86/libudis86/itab.h vendored Normal file
View File

@ -0,0 +1,939 @@
#ifndef UD_ITAB_H
#define UD_ITAB_H
/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */
/* ud_table_type -- lookup table types (see decode.c) */
enum ud_table_type {
UD_TAB__OPC_VEX,
UD_TAB__OPC_TABLE,
UD_TAB__OPC_X87,
UD_TAB__OPC_MOD,
UD_TAB__OPC_RM,
UD_TAB__OPC_OSIZE,
UD_TAB__OPC_MODE,
UD_TAB__OPC_VEX_L,
UD_TAB__OPC_3DNOW,
UD_TAB__OPC_REG,
UD_TAB__OPC_ASIZE,
UD_TAB__OPC_VEX_W,
UD_TAB__OPC_SSE,
UD_TAB__OPC_VENDOR
};
/* ud_mnemonic -- mnemonic constants */
enum ud_mnemonic_code {
UD_Iaaa,
UD_Iaad,
UD_Iaam,
UD_Iaas,
UD_Iadc,
UD_Iadd,
UD_Iaddpd,
UD_Iaddps,
UD_Iaddsd,
UD_Iaddss,
UD_Iaddsubpd,
UD_Iaddsubps,
UD_Iaesdec,
UD_Iaesdeclast,
UD_Iaesenc,
UD_Iaesenclast,
UD_Iaesimc,
UD_Iaeskeygenassist,
UD_Iand,
UD_Iandnpd,
UD_Iandnps,
UD_Iandpd,
UD_Iandps,
UD_Iarpl,
UD_Iblendpd,
UD_Iblendps,
UD_Iblendvpd,
UD_Iblendvps,
UD_Ibound,
UD_Ibsf,
UD_Ibsr,
UD_Ibswap,
UD_Ibt,
UD_Ibtc,
UD_Ibtr,
UD_Ibts,
UD_Icall,
UD_Icbw,
UD_Icdq,
UD_Icdqe,
UD_Iclc,
UD_Icld,
UD_Iclflush,
UD_Iclgi,
UD_Icli,
UD_Iclts,
UD_Icmc,
UD_Icmova,
UD_Icmovae,
UD_Icmovb,
UD_Icmovbe,
UD_Icmovg,
UD_Icmovge,
UD_Icmovl,
UD_Icmovle,
UD_Icmovno,
UD_Icmovnp,
UD_Icmovns,
UD_Icmovnz,
UD_Icmovo,
UD_Icmovp,
UD_Icmovs,
UD_Icmovz,
UD_Icmp,
UD_Icmppd,
UD_Icmpps,
UD_Icmpsb,
UD_Icmpsd,
UD_Icmpsq,
UD_Icmpss,
UD_Icmpsw,
UD_Icmpxchg,
UD_Icmpxchg16b,
UD_Icmpxchg8b,
UD_Icomisd,
UD_Icomiss,
UD_Icpuid,
UD_Icqo,
UD_Icrc32,
UD_Icvtdq2pd,
UD_Icvtdq2ps,
UD_Icvtpd2dq,
UD_Icvtpd2pi,
UD_Icvtpd2ps,
UD_Icvtpi2pd,
UD_Icvtpi2ps,
UD_Icvtps2dq,
UD_Icvtps2pd,
UD_Icvtps2pi,
UD_Icvtsd2si,
UD_Icvtsd2ss,
UD_Icvtsi2sd,
UD_Icvtsi2ss,
UD_Icvtss2sd,
UD_Icvtss2si,
UD_Icvttpd2dq,
UD_Icvttpd2pi,
UD_Icvttps2dq,
UD_Icvttps2pi,
UD_Icvttsd2si,
UD_Icvttss2si,
UD_Icwd,
UD_Icwde,
UD_Idaa,
UD_Idas,
UD_Idec,
UD_Idiv,
UD_Idivpd,
UD_Idivps,
UD_Idivsd,
UD_Idivss,
UD_Idppd,
UD_Idpps,
UD_Iemms,
UD_Ienter,
UD_Iextractps,
UD_If2xm1,
UD_Ifabs,
UD_Ifadd,
UD_Ifaddp,
UD_Ifbld,
UD_Ifbstp,
UD_Ifchs,
UD_Ifclex,
UD_Ifcmovb,
UD_Ifcmovbe,
UD_Ifcmove,
UD_Ifcmovnb,
UD_Ifcmovnbe,
UD_Ifcmovne,
UD_Ifcmovnu,
UD_Ifcmovu,
UD_Ifcom,
UD_Ifcom2,
UD_Ifcomi,
UD_Ifcomip,
UD_Ifcomp,
UD_Ifcomp3,
UD_Ifcomp5,
UD_Ifcompp,
UD_Ifcos,
UD_Ifdecstp,
UD_Ifdiv,
UD_Ifdivp,
UD_Ifdivr,
UD_Ifdivrp,
UD_Ifemms,
UD_Iffree,
UD_Iffreep,
UD_Ifiadd,
UD_Ificom,
UD_Ificomp,
UD_Ifidiv,
UD_Ifidivr,
UD_Ifild,
UD_Ifimul,
UD_Ifincstp,
UD_Ifist,
UD_Ifistp,
UD_Ifisttp,
UD_Ifisub,
UD_Ifisubr,
UD_Ifld,
UD_Ifld1,
UD_Ifldcw,
UD_Ifldenv,
UD_Ifldl2e,
UD_Ifldl2t,
UD_Ifldlg2,
UD_Ifldln2,
UD_Ifldpi,
UD_Ifldz,
UD_Ifmul,
UD_Ifmulp,
UD_Ifndisi,
UD_Ifneni,
UD_Ifninit,
UD_Ifnop,
UD_Ifnsave,
UD_Ifnsetpm,
UD_Ifnstcw,
UD_Ifnstenv,
UD_Ifnstsw,
UD_Ifpatan,
UD_Ifprem,
UD_Ifprem1,
UD_Ifptan,
UD_Ifrndint,
UD_Ifrstor,
UD_Ifrstpm,
UD_Ifscale,
UD_Ifsin,
UD_Ifsincos,
UD_Ifsqrt,
UD_Ifst,
UD_Ifstp,
UD_Ifstp1,
UD_Ifstp8,
UD_Ifstp9,
UD_Ifsub,
UD_Ifsubp,
UD_Ifsubr,
UD_Ifsubrp,
UD_Iftst,
UD_Ifucom,
UD_Ifucomi,
UD_Ifucomip,
UD_Ifucomp,
UD_Ifucompp,
UD_Ifxam,
UD_Ifxch,
UD_Ifxch4,
UD_Ifxch7,
UD_Ifxrstor,
UD_Ifxsave,
UD_Ifxtract,
UD_Ifyl2x,
UD_Ifyl2xp1,
UD_Igetsec,
UD_Ihaddpd,
UD_Ihaddps,
UD_Ihlt,
UD_Ihsubpd,
UD_Ihsubps,
UD_Iidiv,
UD_Iimul,
UD_Iin,
UD_Iinc,
UD_Iinsb,
UD_Iinsd,
UD_Iinsertps,
UD_Iinsw,
UD_Iint,
UD_Iint1,
UD_Iint3,
UD_Iinto,
UD_Iinvd,
UD_Iinvept,
UD_Iinvlpg,
UD_Iinvlpga,
UD_Iinvvpid,
UD_Iiretd,
UD_Iiretq,
UD_Iiretw,
UD_Ija,
UD_Ijae,
UD_Ijb,
UD_Ijbe,
UD_Ijcxz,
UD_Ijecxz,
UD_Ijg,
UD_Ijge,
UD_Ijl,
UD_Ijle,
UD_Ijmp,
UD_Ijno,
UD_Ijnp,
UD_Ijns,
UD_Ijnz,
UD_Ijo,
UD_Ijp,
UD_Ijrcxz,
UD_Ijs,
UD_Ijz,
UD_Ilahf,
UD_Ilar,
UD_Ilddqu,
UD_Ildmxcsr,
UD_Ilds,
UD_Ilea,
UD_Ileave,
UD_Iles,
UD_Ilfence,
UD_Ilfs,
UD_Ilgdt,
UD_Ilgs,
UD_Ilidt,
UD_Illdt,
UD_Ilmsw,
UD_Ilock,
UD_Ilodsb,
UD_Ilodsd,
UD_Ilodsq,
UD_Ilodsw,
UD_Iloop,
UD_Iloope,
UD_Iloopne,
UD_Ilsl,
UD_Ilss,
UD_Iltr,
UD_Imaskmovdqu,
UD_Imaskmovq,
UD_Imaxpd,
UD_Imaxps,
UD_Imaxsd,
UD_Imaxss,
UD_Imfence,
UD_Iminpd,
UD_Iminps,
UD_Iminsd,
UD_Iminss,
UD_Imonitor,
UD_Imontmul,
UD_Imov,
UD_Imovapd,
UD_Imovaps,
UD_Imovbe,
UD_Imovd,
UD_Imovddup,
UD_Imovdq2q,
UD_Imovdqa,
UD_Imovdqu,
UD_Imovhlps,
UD_Imovhpd,
UD_Imovhps,
UD_Imovlhps,
UD_Imovlpd,
UD_Imovlps,
UD_Imovmskpd,
UD_Imovmskps,
UD_Imovntdq,
UD_Imovntdqa,
UD_Imovnti,
UD_Imovntpd,
UD_Imovntps,
UD_Imovntq,
UD_Imovq,
UD_Imovq2dq,
UD_Imovsb,
UD_Imovsd,
UD_Imovshdup,
UD_Imovsldup,
UD_Imovsq,
UD_Imovss,
UD_Imovsw,
UD_Imovsx,
UD_Imovsxd,
UD_Imovupd,
UD_Imovups,
UD_Imovzx,
UD_Impsadbw,
UD_Imul,
UD_Imulpd,
UD_Imulps,
UD_Imulsd,
UD_Imulss,
UD_Imwait,
UD_Ineg,
UD_Inop,
UD_Inot,
UD_Ior,
UD_Iorpd,
UD_Iorps,
UD_Iout,
UD_Ioutsb,
UD_Ioutsd,
UD_Ioutsw,
UD_Ipabsb,
UD_Ipabsd,
UD_Ipabsw,
UD_Ipackssdw,
UD_Ipacksswb,
UD_Ipackusdw,
UD_Ipackuswb,
UD_Ipaddb,
UD_Ipaddd,
UD_Ipaddq,
UD_Ipaddsb,
UD_Ipaddsw,
UD_Ipaddusb,
UD_Ipaddusw,
UD_Ipaddw,
UD_Ipalignr,
UD_Ipand,
UD_Ipandn,
UD_Ipavgb,
UD_Ipavgusb,
UD_Ipavgw,
UD_Ipblendvb,
UD_Ipblendw,
UD_Ipclmulqdq,
UD_Ipcmpeqb,
UD_Ipcmpeqd,
UD_Ipcmpeqq,
UD_Ipcmpeqw,
UD_Ipcmpestri,
UD_Ipcmpestrm,
UD_Ipcmpgtb,
UD_Ipcmpgtd,
UD_Ipcmpgtq,
UD_Ipcmpgtw,
UD_Ipcmpistri,
UD_Ipcmpistrm,
UD_Ipextrb,
UD_Ipextrd,
UD_Ipextrq,
UD_Ipextrw,
UD_Ipf2id,
UD_Ipf2iw,
UD_Ipfacc,
UD_Ipfadd,
UD_Ipfcmpeq,
UD_Ipfcmpge,
UD_Ipfcmpgt,
UD_Ipfmax,
UD_Ipfmin,
UD_Ipfmul,
UD_Ipfnacc,
UD_Ipfpnacc,
UD_Ipfrcp,
UD_Ipfrcpit1,
UD_Ipfrcpit2,
UD_Ipfrsqit1,
UD_Ipfrsqrt,
UD_Ipfsub,
UD_Ipfsubr,
UD_Iphaddd,
UD_Iphaddsw,
UD_Iphaddw,
UD_Iphminposuw,
UD_Iphsubd,
UD_Iphsubsw,
UD_Iphsubw,
UD_Ipi2fd,
UD_Ipi2fw,
UD_Ipinsrb,
UD_Ipinsrd,
UD_Ipinsrq,
UD_Ipinsrw,
UD_Ipmaddubsw,
UD_Ipmaddwd,
UD_Ipmaxsb,
UD_Ipmaxsd,
UD_Ipmaxsw,
UD_Ipmaxub,
UD_Ipmaxud,
UD_Ipmaxuw,
UD_Ipminsb,
UD_Ipminsd,
UD_Ipminsw,
UD_Ipminub,
UD_Ipminud,
UD_Ipminuw,
UD_Ipmovmskb,
UD_Ipmovsxbd,
UD_Ipmovsxbq,
UD_Ipmovsxbw,
UD_Ipmovsxdq,
UD_Ipmovsxwd,
UD_Ipmovsxwq,
UD_Ipmovzxbd,
UD_Ipmovzxbq,
UD_Ipmovzxbw,
UD_Ipmovzxdq,
UD_Ipmovzxwd,
UD_Ipmovzxwq,
UD_Ipmuldq,
UD_Ipmulhrsw,
UD_Ipmulhrw,
UD_Ipmulhuw,
UD_Ipmulhw,
UD_Ipmulld,
UD_Ipmullw,
UD_Ipmuludq,
UD_Ipop,
UD_Ipopa,
UD_Ipopad,
UD_Ipopcnt,
UD_Ipopfd,
UD_Ipopfq,
UD_Ipopfw,
UD_Ipor,
UD_Iprefetch,
UD_Iprefetchnta,
UD_Iprefetcht0,
UD_Iprefetcht1,
UD_Iprefetcht2,
UD_Ipsadbw,
UD_Ipshufb,
UD_Ipshufd,
UD_Ipshufhw,
UD_Ipshuflw,
UD_Ipshufw,
UD_Ipsignb,
UD_Ipsignd,
UD_Ipsignw,
UD_Ipslld,
UD_Ipslldq,
UD_Ipsllq,
UD_Ipsllw,
UD_Ipsrad,
UD_Ipsraw,
UD_Ipsrld,
UD_Ipsrldq,
UD_Ipsrlq,
UD_Ipsrlw,
UD_Ipsubb,
UD_Ipsubd,
UD_Ipsubq,
UD_Ipsubsb,
UD_Ipsubsw,
UD_Ipsubusb,
UD_Ipsubusw,
UD_Ipsubw,
UD_Ipswapd,
UD_Iptest,
UD_Ipunpckhbw,
UD_Ipunpckhdq,
UD_Ipunpckhqdq,
UD_Ipunpckhwd,
UD_Ipunpcklbw,
UD_Ipunpckldq,
UD_Ipunpcklqdq,
UD_Ipunpcklwd,
UD_Ipush,
UD_Ipusha,
UD_Ipushad,
UD_Ipushfd,
UD_Ipushfq,
UD_Ipushfw,
UD_Ipxor,
UD_Ircl,
UD_Ircpps,
UD_Ircpss,
UD_Ircr,
UD_Irdmsr,
UD_Irdpmc,
UD_Irdrand,
UD_Irdtsc,
UD_Irdtscp,
UD_Irep,
UD_Irepne,
UD_Iret,
UD_Iretf,
UD_Irol,
UD_Iror,
UD_Iroundpd,
UD_Iroundps,
UD_Iroundsd,
UD_Iroundss,
UD_Irsm,
UD_Irsqrtps,
UD_Irsqrtss,
UD_Isahf,
UD_Isalc,
UD_Isar,
UD_Isbb,
UD_Iscasb,
UD_Iscasd,
UD_Iscasq,
UD_Iscasw,
UD_Iseta,
UD_Isetae,
UD_Isetb,
UD_Isetbe,
UD_Isetg,
UD_Isetge,
UD_Isetl,
UD_Isetle,
UD_Isetno,
UD_Isetnp,
UD_Isetns,
UD_Isetnz,
UD_Iseto,
UD_Isetp,
UD_Isets,
UD_Isetz,
UD_Isfence,
UD_Isgdt,
UD_Ishl,
UD_Ishld,
UD_Ishr,
UD_Ishrd,
UD_Ishufpd,
UD_Ishufps,
UD_Isidt,
UD_Iskinit,
UD_Isldt,
UD_Ismsw,
UD_Isqrtpd,
UD_Isqrtps,
UD_Isqrtsd,
UD_Isqrtss,
UD_Istc,
UD_Istd,
UD_Istgi,
UD_Isti,
UD_Istmxcsr,
UD_Istosb,
UD_Istosd,
UD_Istosq,
UD_Istosw,
UD_Istr,
UD_Isub,
UD_Isubpd,
UD_Isubps,
UD_Isubsd,
UD_Isubss,
UD_Iswapgs,
UD_Isyscall,
UD_Isysenter,
UD_Isysexit,
UD_Isysret,
UD_Itest,
UD_Iucomisd,
UD_Iucomiss,
UD_Iud2,
UD_Iunpckhpd,
UD_Iunpckhps,
UD_Iunpcklpd,
UD_Iunpcklps,
UD_Ivaddpd,
UD_Ivaddps,
UD_Ivaddsd,
UD_Ivaddss,
UD_Ivaddsubpd,
UD_Ivaddsubps,
UD_Ivaesdec,
UD_Ivaesdeclast,
UD_Ivaesenc,
UD_Ivaesenclast,
UD_Ivaesimc,
UD_Ivaeskeygenassist,
UD_Ivandnpd,
UD_Ivandnps,
UD_Ivandpd,
UD_Ivandps,
UD_Ivblendpd,
UD_Ivblendps,
UD_Ivblendvpd,
UD_Ivblendvps,
UD_Ivbroadcastsd,
UD_Ivbroadcastss,
UD_Ivcmppd,
UD_Ivcmpps,
UD_Ivcmpsd,
UD_Ivcmpss,
UD_Ivcomisd,
UD_Ivcomiss,
UD_Ivcvtdq2pd,
UD_Ivcvtdq2ps,
UD_Ivcvtpd2dq,
UD_Ivcvtpd2ps,
UD_Ivcvtps2dq,
UD_Ivcvtps2pd,
UD_Ivcvtsd2si,
UD_Ivcvtsd2ss,
UD_Ivcvtsi2sd,
UD_Ivcvtsi2ss,
UD_Ivcvtss2sd,
UD_Ivcvtss2si,
UD_Ivcvttpd2dq,
UD_Ivcvttps2dq,
UD_Ivcvttsd2si,
UD_Ivcvttss2si,
UD_Ivdivpd,
UD_Ivdivps,
UD_Ivdivsd,
UD_Ivdivss,
UD_Ivdppd,
UD_Ivdpps,
UD_Iverr,
UD_Iverw,
UD_Ivextractf128,
UD_Ivextractps,
UD_Ivhaddpd,
UD_Ivhaddps,
UD_Ivhsubpd,
UD_Ivhsubps,
UD_Ivinsertf128,
UD_Ivinsertps,
UD_Ivlddqu,
UD_Ivmaskmovdqu,
UD_Ivmaskmovpd,
UD_Ivmaskmovps,
UD_Ivmaxpd,
UD_Ivmaxps,
UD_Ivmaxsd,
UD_Ivmaxss,
UD_Ivmcall,
UD_Ivmclear,
UD_Ivminpd,
UD_Ivminps,
UD_Ivminsd,
UD_Ivminss,
UD_Ivmlaunch,
UD_Ivmload,
UD_Ivmmcall,
UD_Ivmovapd,
UD_Ivmovaps,
UD_Ivmovd,
UD_Ivmovddup,
UD_Ivmovdqa,
UD_Ivmovdqu,
UD_Ivmovhlps,
UD_Ivmovhpd,
UD_Ivmovhps,
UD_Ivmovlhps,
UD_Ivmovlpd,
UD_Ivmovlps,
UD_Ivmovmskpd,
UD_Ivmovmskps,
UD_Ivmovntdq,
UD_Ivmovntdqa,
UD_Ivmovntpd,
UD_Ivmovntps,
UD_Ivmovq,
UD_Ivmovsd,
UD_Ivmovshdup,
UD_Ivmovsldup,
UD_Ivmovss,
UD_Ivmovupd,
UD_Ivmovups,
UD_Ivmpsadbw,
UD_Ivmptrld,
UD_Ivmptrst,
UD_Ivmread,
UD_Ivmresume,
UD_Ivmrun,
UD_Ivmsave,
UD_Ivmulpd,
UD_Ivmulps,
UD_Ivmulsd,
UD_Ivmulss,
UD_Ivmwrite,
UD_Ivmxoff,
UD_Ivmxon,
UD_Ivorpd,
UD_Ivorps,
UD_Ivpabsb,
UD_Ivpabsd,
UD_Ivpabsw,
UD_Ivpackssdw,
UD_Ivpacksswb,
UD_Ivpackusdw,
UD_Ivpackuswb,
UD_Ivpaddb,
UD_Ivpaddd,
UD_Ivpaddq,
UD_Ivpaddsb,
UD_Ivpaddsw,
UD_Ivpaddusb,
UD_Ivpaddusw,
UD_Ivpaddw,
UD_Ivpalignr,
UD_Ivpand,
UD_Ivpandn,
UD_Ivpavgb,
UD_Ivpavgw,
UD_Ivpblendvb,
UD_Ivpblendw,
UD_Ivpclmulqdq,
UD_Ivpcmpeqb,
UD_Ivpcmpeqd,
UD_Ivpcmpeqq,
UD_Ivpcmpeqw,
UD_Ivpcmpestri,
UD_Ivpcmpestrm,
UD_Ivpcmpgtb,
UD_Ivpcmpgtd,
UD_Ivpcmpgtq,
UD_Ivpcmpgtw,
UD_Ivpcmpistri,
UD_Ivpcmpistrm,
UD_Ivperm2f128,
UD_Ivpermilpd,
UD_Ivpermilps,
UD_Ivpextrb,
UD_Ivpextrd,
UD_Ivpextrq,
UD_Ivpextrw,
UD_Ivphaddd,
UD_Ivphaddsw,
UD_Ivphaddw,
UD_Ivphminposuw,
UD_Ivphsubd,
UD_Ivphsubsw,
UD_Ivphsubw,
UD_Ivpinsrb,
UD_Ivpinsrd,
UD_Ivpinsrq,
UD_Ivpinsrw,
UD_Ivpmaddubsw,
UD_Ivpmaddwd,
UD_Ivpmaxsb,
UD_Ivpmaxsd,
UD_Ivpmaxsw,
UD_Ivpmaxub,
UD_Ivpmaxud,
UD_Ivpmaxuw,
UD_Ivpminsb,
UD_Ivpminsd,
UD_Ivpminsw,
UD_Ivpminub,
UD_Ivpminud,
UD_Ivpminuw,
UD_Ivpmovmskb,
UD_Ivpmovsxbd,
UD_Ivpmovsxbq,
UD_Ivpmovsxbw,
UD_Ivpmovsxwd,
UD_Ivpmovsxwq,
UD_Ivpmovzxbd,
UD_Ivpmovzxbq,
UD_Ivpmovzxbw,
UD_Ivpmovzxdq,
UD_Ivpmovzxwd,
UD_Ivpmovzxwq,
UD_Ivpmuldq,
UD_Ivpmulhrsw,
UD_Ivpmulhuw,
UD_Ivpmulhw,
UD_Ivpmulld,
UD_Ivpmullw,
UD_Ivpor,
UD_Ivpsadbw,
UD_Ivpshufb,
UD_Ivpshufd,
UD_Ivpshufhw,
UD_Ivpshuflw,
UD_Ivpsignb,
UD_Ivpsignd,
UD_Ivpsignw,
UD_Ivpslld,
UD_Ivpslldq,
UD_Ivpsllq,
UD_Ivpsllw,
UD_Ivpsrad,
UD_Ivpsraw,
UD_Ivpsrld,
UD_Ivpsrldq,
UD_Ivpsrlq,
UD_Ivpsrlw,
UD_Ivpsubb,
UD_Ivpsubd,
UD_Ivpsubq,
UD_Ivpsubsb,
UD_Ivpsubsw,
UD_Ivpsubusb,
UD_Ivpsubusw,
UD_Ivpsubw,
UD_Ivptest,
UD_Ivpunpckhbw,
UD_Ivpunpckhdq,
UD_Ivpunpckhqdq,
UD_Ivpunpckhwd,
UD_Ivpunpcklbw,
UD_Ivpunpckldq,
UD_Ivpunpcklqdq,
UD_Ivpunpcklwd,
UD_Ivpxor,
UD_Ivrcpps,
UD_Ivrcpss,
UD_Ivroundpd,
UD_Ivroundps,
UD_Ivroundsd,
UD_Ivroundss,
UD_Ivrsqrtps,
UD_Ivrsqrtss,
UD_Ivshufpd,
UD_Ivshufps,
UD_Ivsqrtpd,
UD_Ivsqrtps,
UD_Ivsqrtsd,
UD_Ivsqrtss,
UD_Ivstmxcsr,
UD_Ivsubpd,
UD_Ivsubps,
UD_Ivsubsd,
UD_Ivsubss,
UD_Ivtestpd,
UD_Ivtestps,
UD_Ivucomisd,
UD_Ivucomiss,
UD_Ivunpckhpd,
UD_Ivunpckhps,
UD_Ivunpcklpd,
UD_Ivunpcklps,
UD_Ivxorpd,
UD_Ivxorps,
UD_Ivzeroall,
UD_Ivzeroupper,
UD_Iwait,
UD_Iwbinvd,
UD_Iwrmsr,
UD_Ixadd,
UD_Ixchg,
UD_Ixcryptcbc,
UD_Ixcryptcfb,
UD_Ixcryptctr,
UD_Ixcryptecb,
UD_Ixcryptofb,
UD_Ixgetbv,
UD_Ixlatb,
UD_Ixor,
UD_Ixorpd,
UD_Ixorps,
UD_Ixrstor,
UD_Ixsave,
UD_Ixsetbv,
UD_Ixsha1,
UD_Ixsha256,
UD_Ixstore,
UD_Iinvalid,
UD_I3dnow,
UD_Inone,
UD_Idb,
UD_Ipause,
UD_MAX_MNEMONIC_CODE
};
extern const char * ud_mnemonics_str[];
#endif /* UD_ITAB_H */

228
deps/udis86/libudis86/syn-att.c vendored Normal file
View File

@ -0,0 +1,228 @@
/* udis86 - libudis86/syn-att.c
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
switch(op->size) {
case 16 : case 32 :
ud_asmprintf(u, "*"); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void
gen_operand(struct ud* u, struct ud_operand* op)
{
switch(op->type) {
case UD_OP_CONST:
ud_asmprintf(u, "$0x%x", op->lval.udword);
break;
case UD_OP_REG:
ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (u->br_far) {
opr_cast(u, op);
}
if (u->pfx_seg) {
ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, 0);
}
if (op->base) {
ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
if (op->base) {
ud_asmprintf(u, ",");
} else {
ud_asmprintf(u, "(");
}
ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
}
if (op->scale) {
ud_asmprintf(u, ",%d", op->scale);
}
if (op->base || op->index) {
ud_asmprintf(u, ")");
}
break;
case UD_OP_IMM:
ud_asmprintf(u, "$");
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
default: return;
}
}
/* =============================================================================
* translates to AT&T syntax
* =============================================================================
*/
extern void
ud_translate_att(struct ud *u)
{
int size = 0;
int star = 0;
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "o32 ");
break;
case 32:
case 64:
ud_asmprintf(u, "o16 ");
break;
}
}
/* check if P_ASO prefix was used */
if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "a32 ");
break;
case 32:
ud_asmprintf(u, "a16 ");
break;
case 64:
ud_asmprintf(u, "a32 ");
break;
}
}
if (u->pfx_lock)
ud_asmprintf(u, "lock ");
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* special instructions */
switch (u->mnemonic) {
case UD_Iretf:
ud_asmprintf(u, "lret ");
break;
case UD_Idb:
ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte);
return;
case UD_Ijmp:
case UD_Icall:
if (u->br_far) ud_asmprintf(u, "l");
if (u->operand[0].type == UD_OP_REG) {
star = 1;
}
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
break;
case UD_Ibound:
case UD_Ienter:
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
if (u->operand[1].type != UD_NONE) {
ud_asmprintf(u, ",");
gen_operand(u, &u->operand[1]);
}
return;
default:
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
if (size == 8) {
ud_asmprintf(u, "b");
} else if (size == 16) {
ud_asmprintf(u, "w");
} else if (size == 64) {
ud_asmprintf(u, "q");
}
if (star) {
ud_asmprintf(u, " *");
} else {
ud_asmprintf(u, " ");
}
if (u->operand[3].type != UD_NONE) {
gen_operand(u, &u->operand[3]);
ud_asmprintf(u, ", ");
}
if (u->operand[2].type != UD_NONE) {
gen_operand(u, &u->operand[2]);
ud_asmprintf(u, ", ");
}
if (u->operand[1].type != UD_NONE) {
gen_operand(u, &u->operand[1]);
ud_asmprintf(u, ", ");
}
if (u->operand[0].type != UD_NONE) {
gen_operand(u, &u->operand[0]);
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

224
deps/udis86/libudis86/syn-intel.c vendored Normal file
View File

@ -0,0 +1,224 @@
/* udis86 - libudis86/syn-intel.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
if (u->br_far) {
ud_asmprintf(u, "far ");
}
switch(op->size) {
case 8: ud_asmprintf(u, "byte " ); break;
case 16: ud_asmprintf(u, "word " ); break;
case 32: ud_asmprintf(u, "dword "); break;
case 64: ud_asmprintf(u, "qword "); break;
case 80: ud_asmprintf(u, "tword "); break;
case 128: ud_asmprintf(u, "oword "); break;
case 256: ud_asmprintf(u, "yword "); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
{
switch(op->type) {
case UD_OP_REG:
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (syn_cast) {
opr_cast(u, op);
}
ud_asmprintf(u, "[");
if (u->pfx_seg) {
ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->base) {
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "",
ud_reg_tab[op->index - UD_R_AL]);
if (op->scale) {
ud_asmprintf(u, "*%d", op->scale);
}
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, (op->base != UD_NONE ||
op->index != UD_NONE) ? 1 : 0);
}
ud_asmprintf(u, "]");
break;
case UD_OP_IMM:
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
case UD_OP_CONST:
if (syn_cast) opr_cast(u, op);
ud_asmprintf(u, "%d", op->lval.udword);
break;
default: return;
}
}
/* =============================================================================
* translates to intel syntax
* =============================================================================
*/
extern void
ud_translate_intel(struct ud* u)
{
/* check if P_OSO prefix is used */
if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "o32 "); break;
case 32:
case 64: ud_asmprintf(u, "o16 "); break;
}
}
/* check if P_ASO prefix was used */
if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "a32 "); break;
case 32: ud_asmprintf(u, "a16 "); break;
case 64: ud_asmprintf(u, "a32 "); break;
}
}
if (u->pfx_seg &&
u->operand[0].type != UD_OP_MEM &&
u->operand[1].type != UD_OP_MEM ) {
ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (u->pfx_lock) {
ud_asmprintf(u, "lock ");
}
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* print the instruction mnemonic */
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
if (u->operand[0].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, " ");
if (u->operand[0].type == UD_OP_MEM) {
if (u->operand[1].type == UD_OP_IMM ||
u->operand[1].type == UD_OP_CONST ||
u->operand[1].type == UD_NONE ||
(u->operand[0].size != u->operand[1].size)) {
cast = 1;
} else if (u->operand[1].type == UD_OP_REG &&
u->operand[1].base == UD_R_CL) {
switch (u->mnemonic) {
case UD_Ircl:
case UD_Irol:
case UD_Iror:
case UD_Ircr:
case UD_Ishl:
case UD_Ishr:
case UD_Isar:
cast = 1;
break;
default: break;
}
}
}
gen_operand(u, &u->operand[0], cast);
}
if (u->operand[1].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
if (u->operand[1].type == UD_OP_MEM &&
u->operand[0].size != u->operand[1].size &&
!ud_opr_is_sreg(&u->operand[0])) {
cast = 1;
}
gen_operand(u, &u->operand[1], cast);
}
if (u->operand[2].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
if (u->operand[2].type == UD_OP_MEM &&
u->operand[2].size != u->operand[1].size) {
cast = 1;
}
gen_operand(u, &u->operand[2], cast);
}
if (u->operand[3].type != UD_NONE) {
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[3], 0);
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

212
deps/udis86/libudis86/syn.c vendored Normal file
View File

@ -0,0 +1,212 @@
/* udis86 - libudis86/syn.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#include "types.h"
#include "decode.h"
#include "syn.h"
#include "udint.h"
/*
* Register Table - Order Matters (types.h)!
*
*/
const char* ud_reg_tab[] =
{
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w", "r14w", "r15w",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"es", "cs", "ss", "ds",
"fs", "gs",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"ymm0", "ymm1", "ymm2", "ymm3",
"ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11",
"ymm12", "ymm13", "ymm14", "ymm15",
"rip"
};
uint64_t
ud_syn_rel_target(struct ud *u, struct ud_operand *opr)
{
const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode);
switch (opr->size) {
case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask;
case 16: return (u->pc + opr->lval.sword) & trunc_mask;
case 32: return (u->pc + opr->lval.sdword) & trunc_mask;
default: UD_ASSERT(!"invalid relative offset size.");
return 0ull;
}
}
/*
* asmprintf
* Printf style function for printing translated assembly
* output. Returns the number of characters written and
* moves the buffer pointer forward. On an overflow,
* returns a negative number and truncates the output.
*/
int
ud_asmprintf(struct ud *u, const char *fmt, ...)
{
int ret;
int avail;
va_list ap;
va_start(ap, fmt);
avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */;
ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap);
if (ret < 0 || ret > avail) {
u->asm_buf_fill = u->asm_buf_size - 1;
} else {
u->asm_buf_fill += ret;
}
va_end(ap);
return ret;
}
void
ud_syn_print_addr(struct ud *u, uint64_t addr)
{
const char *name = NULL;
if (u->sym_resolver) {
int64_t offset = 0;
name = u->sym_resolver(u, addr, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
ud_asmprintf(u, "0x%" FMT64 "x", addr);
}
void
ud_syn_print_imm(struct ud* u, const struct ud_operand *op)
{
uint64_t v;
if (op->_oprcode == OP_sI && op->size != u->opr_mode) {
if (op->size == 8) {
v = (int64_t)op->lval.sbyte;
} else {
UD_ASSERT(op->size == 32);
v = (int64_t)op->lval.sdword;
}
if (u->opr_mode < 64) {
v = v & ((1ull << u->opr_mode) - 1ull);
}
} else {
switch (op->size) {
case 8 : v = op->lval.ubyte; break;
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
}
ud_asmprintf(u, "0x%" FMT64 "x", v);
}
void
ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign)
{
UD_ASSERT(op->offset != 0);
if (op->base == UD_NONE && op->index == UD_NONE) {
uint64_t v;
UD_ASSERT(op->scale == UD_NONE && op->offset != 8);
/* unsigned mem-offset */
switch (op->offset) {
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
ud_asmprintf(u, "0x%" FMT64 "x", v);
} else {
int64_t v;
UD_ASSERT(op->offset != 64);
switch (op->offset) {
case 8 : v = op->lval.sbyte; break;
case 16: v = op->lval.sword; break;
case 32: v = op->lval.sdword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
if (v < 0) {
ud_asmprintf(u, "-0x%" FMT64 "x", -v);
} else if (v > 0) {
ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v);
}
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

53
deps/udis86/libudis86/syn.h vendored Normal file
View File

@ -0,0 +1,53 @@
/* udis86 - libudis86/syn.h
*
* Copyright (c) 2002-2009
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef UD_SYN_H
#define UD_SYN_H
#include "types.h"
#ifndef __UD_STANDALONE__
# include <stdarg.h>
#endif /* __UD_STANDALONE__ */
extern const char* ud_reg_tab[];
uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*);
#ifdef __GNUC__
int ud_asmprintf(struct ud *u, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#else
int ud_asmprintf(struct ud *u, const char *fmt, ...);
#endif
void ud_syn_print_addr(struct ud *u, uint64_t addr);
void ud_syn_print_imm(struct ud* u, const struct ud_operand *op);
void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign);
#endif /* UD_SYN_H */
/*
vim: set ts=2 sw=2 expandtab
*/

260
deps/udis86/libudis86/types.h vendored Normal file
View File

@ -0,0 +1,260 @@
/* udis86 - libudis86/types.h
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef UD_TYPES_H
#define UD_TYPES_H
#ifdef __KERNEL__
/*
* -D__KERNEL__ is automatically passed on the command line when
* building something as part of the Linux kernel. Assume standalone
* mode.
*/
# include <linux/kernel.h>
# include <linux/string.h>
# ifndef __UD_STANDALONE__
# define __UD_STANDALONE__ 1
# endif
#endif /* __KERNEL__ */
#if !defined(__UD_STANDALONE__)
# include <stdint.h>
# include <stdio.h>
#endif
/* gcc specific extensions */
#ifdef __GNUC__
# define UD_ATTR_PACKED __attribute__((packed))
#else
# define UD_ATTR_PACKED
#endif /* UD_ATTR_PACKED */
/* -----------------------------------------------------------------------------
* All possible "types" of objects in udis86. Order is Important!
* -----------------------------------------------------------------------------
*/
enum ud_type
{
UD_NONE,
/* 8 bit GPRs */
UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
/* 16 bit GPRs */
UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
/* 32 bit GPRs */
UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
/* 64 bit GPRs */
UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
/* segment registers */
UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
UD_R_FS, UD_R_GS,
/* control registers*/
UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
/* debug registers */
UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
/* mmx registers */
UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
/* x87 registers */
UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
/* extended multimedia registers */
UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
/* 256B multimedia registers */
UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3,
UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7,
UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11,
UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15,
UD_R_RIP,
/* Operand Types */
UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
UD_OP_JIMM, UD_OP_CONST
};
#include "itab.h"
union ud_lval {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
};
/* -----------------------------------------------------------------------------
* struct ud_operand - Disassembled instruction Operand.
* -----------------------------------------------------------------------------
*/
struct ud_operand {
enum ud_type type;
uint16_t size;
enum ud_type base;
enum ud_type index;
uint8_t scale;
uint8_t offset;
union ud_lval lval;
/*
* internal use only
*/
uint64_t _legacy; /* this will be removed in 1.8 */
uint8_t _oprcode;
};
/* -----------------------------------------------------------------------------
* struct ud - The udis86 object.
* -----------------------------------------------------------------------------
*/
struct ud
{
/*
* input buffering
*/
int (*inp_hook) (struct ud*);
#ifndef __UD_STANDALONE__
FILE* inp_file;
#endif
const uint8_t* inp_buf;
size_t inp_buf_size;
size_t inp_buf_index;
uint8_t inp_curr;
size_t inp_ctr;
uint8_t inp_sess[64];
int inp_end;
int inp_peek;
void (*translator)(struct ud*);
uint64_t insn_offset;
char insn_hexcode[64];
/*
* Assembly output buffer
*/
char *asm_buf;
size_t asm_buf_size;
size_t asm_buf_fill;
char asm_buf_int[128];
/*
* Symbol resolver for use in the translation phase.
*/
const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset);
uint8_t dis_mode;
uint64_t pc;
uint8_t vendor;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[4];
uint8_t error;
uint8_t _rex;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
uint8_t pfx_adr;
uint8_t pfx_lock;
uint8_t pfx_str;
uint8_t pfx_rep;
uint8_t pfx_repe;
uint8_t pfx_repne;
uint8_t opr_mode;
uint8_t adr_mode;
uint8_t br_far;
uint8_t br_near;
uint8_t have_modrm;
uint8_t modrm;
uint8_t modrm_offset;
uint8_t vex_op;
uint8_t vex_b1;
uint8_t vex_b2;
uint8_t primary_opcode;
void * user_opaque_data;
struct ud_itab_entry * itab_entry;
struct ud_lookup_table_list_entry *le;
};
/* -----------------------------------------------------------------------------
* Type-definitions
* -----------------------------------------------------------------------------
*/
typedef enum ud_type ud_type_t;
typedef enum ud_mnemonic_code ud_mnemonic_code_t;
typedef struct ud ud_t;
typedef struct ud_operand ud_operand_t;
#define UD_SYN_INTEL ud_translate_intel
#define UD_SYN_ATT ud_translate_att
#define UD_EOI (-1)
#define UD_INP_CACHE_SZ 32
#define UD_VENDOR_AMD 0
#define UD_VENDOR_INTEL 1
#define UD_VENDOR_ANY 2
#endif
/*
vim: set ts=2 sw=2 expandtab
*/

99
deps/udis86/libudis86/udint.h vendored Normal file
View File

@ -0,0 +1,99 @@
/* udis86 - libudis86/udint.h -- definitions for internal use only
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef _UDINT_H_
#define _UDINT_H_
#include "types.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#if defined(UD_DEBUG) && HAVE_ASSERT_H
# include <assert.h>
# define UD_ASSERT(_x) assert(_x)
#else
# define UD_ASSERT(_x)
#endif /* !HAVE_ASSERT_H */
#if defined(UD_DEBUG)
#define UDERR(u, msg) \
do { \
(u)->error = 1; \
fprintf(stderr, "decode-error: %s:%d: %s", \
__FILE__, __LINE__, (msg)); \
} while (0)
#else
#define UDERR(u, m) \
do { \
(u)->error = 1; \
} while (0)
#endif /* !LOGERR */
#define UD_RETURN_ON_ERROR(u) \
do { \
if ((u)->error != 0) { \
return (u)->error; \
} \
} while (0)
#define UD_RETURN_WITH_ERROR(u, m) \
do { \
UDERR(u, m); \
return (u)->error; \
} while (0)
#ifndef __UD_STANDALONE__
# define UD_NON_STANDALONE(x) x
#else
# define UD_NON_STANDALONE(x)
#endif
/* printf formatting int64 specifier */
#ifdef FMT64
# undef FMT64
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define FMT64 "I64"
#else
# if defined(__APPLE__)
# define FMT64 "ll"
# elif defined(__amd64__) || defined(__x86_64__)
# define FMT64 "l"
# else
# define FMT64 "ll"
# endif /* !x64 */
#endif
/* define an inline macro */
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define UD_INLINE __inline /* MS Visual Studio requires __inline
instead of inline for C code */
#else
# define UD_INLINE inline
#endif
#endif /* _UDINT_H_ */

458
deps/udis86/libudis86/udis86.c vendored Normal file
View File

@ -0,0 +1,458 @@
/* udis86 - libudis86/udis86.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#include "udint.h"
#include "extern.h"
#include "decode.h"
#if !defined(__UD_STANDALONE__)
# if HAVE_STRING_H
# include <string.h>
# endif
#endif /* !__UD_STANDALONE__ */
static void ud_inp_init(struct ud *u);
/* =============================================================================
* ud_init
* Initializes ud_t object.
* =============================================================================
*/
extern void
ud_init(struct ud* u)
{
memset((void*)u, 0, sizeof(struct ud));
ud_set_mode(u, 16);
u->mnemonic = UD_Iinvalid;
ud_set_pc(u, 0);
#ifndef __UD_STANDALONE__
ud_set_input_file(u, stdin);
#endif /* __UD_STANDALONE__ */
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
}
/* =============================================================================
* ud_disassemble
* Disassembles one instruction and returns the number of
* bytes disassembled. A zero means end of disassembly.
* =============================================================================
*/
extern unsigned int
ud_disassemble(struct ud* u)
{
int len;
if (u->inp_end) {
return 0;
}
if ((len = ud_decode(u)) > 0) {
if (u->translator != NULL) {
u->asm_buf[0] = '\0';
u->translator(u);
}
}
return len;
}
/* =============================================================================
* ud_set_mode() - Set Disassemly Mode.
* =============================================================================
*/
extern void
ud_set_mode(struct ud* u, uint8_t m)
{
switch(m) {
case 16:
case 32:
case 64: u->dis_mode = m ; return;
default: u->dis_mode = 16; return;
}
}
/* =============================================================================
* ud_set_vendor() - Set vendor.
* =============================================================================
*/
extern void
ud_set_vendor(struct ud* u, unsigned v)
{
switch(v) {
case UD_VENDOR_INTEL:
u->vendor = v;
break;
case UD_VENDOR_ANY:
u->vendor = v;
break;
default:
u->vendor = UD_VENDOR_AMD;
}
}
/* =============================================================================
* ud_set_pc() - Sets code origin.
* =============================================================================
*/
extern void
ud_set_pc(struct ud* u, uint64_t o)
{
u->pc = o;
}
/* =============================================================================
* ud_set_syntax() - Sets the output syntax.
* =============================================================================
*/
extern void
ud_set_syntax(struct ud* u, void (*t)(struct ud*))
{
u->translator = t;
}
/* =============================================================================
* ud_insn() - returns the disassembled instruction
* =============================================================================
*/
const char*
ud_insn_asm(const struct ud* u)
{
return u->asm_buf;
}
/* =============================================================================
* ud_insn_offset() - Returns the offset.
* =============================================================================
*/
uint64_t
ud_insn_off(const struct ud* u)
{
return u->insn_offset;
}
/* =============================================================================
* ud_insn_hex() - Returns hex form of disassembled instruction.
* =============================================================================
*/
const char*
ud_insn_hex(struct ud* u)
{
u->insn_hexcode[0] = 0;
if (!u->error) {
unsigned int i;
const unsigned char *src_ptr = ud_insn_ptr(u);
char* src_hex;
src_hex = (char*) u->insn_hexcode;
/* for each byte used to decode instruction */
for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2;
++i, ++src_ptr) {
sprintf(src_hex, "%02x", *src_ptr & 0xFF);
src_hex += 2;
}
}
return u->insn_hexcode;
}
/* =============================================================================
* ud_insn_ptr
* Returns a pointer to buffer containing the bytes that were
* disassembled.
* =============================================================================
*/
extern const uint8_t*
ud_insn_ptr(const struct ud* u)
{
return (u->inp_buf == NULL) ?
u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr);
}
/* =============================================================================
* ud_insn_len
* Returns the count of bytes disassembled.
* =============================================================================
*/
extern unsigned int
ud_insn_len(const struct ud* u)
{
return u->inp_ctr;
}
/* =============================================================================
* ud_insn_get_opr
* Return the operand struct representing the nth operand of
* the currently disassembled instruction. Returns NULL if
* there's no such operand.
* =============================================================================
*/
const struct ud_operand*
ud_insn_opr(const struct ud *u, unsigned int n)
{
if (n > 3 || u->operand[n].type == UD_NONE) {
return NULL;
} else {
return &u->operand[n];
}
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a segment register type.
* =============================================================================
*/
int
ud_opr_is_sreg(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_ES &&
opr->base <= UD_R_GS;
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a general purpose
* register type.
* =============================================================================
*/
int
ud_opr_is_gpr(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_AL &&
opr->base <= UD_R_R15;
}
/* =============================================================================
* ud_set_user_opaque_data
* ud_get_user_opaque_data
* Get/set user opaqute data pointer
* =============================================================================
*/
void
ud_set_user_opaque_data(struct ud * u, void* opaque)
{
u->user_opaque_data = opaque;
}
void*
ud_get_user_opaque_data(const struct ud *u)
{
return u->user_opaque_data;
}
/* =============================================================================
* ud_set_asm_buffer
* Allow the user to set an assembler output buffer. If `buf` is NULL,
* we switch back to the internal buffer.
* =============================================================================
*/
void
ud_set_asm_buffer(struct ud *u, char *buf, size_t size)
{
if (buf == NULL) {
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
} else {
u->asm_buf = buf;
u->asm_buf_size = size;
}
}
/* =============================================================================
* ud_set_sym_resolver
* Set symbol resolver for relative targets used in the translation
* phase.
*
* The resolver is a function that takes a uint64_t address and returns a
* symbolic name for the that address. The function also takes a second
* argument pointing to an integer that the client can optionally set to a
* non-zero value for offsetted targets. (symbol+offset) The function may
* also return NULL, in which case the translator only prints the target
* address.
*
* The function pointer maybe NULL which resets symbol resolution.
* =============================================================================
*/
void
ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset))
{
u->sym_resolver = resolver;
}
/* =============================================================================
* ud_insn_mnemonic
* Return the current instruction mnemonic.
* =============================================================================
*/
enum ud_mnemonic_code
ud_insn_mnemonic(const struct ud *u)
{
return u->mnemonic;
}
/* =============================================================================
* ud_lookup_mnemonic
* Looks up mnemonic code in the mnemonic string table.
* Returns NULL if the mnemonic code is invalid.
* =============================================================================
*/
const char*
ud_lookup_mnemonic(enum ud_mnemonic_code c)
{
if (c < UD_MAX_MNEMONIC_CODE) {
return ud_mnemonics_str[c];
} else {
return NULL;
}
}
/*
* ud_inp_init
* Initializes the input system.
*/
static void
ud_inp_init(struct ud *u)
{
u->inp_hook = NULL;
u->inp_buf = NULL;
u->inp_buf_size = 0;
u->inp_buf_index = 0;
u->inp_curr = 0;
u->inp_ctr = 0;
u->inp_end = 0;
u->inp_peek = UD_EOI;
UD_NON_STANDALONE(u->inp_file = NULL);
}
/* =============================================================================
* ud_inp_set_hook
* Sets input hook.
* =============================================================================
*/
void
ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
{
ud_inp_init(u);
u->inp_hook = hook;
}
/* =============================================================================
* ud_inp_set_buffer
* Set buffer as input.
* =============================================================================
*/
void
ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len)
{
ud_inp_init(u);
u->inp_buf = buf;
u->inp_buf_size = len;
u->inp_buf_index = 0;
}
#ifndef __UD_STANDALONE__
/* =============================================================================
* ud_input_set_file
* Set FILE as input.
* =============================================================================
*/
static int
inp_file_hook(struct ud* u)
{
return fgetc(u->inp_file);
}
void
ud_set_input_file(register struct ud* u, FILE* f)
{
ud_inp_init(u);
u->inp_hook = inp_file_hook;
u->inp_file = f;
}
#endif /* __UD_STANDALONE__ */
/* =============================================================================
* ud_input_skip
* Skip n input bytes.
* ============================================================================
*/
void
ud_input_skip(struct ud* u, size_t n)
{
if (u->inp_end) {
return;
}
if (u->inp_buf == NULL) {
while (n--) {
int c = u->inp_hook(u);
if (c == UD_EOI) {
goto eoi;
}
}
return;
} else {
if (n > u->inp_buf_size ||
u->inp_buf_index > u->inp_buf_size - n) {
u->inp_buf_index = u->inp_buf_size;
goto eoi;
}
u->inp_buf_index += n;
return;
}
eoi:
u->inp_end = 1;
UDERR(u, "cannot skip, eoi received\b");
return;
}
/* =============================================================================
* ud_input_end
* Returns non-zero on end-of-input.
* =============================================================================
*/
int
ud_input_end(const struct ud *u)
{
return u->inp_end;
}
/* vim:set ts=2 sw=2 expandtab */

33
deps/udis86/udis86.h vendored Normal file
View File

@ -0,0 +1,33 @@
/* udis86 - udis86.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
*
* 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 OWNER 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.
*/
#ifndef UDIS86_H
#define UDIS86_H
#include "libudis86/types.h"
#include "libudis86/extern.h"
#include "libudis86/itab.h"
#endif

2
premake5.bat Normal file
View File

@ -0,0 +1,2 @@
premake5 vs2017
pause

BIN
premake5.exe Normal file

Binary file not shown.

71
premake5.lua Normal file
View File

@ -0,0 +1,71 @@
workspace "OpenParrot"
configurations { "Debug", "Release"}
platforms { "x64", "x86" }
flags { "StaticRuntime", "No64BitChecks" }
systemversion "10.0.16299.0"
symbols "On"
characterset "Unicode"
flags { "NoIncrementalLink", "NoEditAndContinue", "NoMinimalRebuild" }
includedirs { "deps/inc/", "deps/udis86/" }
libdirs { "deps/lib/" }
buildoptions { "/MP", "/std:c++17" }
configuration "Debug*"
targetdir "build/bin/debug"
defines "NDEBUG"
objdir "build/obj/debug"
configuration "Release*"
targetdir "build/bin/release"
defines "NDEBUG"
optimize "speed"
objdir "build/obj/release"
filter "platforms:x86"
architecture "x32"
filter "platforms:x64"
architecture "x64"
project "MinHook"
targetname "MinHook"
language "C"
kind "StaticLib"
files
{
"deps/src/buffer.c", "deps/src/hook.c",
"deps/src/trampoline.c",
}
filter "platforms:x86"
files { "deps/src/hde/hde32.c" }
filter "platforms:x64"
files { "deps/src/hde/hde64.c" }
project "udis86"
targetname "udis86"
language "C"
kind "StaticLib"
includedirs
{
"deps/udis86/"
}
files
{
"deps/udis86/libudis86/*.c"
}
include "OpenParrot"
include "OpenParrotLoader"