VB Scripting examples

This commit is contained in:
Michal Salát 2023-01-04 16:31:51 +01:00 committed by GitHub
parent 7793f1fed3
commit aa0c9e4fb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 17207 additions and 0 deletions

45
VB-Research/ReadMe.txt Normal file
View File

@ -0,0 +1,45 @@
Credits:
-----------------------------
NTCore Hooking Engine written by Daniel Pistelli ntcore at gmail dot com (slightly modified)
https://ntcore.com/files/nthookengine.htm
diStorm x86/x64 BSD disassembler engine
Copyright (C) 2003-2012 Gil Dabah. diStorm at gmail dot com.
https://github.com/gdabah/distorm
vb_structs.h is from vbParser by sysenter-eip
openscript.dll and injector written by David Zimmer dzzie@yahoo.com
http://sandsprite.com
About:
-----------------------------
This is a research project aimed at making any VB6 application scriptable.
This starts with an injection dll that hooks some functions in the vb runtime,
patches internal class ObjectTypes, and registers the vb.global.forms
object in the Running Object Table (ROT)
Now all of the forms, embedded controls, public methods/variables/classes are accessible
as if it were an ActiveX exe. Clients can include WSH scripts, python scripts, VB6 etc.
Basically any language that use COM objects.
A brief overview of the technique is as follows:
- VB6 process is started with an injection dll
- New thread hooks CVBApplication_Init and BeginPaint
- CVBApplication_Init hook:
- Stores a reference to internal VB objects during runtime initialization
- Patches VBHeader.ProjectInfo.ObjectTable setting all classes public
- BeginPaint hook:
- Runs from main VB6 thread
- Adds a system menu item and subclasses main window for IPC (optional)
- Registers internal VB.Global.Forms object in the ROT
Note: This code is dependant on this particular version of the vb runtime (msvbvm60.dll)
See the following Avast blog post for more details: https://decoded.avast.io/davidzimmer/scripting-arbitrary-vb6-applications/

Binary file not shown.

View File

@ -0,0 +1,798 @@
#include <windows.h>
#include <stdlib.h>
#include "./distorm3.3/distorm.h"
#include <stdio.h>
#include <intrin.h>
#pragma warning(disable:4996)
//This is a modified version of the open source x86/x64
//NTCore Hooking Engine written by:
//Daniel Pistelli <ntcore@gmail.com>
//http://www.ntcore.com/files/nthookengine.htm
//
//It uses the x86/x64 GPL disassembler engine
//diStorm was written by Gil Dabah.
//Copyright (C) 2003-2012 Gil Dabah. diStorm at gmail dot com.
//
//Mods by David Zimmer <dzzie@yahoo.com>
//note: in several places we work on g_HookInfo[g_NumberOfHooks] as a global object in sub fx..
// 10000 hooks should be enough
#define MAX_HOOKS 10000
#define JUMP_WORST 0x10 // Worst case scenario + line all up on 0x10 boundary...
#define MAX_INSTRUCTIONS 100
#ifndef __cplusplus
#define extern "C" stdc
#else
#define stdc
#endif
#ifdef _M_IX86
#define isX64 false
#else
#define isX64 true
#endif
//on x86 htjmp requires less than 2gb between addresses
//on x64 pushret requires a 32 bit safe address use #pragma comment( linker, "/BASE:0x8000000")
// x86 only
enum hookType{ ht_jmp = 0, ht_pushret=1, ht_jmp5safe=2, ht_jmpderef=3, ht_micro, ht_auto };
enum hookErrors{ he_None=0, he_cantDisasm, he_cantHook, he_maxHooks, he_UnknownHookType, he_cantInit };
enum specificErrors{ hs_None, hs_NeedsAbs, hs_NoMicro, hs_ToBig, hs_x64NoPushRet };
char* hook_name[] = {"ht_jmp", "ht_pushret", "ht_jmp5safe", "ht_jmpderef", "ht_micro", "ht_auto"};
int logLevel = 0;
bool initilized = false;
char lastError[500] = {0};
hookErrors lastErrorCode = he_None;
specificErrors specificError = hs_None;
void (__cdecl *debugMsgHandler)(char* msg);
typedef struct _HOOK_INFO
{
ULONG_PTR Function; // Address of the original function
ULONG_PTR Hook; // Address of the function to call
ULONG_PTR Bridge; // Address of the instruction bridge
hookType hooktype;
char* ApiName;
bool Enabled;
int preAlignBytes;
int index;
int hookableBytes;
int OverwrittenBytes;
int OverwrittenInstructions;
} HOOK_INFO, *PHOOK_INFO;
HOOK_INFO g_HookInfo[MAX_HOOKS];
UINT g_NumberOfHooks = 0;
BYTE *g_pBridgeBuffer = NULL; // Here are going to be stored all the bridges
UINT g_CurrentBridgeBufferSize = 0; // This number is incremented as the bridge buffer is growing
char* GetHookName(hookType ht){
return hook_name[ht];
}
stdc
char* __cdecl GetHookError(void){
return (char*)lastError;
}
stdc
bool is32BitSafe(ULONG_PTR value){
ULONG_PTR b = value & 0x00000000FFFFFFFF;
return value == b ? true : false;
}
void dbgmsg(int level, const char *format, ...)
{
char buf[1024];
if(level > logLevel) return;
if(debugMsgHandler!=NULL && format!=NULL){
va_list args;
va_start(args,format);
try{
_vsnprintf(buf,1024,format,args);
(*debugMsgHandler)(buf);
}
catch(...){}
}
}
stdc
bool __cdecl InitHookEngine(void){
if(initilized) return true;
char* mem_marker = "APIHOOKS";
int len_marker = strlen(mem_marker);
UINT sz = MAX_HOOKS * (JUMP_WORST * 3);
sz +=len_marker;
//try to get a 32bit safe allocation address...
//g_pBridgeBuffer = (BYTE *)VirtualAlloc((void*)0x11000000 , sz, MEM_RESERVE | MEM_COMMIT , 0x40);
if(g_pBridgeBuffer == NULL){
g_pBridgeBuffer = (BYTE *) VirtualAlloc(NULL, sz, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}else{
dbgmsg(1,"32 bit safe trampoline buffer obtained\n");
}
if(g_pBridgeBuffer == NULL) return false;
memset(g_pBridgeBuffer, 0 , sz);
memset(&g_HookInfo[0], 0, sizeof(struct _HOOK_INFO) * MAX_HOOKS);
memcpy(g_pBridgeBuffer, mem_marker, len_marker);
g_CurrentBridgeBufferSize += len_marker;
initilized = true;
return true;
}
//can now resolve from any pointer - dz 11.28.22
HOOK_INFO *GetHookInfoFromFunction(ULONG_PTR lpFunc)
{
if (g_NumberOfHooks == 0)
return NULL;
for (UINT x = 0; x < g_NumberOfHooks; x++)
{
if (g_HookInfo[x].Function == lpFunc) return &g_HookInfo[x];
if (g_HookInfo[x].Bridge == lpFunc) return &g_HookInfo[x];
if (g_HookInfo[x].Hook == lpFunc) return &g_HookInfo[x];
}
return NULL;
}
#ifdef _M_IX86
//these two are only used for x86 ht_jmp5safe hooks..
void __stdcall output(ULONG_PTR ra){
HOOK_INFO *hi = GetHookInfoFromFunction(ra);
if(hi){
dbgmsg(0,"jmp %s+5 api detected trying to recover...\n", hi->ApiName );
}else{
dbgmsg(0,"jmp+5 api caught %x\n", ra );
}
}
void __declspec(naked) UnwindProlog(void){
_asm{
mov eax, [ebp-4] //return address
sub eax, 10 //function entry point
push eax //arg to output
call output
pop eax //we got here through a call from our api hook stub so this is ret
sub eax, 10 //back to api start address
mov esp, ebp //now unwind the prolog the shellcode did on its own..
pop ebp //saved ebp
jmp eax //and jmp back to the api public entry point to hit main hook jmp
}
}
#endif
// This function retrieves the necessary size for the jump
// overwrite as little of the api function as possible per hook type...
UINT GetJumpSize(hookType ht)
{
#ifdef _M_IX86
switch(ht){
case ht_jmp: return 5;
case ht_pushret: return 6;
case ht_micro: return 2; //overwrite size is actually only 2 + 5 in preamble.
default: return 10;
}
#else
switch(ht){
case ht_jmpderef: return 14;
case ht_pushret: return 6;
case ht_micro: return 6; //overwrite size is actually only 6 + 8 in preamble.
default: return 12;
}
#endif
}
stdc
char* __cdecl GetDisasm(ULONG_PTR pAddress, int* retLen = NULL){ //just a helper doesnt set error code..
_DecodeResult res;
_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
unsigned int decodedInstructionsCount = 0;
_DecodeType dt = isX64 ? Decode64Bits : Decode32Bits;
_OffsetType offset = 0;
res = distorm_decode(offset, // offset for buffer
(const BYTE *) pAddress, // buffer to disassemble
50, // function size (code size to disasm)
dt, // x86 or x64?
decodedInstructions, // decoded instr
MAX_INSTRUCTIONS, // array size
&decodedInstructionsCount // how many instr were disassembled?
);
if (res == DECRES_INPUTERR) return NULL;
int bufsz = 120;
char* tmp = (char*)malloc(bufsz);
memset(tmp, 0, bufsz);
_snprintf(tmp, bufsz-1 , "%10x %-10s %-6s %s\n",
pAddress,
decodedInstructions[0].instructionHex.p,
decodedInstructions[0].mnemonic.p,
decodedInstructions[0].operands.p
);
if(retLen !=NULL) *retLen = decodedInstructions[0].size;
return tmp;
}
bool UnSupportedOpcode(BYTE *b, int hookIndex){ //primary instruction opcodes are the same for x64 and x86
BYTE bb = *b;
switch(bb){
case 0x74:
case 0x75:
case 0xEB:
case 0xE8:
case 0xE9:
case 0x0F: //can lead to false positive...
//case 0xFF:
case 0xc3:
case 0xc4:
goto failed;
}
return false;
failed:
UINT offset = (UINT)b - g_HookInfo[hookIndex].Function;
char* d = GetDisasm((ULONG_PTR)b);
if(d == NULL){
sprintf(lastError,"Unsupported opcode at %s+%d: Opcode: %x", g_HookInfo[hookIndex].ApiName, offset, *b);
lastErrorCode = he_cantHook;
}else{
sprintf(lastError,"Unsupported opcode at %s+%d\n%s", g_HookInfo[hookIndex].ApiName, offset, d);
lastErrorCode = he_cantHook;
free(d);
}
dbgmsg(1,lastError);
return true;
}
void WriteInt( BYTE *pAddress, UINT value){ //4 bytes always
*(UINT*)pAddress = value;
}
void WriteShort( BYTE *pAddress, short value){ //2 bytes always
*(short*)pAddress = value;
}
void WriteULONG( BYTE *pAddress, ULONG_PTR value){//8 BYTES ON X64
*(ULONG_PTR*)pAddress = value;
}
// A relative jump (opcode 0xE9) treats its operand as a 32 bit signed offset. If the unsigned
// distance between from and to is of sufficient magnitude that it cannot be represented as a
// signed 32 bit integer, then we'll have to use an absolute jump instead (0xFF 0x25).
//https://bitbucket.org/edd/nanohook/src/da62bc7232e6/src/hook.cpp
bool abs_jump_required(UINT from, UINT to)
{
const UINT upper = max(from, to);
const UINT lower = min(from, to);
return ((upper - lower) > 0x7FFFFFFF) ? true : false;
}
bool isRelativeJump(hookType ht){
#ifdef _M_IX86
if( ht == ht_pushret ) return false;
if( ht == ht_jmpderef ) return false;
return true;
#else
return false;
#endif
}
void OverWriteScratchPad(VOID *pAddress, HOOK_INFO *hinfo)
{
DWORD dwOldProtect = 0;
DWORD dwBuf = 0;
int minPreAlign = 0;
int sz = hinfo->OverwrittenBytes;
BYTE *pCur = (BYTE *)pAddress;
if(hinfo->hooktype == ht_micro){
minPreAlign = isX64 ? 8 : 5 ;
pCur -= minPreAlign;
sz += minPreAlign;
}
VirtualProtect(pCur, JUMP_WORST, PAGE_EXECUTE_READWRITE, &dwOldProtect);
for(int i=0; i<sz; i++) *pCur++ = 0xCC;
VirtualProtect(pCur, JUMP_WORST, dwOldProtect, &dwBuf);
}
bool WriteJump(VOID *pAddress, ULONG_PTR JumpTo, hookType ht, int hookIndex)
{
DWORD dwOldProtect = 0;
int minPreAlign = 0;
if(ht == ht_micro) minPreAlign = isX64 ? 8 : 5 ;
BYTE *pCur = (BYTE *)pAddress;
VirtualProtect(pCur - minPreAlign , JUMP_WORST, PAGE_EXECUTE_READWRITE, &dwOldProtect);
#ifdef _M_IX86
if( isRelativeJump(ht) ){
if( abs_jump_required( (UINT)pAddress, (UINT)JumpTo) ){
DebugBreak(); //this shouldnt happen with the pre-Validation
//sprintf(lastError, "Can not use a relative jump for this hook %s\n", g_HookInfo[hookIndex].ApiName);
//lastErrorCode = he_cantHook;
//dbgmsg(0, "Can not use a relative jump for this hook %s\n", g_HookInfo[hookIndex].ApiName);
return false;
}
}
if(ht == ht_pushret){
//68 DDCCBBAA PUSH AABBCCDD (6 bytes) - hook detectors wont see it,
//C3 RETN jmp+5 = crash (good no exec, bad crash..)
*pCur = 0x68;
*((ULONG_PTR *)++pCur) = JumpTo;
pCur+=4;
*pCur = 0xc3;
}
else if(ht == ht_micro){
// E9 xxxxxxxx jmp 0x11111111 <--in fx preamble (5 bytes)
// EB F9 jmp short here <--api entry point (2 bytes)
pAddress = (BYTE *)pAddress - 5;
UINT dst = JumpTo - (UINT)(pAddress) - 5; //2gb address limitation
*pCur = 0xE9;
WriteInt(pCur+1, dst);
WriteShort(pCur+5, 0xF9EB);
}
else if(ht == ht_jmpderef){
//eip> FF25 AABBCCDD JMP DWORD PTR DS:[eip+6] 10 bytes
//eip+6 xxxxxxxx data after instruction, other hookers will bad disasm, and large footprint
*pCur = 0xff; //if we can use the preALignBytes footprint down to 6...
*(pCur+1) = 0x25;
WriteInt(pCur+2, (int)pCur + 6);
WriteInt(pCur+6, JumpTo);
}
else if(ht== ht_jmp){
//E9 jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)]) (5 bytes)
UINT dst = JumpTo - (UINT)(pAddress) - 5; //2gb address limitation
*pCur = 0xE9;
WriteInt(pCur+1, dst);
}
else if(ht = ht_jmp5safe){ //this needs a second trampoline if api+5 jmp is hit, it needs to reverse the push ebp to send to hook..
//E9 jmp normal prolog + eB call to UnwindProlog (10 bytes)
*(pCur) = 0xE9; //fancy and cool but big footprint and complex..
UINT dst = JumpTo - (UINT)(pCur) - 5;
WriteInt(pCur+1, dst);
*(pCur+5) = 0xE8;
dst = (UINT)&UnwindProlog - (UINT)(pCur+5) - 5; //api+5 jmps are sent to our generic unwinder
WriteInt(pCur+6, dst);
}
else{
dbgmsg(0, "Unimplemented hook type asked for");
DebugBreak();
return false;
}
#else ifdef _M_AMD64
if(ht == ht_jmpderef){
//ff 25 00 00 00 00 jmp [rip+addr] (14 bytes)
//80 70 8e 77 00 00 00 00 data: 00000000778E7080
WriteShort(pCur, 0x25FF);
WriteInt(pCur+2, 0x00000000);
WriteULONG(pCur+6, JumpTo);
}else if(ht == ht_pushret){
//68 DDCCBBAA PUSH AABBCCDD (6 bytes) - x64 push still takes a 32 bit const, 8 bytes written to stack, high 8 = 0
//C3 RETN
if(!is32BitSafe(JumpTo) ){
dbgmsg(0, "Hooking %s failed: Can not use x64 push ret hook - jumpTo address is not 32bit safe %016llx\n", g_HookInfo[hookIndex].ApiName, JumpTo);
DebugBreak(); //this shouldnt happen with the pre-Validation
return false;
}
*pCur = 0x68;
WriteInt(pCur+1, JumpTo);
pCur+=5;
*pCur = 0xc3;
}else if(ht == ht_micro){
//0000000011000000 8 data bytes in function prealignment paddding...
//0000000011000008 FF 25 F2 FF FF FF jmp qword ptr [11000000h] <-- 6 byte hook in API prolog
WriteInt(pCur, 0xFFF225FF);
WriteShort(pCur+4, 0xFFFF);
WriteULONG(pCur-8, JumpTo);
}else{
//default x64 hooktype..
//48 b8 80 70 8e 77 00 00 00 00 mov rax, 0x00000000778E7080 (12 bytes)
//ff e0 jmp rax
WriteShort(pCur, 0xb848);
WriteULONG(pCur+2, JumpTo);
WriteShort(pCur+10, 0xE0FF);
}
/*
how about ff25 [4byte address of alloced table entry]..
should be down to 6 bytes inline?
if you can stay in the 2gb range i think..
(16 bytes preserves rax)
50 push rax
48 B8 EF CD AB 90 78 56 34 12 mov rax, 1234567890ABCDEFh
48 87 04 24 xchg rax, [rsp]
C3 retn
*/
#endif
DWORD dwBuf = 0; // nessary othewrise the function fails
VirtualProtect(pCur - minPreAlign, JUMP_WORST, dwOldProtect, &dwBuf);
return true;
}
//is there any padding before the function start to emded data? many x86 have 5 bytes..
int CountPreAlignBytes(BYTE* pAddress){
int x;
for(x=0; x<=9; x++ ){
BYTE b = *(BYTE*)(pAddress-x-1);
if(b==0x90 || b==0xCC) ; else break;
}
return x;
}
VOID *CreateBridge(HOOK_INFO *hinfo)
{
if (g_pBridgeBuffer == NULL) return NULL;
UINT x = 0;
_DecodeResult res;
_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
unsigned int decodedInstructionsCount = 0;
_DecodeType dt = isX64 ? Decode64Bits : Decode32Bits;
_OffsetType offset = 0;
ULONG_PTR Function = hinfo->Function;
int JumpSize = GetJumpSize(hinfo->hooktype);
res = distorm_decode(offset, // offset for buffer
(const BYTE *) Function, // buffer to disassemble
50, // function size (code size to disasm)
// 50 instr should be _quite_ enough
dt, // x86 or x64?
decodedInstructions, // decoded instr
MAX_INSTRUCTIONS, // array size
&decodedInstructionsCount // how many instr were disassembled?
);
if (res == DECRES_INPUTERR){
sprintf(lastError, "Could not disassemble address %x", (UINT)Function);
//dbgmsg(lastError);
lastErrorCode = he_cantDisasm;
return NULL;
}
DWORD InstrSize = 0;
VOID *pBridge = (VOID *) &g_pBridgeBuffer[g_CurrentBridgeBufferSize];
//copy full instructions from API to our trampoline.
for (x ; x < decodedInstructionsCount; x++)
{
if (InstrSize >= JumpSize) break;
BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR) Function);
if(logLevel >=3){
dbgmsg(3, "%s+%d \t %-10s %-6s %s",
hinfo->ApiName,
InstrSize,
decodedInstructions[x].instructionHex.p,
decodedInstructions[x].mnemonic.p,
decodedInstructions[x].operands.p
);
}
if( UnSupportedOpcode(pCurInstr, hinfo->index) ){
dbgmsg(0, "CreatreBridge::UnSupportedOpcode found missed in pre-Validation?! needed=%d, hookable=%d, cur=%d, type=%s",
JumpSize, hinfo->hookableBytes,InstrSize, GetHookName(hinfo->hooktype)
);
DebugBreak();
//if we leave here, g_CurrentBridgeBufferSize has been incremented and bytes copied to
//the alloced g_pBridgeBuffer, but the API itself is untouched.
return NULL;
}
memcpy(&g_pBridgeBuffer[g_CurrentBridgeBufferSize], (VOID *) pCurInstr, decodedInstructions[x].size);
g_CurrentBridgeBufferSize += decodedInstructions[x].size;
InstrSize += decodedInstructions[x].size;
}
hinfo->OverwrittenInstructions = x;
hinfo->OverwrittenBytes = InstrSize; //we will 0xCC this many in API latter for debugging sake...
//to leave trampoline...
hookType ht = isX64 ? ht_jmp : ht_pushret; //both absolute address jumps for safety...
bool rv = WriteJump(&g_pBridgeBuffer[g_CurrentBridgeBufferSize], Function + InstrSize, ht, hinfo->index);
g_CurrentBridgeBufferSize += GetJumpSize(ht);
if(!rv) return NULL;
return pBridge;
}
void ZeroHookInfo(int hookIndex){
if( g_HookInfo[hookIndex].ApiName != NULL) free(g_HookInfo[hookIndex].ApiName);
memset(&g_HookInfo[hookIndex], 0, sizeof(struct _HOOK_INFO));
}
int HookableBytes(ULONG_PTR Function){
_DecodeResult res;
_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
unsigned int decodedInstructionsCount = 0;
_DecodeType dt = isX64 ? Decode64Bits : Decode32Bits;
_OffsetType offset = 0;
res = distorm_decode(offset, // offset for buffer
(const BYTE *) Function, // buffer to disassemble
50, // function size (code size to disasm)
// 50 instr should be _quite_ enough
dt, // x86 or x64?
decodedInstructions, // decoded instr
MAX_INSTRUCTIONS, // array size
&decodedInstructionsCount // how many instr were disassembled?
);
if (res == DECRES_INPUTERR) return 0;
DWORD InstrSize = 0;
for (UINT x = 0; x < decodedInstructionsCount; x++)
{
BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR)Function);
if (InstrSize >= 15) break;
if(UnSupportedOpcode(pCurInstr, g_NumberOfHooks)) break;
InstrSize += decodedInstructions[x].size;
}
return InstrSize;
}
bool ValidateHookType(HOOK_INFO *hinfo){
int neededSize = GetJumpSize(hinfo->hooktype);
char* name = hook_name[(int)hinfo->hooktype];
specificError = hs_None;
if(hinfo->hookableBytes < neededSize){
specificError = hs_ToBig;
sprintf(lastError, "%s hook failed %s only has %d hookable bytes available\n", name , hinfo->ApiName, hinfo->hookableBytes );
return false;
}
if( isRelativeJump( hinfo->hooktype ) ){//only use relative jumps for api->hook *never* bridge->real api
if( abs_jump_required( (UINT)hinfo->Function, (UINT)hinfo->Hook ) ){
specificError = hs_NeedsAbs;
sprintf(lastError, "Can not use a relative jump for this hook %s\n", hinfo->ApiName);
return false;
}
}
if(hinfo->hooktype == ht_micro){
int minPreAlign = isX64 ? 8 : 5 ;
if(hinfo->preAlignBytes < minPreAlign){
specificError = hs_NoMicro;
sprintf(lastError, "ht_micro hook failed %s only has %d preAmble bytes available\n", hinfo->ApiName, hinfo->preAlignBytes );
return false;
}
}
if(isX64 && !is32BitSafe(hinfo->Hook) ){
specificError = hs_x64NoPushRet;
sprintf(lastError, "Hooking %s failed: Can not use x64 push ret hook - jumpTo address is not 32bit safe %016llx\n", hinfo->ApiName, hinfo->Hook);
return false;
}
return true;
}
bool AutoChooseHookType(HOOK_INFO *hinfo){
// ht_jmp = 0, ht_pushret=1, ht_jmp5safe=2, ht_jmpderef=3, ht_micro, ht_auto
if(isX64){
//ht_jmpderef:14, ht_pushret 6; ht_micro 6; default: 12;
hinfo->hooktype = ht_jmp; //safest but requires 12 bytes...
if(ValidateHookType(hinfo)) return true;
hinfo->hooktype = ht_micro; //if size was an issue, lets try this one
if(ValidateHookType(hinfo)) return true;
hinfo->hooktype = ht_pushret; //maybe no preamble space, this one is more limited though in address range..
if(ValidateHookType(hinfo)) return true;
return false; //bummer no go...
}else{
//ht_jmp: 5; ht_pushret 6; ht_micro 2; default: 10
hinfo->hooktype = ht_jmp; //best general choice
if(ValidateHookType(hinfo)) return true;
hinfo->hooktype = ht_micro; //if size was an issue, lets try this one
if(ValidateHookType(hinfo)) return true;
return false; //bummer no go...
}
}
stdc
BOOL __cdecl HookFunction(ULONG_PTR OriginalFunction, ULONG_PTR NewFunction, char *name, hookType ht)
{
lastErrorCode = he_None;
specificError = hs_None;
lastError[0] = 0;
if(!initilized){
if( !InitHookEngine() ){
lastErrorCode = he_cantInit;
strcpy(lastError,"Can not Initilize HookEngine.");
dbgmsg(1,lastError);
return FALSE;
}
}
HOOK_INFO *hinfo = GetHookInfoFromFunction(OriginalFunction);
if (hinfo) return TRUE; //already hooked...
if (g_NumberOfHooks == (MAX_HOOKS - 1)){
lastErrorCode = he_maxHooks;
strcpy(lastError,"Maximum number of hooks reached.");
dbgmsg(1,lastError);
return FALSE;
}
if(ht > ht_auto){
sprintf(lastError, "Unimplemented hook type asked for");
lastErrorCode = he_UnknownHookType;
return false;
}
hinfo = &g_HookInfo[g_NumberOfHooks];
hinfo->Function = OriginalFunction;
hinfo->Hook = NewFunction;
hinfo->hooktype = ht;
hinfo->index = g_NumberOfHooks;
hinfo->ApiName = strdup(name);
hinfo->preAlignBytes = CountPreAlignBytes( (BYTE*)OriginalFunction );
hinfo->hookableBytes = HookableBytes( OriginalFunction );
dbgmsg(1, "Hooking %s (0x%llx) -> 0x%llx, pre=%d avail=%d\n", hinfo->ApiName, hinfo->Function , hinfo->Hook , hinfo->preAlignBytes, hinfo->hookableBytes);
if( ht == ht_auto ){
if(!AutoChooseHookType(hinfo)){
lastErrorCode = he_cantHook;
dbgmsg(1, lastError);
ZeroHookInfo(hinfo->index);
return FALSE;
}
dbgmsg(1, "AutoChooseHookType selected %s for %s\n", hook_name[(int)hinfo->hooktype], hinfo->ApiName );
}
if( !ValidateHookType(hinfo) ){
lastErrorCode = he_cantHook;
dbgmsg(1, lastError);
ZeroHookInfo(hinfo->index);
return FALSE;
}
VOID *pBridge = CreateBridge(hinfo);
if (pBridge == NULL){
ZeroHookInfo(g_NumberOfHooks);
return FALSE;
}
hinfo->Bridge = (ULONG_PTR) pBridge;
hinfo->Enabled = true;
OverWriteScratchPad((VOID *)OriginalFunction, hinfo); //make pad were going to overwrite all 0xCC for debugging sake..
if(!WriteJump((VOID *) OriginalFunction, NewFunction, hinfo->hooktype, g_NumberOfHooks)){ //activates hook in api prolog..
ZeroHookInfo(g_NumberOfHooks);
return FALSE;
}
g_NumberOfHooks++; //now its complete..
return TRUE;
}
stdc
int __cdecl DisableHook(ULONG_PTR Function)
{
HOOK_INFO *hinfo = GetHookInfoFromFunction(Function);
if (hinfo)
{
if(hinfo->Enabled){
hinfo->Enabled = false;
WriteJump((VOID *)hinfo->Function, hinfo->Bridge, ht_jmp, hinfo->index);
return 1;
}
return -1;
}
return -2;
}
stdc
VOID __cdecl EnableHook(ULONG_PTR Function)
{
HOOK_INFO *hinfo = GetHookInfoFromFunction(Function);
if (hinfo)
{
if(!hinfo->Enabled){
hinfo->Enabled = true;
WriteJump((VOID *)hinfo->Function, hinfo->Hook, hinfo->hooktype, hinfo->index );
}
}
}
stdc
ULONG_PTR __cdecl GetOriginalFunction(ULONG_PTR Hook)
{
if (g_NumberOfHooks == 0)
return NULL;
for (UINT x = 0; x < g_NumberOfHooks; x++)
{
if (g_HookInfo[x].Hook == Hook)
return g_HookInfo[x].Bridge;
}
return NULL;
}

View File

@ -0,0 +1,37 @@
//This is a modified version of the open source x86/x64
//NTCore Hooking Engine written by:
//Daniel Pistelli <ntcore@gmail.com>
//http://www.ntcore.com/files/nthookengine.htm
//
//It uses the x86/x64 GPL disassembler engine
//diStorm was written by Gil Dabah.
//Copyright (C) 2003-2012 Gil Dabah. diStorm at gmail dot com.
//
//Mods by David Zimmer <dzzie@yahoo.com>
enum hookType{
ht_jmp = 0, /* 32 - 5 byte relative, 64 - 12 byte absolute */
ht_pushret=1, /* 32 - 6 byte absolute, 64 - 6 byte absolute (target MUST be 32 bit addressable) */
ht_jmp5safe=2, /* 32 bit only, 10 byte relative hook, safe against hook bypassers */
ht_jmpderef=3, /* 32 bit - 10 byte absolute, 64 bit - 14 byte absolute */
ht_micro, /* 32 bit - 2/5 byte hook (api/prealignment) relative jmp, 64 bit - 6/8 byte hook - absolute address */
ht_auto /* probes best hook to use automatically at runtime */
};
enum hookErrors{ he_None=0, he_cantDisasm, he_cantHook, he_maxHooks, he_UnknownHookType, he_cantInit };
enum specificErrors{ hs_None, hs_NeedsAbs, hs_NoMicro, hs_ToBig, hs_x64NoPushRet };
extern specificErrors specificError;
extern hookErrors lastErrorCode;
extern int logLevel;
extern void (__cdecl *debugMsgHandler)(char* msg);
extern char* __cdecl GetHookError(void);
extern char* __cdecl GetDisasm(ULONG_PTR pAddress, int* retLen = NULL);
extern int __cdecl DisableHook(ULONG_PTR Function);
extern void __cdecl EnableHook(ULONG_PTR Function);
extern ULONG_PTR __cdecl GetOriginalFunction(ULONG_PTR Hook);
extern BOOL __cdecl HookFunction(ULONG_PTR OriginalFunction, ULONG_PTR NewFunction, char* name, enum hookType ht);
extern bool is32BitSafe(ULONG_PTR value);

View File

@ -0,0 +1,181 @@
/*
config.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef CONFIG_H
#define CONFIG_H
/* diStorm version number. */
#define __DISTORMV__ 0x030300
#include <string.h> /* memset, memcpy - can be easily self implemented for libc independency. */
#include "distorm.h"
/*
* 64 bit offsets support:
* This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET
* Note: make sure that the caller (library user) defines it too!
*/
/* #define SUPPORT_64BIT_OFFSET */
/*
* If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line.
* So the interface functions will be exported, otherwise they are useable only for static library.
* For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes.
*/
/* #define DISTORM_DYNAMIC */
/*
* If DISTORM_LIGHT is defined, everything involved in formatting the instructions
* as text will be excluded from compilation.
* distorm_decode(..) and distorm_format(..) will not be available.
* This will decrease the size of the executable and leave you with decomposition functionality only.
*
* Note: it should be either set in the preprocessor definitions manually or in command line -D switch.
* #define DISTORM_LIGHT
*/
/*
* diStorm now supports little/big endian CPU's.
* It should detect the endianness according to predefined macro's of the compiler.
* If you don't use GCC/MSVC you will have to define it on your own.
*/
/* These macros are used in order to make the code portable. */
#ifdef __GNUC__
#include <stdint.h>
#define _DLLEXPORT_
#define _FASTCALL_
#define _INLINE_ static
/* GCC ignores this directive... */
/*#define _FASTCALL_ __attribute__((__fastcall__))*/
/* Set endianity (supposed to be LE though): */
#ifdef __BIG_ENDIAN__
#define BE_SYSTEM
#endif
/* End of __GCC__ */
#elif __WATCOMC__
#include <stdint.h>
#define _DLLEXPORT_
#define _FASTCALL_
#define _INLINE_ __inline
/* End of __WATCOMC__ */
#elif __DMC__
#include <stdint.h>
#define _DLLEXPORT_
#define _FASTCALL_
#define _INLINE_ __inline
/* End of __DMC__ */
#elif __TINYC__
#include <stdint.h>
#define _DLLEXPORT_
#define _FASTCALL_
#define _INLINE_
/* End of __TINYC__ */
#elif _MSC_VER
/* stdint alternative is defined in distorm.h */
#define _DLLEXPORT_ __declspec(dllexport)
#define _FASTCALL_ __fastcall
#define _INLINE_ __inline
/* Set endianity (supposed to be LE though): */
#if !defined(_M_IX86) && !defined(_M_X64)
#define BE_SYSTEM
#endif
#endif /* #elif _MSC_VER */
/* If the library isn't compiled as a dynamic library don't export any functions. */
#ifndef DISTORM_DYNAMIC
#undef _DLLEXPORT_
#define _DLLEXPORT_
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/* Define stream read functions for big endian systems. */
#ifdef BE_SYSTEM
/*
* These functions can read from the stream safely!
* Swap endianity of input to little endian.
*/
static _INLINE_ int16_t RSHORT(const uint8_t *s)
{
return s[0] | (s[1] << 8);
}
static _INLINE_ uint16_t RUSHORT(const uint8_t *s)
{
return s[0] | (s[1] << 8);
}
static _INLINE_ int32_t RLONG(const uint8_t *s)
{
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
}
static _INLINE_ uint32_t RULONG(const uint8_t *s)
{
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
}
static _INLINE_ int64_t RLLONG(const uint8_t *s)
{
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56);
}
static _INLINE_ uint64_t RULLONG(const uint8_t *s)
{
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56);
}
#else
/* Little endian macro's will just make the cast. */
#define RSHORT(x) *(int16_t *)x
#define RUSHORT(x) *(uint16_t *)x
#define RLONG(x) *(int32_t *)x
#define RULONG(x) *(uint32_t *)x
#define RLLONG(x) *(int64_t *)x
#define RULLONG(x) *(uint64_t *)x
#endif
#endif /* CONFIG_H */

View File

