Initial Commit
This commit is contained in:
parent
a3145bd1f8
commit
329e263b1c
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal 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
|
1279
OpenParrot/deps/inc/dx8/d3d8.h
Normal file
1279
OpenParrot/deps/inc/dx8/d3d8.h
Normal file
File diff suppressed because it is too large
Load Diff
364
OpenParrot/deps/inc/dx8/d3d8caps.h
Normal file
364
OpenParrot/deps/inc/dx8/d3d8caps.h
Normal 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_ */
|
||||
|
1684
OpenParrot/deps/inc/dx8/d3d8types.h
Normal file
1684
OpenParrot/deps/inc/dx8/d3d8types.h
Normal file
File diff suppressed because it is too large
Load Diff
314
OpenParrot/deps/inc/ini_parser.hpp
Normal file
314
OpenParrot/deps/inc/ini_parser.hpp
Normal 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
|
||||
|
178
OpenParrot/deps/inc/injector/assembly.hpp
Normal file
178
OpenParrot/deps/inc/injector/assembly.hpp
Normal 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);
|
||||
}
|
||||
};
|
127
OpenParrot/deps/inc/injector/calling.hpp
Normal file
127
OpenParrot/deps/inc/injector/calling.hpp
Normal 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)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
229
OpenParrot/deps/inc/injector/gvm/gvm.hpp
Normal file
229
OpenParrot/deps/inc/injector/gvm/gvm.hpp
Normal 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
|
||||
|
||||
|
||||
}
|
203
OpenParrot/deps/inc/injector/gvm/translator.hpp
Normal file
203
OpenParrot/deps/inc/injector/gvm/translator.hpp
Normal 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);
|
||||
}
|
||||
}
|
687
OpenParrot/deps/inc/injector/hooking.hpp
Normal file
687
OpenParrot/deps/inc/injector/hooking.hpp
Normal 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
|
||||
|
||||
}
|
752
OpenParrot/deps/inc/injector/injector.hpp
Normal file
752
OpenParrot/deps/inc/injector/injector.hpp
Normal 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
|
||||
|
56
OpenParrot/deps/inc/injector/utility.hpp
Normal file
56
OpenParrot/deps/inc/injector/utility.hpp
Normal 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
25
OpenParrot/premake5.lua
Normal 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"
|
23
OpenParrot/src/Functions/Games/ES3X/MachStorm.cpp
Normal file
23
OpenParrot/src/Functions/Games/ES3X/MachStorm.cpp
Normal 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
|
53
OpenParrot/src/Functions/Games/Europa-R/FordRacing.cpp
Normal file
53
OpenParrot/src/Functions/Games/Europa-R/FordRacing.cpp
Normal 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
|
42
OpenParrot/src/Functions/Games/Europa-R/SR3.cpp
Normal file
42
OpenParrot/src/Functions/Games/Europa-R/SR3.cpp
Normal 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
|
41
OpenParrot/src/Functions/Games/Nesica/NesicaGeneric.cpp
Normal file
41
OpenParrot/src/Functions/Games/Nesica/NesicaGeneric.cpp
Normal 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);
|
385
OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp
Normal file
385
OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp
Normal 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)
|
238
OpenParrot/src/Functions/Games/TypeX2/TypeX2Generic.cpp
Normal file
238
OpenParrot/src/Functions/Games/TypeX2/TypeX2Generic.cpp
Normal 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)
|
197
OpenParrot/src/Functions/Global.cpp
Normal file
197
OpenParrot/src/Functions/Global.cpp
Normal 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)
|
103
OpenParrot/src/Functions/Global.h
Normal file
103
OpenParrot/src/Functions/Global.h
Normal 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;
|
||||
}
|
311
OpenParrot/src/Functions/Nesica_Libs/CryptoPipe.cpp
Normal file
311
OpenParrot/src/Functions/Nesica_Libs/CryptoPipe.cpp
Normal 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
|
14
OpenParrot/src/Functions/Nesica_Libs/CryptoPipe.h
Normal file
14
OpenParrot/src/Functions/Nesica_Libs/CryptoPipe.h
Normal 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);
|
251
OpenParrot/src/Functions/Nesica_Libs/FastIoEmu.cpp
Normal file
251
OpenParrot/src/Functions/Nesica_Libs/FastIoEmu.cpp
Normal 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);
|
||||
}
|
2
OpenParrot/src/Functions/Nesica_Libs/FastIoEmu.h
Normal file
2
OpenParrot/src/Functions/Nesica_Libs/FastIoEmu.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
void init_FastIoEmu();
|
536
OpenParrot/src/Functions/Nesica_Libs/NesysEmu.cpp
Normal file
536
OpenParrot/src/Functions/Nesica_Libs/NesysEmu.cpp
Normal 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)
|
144
OpenParrot/src/Functions/Nesica_Libs/NesysEmu.h
Normal file
144
OpenParrot/src/Functions/Nesica_Libs/NesysEmu.h
Normal 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();
|
847
OpenParrot/src/Functions/Nesica_Libs/RfidEmu.cpp
Normal file
847
OpenParrot/src/Functions/Nesica_Libs/RfidEmu.cpp
Normal 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);
|
||||
}
|
5
OpenParrot/src/Functions/Nesica_Libs/RfidEmu.h
Normal file
5
OpenParrot/src/Functions/Nesica_Libs/RfidEmu.h
Normal 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);
|
358
OpenParrot/src/Functions/Ring_amLib/amJvs.cpp
Normal file
358
OpenParrot/src/Functions/Ring_amLib/amJvs.cpp
Normal 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)
|
1
OpenParrot/src/Functions/Ring_amLib/amJvs.h
Normal file
1
OpenParrot/src/Functions/Ring_amLib/amJvs.h
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
12
OpenParrot/src/Functions/Types.h
Normal file
12
OpenParrot/src/Functions/Types.h
Normal file
@ -0,0 +1,12 @@
|
||||
enum class X2Type {
|
||||
None,
|
||||
RFID,
|
||||
Digital,
|
||||
Analog,
|
||||
VRL,
|
||||
Raiden4,
|
||||
BG4,
|
||||
Lupin3,
|
||||
Generic,
|
||||
GaiaAttack4
|
||||
};
|
88
OpenParrot/src/Functions/WindowedDx8.cpp
Normal file
88
OpenParrot/src/Functions/WindowedDx8.cpp
Normal 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)
|
80
OpenParrot/src/Functions/WindowedDx9.cpp
Normal file
80
OpenParrot/src/Functions/WindowedDx9.cpp
Normal 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)
|
251
OpenParrot/src/Functions/WindowedDxgi.cpp
Normal file
251
OpenParrot/src/Functions/WindowedDxgi.cpp
Normal 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
|
1
OpenParrot/src/StdInc.cpp
Normal file
1
OpenParrot/src/StdInc.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include <StdInc.h>
|
19
OpenParrot/src/StdInc.h
Normal file
19
OpenParrot/src/StdInc.h
Normal 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;
|
256
OpenParrot/src/Utility/GameDetect.cpp
Normal file
256
OpenParrot/src/Utility/GameDetect.cpp
Normal 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)
|
19
OpenParrot/src/Utility/GameDetect.h
Normal file
19
OpenParrot/src/Utility/GameDetect.h
Normal 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;
|
||||
};
|
41
OpenParrot/src/Utility/GameID.h
Normal file
41
OpenParrot/src/Utility/GameID.h
Normal 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,
|
||||
};
|
350
OpenParrot/src/Utility/Hooking.Patterns.cpp
Normal file
350
OpenParrot/src/Utility/Hooking.Patterns.cpp
Normal 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
|
||||
}
|
242
OpenParrot/src/Utility/Hooking.Patterns.h
Normal file
242
OpenParrot/src/Utility/Hooking.Patterns.h
Normal 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);
|
||||
}
|
||||
}
|
28
OpenParrot/src/Utility/InitFunction.cpp
Normal file
28
OpenParrot/src/Utility/InitFunction.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
16
OpenParrot/src/Utility/InitFunction.h
Normal file
16
OpenParrot/src/Utility/InitFunction.h
Normal 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;
|
||||
};
|
160
OpenParrot/src/Utility/Utils.cpp
Normal file
160
OpenParrot/src/Utility/Utils.cpp
Normal 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);
|
||||
}
|
149
OpenParrot/src/Utility/Utils.h
Normal file
149
OpenParrot/src/Utility/Utils.h
Normal 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
114
OpenParrot/src/dllmain.cpp
Normal 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)
|
17
OpenParrot/src/win64init.asm
Normal file
17
OpenParrot/src/win64init.asm
Normal 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
|
22
OpenParrotLoader/premake5.lua
Normal file
22
OpenParrotLoader/premake5.lua
Normal 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"
|
57
OpenParrotLoader/src/PE.cpp
Normal file
57
OpenParrotLoader/src/PE.cpp
Normal 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
18
OpenParrotLoader/src/PE.h
Normal 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);
|
263
OpenParrotLoader/src/main.cpp
Normal file
263
OpenParrotLoader/src/main.cpp
Normal 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
334
OpenParrotLoader/src/main.h
Normal 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
186
deps/inc/MinHook.h
vendored
Normal 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
312
deps/src/buffer.c
vendored
Normal 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
42
deps/src/buffer.h
vendored
Normal 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
326
deps/src/hde/hde32.c
vendored
Normal 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
105
deps/src/hde/hde32.h
vendored
Normal 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
337
deps/src/hde/hde64.c
vendored
Normal 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
112
deps/src/hde/hde64.h
vendored
Normal 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
39
deps/src/hde/pstdint.h
vendored
Normal 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
73
deps/src/hde/table32.h
vendored
Normal 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
74
deps/src/hde/table64.h
vendored
Normal 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
889
deps/src/hook.c
vendored
Normal 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
316
deps/src/trampoline.c
vendored
Normal 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
105
deps/src/trampoline.h
vendored
Normal 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
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
197
deps/udis86/libudis86/decode.h
vendored
Normal 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
113
deps/udis86/libudis86/extern.h
vendored
Normal 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
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
939
deps/udis86/libudis86/itab.h
vendored
Normal 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
228
deps/udis86/libudis86/syn-att.c
vendored
Normal 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
224
deps/udis86/libudis86/syn-intel.c
vendored
Normal 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
212
deps/udis86/libudis86/syn.c
vendored
Normal 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
53
deps/udis86/libudis86/syn.h
vendored
Normal 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
260
deps/udis86/libudis86/types.h
vendored
Normal 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
99
deps/udis86/libudis86/udint.h
vendored
Normal 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
458
deps/udis86/libudis86/udis86.c
vendored
Normal 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
33
deps/udis86/udis86.h
vendored
Normal 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
2
premake5.bat
Normal file
@ -0,0 +1,2 @@
|
||||
premake5 vs2017
|
||||
pause
|
BIN
premake5.exe
Normal file
BIN
premake5.exe
Normal file
Binary file not shown.
71
premake5.lua
Normal file
71
premake5.lua
Normal 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"
|
Loading…
Reference in New Issue
Block a user