mireado

starting commit

// disasm.cc
// 1/27/2013 jichi
// Original source: http://hack-expo.void.ru/groups/blt/text/disasm.txt
//
// 7/19/2014 jichi: Need to add SSE instruction support for PCSX2
// Sample problematic input from Fate/Stay night PS2:
// 3024b80c -0f88 ae58dbd2 js pcsx2.030010c0
// 3024b812 0f1201 movlps xmm0,qword ptr ds:[ecx] ; jichi: hook here
// 3024b815 0f1302 movlps qword ptr ds:[edx],xmm0
#include "disasm.h"
// disasm_flag values:
enum : unsigned {
C_66 = 0x00000001 // 66-prefix
, C_67 = 0x00000002 // 67-prefix
, C_LOCK = 0x00000004 // lock
, C_REP = 0x00000008 // repz/repnz
, C_SEG = 0x00000010 // seg-prefix
, C_OPCODE2 = 0x00000020 // 2nd opcode present (1st==0f)
, C_MODRM = 0x00000040 // modrm present
, C_SIB = 0x00000080 // sib present
, C_ANYPREFIX = (C_66|C_67|C_LOCK|C_REP|C_SEG)
};
DISASM_BEGIN_NAMESPACE
// These values are served as the output of disasm
// But the are currently unused and could make disasm thread-unsafe
namespace { // unnamed
BYTE disasm_seg, // CS DS ES SS FS GS
disasm_rep, // REPZ/REPNZ
disasm_opcode, // opcode
disasm_opcode2, // used when opcode==0f
disasm_modrm, // modxxxrm
disasm_sib, // scale-index-base
disasm_mem[8], // mem addr value
disasm_data[8]; // data value
} // unnamed namespace
// return: length if success, 0 if error
int disasm(const BYTE *opcode0)
{
const BYTE *opcode = opcode0;
DWORD disasm_len = 0, // 0 if error
disasm_flag = 0, // C_xxx
disasm_memsize = 0, // value = disasm_mem
disasm_datasize = 0, // value = disasm_data
disasm_defdata = 4, // == C_66 ? 2 : 4
disasm_defmem = 4; // == C_67 ? 2 : 4
retry:
disasm_opcode = *opcode++;
switch (disasm_opcode) {
case 0x99: // 7/20/2014 jichi: CDQ, size = 1
break;
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x28: case 0x29: case 0x2a: case 0x2b:
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x38: case 0x39: case 0x3a: case 0x3b:
case 0x62: case 0x63:
case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b:
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
case 0xc4: case 0xc5:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xfe: case 0xff:
disasm_flag |= C_MODRM;
break;
case 0xcd: disasm_datasize += *opcode==0x20 ? 1+4 : 1;
break;
case 0xf6:
case 0xf7: disasm_flag |= C_MODRM;
if (*opcode & 0x38) break;
// continue if <test ..., xx>
case 0x04: case 0x05: case 0x0c: case 0x0d:
case 0x14: case 0x15: case 0x1c: case 0x1d:
case 0x24: case 0x25: case 0x2c: case 0x2d:
case 0x34: case 0x35: case 0x3c: case 0x3d:
if (disasm_opcode & 1)
disasm_datasize += disasm_defdata;
else
disasm_datasize++;
break;
case 0x6a:
case 0xa8:
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xd4: case 0xd5:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0x70: case 0x71: case 0x72: case 0x73:
case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7a: case 0x7b:
case 0x7c: case 0x7d: case 0x7e: case 0x7f:
case 0xeb:
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
disasm_datasize++;
break;
case 0x26: case 0x2e: case 0x36: case 0x3e:
case 0x64: case 0x65:
if (disasm_flag & C_SEG) return 0;
disasm_flag |= C_SEG;
disasm_seg = disasm_opcode;
goto retry;
case 0xf0:
if (disasm_flag & C_LOCK) return 0;
disasm_flag |= C_LOCK;
goto retry;
case 0xf2: case 0xf3:
if (disasm_flag & C_REP) return 0;
disasm_flag |= C_REP;
disasm_rep = disasm_opcode;
goto retry;
case 0x66:
if (disasm_flag & C_66) return 0;
disasm_flag |= C_66;
disasm_defdata = 2;
goto retry;
case 0x67:
if (disasm_flag & C_67) return 0;
disasm_flag |= C_67;
disasm_defmem = 2;
goto retry;
case 0x6b:
case 0x80:
case 0x82:
case 0x83:
case 0xc0:
case 0xc1:
case 0xc6: disasm_datasize++;
disasm_flag |= C_MODRM;
break;
case 0x69:
case 0x81:
case 0xc7:
disasm_datasize += disasm_defdata;
disasm_flag |= C_MODRM;
break;
case 0x9a:
case 0xea: disasm_datasize += 2 + disasm_defdata;
break;
case 0xa0:
case 0xa1:
case 0xa2:
case 0xa3: disasm_memsize += disasm_defmem;
break;
case 0x68:
case 0xa9:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
case 0xe8:
case 0xe9:
disasm_datasize += disasm_defdata;
break;
case 0xc2:
case 0xca: disasm_datasize += 2;
break;
case 0xc8:
disasm_datasize += 3;
break;
case 0xf1:
return 0;
case 0x0f:
// 7/19/2014 jichi: 0x0f1201 = movlps xmm0,qword ptr ds:[ecx]
// Given 0x0f1201, 0x0f will be strip off here and left 0x1201
disasm_flag |= C_OPCODE2;
disasm_opcode2 = *opcode++;
switch (disasm_opcode2) {
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x90: case 0x91: case 0x92: case 0x93:
case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b:
case 0x9c: case 0x9d: case 0x9e: case 0x9f:
case 0xa3:
case 0xa5:
case 0xab:
case 0xad:
case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
case 0xc0:
case 0xc1:
// 7/19/2014 jichi: Add more cases for SSE instructions
// Sample instructions I need to consider
// 0f1201 movlps xmm0,qword ptr ds:[ecx] ; jichi: hook here
// 0f1302 movlps qword ptr ds:[edx],xmm0
case 0x12:
case 0x13:
disasm_flag |= C_MODRM;
break;
case 0x06:
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0xa0: case 0xa1: case 0xa2: case 0xa8:
case 0xa9:
case 0xaa:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
break;
case 0x80: case 0x81: case 0x82: case 0x83:
case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b:
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
disasm_datasize += disasm_defdata;
break;
case 0xa4:
case 0xac:
case 0xba:
default: return 0; // 7/19/2014 jichi: error
} // 0F-switch
break;
} // switch
if (disasm_flag & C_MODRM) {
disasm_modrm = *opcode++;
BYTE mod = disasm_modrm & 0xc0;
BYTE rm = disasm_modrm & 0x07;
if (mod != 0xc0) {
if (mod == 0x40)
disasm_memsize++;
if (mod == 0x80)
disasm_memsize += disasm_defmem;
if (disasm_defmem == 2) { // modrm16
if (mod == 0x00 && rm == 0x06)
disasm_memsize += 2;
} else { // modrm32
if (rm == 0x04) {
disasm_flag |= C_SIB;
disasm_sib = *opcode++;
rm = disasm_sib & 0x07;
}
if (rm == 0x05 && mod == 0x00)
disasm_memsize += 4;
}
}
} // C_MODRM
for (DWORD i = 0; i < disasm_memsize; i++)
disasm_mem[i] = *opcode++;
for (DWORD i = 0; i < disasm_datasize; i++)
disasm_data[i] = *opcode++;
disasm_len = opcode - opcode0;
return disasm_len;
} // disasm
DISASM_END_NAMESPACE
// EOF
#pragma once
// disasm.h
// 1/27/2013 jichi
// Include typedef of BYTE
//#include <windef.h>
#include <windows.h>
//#ifdef QT_CORE_LIB
//# include <qt_windows.h>
//#else
//# include <windows.h>
//#endif
#ifndef DISASM_BEGIN_NAMESPACE
# define DISASM_BEGIN_NAMESPACE
#endif
#ifndef DISASM_END_NAMESPACE
# define DISASM_END_NAMESPACE
#endif
DISASM_BEGIN_NAMESPACE
int disasm(const BYTE *opcode0); // return: op length if success, 0 if error
DISASM_END_NAMESPACE
// EOF
# disasm.pri
# 1/31/2012 jichi
win32 {
DEFINES += WITH_LIB_DISASM
LIBS += -ldisasm
DEPENDPATH += $$PWD
HEADERS += $$PWD/disasm.h
#SOURCES += $$PWD/disasm.cc
}
# EOF
# sys.pro
# 8/21/2013 jichi
# Build ITH_engine.dll
CONFIG += noqt noeh staticlib
include(../../../config.pri)
## Sources
TEMPLATE = lib
TARGET = disasm
HEADERS += disasm.h
SOURCES += disasm.cc
# EOF
# ith/common/common.pri
# 8/9/2011 jichi
# Overwrite ITH headers
#DEFINES += ITH_HAS_CRT # whether ITH is linked with msvcrt
#DEFINES += ITH_HAS_CXX # whether ITH has access to native C++ syntax
DEPENDPATH += $$PWD
HEADERS += \
$$PWD/const.h \
$$PWD/defs.h \
$$PWD/except.h \
$$PWD/growl.h \
$$PWD/memory.h \
$$PWD/string.h \
$$PWD/types.h
DEFINES += _CRT_NON_CONFORMING_SWPRINTFS
# jichi 9/14/2013: Whether using SEH exception handle.
# msvcrt on Windows XP is missin EH
#DEFINES += ITH_HAS_SEH
# jichi 9/22/2013: Whether let ITH manage heap
#DEFINES += ITH_HAS_HEAP
# EOF
#pragma once
// ith/common/const.h
// 8/23/2013 jichi
// Branch: ITH/common.h, rev 128
// jichi 9/9/2013: Another importnat function is lstrcatA, which is already handled by
// Debonosu hooks. Wait until it is really needed by certain games.
// The order of the functions is used in several place.
// I need to recompile all of the dlls to modify the order.
enum HookFunType {
HF_Null = -1
, HF_GetTextExtentPoint32A
, HF_GetGlyphOutlineA
, HF_ExtTextOutA
, HF_TextOutA
, HF_GetCharABCWidthsA
, HF_DrawTextA
, HF_DrawTextExA
//, HF_lstrlenA
, HF_GetTextExtentPoint32W
, HF_GetGlyphOutlineW
, HF_ExtTextOutW
, HF_TextOutW
, HF_GetCharABCWidthsW
, HF_DrawTextW
, HF_DrawTextExW
//, HF_lstrlenW
, HookFunCount // 14
};
// jichi 10/14/2014
#define HOOK_GDI_FUNCTION_LIST \
GetTextExtentPoint32A \
, GetGlyphOutlineA \
, ExtTextOutA \
, TextOutA \
, GetCharABCWidthsA \
, GetTextExtentPoint32W \
, GetGlyphOutlineW \
, ExtTextOutW \
, TextOutW \
, GetCharABCWidthsW \
, DrawTextA \
, DrawTextExA \
, DrawTextW \
, DrawTextExW
enum { HOOK_FUN_COUNT = HookFunCount };
// jichi 1/16/2015: Though called max hook, it means max number of text threads
enum { MAX_HOOK = 32 }; // must be larger than HookFunCount
//enum { HOOK_SECTION_SIZE = 0x2000 }; // default ITH value
// jichi 1/16/2015: Change to a very large number to prevent crash
//enum { MAX_HOOK = 0x100 }; // must be larger than HookFunCount
enum { HOOK_SECTION_SIZE = MAX_HOOK * 0x100 }; // default ITH value is 0x2000 for 32 hook (0x100 per hook)
// jichi 375/2014: Add offset of pusha/pushad
// http://faydoc.tripod.com/cpu/pushad.htm
// http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial
//
// Warning: The offset in ITH has -4 offset comparing to pusha and AGTH
enum pusha_off {
pusha_eax_off = -0x4
, pusha_ecx_off = -0x8
, pusha_edx_off = -0xc
, pusha_ebx_off = -0x10
, pusha_esp_off = -0x14
, pusha_ebp_off = -0x18
, pusha_esi_off = -0x1c
, pusha_edi_off = -0x20
, pusha_off = -0x24 // pushad offset
};
enum IhfCommandType {
IHF_COMMAND = -1 // null type
, IHF_COMMAND_NEW_HOOK = 0
, IHF_COMMAND_REMOVE_HOOK = 1
, IHF_COMMAND_MODIFY_HOOK = 2
, IHF_COMMAND_DETACH = 3
};
enum IhfNotificationType {
IHF_NOTIFICATION = -1 // null type
, IHF_NOTIFICATION_TEXT = 0
, IHF_NOTIFICATION_NEWHOOK = 1
};
// jichi 9/8/2013: The meaning are guessed
// Values must be within DWORD
// Unused values are as follows:
// - 0x100
enum HookParamType : unsigned long {
USING_STRING = 0x1 // type(data) is char* or wchar_t* and has length
, USING_UTF8 = USING_STRING // jichi 10/21/2014: temporarily handled the same way as USING_STRING
, USING_UNICODE = 0x2 // type(data) is wchar_t or wchar_t*
, BIG_ENDIAN = 0x4 // type(data) is char
, DATA_INDIRECT = 0x8
, USING_SPLIT = 0x10 // aware of split time?
, SPLIT_INDIRECT = 0x20
, MODULE_OFFSET = 0x40 // do hash module, and the address is relative to module
, FUNCTION_OFFSET = 0x80 // do hash function, and the address is relative to funccion
, PRINT_DWORD = 0x100 // jichi 12/7/2014: Removed
, STRING_LAST_CHAR = 0x200
, NO_CONTEXT = 0x400
//, EXTERN_HOOK = 0x800 // jichi 10/24/2014: Removed
//, HOOK_AUXILIARY = 0x2000 // jichi 12/13/2013: None of known hooks are auxiliary
, HOOK_ENGINE = 0x4000
, HOOK_ADDITIONAL = 0x8000
// jichi 10/24/2014: Only trigger the dynamic function, do not return any data
, HOOK_EMPTY = 0x800
// jichi 6/1/2014: fix the split value to 0x10001
, FIXING_SPLIT = 0x1000
, RELATIVE_SPLIT = 0x2000 // relative split return address
};
// 6/1/2014: Fixed split value for hok parameter
// Fuse all threads, and prevent floating
enum { FIXED_SPLIT_VALUE = 0x10001 };
// jichi 12/18/2013:
// These dlls are used to guess the range for non-NO_CONTEXT hooks.
//
// Disabling uxtheme.dll would crash certain system: http://tieba.baidu.com/p/2764436254
#define IHF_FILTER_DLL_LIST \
/* ITH original filters */ \
L"gdiplus.dll" /* Graphics functions like TextOutA */ \
, L"lpk.dll" /* Language package scripts and fonts */ \
, L"msctf.dll" /* Text service */ \
, L"psapi.dll" /* Processes */ \
, L"usp10.dll" /* UNICODE rendering */ \
, L"user32.dll" /* Non-graphics functions like lstrlenA */ \
, L"uxtheme.dll" /* Theme */ \
\
/* Windows DLLs */ \
, L"advapi32.dll" /* Advanced services */ \
, L"apphelp.dll" /* Appliation help */ \
, L"audioses.dll" /* Audios */ \
, L"avrt.dll" /* Audio video runtime */ \
, L"cfgmgr32.dll" /* Configuration manager */ \
, L"clbcatq.dll" /* COM query service */ \
, L"comctl32.dll" /* Common control library */ \
, L"comdlg32.dll" /* Common dialogs */ \
, L"crypt32.dll" /* Security cryption */ \
, L"cryptbase.dll"/* Security cryption */ \
, L"cryptsp.dll" /* Security cryption */ \
, L"d3d8thk.dll" /* Direct3D 8 */ \
, L"d3d9.dll" /* Direct3D 9 */ \
, L"dbghelp.dll" /* Debug help */ \
, L"dciman32.dll" /* Display cotrol */ \
, L"devobj.dll" /* Device object */ \
, L"ddraw.dll" /* Direct draw */ \
, L"dinput.dll" /* Diret input */ \
, L"dsound.dll" /* Direct sound */ \
, L"DShowRdpFilter.dll" /* Direct show */ \
, L"dwmapi.dll" /* Windows manager */ \
, L"gdi32.dll" /* GDI32 */ \
, L"hid.dll" /* HID user library */ \
, L"iertutil.dll" /* IE runtime */ \
, L"imagehlp.dll" /* Image help */ \
, L"imm32.dll" /* Input method */ \
, L"ksuser.dll" /* Kernel service */ \
, L"ole32.dll" /* COM OLE */ \
, L"oleacc.dll" /* OLE access */ \
, L"oleaut32.dll" /* COM OLE */ \
, L"kernel.dll" /* Kernel functions */ \
, L"kernelbase.dll" /* Kernel functions */ \
, L"midimap.dll" /* MIDI */ \
, L"mmdevapi.dll" /* Audio device */ \
, L"mpr.dll" /* Winnet */ \
, L"msacm32.dll" /* MS ACM */ \
, L"msacm32.drv" /* MS ACM */ \
, L"msasn1.dll" /* Encoding/decoding */ \
, L"msimg32.dll" /* Image */ \
, L"msvfw32.dll" /* Media play */ \
, L"netapi32.dll" /* Network service */ \
, L"normaliz.dll" /* Normalize */ \
, L"nsi.dll" /* NSI */ \
, L"ntdll.dll" /* NT functions */ \
, L"ntmarta.dll" /* NT MARTA */ \
, L"nvd3dum.dll" /* Direct 3D */ \
, L"powerprof.dll"/* Power profile */ \
, L"profapi.dll" /* Profile API */ \
, L"propsys.dll" /* System properties */ \
, L"quartz.dll" /* OpenGL */ \
, L"rpcrt4.dll" /* RPC runtime */ \
, L"rpcrtremote.dll" /* RPC runtime */ \
, L"rsabase.dll" /* RSA cryption */ \
, L"rsaenh.dll" /* RSA cryption */ \
, L"schannel.dll" /* Security channel */ \
, L"sechost.dll" /* Service host */ \
, L"setupapi.dll" /* Setup service */ \
, L"shell32.dll" /* Windows shell */ \
, L"shlwapi.dll" /* Light-weighted shell */ \
, L"slc.dll" /* SLC */ \
, L"srvcli.dll" /* Service client */ \
, L"version.dll" /* Windows version */ \
, L"wdmaud.drv" /* Wave output */ \
, L"wldap32.dll" /* Wireless */ \
, L"wininet.dll" /* Internet access */ \
, L"winmm.dll" /* Windows sound */ \
, L"winsta.dll" /* Connection system */ \
, L"wtsapi32.dll" /* Windows terminal server */ \
, L"wintrust.dll" /* Windows trust */ \
, L"wsock32.dll" /* Windows sock */ \
, L"ws2_32.dll" /* Terminal server */ \
, L"wkscli.dll" /* ACIS */ \
\
/* MSVCRT */ \
, L"msvcrt.dll" /* VC rutime */ \
, L"msvcr80.dll" /* VC rutime 8 */ \
, L"msvcp80.dll" /* VC rutime 8 */ \
, L"msvcr90.dll" /* VC rutime 9 */ \
, L"msvcp90.dll" /* VC rutime 9 */ \
, L"msvcr100.dll" /* VC rutime 10 */ \
, L"msvcp100.dll" /* VC rutime 10 */ \
, L"msvcr110.dll" /* VC rutime 11 */ \
, L"msvcp110.dll" /* VC rutime 11 */ \
\
/* VNR */ \
, L"vnrhook.dll" \
, L"vnrhookxp.dll" \
\
/* Sogou IME */ \
, L"sogoupy.ime" \
, L"PicFace.dll" \
, L"AddressSearch.dll" \
\
/* QQ IME */ \
, L"QQPINYIN.IME" \
\
/* AlphaROM */ \
, L"kDays.dll" \
\
/* 360Safe */ \
, L"safemon.dll" \
\
/* Locale changers */ \
, L"AlLayer.dll" /* AppLocale */ \
, L"LocaleEmulator.dll" /* Locale Emulator */ \
, L"LSH.dll" /* LocaleSwitch */ \
, L"ntleah.dll" /* NTLEA */
// Google Japanese IME
//, L"GoogleIMEJaTIP32.dll"
enum {
//IHF_FILTER_COUNT = 7
IHF_FILTER_COUNT = 7 + 72 + 9 + 4 + 3 + 1 + 1 + 1 + 4 // count of total dlls to filter
, IHF_FILTER_CAPACITY = IHF_FILTER_COUNT + 1 // one more than the dll count
};
// EOF