@ -0,0 +1,615 @@
/*
decoder.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "decoder.h"
#include "instructions.h"
#include "insts.h"
#include "prefix.h"
#include "x86defs.h"
#include "operands.h"
#include "insts.h"
#include "mnemonics.h"
/* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */
static _DecodeType decode_get_effective_addr_size(_DecodeType dt, _iflags decodedPrefixes)
{
/*
* This table is to map from the current decoding mode to an effective address size:
* Decode16 -> Decode32
* Decode32 -> Decode16
* Decode64 -> Decode32
*/
static _DecodeType AddrSizeTable[] = {Decode32Bits, Decode16Bits, Decode32Bits};
/* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */
if (decodedPrefixes & INST_PRE_ADDR_SIZE) dt = AddrSizeTable[dt];
return dt;
}
static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedPrefixes, unsigned int rex, _iflags instFlags)
{
/*
* This table is to map from the current decoding mode to an effective operand size:
* Decode16 -> Decode32
* Decode32 -> Decode16
* Decode64 -> Decode16
* Not that in 64bits it's a bit more complicated, because of REX and promoted instructions.
*/
static _DecodeType OpSizeTable[] = {Decode32Bits, Decode16Bits, Decode16Bits};
if (decodedPrefixes & INST_PRE_OP_SIZE) return OpSizeTable[dt];
if (dt == Decode64Bits) {
/*
* REX Prefix toggles data size to 64 bits.
* Operand size prefix toggles data size to 16.
* Default data size is 32 bits.
* Promoted instructions are 64 bits if they don't require a REX perfix.
* Non promoted instructions are 64 bits if the REX prefix exists.
*/
/* Automatically promoted instructions have only INST_64BITS SET! */
if (((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) ||
/* Other instructions in 64 bits can be promoted only with a REX prefix. */
((decodedPrefixes & INST_PRE_REX) && (rex & PREFIX_EX_W))) dt = Decode64Bits;
else dt = Decode32Bits; /* Default. */
}
return dt;
}
static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di)
{
/* The ModR/M byte of the current instruction. */
unsigned int modrm = 0;
/* The REX/VEX prefix byte value. */
unsigned int vrex = ps->vrex;
/*
* Backup original input, so we can use it later if a problem occurs
* (like not enough data for decoding, invalid opcode, etc).
*/
const uint8_t* startCode = ci->code;
/* Holds the info about the current found instruction. */
_InstInfo* ii = NULL;
_InstSharedInfo* isi = NULL;
/* Used only for special CMP instructions which have pseudo opcodes suffix. */
unsigned char cmpType = 0;
/*
* Indicates whether it is right to LOCK the instruction by decoding its first operand.
* Only then you know if it's ok to output the LOCK prefix's text...
* Used for first operand only.
*/
int lockable = FALSE;
/* Calcualte (and cache) effective-operand-size and effective-address-size only once. */
_DecodeType effOpSz, effAdrSz;
_iflags instFlags;
ii = inst_lookup(ci, ps);
if (ii == NULL) goto _Undecodable;
isi = &InstSharedInfoTable[ii->sharedIndex];
instFlags = FlagsTable[isi->flagsIndex];
/*
* If both REX and OpSize are available we will have to disable the OpSize, because REX has precedence.
* However, only if REX.W is set !
* We had to wait with this test, since the operand size may be a mandatory prefix,
* and we know it only after prefetching.
*/
if ((ps->prefixExtType == PET_REX) &&
(ps->decodedPrefixes & INST_PRE_OP_SIZE) &&
(!ps->isOpSizeMandatory) &&
(vrex & PREFIX_EX_W)) {
ps->decodedPrefixes &= ~INST_PRE_OP_SIZE;
prefixes_ignore(ps, PFXIDX_OP_SIZE);
}
/*
* In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!),
* so it makes it the right time for decoding-type suitability testing.
* Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow
* 16 bits instructions in 32 bits decoding mode, of course...
* NOTE: Make sure the instruction set for 32 bits has explicitly this specfic flag set.
* NOTE2: Make sure the instruction set for 64 bits has explicitly this specfic flag set.
* If this is the case, drop what we've got and restart all over after DB'ing that byte.
* Though, don't drop an instruction which is also supported in 16 and 32 bits.
*/
/* ! ! ! DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/
/* if (ii && (dt == Decode16Bits) && (instFlags & INST_32BITS) && (~instFlags & INST_16BITS)) ii = NULL; */
/* Drop instructions which are invalid in 64 bits. */
if ((ci->dt == Decode64Bits) && (instFlags & INST_INVALID_64BITS)) goto _Undecodable;
/* If it's only a 64 bits instruction drop it in other decoding modes. */
if ((ci->dt != Decode64Bits) && (instFlags & INST_64BITS_FETCH)) goto _Undecodable;
if (instFlags & INST_MODRM_REQUIRED) {
/* If the ModRM byte is not part of the opcode, skip the last byte code, so code points now to ModRM. */
if (~instFlags & INST_MODRM_INCLUDED) {
ci->code++;
if (--ci->codeLen < 0) goto _Undecodable;
}
modrm = *ci->code;
/* Some instructions enforce that reg=000, so validate that. (Specifically EXTRQ). */
if ((instFlags & INST_FORCE_REG0) && (((modrm >> 3) & 7) != 0)) goto _Undecodable;
/* Some instructions enforce that mod=11, so validate that. */
if ((instFlags & INST_MODRR_REQUIRED) && (modrm < INST_DIVIDED_MODRM)) goto _Undecodable;
}
ci->code++; /* Skip the last byte we just read (either last opcode's byte code or a ModRM). */
/* Cache the effective operand-size and address-size. */
effOpSz = decode_get_effective_op_size(ci->dt, ps->decodedPrefixes, vrex, instFlags);
effAdrSz = decode_get_effective_addr_size(ci->dt, ps->decodedPrefixes);
memset(di, 0, sizeof(_DInst));
di->base = R_NONE;
/*
* Try to extract the next operand only if the latter exists.
* For example, if there is not first operand, no reason to try to extract second operand...
* I decided that a for-break is better for readability in this specific case than goto.
* Note: do-while with a constant 0 makes the compiler warning about it.
*/
for (;;) {
if (isi->d != OT_NONE) {
if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->d, ONT_1, modrm, ps, effOpSz, effAdrSz, &lockable)) goto _Undecodable;
} else break;
if (isi->s != OT_NONE) {
if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->s, ONT_2, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable;
} else break;
/* Use third operand, only if the flags says this InstInfo requires it. */
if (instFlags & INST_USE_OP3) {
if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op3, ONT_3, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable;
} else break;
/* Support for a fourth operand is added for (i.e:) INSERTQ instruction. */
if (instFlags & INST_USE_OP4) {
if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op4, ONT_4, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable;
}
break;
} /* Continue here after all operands were extracted. */
/* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */
if (instFlags & INST_3DNOW_FETCH) {
ii = inst_lookup_3dnow(ci);
if (ii == NULL) goto _Undecodable;
isi = &InstSharedInfoTable[ii->sharedIndex];
instFlags = FlagsTable[isi->flagsIndex];
}
/* Check whether pseudo opcode is needed, only for CMP instructions: */
if (instFlags & INST_PSEUDO_OPCODE) {
if (--ci->codeLen < 0) goto _Undecodable;
cmpType = *ci->code;
ci->code++;
if (instFlags & INST_PRE_VEX) {
/* AVX Comparison type must be between 0 to 32, otherwise Reserved. */
if (cmpType >= INST_VCMP_MAX_RANGE) goto _Undecodable;
} else {
/* SSE Comparison type must be between 0 to 8, otherwise Reserved. */
if (cmpType >= INST_CMP_MAX_RANGE) goto _Undecodable;
}
}
/*
* There's a limit of 15 bytes on instruction length. The only way to violate
* this limit is by putting redundant prefixes before an instruction.
* start points to first prefix if any, otherwise it points to instruction first byte.
*/
if ((ci->code - ps->start) > INST_MAXIMUM_SIZE) goto _Undecodable; /* Drop instruction. */
/*
* If we reached here the instruction was fully decoded, we located the instruction in the DB and extracted operands.
* Use the correct mnemonic according to the DT.
* If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas,
* it means that if there is a mnemonic2, it will be used.
*/
/* Start with prefix LOCK. */
if ((lockable == TRUE) && (instFlags & INST_PRE_LOCK)) {
ps->usedPrefixes |= INST_PRE_LOCK;
di->flags |= FLAG_LOCK;
} else if ((instFlags & INST_PRE_REPNZ) && (ps->decodedPrefixes & INST_PRE_REPNZ)) {
ps->usedPrefixes |= INST_PRE_REPNZ;
di->flags |= FLAG_REPNZ;
} else if ((instFlags & INST_PRE_REP) && (ps->decodedPrefixes & INST_PRE_REP)) {
ps->usedPrefixes |= INST_PRE_REP;
di->flags |= FLAG_REP;
}
/* If it's JeCXZ the ADDR_SIZE prefix affects them. */
if ((instFlags & (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) == (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) {
ps->usedPrefixes |= INST_PRE_ADDR_SIZE;
if (effAdrSz == Decode16Bits) di->opcode = ii->opcodeId;
else if (effAdrSz == Decode32Bits) di->opcode = ((_InstInfoEx*)ii)->opcodeId2;
/* Ignore REX.W in 64bits, JECXZ is promoted. */
else /* Decode64Bits */ di->opcode = ((_InstInfoEx*)ii)->opcodeId3;
}
/* LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */
else if ((instFlags & (INST_PRE_ADDR_SIZE | INST_NATIVE)) == (INST_PRE_ADDR_SIZE | INST_NATIVE)) {
di->opcode = ii->opcodeId;
/* If LOOPxx gets here from 64bits, it must be Decode32Bits because Address Size perfix is set. */
ps->usedPrefixes |= INST_PRE_ADDR_SIZE;
}
/*
* Note:
* If the instruction is prefixed by operand size we will format it in the non-default decoding mode!
* So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode.
* Both ways should end up with a correct and expected formatting of the text.
*/
else if (effOpSz == Decode16Bits) { /* Decode16Bits */
/* Set operand size. */
FLAG_SET_OPSIZE(di, Decode16Bits);
/*
* If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes.
* Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly.
*/
if ((instFlags & INST_USE_EXMNEMONIC) && ((instFlags & (INST_32BITS | INST_64BITS)) == 0)) ps->usedPrefixes |= INST_PRE_OP_SIZE;
di->opcode = ii->opcodeId;
} else if (effOpSz == Decode32Bits) { /* Decode32Bits */
/* Set operand size. */
FLAG_SET_OPSIZE(di, Decode32Bits);
/* Give a chance for special mnemonic instruction in 32 bits decoding. */
if (instFlags & INST_USE_EXMNEMONIC) {
ps->usedPrefixes |= INST_PRE_OP_SIZE;
/* Is it a special instruction which has another mnemonic for mod=11 ? */
if (instFlags & INST_MNEMONIC_MODRM_BASED) {
if (modrm >= INST_DIVIDED_MODRM) di->opcode = ii->opcodeId;
else di->opcode = ((_InstInfoEx*)ii)->opcodeId2;
} else di->opcode = ((_InstInfoEx*)ii)->opcodeId2;
} else di->opcode = ii->opcodeId;
} else { /* Decode64Bits, note that some instructions might be decoded in Decode32Bits above. */
/* Set operand size. */
FLAG_SET_OPSIZE(di, Decode64Bits);
if (instFlags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) {
/*
* We shouldn't be here for MODRM based mnemonics with a MOD=11,
* because they must not use REX (otherwise it will get to the wrong instruction which share same opcode).
* See XRSTOR and XSAVEOPT.
*/
if ((instFlags & INST_MNEMONIC_MODRM_BASED) && (modrm >= INST_DIVIDED_MODRM)) goto _Undecodable;
/* Use third mnemonic, for 64 bits. */
if ((instFlags & INST_USE_EXMNEMONIC2) && (vrex & PREFIX_EX_W)) {
ps->usedPrefixes |= INST_PRE_REX;
di->opcode = ((_InstInfoEx*)ii)->opcodeId3;
} else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; /* Use second mnemonic. */
} else di->opcode = ii->opcodeId;
}
/* If it's a native instruction use OpSize Prefix. */
if ((instFlags & INST_NATIVE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) ps->usedPrefixes |= INST_PRE_OP_SIZE;
/* Check VEX mnemonics: */
if ((instFlags & INST_PRE_VEX) &&
(((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXW_BASED) && (vrex & PREFIX_EX_W)) ||
((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXL_BASED) && (vrex & PREFIX_EX_L)))) {
di->opcode = ((_InstInfoEx*)ii)->opcodeId2;
}
/* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */
if (instFlags & INST_PSEUDO_OPCODE) {
/*
* The opcodeId is the offset to the FIRST pseudo compare mnemonic,
* we will have to fix it so it offsets into the corrected mnemonic.
* Therefore, we use another table to fix the offset.
*/
if (instFlags & INST_PRE_VEX) {
/* Use the AVX pesudo compare mnemonics table. */
di->opcode = ii->opcodeId + VCmpMnemonicOffsets[cmpType];
} else {
/* Use the SSE psuedo compare mnemonics table. */
di->opcode = ii->opcodeId + CmpMnemonicOffsets[cmpType];
}
}
/*
* Store the address size inside the flags.
* This is necessary for the caller to know the size of rSP when using PUSHA for example.
*/
FLAG_SET_ADDRSIZE(di, effAdrSz);
/* Copy DST_WR flag. */
if (instFlags & INST_DST_WR) di->flags |= FLAG_DST_WR;
/* Set the unused prefixes mask. */
di->unusedPrefixesMask = prefixes_set_unused_mask(ps);
/* Copy instruction meta. */
di->meta = isi->meta;
if (di->segment == 0) di->segment = R_NONE;
/* Take into account the O_MEM base register for the mask. */
if (di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base];
/* Copy CPU affected flags. */
di->modifiedFlagsMask = isi->modifiedFlags;
di->testedFlagsMask = isi->testedFlags;
di->undefinedFlagsMask = isi->undefinedFlags;
/* Calculate the size of the instruction we've just decoded. */
di->size = (uint8_t)((ci->code - startCode) & 0xff);
return DECRES_SUCCESS;
_Undecodable: /* If the instruction couldn't be decoded for some reason, drop the first byte. */
memset(di, 0, sizeof(_DInst));
di->base = R_NONE;
di->size = 1;
/* Clean prefixes just in case... */
ps->usedPrefixes = 0;
/* Special case for WAIT instruction: If it's dropped, you have to return a valid instruction! */
if (*startCode == INST_WAIT_INDEX) {
di->opcode = I_WAIT;
META_SET_ISC(di, ISC_INTEGER);
return DECRES_SUCCESS;
}
/* Mark that we didn't manage to decode the instruction well, caller will drop it. */
return DECRES_INPUTERR;
}
/*
* decode_internal
*
* supportOldIntr - Since now we work with new structure instead of the old _DecodedInst, we are still interested in backward compatibility.
* So although, the array is now of type _DInst, we want to read it in jumps of the old array element's size.
* This is in order to save memory allocation for conversion between the new and the old structures.
* It really means we can do the conversion in-place now.
*/
_DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount)
{
_PrefixState ps;
unsigned int prefixSize;
_CodeInfo ci;
_OffsetType codeOffset = _ci->codeOffset;
const uint8_t* code = _ci->code;
int codeLen = _ci->codeLen;
/*
* This is used for printing only, it is the real offset of where the whole instruction begins.
* We need this variable in addition to codeOffset, because prefixes might change the real offset an instruction begins at.
* So we keep track of both.
*/
_OffsetType startInstOffset = 0;
const uint8_t* p;
/* Current working decoded instruction in results. */
unsigned int nextPos = 0;
_DInst *pdi = NULL;
_OffsetType addrMask = (_OffsetType)-1;
_DecodeResult decodeResult;
#ifdef DISTORM_LIGHT
supportOldIntr; /* Unreferenced. */
#endif
if (_ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff;
else if (_ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff;
/* No entries are used yet. */
*usedInstructionsCount = 0;
ci.dt = _ci->dt;
_ci->nextOffset = codeOffset;
/* Decode instructions as long as we have what to decode/enough room in entries. */
while (codeLen > 0) {
/* startInstOffset holds the displayed offset of current instruction. */
startInstOffset = codeOffset;
memset(&ps, 0, (size_t)((char*)&ps.pfxIndexer[0] - (char*)&ps));
memset(ps.pfxIndexer, PFXIDX_NONE, sizeof(int) * PFXIDX_MAX);
ps.start = code;
ps.last = code;
prefixSize = 0;
if (prefixes_is_valid(*code, ci.dt)) {
prefixes_decode(code, codeLen, &ps, ci.dt);
/* Count prefixes, start points to first prefix. */
prefixSize = (unsigned int)(ps.last - ps.start);
/*
* It might be that we will just notice that we ran out of bytes, or only prefixes
* so we will have to drop everything and halt.
* Also take into consideration of flow control instruction filter.
*/
codeLen -= prefixSize;
if ((codeLen == 0) || (prefixSize == INST_MAXIMUM_SIZE)) {
if (~_ci->features & DF_RETURN_FC_ONLY) {
/* Make sure there is enough room. */
if (nextPos + (ps.last - code) > maxResultCount) return DECRES_MEMORYERR;
for (p = code; p < ps.last; p++, startInstOffset++) {
/* Use next entry. */
#ifndef DISTORM_LIGHT
if (supportOldIntr) {
pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst));
}
else
#endif /* DISTORM_LIGHT */
{
pdi = &result[nextPos];
}
nextPos++;
memset(pdi, 0, sizeof(_DInst));
pdi->flags = FLAG_NOT_DECODABLE;
pdi->imm.byte = *p;
pdi->size = 1;
pdi->addr = startInstOffset & addrMask;
}
*usedInstructionsCount = nextPos; /* Include them all. */
}
if (codeLen == 0) break; /* Bye bye, out of bytes. */
}
code += prefixSize;
codeOffset += prefixSize;
/* If we got only prefixes continue to next instruction. */
if (prefixSize == INST_MAXIMUM_SIZE) continue;
}
/*
* Now we decode the instruction and only then we do further prefixes handling.
* This is because the instruction could not be decoded at all, or an instruction requires
* a mandatory prefix, or some of the prefixes were useless, etc...
* Even if there were a mandatory prefix, we already took into account its size as a normal prefix.
* so prefixSize includes that, and the returned size in pdi is simply the size of the real(=without prefixes) instruction.
*/
if (ci.dt == Decode64Bits) {
if (ps.decodedPrefixes & INST_PRE_REX) {
/* REX prefix must precede first byte of instruction. */
if (ps.rexPos != (code - 1)) {
ps.decodedPrefixes &= ~INST_PRE_REX;
ps.prefixExtType = PET_NONE;
prefixes_ignore(&ps, PFXIDX_REX);
}
/*
* We will disable operand size prefix,
* if it exists only after decoding the instruction, since it might be a mandatory prefix.
* This will be done after calling inst_lookup in decode_inst.
*/
}
/* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */
if (ps.decodedPrefixes & INST_PRE_SEGOVRD_MASK32) {
ps.decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK32;
prefixes_ignore(&ps, PFXIDX_SEG);
}
}
/* Make sure there is at least one more entry to use, for the upcoming instruction. */
if (nextPos + 1 > maxResultCount) return DECRES_MEMORYERR;
#ifndef DISTORM_LIGHT
if (supportOldIntr) {
pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst));
}
else
#endif /* DISTORM_LIGHT */
{
pdi = &result[nextPos];
}
nextPos++;
/*
* The reason we copy these two again is because we have to keep track on the input ourselves.
* There might be a case when an instruction is invalid, and then it will be counted as one byte only.
* But that instruction already read a byte or two from the stream and only then returned the error.
* Thus, we end up unsynchronized on the stream.
* This way, we are totally safe, because we keep track after the call to decode_inst, using the returned size.
*/
ci.code = code;
ci.codeLen = codeLen;
/* Nobody uses codeOffset in the decoder itself, so spare it. */
decodeResult = decode_inst(&ci, &ps, pdi);
/* See if we need to filter this instruction. */
if ((_ci->features & DF_RETURN_FC_ONLY) && (META_GET_FC(pdi->meta) == FC_NONE)) decodeResult = DECRES_FILTERED;
/* Set address to the beginning of the instruction. */
pdi->addr = startInstOffset & addrMask;
/* pdi->disp &= addrMask; */
/* Advance to next instruction. */
codeLen -= pdi->size;
codeOffset += pdi->size;
code += pdi->size;
/* Instruction's size should include prefixes. */
pdi->size += (uint8_t)prefixSize;
/* Drop all prefixes and the instruction itself, because the instruction wasn't successfully decoded. */
if ((decodeResult == DECRES_INPUTERR) && (~_ci->features & DF_RETURN_FC_ONLY)) {
nextPos--; /* Undo last result. */
if ((prefixSize + 1) > 0) { /* 1 for the first instruction's byte. */
if ((nextPos + prefixSize + 1) > maxResultCount) return DECRES_MEMORYERR;
for (p = ps.start; p < ps.last + 1; p++, startInstOffset++) {
/* Use next entry. */
#ifndef DISTORM_LIGHT
if (supportOldIntr) {
pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst));
}
else
#endif /* DISTORM_LIGHT */
{
pdi = &result[nextPos];
}
nextPos++;
memset(pdi, 0, sizeof(_DInst));
pdi->flags = FLAG_NOT_DECODABLE;
pdi->imm.byte = *p;
pdi->size = 1;
pdi->addr = startInstOffset & addrMask;
}
}
} else if (decodeResult == DECRES_FILTERED) nextPos--; /* Return it to pool, since it was filtered. */
/* Alright, the caller can read, at least, up to this one. */
*usedInstructionsCount = nextPos;
/* Fix next offset. */
_ci->nextOffset = codeOffset;
/* Check whether we need to stop on any flow control instruction. */
if ((decodeResult == DECRES_SUCCESS) && (_ci->features & DF_STOP_ON_FLOW_CONTROL)) {
if (((_ci->features & DF_STOP_ON_CALL) && (META_GET_FC(pdi->meta) == FC_CALL)) ||
((_ci->features & DF_STOP_ON_RET) && (META_GET_FC(pdi->meta) == FC_RET)) ||
((_ci->features & DF_STOP_ON_SYS) && (META_GET_FC(pdi->meta) == FC_SYS)) ||
((_ci->features & DF_STOP_ON_UNC_BRANCH) && (META_GET_FC(pdi->meta) == FC_UNC_BRANCH)) ||
((_ci->features & DF_STOP_ON_CND_BRANCH) && (META_GET_FC(pdi->meta) == FC_CND_BRANCH)) ||
((_ci->features & DF_STOP_ON_INT) && (META_GET_FC(pdi->meta) == FC_INT)) ||
((_ci->features & DF_STOP_ON_CMOV) && (META_GET_FC(pdi->meta) == FC_CMOV)))
return DECRES_SUCCESS;
}
}
return DECRES_SUCCESS;
}

View File

@ -0,0 +1,33 @@
/*
decoder.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2011 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef DECODER_H
#define DECODER_H
#include "config.h"
typedef unsigned int _iflags;
_DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount);
#endif /* DECODER_H */

View File

@ -0,0 +1,384 @@
/*
distorm.c
diStorm3 C Library Interface
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "distorm.h"
#include "config.h"
#include "decoder.h"
#include "x86defs.h"
#include "textdefs.h"
#include "wstring.h"
#include "mnemonics.h"
/* C DLL EXPORTS */
#ifdef SUPPORT_64BIT_OFFSET
_DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount)
#else
_DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount)
#endif
{
if (usedInstructionsCount == NULL) {
return DECRES_SUCCESS;
}
/* DECRES_SUCCESS still may indicate we may have something in the result, so zero it first thing. */
*usedInstructionsCount = 0;
if ((ci == NULL) ||
(ci->codeLen < 0) ||
((ci->dt != Decode16Bits) && (ci->dt != Decode32Bits) && (ci->dt != Decode64Bits)) ||
(ci->code == NULL) ||
(result == NULL) ||
((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)))
{
return DECRES_INPUTERR;
}
/* Assume length=0 is success. */
if (ci->codeLen == 0) {
return DECRES_SUCCESS;
}
return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount);
}
#ifndef DISTORM_LIGHT
/* Helper function to concat an explicit size when it's unknown from the operands. */
static void distorm_format_size(_WString* str, const _DInst* di, int opNum)
{
/*
* We only have to output the size explicitly if it's not clear from the operands.
* For example:
* mov al, [0x1234] -> The size is 8, we know it from the AL register operand.
* mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam
*
* If given operand number is higher than 2, then output the size anyways.
*/
if (((opNum >= 2) || ((di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))) ||
/* INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. */
((di->opcode == I_INS) || (di->opcode == I_OUTS))) {
switch (di->ops[opNum].size)
{
case 0: break; /* OT_MEM's unknown size. */
case 8: strcat_WSN(str, "BYTE "); break;
case 16: strcat_WSN(str, "WORD "); break;
case 32: strcat_WSN(str, "DWORD "); break;
case 64: strcat_WSN(str, "QWORD "); break;
case 80: strcat_WSN(str, "TBYTE "); break;
case 128: strcat_WSN(str, "DQWORD "); break;
case 256: strcat_WSN(str, "YWORD "); break;
default: /* Big oh uh if it gets here. */ break;
}
}
}
static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t addrMask)
{
int64_t tmpDisp64;
if (di->dispSize) {
chrcat_WS(str, ((int64_t)di->disp < 0) ? MINUS_DISP_CHR : PLUS_DISP_CHR);
if ((int64_t)di->disp < 0) tmpDisp64 = -(int64_t)di->disp;
else tmpDisp64 = di->disp;
tmpDisp64 &= addrMask;
str_code_hqw(str, (uint8_t*)&tmpDisp64);
}
}
#ifdef SUPPORT_64BIT_OFFSET
_DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result)
#else
_DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result)
#endif
{
_WString* str;
unsigned int i, isDefault;
int64_t tmpDisp64;
uint64_t addrMask = (uint64_t)-1;
uint8_t segment;
const _WMnemonic* mnemonic;
/* Set address mask, when default is for 64bits addresses. */
if (ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff;
else if (ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff;
/* Copy other fields. */
result->size = di->size;
result->offset = di->addr & addrMask;
if (di->flags == FLAG_NOT_DECODABLE) {
str = &result->mnemonic;
strclear_WS(&result->operands);
strcpy_WSN(str, "DB ");
str_code_hb(str, di->imm.byte);
strclear_WS(&result->instructionHex);
str_hex_b(&result->instructionHex, di->imm.byte);
return; /* Skip to next instruction. */
}
str = &result->instructionHex;
strclear_WS(str);
for (i = 0; i < di->size; i++)
str_hex_b(str, ci->code[(unsigned int)(di->addr - ci->codeOffset + i)]);
str = &result->mnemonic;
switch (FLAG_GET_PREFIX(di->flags))
{
case FLAG_LOCK:
strcpy_WSN(str, "LOCK ");
break;
case FLAG_REP:
strcpy_WSN(str, "REP ");
break;
case FLAG_REPNZ:
strcpy_WSN(str, "REPNZ ");
break;
default:
/* Init mnemonic string, cause next touch is concatenation. */
strclear_WS(str);
break;
}
mnemonic = (const _WMnemonic*)&_MNEMONICS[di->opcode];
memcpy((int8_t*)&str->p[str->length], mnemonic->p, mnemonic->length + 1);
str->length += mnemonic->length;
/* Format operands: */
str = &result->operands;
strclear_WS(str);
/* Special treatment for String instructions. */
if ((META_GET_ISC(di->meta) == ISC_INTEGER) &&
((di->opcode == I_MOVS) ||
(di->opcode == I_CMPS) ||
(di->opcode == I_STOS) ||
(di->opcode == I_LODS) ||
(di->opcode == I_SCAS)))
{
/*
* No operands are needed if the address size is the default one,
* and no segment is overridden, so add the suffix letter,
* to indicate size of operation and continue to next instruction.
*/
if ((FLAG_GET_ADDRSIZE(di->flags) == ci->dt) && (SEGMENT_IS_DEFAULT(di->segment))) {
str = &result->mnemonic;
switch (di->ops[0].size)
{
case 8: chrcat_WS(str, 'B'); break;
case 16: chrcat_WS(str, 'W'); break;
case 32: chrcat_WS(str, 'D'); break;
case 64: chrcat_WS(str, 'Q'); break;
}
return;
}
}
for (i = 0; ((i < OPERANDS_NO) && (di->ops[i].type != O_NONE)); i++) {
if (i > 0) strcat_WSN(str, ", ");
switch (di->ops[i].type)
{
case O_REG:
strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]);
break;
case O_IMM:
/* If the instruction is 'push', show explicit size (except byte imm). */
if (di->opcode == I_PUSH && di->ops[i].size != 8) distorm_format_size(str, di, i);
/* Special fix for negative sign extended immediates. */
if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8)) {
if (di->imm.sbyte < 0) {
chrcat_WS(str, MINUS_DISP_CHR);
str_code_hb(str, -di->imm.sbyte);
break;
}
}
if (di->ops[i].size == 64) str_code_hqw(str, (uint8_t*)&di->imm.qword);
else str_code_hdw(str, di->imm.dword);
break;
case O_IMM1:
str_code_hdw(str, di->imm.ex.i1);
break;
case O_IMM2:
str_code_hdw(str, di->imm.ex.i2);
break;
case O_DISP:
distorm_format_size(str, di, i);
chrcat_WS(str, OPEN_CHR);
if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) {
strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]);
chrcat_WS(str, SEG_OFF_CHR);
}
tmpDisp64 = di->disp & addrMask;
str_code_hqw(str, (uint8_t*)&tmpDisp64);
chrcat_WS(str, CLOSE_CHR);
break;
case O_SMEM:
distorm_format_size(str, di, i);
chrcat_WS(str, OPEN_CHR);
/*
* This is where we need to take special care for String instructions.
* If we got here, it means we need to explicitly show their operands.
* The problem with CMPS and MOVS is that they have two(!) memory operands.
* So we have to complete it ourselves, since the structure supplies only the segment that can be overridden.
* And make the rest of the String operations explicit.
*/
segment = SEGMENT_GET(di->segment);
isDefault = SEGMENT_IS_DEFAULT(di->segment);
switch (di->opcode)
{
case I_MOVS:
isDefault = FALSE;
if (i == 0) segment = R_ES;
break;
case I_CMPS:
isDefault = FALSE;
if (i == 1) segment = R_ES;
break;
case I_INS:
case I_LODS:
case I_STOS:
case I_SCAS: isDefault = FALSE; break;
}
if (!isDefault && (segment != R_NONE)) {
strcat_WS(str, (const _WString*)&_REGISTERS[segment]);
chrcat_WS(str, SEG_OFF_CHR);
}
strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]);
distorm_format_signed_disp(str, di, addrMask);
chrcat_WS(str, CLOSE_CHR);
break;
case O_MEM:
distorm_format_size(str, di, i);
chrcat_WS(str, OPEN_CHR);
if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) {
strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]);
chrcat_WS(str, SEG_OFF_CHR);
}
if (di->base != R_NONE) {
strcat_WS(str, (const _WString*)&_REGISTERS[di->base]);
chrcat_WS(str, PLUS_DISP_CHR);
}
strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]);
if (di->scale != 0) {
chrcat_WS(str, '*');
if (di->scale == 2) chrcat_WS(str, '2');
else if (di->scale == 4) chrcat_WS(str, '4');
else /* if (di->scale == 8) */ chrcat_WS(str, '8');
}
distorm_format_signed_disp(str, di, addrMask);
chrcat_WS(str, CLOSE_CHR);
break;
case O_PC:
#ifdef SUPPORT_64BIT_OFFSET
str_off64(str, (di->imm.sqword + di->addr + di->size) & addrMask);
#else
str_code_hdw(str, ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask);
#endif
break;
case O_PTR:
str_code_hdw(str, di->imm.ptr.seg);
chrcat_WS(str, SEG_OFF_CHR);
str_code_hdw(str, di->imm.ptr.off);
break;
}
}
if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN");
else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN");
}
#ifdef SUPPORT_64BIT_OFFSET
_DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount)
#else
_DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount)
#endif
{
_DecodeResult res;
_DInst di;
_CodeInfo ci;
unsigned int instsCount = 0, i;
*usedInstructionsCount = 0;
/* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */
if (codeLen < 0) {
return DECRES_INPUTERR;
}
if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) {
return DECRES_INPUTERR;
}
if (code == NULL || result == NULL) {
return DECRES_INPUTERR;
}
/* Assume length=0 is success. */
if (codeLen == 0) {
return DECRES_SUCCESS;
}
/*
* We have to format the result into text. But the interal decoder works with the new structure of _DInst.
* Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's.
* Then we will copy each result to a temporary structure, and use it to reformat that specific result.
*
* This is all done to save memory allocation and to work on the same result array in-place!!!
* It's a bit ugly, I have to admit, but worth it.
*/
ci.codeOffset = codeOffset;
ci.code = code;
ci.codeLen = codeLen;
ci.dt = dt;
ci.features = DF_NONE;
if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16;
else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32;
res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount);
for (i = 0; i < instsCount; i++) {
if ((*usedInstructionsCount + i) >= maxInstructions) return DECRES_MEMORYERR;
/* Copy the current decomposed result to a temp structure, so we can override the result with text. */
memcpy(&di, (char*)result + (i * sizeof(_DecodedInst)), sizeof(_DInst));
#ifdef SUPPORT_64BIT_OFFSET
distorm_format64(&ci, &di, &result[i]);
#else
distorm_format32(&ci, &di, &result[i]);
#endif
}
*usedInstructionsCount = instsCount;
return res;
}
#endif /* DISTORM_LIGHT */
_DLLEXPORT_ unsigned int distorm_version()
{
return __DISTORMV__;
}

View File

@ -0,0 +1,473 @@
/* diStorm3 3.2 */
/*
distorm.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef DISTORM_H
#define DISTORM_H
/*
* 64 bit offsets support:
* If the diStorm library you use was compiled with 64 bits offsets,
* make sure you compile your own code with the following macro set:
* SUPPORT_64BIT_OFFSET
* Otherwise comment it out, or you will get a linker error of an unresolved symbol...
* Turned on by default!
*/
#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC))
/* Define this macro for outer projects by default. */
#define SUPPORT_64BIT_OFFSET
#endif
/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */
#ifdef __TINYC__
#undef SUPPORT_64BIT_OFFSET
#endif
/* If your compiler doesn't support stdint.h, define your own 64 bits type. */
#ifdef SUPPORT_64BIT_OFFSET
#ifdef _MSC_VER
#define OFFSET_INTEGER unsigned __int64
#else
#include <stdint.h>
#define OFFSET_INTEGER uint64_t
#endif
#else
/* 32 bit offsets are used. */
#define OFFSET_INTEGER unsigned long
#endif
#ifdef _MSC_VER
/* Since MSVC isn't shipped with stdint.h, we will have our own: */
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
#endif
/* Support C++ compilers */
#ifdef __cplusplus
extern "C" {
#endif
/* *** Helper Macros *** */
/* Get the ISC of the instruction, used with the definitions below. */
#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f)
#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3))
/* Get the flow control flags of the instruction, see 'features for decompose' below. */
#define META_GET_FC(meta) ((meta) & 0x7)
/* Get the target address of a branching instruction. O_PC operand type. */
#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size)))
/* Get the target address of a RIP-relative memory indirection. */
#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size)))
/*
* Operand Size or Adderss size are stored inside the flags:
* 0 - 16 bits
* 1 - 32 bits
* 2 - 64 bits
* 3 - reserved
*
* If you call these set-macros more than once, you will have to clean the bits before doing so.
*/
#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8))
#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10))
#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3)
#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3)
/* To get the LOCK/REPNZ/REP prefixes. */
#define FLAG_GET_PREFIX(flags) ((flags) & 7)
/*
* Macros to extract segment registers from 'segment':
*/
#define SEGMENT_DEFAULT 0x80
#define SEGMENT_SET(di, seg) ((di->segment) |= seg)
#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f))
#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT)
/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */
typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType;
typedef OFFSET_INTEGER _OffsetType;
typedef struct {
_OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */
const uint8_t* code;
int codeLen; /* Using signed integer makes it easier to detect an underflow. */
_DecodeType dt;
unsigned int features;
} _CodeInfo;
typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType;
typedef union {
/* Used by O_IMM: */
int8_t sbyte;
uint8_t byte;
int16_t sword;
uint16_t word;
int32_t sdword;
uint32_t dword;
int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */
uint64_t qword;
/* Used by O_PC: (Use GET_TARGET_ADDR).*/
_OffsetType addr; /* It's a relative offset as for now. */
/* Used by O_PTR: */
struct {
uint16_t seg;
/* Can be 16 or 32 bits, size is in ops[n].size. */
uint32_t off;
} ptr;
/* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */
struct {
uint32_t i1;
uint32_t i2;
} ex;
} _Value;
typedef struct {
/* Type of operand:
O_NONE: operand is to be ignored.
O_REG: index holds global register index.
O_IMM: instruction.imm.
O_IMM1: instruction.imm.ex.i1.
O_IMM2: instruction.imm.ex.i2.
O_DISP: memory dereference with displacement only, instruction.disp.
O_SMEM: simple memory dereference with optional displacement (a single register memory dereference).
O_MEM: complex memory dereference (optional fields: s/i/b/disp).
O_PC: the relative address of a branch instruction (instruction.imm.addr).
O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off).
*/
uint8_t type; /* _OperandType */
/* Index of:
O_REG: holds global register index
O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index.
O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index.
*/
uint8_t index;
/* Size of:
O_REG: register
O_IMM: instruction.imm
O_IMM1: instruction.imm.ex.i1
O_IMM2: instruction.imm.ex.i2
O_DISP: instruction.disp
O_SMEM: size of indirection.
O_MEM: size of indirection.
O_PC: size of the relative offset
O_PTR: size of instruction.imm.ptr.off (16 or 32)
*/
uint16_t size;
} _Operand;
#define OPCODE_ID_NONE 0
/* Instruction could not be disassembled. */
#define FLAG_NOT_DECODABLE ((uint16_t)-1)
/* The instruction locks memory access. */
#define FLAG_LOCK (1 << 0)
/* The instruction is prefixed with a REPNZ. */
#define FLAG_REPNZ (1 << 1)
/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */
#define FLAG_REP (1 << 2)
/* Indicates there is a hint taken for Jcc instructions only. */
#define FLAG_HINT_TAKEN (1 << 3)
/* Indicates there is a hint non-taken for Jcc instructions only. */
#define FLAG_HINT_NOT_TAKEN (1 << 4)
/* The Imm value is signed extended. */
#define FLAG_IMM_SIGNED (1 << 5)
/* The destination operand is writable. */
#define FLAG_DST_WR (1 << 6)
/* The instruction uses RIP-relative indirection. */
#define FLAG_RIP_RELATIVE (1 << 7)
/* No register was defined. */
#define R_NONE ((uint8_t)-1)
#define REGS64_BASE 0
#define REGS32_BASE 16
#define REGS16_BASE 32
#define REGS8_BASE 48
#define REGS8_REX_BASE 64
#define SREGS_BASE 68
#define FPUREGS_BASE 75
#define MMXREGS_BASE 83
#define SSEREGS_BASE 91
#define AVXREGS_BASE 107
#define CREGS_BASE 123
#define DREGS_BASE 132
#define OPERANDS_NO (4)
typedef struct {
/* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */
_Value imm;
/* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */
uint64_t disp;
/* Virtual address of first byte of instruction. */
_OffsetType addr;
/* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */
uint16_t flags;
/* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */
uint16_t unusedPrefixesMask;
/* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */
uint16_t usedRegistersMask;
/* ID of opcode in the global opcode table. Use for mnemonic look up. */
uint16_t opcode;
/* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */
_Operand ops[OPERANDS_NO];
/* Size of the whole instruction. */
uint8_t size;
/* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */
uint8_t segment;
/* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */
uint8_t base, scale;
uint8_t dispSize;
/* Meta defines the instruction set class, and the flow control flags. Use META macros. */
uint8_t meta;
/* The CPU flags that the instruction operates upon. */
uint8_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask;
} _DInst;
#ifndef DISTORM_LIGHT
/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */
#define MAX_TEXT_SIZE (48)
typedef struct {
unsigned int length;
unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */
} _WString;
/*
* Old decoded instruction structure in text format.
* Used only for backward compatibility with diStorm64.
* This structure holds all information the disassembler generates per instruction.
*/
typedef struct {
_WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */
_WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */
_WString instructionHex; /* Hex dump - little endian, including prefixes. */
unsigned int size; /* Size of decoded instruction. */
_OffsetType offset; /* Start offset of the decoded instruction. */
} _DecodedInst;
#endif /* DISTORM_LIGHT */
/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */
#define RM_AX 1 /* AL, AH, AX, EAX, RAX */
#define RM_CX 2 /* CL, CH, CX, ECX, RCX */
#define RM_DX 4 /* DL, DH, DX, EDX, RDX */
#define RM_BX 8 /* BL, BH, BX, EBX, RBX */
#define RM_SP 0x10 /* SPL, SP, ESP, RSP */
#define RM_BP 0x20 /* BPL, BP, EBP, RBP */
#define RM_SI 0x40 /* SIL, SI, ESI, RSI */
#define RM_DI 0x80 /* DIL, DI, EDI, RDI */
#define RM_FPU 0x100 /* ST(0) - ST(7) */
#define RM_MMX 0x200 /* MM0 - MM7 */
#define RM_SSE 0x400 /* XMM0 - XMM15 */
#define RM_AVX 0x800 /* YMM0 - YMM15 */
#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */
#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */
/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE.
* Segments should be checked using the segment macros.
* For now R8 - R15 are not supported and non general purpose registers map into same RM.
*/
/* CPU Flags that instructions modify, test or undefine. */
#define D_ZF 1 /* Zero */
#define D_SF 2 /* Sign */
#define D_CF 4 /* Carry */
#define D_OF 8 /* Overflow */
#define D_PF 0x10 /* Parity */
#define D_AF 0x20 /* Auxilary */
#define D_DF 0x40 /* Direction */
#define D_IF 0x80 /* Interrupt */
/*
* Instructions Set classes:
* if you want a better understanding of the available classes, look at disOps project, file: x86sets.py.
*/
/* Indicates the instruction belongs to the General Integer set. */
#define ISC_INTEGER 1
/* Indicates the instruction belongs to the 387 FPU set. */
#define ISC_FPU 2
/* Indicates the instruction belongs to the P6 set. */
#define ISC_P6 3
/* Indicates the instruction belongs to the MMX set. */
#define ISC_MMX 4
/* Indicates the instruction belongs to the SSE set. */
#define ISC_SSE 5
/* Indicates the instruction belongs to the SSE2 set. */
#define ISC_SSE2 6
/* Indicates the instruction belongs to the SSE3 set. */
#define ISC_SSE3 7
/* Indicates the instruction belongs to the SSSE3 set. */
#define ISC_SSSE3 8
/* Indicates the instruction belongs to the SSE4.1 set. */
#define ISC_SSE4_1 9
/* Indicates the instruction belongs to the SSE4.2 set. */
#define ISC_SSE4_2 10
/* Indicates the instruction belongs to the AMD's SSE4.A set. */
#define ISC_SSE4_A 11
/* Indicates the instruction belongs to the 3DNow! set. */
#define ISC_3DNOW 12
/* Indicates the instruction belongs to the 3DNow! Extensions set. */
#define ISC_3DNOWEXT 13
/* Indicates the instruction belongs to the VMX (Intel) set. */
#define ISC_VMX 14
/* Indicates the instruction belongs to the SVM (AMD) set. */
#define ISC_SVM 15
/* Indicates the instruction belongs to the AVX (Intel) set. */
#define ISC_AVX 16
/* Indicates the instruction belongs to the FMA (Intel) set. */
#define ISC_FMA 17
/* Indicates the instruction belongs to the AES/AVX (Intel) set. */
#define ISC_AES 18
/* Indicates the instruction belongs to the CLMUL (Intel) set. */
#define ISC_CLMUL 19
/* Features for decompose: */
#define DF_NONE 0
/* The decoder will limit addresses to a maximum of 16 bits. */
#define DF_MAXIMUM_ADDR16 1
/* The decoder will limit addresses to a maximum of 32 bits. */
#define DF_MAXIMUM_ADDR32 2
/* The decoder will return only flow control instructions (and filter the others internally). */
#define DF_RETURN_FC_ONLY 4
/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */
#define DF_STOP_ON_CALL 8
/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */
#define DF_STOP_ON_RET 0x10
/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */
#define DF_STOP_ON_SYS 0x20
/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */
#define DF_STOP_ON_UNC_BRANCH 0x40
/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */
#define DF_STOP_ON_CND_BRANCH 0x80
/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */
#define DF_STOP_ON_INT 0x100
/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */
#define DF_STOP_ON_CMOV 0x200
/* The decoder will stop and return to the caller when any flow control instruction was decoded. */
#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV)
/* Indicates the instruction is not a flow-control instruction. */
#define FC_NONE 0
/* Indicates the instruction is one of: CALL, CALL FAR. */
#define FC_CALL 1
/* Indicates the instruction is one of: RET, IRET, RETF. */
#define FC_RET 2
/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */
#define FC_SYS 3
/* Indicates the instruction is one of: JMP, JMP FAR. */
#define FC_UNC_BRANCH 4
/*
* Indicates the instruction is one of:
* JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ.
*/
#define FC_CND_BRANCH 5
/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */
#define FC_INT 6
/* Indicates the instruction is one of: CMOVxx. */
#define FC_CMOV 7
/* Return code of the decoding function. */
typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult;
/* Define the following interface functions only for outer projects. */
#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC))
/* distorm_decode
* Input:
* offset - Origin of the given code (virtual address that is), NOT an offset in code.
* code - Pointer to the code buffer to be disassembled.
* length - Amount of bytes that should be decoded from the code buffer.
* dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits).
* result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions.
* maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound.
* usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array.
* Output: usedInstructionsCount will hold the number of entries used in the result array
* and the result array itself will be filled with the disassembled instructions.
* Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...),
* DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount!
* Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the
* array you passed, this function will try to use as much entries as possible!
* Notes: 1)The minimal size of maxInstructions is 15.
* 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block!
*/
#ifdef SUPPORT_64BIT_OFFSET
_DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
#define distorm_decompose distorm_decompose64
#ifndef DISTORM_LIGHT
/* If distorm-light is defined, we won't export these text-formatting functionality. */
_DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result);
#define distorm_decode distorm_decode64
#define distorm_format distorm_format64
#endif /*DISTORM_LIGHT*/
#else /*SUPPORT_64BIT_OFFSET*/
_DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
#define distorm_decompose distorm_decompose32
#ifndef DISTORM_LIGHT
/* If distorm-light is defined, we won't export these text-formatting functionality. */
_DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result);
#define distorm_decode distorm_decode32
#define distorm_format distorm_format32
#endif /*DISTORM_LIGHT*/
#endif
/*
* distorm_version
* Input:
* none
*
* Output: unsigned int - version of compiled library.
*/
unsigned int distorm_version();
#endif /* DISTORM_STATIC */
#ifdef __cplusplus
} /* End Of Extern */
#endif
#endif /* DISTORM_H */

View File

@ -0,0 +1,590 @@
/*
instructions.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "instructions.h"
#include "insts.h"
#include "prefix.h"
#include "x86defs.h"
#include "mnemonics.h"
/* Helper macros to extract the type or index from an inst-node value. */
#define INST_NODE_INDEX(n) ((n) & 0x1fff)
#define INST_NODE_TYPE(n) ((n) >> 13)
/* Helper macro to read the actual flags that are associated with an inst-info. */
#define INST_INFO_FLAGS(ii) (FlagsTable[InstSharedInfoTable[(ii)->sharedIndex].flagsIndex])
/*
I use the trie data structure as I found it most fitting to a disassembler mechanism.
When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information.
It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte.
For a simple explanation, check this out:
http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/
Futher reading: http://en.wikipedia.org/wiki/Trie
The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler.
The second and third gates if used are being allocated dynamically by the instructions-insertion functionality.
How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates).
->
|-------| 0,
|0| -------------------------------> |-------|
|1|RET | 1, |0|AND |
|2| -----> |-------| |1|XOR |
|3|INT3 | |0|PUSH | |2|OR | 0,3,
|-------| |1|POP | |3| --------->|-------|
|2|PUSHF| |-------| |0|ROR |
|3|POPF | |1|ROL |
|-------| |2|SHR |
|3|SHL |
|-------|
Of course, this is NOT how Intel instructions set looks!!!
but I just wanted to give a small demonstration.
Now the instructions you get from such a trie DB goes like this:
0, 0 - AND
0, 1 - XOR
0, 2 - OR
0, 3, 0, ROR
0, 3, 1, ROL
0, 3, 2, SHR
0, 3, 3, SHL
1 - RET
2, 0 - PUSH
2, 1 - POP
2, 2 - PUSHF
2, 3 - POPF
3 - INT3
I guess it's clear by now.
So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index.
But if you read 1, you know that you go to an instruction (in this case, a RET).
That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list
so you should keep on reading byte).
In Intel, you could go through 4 gates at top, because there're instructions which are built from 2 bytes and another smaller list
for the REG part, or newest SSE4 instructions which use 4 bytes for opcode.
Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much alot of memory
for non-used defined instructions, but I think that it still rocks.
*/
/*
* A helper function to look up the correct inst-info structure.
* It does one fetch from the index-table, and then another to get the inst-info.
* Note that it takes care about basic inst-info or inst-info-ex.
* The caller should worry about boundary checks and whether it accesses a last-level table.
*/
static _InstInfo* inst_get_info(_InstNode in, int index)
{
int instIndex = 0;
in = InstructionsTree[INST_NODE_INDEX(in) + index];
if (in == INT_NOTEXISTS) return NULL;
instIndex = INST_NODE_INDEX(in);
return INST_NODE_TYPE(in) == INT_INFO ? &InstInfos[instIndex] : (_InstInfo*)&InstInfosEx[instIndex];
}
/*
* This function is responsible to return the instruction information of the first found in code.
* It returns the _InstInfo of the found instruction, otherwise NULL.
* code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself.
* This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid.
* Get the instruction info, using a Trie data structure.
*
* Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes.
* This is a bit tricky now,
* if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction.
* If an instruction doesn't exist, we will make it as a prefix and re-locateinst.
* A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen,
* simply because there are no collisions between string instruction and SSE instructions (they are escaped).
* As for S/SSE2/3, check for F2 and 66 as well.
* In 64 bits, we have to make sure that we will skip the REX prefix, if it exists.
* There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used,
* but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account.
* For example (64 bits decoding mode):
* 66 98 CBW
* 48 98 CDQE
* 66 48 98: db 0x66; CDQE
* Shows that operand size is dropped.
* Now, it's a mandatory prefix and NOT an operand size one.
* 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0
* Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter.
* REX.W is dropped because it's not requried, but the decode function disabled the operand size even so.
*/
static _InstInfo* inst_lookup_prefixed(_InstNode in, _PrefixState* ps)
{
int checkOpSize = FALSE;
int index = 0;
_InstInfo* ii = NULL;
/* Check prefixes of current decoded instruction (None, 0x66, 0xf3, 0xf2). */
switch (ps->decodedPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS))
{
case 0:
/* Non-prefixed, index = 0. */
index = 0;
break;
case INST_PRE_OP_SIZE:
/* 0x66, index = 1. */
index = 1;
/* Mark that we used it as a mandatory prefix. */
ps->isOpSizeMandatory = TRUE;
ps->decodedPrefixes &= ~INST_PRE_OP_SIZE;
break;
case INST_PRE_REP:
/* 0xf3, index = 2. */
index = 2;
ps->decodedPrefixes &= ~INST_PRE_REP;
break;
case INST_PRE_REPNZ:
/* 0xf2, index = 3. */
index = 3;
ps->decodedPrefixes &= ~INST_PRE_REPNZ;
break;
default:
/*
* Now we got a problem, since there are a few mandatory prefixes at once.
* There is only one case when it's ok, when the operand size prefix is for real (not mandatory).
* Otherwise we will have to return NULL, since the instruction is illegal.
* Therefore we will start with REPNZ and REP prefixes,
* try to get the instruction and only then check for the operand size prefix.
*/
/* If both REPNZ and REP are together, it's illegal for sure. */
if ((ps->decodedPrefixes & INST_PRE_REPS) == INST_PRE_REPS) return NULL;
/* Now we know it's either REPNZ+OPSIZE or REP+OPSIZE, so examine the instruction. */
if (ps->decodedPrefixes & INST_PRE_REPNZ) {
index = 3;
ps->decodedPrefixes &= ~INST_PRE_REPNZ;
} else if (ps->decodedPrefixes & INST_PRE_REP) {
index = 2;
ps->decodedPrefixes &= ~INST_PRE_REP;
}
/* Mark to verify the operand-size prefix of the fetched instruction below. */
checkOpSize = TRUE;
break;
}
/* Fetch the inst-info from the index. */
ii = inst_get_info(in, index);
if (checkOpSize) {
/* If the instruction doesn't support operand size prefix, then it's illegal. */
if ((ii == NULL) || (~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE)) return NULL;
}
/* If there was a prefix, but the instruction wasn't found. Try to fall back to use the normal instruction. */
if (ii == NULL) ii = inst_get_info(in, 0);
return ii;
}
/* A helper function to look up special VEX instructions.
* See if it's a MOD based instruction and fix index if required.
* Only after a first lookup (that was done by caller), we can tell if we need to fix the index.
* Because these are coupled instructions
* (which means that the base instruction hints about the other instruction).
* Note that caller should check if it's a MOD dependent instruction before getting in here.
*/
static _InstInfo* inst_vex_mod_lookup(_CodeInfo* ci, _InstNode in, _InstInfo* ii, unsigned int index)
{
/* Advance to read the MOD from ModRM byte. */
ci->code += 1;
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
if (*ci->code < INST_DIVIDED_MODRM) {
/* MOD is not 11, therefore change the index to 8 - 12 range in the prefixed table. */
index += 4;
/* Make a second lookup for this special instruction. */
return inst_get_info(in, index);
}
/* Return the original one, in case we didn't find a stuited instruction. */
return ii;
}
static _InstInfo* inst_vex_lookup(_CodeInfo* ci, _PrefixState* ps)
{
_InstNode in = 0;
unsigned int pp = 0, start = 0;
unsigned int index = 4; /* VEX instructions start at index 4 in the Prefixed table. */
uint8_t vex = *ps->vexPos, vex2 = 0, v = 0;
int instType = 0, instIndex = 0;
/* The VEX instruction will #ud if any of 66, f0, f2, f3, REX prefixes precede. */
_iflags illegal = (INST_PRE_OP_SIZE | INST_PRE_LOCK | INST_PRE_REP | INST_PRE_REPNZ | INST_PRE_REX);
if ((ps->decodedPrefixes & illegal) != 0) return NULL;
/* Read the some fields from the VEX prefix we need to extract the instruction. */
if (ps->prefixExtType == PET_VEX2BYTES) {
ps->vexV = v = (~vex >> 3) & 0xf;
pp = vex & 3;
/* Implied leading 0x0f byte by default for 2 bytes VEX prefix. */
start = 1;
} else { /* PET_VEX3BYTES */
start = vex & 0x1f;
vex2 = *(ps->vexPos + 1);
ps->vexV = v = (~vex2 >> 3) & 0xf;
pp = vex2 & 3;
}
/* start can be either 1 (0x0f), 2 (0x0f, 0x038) or 3 (0x0f, 0x3a), otherwise it's illegal. */
switch (start)
{
case 1: in = Table_0F; break;
case 2: in = Table_0F_38; break;
case 3: in = Table_0F_3A; break;
default: return NULL;
}
/* pp is actually the implied mandatory prefix, apply it to the index. */
index += pp; /* (None, 0x66, 0xf3, 0xf2) */
/* Read a byte from the stream. */
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
in = InstructionsTree[INST_NODE_INDEX(in) + *ci->code];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
instIndex = INST_NODE_INDEX(in);
/*
* If we started with 0f38 or 0f3a so it's a prefixed table,
* therefore it's surely a VEXed instruction (because of a high index).
* However, starting with 0f, could also lead immediately to a prefixed table for some bytes.
* it might return NULL, if the index is invalid.
*/
if (instType == INT_LIST_PREFIXED) {
_InstInfo* ii = inst_get_info(in, index);
/* See if the instruction is dependent on MOD. */
if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) {
ii = inst_vex_mod_lookup(ci, in, ii, index);
}
return ii;
}
/*
* If we reached here, obviously we started with 0f. VEXed instructions must be nodes of a prefixed table.
* But since we found an instruction (or divided one), just return NULL.
* They cannot lead to a VEXed instruction.
*/
if ((instType == INT_INFO) || (instType == INT_INFOEX) || (instType == INT_LIST_DIVIDED)) return NULL;
/* Now we are left with handling either GROUP or FULL tables, therefore we will read another byte from the stream. */
ci->code += 1;
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
if (instType == INT_LIST_GROUP) {
in = InstructionsTree[instIndex + ((*ci->code >> 3) & 7)];
/* Continue below to check prefixed table. */
} else if (instType == INT_LIST_FULL) {
in = InstructionsTree[instIndex + *ci->code];
/* Continue below to check prefixed table. */
}
/* Now that we got to the last table in the trie, check for a prefixed table. */
if (INST_NODE_TYPE(in) == INT_LIST_PREFIXED) {
_InstInfo* ii = inst_get_info(in, index);
/* See if the instruction is dependent on MOD. */
if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) {
ii = inst_vex_mod_lookup(ci, in, ii, index);
}
return ii;
}
/* No VEXed instruction was found. */
return NULL;
}
_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps)
{
unsigned int tmpIndex0 = 0, tmpIndex1 = 0, tmpIndex2 = 0, rex = ps->vrex;
int instType = 0;
_InstNode in = 0;
_InstInfo* ii = NULL;
int isWaitIncluded = FALSE;
/* See whether we have to handle a VEX prefixed instruction. */
if (ps->decodedPrefixes & INST_PRE_VEX) {
ii = inst_vex_lookup(ci, ps);
if (ii != NULL) {
/* Make sure that VEX.L exists when forced. */
if ((((_InstInfoEx*)ii)->flagsEx & INST_FORCE_VEXL) && (~ps->vrex & PREFIX_EX_L)) return NULL;
/* If the instruction doesn't use VEX.vvvv it must be zero. */
if ((((_InstInfoEx*)ii)->flagsEx & INST_VEX_V_UNUSED) && ps->vexV) return NULL;
}
return ii;
}
/* Read first byte. */
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
tmpIndex0 = *ci->code;
/* Check for special 0x9b, WAIT instruction, which can be part of some instructions(x87). */
if (tmpIndex0 == INST_WAIT_INDEX) {
/* Only OCST_1dBYTES get a chance to include this byte as part of the opcode. */
isWaitIncluded = TRUE;
/* Ignore all prefixes, since they are useless and operate on the WAIT instruction itself. */
prefixes_ignore_all(ps);
/* Move to next code byte as a new whole instruction. */
ci->code += 1;
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL; /* Faster to return NULL, it will be detected as WAIT later anyway. */
/* Since we got a WAIT prefix, we re-read the first byte. */
tmpIndex0 = *ci->code;
}
/* Walk first byte in InstructionsTree root. */
in = InstructionsTree[tmpIndex0];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
/* Single byte instruction (OCST_1BYTE). */
if ((instType < INT_INFOS) && (!isWaitIncluded)) {
/* Some single byte instructions need extra treatment. */
switch (tmpIndex0)
{
case INST_ARPL_INDEX:
/*
* ARPL/MOVSXD share the same opcode, and both have different operands and mnemonics, of course.
* Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD.
* And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant,
* I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim
*/
if (ci->dt == Decode64Bits) {
return &II_MOVSXD;
} /* else ARPL will be returned because its defined in the DB already. */
break;
case INST_NOP_INDEX: /* Nopnopnop */
/* Check for Pause, since it's prefixed with 0xf3, which is not a real mandatory prefix. */
if (ps->decodedPrefixes & INST_PRE_REP) {
/* Flag this prefix as used. */
ps->usedPrefixes |= INST_PRE_REP;
return &II_PAUSE;
}
/*
* Treat NOP/XCHG specially.
* If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG.
* Else if we're in 64bits examine REX, if exists, and decide which instruction should go to output.
* 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid).
* 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 although it should be a 32 bits operation).
* Note that if the REX.B is used, then the register is not RAX anymore but R8, which means it's not a NOP.
*/
if (rex & PREFIX_EX_W) ps->usedPrefixes |= INST_PRE_REX;
if ((ci->dt != Decode64Bits) || (~rex & PREFIX_EX_B)) return &II_NOP;
break;
case INST_LEA_INDEX:
/* Ignore segment override prefixes for LEA instruction. */
ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK;
/* Update unused mask for ignoring segment prefix. */
prefixes_ignore(ps, PFXIDX_SEG);
break;
}
/* Return the 1 byte instruction we found. */
return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)];
}
/* Read second byte, still doens't mean all of its bits are used (I.E: ModRM). */
ci->code += 1;
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
tmpIndex1 = *ci->code;
/* Try single byte instruction + reg bits (OCST_13BYTES). */
if ((instType == INT_LIST_GROUP) && (!isWaitIncluded)) return inst_get_info(in, (tmpIndex1 >> 3) & 7);
/* Try single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */
if (instType == INT_LIST_DIVIDED) {
/* OCST_1dBYTES is relatively simple to OCST_2dBYTES, since it's really divided at 0xc0. */
if (tmpIndex1 < INST_DIVIDED_MODRM) {
/* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */
tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */
} else { /* Normal 2 bytes instruction. */
/*
* Divided instructions can't be in the range of 0x8-0xc0.
* That's because 0-8 are used for 3 bits group.
* And 0xc0-0xff are used for not-divided instruction.
* So the inbetween range is omitted, thus saving some more place in the tables.
*/
tmpIndex1 -= INST_DIVIDED_MODRM - 8;
}
in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
if (instType < INT_INFOS) {
/* If the instruction doesn't support the wait (marked as opsize) as part of the opcode, it's illegal. */
ii = instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)];
if ((~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE) && (isWaitIncluded)) return NULL;
return ii;
}
/*
* If we got here the instruction can support the wait prefix, so see if it was part of the stream.
* Examine prefixed table, specially used for 0x9b, since it's optional.
* No Wait: index = 0.
* Wait Exists, index = 1.
*/
return inst_get_info(in, isWaitIncluded);
}
/* Don't allow to continue if WAIT is part of the opcode, because there are no instructions that include it. */
if (isWaitIncluded) return NULL;
/* Try 2 bytes long instruction (doesn't include ModRM byte). */
if (instType == INT_LIST_FULL) {
in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
/* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */
if ((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) return &II_3DNOW;
/* 2 bytes instruction (OCST_2BYTES). */
if (instType < INT_INFOS)
return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)];
/*
* 2 bytes + mandatory perfix.
* Mandatory prefixes can be anywhere in the prefixes.
* There cannot be more than one mandatory prefix, unless it's a normal operand size prefix.
*/
if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps);
}
/* Read third byte, still doens't mean all of its bits are used (I.E: ModRM). */
ci->code += 1;
ci->codeLen -= 1;
if (ci->codeLen < 0) return NULL;
tmpIndex2 = *ci->code;
/* Try 2 bytes + reg instruction (OCST_23BYTES). */
if (instType == INT_LIST_GROUP) {
in = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
if (instType < INT_INFOS)
return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)];
/* It has to be a prefixed table then. */
return inst_lookup_prefixed(in, ps);
}
/* Try 2 bytes + divided range (OCST_2dBYTES). */
if (instType == INT_LIST_DIVIDED) {
_InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)];
/*
* Do NOT check for NULL here, since we do a bit of a guess work,
* hence we don't override 'in', cause we might still need it.
*/
instType = INST_NODE_TYPE(in2);
if (instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)];
else if (instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)];
/*
* OCST_2dBYTES is complex, because there are a few instructions which are not divided in some special cases.
* If the instruction wasn't divided (but still it must be a 2.3 because we are in divided category)
* or it was an official 2.3 (because its index was less than 0xc0) -
* Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff.
*/
/* If we found an instruction only by its REG bits, AND it is not divided, then return it. */
if ((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii;
/* Otherwise, if the range is above 0xc0, try the special divided range (range 0x8-0xc0 is omitted). */
if (tmpIndex2 >= INST_DIVIDED_MODRM) return inst_get_info(in, tmpIndex2 - INST_DIVIDED_MODRM + 8);
/* It might be that we got here without touching ii in the above if statements, then it becomes an invalid instruction prolly. */
return ii;
}
/* Try 3 full bytes (OCST_3BYTES - no ModRM byte). */
if (instType == INT_LIST_FULL) {
/* OCST_3BYTES. */
in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex2];
if (in == INT_NOTEXISTS) return NULL;
instType = INST_NODE_TYPE(in);
if (instType < INT_INFOS)
return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)];
if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps);
}
/* Kahtchinggg, damn. */
return NULL;
}
/*
* 3DNow! instruction handling:
* This is used when we encounter a 3DNow! instruction.
* We can't really locate a 3DNow! instruction before we see two escaped bytes,
* 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection.
* When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte
* which tells us which 3DNow instruction we really tracked down...
* So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some
* generic instruction info for 3DNow! instructions.
* In the inst_lookup itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f.
* we will return this special generic II for the specific operands we are interested in (MM, MM64).
* Then after extracting the operand, we'll call a completion routine for locating the instruction
* which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes.
*
* The id of this opcode should not be used, the following function should change it anyway.
*/
_InstInfo* inst_lookup_3dnow(_CodeInfo* ci)
{
/* Start off from the two escape bytes gates... which is 3DNow! table.*/
_InstNode in = Table_0F_0F;
int index;
/* Make sure we can read a byte off the stream. */
if (ci->codeLen < 1) return NULL;
index = *ci->code;
ci->codeLen -= 1;
ci->code += 1;
return inst_get_info(in, index);
}

View File

@ -0,0 +1,454 @@
/*
instructions.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef INSTRUCTIONS_H
#define INSTRUCTIONS_H
#include "config.h"
#include "prefix.h"
/*
* Operand type possibilities:
* Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType -
* actually, it depends on the decoding mode, unless there's an operand/address size prefix.
* For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX.
*/
typedef enum OpType {
/* No operand is set */
OT_NONE = 0,
/* Read a byte(8 bits) immediate */
OT_IMM8,
/* Force a read of a word(16 bits) immediate, used by ret only */
OT_IMM16,
/* Read a word/dword immediate */
OT_IMM_FULL,
/* Read a double-word(32 bits) immediate */
OT_IMM32,
/* Read a signed extended byte(8 bits) immediate */
OT_SEIMM8,
/*
* Special immediates for instructions which have more than one immediate,
* which is an exception from standard instruction format.
* As to version v1.0: ENTER, INSERTQ, EXTRQ are the only problematic ones.
*/
/* 16 bits immediate using the first imm-slot */
OT_IMM16_1,
/* 8 bits immediate using the first imm-slot */
OT_IMM8_1,
/* 8 bits immediate using the second imm-slot */
OT_IMM8_2,
/* Use a 8bit register */
OT_REG8,
/* Use a 16bit register */
OT_REG16,
/* Use a 16/32/64bit register */
OT_REG_FULL,
/* Use a 32bit register */
OT_REG32,
/*
* If used with REX the reg operand size becomes 64 bits, otherwise 32 bits.
* VMX instructions are promoted automatically without a REX prefix.
*/
OT_REG32_64,
/* Used only by MOV CR/DR(n). Promoted with REX onlly. */
OT_FREG32_64_RM,
/* Use or read (indirection) a 8bit register or immediate byte */
OT_RM8,
/* Some instructions force 16 bits (mov sreg, rm16) */
OT_RM16,
/* Use or read a 16/32/64bit register or immediate word/dword/qword */
OT_RM_FULL,
/*
* 32 or 64 bits (with REX) operand size indirection memory operand.
* Some instructions are promoted automatically without a REX prefix.
*/
OT_RM32_64,
/* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */
OT_RM16_32,
/* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */
OT_FPUM16,
/* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */
OT_FPUM32,
/* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */
OT_FPUM64,
/* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */
OT_FPUM80,
/*
* Special operand type for SSE4 where the ModR/M might
* be a 32 bits register or 8 bits memory indirection operand.
*/
OT_R32_M8,
/*
* Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register.
* In 16 bits decoding mode R32 becomes R16, operand size cannot affect this.
*/
OT_R32_M16,
/*
* Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or
* a 8 bits memory indirection operand.
*/
OT_R32_64_M8,
/*
* Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or
* a 16 bits memory indirection operand.
*/
OT_R32_64_M16,
/*
* Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW.
* It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection.
*/
OT_RFULL_M16,
/* Use a control register */
OT_CREG,
/* Use a debug register */
OT_DREG,
/* Use a segment register */
OT_SREG,
/*
* SEG is encoded in the flags of the opcode itself!
* This is used for specific "push SS" where SS is a segment where
* each "push SS" has an absolutely different opcode byte.
* We need this to detect whether an operand size prefix is used.
*/
OT_SEG,
/* Use AL */
OT_ACC8,
/* Use AX (FSTSW) */
OT_ACC16,
/* Use AX/EAX/RAX */
OT_ACC_FULL,
/* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */
OT_ACC_FULL_NOT64,
/*
* Read one word (seg), and a word/dword/qword (depends on operand size) from memory.
* JMP FAR [EBX] means EBX point to 16:32 ptr.
*/
OT_MEM16_FULL,
/* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */
OT_PTR16_FULL,
/* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */
OT_MEM16_3264,
/* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */
OT_RELCB,
/* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */
OT_RELC_FULL,
/* Use general memory indirection, with varying sizes: */
OT_MEM,
/* Used when a memory indirection is required, but if the mod field is 11, this operand will be ignored. */
OT_MEM_OPT,
OT_MEM32,
/* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */
OT_MEM32_64,
OT_MEM64,
OT_MEM128,
/* Used for cmpxchg8b/16b. */
OT_MEM64_128,
/* Read an immediate as an absolute address, size is known by instruction, used by MOV (memory offset) only */
OT_MOFFS8,
OT_MOFFS_FULL,
/* Use an immediate of 1, as for SHR R/M, 1 */
OT_CONST1,
/* Use CL, as for SHR R/M, CL */
OT_REGCL,
/*
* Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG,
* REG is extracted from the value of opcode
* Use a 8bit register
*/
OT_IB_RB,
/* Use a 16/32/64bit register */
OT_IB_R_FULL,
/* Use [(r)SI] as INDIRECTION, for repeatable instructions */
OT_REGI_ESI,
/* Use [(r)DI] as INDIRECTION, for repeatable instructions */
OT_REGI_EDI,
/* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */
OT_REGI_EBXAL,
/* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */
OT_REGI_EAX,
/* Use DX, as for OUTS DX, BYTE [SI] */
OT_REGDX,
/* Use ECX in INVLPGA instruction */
OT_REGECX,
/* FPU registers: */
OT_FPU_SI, /* ST(i) */
OT_FPU_SSI, /* ST(0), ST(i) */
OT_FPU_SIS, /* ST(i), ST(0) */
/* MMX registers: */
OT_MM,
/* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */
OT_MM_RM,
/* ModR/M points to 32 bits MMX variable */
OT_MM32,
/* ModR/M points to 32 bits MMX variable */
OT_MM64,
/* SSE registers: */
OT_XMM,
/* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */
OT_XMM_RM,
/* ModR/M points to 16 bits SSE variable */
OT_XMM16,
/* ModR/M points to 32 bits SSE variable */
OT_XMM32,
/* ModR/M points to 64 bits SSE variable */
OT_XMM64,
/* ModR/M points to 128 bits SSE variable */
OT_XMM128,
/* Implied XMM0 register as operand, used in SSE4. */
OT_REGXMM0,
/* AVX operands: */
/* ModR/M for 32 bits. */
OT_RM32,
/* Reg32/Reg64 (prefix width) or Mem8. */
OT_REG32_64_M8,
/* Reg32/Reg64 (prefix width) or Mem16. */
OT_REG32_64_M16,
/* Reg32/Reg 64 depends on prefix width only. */
OT_WREG32_64,
/* RM32/RM64 depends on prefix width only. */
OT_WRM32_64,
/* XMM or Mem32/Mem64 depends on perfix width only. */
OT_WXMM32_64,
/* XMM is encoded in VEX.VVVV. */
OT_VXMM,
/* XMM is encoded in the high nibble of an immediate byte. */
OT_XMM_IMM,
/* YMM/XMM is dependent on VEX.L. */
OT_YXMM,
/* YMM/XMM (depends on prefix length) is encoded in the high nibble of an immediate byte. */
OT_YXMM_IMM,
/* YMM is encoded in reg. */
OT_YMM,
/* YMM or Mem256. */
OT_YMM256,
/* YMM is encoded in VEX.VVVV. */
OT_VYMM,
/* YMM/XMM is dependent on VEX.L, and encoded in VEX.VVVV. */
OT_VYXMM,
/* YMM/XMM or Mem64/Mem256 is dependent on VEX.L. */
OT_YXMM64_256,
/* YMM/XMM or Mem128/Mem256 is dependent on VEX.L. */
OT_YXMM128_256,
/* XMM or Mem64/Mem256 is dependent on VEX.L. */
OT_LXMM64_128,
/* Mem128/Mem256 is dependent on VEX.L. */
OT_LMEM128_256
} _OpType;
/* Flags for instruction: */
/* Empty flags indicator: */
#define INST_FLAGS_NONE (0)
/* The instruction we are going to decode requires ModR/M encoding. */
#define INST_MODRM_REQUIRED (1)
/* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */
#define INST_NOT_DIVIDED (1 << 1)
/*
* Used explicitly in repeatable instructions,
* which needs a suffix letter in their mnemonic to specify operation-size (depend on operands).
*/
#define INST_16BITS (1 << 2)
/* If the opcode is supported by 80286 and upper models (16/32 bits). */
#define INST_32BITS (1 << 3)
/*
* Prefix flags (6 types: lock/rep, seg override, addr-size, oper-size, REX, VEX)
* There are several specific instructions that can follow LOCK prefix,
* note that they must be using a memory operand form, otherwise they generate an exception.
*/
#define INST_PRE_LOCK (1 << 4)
/* REPNZ prefix for string instructions only - means an instruction can follow it. */
#define INST_PRE_REPNZ (1 << 5)
/* REP prefix for string instructions only - means an instruction can follow it. */
#define INST_PRE_REP (1 << 6)
/* CS override prefix. */
#define INST_PRE_CS (1 << 7)
/* SS override prefix. */
#define INST_PRE_SS (1 << 8)
/* DS override prefix. */
#define INST_PRE_DS (1 << 9)
/* ES override prefix. */
#define INST_PRE_ES (1 << 10)
/* FS override prefix. Funky Segment :) */
#define INST_PRE_FS (1 << 11)
/* GS override prefix. Groovy Segment, of course not, duh ! */
#define INST_PRE_GS (1 << 12)
/* Switch operand size from 32 to 16 and vice versa. */
#define INST_PRE_OP_SIZE (1 << 13)
/* Switch address size from 32 to 16 and vice versa. */
#define INST_PRE_ADDR_SIZE (1 << 14)
/* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */
#define INST_NATIVE (1 << 15)
/* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */
#define INST_USE_EXMNEMONIC (1 << 16)
/* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */
#define INST_USE_OP3 (1 << 17)
/* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */
#define INST_USE_OP4 (1 << 18)
/* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */
#define INST_MNEMONIC_MODRM_BASED (1 << 19)
/* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */
#define INST_MODRR_REQUIRED (1 << 20)
/* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */
#define INST_3DNOW_FETCH (1 << 21)
/* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */
#define INST_PSEUDO_OPCODE (1 << 22)
/* Invalid instruction at 64 bits decoding mode. */
#define INST_INVALID_64BITS (1 << 23)
/* Specific instruction can be promoted to 64 bits (without REX, it is promoted automatically). */
#define INST_64BITS (1 << 24)
/* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */
#define INST_PRE_REX (1 << 25)
/* Third mnemonic is set. */
#define INST_USE_EXMNEMONIC2 (1 << 26)
/* Instruction is only valid in 64 bits decoding mode. */
#define INST_64BITS_FETCH (1 << 27)
/* Forces that the ModRM-REG/Opcode field will be 0. (For EXTRQ). */
#define INST_FORCE_REG0 (1 << 28)
/* Indicates that instruction is encoded with a VEX prefix. */
#define INST_PRE_VEX (1 << 29)
/* Indicates that the instruction is encoded with a ModRM byte (REG field specifically). */
#define INST_MODRM_INCLUDED (1 << 30)
/* Indicates that the first (/destination) operand of the instruction is writable. */
#define INST_DST_WR (1 << 31)
#define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP)
#define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP)
#define INST_PRE_SEGOVRD_MASK32 (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES)
#define INST_PRE_SEGOVRD_MASK64 (INST_PRE_FS | INST_PRE_GS)
#define INST_PRE_SEGOVRD_MASK (INST_PRE_SEGOVRD_MASK32 | INST_PRE_SEGOVRD_MASK64)
/* Extended flags for VEX: */
/* Indicates that the instruction might have VEX.L encoded. */
#define INST_VEX_L (1)
/* Indicates that the instruction might have VEX.W encoded. */
#define INST_VEX_W (1 << 1)
/* Indicates that the mnemonic of the instruction is based on the VEX.W bit. */
#define INST_MNEMONIC_VEXW_BASED (1 << 2)
/* Indicates that the mnemonic of the instruction is based on the VEX.L bit. */
#define INST_MNEMONIC_VEXL_BASED (1 << 3)
/* Forces the instruction to be encoded with VEX.L, otherwise it's undefined. */
#define INST_FORCE_VEXL (1 << 4)
/*
* Indicates that the instruction is based on the MOD field of the ModRM byte.
* (MOD==11: got the right instruction, else skip +4 in prefixed table for the correct instruction).
*/
#define INST_MODRR_BASED (1 << 5)
/* Indicates that the instruction doesn't use the VVVV field of the VEX prefix, if it does then it's undecodable. */
#define INST_VEX_V_UNUSED (1 << 6)
/*
* Indicates which operand is being decoded.
* Destination (1st), Source (2nd), op3 (3rd), op4 (4th).
* Used to set the operands' fields in the _DInst structure!
*/
typedef enum {ONT_NONE = -1, ONT_1 = 0, ONT_2 = 1, ONT_3 = 2, ONT_4 = 3} _OperandNumberType;
/*
* In order to save more space for storing the DB statically,
* I came up with another level of shared info.
* Because I saw that most of the information that instructions use repeats itself.
*
* Info about the instruction, source/dest types, meta and flags.
* _InstInfo points to a table of _InstSharedInfo.
*/
typedef struct {
uint8_t flagsIndex; /* An index into FlagsTables */
uint8_t s, d; /* OpType. */
uint8_t meta; /* Hi 5 bits = Instruction set class | Lo 3 bits = flow control flags. */
/* The following are CPU flag masks that the instruction changes. */
uint8_t modifiedFlags;
uint8_t testedFlags;
uint8_t undefinedFlags;
} _InstSharedInfo;
/*
* This structure is used for the instructions DB and NOT for the disassembled result code!
* This is the BASE structure, there are extentions to this structure below.
*/
typedef struct {
uint16_t sharedIndex; /* An index into the SharedInfoTable. */
uint16_t opcodeId; /* The opcodeId is really a byte-offset into the mnemonics table. */
} _InstInfo;
/*
* There are merely few instructions which need a second mnemonic for 32 bits.
* Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third.
* In all decoding modes the first mnemonic is the default.
* A flag will indicate it uses another mnemonic.
*
* There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits,
* therefore, I decided to make the extended structure contain all extra info in the same structure.
* There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth).
* A flag will indicate it uses a third/fourth operand.
*/
typedef struct {
/* Base structure (doesn't get accessed directly from code). */
_InstInfo BASE;
/* Extended starts here. */
uint8_t flagsEx; /* 8 bits are enough, in the future we might make it a bigger integer. */
uint8_t op3, op4; /* OpType. */
uint16_t opcodeId2, opcodeId3;
} _InstInfoEx;
/* Trie data structure node type: */
typedef enum {
INT_NOTEXISTS = 0, /* Not exists. */
INT_INFO = 1, /* It's an instruction info. */
INT_INFOEX,
INT_LIST_GROUP,
INT_LIST_FULL,
INT_LIST_DIVIDED,
INT_LIST_PREFIXED
} _InstNodeType;
/* Used to check instType < INT_INFOS, means we got an inst-info. Cause it has to be only one of them. */
#define INT_INFOS (INT_LIST_GROUP)
/* Instruction node is treated as { int index:13; int type:3; } */
typedef uint16_t _InstNode;
_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps);
_InstInfo* inst_lookup_3dnow(_CodeInfo* ci);
#endif /* INSTRUCTIONS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
insts.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef INSTS_H
#define INSTS_H
#include "instructions.h"
/* Flags Table */
extern _iflags FlagsTable[];
/* Root Trie DB */
extern _InstSharedInfo InstSharedInfoTable[];
extern _InstInfo InstInfos[];
extern _InstInfoEx InstInfosEx[];
extern _InstNode InstructionsTree[];
/* 3DNow! Trie DB */
extern _InstNode Table_0F_0F;
/* AVX related: */
extern _InstNode Table_0F, Table_0F_38, Table_0F_3A;
/*
* The inst_lookup will return on of these two instructions according to the specified decoding mode.
* ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63.
*/
extern _InstInfo II_ARPL;
extern _InstInfo II_MOVSXD;
/*
* The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction.
* If 0x90 is prefixed by a useable REX it will become XCHG, otherwise it will become a NOP.
* Also note that if it's prefixed by 0xf3, it becomes a Pause.
*/
extern _InstInfo II_NOP;
extern _InstInfo II_PAUSE;
/*
* Used for letting the extract operand know the type of operands without knowing the
* instruction itself yet, because of the way those instructions work.
* See function instructions.c!inst_lookup_3dnow.
*/
extern _InstInfo II_3DNOW;
/* Helper tables for pesudo compare mnemonics. */
extern uint16_t CmpMnemonicOffsets[8]; /* SSE */
extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */
#endif /* INSTS_H */

View File

@ -0,0 +1,295 @@
/*
mnemonics.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "mnemonics.h"
#ifndef DISTORM_LIGHT
const unsigned char _MNEMONICS[] =
"\x09" "UNDEFINED\0" "\x03" "ADD\0" "\x04" "PUSH\0" "\x03" "POP\0" "\x02" "OR\0" \
"\x03" "ADC\0" "\x03" "SBB\0" "\x03" "AND\0" "\x03" "DAA\0" "\x03" "SUB\0" \
"\x03" "DAS\0" "\x03" "XOR\0" "\x03" "AAA\0" "\x03" "CMP\0" "\x03" "AAS\0" \
"\x03" "INC\0" "\x03" "DEC\0" "\x05" "PUSHA\0" "\x04" "POPA\0" "\x05" "BOUND\0" \
"\x04" "ARPL\0" "\x04" "IMUL\0" "\x03" "INS\0" "\x04" "OUTS\0" "\x02" "JO\0" \
"\x03" "JNO\0" "\x02" "JB\0" "\x03" "JAE\0" "\x02" "JZ\0" "\x03" "JNZ\0" "\x03" "JBE\0" \
"\x02" "JA\0" "\x02" "JS\0" "\x03" "JNS\0" "\x02" "JP\0" "\x03" "JNP\0" "\x02" "JL\0" \
"\x03" "JGE\0" "\x03" "JLE\0" "\x02" "JG\0" "\x04" "TEST\0" "\x04" "XCHG\0" \
"\x03" "MOV\0" "\x03" "LEA\0" "\x03" "CBW\0" "\x04" "CWDE\0" "\x04" "CDQE\0" \
"\x03" "CWD\0" "\x03" "CDQ\0" "\x03" "CQO\0" "\x08" "CALL FAR\0" "\x05" "PUSHF\0" \
"\x04" "POPF\0" "\x04" "SAHF\0" "\x04" "LAHF\0" "\x04" "MOVS\0" "\x04" "CMPS\0" \
"\x04" "STOS\0" "\x04" "LODS\0" "\x04" "SCAS\0" "\x03" "RET\0" "\x03" "LES\0" \
"\x03" "LDS\0" "\x05" "ENTER\0" "\x05" "LEAVE\0" "\x04" "RETF\0" "\x05" "INT 3\0" \
"\x03" "INT\0" "\x04" "INTO\0" "\x04" "IRET\0" "\x03" "AAM\0" "\x03" "AAD\0" \
"\x04" "SALC\0" "\x04" "XLAT\0" "\x06" "LOOPNZ\0" "\x05" "LOOPZ\0" "\x04" "LOOP\0" \
"\x04" "JCXZ\0" "\x05" "JECXZ\0" "\x05" "JRCXZ\0" "\x02" "IN\0" "\x03" "OUT\0" \
"\x04" "CALL\0" "\x03" "JMP\0" "\x07" "JMP FAR\0" "\x04" "INT1\0" "\x03" "HLT\0" \
"\x03" "CMC\0" "\x03" "CLC\0" "\x03" "STC\0" "\x03" "CLI\0" "\x03" "STI\0" \
"\x03" "CLD\0" "\x03" "STD\0" "\x03" "LAR\0" "\x03" "LSL\0" "\x07" "SYSCALL\0" \
"\x04" "CLTS\0" "\x06" "SYSRET\0" "\x04" "INVD\0" "\x06" "WBINVD\0" "\x03" "UD2\0" \
"\x05" "FEMMS\0" "\x03" "NOP\0" "\x05" "WRMSR\0" "\x05" "RDTSC\0" "\x05" "RDMSR\0" \
"\x05" "RDPMC\0" "\x08" "SYSENTER\0" "\x07" "SYSEXIT\0" "\x06" "GETSEC\0" "\x05" "CMOVO\0" \
"\x06" "CMOVNO\0" "\x05" "CMOVB\0" "\x06" "CMOVAE\0" "\x05" "CMOVZ\0" "\x06" "CMOVNZ\0" \
"\x06" "CMOVBE\0" "\x05" "CMOVA\0" "\x05" "CMOVS\0" "\x06" "CMOVNS\0" "\x05" "CMOVP\0" \
"\x06" "CMOVNP\0" "\x05" "CMOVL\0" "\x06" "CMOVGE\0" "\x06" "CMOVLE\0" "\x05" "CMOVG\0" \
"\x04" "SETO\0" "\x05" "SETNO\0" "\x04" "SETB\0" "\x05" "SETAE\0" "\x04" "SETZ\0" \
"\x05" "SETNZ\0" "\x05" "SETBE\0" "\x04" "SETA\0" "\x04" "SETS\0" "\x05" "SETNS\0" \
"\x04" "SETP\0" "\x05" "SETNP\0" "\x04" "SETL\0" "\x05" "SETGE\0" "\x05" "SETLE\0" \
"\x04" "SETG\0" "\x05" "CPUID\0" "\x02" "BT\0" "\x04" "SHLD\0" "\x03" "RSM\0" \
"\x03" "BTS\0" "\x04" "SHRD\0" "\x07" "CMPXCHG\0" "\x03" "LSS\0" "\x03" "BTR\0" \
"\x03" "LFS\0" "\x03" "LGS\0" "\x05" "MOVZX\0" "\x03" "BTC\0" "\x05" "MOVSX\0" \
"\x04" "XADD\0" "\x06" "MOVNTI\0" "\x05" "BSWAP\0" "\x03" "ROL\0" "\x03" "ROR\0" \
"\x03" "RCL\0" "\x03" "RCR\0" "\x03" "SHL\0" "\x03" "SHR\0" "\x03" "SAL\0" \
"\x03" "SAR\0" "\x04" "FADD\0" "\x04" "FMUL\0" "\x04" "FCOM\0" "\x05" "FCOMP\0" \
"\x04" "FSUB\0" "\x05" "FSUBR\0" "\x04" "FDIV\0" "\x05" "FDIVR\0" "\x03" "FLD\0" \
"\x03" "FST\0" "\x04" "FSTP\0" "\x06" "FLDENV\0" "\x05" "FLDCW\0" "\x04" "FXCH\0" \
"\x04" "FNOP\0" "\x04" "FCHS\0" "\x04" "FABS\0" "\x04" "FTST\0" "\x04" "FXAM\0" \
"\x04" "FLD1\0" "\x06" "FLDL2T\0" "\x06" "FLDL2E\0" "\x05" "FLDPI\0" "\x06" "FLDLG2\0" \
"\x06" "FLDLN2\0" "\x04" "FLDZ\0" "\x05" "F2XM1\0" "\x05" "FYL2X\0" "\x05" "FPTAN\0" \
"\x06" "FPATAN\0" "\x07" "FXTRACT\0" "\x06" "FPREM1\0" "\x07" "FDECSTP\0" "\x07" "FINCSTP\0" \
"\x05" "FPREM\0" "\x07" "FYL2XP1\0" "\x05" "FSQRT\0" "\x07" "FSINCOS\0" "\x07" "FRNDINT\0" \
"\x06" "FSCALE\0" "\x04" "FSIN\0" "\x04" "FCOS\0" "\x05" "FIADD\0" "\x05" "FIMUL\0" \
"\x05" "FICOM\0" "\x06" "FICOMP\0" "\x05" "FISUB\0" "\x06" "FISUBR\0" "\x05" "FIDIV\0" \
"\x06" "FIDIVR\0" "\x06" "FCMOVB\0" "\x06" "FCMOVE\0" "\x07" "FCMOVBE\0" "\x06" "FCMOVU\0" \
"\x07" "FUCOMPP\0" "\x04" "FILD\0" "\x06" "FISTTP\0" "\x04" "FIST\0" "\x05" "FISTP\0" \
"\x07" "FCMOVNB\0" "\x07" "FCMOVNE\0" "\x08" "FCMOVNBE\0" "\x07" "FCMOVNU\0" \
"\x04" "FENI\0" "\x06" "FEDISI\0" "\x06" "FSETPM\0" "\x06" "FUCOMI\0" "\x05" "FCOMI\0" \
"\x06" "FRSTOR\0" "\x05" "FFREE\0" "\x05" "FUCOM\0" "\x06" "FUCOMP\0" "\x05" "FADDP\0" \
"\x05" "FMULP\0" "\x06" "FCOMPP\0" "\x06" "FSUBRP\0" "\x05" "FSUBP\0" "\x06" "FDIVRP\0" \
"\x05" "FDIVP\0" "\x04" "FBLD\0" "\x05" "FBSTP\0" "\x07" "FUCOMIP\0" "\x06" "FCOMIP\0" \
"\x03" "NOT\0" "\x03" "NEG\0" "\x03" "MUL\0" "\x03" "DIV\0" "\x04" "IDIV\0" \
"\x04" "SLDT\0" "\x03" "STR\0" "\x04" "LLDT\0" "\x03" "LTR\0" "\x04" "VERR\0" \
"\x04" "VERW\0" "\x04" "SGDT\0" "\x04" "SIDT\0" "\x04" "LGDT\0" "\x04" "LIDT\0" \
"\x04" "SMSW\0" "\x04" "LMSW\0" "\x06" "INVLPG\0" "\x06" "VMCALL\0" "\x08" "VMLAUNCH\0" \
"\x08" "VMRESUME\0" "\x06" "VMXOFF\0" "\x07" "MONITOR\0" "\x05" "MWAIT\0" "\x06" "XGETBV\0" \
"\x06" "XSETBV\0" "\x06" "VMFUNC\0" "\x05" "VMRUN\0" "\x07" "VMMCALL\0" "\x06" "VMLOAD\0" \
"\x06" "VMSAVE\0" "\x04" "STGI\0" "\x04" "CLGI\0" "\x06" "SKINIT\0" "\x07" "INVLPGA\0" \
"\x06" "SWAPGS\0" "\x06" "RDTSCP\0" "\x08" "PREFETCH\0" "\x09" "PREFETCHW\0" \
"\x05" "PI2FW\0" "\x05" "PI2FD\0" "\x05" "PF2IW\0" "\x05" "PF2ID\0" "\x06" "PFNACC\0" \
"\x07" "PFPNACC\0" "\x07" "PFCMPGE\0" "\x05" "PFMIN\0" "\x05" "PFRCP\0" "\x07" "PFRSQRT\0" \
"\x05" "PFSUB\0" "\x05" "PFADD\0" "\x07" "PFCMPGT\0" "\x05" "PFMAX\0" "\x08" "PFRCPIT1\0" \
"\x08" "PFRSQIT1\0" "\x06" "PFSUBR\0" "\x05" "PFACC\0" "\x07" "PFCMPEQ\0" "\x05" "PFMUL\0" \
"\x08" "PFRCPIT2\0" "\x07" "PMULHRW\0" "\x06" "PSWAPD\0" "\x07" "PAVGUSB\0" \
"\x06" "MOVUPS\0" "\x06" "MOVUPD\0" "\x05" "MOVSS\0" "\x05" "MOVSD\0" "\x07" "VMOVUPS\0" \
"\x07" "VMOVUPD\0" "\x06" "VMOVSS\0" "\x06" "VMOVSD\0" "\x07" "MOVHLPS\0" "\x06" "MOVLPS\0" \
"\x06" "MOVLPD\0" "\x08" "MOVSLDUP\0" "\x07" "MOVDDUP\0" "\x08" "VMOVHLPS\0" \
"\x07" "VMOVLPS\0" "\x07" "VMOVLPD\0" "\x09" "VMOVSLDUP\0" "\x08" "VMOVDDUP\0" \
"\x08" "UNPCKLPS\0" "\x08" "UNPCKLPD\0" "\x09" "VUNPCKLPS\0" "\x09" "VUNPCKLPD\0" \
"\x08" "UNPCKHPS\0" "\x08" "UNPCKHPD\0" "\x09" "VUNPCKHPS\0" "\x09" "VUNPCKHPD\0" \
"\x07" "MOVLHPS\0" "\x06" "MOVHPS\0" "\x06" "MOVHPD\0" "\x08" "MOVSHDUP\0" \
"\x08" "VMOVLHPS\0" "\x07" "VMOVHPS\0" "\x07" "VMOVHPD\0" "\x09" "VMOVSHDUP\0" \
"\x0b" "PREFETCHNTA\0" "\x0a" "PREFETCHT0\0" "\x0a" "PREFETCHT1\0" "\x0a" "PREFETCHT2\0" \
"\x06" "MOVAPS\0" "\x06" "MOVAPD\0" "\x07" "VMOVAPS\0" "\x07" "VMOVAPD\0" "\x08" "CVTPI2PS\0" \
"\x08" "CVTPI2PD\0" "\x08" "CVTSI2SS\0" "\x08" "CVTSI2SD\0" "\x09" "VCVTSI2SS\0" \
"\x09" "VCVTSI2SD\0" "\x07" "MOVNTPS\0" "\x07" "MOVNTPD\0" "\x07" "MOVNTSS\0" \
"\x07" "MOVNTSD\0" "\x08" "VMOVNTPS\0" "\x08" "VMOVNTPD\0" "\x09" "CVTTPS2PI\0" \
"\x09" "CVTTPD2PI\0" "\x09" "CVTTSS2SI\0" "\x09" "CVTTSD2SI\0" "\x0a" "VCVTTSS2SI\0" \
"\x0a" "VCVTTSD2SI\0" "\x08" "CVTPS2PI\0" "\x08" "CVTPD2PI\0" "\x08" "CVTSS2SI\0" \
"\x08" "CVTSD2SI\0" "\x09" "VCVTSS2SI\0" "\x09" "VCVTSD2SI\0" "\x07" "UCOMISS\0" \
"\x07" "UCOMISD\0" "\x08" "VUCOMISS\0" "\x08" "VUCOMISD\0" "\x06" "COMISS\0" \
"\x06" "COMISD\0" "\x07" "VCOMISS\0" "\x07" "VCOMISD\0" "\x08" "MOVMSKPS\0" \
"\x08" "MOVMSKPD\0" "\x09" "VMOVMSKPS\0" "\x09" "VMOVMSKPD\0" "\x06" "SQRTPS\0" \
"\x06" "SQRTPD\0" "\x06" "SQRTSS\0" "\x06" "SQRTSD\0" "\x07" "VSQRTPS\0" "\x07" "VSQRTPD\0" \
"\x07" "VSQRTSS\0" "\x07" "VSQRTSD\0" "\x07" "RSQRTPS\0" "\x07" "RSQRTSS\0" \
"\x08" "VRSQRTPS\0" "\x08" "VRSQRTSS\0" "\x05" "RCPPS\0" "\x05" "RCPSS\0" "\x06" "VRCPPS\0" \
"\x06" "VRCPSS\0" "\x05" "ANDPS\0" "\x05" "ANDPD\0" "\x06" "VANDPS\0" "\x06" "VANDPD\0" \
"\x06" "ANDNPS\0" "\x06" "ANDNPD\0" "\x07" "VANDNPS\0" "\x07" "VANDNPD\0" "\x04" "ORPS\0" \
"\x04" "ORPD\0" "\x05" "VORPS\0" "\x05" "VORPD\0" "\x05" "XORPS\0" "\x05" "XORPD\0" \
"\x06" "VXORPS\0" "\x06" "VXORPD\0" "\x05" "ADDPS\0" "\x05" "ADDPD\0" "\x05" "ADDSS\0" \
"\x05" "ADDSD\0" "\x06" "VADDPS\0" "\x06" "VADDPD\0" "\x06" "VADDSS\0" "\x06" "VADDSD\0" \
"\x05" "MULPS\0" "\x05" "MULPD\0" "\x05" "MULSS\0" "\x05" "MULSD\0" "\x06" "VMULPS\0" \
"\x06" "VMULPD\0" "\x06" "VMULSS\0" "\x06" "VMULSD\0" "\x08" "CVTPS2PD\0" "\x08" "CVTPD2PS\0" \
"\x08" "CVTSS2SD\0" "\x08" "CVTSD2SS\0" "\x09" "VCVTPS2PD\0" "\x09" "VCVTPD2PS\0" \
"\x09" "VCVTSS2SD\0" "\x09" "VCVTSD2SS\0" "\x08" "CVTDQ2PS\0" "\x08" "CVTPS2DQ\0" \
"\x09" "CVTTPS2DQ\0" "\x09" "VCVTDQ2PS\0" "\x09" "VCVTPS2DQ\0" "\x0a" "VCVTTPS2DQ\0" \
"\x05" "SUBPS\0" "\x05" "SUBPD\0" "\x05" "SUBSS\0" "\x05" "SUBSD\0" "\x06" "VSUBPS\0" \
"\x06" "VSUBPD\0" "\x06" "VSUBSS\0" "\x06" "VSUBSD\0" "\x05" "MINPS\0" "\x05" "MINPD\0" \
"\x05" "MINSS\0" "\x05" "MINSD\0" "\x06" "VMINPS\0" "\x06" "VMINPD\0" "\x06" "VMINSS\0" \
"\x06" "VMINSD\0" "\x05" "DIVPS\0" "\x05" "DIVPD\0" "\x05" "DIVSS\0" "\x05" "DIVSD\0" \
"\x06" "VDIVPS\0" "\x06" "VDIVPD\0" "\x06" "VDIVSS\0" "\x06" "VDIVSD\0" "\x05" "MAXPS\0" \
"\x05" "MAXPD\0" "\x05" "MAXSS\0" "\x05" "MAXSD\0" "\x06" "VMAXPS\0" "\x06" "VMAXPD\0" \
"\x06" "VMAXSS\0" "\x06" "VMAXSD\0" "\x09" "PUNPCKLBW\0" "\x0a" "VPUNPCKLBW\0" \
"\x09" "PUNPCKLWD\0" "\x0a" "VPUNPCKLWD\0" "\x09" "PUNPCKLDQ\0" "\x0a" "VPUNPCKLDQ\0" \
"\x08" "PACKSSWB\0" "\x09" "VPACKSSWB\0" "\x07" "PCMPGTB\0" "\x08" "VPCMPGTB\0" \
"\x07" "PCMPGTW\0" "\x08" "VPCMPGTW\0" "\x07" "PCMPGTD\0" "\x08" "VPCMPGTD\0" \
"\x08" "PACKUSWB\0" "\x09" "VPACKUSWB\0" "\x09" "PUNPCKHBW\0" "\x0a" "VPUNPCKHBW\0" \
"\x09" "PUNPCKHWD\0" "\x0a" "VPUNPCKHWD\0" "\x09" "PUNPCKHDQ\0" "\x0a" "VPUNPCKHDQ\0" \
"\x08" "PACKSSDW\0" "\x09" "VPACKSSDW\0" "\x0a" "PUNPCKLQDQ\0" "\x0b" "VPUNPCKLQDQ\0" \
"\x0a" "PUNPCKHQDQ\0" "\x0b" "VPUNPCKHQDQ\0" "\x04" "MOVD\0" "\x04" "MOVQ\0" \
"\x05" "VMOVD\0" "\x05" "VMOVQ\0" "\x06" "MOVDQA\0" "\x06" "MOVDQU\0" "\x07" "VMOVDQA\0" \
"\x07" "VMOVDQU\0" "\x06" "PSHUFW\0" "\x06" "PSHUFD\0" "\x07" "PSHUFHW\0" "\x07" "PSHUFLW\0" \
"\x07" "VPSHUFD\0" "\x08" "VPSHUFHW\0" "\x08" "VPSHUFLW\0" "\x07" "PCMPEQB\0" \
"\x08" "VPCMPEQB\0" "\x07" "PCMPEQW\0" "\x08" "VPCMPEQW\0" "\x07" "PCMPEQD\0" \
"\x08" "VPCMPEQD\0" "\x04" "EMMS\0" "\x0a" "VZEROUPPER\0" "\x08" "VZEROALL\0" \
"\x06" "VMREAD\0" "\x05" "EXTRQ\0" "\x07" "INSERTQ\0" "\x07" "VMWRITE\0" "\x08" "CVTPH2PS\0" \
"\x08" "CVTPS2PH\0" "\x06" "HADDPD\0" "\x06" "HADDPS\0" "\x07" "VHADDPD\0" \
"\x07" "VHADDPS\0" "\x06" "HSUBPD\0" "\x06" "HSUBPS\0" "\x07" "VHSUBPD\0" "\x07" "VHSUBPS\0" \
"\x05" "XSAVE\0" "\x07" "XSAVE64\0" "\x06" "LFENCE\0" "\x06" "XRSTOR\0" "\x08" "XRSTOR64\0" \
"\x06" "MFENCE\0" "\x08" "XSAVEOPT\0" "\x0a" "XSAVEOPT64\0" "\x06" "SFENCE\0" \
"\x07" "CLFLUSH\0" "\x06" "POPCNT\0" "\x03" "BSF\0" "\x05" "TZCNT\0" "\x03" "BSR\0" \
"\x05" "LZCNT\0" "\x07" "CMPEQPS\0" "\x07" "CMPLTPS\0" "\x07" "CMPLEPS\0" "\x0a" "CMPUNORDPS\0" \
"\x08" "CMPNEQPS\0" "\x08" "CMPNLTPS\0" "\x08" "CMPNLEPS\0" "\x08" "CMPORDPS\0" \
"\x07" "CMPEQPD\0" "\x07" "CMPLTPD\0" "\x07" "CMPLEPD\0" "\x0a" "CMPUNORDPD\0" \
"\x08" "CMPNEQPD\0" "\x08" "CMPNLTPD\0" "\x08" "CMPNLEPD\0" "\x08" "CMPORDPD\0" \
"\x07" "CMPEQSS\0" "\x07" "CMPLTSS\0" "\x07" "CMPLESS\0" "\x0a" "CMPUNORDSS\0" \
"\x08" "CMPNEQSS\0" "\x08" "CMPNLTSS\0" "\x08" "CMPNLESS\0" "\x08" "CMPORDSS\0" \
"\x07" "CMPEQSD\0" "\x07" "CMPLTSD\0" "\x07" "CMPLESD\0" "\x0a" "CMPUNORDSD\0" \
"\x08" "CMPNEQSD\0" "\x08" "CMPNLTSD\0" "\x08" "CMPNLESD\0" "\x08" "CMPORDSD\0" \
"\x08" "VCMPEQPS\0" "\x08" "VCMPLTPS\0" "\x08" "VCMPLEPS\0" "\x0b" "VCMPUNORDPS\0" \
"\x09" "VCMPNEQPS\0" "\x09" "VCMPNLTPS\0" "\x09" "VCMPNLEPS\0" "\x09" "VCMPORDPS\0" \
"\x0b" "VCMPEQ_UQPS\0" "\x09" "VCMPNGEPS\0" "\x09" "VCMPNGTPS\0" "\x0b" "VCMPFALSEPS\0" \
"\x0c" "VCMPNEQ_OQPS\0" "\x08" "VCMPGEPS\0" "\x08" "VCMPGTPS\0" "\x0a" "VCMPTRUEPS\0" \
"\x0b" "VCMPEQ_OSPS\0" "\x0b" "VCMPLT_OQPS\0" "\x0b" "VCMPLE_OQPS\0" "\x0d" "VCMPUNORD_SPS\0" \
"\x0c" "VCMPNEQ_USPS\0" "\x0c" "VCMPNLT_UQPS\0" "\x0c" "VCMPNLE_UQPS\0" "\x0b" "VCMPORD_SPS\0" \
"\x0b" "VCMPEQ_USPS\0" "\x0c" "VCMPNGE_UQPS\0" "\x0c" "VCMPNGT_UQPS\0" "\x0e" "VCMPFALSE_OSPS\0" \
"\x0c" "VCMPNEQ_OSPS\0" "\x0b" "VCMPGE_OQPS\0" "\x0b" "VCMPGT_OQPS\0" "\x0d" "VCMPTRUE_USPS\0" \
"\x08" "VCMPEQPD\0" "\x08" "VCMPLTPD\0" "\x08" "VCMPLEPD\0" "\x0b" "VCMPUNORDPD\0" \
"\x09" "VCMPNEQPD\0" "\x09" "VCMPNLTPD\0" "\x09" "VCMPNLEPD\0" "\x09" "VCMPORDPD\0" \
"\x0b" "VCMPEQ_UQPD\0" "\x09" "VCMPNGEPD\0" "\x09" "VCMPNGTPD\0" "\x0b" "VCMPFALSEPD\0" \
"\x0c" "VCMPNEQ_OQPD\0" "\x08" "VCMPGEPD\0" "\x08" "VCMPGTPD\0" "\x0a" "VCMPTRUEPD\0" \
"\x0b" "VCMPEQ_OSPD\0" "\x0b" "VCMPLT_OQPD\0" "\x0b" "VCMPLE_OQPD\0" "\x0d" "VCMPUNORD_SPD\0" \
"\x0c" "VCMPNEQ_USPD\0" "\x0c" "VCMPNLT_UQPD\0" "\x0c" "VCMPNLE_UQPD\0" "\x0b" "VCMPORD_SPD\0" \
"\x0b" "VCMPEQ_USPD\0" "\x0c" "VCMPNGE_UQPD\0" "\x0c" "VCMPNGT_UQPD\0" "\x0e" "VCMPFALSE_OSPD\0" \
"\x0c" "VCMPNEQ_OSPD\0" "\x0b" "VCMPGE_OQPD\0" "\x0b" "VCMPGT_OQPD\0" "\x0d" "VCMPTRUE_USPD\0" \
"\x08" "VCMPEQSS\0" "\x08" "VCMPLTSS\0" "\x08" "VCMPLESS\0" "\x0b" "VCMPUNORDSS\0" \
"\x09" "VCMPNEQSS\0" "\x09" "VCMPNLTSS\0" "\x09" "VCMPNLESS\0" "\x09" "VCMPORDSS\0" \
"\x0b" "VCMPEQ_UQSS\0" "\x09" "VCMPNGESS\0" "\x09" "VCMPNGTSS\0" "\x0b" "VCMPFALSESS\0" \
"\x0c" "VCMPNEQ_OQSS\0" "\x08" "VCMPGESS\0" "\x08" "VCMPGTSS\0" "\x0a" "VCMPTRUESS\0" \
"\x0b" "VCMPEQ_OSSS\0" "\x0b" "VCMPLT_OQSS\0" "\x0b" "VCMPLE_OQSS\0" "\x0d" "VCMPUNORD_SSS\0" \
"\x0c" "VCMPNEQ_USSS\0" "\x0c" "VCMPNLT_UQSS\0" "\x0c" "VCMPNLE_UQSS\0" "\x0b" "VCMPORD_SSS\0" \
"\x0b" "VCMPEQ_USSS\0" "\x0c" "VCMPNGE_UQSS\0" "\x0c" "VCMPNGT_UQSS\0" "\x0e" "VCMPFALSE_OSSS\0" \
"\x0c" "VCMPNEQ_OSSS\0" "\x0b" "VCMPGE_OQSS\0" "\x0b" "VCMPGT_OQSS\0" "\x0d" "VCMPTRUE_USSS\0" \
"\x08" "VCMPEQSD\0" "\x08" "VCMPLTSD\0" "\x08" "VCMPLESD\0" "\x0b" "VCMPUNORDSD\0" \
"\x09" "VCMPNEQSD\0" "\x09" "VCMPNLTSD\0" "\x09" "VCMPNLESD\0" "\x09" "VCMPORDSD\0" \
"\x0b" "VCMPEQ_UQSD\0" "\x09" "VCMPNGESD\0" "\x09" "VCMPNGTSD\0" "\x0b" "VCMPFALSESD\0" \
"\x0c" "VCMPNEQ_OQSD\0" "\x08" "VCMPGESD\0" "\x08" "VCMPGTSD\0" "\x0a" "VCMPTRUESD\0" \
"\x0b" "VCMPEQ_OSSD\0" "\x0b" "VCMPLT_OQSD\0" "\x0b" "VCMPLE_OQSD\0" "\x0d" "VCMPUNORD_SSD\0" \
"\x0c" "VCMPNEQ_USSD\0" "\x0c" "VCMPNLT_UQSD\0" "\x0c" "VCMPNLE_UQSD\0" "\x0b" "VCMPORD_SSD\0" \
"\x0b" "VCMPEQ_USSD\0" "\x0c" "VCMPNGE_UQSD\0" "\x0c" "VCMPNGT_UQSD\0" "\x0e" "VCMPFALSE_OSSD\0" \
"\x0c" "VCMPNEQ_OSSD\0" "\x0b" "VCMPGE_OQSD\0" "\x0b" "VCMPGT_OQSD\0" "\x0d" "VCMPTRUE_USSD\0" \
"\x06" "PINSRW\0" "\x07" "VPINSRW\0" "\x06" "PEXTRW\0" "\x07" "VPEXTRW\0" "\x06" "SHUFPS\0" \
"\x06" "SHUFPD\0" "\x07" "VSHUFPS\0" "\x07" "VSHUFPD\0" "\x09" "CMPXCHG8B\0" \
"\x0a" "CMPXCHG16B\0" "\x07" "VMPTRST\0" "\x08" "ADDSUBPD\0" "\x08" "ADDSUBPS\0" \
"\x09" "VADDSUBPD\0" "\x09" "VADDSUBPS\0" "\x05" "PSRLW\0" "\x06" "VPSRLW\0" \
"\x05" "PSRLD\0" "\x06" "VPSRLD\0" "\x05" "PSRLQ\0" "\x06" "VPSRLQ\0" "\x05" "PADDQ\0" \
"\x06" "VPADDQ\0" "\x06" "PMULLW\0" "\x07" "VPMULLW\0" "\x07" "MOVQ2DQ\0" "\x07" "MOVDQ2Q\0" \
"\x08" "PMOVMSKB\0" "\x09" "VPMOVMSKB\0" "\x07" "PSUBUSB\0" "\x08" "VPSUBUSB\0" \
"\x07" "PSUBUSW\0" "\x08" "VPSUBUSW\0" "\x06" "PMINUB\0" "\x07" "VPMINUB\0" \
"\x04" "PAND\0" "\x05" "VPAND\0" "\x07" "PADDUSB\0" "\x08" "VPADDUSW\0" "\x07" "PADDUSW\0" \
"\x06" "PMAXUB\0" "\x07" "VPMAXUB\0" "\x05" "PANDN\0" "\x06" "VPANDN\0" "\x05" "PAVGB\0" \
"\x06" "VPAVGB\0" "\x05" "PSRAW\0" "\x06" "VPSRAW\0" "\x05" "PSRAD\0" "\x06" "VPSRAD\0" \
"\x05" "PAVGW\0" "\x06" "VPAVGW\0" "\x07" "PMULHUW\0" "\x08" "VPMULHUW\0" "\x06" "PMULHW\0" \
"\x07" "VPMULHW\0" "\x09" "CVTTPD2DQ\0" "\x08" "CVTDQ2PD\0" "\x08" "CVTPD2DQ\0" \
"\x0a" "VCVTTPD2DQ\0" "\x09" "VCVTDQ2PD\0" "\x09" "VCVTPD2DQ\0" "\x06" "MOVNTQ\0" \
"\x07" "MOVNTDQ\0" "\x08" "VMOVNTDQ\0" "\x06" "PSUBSB\0" "\x07" "VPSUBSB\0" \
"\x06" "PSUBSW\0" "\x07" "VPSUBSW\0" "\x06" "PMINSW\0" "\x07" "VPMINSW\0" "\x03" "POR\0" \
"\x04" "VPOR\0" "\x06" "PADDSB\0" "\x07" "VPADDSB\0" "\x06" "PADDSW\0" "\x07" "VPADDSW\0" \
"\x06" "PMAXSW\0" "\x07" "VPMAXSW\0" "\x04" "PXOR\0" "\x05" "VPXOR\0" "\x05" "LDDQU\0" \
"\x06" "VLDDQU\0" "\x05" "PSLLW\0" "\x06" "VPSLLW\0" "\x05" "PSLLD\0" "\x06" "VPSLLD\0" \
"\x05" "PSLLQ\0" "\x06" "VPSLLQ\0" "\x07" "PMULUDQ\0" "\x08" "VPMULUDQ\0" "\x07" "PMADDWD\0" \
"\x08" "VPMADDWD\0" "\x06" "PSADBW\0" "\x07" "VPSADBW\0" "\x08" "MASKMOVQ\0" \
"\x0a" "MASKMOVDQU\0" "\x0b" "VMASKMOVDQU\0" "\x05" "PSUBB\0" "\x06" "VPSUBB\0" \
"\x05" "PSUBW\0" "\x06" "VPSUBW\0" "\x05" "PSUBD\0" "\x06" "VPSUBD\0" "\x05" "PSUBQ\0" \
"\x06" "VPSUBQ\0" "\x05" "PADDB\0" "\x06" "VPADDB\0" "\x05" "PADDW\0" "\x06" "VPADDW\0" \
"\x05" "PADDD\0" "\x06" "VPADDD\0" "\x07" "FNSTENV\0" "\x06" "FSTENV\0" "\x06" "FNSTCW\0" \
"\x05" "FSTCW\0" "\x06" "FNCLEX\0" "\x05" "FCLEX\0" "\x06" "FNINIT\0" "\x05" "FINIT\0" \
"\x06" "FNSAVE\0" "\x05" "FSAVE\0" "\x06" "FNSTSW\0" "\x05" "FSTSW\0" "\x06" "PSHUFB\0" \
"\x07" "VPSHUFB\0" "\x06" "PHADDW\0" "\x07" "VPHADDW\0" "\x06" "PHADDD\0" "\x07" "VPHADDD\0" \
"\x07" "PHADDSW\0" "\x08" "VPHADDSW\0" "\x09" "PMADDUBSW\0" "\x0a" "VPMADDUBSW\0" \
"\x06" "PHSUBW\0" "\x07" "VPHSUBW\0" "\x06" "PHSUBD\0" "\x07" "VPHSUBD\0" "\x07" "PHSUBSW\0" \
"\x08" "VPHSUBSW\0" "\x06" "PSIGNB\0" "\x07" "VPSIGNB\0" "\x06" "PSIGNW\0" \
"\x07" "VPSIGNW\0" "\x06" "PSIGND\0" "\x07" "VPSIGND\0" "\x08" "PMULHRSW\0" \
"\x09" "VPMULHRSW\0" "\x09" "VPERMILPS\0" "\x09" "VPERMILPD\0" "\x07" "VTESTPS\0" \
"\x07" "VTESTPD\0" "\x08" "PBLENDVB\0" "\x08" "BLENDVPS\0" "\x08" "BLENDVPD\0" \
"\x05" "PTEST\0" "\x06" "VPTEST\0" "\x0c" "VBROADCASTSS\0" "\x0c" "VBROADCASTSD\0" \
"\x0e" "VBROADCASTF128\0" "\x05" "PABSB\0" "\x06" "VPABSB\0" "\x05" "PABSW\0" \
"\x06" "VPABSW\0" "\x05" "PABSD\0" "\x06" "VPABSD\0" "\x08" "PMOVSXBW\0" "\x09" "VPMOVSXBW\0" \
"\x08" "PMOVSXBD\0" "\x09" "VPMOVSXBD\0" "\x08" "PMOVSXBQ\0" "\x09" "VPMOVSXBQ\0" \
"\x08" "PMOVSXWD\0" "\x09" "VPMOVSXWD\0" "\x08" "PMOVSXWQ\0" "\x09" "VPMOVSXWQ\0" \
"\x08" "PMOVSXDQ\0" "\x09" "VPMOVSXDQ\0" "\x06" "PMULDQ\0" "\x07" "VPMULDQ\0" \
"\x07" "PCMPEQQ\0" "\x08" "VPCMPEQQ\0" "\x08" "MOVNTDQA\0" "\x09" "VMOVNTDQA\0" \
"\x08" "PACKUSDW\0" "\x09" "VPACKUSDW\0" "\x0a" "VMASKMOVPS\0" "\x0a" "VMASKMOVPD\0" \
"\x08" "PMOVZXBW\0" "\x09" "VPMOVZXBW\0" "\x08" "PMOVZXBD\0" "\x09" "VPMOVZXBD\0" \
"\x08" "PMOVZXBQ\0" "\x09" "VPMOVZXBQ\0" "\x08" "PMOVZXWD\0" "\x09" "VPMOVZXWD\0" \
"\x08" "PMOVZXWQ\0" "\x09" "VPMOVZXWQ\0" "\x08" "PMOVZXDQ\0" "\x09" "VPMOVZXDQ\0" \
"\x07" "PCMPGTQ\0" "\x08" "VPCMPGTQ\0" "\x06" "PMINSB\0" "\x07" "VPMINSB\0" \
"\x06" "PMINSD\0" "\x07" "VPMINSD\0" "\x06" "PMINUW\0" "\x07" "VPMINUW\0" "\x06" "PMINUD\0" \
"\x07" "VPMINUD\0" "\x06" "PMAXSB\0" "\x07" "VPMAXSB\0" "\x06" "PMAXSD\0" "\x07" "VPMAXSD\0" \
"\x06" "PMAXUW\0" "\x07" "VPMAXUW\0" "\x06" "PMAXUD\0" "\x07" "VPMAXUD\0" "\x06" "PMULLD\0" \
"\x07" "VPMULLD\0" "\x0a" "PHMINPOSUW\0" "\x0b" "VPHMINPOSUW\0" "\x06" "INVEPT\0" \
"\x07" "INVVPID\0" "\x07" "INVPCID\0" "\x0e" "VFMADDSUB132PS\0" "\x0e" "VFMADDSUB132PD\0" \
"\x0e" "VFMSUBADD132PS\0" "\x0e" "VFMSUBADD132PD\0" "\x0b" "VFMADD132PS\0" \
"\x0b" "VFMADD132PD\0" "\x0b" "VFMADD132SS\0" "\x0b" "VFMADD132SD\0" "\x0b" "VFMSUB132PS\0" \
"\x0b" "VFMSUB132PD\0" "\x0b" "VFMSUB132SS\0" "\x0b" "VFMSUB132SD\0" "\x0c" "VFNMADD132PS\0" \
"\x0c" "VFNMADD132PD\0" "\x0c" "VFNMADD132SS\0" "\x0c" "VFNMADD132SD\0" "\x0c" "VFNMSUB132PS\0" \
"\x0c" "VFNMSUB132PD\0" "\x0c" "VFNMSUB132SS\0" "\x0c" "VFNMSUB132SD\0" "\x0e" "VFMADDSUB213PS\0" \
"\x0e" "VFMADDSUB213PD\0" "\x0e" "VFMSUBADD213PS\0" "\x0e" "VFMSUBADD213PD\0" \
"\x0b" "VFMADD213PS\0" "\x0b" "VFMADD213PD\0" "\x0b" "VFMADD213SS\0" "\x0b" "VFMADD213SD\0" \
"\x0b" "VFMSUB213PS\0" "\x0b" "VFMSUB213PD\0" "\x0b" "VFMSUB213SS\0" "\x0b" "VFMSUB213SD\0" \
"\x0c" "VFNMADD213PS\0" "\x0c" "VFNMADD213PD\0" "\x0c" "VFNMADD213SS\0" "\x0c" "VFNMADD213SD\0" \
"\x0c" "VFNMSUB213PS\0" "\x0c" "VFNMSUB213PD\0" "\x0c" "VFNMSUB213SS\0" "\x0c" "VFNMSUB213SD\0" \
"\x0e" "VFMADDSUB231PS\0" "\x0e" "VFMADDSUB231PD\0" "\x0e" "VFMSUBADD231PS\0" \
"\x0e" "VFMSUBADD231PD\0" "\x0b" "VFMADD231PS\0" "\x0b" "VFMADD231PD\0" "\x0b" "VFMADD231SS\0" \
"\x0b" "VFMADD231SD\0" "\x0b" "VFMSUB231PS\0" "\x0b" "VFMSUB231PD\0" "\x0b" "VFMSUB231SS\0" \
"\x0b" "VFMSUB231SD\0" "\x0c" "VFNMADD231PS\0" "\x0c" "VFNMADD231PD\0" "\x0c" "VFNMADD231SS\0" \
"\x0c" "VFNMADD231SD\0" "\x0c" "VFNMSUB231PS\0" "\x0c" "VFNMSUB231PD\0" "\x0c" "VFNMSUB231SS\0" \
"\x0c" "VFNMSUB231SD\0" "\x06" "AESIMC\0" "\x07" "VAESIMC\0" "\x06" "AESENC\0" \
"\x07" "VAESENC\0" "\x0a" "AESENCLAST\0" "\x0b" "VAESENCLAST\0" "\x06" "AESDEC\0" \
"\x07" "VAESDEC\0" "\x0a" "AESDECLAST\0" "\x0b" "VAESDECLAST\0" "\x05" "MOVBE\0" \
"\x05" "CRC32\0" "\x0a" "VPERM2F128\0" "\x07" "ROUNDPS\0" "\x08" "VROUNDPS\0" \
"\x07" "ROUNDPD\0" "\x08" "VROUNDPD\0" "\x07" "ROUNDSS\0" "\x08" "VROUNDSS\0" \
"\x07" "ROUNDSD\0" "\x08" "VROUNDSD\0" "\x07" "BLENDPS\0" "\x08" "VBLENDPS\0" \
"\x07" "BLENDPD\0" "\x08" "VBLENDPD\0" "\x07" "PBLENDW\0" "\x08" "VPBLENDW\0" \
"\x07" "PALIGNR\0" "\x08" "VPALIGNR\0" "\x06" "PEXTRB\0" "\x07" "VPEXTRB\0" \
"\x06" "PEXTRD\0" "\x06" "PEXTRQ\0" "\x07" "VPEXTRD\0" "\x07" "VPEXTRQ\0" "\x09" "EXTRACTPS\0" \
"\x0a" "VEXTRACTPS\0" "\x0b" "VINSERTF128\0" "\x0c" "VEXTRACTF128\0" "\x06" "PINSRB\0" \
"\x07" "VPINSRB\0" "\x08" "INSERTPS\0" "\x09" "VINSERTPS\0" "\x06" "PINSRD\0" \
"\x06" "PINSRQ\0" "\x07" "VPINSRD\0" "\x07" "VPINSRQ\0" "\x04" "DPPS\0" "\x05" "VDPPS\0" \
"\x04" "DPPD\0" "\x05" "VDPPD\0" "\x07" "MPSADBW\0" "\x08" "VMPSADBW\0" "\x09" "PCLMULQDQ\0" \
"\x0a" "VPCLMULQDQ\0" "\x09" "VBLENDVPS\0" "\x09" "VBLENDVPD\0" "\x09" "VPBLENDVB\0" \
"\x09" "PCMPESTRM\0" "\x0a" "VPCMPESTRM\0" "\x09" "PCMPESTRI\0" "\x0a" "VPCMPESTRI\0" \
"\x09" "PCMPISTRM\0" "\x0a" "VPCMPISTRM\0" "\x09" "PCMPISTRI\0" "\x0a" "VPCMPISTRI\0" \
"\x0f" "AESKEYGENASSIST\0" "\x10" "VAESKEYGENASSIST\0" "\x06" "PSRLDQ\0" "\x07" "VPSRLDQ\0" \
"\x06" "PSLLDQ\0" "\x07" "VPSLLDQ\0" "\x06" "FXSAVE\0" "\x08" "FXSAVE64\0" \
"\x08" "RDFSBASE\0" "\x07" "FXRSTOR\0" "\x09" "FXRSTOR64\0" "\x08" "RDGSBASE\0" \
"\x07" "LDMXCSR\0" "\x08" "WRFSBASE\0" "\x08" "VLDMXCSR\0" "\x07" "STMXCSR\0" \
"\x08" "WRGSBASE\0" "\x08" "VSTMXCSR\0" "\x06" "RDRAND\0" "\x07" "VMPTRLD\0" \
"\x07" "VMCLEAR\0" "\x05" "VMXON\0" "\x06" "MOVSXD\0" "\x05" "PAUSE\0" "\x04" "WAIT\0" \
"\x05" "3DNOW\0";
const _WRegister _REGISTERS[] = {
{3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"},
{3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"},
{2, "AX"}, {2, "CX"}, {2, "DX"}, {2, "BX"}, {2, "SP"}, {2, "BP"}, {2, "SI"}, {2, "DI"}, {3, "R8W"}, {3, "R9W"}, {4, "R10W"}, {4, "R11W"}, {4, "R12W"}, {4, "R13W"}, {4, "R14W"}, {4, "R15W"},
{2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {2, "AH"}, {2, "CH"}, {2, "DH"}, {2, "BH"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"},
{3, "SPL"}, {3, "BPL"}, {3, "SIL"}, {3, "DIL"},
{2, "ES"}, {2, "CS"}, {2, "SS"}, {2, "DS"}, {2, "FS"}, {2, "GS"},
{3, "RIP"},
{3, "ST0"}, {3, "ST1"}, {3, "ST2"}, {3, "ST3"}, {3, "ST4"}, {3, "ST5"}, {3, "ST6"}, {3, "ST7"},
{3, "MM0"}, {3, "MM1"}, {3, "MM2"}, {3, "MM3"}, {3, "MM4"}, {3, "MM5"}, {3, "MM6"}, {3, "MM7"},
{4, "XMM0"}, {4, "XMM1"}, {4, "XMM2"}, {4, "XMM3"}, {4, "XMM4"}, {4, "XMM5"}, {4, "XMM6"}, {4, "XMM7"}, {4, "XMM8"}, {4, "XMM9"}, {5, "XMM10"}, {5, "XMM11"}, {5, "XMM12"}, {5, "XMM13"}, {5, "XMM14"}, {5, "XMM15"},
{4, "YMM0"}, {4, "YMM1"}, {4, "YMM2"}, {4, "YMM3"}, {4, "YMM4"}, {4, "YMM5"}, {4, "YMM6"}, {4, "YMM7"}, {4, "YMM8"}, {4, "YMM9"}, {5, "YMM10"}, {5, "YMM11"}, {5, "YMM12"}, {5, "YMM13"}, {5, "YMM14"}, {5, "YMM15"},
{3, "CR0"}, {0, ""}, {3, "CR2"}, {3, "CR3"}, {3, "CR4"}, {0, ""}, {0, ""}, {0, ""}, {3, "CR8"},
{3, "DR0"}, {3, "DR1"}, {3, "DR2"}, {3, "DR3"}, {0, ""}, {0, ""}, {3, "DR6"}, {3, "DR7"}
};
#endif /* DISTORM_LIGHT */

View File

@ -0,0 +1,313 @@
/*
mnemonics.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef MNEMONICS_H
#define MNEMONICS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DISTORM_LIGHT
typedef struct WMnemonic {
unsigned char length;
unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */
} _WMnemonic;
typedef struct WRegister {
unsigned int length;
unsigned char p[6]; /* p is a null terminated string. */
} _WRegister;
extern const unsigned char _MNEMONICS[];
extern const _WRegister _REGISTERS[];
#endif /* DISTORM_LIGHT */
#ifdef __cplusplus
} /* End Of Extern */
#endif
#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p
#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p
typedef enum {
I_UNDEFINED = 0, I_3DNOW = 10034, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31,
I_ADD = 11, I_ADDPD = 3110, I_ADDPS = 3103, I_ADDSD = 3124, I_ADDSS = 3117,
I_ADDSUBPD = 6394, I_ADDSUBPS = 6404, I_AESDEC = 9209, I_AESDECLAST = 9226,
I_AESENC = 9167, I_AESENCLAST = 9184, I_AESIMC = 9150, I_AESKEYGENASSIST = 9795,
I_AND = 41, I_ANDNPD = 3021, I_ANDNPS = 3013, I_ANDPD = 2990, I_ANDPS = 2983,
I_ARPL = 111, I_BLENDPD = 9372, I_BLENDPS = 9353, I_BLENDVPD = 7619, I_BLENDVPS = 7609,
I_BOUND = 104, I_BSF = 4346, I_BSR = 4358, I_BSWAP = 960, I_BT = 872, I_BTC = 934,
I_BTR = 912, I_BTS = 887, I_CALL = 456, I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250,
I_CDQE = 239, I_CLC = 492, I_CLD = 512, I_CLFLUSH = 4329, I_CLGI = 1833, I_CLI = 502,
I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686,
I_CMOVG = 754, I_CMOVGE = 738, I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648,
I_CMOVNP = 723, I_CMOVNS = 708, I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716,
I_CMOVS = 701, I_CMOVZ = 671, I_CMP = 71, I_CMPEQPD = 4449, I_CMPEQPS = 4370,
I_CMPEQSD = 4607, I_CMPEQSS = 4528, I_CMPLEPD = 4467, I_CMPLEPS = 4388, I_CMPLESD = 4625,
I_CMPLESS = 4546, I_CMPLTPD = 4458, I_CMPLTPS = 4379, I_CMPLTSD = 4616, I_CMPLTSS = 4537,
I_CMPNEQPD = 4488, I_CMPNEQPS = 4409, I_CMPNEQSD = 4646, I_CMPNEQSS = 4567,
I_CMPNLEPD = 4508, I_CMPNLEPS = 4429, I_CMPNLESD = 4666, I_CMPNLESS = 4587,
I_CMPNLTPD = 4498, I_CMPNLTPS = 4419, I_CMPNLTSD = 4656, I_CMPNLTSS = 4577,
I_CMPORDPD = 4518, I_CMPORDPS = 4439, I_CMPORDSD = 4676, I_CMPORDSS = 4597,
I_CMPS = 301, I_CMPUNORDPD = 4476, I_CMPUNORDPS = 4397, I_CMPUNORDSD = 4634,
I_CMPUNORDSS = 4555, I_CMPXCHG = 898, I_CMPXCHG16B = 6373, I_CMPXCHG8B = 6362,
I_COMISD = 2779, I_COMISS = 2771, I_CPUID = 865, I_CQO = 255, I_CRC32 = 9258,
I_CVTDQ2PD = 6787, I_CVTDQ2PS = 3307, I_CVTPD2DQ = 6797, I_CVTPD2PI = 2681,
I_CVTPD2PS = 3233, I_CVTPH2PS = 4161, I_CVTPI2PD = 2495, I_CVTPI2PS = 2485,
I_CVTPS2DQ = 3317, I_CVTPS2PD = 3223, I_CVTPS2PH = 4171, I_CVTPS2PI = 2671,
I_CVTSD2SI = 2701, I_CVTSD2SS = 3253, I_CVTSI2SD = 2515, I_CVTSI2SS = 2505,
I_CVTSS2SD = 3243, I_CVTSS2SI = 2691, I_CVTTPD2DQ = 6776, I_CVTTPD2PI = 2614,
I_CVTTPS2DQ = 3327, I_CVTTPS2PI = 2603, I_CVTTSD2SI = 2636, I_CVTTSS2SI = 2625,
I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1630,
I_DIVPD = 3499, I_DIVPS = 3492, I_DIVSD = 3513, I_DIVSS = 3506, I_DPPD = 9615,
I_DPPS = 9602, I_EMMS = 4100, I_ENTER = 340, I_EXTRACTPS = 9480, I_EXTRQ = 4136,
I_F2XM1 = 1176, I_FABS = 1107, I_FADD = 1007, I_FADDP = 1533, I_FBLD = 1585,
I_FBSTP = 1591, I_FCHS = 1101, I_FCLEX = 7289, I_FCMOVB = 1360, I_FCMOVBE = 1376,
I_FCMOVE = 1368, I_FCMOVNB = 1429, I_FCMOVNBE = 1447, I_FCMOVNE = 1438, I_FCMOVNU = 1457,
I_FCMOVU = 1385, I_FCOM = 1019, I_FCOMI = 1496, I_FCOMIP = 1607, I_FCOMP = 1025,
I_FCOMPP = 1547, I_FCOS = 1295, I_FDECSTP = 1222, I_FDIV = 1045, I_FDIVP = 1578,
I_FDIVR = 1051, I_FDIVRP = 1570, I_FEDISI = 1472, I_FEMMS = 574, I_FENI = 1466,
I_FFREE = 1511, I_FIADD = 1301, I_FICOM = 1315, I_FICOMP = 1322, I_FIDIV = 1345,
I_FIDIVR = 1352, I_FILD = 1402, I_FIMUL = 1308, I_FINCSTP = 1231, I_FINIT = 7304,
I_FIST = 1416, I_FISTP = 1422, I_FISTTP = 1408, I_FISUB = 1330, I_FISUBR = 1337,
I_FLD = 1058, I_FLD1 = 1125, I_FLDCW = 1082, I_FLDENV = 1074, I_FLDL2E = 1139,
I_FLDL2T = 1131, I_FLDLG2 = 1154, I_FLDLN2 = 1162, I_FLDPI = 1147, I_FLDZ = 1170,
I_FMUL = 1013, I_FMULP = 1540, I_FNCLEX = 7281, I_FNINIT = 7296, I_FNOP = 1095,
I_FNSAVE = 7311, I_FNSTCW = 7266, I_FNSTENV = 7249, I_FNSTSW = 7326, I_FPATAN = 1197,
I_FPREM = 1240, I_FPREM1 = 1214, I_FPTAN = 1190, I_FRNDINT = 1272, I_FRSTOR = 1503,
I_FSAVE = 7319, I_FSCALE = 1281, I_FSETPM = 1480, I_FSIN = 1289, I_FSINCOS = 1263,
I_FSQRT = 1256, I_FST = 1063, I_FSTCW = 7274, I_FSTENV = 7258, I_FSTP = 1068,
I_FSTSW = 7334, I_FSUB = 1032, I_FSUBP = 1563, I_FSUBR = 1038, I_FSUBRP = 1555,
I_FTST = 1113, I_FUCOM = 1518, I_FUCOMI = 1488, I_FUCOMIP = 1598, I_FUCOMP = 1525,
I_FUCOMPP = 1393, I_FXAM = 1119, I_FXCH = 1089, I_FXRSTOR = 9892, I_FXRSTOR64 = 9901,
I_FXSAVE = 9864, I_FXSAVE64 = 9872, I_FXTRACT = 1205, I_FYL2X = 1183, I_FYL2XP1 = 1247,
I_GETSEC = 633, I_HADDPD = 4181, I_HADDPS = 4189, I_HLT = 482, I_HSUBPD = 4215,
I_HSUBPS = 4223, I_IDIV = 1635, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123,
I_INSERTPS = 9547, I_INSERTQ = 4143, I_INT = 367, I_INT_3 = 360, I_INT1 = 476,
I_INTO = 372, I_INVD = 555, I_INVEPT = 8284, I_INVLPG = 1711, I_INVLPGA = 1847,
I_INVPCID = 8301, I_INVVPID = 8292, I_IRET = 378, I_JA = 166, I_JAE = 147,
I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192,
I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183,
I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170,
I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 6994, I_LDMXCSR = 9922, I_LDS = 335,
I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4265, I_LFS = 917, I_LGDT = 1687,
I_LGS = 922, I_LIDT = 1693, I_LLDT = 1652, I_LMSW = 1705, I_LODS = 313, I_LOOP = 421,
I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1658, I_LZCNT = 4363,
I_MASKMOVDQU = 7119, I_MASKMOVQ = 7109, I_MAXPD = 3559, I_MAXPS = 3552, I_MAXSD = 3573,
I_MAXSS = 3566, I_MFENCE = 4291, I_MINPD = 3439, I_MINPS = 3432, I_MINSD = 3453,
I_MINSS = 3446, I_MONITOR = 1755, I_MOV = 218, I_MOVAPD = 2459, I_MOVAPS = 2451,
I_MOVBE = 9251, I_MOVD = 3920, I_MOVDDUP = 2186, I_MOVDQ2Q = 6522, I_MOVDQA = 3946,
I_MOVDQU = 3954, I_MOVHLPS = 2151, I_MOVHPD = 2345, I_MOVHPS = 2337, I_MOVLHPS = 2328,
I_MOVLPD = 2168, I_MOVLPS = 2160, I_MOVMSKPD = 2815, I_MOVMSKPS = 2805, I_MOVNTDQ = 6849,
I_MOVNTDQA = 7895, I_MOVNTI = 952, I_MOVNTPD = 2556, I_MOVNTPS = 2547, I_MOVNTQ = 6841,
I_MOVNTSD = 2574, I_MOVNTSS = 2565, I_MOVQ = 3926, I_MOVQ2DQ = 6513, I_MOVS = 295,
I_MOVSD = 2110, I_MOVSHDUP = 2353, I_MOVSLDUP = 2176, I_MOVSS = 2103, I_MOVSX = 939,
I_MOVSXD = 10013, I_MOVUPD = 2095, I_MOVUPS = 2087, I_MOVZX = 927, I_MPSADBW = 9628,
I_MUL = 1625, I_MULPD = 3170, I_MULPS = 3163, I_MULSD = 3184, I_MULSS = 3177,
I_MWAIT = 1764, I_NEG = 1620, I_NOP = 581, I_NOT = 1615, I_OR = 27, I_ORPD = 3053,
I_ORPS = 3047, I_OUT = 451, I_OUTS = 128, I_PABSB = 7688, I_PABSD = 7718, I_PABSW = 7703,
I_PACKSSDW = 3849, I_PACKSSWB = 3681, I_PACKUSDW = 7916, I_PACKUSWB = 3759,
I_PADDB = 7204, I_PADDD = 7234, I_PADDQ = 6481, I_PADDSB = 6930, I_PADDSW = 6947,
I_PADDUSB = 6620, I_PADDUSW = 6639, I_PADDW = 7219, I_PALIGNR = 9410, I_PAND = 6607,
I_PANDN = 6665, I_PAUSE = 10021, I_PAVGB = 6680, I_PAVGUSB = 2078, I_PAVGW = 6725,
I_PBLENDVB = 7599, I_PBLENDW = 9391, I_PCLMULQDQ = 9647, I_PCMPEQB = 4043,
I_PCMPEQD = 4081, I_PCMPEQQ = 7876, I_PCMPEQW = 4062, I_PCMPESTRI = 9726,
I_PCMPESTRM = 9703, I_PCMPGTB = 3702, I_PCMPGTD = 3740, I_PCMPGTQ = 8087,
I_PCMPGTW = 3721, I_PCMPISTRI = 9772, I_PCMPISTRM = 9749, I_PEXTRB = 9429,
I_PEXTRD = 9446, I_PEXTRQ = 9454, I_PEXTRW = 6311, I_PF2ID = 1914, I_PF2IW = 1907,
I_PFACC = 2028, I_PFADD = 1977, I_PFCMPEQ = 2035, I_PFCMPGE = 1938, I_PFCMPGT = 1984,
I_PFMAX = 1993, I_PFMIN = 1947, I_PFMUL = 2044, I_PFNACC = 1921, I_PFPNACC = 1929,
I_PFRCP = 1954, I_PFRCPIT1 = 2000, I_PFRCPIT2 = 2051, I_PFRSQIT1 = 2010, I_PFRSQRT = 1961,
I_PFSUB = 1970, I_PFSUBR = 2020, I_PHADDD = 7375, I_PHADDSW = 7392, I_PHADDW = 7358,
I_PHMINPOSUW = 8259, I_PHSUBD = 7451, I_PHSUBSW = 7468, I_PHSUBW = 7434, I_PI2FD = 1900,
I_PI2FW = 1893, I_PINSRB = 9530, I_PINSRD = 9568, I_PINSRQ = 9576, I_PINSRW = 6294,
I_PMADDUBSW = 7411, I_PMADDWD = 7073, I_PMAXSB = 8174, I_PMAXSD = 8191, I_PMAXSW = 6964,
I_PMAXUB = 6648, I_PMAXUD = 8225, I_PMAXUW = 8208, I_PMINSB = 8106, I_PMINSD = 8123,
I_PMINSW = 6902, I_PMINUB = 6590, I_PMINUD = 8157, I_PMINUW = 8140, I_PMOVMSKB = 6531,
I_PMOVSXBD = 7754, I_PMOVSXBQ = 7775, I_PMOVSXBW = 7733, I_PMOVSXDQ = 7838,
I_PMOVSXWD = 7796, I_PMOVSXWQ = 7817, I_PMOVZXBD = 7982, I_PMOVZXBQ = 8003,
I_PMOVZXBW = 7961, I_PMOVZXDQ = 8066, I_PMOVZXWD = 8024, I_PMOVZXWQ = 8045,
I_PMULDQ = 7859, I_PMULHRSW = 7538, I_PMULHRW = 2061, I_PMULHUW = 6740, I_PMULHW = 6759,
I_PMULLD = 8242, I_PMULLW = 6496, I_PMULUDQ = 7054, I_POP = 22, I_POPA = 98,
I_POPCNT = 4338, I_POPF = 277, I_POR = 6919, I_PREFETCH = 1872, I_PREFETCHNTA = 2402,
I_PREFETCHT0 = 2415, I_PREFETCHT1 = 2427, I_PREFETCHT2 = 2439, I_PREFETCHW = 1882,
I_PSADBW = 7092, I_PSHUFB = 7341, I_PSHUFD = 3988, I_PSHUFHW = 3996, I_PSHUFLW = 4005,
I_PSHUFW = 3980, I_PSIGNB = 7487, I_PSIGND = 7521, I_PSIGNW = 7504, I_PSLLD = 7024,
I_PSLLDQ = 9847, I_PSLLQ = 7039, I_PSLLW = 7009, I_PSRAD = 6710, I_PSRAW = 6695,
I_PSRLD = 6451, I_PSRLDQ = 9830, I_PSRLQ = 6466, I_PSRLW = 6436, I_PSUBB = 7144,
I_PSUBD = 7174, I_PSUBQ = 7189, I_PSUBSB = 6868, I_PSUBSW = 6885, I_PSUBUSB = 6552,
I_PSUBUSW = 6571, I_PSUBW = 7159, I_PSWAPD = 2070, I_PTEST = 7629, I_PUNPCKHBW = 3780,
I_PUNPCKHDQ = 3826, I_PUNPCKHQDQ = 3895, I_PUNPCKHWD = 3803, I_PUNPCKLBW = 3612,
I_PUNPCKLDQ = 3658, I_PUNPCKLQDQ = 3870, I_PUNPCKLWD = 3635, I_PUSH = 16,
I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 6981, I_RCL = 977, I_RCPPS = 2953, I_RCPSS = 2960,
I_RCR = 982, I_RDFSBASE = 9882, I_RDGSBASE = 9912, I_RDMSR = 600, I_RDPMC = 607,
I_RDRAND = 9980, I_RDTSC = 593, I_RDTSCP = 1864, I_RET = 325, I_RETF = 354,
I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9296, I_ROUNDPS = 9277, I_ROUNDSD = 9334,
I_ROUNDSS = 9315, I_RSM = 882, I_RSQRTPS = 2915, I_RSQRTSS = 2924, I_SAHF = 283,
I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807,
I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839,
I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793,
I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4321, I_SGDT = 1675,
I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6336, I_SHUFPS = 6328,
I_SIDT = 1681, I_SKINIT = 1839, I_SLDT = 1641, I_SMSW = 1699, I_SQRTPD = 2855,
I_SQRTPS = 2847, I_SQRTSD = 2871, I_SQRTSS = 2863, I_STC = 497, I_STD = 517,
I_STGI = 1827, I_STI = 507, I_STMXCSR = 9951, I_STOS = 307, I_STR = 1647, I_SUB = 51,
I_SUBPD = 3379, I_SUBPS = 3372, I_SUBSD = 3393, I_SUBSS = 3386, I_SWAPGS = 1856,
I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206,
I_TZCNT = 4351, I_UCOMISD = 2742, I_UCOMISS = 2733, I_UD2 = 569, I_UNPCKHPD = 2296,
I_UNPCKHPS = 2286, I_UNPCKLPD = 2254, I_UNPCKLPS = 2244, I_VADDPD = 3139,
I_VADDPS = 3131, I_VADDSD = 3155, I_VADDSS = 3147, I_VADDSUBPD = 6414, I_VADDSUBPS = 6425,
I_VAESDEC = 9217, I_VAESDECLAST = 9238, I_VAESENC = 9175, I_VAESENCLAST = 9196,
I_VAESIMC = 9158, I_VAESKEYGENASSIST = 9812, I_VANDNPD = 3038, I_VANDNPS = 3029,
I_VANDPD = 3005, I_VANDPS = 2997, I_VBLENDPD = 9381, I_VBLENDPS = 9362, I_VBLENDVPD = 9681,
I_VBLENDVPS = 9670, I_VBROADCASTF128 = 7672, I_VBROADCASTSD = 7658, I_VBROADCASTSS = 7644,
I_VCMPEQPD = 5088, I_VCMPEQPS = 4686, I_VCMPEQSD = 5892, I_VCMPEQSS = 5490,
I_VCMPEQ_OSPD = 5269, I_VCMPEQ_OSPS = 4867, I_VCMPEQ_OSSD = 6073, I_VCMPEQ_OSSS = 5671,
I_VCMPEQ_UQPD = 5175, I_VCMPEQ_UQPS = 4773, I_VCMPEQ_UQSD = 5979, I_VCMPEQ_UQSS = 5577,
I_VCMPEQ_USPD = 5378, I_VCMPEQ_USPS = 4976, I_VCMPEQ_USSD = 6182, I_VCMPEQ_USSS = 5780,
I_VCMPFALSEPD = 5210, I_VCMPFALSEPS = 4808, I_VCMPFALSESD = 6014, I_VCMPFALSESS = 5612,
I_VCMPFALSE_OSPD = 5419, I_VCMPFALSE_OSPS = 5017, I_VCMPFALSE_OSSD = 6223,
I_VCMPFALSE_OSSS = 5821, I_VCMPGEPD = 5237, I_VCMPGEPS = 4835, I_VCMPGESD = 6041,
I_VCMPGESS = 5639, I_VCMPGE_OQPD = 5449, I_VCMPGE_OQPS = 5047, I_VCMPGE_OQSD = 6253,
I_VCMPGE_OQSS = 5851, I_VCMPGTPD = 5247, I_VCMPGTPS = 4845, I_VCMPGTSD = 6051,
I_VCMPGTSS = 5649, I_VCMPGT_OQPD = 5462, I_VCMPGT_OQPS = 5060, I_VCMPGT_OQSD = 6266,
I_VCMPGT_OQSS = 5864, I_VCMPLEPD = 5108, I_VCMPLEPS = 4706, I_VCMPLESD = 5912,
I_VCMPLESS = 5510, I_VCMPLE_OQPD = 5295, I_VCMPLE_OQPS = 4893, I_VCMPLE_OQSD = 6099,
I_VCMPLE_OQSS = 5697, I_VCMPLTPD = 5098, I_VCMPLTPS = 4696, I_VCMPLTSD = 5902,
I_VCMPLTSS = 5500, I_VCMPLT_OQPD = 5282, I_VCMPLT_OQPS = 4880, I_VCMPLT_OQSD = 6086,
I_VCMPLT_OQSS = 5684, I_VCMPNEQPD = 5131, I_VCMPNEQPS = 4729, I_VCMPNEQSD = 5935,
I_VCMPNEQSS = 5533, I_VCMPNEQ_OQPD = 5223, I_VCMPNEQ_OQPS = 4821, I_VCMPNEQ_OQSD = 6027,
I_VCMPNEQ_OQSS = 5625, I_VCMPNEQ_OSPD = 5435, I_VCMPNEQ_OSPS = 5033, I_VCMPNEQ_OSSD = 6239,
I_VCMPNEQ_OSSS = 5837, I_VCMPNEQ_USPD = 5323, I_VCMPNEQ_USPS = 4921, I_VCMPNEQ_USSD = 6127,
I_VCMPNEQ_USSS = 5725, I_VCMPNGEPD = 5188, I_VCMPNGEPS = 4786, I_VCMPNGESD = 5992,
I_VCMPNGESS = 5590, I_VCMPNGE_UQPD = 5391, I_VCMPNGE_UQPS = 4989, I_VCMPNGE_UQSD = 6195,
I_VCMPNGE_UQSS = 5793, I_VCMPNGTPD = 5199, I_VCMPNGTPS = 4797, I_VCMPNGTSD = 6003,
I_VCMPNGTSS = 5601, I_VCMPNGT_UQPD = 5405, I_VCMPNGT_UQPS = 5003, I_VCMPNGT_UQSD = 6209,
I_VCMPNGT_UQSS = 5807, I_VCMPNLEPD = 5153, I_VCMPNLEPS = 4751, I_VCMPNLESD = 5957,
I_VCMPNLESS = 5555, I_VCMPNLE_UQPD = 5351, I_VCMPNLE_UQPS = 4949, I_VCMPNLE_UQSD = 6155,
I_VCMPNLE_UQSS = 5753, I_VCMPNLTPD = 5142, I_VCMPNLTPS = 4740, I_VCMPNLTSD = 5946,
I_VCMPNLTSS = 5544, I_VCMPNLT_UQPD = 5337, I_VCMPNLT_UQPS = 4935, I_VCMPNLT_UQSD = 6141,
I_VCMPNLT_UQSS = 5739, I_VCMPORDPD = 5164, I_VCMPORDPS = 4762, I_VCMPORDSD = 5968,
I_VCMPORDSS = 5566, I_VCMPORD_SPD = 5365, I_VCMPORD_SPS = 4963, I_VCMPORD_SSD = 6169,
I_VCMPORD_SSS = 5767, I_VCMPTRUEPD = 5257, I_VCMPTRUEPS = 4855, I_VCMPTRUESD = 6061,
I_VCMPTRUESS = 5659, I_VCMPTRUE_USPD = 5475, I_VCMPTRUE_USPS = 5073, I_VCMPTRUE_USSD = 6279,
I_VCMPTRUE_USSS = 5877, I_VCMPUNORDPD = 5118, I_VCMPUNORDPS = 4716, I_VCMPUNORDSD = 5922,
I_VCMPUNORDSS = 5520, I_VCMPUNORD_SPD = 5308, I_VCMPUNORD_SPS = 4906, I_VCMPUNORD_SSD = 6112,
I_VCMPUNORD_SSS = 5710, I_VCOMISD = 2796, I_VCOMISS = 2787, I_VCVTDQ2PD = 6819,
I_VCVTDQ2PS = 3338, I_VCVTPD2DQ = 6830, I_VCVTPD2PS = 3274, I_VCVTPS2DQ = 3349,
I_VCVTPS2PD = 3263, I_VCVTSD2SI = 2722, I_VCVTSD2SS = 3296, I_VCVTSI2SD = 2536,
I_VCVTSI2SS = 2525, I_VCVTSS2SD = 3285, I_VCVTSS2SI = 2711, I_VCVTTPD2DQ = 6807,
I_VCVTTPS2DQ = 3360, I_VCVTTSD2SI = 2659, I_VCVTTSS2SI = 2647, I_VDIVPD = 3528,
I_VDIVPS = 3520, I_VDIVSD = 3544, I_VDIVSS = 3536, I_VDPPD = 9621, I_VDPPS = 9608,
I_VERR = 1663, I_VERW = 1669, I_VEXTRACTF128 = 9516, I_VEXTRACTPS = 9491,
I_VFMADD132PD = 8387, I_VFMADD132PS = 8374, I_VFMADD132SD = 8413, I_VFMADD132SS = 8400,
I_VFMADD213PD = 8667, I_VFMADD213PS = 8654, I_VFMADD213SD = 8693, I_VFMADD213SS = 8680,
I_VFMADD231PD = 8947, I_VFMADD231PS = 8934, I_VFMADD231SD = 8973, I_VFMADD231SS = 8960,
I_VFMADDSUB132PD = 8326, I_VFMADDSUB132PS = 8310, I_VFMADDSUB213PD = 8606,
I_VFMADDSUB213PS = 8590, I_VFMADDSUB231PD = 8886, I_VFMADDSUB231PS = 8870,
I_VFMSUB132PD = 8439, I_VFMSUB132PS = 8426, I_VFMSUB132SD = 8465, I_VFMSUB132SS = 8452,
I_VFMSUB213PD = 8719, I_VFMSUB213PS = 8706, I_VFMSUB213SD = 8745, I_VFMSUB213SS = 8732,
I_VFMSUB231PD = 8999, I_VFMSUB231PS = 8986, I_VFMSUB231SD = 9025, I_VFMSUB231SS = 9012,
I_VFMSUBADD132PD = 8358, I_VFMSUBADD132PS = 8342, I_VFMSUBADD213PD = 8638,
I_VFMSUBADD213PS = 8622, I_VFMSUBADD231PD = 8918, I_VFMSUBADD231PS = 8902,
I_VFNMADD132PD = 8492, I_VFNMADD132PS = 8478, I_VFNMADD132SD = 8520, I_VFNMADD132SS = 8506,
I_VFNMADD213PD = 8772, I_VFNMADD213PS = 8758, I_VFNMADD213SD = 8800, I_VFNMADD213SS = 8786,
I_VFNMADD231PD = 9052, I_VFNMADD231PS = 9038, I_VFNMADD231SD = 9080, I_VFNMADD231SS = 9066,
I_VFNMSUB132PD = 8548, I_VFNMSUB132PS = 8534, I_VFNMSUB132SD = 8576, I_VFNMSUB132SS = 8562,
I_VFNMSUB213PD = 8828, I_VFNMSUB213PS = 8814, I_VFNMSUB213SD = 8856, I_VFNMSUB213SS = 8842,
I_VFNMSUB231PD = 9108, I_VFNMSUB231PS = 9094, I_VFNMSUB231SD = 9136, I_VFNMSUB231SS = 9122,
I_VHADDPD = 4197, I_VHADDPS = 4206, I_VHSUBPD = 4231, I_VHSUBPS = 4240, I_VINSERTF128 = 9503,
I_VINSERTPS = 9557, I_VLDDQU = 7001, I_VLDMXCSR = 9941, I_VMASKMOVDQU = 7131,
I_VMASKMOVPD = 7949, I_VMASKMOVPS = 7937, I_VMAXPD = 3588, I_VMAXPS = 3580,
I_VMAXSD = 3604, I_VMAXSS = 3596, I_VMCALL = 1719, I_VMCLEAR = 9997, I_VMFUNC = 1787,
I_VMINPD = 3468, I_VMINPS = 3460, I_VMINSD = 3484, I_VMINSS = 3476, I_VMLAUNCH = 1727,
I_VMLOAD = 1811, I_VMMCALL = 1802, I_VMOVAPD = 2476, I_VMOVAPS = 2467, I_VMOVD = 3932,
I_VMOVDDUP = 2234, I_VMOVDQA = 3962, I_VMOVDQU = 3971, I_VMOVHLPS = 2195,
I_VMOVHPD = 2382, I_VMOVHPS = 2373, I_VMOVLHPS = 2363, I_VMOVLPD = 2214, I_VMOVLPS = 2205,
I_VMOVMSKPD = 2836, I_VMOVMSKPS = 2825, I_VMOVNTDQ = 6858, I_VMOVNTDQA = 7905,
I_VMOVNTPD = 2593, I_VMOVNTPS = 2583, I_VMOVQ = 3939, I_VMOVSD = 2143, I_VMOVSHDUP = 2391,
I_VMOVSLDUP = 2223, I_VMOVSS = 2135, I_VMOVUPD = 2126, I_VMOVUPS = 2117, I_VMPSADBW = 9637,
I_VMPTRLD = 9988, I_VMPTRST = 6385, I_VMREAD = 4128, I_VMRESUME = 1737, I_VMRUN = 1795,
I_VMSAVE = 1819, I_VMULPD = 3199, I_VMULPS = 3191, I_VMULSD = 3215, I_VMULSS = 3207,
I_VMWRITE = 4152, I_VMXOFF = 1747, I_VMXON = 10006, I_VORPD = 3066, I_VORPS = 3059,
I_VPABSB = 7695, I_VPABSD = 7725, I_VPABSW = 7710, I_VPACKSSDW = 3859, I_VPACKSSWB = 3691,
I_VPACKUSDW = 7926, I_VPACKUSWB = 3769, I_VPADDB = 7211, I_VPADDD = 7241,
I_VPADDQ = 6488, I_VPADDSB = 6938, I_VPADDSW = 6955, I_VPADDUSW = 6629, I_VPADDW = 7226,
I_VPALIGNR = 9419, I_VPAND = 6613, I_VPANDN = 6672, I_VPAVGB = 6687, I_VPAVGW = 6732,
I_VPBLENDVB = 9692, I_VPBLENDW = 9400, I_VPCLMULQDQ = 9658, I_VPCMPEQB = 4052,
I_VPCMPEQD = 4090, I_VPCMPEQQ = 7885, I_VPCMPEQW = 4071, I_VPCMPESTRI = 9737,
I_VPCMPESTRM = 9714, I_VPCMPGTB = 3711, I_VPCMPGTD = 3749, I_VPCMPGTQ = 8096,
I_VPCMPGTW = 3730, I_VPCMPISTRI = 9783, I_VPCMPISTRM = 9760, I_VPERM2F128 = 9265,
I_VPERMILPD = 7570, I_VPERMILPS = 7559, I_VPEXTRB = 9437, I_VPEXTRD = 9462,
I_VPEXTRQ = 9471, I_VPEXTRW = 6319, I_VPHADDD = 7383, I_VPHADDSW = 7401, I_VPHADDW = 7366,
I_VPHMINPOSUW = 8271, I_VPHSUBD = 7459, I_VPHSUBSW = 7477, I_VPHSUBW = 7442,
I_VPINSRB = 9538, I_VPINSRD = 9584, I_VPINSRQ = 9593, I_VPINSRW = 6302, I_VPMADDUBSW = 7422,
I_VPMADDWD = 7082, I_VPMAXSB = 8182, I_VPMAXSD = 8199, I_VPMAXSW = 6972, I_VPMAXUB = 6656,
I_VPMAXUD = 8233, I_VPMAXUW = 8216, I_VPMINSB = 8114, I_VPMINSD = 8131, I_VPMINSW = 6910,
I_VPMINUB = 6598, I_VPMINUD = 8165, I_VPMINUW = 8148, I_VPMOVMSKB = 6541,
I_VPMOVSXBD = 7764, I_VPMOVSXBQ = 7785, I_VPMOVSXBW = 7743, I_VPMOVSXDQ = 7848,
I_VPMOVSXWD = 7806, I_VPMOVSXWQ = 7827, I_VPMOVZXBD = 7992, I_VPMOVZXBQ = 8013,
I_VPMOVZXBW = 7971, I_VPMOVZXDQ = 8076, I_VPMOVZXWD = 8034, I_VPMOVZXWQ = 8055,
I_VPMULDQ = 7867, I_VPMULHRSW = 7548, I_VPMULHUW = 6749, I_VPMULHW = 6767,
I_VPMULLD = 8250, I_VPMULLW = 6504, I_VPMULUDQ = 7063, I_VPOR = 6924, I_VPSADBW = 7100,
I_VPSHUFB = 7349, I_VPSHUFD = 4014, I_VPSHUFHW = 4023, I_VPSHUFLW = 4033,
I_VPSIGNB = 7495, I_VPSIGND = 7529, I_VPSIGNW = 7512, I_VPSLLD = 7031, I_VPSLLDQ = 9855,
I_VPSLLQ = 7046, I_VPSLLW = 7016, I_VPSRAD = 6717, I_VPSRAW = 6702, I_VPSRLD = 6458,
I_VPSRLDQ = 9838, I_VPSRLQ = 6473, I_VPSRLW = 6443, I_VPSUBB = 7151, I_VPSUBD = 7181,
I_VPSUBQ = 7196, I_VPSUBSB = 6876, I_VPSUBSW = 6893, I_VPSUBUSB = 6561, I_VPSUBUSW = 6580,
I_VPSUBW = 7166, I_VPTEST = 7636, I_VPUNPCKHBW = 3791, I_VPUNPCKHDQ = 3837,
I_VPUNPCKHQDQ = 3907, I_VPUNPCKHWD = 3814, I_VPUNPCKLBW = 3623, I_VPUNPCKLDQ = 3669,
I_VPUNPCKLQDQ = 3882, I_VPUNPCKLWD = 3646, I_VPXOR = 6987, I_VRCPPS = 2967,
I_VRCPSS = 2975, I_VROUNDPD = 9305, I_VROUNDPS = 9286, I_VROUNDSD = 9343,
I_VROUNDSS = 9324, I_VRSQRTPS = 2933, I_VRSQRTSS = 2943, I_VSHUFPD = 6353,
I_VSHUFPS = 6344, I_VSQRTPD = 2888, I_VSQRTPS = 2879, I_VSQRTSD = 2906, I_VSQRTSS = 2897,
I_VSTMXCSR = 9970, I_VSUBPD = 3408, I_VSUBPS = 3400, I_VSUBSD = 3424, I_VSUBSS = 3416,
I_VTESTPD = 7590, I_VTESTPS = 7581, I_VUCOMISD = 2761, I_VUCOMISS = 2751,
I_VUNPCKHPD = 2317, I_VUNPCKHPS = 2306, I_VUNPCKLPD = 2275, I_VUNPCKLPS = 2264,
I_VXORPD = 3095, I_VXORPS = 3087, I_VZEROALL = 4118, I_VZEROUPPER = 4106,
I_WAIT = 10028, I_WBINVD = 561, I_WRFSBASE = 9931, I_WRGSBASE = 9960, I_WRMSR = 586,
I_XADD = 946, I_XCHG = 212, I_XGETBV = 1771, I_XLAT = 400, I_XOR = 61, I_XORPD = 3080,
I_XORPS = 3073, I_XRSTOR = 4273, I_XRSTOR64 = 4281, I_XSAVE = 4249, I_XSAVE64 = 4256,
I_XSAVEOPT = 4299, I_XSAVEOPT64 = 4309, I_XSETBV = 1779
} _InstructionType;
typedef enum {
R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15,
R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D,
R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W,
R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B,
R_SPL, R_BPL, R_SIL, R_DIL,
R_ES, R_CS, R_SS, R_DS, R_FS, R_GS,
R_RIP,
R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7,
R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15,
R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15,
R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8,
R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7
} _RegisterType;
#endif /* MNEMONICS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
/*
operands.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OPERANDS_H
#define OPERANDS_H
#include "config.h"
#include "decoder.h"
#include "prefix.h"
#include "instructions.h"
extern uint16_t _REGISTERTORCLASS[];
int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii,
_iflags instFlags, _OpType type, _OperandNumberType opNum,
unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz,
_DecodeType effAdrSz, int* lockableInstruction);
#endif /* OPERANDS_H */

View File

@ -0,0 +1,380 @@
/*
prefix.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "prefix.h"
#include "x86defs.h"
#include "instructions.h"
#include "mnemonics.h"
/*
* The main purpose of this module is to keep track of all kind of prefixes a single instruction may have.
* The problem is that a single instruction may have up to six different prefix-types.
* That's why I have to detect such cases and drop those excess prefixes.
*/
int prefixes_is_valid(unsigned int ch, _DecodeType dt)
{
switch (ch) {
/* for i in xrange(0x40, 0x50): print "case 0x%2x:" % i */
case 0x40: /* REX: */
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f: return (dt == Decode64Bits);
case PREFIX_LOCK: return TRUE;
case PREFIX_REPNZ: return TRUE;
case PREFIX_REP: return TRUE;
case PREFIX_CS: return TRUE;
case PREFIX_SS: return TRUE;
case PREFIX_DS: return TRUE;
case PREFIX_ES: return TRUE;
case PREFIX_FS: return TRUE;
case PREFIX_GS: return TRUE;
case PREFIX_OP_SIZE: return TRUE;
case PREFIX_ADDR_SIZE: return TRUE;
/* The VEXs might be false positives, the decode_perfixes will determine for sure. */
case PREFIX_VEX2b: /* VEX is supported for all modes, because 16 bits Pmode is included. */
case PREFIX_VEX3b: return TRUE;
}
return FALSE;
}
/* Ignore a specific prefix type. */
void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi)
{
/*
* If that type of prefix appeared already, set the bit of that *former* prefix.
* Anyway, set the new index of that prefix type to the current index, so next time we know its position.
*/
if (ps->pfxIndexer[pi] != PFXIDX_NONE) ps->unusedPrefixesMask |= (1 << ps->pfxIndexer[pi]);
}
/* Ignore all prefix. */
void prefixes_ignore_all(_PrefixState* ps)
{
int i;
for (i = 0; i < PFXIDX_MAX; i++)
prefixes_ignore(ps, i);
}
/* Calculates which prefixes weren't used and accordingly sets the bits in the unusedPrefixesMask. */
uint16_t prefixes_set_unused_mask(_PrefixState* ps)
{
/*
* The decodedPrefixes represents the prefixes that were *read* from the binary stream for the instruction.
* The usedPrefixes represents the prefixes that were actually used by the instruction in the *decode* phase.
* Xoring between the two will result in a 'diff' which returns the prefixes that were read
* from the stream *and* that were never used in the actual decoding.
*
* Only one prefix per type can be set in decodedPrefixes from the stream.
* Therefore it's enough to check each type once and set the flag accordingly.
* That's why we had to book-keep each prefix type and its position.
* So now we know which bits we need to set exactly in the mask.
*/
_iflags unusedPrefixesDiff = ps->decodedPrefixes ^ ps->usedPrefixes;
/* Examine unused prefixes by type: */
/*
* About REX: it might be set in the diff although it was never in the stream itself.
* This is because the vrex is shared between VEX and REX and some places flag it as REX usage, while
* we were really decoding an AVX instruction.
* It's not a big problem, because the prefixes_ignore func will ignore it anyway,
* since it wasn't seen earlier. But it's important to know this.
*/
if (unusedPrefixesDiff & INST_PRE_REX) prefixes_ignore(ps, PFXIDX_REX);
if (unusedPrefixesDiff & INST_PRE_SEGOVRD_MASK) prefixes_ignore(ps, PFXIDX_SEG);
if (unusedPrefixesDiff & INST_PRE_LOKREP_MASK) prefixes_ignore(ps, PFXIDX_LOREP);
if (unusedPrefixesDiff & INST_PRE_OP_SIZE) prefixes_ignore(ps, PFXIDX_OP_SIZE);
if (unusedPrefixesDiff & INST_PRE_ADDR_SIZE) prefixes_ignore(ps, PFXIDX_ADRS);
/* If a VEX instruction was found, its prefix is considered as used, therefore no point for checking for it. */
return ps->unusedPrefixesMask;
}
/*
* Mark a prefix as unused, and bookkeep where we last saw this same type,
* because in the future we might want to disable it too.
*/
_INLINE_ void prefixes_track_unused(_PrefixState* ps, int index, _PrefixIndexer pi)
{
prefixes_ignore(ps, pi);
/* Book-keep the current index for this type. */
ps->pfxIndexer[pi] = index;
}
/*
* Read as many prefixes as possible, up to 15 bytes, and halt when we encounter non-prefix byte.
* This algorithm tries to imitate a real processor, where the same prefix can appear a few times, etc.
* The tiny complexity is that we want to know when a prefix was superfluous and mark any copy of it as unused.
* Note that the last prefix of its type will be considered as used, and all the others (of same type) before it as unused.
*/
void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt)
{
int index, done;
uint8_t vex;
/*
* First thing to do, scan for prefixes, there are six types of prefixes.
* There may be up to six prefixes before a single instruction, not the same type, no special order,
* except REX/VEX must precede immediately the first opcode byte.
* BTW - This is the reason why I didn't make the REP prefixes part of the instructions (STOS/SCAS/etc).
*
* Another thing, the instruction maximum size is 15 bytes, thus if we read more than 15 bytes, we will halt.
*
* We attach all prefixes to the next instruction, there might be two or more occurrences from the same prefix.
* Also, since VEX can be allowed only once we will test it separately.
*/
for (index = 0, done = FALSE;
(codeLen > 0) && (code - ps->start < INST_MAXIMUM_SIZE);
code++, codeLen--, index++) {
/*
NOTE: AMD treat lock/rep as two different groups... But I am based on Intel.
- Lock and Repeat:
- 0xF0 LOCK
- 0xF2 REPNE/REPNZ
- 0xF3 - REP/REPE/REPZ
- Segment Override:
- 0x2E - CS
- 0x36 - SS
- 0x3E - DS
- 0x26 - ES
- 0x64 - FS
- 0x65 - GS
- Operand-Size Override: 0x66, switching default size.
- Address-Size Override: 0x67, switching default size.
64 Bits:
- REX: 0x40 - 0x4f, extends register access.
- 2 Bytes VEX: 0xc4
- 3 Bytes VEX: 0xc5
32 Bits:
- 2 Bytes VEX: 0xc4 11xx-xxxx
- 3 Bytes VEX: 0xc5 11xx-xxxx
*/
/* Examine what type of prefix we got. */
switch (*code)
{
/* REX type, 64 bits decoding mode only: */
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
if (dt == Decode64Bits) {
ps->decodedPrefixes |= INST_PRE_REX;
ps->vrex = *code & 0xf; /* Keep only BXRW. */
ps->rexPos = code;
ps->prefixExtType = PET_REX;
prefixes_track_unused(ps, index, PFXIDX_REX);
} else done = TRUE; /* If we are not in 64 bits mode, it's an instruction, then halt. */
break;
/* LOCK and REPx type: */
case PREFIX_LOCK:
ps->decodedPrefixes |= INST_PRE_LOCK;
prefixes_track_unused(ps, index, PFXIDX_LOREP);
break;
case PREFIX_REPNZ:
ps->decodedPrefixes |= INST_PRE_REPNZ;
prefixes_track_unused(ps, index, PFXIDX_LOREP);
break;
case PREFIX_REP:
ps->decodedPrefixes |= INST_PRE_REP;
prefixes_track_unused(ps, index, PFXIDX_LOREP);
break;
/* Seg Overide type: */
case PREFIX_CS:
ps->decodedPrefixes |= INST_PRE_CS;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
case PREFIX_SS:
ps->decodedPrefixes |= INST_PRE_SS;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
case PREFIX_DS:
ps->decodedPrefixes |= INST_PRE_DS;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
case PREFIX_ES:
ps->decodedPrefixes |= INST_PRE_ES;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
case PREFIX_FS:
ps->decodedPrefixes |= INST_PRE_FS;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
case PREFIX_GS:
ps->decodedPrefixes |= INST_PRE_GS;
prefixes_track_unused(ps, index, PFXIDX_SEG);
break;
/* Op Size type: */
case PREFIX_OP_SIZE:
ps->decodedPrefixes |= INST_PRE_OP_SIZE;
prefixes_track_unused(ps, index, PFXIDX_OP_SIZE);
break;
/* Addr Size type: */
case PREFIX_ADDR_SIZE:
ps->decodedPrefixes |= INST_PRE_ADDR_SIZE;
prefixes_track_unused(ps, index, PFXIDX_ADRS);
break;
/* Non-prefix byte now, so break 2. */
default: done = TRUE; break;
}
if (done) break;
}
/* 2 Bytes VEX: */
if ((codeLen >= 2) &&
(*code == PREFIX_VEX2b) &&
((code - ps->start) <= INST_MAXIMUM_SIZE - 2)) {
/*
* In 32 bits the second byte has to be in the special range of Mod=11.
* Otherwise it might be a normal LDS instruction.
*/
if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) {
ps->vexPos = code + 1;
ps->decodedPrefixes |= INST_PRE_VEX;
ps->prefixExtType = PET_VEX2BYTES;
/*
* VEX 1 byte bits:
* |7-6--3-2-10|
* |R|vvvv|L|pp|
* |-----------|
*/
/* -- Convert from VEX prefix to VREX flags -- */
vex = *ps->vexPos;
if (~vex & 0x80 && dt == Decode64Bits) ps->vrex |= PREFIX_EX_R; /* Convert VEX.R. */
if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */
code += 2;
}
}
/* 3 Bytes VEX: */
if ((codeLen >= 3) &&
(*code == PREFIX_VEX3b) &&
((code - ps->start) <= INST_MAXIMUM_SIZE - 3) &&
(~ps->decodedPrefixes & INST_PRE_VEX)) {
/*
* In 32 bits the second byte has to be in the special range of Mod=11.
* Otherwise it might be a normal LES instruction.
* And we don't care now about the 3rd byte.
*/
if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) {
ps->vexPos = code + 1;
ps->decodedPrefixes |= INST_PRE_VEX;
ps->prefixExtType = PET_VEX3BYTES;
/*
* VEX first and second bytes:
* |7-6-5-4----0| |7-6--3-2-10|
* |R|X|B|m-mmmm| |W|vvvv|L|pp|
* |------------| |-----------|
*/
/* -- Convert from VEX prefix to VREX flags -- */
vex = *ps->vexPos;
ps->vrex |= ((~vex >> 5) & 0x7); /* Shift and invert VEX.R/X/B to their place */
vex = *(ps->vexPos + 1);
if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */
if (vex & 0x80) ps->vrex |= PREFIX_EX_W; /* Convert VEX.W. */
/* Clear some flags if the mode isn't 64 bits. */
if (dt != Decode64Bits) ps->vrex &= ~(PREFIX_EX_B | PREFIX_EX_X | PREFIX_EX_R | PREFIX_EX_W);
code += 3;
}
}
/*
* Save last byte scanned address, so the decoder could keep on scanning from this point and on and on and on.
* In addition the decoder is able to know that the last byte could lead to MMX/SSE instructions (preceding REX if exists).
*/
ps->last = code; /* ps->last points to an opcode byte. */
}
/*
* For every memory-indirection operand we want to set its corresponding default segment.
* If the segment is being overrided, we need to see whether we use it or not.
* We will use it only if it's not the default one already.
*/
void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di)
{
_iflags flags = 0;
if (dt == Decode64Bits) flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK64;
else flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK;
if ((flags == 0) || (flags == defaultSeg)) {
flags = defaultSeg;
di->segment |= SEGMENT_DEFAULT;
} else if (flags != defaultSeg) {
/* Use it only if it's non-default segment. */
ps->usedPrefixes |= flags;
}
/* ASSERT: R_XX must be below 128. */
switch (flags)
{
case INST_PRE_ES: di->segment |= R_ES; break;
case INST_PRE_CS: di->segment |= R_CS; break;
case INST_PRE_SS: di->segment |= R_SS; break;
case INST_PRE_DS: di->segment |= R_DS; break;
case INST_PRE_FS: di->segment |= R_FS; break;
case INST_PRE_GS: di->segment |= R_GS; break;
}
/* If it's one of the CS,SS,DS,ES and the mode is 64 bits, set segment it to none, since it's ignored. */
if ((dt == Decode64Bits) && (flags & INST_PRE_SEGOVRD_MASK32)) di->segment = R_NONE;
}

View File

@ -0,0 +1,76 @@
/*
prefix.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef PREFIX_H
#define PREFIX_H
#include "config.h"
#include "decoder.h"
/* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */
typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType;
/* Specifies an index into a table of prefixes by their type. */
typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer;
/*
* This holds the prefixes state for the current instruction we decode.
* decodedPrefixes includes all specific prefixes that the instruction got.
* start is a pointer to the first prefix to take into account.
* last is a pointer to the last byte we scanned.
* Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where.
*/
typedef struct {
_iflags decodedPrefixes, usedPrefixes;
const uint8_t *start, *last, *vexPos, *rexPos;
_PrefixExtType prefixExtType;
uint16_t unusedPrefixesMask;
/* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */
int isOpSizeMandatory;
/* If VEX prefix is used, store the VEX.vvvv field. */
unsigned int vexV;
/* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */
unsigned int vrex;
/* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */
/* Holds the offset to the prefix byte by its type. */
int pfxIndexer[PFXIDX_MAX];
} _PrefixState;
/*
* Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz).
* REX is the fifth prefix type, this time I'm based on AMD64.
* VEX is the 6th, though it can't be repeated.
*/
#define MAX_PREFIXES (5)
int prefixes_is_valid(unsigned int ch, _DecodeType dt);
void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi);
void prefixes_ignore_all(_PrefixState* ps);
uint16_t prefixes_set_unused_mask(_PrefixState* ps);
void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt);
void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di);
#endif /* PREFIX_H */

View File

@ -0,0 +1,184 @@
/*
textdefs.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "textdefs.h"
#ifndef DISTORM_LIGHT
static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
#define NIBBLE_TO_CHR Nibble2ChrTable[t]
void _FASTCALL_ str_hex_b(_WString* s, unsigned int x)
{
/*
* def prebuilt():
* s = ""
* for i in xrange(256):
* if ((i % 0x10) == 0):
* s += "\r\n"
* s += "\"%02x\", " % (i)
* return s
*/
static int8_t TextBTable[256][3] = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"
};
/*
* Fixed length of 3 including null terminate character.
*/
memcpy(&s->p[s->length], TextBTable[x & 255], 3);
s->length += 2;
}
void _FASTCALL_ str_code_hb(_WString* s, unsigned int x)
{
static int8_t TextHBTable[256][5] = {
/*
* def prebuilt():
* s = ""
* for i in xrange(256):
* if ((i % 0x10) == 0):
* s += "\r\n"
* s += "\"0x%x\", " % (i)
* return s
*/
"0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf",
"0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f",
"0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26", "0x27", "0x28", "0x29", "0x2a", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f",
"0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f",
"0x40", "0x41", "0x42", "0x43", "0x44", "0x45", "0x46", "0x47", "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f",
"0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f",
"0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", "0x68", "0x69", "0x6a", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f",
"0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f",
"0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f",
"0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f",
"0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf",
"0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf",
"0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf",
"0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf",
"0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef",
"0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff"
};
if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */
memcpy(&s->p[s->length], TextHBTable[x & 255], 4);
s->length += 3;
} else { /* >= 0x10 has a fixed length of 5 including null terminate. */
memcpy(&s->p[s->length], TextHBTable[x & 255], 5);
s->length += 4;
}
}
void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x)
{
int8_t* buf;
int i = 0, shift = 0;
unsigned int t = 0;
buf = (int8_t*)&s->p[s->length];
buf[0] = '0';
buf[1] = 'x';
buf += 2;
for (shift = 28; shift != 0; shift -= 4) {
t = (x >> shift) & 0xf;
if (i | t) buf[i++] = NIBBLE_TO_CHR;
}
t = x & 0xf;
buf[i++] = NIBBLE_TO_CHR;
s->length += i + 2;
buf[i] = '\0';
}
void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8])
{
int8_t* buf;
int i = 0, shift = 0;
uint32_t x = RULONG(&src[sizeof(int32_t)]);
int t;
buf = (int8_t*)&s->p[s->length];
buf[0] = '0';
buf[1] = 'x';
buf += 2;
for (shift = 28; shift != -4; shift -= 4) {
t = (x >> shift) & 0xf;
if (i | t) buf[i++] = NIBBLE_TO_CHR;
}
x = RULONG(src);
for (shift = 28; shift != 0; shift -= 4) {
t = (x >> shift) & 0xf;
if (i | t) buf[i++] = NIBBLE_TO_CHR;
}
t = x & 0xf;
buf[i++] = NIBBLE_TO_CHR;
s->length += i + 2;
buf[i] = '\0';
}
#ifdef SUPPORT_64BIT_OFFSET
void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x)
{
int8_t* buf;
int i = 0, shift = 0;
OFFSET_INTEGER t = 0;
buf = (int8_t*)&s->p[s->length];
buf[0] = '0';
buf[1] = 'x';
buf += 2;
for (shift = 60; shift != 0; shift -= 4) {
t = (x >> shift) & 0xf;
if (i | t) buf[i++] = NIBBLE_TO_CHR;
}
t = x & 0xf;
buf[i++] = NIBBLE_TO_CHR;
s->length += i + 2;
buf[i] = '\0';
}
#endif /* SUPPORT_64BIT_OFFSET */
#endif /* DISTORM_LIGHT */

View File

@ -0,0 +1,71 @@
/*
textdefs.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef TEXTDEFS_H
#define TEXTDEFS_H
#include "config.h"
#include "wstring.h"
#ifndef DISTORM_LIGHT
#define PLUS_DISP_CHR '+'
#define MINUS_DISP_CHR '-'
#define OPEN_CHR '['
#define CLOSE_CHR ']'
#define SP_CHR ' '
#define SEG_OFF_CHR ':'
/*
Naming Convention:
* get - returns a pointer to a string.
* str - concatenates to string.
* hex - means the function is used for hex dump (number is padded to required size) - Little Endian output.
* code - means the function is used for disassembled instruction - Big Endian output.
* off - means the function is used for 64bit offset - Big Endian output.
* h - '0x' in front of the string.
* b - byte
* dw - double word (can be used for word also)
* qw - quad word
* all numbers are in HEX.
*/
extern int8_t TextBTable[256][4];
void _FASTCALL_ str_hex_b(_WString* s, unsigned int x);
void _FASTCALL_ str_code_hb(_WString* s, unsigned int x);
void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x);
void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]);
#ifdef SUPPORT_64BIT_OFFSET
void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x);
#endif
#endif /* DISTORM_LIGHT */
#endif /* TEXTDEFS_H */

View File

@ -0,0 +1,59 @@
/*
wstring.c
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "wstring.h"
#ifndef DISTORM_LIGHT
void strclear_WS(_WString* s)
{
s->p[0] = '\0';
s->length = 0;
}
void chrcat_WS(_WString* s, uint8_t ch)
{
s->p[s->length] = ch;
s->p[s->length + 1] = '\0';
s->length += 1;
}
void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len)
{
s->length = len;
memcpy((int8_t*)s->p, buf, len + 1);
}
void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len)
{
memcpy((int8_t*)&s->p[s->length], buf, len + 1);
s->length += len;
}
void strcat_WS(_WString* s, const _WString* s2)
{
memcpy((int8_t*)&s->p[s->length], s2->p, s2->length + 1);
s->length += s2->length;
}
#endif /* DISTORM_LIGHT */

View File

@ -0,0 +1,47 @@
/*
wstring.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef WSTRING_H
#define WSTRING_H
#include "config.h"
#ifndef DISTORM_LIGHT
void strclear_WS(_WString* s);
void chrcat_WS(_WString* s, uint8_t ch);
void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len);
void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len);
void strcat_WS(_WString* s, const _WString* s2);
/*
* Warning, this macro should be used only when the compiler knows the size of string in advance!
* This macro is used in order to spare the call to strlen when the strings are known already.
* Note: sizeof includes NULL terminated character.
*/
#define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1)
#define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1)
#endif /* DISTORM_LIGHT */
#endif /* WSTRING_H */

View File

@ -0,0 +1,94 @@
/*
x86defs.h
diStorm3 - Powerful disassembler for X86/AMD64
http://ragestorm.net/distorm/
distorm at gmail dot com
Copyright (C) 2003-2012 Gil Dabah
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef X86DEFS_H
#define X86DEFS_H
#define SEG_REGS_MAX (6)
#define CREGS_MAX (9)
#define DREGS_MAX (8)
/* Maximum instruction size, including prefixes */
#define INST_MAXIMUM_SIZE (15)
/* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */
#define INST_CMP_MAX_RANGE (8)
/* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */
#define INST_VCMP_MAX_RANGE (32)
/* Wait instruction byte code. */
#define INST_WAIT_INDEX (0x9b)
/* Lea instruction byte code. */
#define INST_LEA_INDEX (0x8d)
/* NOP/XCHG instruction byte code. */
#define INST_NOP_INDEX (0x90)
/* ARPL/MOVSXD instruction byte code. */
#define INST_ARPL_INDEX (0x63)
/*
* Minimal MODR/M value of divided instructions.
* It's 0xc0, two MSBs set, which indicates a general purpose register is used too.
*/
#define INST_DIVIDED_MODRM (0xc0)
/* This is the escape byte value used for 3DNow! instructions. */
#define _3DNOW_ESCAPE_BYTE (0x0f)
#define PREFIX_LOCK (0xf0)
#define PREFIX_REPNZ (0xf2)
#define PREFIX_REP (0xf3)
#define PREFIX_CS (0x2e)
#define PREFIX_SS (0x36)
#define PREFIX_DS (0x3e)
#define PREFIX_ES (0x26)
#define PREFIX_FS (0x64)
#define PREFIX_GS (0x65)
#define PREFIX_OP_SIZE (0x66)
#define PREFIX_ADDR_SIZE (0x67)
#define PREFIX_VEX2b (0xc5)
#define PREFIX_VEX3b (0xc4)
/* REX prefix value range, 64 bits mode decoding only. */
#define PREFIX_REX_LOW (0x40)
#define PREFIX_REX_HI (0x4f)
/* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */
#define EX_GPR_BASE (8)
/* Mask for REX and VEX features: */
/* Base */
#define PREFIX_EX_B (1)
/* Index */
#define PREFIX_EX_X (2)
/* Register */
#define PREFIX_EX_R (4)
/* Operand Width */
#define PREFIX_EX_W (8)
/* Vector Lengh */
#define PREFIX_EX_L (0x10)
#endif /* X86DEFS_H */

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcproj", "{1461E901-4125-4CC8-ADBC-8ED146DCF048}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Debug|Win32.ActiveCfg = Debug|Win32
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Debug|Win32.Build.0 = Debug|Win32
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Debug|x64.ActiveCfg = Debug|x64
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Debug|x64.Build.0 = Debug|x64
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Release|Win32.ActiveCfg = Release|Win32
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Release|Win32.Build.0 = Release|Win32
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Release|x64.ActiveCfg = Release|x64
{1461E901-4125-4CC8-ADBC-8ED146DCF048}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Binary file not shown.

View File

@ -0,0 +1,543 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="dll"
ProjectGUID="{1461E901-4125-4CC8-ADBC-8ED146DCF048}"
RootNamespace="dll"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/dll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/dll.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib urlmon.lib ws2_32.lib wininet.lib"
OutputFile="./../openScript.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="./../../api_log.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug/api_log.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/dll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Debug/dll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/dll.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib urlmon.lib ws2_32.lib wininet.lib"
OutputFile="./../../api_log.x64.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="./../../api_log.x64.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug/api_log.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/dll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/dll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/dll.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib urlmon.lib ws2_32.lib"
OutputFile="./../openScript.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile=".\Release/api_log.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/api_log.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/dll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Release/dll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/dll.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib urlmon.lib ws2_32.lib"
OutputFile="./../../api_log.x64.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile=".\Release/api_log.x64.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/api_log.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/dll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="diStorm3.3"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath=".\diStorm3.3\config.h"
>
</File>
<File
RelativePath=".\diStorm3.3\decoder.c"
>
</File>
<File
RelativePath=".\diStorm3.3\decoder.h"
>
</File>
<File
RelativePath=".\diStorm3.3\distorm.c"
>
</File>
<File
RelativePath=".\diStorm3.3\distorm.h"
>
</File>
<File
RelativePath=".\diStorm3.3\instructions.c"
>
</File>
<File
RelativePath=".\diStorm3.3\instructions.h"
>
</File>
<File
RelativePath=".\diStorm3.3\insts.c"
>
</File>
<File
RelativePath=".\diStorm3.3\insts.h"
>
</File>
<File
RelativePath=".\diStorm3.3\mnemonics.c"
>
</File>
<File
RelativePath=".\diStorm3.3\mnemonics.h"
>
</File>
<File
RelativePath=".\diStorm3.3\operands.c"
>
</File>
<File
RelativePath=".\diStorm3.3\operands.h"
>
</File>
<File
RelativePath=".\diStorm3.3\prefix.c"
>
</File>
<File
RelativePath=".\diStorm3.3\prefix.h"
>
</File>
<File
RelativePath=".\diStorm3.3\textdefs.c"
>
</File>
<File
RelativePath=".\diStorm3.3\textdefs.h"
>
</File>
<File
RelativePath=".\diStorm3.3\wstring.c"
>
</File>
<File
RelativePath=".\diStorm3.3\wstring.h"
>
</File>
<File
RelativePath=".\diStorm3.3\x86defs.h"
>
</File>
</Filter>
<File
RelativePath="dll.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath=".\exports.def"
>
</File>
<File
RelativePath="main.h"
>
</File>
<File
RelativePath=".\NtHookEngine.cpp"
>
</File>
<File
RelativePath=".\NtHookEngine.h"
>
</File>
<File
RelativePath=".\vb_structs.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="9.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-F9V9H70"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Debug|x64"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-F9V9H70"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-F9V9H70"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|x64"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-F9V9H70"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,2 @@
EXPORT
NullSub

View File

@ -0,0 +1,80 @@
#include <intrin.h>
void msg(char);
void msgf(const char*, ...);
HWND hServer=0;
typedef struct{
int dwFlag;
int cbSize;
int lpData;
} cpyData;
void FindVBWindow(){
char *vbIDEClassName = "ThunderFormDC" ;
char *vbEXEClassName = "ThunderRT6FormDC" ;
char *vbWindowCaption = "injector" ;
hServer = FindWindowA( vbIDEClassName, vbWindowCaption );
if(hServer==0) hServer = FindWindowA( vbEXEClassName, vbWindowCaption );
}
int msg(char *Buffer){
char msgbuf[0x1001];
if(!IsWindow(hServer)) hServer=0;
if(hServer==0) FindVBWindow();
COPYDATASTRUCT cpStructData;
memset(&cpStructData,0, sizeof(struct tagCOPYDATASTRUCT )) ;
_snprintf(msgbuf, 0x1000, "%x,%x,%s", GetCurrentProcessId(), GetCurrentThreadId(), Buffer);
cpStructData.dwData = 3;
cpStructData.cbData = strlen(msgbuf) ;
cpStructData.lpData = (void*)msgbuf;
int ret = SendMessage(hServer, WM_COPYDATA, 0,(LPARAM)&cpStructData);
//if ret = trigger then do something special
return ret;
}
void msgf(const char *format, ...)
{
DWORD dwErr = GetLastError();
if(format){
char buf[1024];
va_list args;
va_start(args,format);
try{
_vsnprintf(buf,1024,format,args);
msg(buf);
}
catch(...){}
}
SetLastError(dwErr);
}
int* pPlus(int * p, int increment){
_asm{
mov eax, p
add eax, increment
}
}
int* pPlus(void * p, int increment){
_asm{
mov eax, p
add eax, increment
}
}

View File

@ -0,0 +1,90 @@
//slightly tweaked structures from vbParser by sysenter-eip
typedef struct {
DWORD lpObjectInfo;
DWORD dwReserved;
DWORD lpPublicBytes;
DWORD lpStaticBytes;
DWORD lpModulePublic;
DWORD lpModuleStatic;
DWORD lpszObjectName;
DWORD dwMethodCount;
DWORD lpMethodNames;
DWORD bStaticVars;
DWORD fObjectType;
DWORD dwNull;
} VBObject;
typedef struct {
DWORD lpHeapLink;
DWORD lpExecProj;
DWORD lpProjectInfo2;
DWORD dwReserved;
DWORD dwNull;
DWORD lpProjectObject;
UUID uuidObject;
WORD fCompileState;
WORD dwTotalObjects;
WORD dwCompiledObjects;
WORD dwObjectsInUse;
VBObject *ObjectArray;
DWORD fIdeFlag;
DWORD lpIdeData;
DWORD lpIdeData2;
DWORD lpszProjectName;
DWORD dwLcid;
DWORD dwLcid2;
DWORD lpIdeData3;
DWORD dwIdentifier;
} VB_ObjectTable;
typedef struct {
DWORD dwVersion;
VB_ObjectTable *ObjectTable;
DWORD dwNull;
DWORD lpCodeStart;
DWORD lpCodeEnd;
DWORD dwDataSize;
DWORD lpThreadSpace;
DWORD lpVbaSeh;
DWORD lpNativeCode;
WCHAR wsPrimitivePath[3];
WCHAR wsProjectPath[261];
DWORD lpExternalTable;
DWORD dwExternalCount;
} VB_ProjInfo;
typedef struct {
CHAR szVbMagic[4];
WORD wRuntimeBuild;
CHAR szLangDll[14];
CHAR szSecLangDll[14];
WORD wRuntimeRevision;
DWORD dwLCID;
DWORD dwSecLCID;
DWORD lpSubMain;
VB_ProjInfo *ProjectInfo;
DWORD fMdlIntCtls;
DWORD fMdlIntCtls2;
DWORD dwThreadFlags;
DWORD dwThreadCount;
WORD wFormCount;
WORD wExternalComponentCount;
DWORD dwThunkCount;
DWORD lpGuiTable;
DWORD lpExternalComponentTable;
DWORD lpComRegisterData;
DWORD bSZProjectDescription;
DWORD bSZProjectExeName;
DWORD bSZProjectHelpFile;
DWORD bSZProjectName;
} VBHeader;

Binary file not shown.

View File

@ -0,0 +1,520 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "CFileSystem2"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'Author: david zimmer <dzzie@yahoo.com>
'Site: http://sandsprite.com
'Revision 3 <- Incompatiable with all previous..simplified & streamlined
'
'Info: These are basically macros for VB's built in file processes
' this should streamline your code quite a bit and hopefully
' remove alot of redundant coding.
'
'Author: dzzie@yahoo.com
'Sight: http://www.geocities.com/dzzie
'Changes Jan 5 05
'GetFreeFileName - fixed periodic overflow in
'GetFolderFiles - Added recursive option
'CreateFolder - now returns boolean
'GetFreeFolderName - Added
'RandomNum - wrapped with 10 try error handling in case of periodic overflow
'Move - changed mechanism of copy to name x as y instead of copy delete
'CreateFile - now returns boolean
'
'changes feb 8 06
' updated fileexists function to not throw err on bad path
'
' 5.21.12 - bugfix in RandomNum sporotic overflow time of day related...
' 11.14.13- bugfix in FileExists,FolderExists, GetFolderFiles recursive filter, GetParentFolder trailing \ bugfix
' 1.21.14- bugfix deletefile detects readonly attribute and removes
' 11.15.15- bugfix GetParentFolder could fail is ub folder name was repeated in path (sloppy replace)
' 5.31.17 = bugfix GetSubFolders.GetAttr could fail, FileExists could fail with embedded nulls (.\0file)
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Function GetFolderFiles(folderPath As String, Optional Filter As String = "*", Optional retFullPath As Boolean = True, Optional recursive As Boolean = False) As String()
Dim fnames() As String
Dim fs As String
Dim folders() As String
Dim i As Integer
If Not FolderExists(folderPath) Then
'returns empty array if fails
GetFolderFiles = fnames()
Exit Function
End If
folderPath = IIf(Right(folderPath, 1) = "\", folderPath, folderPath & "\")
fs = Dir(folderPath & Filter, vbHidden Or vbNormal Or vbReadOnly Or vbSystem)
While fs <> ""
If fs <> "" Then push fnames(), IIf(retFullPath = True, folderPath & fs, fs)
fs = Dir()
Wend
If recursive Then
folders() = GetSubFolders(folderPath)
If Not AryIsEmpty(folders) Then
For i = 0 To UBound(folders)
FolderEngine folders(i), fnames(), Filter
Next
End If
If Not retFullPath Then
For i = 0 To UBound(fnames)
fnames(i) = Replace(fnames(i), folderPath, Empty) 'make relative path from base
Next
End If
End If
GetFolderFiles = fnames()
End Function
Private Sub FolderEngine(fldrpath As String, ary() As String, Optional Filter As String = "*")
Dim files() As String
Dim folders() As String
Dim i As Long
files = GetFolderFiles(fldrpath, Filter)
folders = GetSubFolders(fldrpath)
If Not AryIsEmpty(files) Then
For i = 0 To UBound(files)
push ary, files(i)
Next
End If
If Not AryIsEmpty(folders) Then
For i = 0 To UBound(folders)
FolderEngine folders(i), ary, Filter
Next
End If
End Sub
Function GetSubFolders(folderPath As String, Optional retFullPath As Boolean = True) As String()
Dim fnames() As String
Dim fd As String
On Error Resume Next 'getattr can barf on weird file names..
If Not FolderExists(folderPath) Then
'returns empty array if fails
GetSubFolders = fnames()
Exit Function
End If
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\"
fd = Dir(folderPath, vbDirectory)
While fd <> ""
If Left(fd, 1) <> "." Then
If (GetAttr(folderPath & fd) And vbDirectory) = vbDirectory Then
If Err.Number = 0 Then
push fnames(), IIf(retFullPath = True, folderPath & fd, fd)
Else
Err.Clear
End If
End If
End If
fd = Dir()
Wend
GetSubFolders = fnames()
End Function
Function FolderExists(path As String) As Boolean
On Error GoTo hell
Dim tmp As String
tmp = path & "\"
If Len(tmp) = 1 Then Exit Function
If Dir(tmp, vbDirectory) <> "" Then FolderExists = True
Exit Function
hell:
FolderExists = False
End Function
Function FileExists(path As String) As Boolean
On Error GoTo hell
If Len(path) = 0 Then Exit Function
If Right(path, 1) = "\" Then Exit Function
If InStr(path, Chr(0)) > 0 Then Exit Function
If Dir(path, vbHidden Or vbNormal Or vbReadOnly Or vbSystem) <> "" Then FileExists = True
Exit Function
hell: FileExists = False
End Function
Function GetParentFolder(path) As String
Dim tmp() As String
Dim my_path
Dim ub As String
On Error GoTo hell
If Len(path) = 0 Then Exit Function
my_path = path
While Len(my_path) > 0 And Right(my_path, 1) = "\"
my_path = Mid(my_path, 1, Len(my_path) - 1)
Wend
tmp = Split(my_path, "\")
tmp(UBound(tmp)) = Empty
my_path = Replace(Join(tmp, "\"), "\\", "\")
If VBA.Right(my_path, 1) = "\" Then my_path = Mid(my_path, 1, Len(my_path) - 1)
GetParentFolder = my_path
Exit Function
hell:
GetParentFolder = Empty
End Function
Function CreateFolder(path As String) As Boolean
On Error GoTo blah
If FolderExists(path) Then Exit Function
MkDir path
If Not FolderExists(path) Then Exit Function
CreateFolder = True
blah:
End Function
Function FileNameFromPath(FullPath As String) As String
Dim tmp() As String
If InStr(FullPath, "\") > 0 Then
tmp = Split(FullPath, "\")
FileNameFromPath = CStr(tmp(UBound(tmp)))
End If
End Function
Function WebFileNameFromPath(FullPath As String)
Dim tmp() As String
If InStr(FullPath, "/") > 0 Then
tmp = Split(FullPath, "/")
WebFileNameFromPath = CStr(tmp(UBound(tmp)))
End If
End Function
Function DeleteFile(fpath As String) As Boolean
On Error GoTo hadErr
Dim attributes As VbFileAttribute
attributes = GetAttr(fpath)
If (attributes And vbReadOnly) Then
attributes = attributes - vbReadOnly
SetAttr fpath, attributes
End If
Kill fpath
DeleteFile = True
Exit Function
hadErr:
'MsgBox "DeleteFile Failed" & vbCrLf & vbCrLf & fpath
DeleteFile = False
End Function
Sub Rename(FullPath As String, newName As String)
Dim pf As String
pf = GetParentFolder(FullPath)
Name FullPath As pf & "\" & newName
End Sub
Sub SetAttribute(fpath, it As VbFileAttribute)
SetAttr fpath, it
End Sub
'always returns lcase
Function GetExtension(path) As String
Dim tmp() As String
Dim ub As String
If Len(path) = 0 Then Exit Function
tmp = Split(path, "\")
ub = tmp(UBound(tmp))
If InStr(1, ub, ".") > 0 Then
GetExtension = LCase(Mid(ub, InStrRev(ub, "."), Len(ub)))
Else
GetExtension = ""
End If
End Function
Function GetBaseName(path As String) As String
Dim tmp() As String
Dim ub As String
If Len(path) = 0 Then Exit Function
tmp = Split(path, "\")
ub = tmp(UBound(tmp))
If InStr(1, ub, ".") > 0 Then
GetBaseName = Mid(ub, 1, InStrRev(ub, ".") - 1)
Else
GetBaseName = ub
End If
End Function
'can also just accept a file name
Function ChangeExt(path As String, ext As String)
Dim newPath As String
If Left(ext, 1) <> "." Then ext = "." & ext
newPath = GetBaseName(path) & ext
If LCase(path) <> LCase(newPath) Then
If FileExists(path) Then
Rename path, newPath
End If
End If
ChangeExt = newPath
End Function
Function SafeFileName(proposed As String) As String
Dim badChars As String, bad() As String, i As Long
badChars = ">,<,&,/,\,:,|,?,*,"""
bad = Split(badChars, ",")
For i = 0 To UBound(bad)
proposed = Replace(proposed, bad(i), "")
Next
SafeFileName = CStr(proposed)
End Function
Function RandomNum() As Long
Dim tmp As Long
Dim tries As Long
On Error Resume Next
Do While 1
Err.Clear
Randomize
tmp = Round(Timer * Now * Rnd(), 0)
RandomNum = tmp
If Err.Number = 0 Then Exit Function
If tries < 100 Then
tries = tries + 1
Else
Exit Do
End If
Loop
RandomNum = GetTickCount
End Function
Function GetFreeFileName(ByVal folder As String, Optional extension = ".txt") As String
On Error GoTo Handler 'can have overflow err once in awhile :(
Dim i As Integer
Dim tmp As String
If Not FolderExists(folder) Then Exit Function
If Right(folder, 1) <> "\" Then folder = folder & "\"
If Left(extension, 1) <> "." Then extension = "." & extension
again:
Do
tmp = folder & RandomNum() & extension
Loop Until Not FileExists(tmp)
GetFreeFileName = tmp
Exit Function
Handler:
If i < 10 Then
i = i + 1
GoTo again
End If
End Function
Function GetFreeFolderName(ByVal parentFolder As String, Optional prefix As String = "") As String
On Error GoTo Handler 'can have overflow err once in awhile :(
Dim i As Integer
Dim tmp As String
If Not FolderExists(parentFolder) Then Exit Function
If Right(parentFolder, 1) <> "\" Then parentFolder = parentFolder & "\"
again:
Do
tmp = parentFolder & prefix & RandomNum()
Loop Until Not FolderExists(tmp)
GetFreeFolderName = tmp
Exit Function
Handler:
If i < 10 Then
i = i + 1
GoTo again
End If
End Function
Function buildPath(folderPath As String) As Boolean
On Error GoTo oops
If FolderExists(folderPath) Then buildPath = True: Exit Function
Dim tmp() As String, build As String, i As Long
tmp = Split(folderPath, "\")
build = tmp(0)
For i = 1 To UBound(tmp)
build = build & "\" & tmp(i)
If InStr(tmp(i), ".") < 1 Then
If Not FolderExists(build) Then CreateFolder (build)
End If
Next
buildPath = True
Exit Function
oops: buildPath = False
End Function
Function ReadFile(filename) As Variant
Dim f As Long
Dim temp As Variant
f = FreeFile
temp = ""
Open filename For Binary As #f ' Open file.(can be text or image)
temp = Input(FileLen(filename), #f) ' Get entire Files data
Close #f
ReadFile = temp
End Function
Sub WriteFile(path As String, it As Variant)
Dim f As Long
f = FreeFile
Open path For Output As #f
Print #f, it
Close f
End Sub
Sub AppendFile(path, it)
Dim f As Long
f = FreeFile
Open path For Append As #f
Print #f, it
Close f
End Sub
Function Copy(fpath As String, toFolder As String)
Dim baseName As String, newName As String
If FolderExists(toFolder) Then
baseName = FileNameFromPath(fpath)
toFolder = IIf(Right(toFolder, 1) = "\", toFolder, toFolder & "\")
newName = toFolder & baseName
FileCopy fpath, newName
Copy = newName
Else 'assume tofolder is actually new desired file path
FileCopy fpath, toFolder
Copy = toFolder
End If
End Function
Function Move(fpath As String, toFolder As String)
Dim fName As String
fName = FileNameFromPath(fpath)
toFolder = IIf(Right(toFolder, 1) = "\", toFolder, toFolder & "\")
Name fpath As toFolder & fName
Move = toFolder & fName
End Function
Function CreateFile(fpath As String) As Boolean
On Error GoTo hell
Dim f As Long
f = FreeFile
If FileExists(fpath) Then Exit Function
Open fpath For Binary As f
Close f
If FileExists(fpath) Then CreateFile = True
hell:
End Function
Function DeleteFolder(folderPath As String, Optional force As Boolean = True) As Boolean
On Error GoTo failed
Call delTree(folderPath, force)
RmDir folderPath
DeleteFolder = True
Exit Function
failed: DeleteFolder = False
End Function
Private Sub delTree(folderPath As String, Optional force As Boolean = True)
Dim sfi() As String, sfo() As String, i As Integer
sfi() = GetFolderFiles(folderPath)
sfo() = GetSubFolders(folderPath)
If Not AryIsEmpty(sfi) And force = True Then
For i = 0 To UBound(sfi)
DeleteFile sfi(i)
Next
End If
If Not AryIsEmpty(sfo) And force = True Then
For i = 0 To UBound(sfo)
Call DeleteFolder(sfo(i), True)
Next
End If
End Sub
Private Sub push(ary, value) 'this modifies parent ary object
On Error GoTo init
Dim x As Long
x = UBound(ary) '<-throws Error If Not initalized
ReDim Preserve ary(UBound(ary) + 1)
ary(UBound(ary)) = value
Exit Sub
init: ReDim ary(0): ary(0) = value
End Sub
Private Function AryIsEmpty(ary) As Boolean
On Error GoTo oops
Dim x As Long
x = UBound(ary)
AryIsEmpty = False
Exit Function
oops: AryIsEmpty = True
End Function
Function FolderName(folderPath) As String
Dim ret As String, tmp() As String
If Len(folderPath) = 0 Then Exit Function
tmp = Split(folderPath, "\")
If Not AryIsEmpty(tmp) Then
If Len(tmp(UBound(tmp))) <> 0 Then ret = tmp(UBound(tmp)) _
Else ret = tmp(UBound(tmp) - 1)
Else
ret = CStr(folderPath)
End If
FolderName = ret
End Function
Private Sub Class_Initialize()
' If Not isRegistered And Not isInitalized Then TellThemAllAboutIt
End Sub

View File

@ -0,0 +1,83 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "CSubclass2"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'Author: david zimmer <dzzie@yahoo.com>
'Site: http://sandsprite.com
'added 5.17.12 - supports changing the return value to the callers SendMessage()
Event MessageReceived(hwnd As Long, wMsg As Long, wParam As Long, lParam As Long, Cancel As Boolean)
Public ErrorMessage As String
Public ErrorNumber As Long
Private mOverRide As Boolean
Private mVal As Long
Public Windows As New Collection
Friend Function WasOverRidden() As Boolean
WasOverRidden = mOverRide
End Function
Friend Function OverRideVal() As Long
OverRideVal = mVal
End Function
Function OverRideRetVal(newRetVal As Long)
mOverRide = True
mVal = newRetVal
End Function
Function AttachMessage(hwnd As Long, wMsg As Long) As Boolean
On Error GoTo hell
modSubclass.MonitorWindowMessage Me, hwnd, wMsg
AttachMessage = True
ErrorMessage = ""
ErrorNumber = 0
Exit Function
hell:
ErrorMessage = Err.Description
ErrorNumber = Err.Number
End Function
Sub DetatchMessage(hwnd As Long, wMsg As Long)
modSubclass.DetachWindowMessage hwnd, wMsg
End Sub
Private Sub Class_Initialize()
modSubclass.RegisterClassActive Me
End Sub
Private Sub Class_Terminate()
modSubclass.RemoveActiveClass Me
End Sub
Friend Sub ForwardMessage(hwnd As Long, wMsg As Long, wParam As Long, lParam As Long, Optional Cancel As Boolean)
'this sub is only called from the module,
'friend methods are not externally visible in compiled dll interface
mOverRide = False
RaiseEvent MessageReceived(hwnd, wMsg, wParam, lParam, Cancel)
End Sub

View File

@ -0,0 +1,93 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "CWindow"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'Author: david zimmer <dzzie@yahoo.com>
'Site: http://sandsprite.com
'each window can only be subclassed by one subclasser.
'this is a new limitation for simplicity/sanity/stability/readability etc!
Public hwnd As Long
Private Messages() As Long
Public pOldWndProc As Long
Public Handler As CSubclass2
Public Function MsgExists(msg As Long) As Boolean
On Error Resume Next
If AryIsEmpty(Messages) Then
MsgExists = False
Exit Function
End If
Dim i As Long
For i = 0 To UBound(Messages)
If Messages(i) = msg Then
MsgExists = True
Exit Function
End If
Next
Exit Function
End Function
Public Function ActiveMessages() As Long
Dim i, found As Long
If Not AryIsEmpty(Messages) Then
For i = 0 To UBound(Messages)
If Messages(i) <> 0 Then
found = found + 1
End If
Next
End If
ActiveMessages = found
End Function
Public Sub RemoveMsg(msg As Long)
Dim i As Long
If AryIsEmpty(Messages) Then Exit Sub
For i = 0 To UBound(Messages)
If Messages(i) = msg Then
Messages(i) = 0
Exit Sub
End If
Next
End Sub
Public Function AddMsg(msg As Long) As Boolean
lpush Messages, msg
End Function
Private Function AryIsEmpty(ary) As Boolean
On Error GoTo oops
Dim x As Long
x = UBound(ary)
AryIsEmpty = False
Exit Function
oops: AryIsEmpty = True
End Function
Private Sub lpush(ary() As Long, value As Long) 'this modifies parent ary object
On Error GoTo init
Dim x As Long
x = UBound(ary) '<-throws Error If Not initalized
ReDim Preserve ary(UBound(ary) + 1)
ary(UBound(ary)) = value
Exit Sub
init: ReDim ary(0): ary(0) = value
End Sub

View File

@ -0,0 +1,46 @@
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation
Form=frmMain.frm
Class=CFileSystem2; CFileSystem2.cls
Class=clsCmnDlg; clsCmnDlg.cls
Module=modSubclass; modSubclass.bas
Class=CSubclass2; CSubClass2.cls
Class=CWindow; CWindow.cls
IconForm="frmMain"
Startup="frmMain"
HelpFile=""
Title="injector"
ExeName32="injector.exe"
Path32=".."
Command32=""
Name="injector"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="sandsprite.com"
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
DebugStartupOption=0
[MS Transaction Server]
AutoRefresh=1
[fastBuild]
fullPath=%ap%\..\injector.exe

View File

@ -0,0 +1,6 @@
frmMain = 25, 4, 1328, 882, , 60, 8, 1062, 827, C
CFileSystem2 = 182, 182, 1072, 655,
clsCmnDlg = 208, 208, 1098, 681, C
modSubclass = 208, 208, 1098, 681,
CSubclass2 = 182, 182, 1072, 655, C
CWindow = 26, 26, 916, 499, C

View File

@ -0,0 +1,226 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "clsCmnDlg"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Private Type OPENFILENAME
lStructSize As Long
hWndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Private Type oColorDlg
lStructSize As Long
hWndOwner As Long
hInstance As Long
rgbResult As Long
lpCustColors As String
flags As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Private Type BrowseInfo
hWndOwner As Long
pIDLRoot As Long
pszDisplayName As Long
lpszTitle As Long
ulFlags As Long
lpfnCallback As Long
lParam As Long
iImage As Long
End Type
Public Enum FilterTypes
textFiles = 0
htmlFiles = 1
exeFiles = 2
zipFiles = 3
AllFiles = 4
CustomFilter = 5
End Enum
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
Private Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Long
Private Declare Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As oColorDlg) As Long
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private o As OPENFILENAME
Private filters(6) As String
Private extensions(6) As String
Private errOnCancel As Boolean
Property Let ErrorOnCancel(bln As Boolean)
errOnCancel = bln
End Property
Property Get ErrorOnCancel() As Boolean
ErrorOnCancel = errOnCancel
End Property
Sub SetCustomFilter(displayText As String, Optional wildCardExtMatch = "*.*")
filters(5) = "____" + Chr$(0) + "___" + Chr$(0) + "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
filters(5) = Replace(filters(5), "____", displayText)
filters(5) = Replace(filters(5), "___", wildCardExtMatch)
extensions(5) = Replace(wildCardExtMatch, "*", "")
End Sub
Private Sub Class_Initialize()
' If Not isRegistered And Not isInitalized Then TellThemAllAboutIt
filters(0) = "Text Files (*.txt)" + Chr$(0) + "*.txt" + Chr$(0) + "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
filters(1) = "Html Files (*.htm*)" + Chr$(0) + "*.htm*" + Chr$(0) + "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
filters(2) = "Exe Files (*.exe)" + Chr$(0) + "*.exe" + Chr$(0) + "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
filters(3) = "Zip Files (*.zip)" + Chr$(0) + "*.zip" + Chr$(0) + "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
filters(4) = "All Files (*.*)" + Chr$(0) + "*.*" + Chr$(0)
extensions(0) = ".txt"
extensions(1) = ".html"
extensions(2) = ".exe"
extensions(3) = ".zip"
extensions(4) = ".bin"
End Sub
Function OpenDialog(filt As FilterTypes, Optional initDir As String, Optional title As String, Optional pHwnd As Long = 0) As String
If pHwnd = 0 Then pHwnd = GetForegroundWindow()
o.lStructSize = Len(o)
o.hWndOwner = pHwnd
o.hInstance = 0
o.lpstrFilter = filters(filt)
o.lpstrFile = Space$(254)
o.nMaxFile = 255
o.lpstrFileTitle = Space$(254)
o.nMaxFileTitle = 255
o.lpstrInitialDir = initDir
o.lpstrTitle = title
o.flags = 0
OpenDialog = IIf(GetOpenFileName(o), Trim$(o.lpstrFile), "")
OpenDialog = Replace(OpenDialog, Chr(0), Empty)
If Len(OpenDialog) = 0 And errOnCancel Then Err.Raise 1, "OpenDialog", "Cancel"
End Function
Function SaveDialog(filt As FilterTypes, Optional initDir As String, Optional title As String = "", Optional ConfirmOvewrite As Boolean = True, Optional pHwnd As Long = 0) As String
If pHwnd = 0 Then pHwnd = GetForegroundWindow()
o.lStructSize = Len(o)
o.hWndOwner = pHwnd
o.hInstance = pHwnd
o.lpstrFilter = filters(filt)
o.lpstrFile = Space$(254)
o.nMaxFile = 255
o.lpstrFileTitle = Space$(254)
o.nMaxFileTitle = 255
o.lpstrInitialDir = initDir
o.lpstrTitle = title
o.lpstrDefExt = extensions(filt)
o.flags = 0
Dim tmp As String
tmp = IIf(GetSaveFileName(o), Trim$(o.lpstrFile), "")
If ConfirmOvewrite And tmp <> "" Then
If FileExists(tmp) Then
If MsgBox("File Already Exists" & vbCrLf & vbCrLf & "Are you sure you wish to overwrite existing file?", vbYesNo + vbExclamation, "Confirm Overwrite") = vbYes Then SaveDialog = tmp
Else
SaveDialog = tmp
End If
Else
SaveDialog = tmp
End If
If Len(SaveDialog) = 0 And errOnCancel Then Err.Raise 1, "SaveDialog", "Cancel"
End Function
Function ColorDialog(Optional pHwnd As Long) As Long
Dim c As oColorDlg
Dim cColors() As Byte
If pHwnd = 0 Then pHwnd = GetForegroundWindow()
c.lStructSize = Len(c)
c.hWndOwner = pHwnd
c.hInstance = App.hInstance
c.lpCustColors = StrConv(cColors, vbUnicode)
c.flags = 0
If ChooseColor(c) <> 0 Then
ColorDialog = c.rgbResult
cColors = StrConv(c.lpCustColors, vbFromUnicode)
Else
ColorDialog = -1
If errOnCancel Then Err.Raise 1, "ShowColor", "Cancel"
End If
End Function
Function FolderDialog(Optional initDir As String, Optional pHwnd As Long = 0) As String
Dim bInfo As BrowseInfo, ret As String, ptrList As Long, nullChar As Long
If pHwnd = 0 Then pHwnd = GetForegroundWindow()
With bInfo
.hWndOwner = pHwnd
.lpszTitle = lstrcat(initDir, "") 'returns memaddress
.ulFlags = 1 'only directories
End With
ptrList = SHBrowseForFolder(bInfo)
If ptrList Then
ret = String$(260, 0)
SHGetPathFromIDList ptrList, ret 'Get the path from the IDList
CoTaskMemFree ptrList 'free the block of memory
nullChar = InStr(ret, vbNullChar)
If nullChar > 0 Then ret = Left$(ret, nullChar - 1)
End If
FolderDialog = ret
If Len(ret) = 0 And errOnCancel Then Err.Raise 1, "ChooseFolder", "Cancel"
End Function
Private Function FileExists(path) As Boolean
If Len(path) = 0 Then Exit Function
If Dir(path, vbHidden Or vbNormal Or vbReadOnly Or vbSystem) <> "" Then FileExists = True
End Function

View File

@ -0,0 +1,514 @@
VERSION 5.00
Begin VB.Form frmMain
Caption = "injector"
ClientHeight = 7305
ClientLeft = 165
ClientTop = 450
ClientWidth = 8670
LinkTopic = "frmMain"
ScaleHeight = 7305
ScaleWidth = 8670
StartUpPosition = 2 'CenterScreen
Begin VB.ListBox List1
BeginProperty Font
Name = "Courier"
Size = 9.75
Charset = 0
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 5130
Left = 90
TabIndex = 14
Top = 1935
Width = 8295
End
Begin VB.TextBox txtIPCHwnd
Height = 330
Left = 1215
TabIndex = 13
Top = 1080
Width = 1185
End
Begin VB.CommandButton cmdSendIPC
Caption = "Send Cmd"
Height = 285
Left = 6210
TabIndex = 12
Top = 1125
Width = 1095
End
Begin VB.TextBox txtIPCCmd
Height = 330
Left = 2520
TabIndex = 11
Text = "my test IPC command"
Top = 1080
Width = 3615
End
Begin VB.CommandButton cmdBrowse
Caption = "..."
Height = 270
Index = 2
Left = 6240
TabIndex = 9
Top = 405
Width = 615
End
Begin VB.CommandButton cmdBrowse
Caption = "..."
Height = 270
Index = 1
Left = 6240
TabIndex = 8
Top = 765
Width = 615
End
Begin VB.CommandButton cmdBrowse
Caption = "..."
Height = 255
Index = 0
Left = 6255
TabIndex = 7
Top = 45
Width = 615
End
Begin VB.TextBox txtArgs
Height = 315
Left = 1200
OLEDropMode = 1 'Manual
TabIndex = 6
Top = 360
Width = 4965
End
Begin VB.TextBox txtDll
Height = 285
Left = 1200
OLEDropMode = 1 'Manual
TabIndex = 4
Top = 720
Width = 4965
End
Begin VB.CommandButton cmdStart
Caption = "Inject"
Height = 300
Left = 7065
TabIndex = 2
Top = 45
Width = 1335
End
Begin VB.TextBox txtExe
Height = 315
Left = 1200
OLEDropMode = 1 'Manual
TabIndex = 1
Top = 0
Width = 4920
End
Begin VB.Label Label3
Caption = "Log Output"
Height = 285
Left = 90
TabIndex = 15
Top = 1530
Width = 915
End
Begin VB.Label Label2
Caption = "IPC hWnd"
Height = 240
Left = 0
TabIndex = 10
Top = 1125
Width = 1095
End
Begin VB.Label Label7
Caption = "Args"
Height = 285
Left = 60
TabIndex = 5
Top = 360
Width = 945
End
Begin VB.Label lblDll
Caption = "Inject DLL"
ForeColor = &H00000000&
Height = 315
Left = 45
TabIndex = 3
Top = 750
Width = 1335
End
Begin VB.Label Label1
Caption = "Executable"
Height = 255
Left = 60
TabIndex = 0
Top = 60
Width = 975
End
End
Attribute VB_Name = "frmMain"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
'Author: david zimmer <dzzie@yahoo.com>
'Site: http://sandsprite.com
Dim WithEvents sc As CSubclass2
Attribute sc.VB_VarHelpID = -1
Public fso As New CFileSystem2
Public dlg As New clsCmnDlg
Private runtime As String
Const targetRuntime As Long = &H360C5B48
'Compiled: Sat, Sep 26 1998, 3:11:04
'MD5: EEBEB73979D0AD3C74B248EBF1B6E770
'SHA256: E86CBB17C8FCD97BB04D9E0B7FB3EF7A33C6896E681705FC95405F14008737CD
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CreateRemoteThread Lib "kernel32" (ByVal ProcessHandle As Long, lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Any, ByVal lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadID As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal fAllocType As Long, FlProtect As Long) As Long
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDriectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function ResumeThread Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Sub DebugBreak Lib "kernel32" ()
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Declare Function WriteProcessBytes Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Long, lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Const WM_COPYDATA = &H4A
Private Const PAGE_READWRITE = 4
Private Const CREATE_SUSPENDED = &H4
Private Const MEM_COMMIT = &H1000
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)
Private Type COPYDATASTRUCT
dwFlag As Long
cbSize As Long
lpData As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Sub cmdBrowse_Click(index As Integer)
Dim f As String
f = dlg.OpenDialog(AllFiles, , "Open Executable", Me.hwnd)
f = Trim(Replace(f, Chr(0), Empty))
If Len(f) = 0 Then Exit Sub
Select Case index
Case 0: txtExe = f
Case 1: txtDll = f
Case 2: txtArgs = f
End Select
End Sub
Private Sub cmdSendIPC_Click()
On Error Resume Next
Dim hwnd As Long
txtIPCCmd = Trim(txtIPCCmd)
If Len(txtIPCCmd) = 0 Then
MsgBox "Nothing to send", vbInformation
Exit Sub
End If
hwnd = Replace(txtIPCHwnd, "0x", "&h", , , vbTextCompare)
If Err.Number <> 0 Then
MsgBox "hwnd not numeric? " & Err.Description, vbExclamation
Exit Sub
End If
If IsWindow(hwnd) <> 1 Then
MsgBox "hwnd not a valid window ", vbExclamation
Exit Sub
End If
SendIPC hwnd, txtIPCCmd, Me.hwnd
End Sub
Private Sub cmdStart_Click()
Dim exe As String
Dim pf As String
Dim ver As Long
Dim tmp As String
On Error GoTo hell
List1.Clear
If Not fso.FileExists(txtExe) Then
List1.AddItem "Executable not found"
Exit Sub
End If
If Not fso.FileExists(txtDll) Then
List1.AddItem "Dll To inject not found"
Exit Sub
End If
If Not fso.FileExists(runtime) Then
List1.AddItem "Could not find a copy of our target runtime in my folder?"
Exit Sub
Else
pf = fso.GetParentFolder(txtExe) & "\"
tmp = pf & "msvbvm60.dll"
If Not fso.FileExists(tmp) Then
fso.Copy runtime, pf
If Not fso.FileExists(tmp) Then
List1.AddItem "Could not copy target runtime to exe folder"
Exit Sub
Else
List1.AddItem "Target runtime copied to exe folder"
End If
Else
'a copy of runtime is already in exe folder, is it ours?
ver = GetCompileTime(tmp, True)
List1.AddItem "Runtime timestamp: " & Hex(ver) & " - " & GetCompileTime(tmp)
If ver <> targetRuntime Then
List1.AddItem "VB runtime in exe folder does not match our target version."
Exit Sub
End If
End If
End If
exe = txtExe
If Len(txtArgs) > 0 Then exe = exe & " " & txtArgs
If StartWithDLL(exe, txtDll) = 0 Then
List1.AddItem "Injection failed"
End If
Exit Sub
hell:
MsgBox "Error: " & Err.Description
End Sub
Private Sub Form_Load()
Set sc = New CSubclass2
sc.AttachMessage Me.hwnd, WM_COPYDATA
txtDll = App.path & IIf(isIde(), "\..\", "\") & "openscript.dll"
runtime = App.path & IIf(isIde(), "\..\", "\") & "msvbvm60.dll"
If Not fso.FileExists(runtime) Then
List1.AddItem "Could not locate target version of the runtime"
runtime = Empty
Else
Dim ver As Long
ver = GetCompileTime(runtime, True)
If ver <> targetRuntime Then
List1.AddItem "Target Runtime version mismatch? Time stamp is: " & GetCompileTime(runtime)
runtime = Empty
End If
End If
If Len(Command) > 0 Then
txtExe = Replace(Command, """", Empty)
Else
txtExe = App.path & IIf(isIde(), "\..\", "\") & "testApp.exe"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set sc = Nothing
End Sub
Private Sub sc_MessageReceived(hwnd As Long, wMsg As Long, wParam As Long, lParam As Long, Cancel As Boolean) '
Dim CopyData As COPYDATASTRUCT
Dim Buffer(1 To 2048) As Byte
Dim temp As String, a As Long
On Error Resume Next
If wMsg = WM_COPYDATA Then
CopyMemory CopyData, ByVal lParam, Len(CopyData)
If CopyData.dwFlag = 3 Then
CopyMemory Buffer(1), ByVal CopyData.lpData, CopyData.cbSize
temp = StrConv(Buffer, vbUnicode, &H409)
temp = Left$(temp, InStr(1, temp, Chr$(0)) - 1)
temp = Trim(temp)
If Len(temp) > 0 Then List1.AddItem temp
If InStr(1, temp, "IPC listening on hwnd", vbTextCompare) > 0 Then
a = InStrRev(temp, " ")
If a > 0 Then txtIPCHwnd = "0x" & Trim(Mid(temp, a))
End If
End If
End If
End Sub
Private Sub txtArgs_OLEDragDrop(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
On Error Resume Next
txtArgs = data.files(1)
End Sub
Private Sub txtDll_OLEDragDrop(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
On Error Resume Next
txtDll = data.files(1)
End Sub
Private Sub txtexe_OLEDragDrop(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
On Error Resume Next
txtExe = data.files(1)
End Sub
Private Sub Form_Resize()
On Error Resume Next
List1.Width = Me.Width - List1.Left - 200
List1.Height = Me.Height - List1.Top - 500
End Sub
Function isIde() As Boolean
On Error GoTo hell
Debug.Print 1 \ 0
Exit Function
hell: isIde = True
End Function
Function GetCompileTime(Optional ByVal exe As String, Optional returnRawVal As Boolean = False)
Dim f As Long, i As Integer
Dim stamp As Long, e_lfanew As Long
Dim base As Date, compiled As Date
On Error GoTo errExit
If Len(exe) = 0 Then
exe = App.path & "" & App.EXEName & ".exe"
End If
FileLen exe 'throw error if not exist
f = FreeFile
Open exe For Binary Access Read As f
Get f, , i
If i <> &H5A4D Then GoTo errExit 'MZ check
Get f, 60 + 1, e_lfanew
Get f, e_lfanew + 1, i
If i <> &H4550 Then GoTo errExit 'PE check
Get f, e_lfanew + 9, stamp
Close f
If returnRawVal Then
GetCompileTime = stamp
Else
base = DateSerial(1970, 1, 1)
compiled = DateAdd("s", stamp, base)
GetCompileTime = Format(compiled, "ddd, mmm d yyyy, h:nn:ss ")
End If
Exit Function
errExit:
Close f
End Function
Function SendIPC(targetHwnd As Long, msg As String, Optional senderHwnd As Long = 0) As Long
Dim cds As COPYDATASTRUCT
Dim buf(1 To 255) As Byte
List1.AddItem "SendIPC(hwnd=" & targetHwnd & ", msg=" & msg & ")"
Call CopyMemory(buf(1), ByVal msg, Len(msg))
cds.dwFlag = 3
cds.cbSize = Len(msg) + 1
cds.lpData = VarPtr(buf(1))
SendIPC = SendMessage(targetHwnd, WM_COPYDATA, senderHwnd, cds)
End Function
Public Function StartWithDLL(exe As String, dll As String) As Long
Dim hProcess As Long, hThread As Long, remoteLoadLib As Long, remoteMem As Long, bufLen As Long, writeLen As Long
Dim pi As PROCESS_INFORMATION, si As STARTUPINFO, buf() As Byte
buf() = StrConv(dll & Chr(0), vbFromUnicode)
bufLen = UBound(buf) + 1
If CreateProcess(0&, exe, 0&, 0&, 1&, CREATE_SUSPENDED, 0&, 0&, si, pi) = 0 Then Exit Function
List1.AddItem "PID: 0x" & Hex(pi.dwProcessId) & " (" & pi.dwProcessId & ")"
hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, pi.dwProcessId)
If hProcess = -1 Then Exit Function
remoteMem = VirtualAllocEx(hProcess, ByVal 0, bufLen, MEM_COMMIT, ByVal PAGE_READWRITE)
If remoteMem <> 0 Then
If WriteProcessBytes(hProcess, ByVal remoteMem, buf(0), bufLen, writeLen) <> 0 Then
remoteLoadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA")
If CreateRemoteThread(hProcess, ByVal 0, 0, remoteLoadLib, remoteMem, 0, hThread) <> -1 Then
List1.AddItem "ThreadID: 0x" & Hex(hThread)
Sleep 300
If ResumeThread(pi.hThread) <> -1 Then StartWithDLL = 1
End If
End If
End If
CloseHandle hProcess
End Function

View File

@ -0,0 +1,165 @@
Attribute VB_Name = "modSubclass"
Option Explicit
'Author: david zimmer <dzzie@yahoo.com>
'Site: http://sandsprite.com
'Design: you can have an unlimited number of classes, and should be
' able to subclass an unlimited number of windows. Each class
' can in turn subclass as many windows as it wants, and it should
' be able to attach to as many messages per window as it wants.
'
' You can edit message parameters and cancel them directly in
' the eventhandler you implement for the clsSubClass in your code.
'
' One thing you cannot do, is to have multiple classes subclass the
' same window looking for the same message. Different subclasses can not
' subclass the same window (new limitation in sake of cleanliness/sanity/stability)
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Const GWL_WNDPROC = (-4)
Private ActiveClasses As New Collection 'of CSubclass2
Private Windows As New Collection 'of CWindow
Function RegisterClassActive(clsActive As CSubclass2)
ActiveClasses.Add clsActive, "Objptr:" & ObjPtr(clsActive)
End Function
Sub RemoveActiveClass(clsTerminate As CSubclass2)
On Error Resume Next
CloseOutClass clsTerminate
ActiveClasses.Remove "Objptr:" & ObjPtr(clsTerminate)
If ActiveClasses.Count = 0 Then InitTearDown
End Sub
'updated
Private Sub InitTearDown()
On Error Resume Next
Dim cw As CWindow
For Each cw In Windows
SetWindowLong cw.hwnd, GWL_WNDPROC, cw.pOldWndProc
Set cw.Handler = Nothing
Next
Set Windows = New Collection
End Sub
Sub MonitorWindowMessage(notify As CSubclass2, ByVal hwnd As Long, ByVal wMsg As Long)
'updated
If IsWindow(hwnd) = False Then Err.Raise 1, , "Invalid Window Handle"
Dim cw As CWindow
If AlreadySubclassing(hwnd, cw) Then
If Not ObjPtr(cw.Handler) <> ObjPtr(notify) Then
Err.Raise 3, , "This window is already subclassed by another class, not supported in name of stability.."
Else
If Not cw.MsgExists(wMsg) Then cw.AddMsg wMsg
End If
Else
'subclass each window only once
Set cw = New CWindow
cw.pOldWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
If cw.pOldWndProc = 0 Then Err.Raise 2, , "Subclass failed hwnd: " & hwnd
cw.hwnd = hwnd
Set cw.Handler = notify
cw.AddMsg wMsg
Windows.Add cw, "Hwnd:" & hwnd
End If
End Sub
'updated
Sub DetachWindowMessage(ByVal hwnd As Long, ByVal wMsg As Long)
Dim cw As CWindow
If AlreadySubclassing(hwnd, cw) Then
cw.RemoveMsg wMsg
If cw.ActiveMessages = 0 Then
SetWindowLong hwnd, GWL_WNDPROC, cw.pOldWndProc
Set cw.Handler = Nothing
Set cw = Nothing
Windows.Remove "Hwnd:" & hwnd
End If
End If
End Sub
Function CloseOutClass(c As CSubclass2)
Dim cw As CWindow
For Each cw In Windows
If ObjPtr(cw.Handler) = ObjPtr(c) Then
SetWindowLong cw.hwnd, GWL_WNDPROC, cw.pOldWndProc
Set cw.Handler = Nothing
Windows.Remove "Hwnd:" & cw.hwnd
End If
Next
End Function
Function WindowProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim stopIt As Boolean
Dim ret As Long
Dim s2 As CSubclass2
Dim cw As CWindow
If Not AlreadySubclassing(hwnd, cw) Then Exit Function 'shouldnt happen...
If cw.Handler Is Nothing Then 'shouldnt happen
DetachWindowMessage hwnd, wMsg
Exit Function
End If
If Not cw.MsgExists(wMsg) Then 'we dont care just pass it on..
WindowProc = CallWindowProc(cw.pOldWndProc, hwnd, wMsg, wParam, ByVal lParam)
Exit Function
End If
cw.Handler.ForwardMessage hwnd, wMsg, wParam, lParam, stopIt
If cw.Handler.WasOverRidden() Then
WindowProc = cw.Handler.OverRideVal()
Exit Function
End If
'stopit can be set = true when event is raised from clsSubClass
'any of the parameters passed in forward message could be changed
If Not stopIt Then
WindowProc = CallWindowProc(cw.pOldWndProc, hwnd, wMsg, wParam, ByVal lParam)
End If
End Function
Private Function AlreadySubclassing(hwnd As Long, cw As CWindow) As Boolean
On Error Resume Next
For Each cw In Windows
If cw.hwnd = hwnd Then
AlreadySubclassing = True
Exit Function
End If
Next
AlreadySubclassing = False
End Function

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,17 @@
// make sure you are running exe and script at same permission level
var o = GetObject("remote.forms")
var f = o.Item(0)
f.List1.Clear()
WScript.Echo( f.text1.text)
f.text1.text = "test from js"
f.List1.AddItem("test list item",0)
f.caption = "yup it works"
WScript.echo(f.formMeth("remote hi").toString(16))
WScript.echo(f.pubClass.classMeth("remote class hi").toString(16))
for(i=0; i< f.controls.count; i++){
f.List1.AddItem('Control ' + i + ' = ' + f.controls(i).name)
}

View File

@ -0,0 +1,28 @@
import os, sys
import win32com.client
# tested w/ 32bit python 2.7
# If you do not have the win32com module run 'pip install pywin32'
# make sure you are running exe and script at same permission level
os.system("cls")
forms = win32com.client.GetObject("remote.forms")
for form in forms:
print form.Name
for c in form.Controls:
print " " + c.Name
f = forms(0)
print "Text1 = " + f.text1.text
print hex(f.formMeth("remote hi"))
print hex(f.pubClass.classMeth("remote class hi"))
print f.pubClass.pubString
f.text1.Text = "I see you"
if f.width < 8000:
f.width = 8000
else:
f.width = 4000

View File

@ -0,0 +1,27 @@
'usage: cscript test.vbs
' make sure you are running exe and script at same permission level
'32/64 bit cmd prompt doesnt matter.
'If you just double click on the file it will run in wscript and
'the echo will be a msgbox vrs console print (still works but)
Set o = GetObject("remote.forms")
Set f = o.Item(0)
f.List1.Clear()
For Each form In o
f.List1.AddItem "Form: " & form.Name
For Each c In form.Controls
f.List1.AddItem vbTab & "Control: " & c.Name & " - " & TypeName(c)
Next
Next
WScript.echo Hex(f.formMeth("remote hi"))
WScript.echo Hex(f.pubClass.classMeth("remote class hi"))
WScript.echo f.pubClass.pubString
f.text1.Text = "I see you"
f.text1.Font.Name = "System"
if f.width < 8000 then f.width = 8000 else f.width = 4000
f.List1.AddItem "hi from script"

Binary file not shown.

View File

@ -0,0 +1,23 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Public pubString As String
Public Function classMeth(x) As Long
Form1.List1.AddItem "Class1.classMeth received: " & x
classMeth = &H44556677
End Function
Private Sub Class_Initialize()
pubString = "my public class string"
End Sub

View File

@ -0,0 +1,15 @@
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Class2"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Public pubString2 As String

View File

@ -0,0 +1,47 @@
VERSION 5.00
Begin VB.Form Form1
Caption = "Sample App"
ClientHeight = 3015
ClientLeft = 60
ClientTop = 405
ClientWidth = 3165
LinkTopic = "Form1"
ScaleHeight = 3015
ScaleWidth = 3165
StartUpPosition = 3 'Windows Default
Begin VB.ListBox List1
Height = 2400
Left = 135
TabIndex = 1
Top = 495
Width = 2850
End
Begin VB.TextBox Text1
Height = 285
Left = 135
TabIndex = 0
Text = "Text1"
Top = 90
Width = 2850
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public pubClass As New Class1
Public Function formMeth(x) As Long
List1.AddItem "form1.formMeth received: " & x
formMeth = &H11223344
End Function
Private Sub Form_Load()
List1.AddItem "VB.Forms: " & Hex(ObjPtr(VB.Forms))
List1.AddItem "ThreadID: " & Hex(GetCurrentThreadId())
If Len(Command) > 0 Then List1.AddItem "CmdLine: " & Command
End Sub

View File

@ -0,0 +1,37 @@
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation
Form=Form1.frm
Class=Class1; Class1.cls
Class=Class2; Class2.cls
IconForm="Form1"
Startup="Form1"
HelpFile=""
ExeName32="Project1.exe"
Path32=".."
Command32=""
Name="Project1"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
[fastBuild]
fullPath=%ap%\..\testApp.exe

View File

@ -0,0 +1,3 @@
Form1 = 52, 52, 864, 657, , 26, 26, 838, 475, C
Class1 = 52, 52, 864, 501, C
Class2 = 52, 52, 728, 489, C

View File

@ -0,0 +1,105 @@
----------------------------------
VB Exe Info
----------------------------------
VB Version: 6
VBStartOffset= 0
FormCount= 1
CompileType= Native
----------------------------------
VB Project Infomation
----------------------------------
ProjectTitle= injector
ProjectName= injector
ExeName= injector
HelpFile=
ExternalComponentCount= 0
----------------------------------
Object List
----------------------------------
frmMain
CFileSystem2
clsCmnDlg
modSubclass
CSubclass2
CWindow
----------------------------------
External Ocx List
----------------------------------
----------------------------------
Api List
----------------------------------
26 Api Calls - 5 Dlls
user32
CallWindowProcA @ 406168
GetWindowLongA @ 406120
SetWindowLongA @ 4060D8
GetForegroundWindow @ 404E48
IsWindow @ 404A70
SendMessageA @ 404A2C
kernel32
GetTickCount @ 405084
lstrcatA @ 404D00
RtlMoveMemory @ 4049D8
CloseHandle @ 404990
DebugBreak @ 404934
ResumeThread @ 4048F0
CreateProcessA @ 4048A8
VirtualAllocEx @ 404860
GetProcAddress @ 404818
GetModuleHandleA @ 4047D0
CreateRemoteThread @ 404768
WriteProcessMemory @ 40471C
OpenProcess @ 4046D0
Sleep @ 40468C
ole32.dll
CoTaskMemFree @ 404DFC
shell32
SHGetPathFromIDList @ 404DA4
SHBrowseForFolder @ 404D58
comdlg32.dll
ChooseColorA @ 404CAC
GetSaveFileNameA @ 404C64
GetOpenFileNameA @ 404C18
----------------------------------
Controls Guids
----------------------------------
Parent Form, Control Name, GUID
frmMain , List1 , {33AD4F10-6699-11CF-B70C-00AA0060D393}
frmMain , Form , {33AD4F38-6699-11CF-B70C-00AA0060D393}
frmMain , mnuUpdateConfig , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuCaptures , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuClearPidList , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuUpdateAll , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , lblDll , {33AD4ED8-6699-11CF-B70C-00AA0060D393}
frmMain , mnuSuspend , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuFind , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuPopup , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuResume , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuTerminate , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , Label7 , {33AD4ED8-6699-11CF-B70C-00AA0060D393}
frmMain , Label1 , {33AD4ED8-6699-11CF-B70C-00AA0060D393}
frmMain , Label2 , {33AD4ED8-6699-11CF-B70C-00AA0060D393}
frmMain , Label3 , {33AD4ED8-6699-11CF-B70C-00AA0060D393}
frmMain , mnuProcess , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , cmdStart , {33AD4EF0-6699-11CF-B70C-00AA0060D393}
frmMain , cmdSendIPC , {33AD4EF0-6699-11CF-B70C-00AA0060D393}
frmMain , mnuLoadSampleApiLog , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , mnuKillAll , {33AD4F68-6699-11CF-B70C-00AA0060D393}
frmMain , txtDll , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
frmMain , txtArgs , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
frmMain , txtExe , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
frmMain , txtIPCCmd , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
frmMain , cmdBrowse , {33AD4EF1-6699-11CF-B70C-00AA0060D393}
frmMain , sc , {CE6C35D1-1F61-414D-AE57-226CB7A5A9A2}
frmMain , txtIPCHwnd , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
CFileSystem2 , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}
clsCmnDlg , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}
CSubclass2 , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}
CWindow , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}

View File

@ -0,0 +1,42 @@
----------------------------------
VB Exe Info
----------------------------------
VB Version: 6
VBStartOffset= 0
FormCount= 1
CompileType= Native
----------------------------------
VB Project Infomation
----------------------------------
ProjectTitle= Project1
ProjectName= Project1
ExeName= testApp
HelpFile=
ExternalComponentCount= 0
----------------------------------
Object List
----------------------------------
Form1
Class1
Class2
----------------------------------
External Ocx List
----------------------------------
----------------------------------
Api List
----------------------------------
1 Api Calls - 1 Dlls
kernel32
GetCurrentThreadId @ 401E04
----------------------------------
Controls Guids
----------------------------------
Parent Form, Control Name, GUID
Form1 , List1 , {33AD4F10-6699-11CF-B70C-00AA0060D393}
Form1 , Form , {33AD4F38-6699-11CF-B70C-00AA0060D393}
Form1 , Text1 , {33AD4EE0-6699-11CF-B70C-00AA0060D393}
Class1 , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}
Class2 , Class , {FCFB3D1F-A0FA-1068-A738-08002B3371B5}