2288 lines
73 KiB
C++
2288 lines
73 KiB
C++
/**
|
|
@file value.cpp
|
|
|
|
@brief Implements the value class.
|
|
*/
|
|
|
|
#include "value.h"
|
|
#include "variable.h"
|
|
#include "debugger.h"
|
|
#include "console.h"
|
|
#include "math.h"
|
|
#include "memory.h"
|
|
#include "addrinfo.h"
|
|
#include "symbolinfo.h"
|
|
#include "module.h"
|
|
#include "label.h"
|
|
|
|
static bool dosignedcalc = false;
|
|
|
|
/**
|
|
\brief Returns whether we do signed or unsigned calculations.
|
|
\return true if we do signed calculations, false for unsigned calculationss.
|
|
*/
|
|
bool valuesignedcalc()
|
|
{
|
|
return dosignedcalc;
|
|
}
|
|
|
|
/**
|
|
\brief Set whether we do signed or unsigned calculations.
|
|
\param a true for signed calculations, false for unsigned calculations.
|
|
*/
|
|
void valuesetsignedcalc(bool a)
|
|
{
|
|
dosignedcalc = a;
|
|
}
|
|
|
|
/**
|
|
\brief Check if a string is a flag.
|
|
\param string The string to check.
|
|
\return true if the string is a flag, false otherwise.
|
|
*/
|
|
static bool isflag(const char* string)
|
|
{
|
|
if(scmp(string, "cf"))
|
|
return true;
|
|
if(scmp(string, "pf"))
|
|
return true;
|
|
if(scmp(string, "af"))
|
|
return true;
|
|
if(scmp(string, "zf"))
|
|
return true;
|
|
if(scmp(string, "sf"))
|
|
return true;
|
|
if(scmp(string, "tf"))
|
|
return true;
|
|
if(scmp(string, "if"))
|
|
return true;
|
|
if(scmp(string, "df"))
|
|
return true;
|
|
if(scmp(string, "of"))
|
|
return true;
|
|
if(scmp(string, "rf"))
|
|
return true;
|
|
if(scmp(string, "vm"))
|
|
return true;
|
|
if(scmp(string, "ac"))
|
|
return true;
|
|
if(scmp(string, "vif"))
|
|
return true;
|
|
if(scmp(string, "vip"))
|
|
return true;
|
|
if(scmp(string, "id"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
\brief Check if a string is a register.
|
|
\param string The string to check.
|
|
\return true if the string is a register, false otherwise.
|
|
*/
|
|
static bool isregister(const char* string)
|
|
{
|
|
if(scmp(string, "eax"))
|
|
return true;
|
|
if(scmp(string, "ebx"))
|
|
return true;
|
|
if(scmp(string, "ecx"))
|
|
return true;
|
|
if(scmp(string, "edx"))
|
|
return true;
|
|
if(scmp(string, "edi"))
|
|
return true;
|
|
if(scmp(string, "esi"))
|
|
return true;
|
|
if(scmp(string, "ebp"))
|
|
return true;
|
|
if(scmp(string, "esp"))
|
|
return true;
|
|
if(scmp(string, "eip"))
|
|
return true;
|
|
if(scmp(string, "eflags"))
|
|
return true;
|
|
|
|
if(scmp(string, "ax"))
|
|
return true;
|
|
if(scmp(string, "bx"))
|
|
return true;
|
|
if(scmp(string, "cx"))
|
|
return true;
|
|
if(scmp(string, "dx"))
|
|
return true;
|
|
if(scmp(string, "si"))
|
|
return true;
|
|
if(scmp(string, "di"))
|
|
return true;
|
|
if(scmp(string, "bp"))
|
|
return true;
|
|
if(scmp(string, "sp"))
|
|
return true;
|
|
if(scmp(string, "ip"))
|
|
return true;
|
|
|
|
if(scmp(string, "ah"))
|
|
return true;
|
|
if(scmp(string, "al"))
|
|
return true;
|
|
if(scmp(string, "bh"))
|
|
return true;
|
|
if(scmp(string, "bl"))
|
|
return true;
|
|
if(scmp(string, "ch"))
|
|
return true;
|
|
if(scmp(string, "cl"))
|
|
return true;
|
|
if(scmp(string, "dh"))
|
|
return true;
|
|
if(scmp(string, "dl"))
|
|
return true;
|
|
if(scmp(string, "sih"))
|
|
return true;
|
|
if(scmp(string, "sil"))
|
|
return true;
|
|
if(scmp(string, "dih"))
|
|
return true;
|
|
if(scmp(string, "dil"))
|
|
return true;
|
|
if(scmp(string, "bph"))
|
|
return true;
|
|
if(scmp(string, "bpl"))
|
|
return true;
|
|
if(scmp(string, "sph"))
|
|
return true;
|
|
if(scmp(string, "spl"))
|
|
return true;
|
|
if(scmp(string, "iph"))
|
|
return true;
|
|
if(scmp(string, "ipl"))
|
|
return true;
|
|
|
|
if(scmp(string, "dr0"))
|
|
return true;
|
|
if(scmp(string, "dr1"))
|
|
return true;
|
|
if(scmp(string, "dr2"))
|
|
return true;
|
|
if(scmp(string, "dr3"))
|
|
return true;
|
|
if(scmp(string, "dr6") or scmp(string, "dr4"))
|
|
return true;
|
|
if(scmp(string, "dr7") or scmp(string, "dr5"))
|
|
return true;
|
|
|
|
if(scmp(string, "cip"))
|
|
return true;
|
|
if(scmp(string, "csp"))
|
|
return true;
|
|
if(scmp(string, "cflags"))
|
|
return true;
|
|
|
|
if(scmp(string, "gs"))
|
|
return true;
|
|
if(scmp(string, "fs"))
|
|
return true;
|
|
if(scmp(string, "es"))
|
|
return true;
|
|
if(scmp(string, "ds"))
|
|
return true;
|
|
if(scmp(string, "cs"))
|
|
return true;
|
|
if(scmp(string, "ss"))
|
|
return true;
|
|
|
|
#ifndef _WIN64
|
|
return false;
|
|
#endif // _WIN64
|
|
if(scmp(string, "rax"))
|
|
return true;
|
|
if(scmp(string, "rbx"))
|
|
return true;
|
|
if(scmp(string, "rcx"))
|
|
return true;
|
|
if(scmp(string, "rdx"))
|
|
return true;
|
|
if(scmp(string, "rdi"))
|
|
return true;
|
|
if(scmp(string, "rsi"))
|
|
return true;
|
|
if(scmp(string, "rbp"))
|
|
return true;
|
|
if(scmp(string, "rsp"))
|
|
return true;
|
|
if(scmp(string, "rip"))
|
|
return true;
|
|
if(scmp(string, "rflags"))
|
|
return true;
|
|
if(scmp(string, "r8"))
|
|
return true;
|
|
if(scmp(string, "r9"))
|
|
return true;
|
|
if(scmp(string, "r10"))
|
|
return true;
|
|
if(scmp(string, "r11"))
|
|
return true;
|
|
if(scmp(string, "r12"))
|
|
return true;
|
|
if(scmp(string, "r13"))
|
|
return true;
|
|
if(scmp(string, "r14"))
|
|
return true;
|
|
if(scmp(string, "r15"))
|
|
return true;
|
|
if(scmp(string, "r8d"))
|
|
return true;
|
|
if(scmp(string, "r9d"))
|
|
return true;
|
|
if(scmp(string, "r10d"))
|
|
return true;
|
|
if(scmp(string, "r11d"))
|
|
return true;
|
|
if(scmp(string, "r12d"))
|
|
return true;
|
|
if(scmp(string, "r13d"))
|
|
return true;
|
|
if(scmp(string, "r14d"))
|
|
return true;
|
|
if(scmp(string, "r15d"))
|
|
return true;
|
|
if(scmp(string, "r8w"))
|
|
return true;
|
|
if(scmp(string, "r9w"))
|
|
return true;
|
|
if(scmp(string, "r10w"))
|
|
return true;
|
|
if(scmp(string, "r11w"))
|
|
return true;
|
|
if(scmp(string, "r12w"))
|
|
return true;
|
|
if(scmp(string, "r13w"))
|
|
return true;
|
|
if(scmp(string, "r14w"))
|
|
return true;
|
|
if(scmp(string, "r15w"))
|
|
return true;
|
|
if(scmp(string, "r8b"))
|
|
return true;
|
|
if(scmp(string, "r9b"))
|
|
return true;
|
|
if(scmp(string, "r10b"))
|
|
return true;
|
|
if(scmp(string, "r11b"))
|
|
return true;
|
|
if(scmp(string, "r12b"))
|
|
return true;
|
|
if(scmp(string, "r13b"))
|
|
return true;
|
|
if(scmp(string, "r14b"))
|
|
return true;
|
|
if(scmp(string, "r15b"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
#define MXCSRFLAG_IE 0x1
|
|
#define MXCSRFLAG_DE 0x2
|
|
#define MXCSRFLAG_ZE 0x4
|
|
#define MXCSRFLAG_OE 0x8
|
|
#define MXCSRFLAG_UE 0x10
|
|
#define MXCSRFLAG_PE 0x20
|
|
#define MXCSRFLAG_DAZ 0x40
|
|
#define MXCSRFLAG_IM 0x80
|
|
#define MXCSRFLAG_DM 0x100
|
|
#define MXCSRFLAG_ZM 0x200
|
|
#define MXCSRFLAG_OM 0x400
|
|
#define MXCSRFLAG_UM 0x800
|
|
#define MXCSRFLAG_PM 0x1000
|
|
#define MXCSRFLAG_FZ 0x8000
|
|
|
|
typedef struct
|
|
{
|
|
char* name;
|
|
unsigned int flag;
|
|
|
|
} FLAG_NAME_VALUE_TABLE_t;
|
|
|
|
#define MXCSR_NAME_FLAG_TABLE_ENTRY(flag_name) { #flag_name, MXCSRFLAG_##flag_name }
|
|
|
|
/**
|
|
\brief Gets the MXCSR flag AND value from a string.
|
|
\param string The flag name.
|
|
\return The value to AND the MXCSR value with to get the flag. 0 when not found.
|
|
*/
|
|
static unsigned int getmxcsrflagfromstring(const char* string)
|
|
{
|
|
static FLAG_NAME_VALUE_TABLE_t mxcsrnameflagtable[] =
|
|
{
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(IE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(DE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(ZE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(OE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(UE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(PE),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(DAZ),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(IM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(DM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(ZM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(OM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(UM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(PM),
|
|
MXCSR_NAME_FLAG_TABLE_ENTRY(FZ)
|
|
};
|
|
|
|
for(int i = 0; i < (sizeof(mxcsrnameflagtable) / sizeof(*mxcsrnameflagtable)); i++)
|
|
{
|
|
if(scmp(string, mxcsrnameflagtable[i].name))
|
|
return mxcsrnameflagtable[i].flag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Gets the MXCSR flag from a string and a flags value.
|
|
\param mxcsrflags The flags value to get the flag from.
|
|
\param string The string with the flag name.
|
|
\return true if the flag is 1, false if the flag is 0.
|
|
*/
|
|
bool valmxcsrflagfromstring(uint mxcsrflags, const char* string)
|
|
{
|
|
unsigned int flag = getmxcsrflagfromstring(string);
|
|
if(flag == 0)
|
|
return false;
|
|
|
|
return (bool)((int)(mxcsrflags & flag) != 0);
|
|
}
|
|
|
|
#define x87STATUSWORD_FLAG_I 0x1
|
|
#define x87STATUSWORD_FLAG_D 0x2
|
|
#define x87STATUSWORD_FLAG_Z 0x4
|
|
#define x87STATUSWORD_FLAG_O 0x8
|
|
#define x87STATUSWORD_FLAG_U 0x10
|
|
#define x87STATUSWORD_FLAG_P 0x20
|
|
#define x87STATUSWORD_FLAG_SF 0x40
|
|
#define x87STATUSWORD_FLAG_IR 0x80
|
|
#define x87STATUSWORD_FLAG_C0 0x100
|
|
#define x87STATUSWORD_FLAG_C1 0x200
|
|
#define x87STATUSWORD_FLAG_C2 0x400
|
|
#define x87STATUSWORD_FLAG_C3 0x4000
|
|
#define x87STATUSWORD_FLAG_B 0x8000
|
|
|
|
#define X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(flag_name) { #flag_name, x87STATUSWORD_FLAG_##flag_name }
|
|
|
|
/**
|
|
\brief Gets the x87 status word AND value from a string.
|
|
\param string The status word name.
|
|
\return The value to AND the status word with to get the flag. 0 when not found.
|
|
*/
|
|
static unsigned int getx87statuswordflagfromstring(const char* string)
|
|
{
|
|
static FLAG_NAME_VALUE_TABLE_t statuswordflagtable[] =
|
|
{
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(I),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(D),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(Z),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(O),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(U),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(P),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(SF),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(IR),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(C0),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(C1),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(C2),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(C3),
|
|
X87STATUSWORD_NAME_FLAG_TABLE_ENTRY(B)
|
|
};
|
|
|
|
for(int i = 0; i < (sizeof(statuswordflagtable) / sizeof(*statuswordflagtable)); i++)
|
|
{
|
|
if(scmp(string, statuswordflagtable[i].name))
|
|
return statuswordflagtable[i].flag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Gets an x87 status flag from a string.
|
|
\param statusword The status word value.
|
|
\param string The flag name.
|
|
\return true if the flag is 1, false if the flag is 0.
|
|
*/
|
|
bool valx87statuswordflagfromstring(uint statusword, const char* string)
|
|
{
|
|
unsigned int flag = getx87statuswordflagfromstring(string);
|
|
if(flag == 0)
|
|
return false;
|
|
|
|
return (bool)((int)(statusword & flag) != 0);
|
|
}
|
|
|
|
#define x87CONTROLWORD_FLAG_IM 0x1
|
|
#define x87CONTROLWORD_FLAG_DM 0x2
|
|
#define x87CONTROLWORD_FLAG_ZM 0x4
|
|
#define x87CONTROLWORD_FLAG_OM 0x8
|
|
#define x87CONTROLWORD_FLAG_UM 0x10
|
|
#define x87CONTROLWORD_FLAG_PM 0x20
|
|
#define x87CONTROLWORD_FLAG_IEM 0x80
|
|
#define x87CONTROLWORD_FLAG_IC 0x1000
|
|
|
|
#define X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(flag_name) { #flag_name, x87CONTROLWORD_FLAG_##flag_name }
|
|
|
|
/**
|
|
\brief Gets the x87 control word flag AND value from a string.
|
|
\param string The name of the control word.
|
|
\return The value to AND the control word with to get the flag. 0 when not found.
|
|
*/
|
|
static unsigned int getx87controlwordflagfromstring(const char* string)
|
|
{
|
|
static FLAG_NAME_VALUE_TABLE_t controlwordflagtable[] =
|
|
{
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(IM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(DM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(ZM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(OM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(UM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(PM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(IEM),
|
|
X87CONTROLWORD_NAME_FLAG_TABLE_ENTRY(IC)
|
|
};
|
|
|
|
for(int i = 0; i < (sizeof(controlwordflagtable) / sizeof(*controlwordflagtable)); i++)
|
|
{
|
|
if(scmp(string, controlwordflagtable[i].name))
|
|
return controlwordflagtable[i].flag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Get an x87 control word flag from a string.
|
|
\param controlword The control word to get the flag from.
|
|
\param string The flag name.
|
|
\return true if the flag is 1, false when the flag is 0.
|
|
*/
|
|
bool valx87controlwordflagfromstring(uint controlword, const char* string)
|
|
{
|
|
unsigned int flag = getx87controlwordflagfromstring(string);
|
|
|
|
if(flag == 0)
|
|
return false;
|
|
|
|
return (bool)((int)(controlword & flag) != 0);
|
|
}
|
|
|
|
/**
|
|
\brief Gets the MXCSR field from a string.
|
|
\param mxcsrflags The mxcsrflags to get the field from.
|
|
\param string The name of the field (should be "RC").
|
|
\return The MXCSR field word.
|
|
*/
|
|
unsigned short valmxcsrfieldfromstring(uint mxcsrflags, const char* string)
|
|
{
|
|
if(scmp(string, "RC"))
|
|
return ((mxcsrflags & 0x6000) >> 13);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Gets the x87 status word field from a string.
|
|
\param statusword The status word to get the field from.
|
|
\param string The name of the field (should be "TOP").
|
|
\return The x87 status word field.
|
|
*/
|
|
unsigned short valx87statuswordfieldfromstring(uint statusword, const char* string)
|
|
{
|
|
if(scmp(string, "TOP"))
|
|
return ((statusword & 0x3800) >> 11);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Gets the x87 control word field from a string.
|
|
\param controlword The control word to get the field from.
|
|
\param string The name of the field.
|
|
\return The x87 control word field.
|
|
*/
|
|
unsigned short valx87controlwordfieldfromstring(uint controlword, const char* string)
|
|
{
|
|
if(scmp(string, "PC"))
|
|
return ((controlword & 0x300) >> 8);
|
|
if(scmp(string, "RC"))
|
|
return ((controlword & 0xC00) >> 10);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Gets a flag from a string.
|
|
\param eflags The eflags value to get the flag from.
|
|
\param string The name of the flag.
|
|
\return true if the flag equals to 1, false if the flag is 0 or not found.
|
|
*/
|
|
bool valflagfromstring(uint eflags, const char* string)
|
|
{
|
|
if(scmp(string, "cf"))
|
|
return (bool)((int)(eflags & 0x1) != 0);
|
|
if(scmp(string, "pf"))
|
|
return (bool)((int)(eflags & 0x4) != 0);
|
|
if(scmp(string, "af"))
|
|
return (bool)((int)(eflags & 0x10) != 0);
|
|
if(scmp(string, "zf"))
|
|
return (bool)((int)(eflags & 0x40) != 0);
|
|
if(scmp(string, "sf"))
|
|
return (bool)((int)(eflags & 0x80) != 0);
|
|
if(scmp(string, "tf"))
|
|
return (bool)((int)(eflags & 0x100) != 0);
|
|
if(scmp(string, "if"))
|
|
return (bool)((int)(eflags & 0x200) != 0);
|
|
if(scmp(string, "df"))
|
|
return (bool)((int)(eflags & 0x400) != 0);
|
|
if(scmp(string, "of"))
|
|
return (bool)((int)(eflags & 0x800) != 0);
|
|
if(scmp(string, "rf"))
|
|
return (bool)((int)(eflags & 0x10000) != 0);
|
|
if(scmp(string, "vm"))
|
|
return (bool)((int)(eflags & 0x20000) != 0);
|
|
if(scmp(string, "ac"))
|
|
return (bool)((int)(eflags & 0x40000) != 0);
|
|
if(scmp(string, "vif"))
|
|
return (bool)((int)(eflags & 0x80000) != 0);
|
|
if(scmp(string, "vip"))
|
|
return (bool)((int)(eflags & 0x100000) != 0);
|
|
if(scmp(string, "id"))
|
|
return (bool)((int)(eflags & 0x200000) != 0);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
\brief Sets a flag value.
|
|
\param string The name of the flag.
|
|
\param set The value of the flag.
|
|
\return true if the flag was successfully set, false otherwise.
|
|
*/
|
|
static bool setflag(const char* string, bool set)
|
|
{
|
|
uint eflags = GetContextDataEx(hActiveThread, UE_CFLAGS);
|
|
uint xorval = 0;
|
|
uint flag = 0;
|
|
if(scmp(string, "cf"))
|
|
flag = 0x1;
|
|
else if(scmp(string, "pf"))
|
|
flag = 0x4;
|
|
else if(scmp(string, "af"))
|
|
flag = 0x10;
|
|
else if(scmp(string, "zf"))
|
|
flag = 0x40;
|
|
else if(scmp(string, "sf"))
|
|
flag = 0x80;
|
|
else if(scmp(string, "tf"))
|
|
flag = 0x100;
|
|
else if(scmp(string, "if"))
|
|
flag = 0x200;
|
|
else if(scmp(string, "df"))
|
|
flag = 0x400;
|
|
else if(scmp(string, "of"))
|
|
flag = 0x800;
|
|
else if(scmp(string, "rf"))
|
|
flag = 0x10000;
|
|
else if(scmp(string, "vm"))
|
|
flag = 0x20000;
|
|
else if(scmp(string, "ac"))
|
|
flag = 0x40000;
|
|
else if(scmp(string, "vif"))
|
|
flag = 0x80000;
|
|
else if(scmp(string, "vip"))
|
|
flag = 0x100000;
|
|
else if(scmp(string, "id"))
|
|
flag = 0x200000;
|
|
if(eflags & flag and !set)
|
|
xorval = flag;
|
|
else if(set)
|
|
xorval = flag;
|
|
return SetContextDataEx(hActiveThread, UE_CFLAGS, eflags ^ xorval);
|
|
}
|
|
|
|
/**
|
|
\brief Gets a register from a string.
|
|
\param [out] size This function can store the register size in bytes in this parameter. Can be null, in that case it will be ignored.
|
|
\param string The name of the register to get.
|
|
\return The register value.
|
|
*/
|
|
static uint getregister(int* size, const char* string)
|
|
{
|
|
if(size)
|
|
*size = 4;
|
|
if(scmp(string, "eax"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EAX);
|
|
}
|
|
if(scmp(string, "ebx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EBX);
|
|
}
|
|
if(scmp(string, "ecx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_ECX);
|
|
}
|
|
if(scmp(string, "edx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EDX);
|
|
}
|
|
if(scmp(string, "edi"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EDI);
|
|
}
|
|
if(scmp(string, "esi"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_ESI);
|
|
}
|
|
if(scmp(string, "ebp"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EBP);
|
|
}
|
|
if(scmp(string, "esp"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_ESP);
|
|
}
|
|
if(scmp(string, "eip"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EIP);
|
|
}
|
|
if(scmp(string, "eflags"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_EFLAGS);
|
|
}
|
|
|
|
if(scmp(string, "gs"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_GS);
|
|
}
|
|
if(scmp(string, "fs"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_FS);
|
|
}
|
|
if(scmp(string, "es"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_ES);
|
|
}
|
|
if(scmp(string, "ds"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_DS);
|
|
}
|
|
if(scmp(string, "cs"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_CS);
|
|
}
|
|
if(scmp(string, "ss"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_SEG_SS);
|
|
}
|
|
|
|
if(size)
|
|
*size = 2;
|
|
if(scmp(string, "ax"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EAX);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "bx"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBX);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "cx"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ECX);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "dx"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDX);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "si"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESI);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "di"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDI);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "bp"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBP);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "sp"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESP);
|
|
return val & 0xFFFF;
|
|
}
|
|
if(scmp(string, "ip"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EIP);
|
|
return val & 0xFFFF;
|
|
}
|
|
|
|
if(size)
|
|
*size = 1;
|
|
if(scmp(string, "ah"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EAX);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "al"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EAX);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "bh"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBX);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "bl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBX);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "ch"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ECX);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "cl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ECX);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "dh"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDX);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "dl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDX);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "sih"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESI);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "sil"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESI);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "dih"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDI);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "dil"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EDI);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "bph"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBP);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "bpl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EBP);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "sph"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESP);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "spl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_ESP);
|
|
return val & 0xFF;
|
|
}
|
|
if(scmp(string, "iph"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EIP);
|
|
return (val >> 8) & 0xFF;
|
|
}
|
|
if(scmp(string, "ipl"))
|
|
{
|
|
uint val = GetContextDataEx(hActiveThread, UE_EIP);
|
|
return val & 0xFF;
|
|
}
|
|
|
|
if(size)
|
|
*size = sizeof(uint);
|
|
if(scmp(string, "dr0"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR0);
|
|
}
|
|
if(scmp(string, "dr1"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR1);
|
|
}
|
|
if(scmp(string, "dr2"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR2);
|
|
}
|
|
if(scmp(string, "dr3"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR3);
|
|
}
|
|
if(scmp(string, "dr6") or scmp(string, "dr4"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR6);
|
|
}
|
|
if(scmp(string, "dr7") or scmp(string, "dr5"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_DR7);
|
|
}
|
|
|
|
if(scmp(string, "cip"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_CIP);
|
|
}
|
|
if(scmp(string, "csp"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_CSP);
|
|
}
|
|
if(scmp(string, "cflags"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_CFLAGS);
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if(size)
|
|
*size = 8;
|
|
if(scmp(string, "rax"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RAX);
|
|
}
|
|
if(scmp(string, "rbx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RBX);
|
|
}
|
|
if(scmp(string, "rcx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RCX);
|
|
}
|
|
if(scmp(string, "rdx"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RDX);
|
|
}
|
|
if(scmp(string, "rdi"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RDI);
|
|
}
|
|
if(scmp(string, "rsi"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RSI);
|
|
}
|
|
if(scmp(string, "rbp"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RBP);
|
|
}
|
|
if(scmp(string, "rsp"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RSP);
|
|
}
|
|
if(scmp(string, "rip"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RIP);
|
|
}
|
|
if(scmp(string, "rflags"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_RFLAGS);
|
|
}
|
|
if(scmp(string, "r8"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R8);
|
|
}
|
|
if(scmp(string, "r9"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R9);
|
|
}
|
|
if(scmp(string, "r10"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R10);
|
|
}
|
|
if(scmp(string, "r11"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R11);
|
|
}
|
|
if(scmp(string, "r12"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R12);
|
|
}
|
|
if(scmp(string, "r13"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R13);
|
|
}
|
|
if(scmp(string, "r14"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R14);
|
|
}
|
|
if(scmp(string, "r15"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R15);
|
|
}
|
|
|
|
if(size)
|
|
*size = 4;
|
|
if(scmp(string, "r8d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R8) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r9d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R9) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r10d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R10) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r11d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R11) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r12d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R12) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r13d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R13) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r14d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R14) & 0xFFFFFFFF;
|
|
}
|
|
if(scmp(string, "r15d"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R15) & 0xFFFFFFFF;
|
|
}
|
|
|
|
if(size)
|
|
*size = 2;
|
|
if(scmp(string, "r8w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R8) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r9w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R9) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r10w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R10) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r11w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R11) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r12w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R12) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r13w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R13) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r14w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R14) & 0xFFFF;
|
|
}
|
|
if(scmp(string, "r15w"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R15) & 0xFFFF;
|
|
}
|
|
|
|
if(size)
|
|
*size = 1;
|
|
if(scmp(string, "r8b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R8) & 0xFF;
|
|
}
|
|
if(scmp(string, "r9b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R9) & 0xFF;
|
|
}
|
|
if(scmp(string, "r10b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R10) & 0xFF;
|
|
}
|
|
if(scmp(string, "r11b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R11) & 0xFF;
|
|
}
|
|
if(scmp(string, "r12b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R12) & 0xFF;
|
|
}
|
|
if(scmp(string, "r13b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R13) & 0xFF;
|
|
}
|
|
if(scmp(string, "r14b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R14) & 0xFF;
|
|
}
|
|
if(scmp(string, "r15b"))
|
|
{
|
|
return GetContextDataEx(hActiveThread, UE_R15) & 0xFF;
|
|
}
|
|
#endif //_WIN64
|
|
|
|
if(size)
|
|
*size = 0;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Sets a register value based on the register name.
|
|
\param string The name of the register to set.
|
|
\param value The new register value.
|
|
\return true if the register was set, false otherwise.
|
|
*/
|
|
static bool setregister(const char* string, uint value)
|
|
{
|
|
if(scmp(string, "eax"))
|
|
return SetContextDataEx(hActiveThread, UE_EAX, value & 0xFFFFFFFF);
|
|
if(scmp(string, "ebx"))
|
|
return SetContextDataEx(hActiveThread, UE_EBX, value & 0xFFFFFFFF);
|
|
if(scmp(string, "ecx"))
|
|
return SetContextDataEx(hActiveThread, UE_ECX, value & 0xFFFFFFFF);
|
|
if(scmp(string, "edx"))
|
|
return SetContextDataEx(hActiveThread, UE_EDX, value & 0xFFFFFFFF);
|
|
if(scmp(string, "edi"))
|
|
return SetContextDataEx(hActiveThread, UE_EDI, value & 0xFFFFFFFF);
|
|
if(scmp(string, "esi"))
|
|
return SetContextDataEx(hActiveThread, UE_ESI, value & 0xFFFFFFFF);
|
|
if(scmp(string, "ebp"))
|
|
return SetContextDataEx(hActiveThread, UE_EBP, value & 0xFFFFFFFF);
|
|
if(scmp(string, "esp"))
|
|
return SetContextDataEx(hActiveThread, UE_ESP, value & 0xFFFFFFFF);
|
|
if(scmp(string, "eip"))
|
|
return SetContextDataEx(hActiveThread, UE_EIP, value & 0xFFFFFFFF);
|
|
if(scmp(string, "eflags"))
|
|
return SetContextDataEx(hActiveThread, UE_EFLAGS, value & 0xFFFFFFFF);
|
|
|
|
if(scmp(string, "gs"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_GS, value & 0xFFFF);
|
|
if(scmp(string, "fs"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_FS, value & 0xFFFF);
|
|
if(scmp(string, "es"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_ES, value & 0xFFFF);
|
|
if(scmp(string, "ds"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_DS, value & 0xFFFF);
|
|
if(scmp(string, "cs"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_CS, value & 0xFFFF);
|
|
if(scmp(string, "ss"))
|
|
return SetContextDataEx(hActiveThread, UE_SEG_SS, value & 0xFFFF);
|
|
|
|
if(scmp(string, "ax"))
|
|
return SetContextDataEx(hActiveThread, UE_EAX, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EAX) & 0xFFFF0000));
|
|
if(scmp(string, "bx"))
|
|
return SetContextDataEx(hActiveThread, UE_EBX, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EBX) & 0xFFFF0000));
|
|
if(scmp(string, "cx"))
|
|
return SetContextDataEx(hActiveThread, UE_ECX, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_ECX) & 0xFFFF0000));
|
|
if(scmp(string, "dx"))
|
|
return SetContextDataEx(hActiveThread, UE_EDX, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EDX) & 0xFFFF0000));
|
|
if(scmp(string, "si"))
|
|
return SetContextDataEx(hActiveThread, UE_ESI, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_ESI) & 0xFFFF0000));
|
|
if(scmp(string, "di"))
|
|
return SetContextDataEx(hActiveThread, UE_EDI, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EDI) & 0xFFFF0000));
|
|
if(scmp(string, "bp"))
|
|
return SetContextDataEx(hActiveThread, UE_EBP, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EBP) & 0xFFFF0000));
|
|
if(scmp(string, "sp"))
|
|
return SetContextDataEx(hActiveThread, UE_ESP, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_ESP) & 0xFFFF0000));
|
|
if(scmp(string, "ip"))
|
|
return SetContextDataEx(hActiveThread, UE_EIP, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_EIP) & 0xFFFF0000));
|
|
|
|
if(scmp(string, "ah"))
|
|
return SetContextDataEx(hActiveThread, UE_EAX, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EAX) & 0xFFFF00FF));
|
|
if(scmp(string, "al"))
|
|
return SetContextDataEx(hActiveThread, UE_EAX, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EAX) & 0xFFFFFF00));
|
|
if(scmp(string, "bh"))
|
|
return SetContextDataEx(hActiveThread, UE_EBX, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EBX) & 0xFFFF00FF));
|
|
if(scmp(string, "bl"))
|
|
return SetContextDataEx(hActiveThread, UE_EBX, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EBX) & 0xFFFFFF00));
|
|
if(scmp(string, "ch"))
|
|
return SetContextDataEx(hActiveThread, UE_ECX, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_ECX) & 0xFFFF00FF));
|
|
if(scmp(string, "cl"))
|
|
return SetContextDataEx(hActiveThread, UE_ECX, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_ECX) & 0xFFFFFF00));
|
|
if(scmp(string, "dh"))
|
|
return SetContextDataEx(hActiveThread, UE_EDX, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EDX) & 0xFFFF00FF));
|
|
if(scmp(string, "dl"))
|
|
return SetContextDataEx(hActiveThread, UE_EDX, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EDX) & 0xFFFFFF00));
|
|
if(scmp(string, "sih"))
|
|
return SetContextDataEx(hActiveThread, UE_ESI, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_ESI) & 0xFFFF00FF));
|
|
if(scmp(string, "sil"))
|
|
return SetContextDataEx(hActiveThread, UE_ESI, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_ESI) & 0xFFFFFF00));
|
|
if(scmp(string, "dih"))
|
|
return SetContextDataEx(hActiveThread, UE_EDI, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EDI) & 0xFFFF00FF));
|
|
if(scmp(string, "dil"))
|
|
return SetContextDataEx(hActiveThread, UE_EDI, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EDI) & 0xFFFFFF00));
|
|
if(scmp(string, "bph"))
|
|
return SetContextDataEx(hActiveThread, UE_EBP, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EBP) & 0xFFFF00FF));
|
|
if(scmp(string, "bpl"))
|
|
return SetContextDataEx(hActiveThread, UE_EBP, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EBP) & 0xFFFFFF00));
|
|
if(scmp(string, "sph"))
|
|
return SetContextDataEx(hActiveThread, UE_ESP, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_ESP) & 0xFFFF00FF));
|
|
if(scmp(string, "spl"))
|
|
return SetContextDataEx(hActiveThread, UE_ESP, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_ESP) & 0xFFFFFF00));
|
|
if(scmp(string, "iph"))
|
|
return SetContextDataEx(hActiveThread, UE_EIP, ((value & 0xFF) << 8) | (GetContextDataEx(hActiveThread, UE_EIP) & 0xFFFF00FF));
|
|
if(scmp(string, "ipl"))
|
|
return SetContextDataEx(hActiveThread, UE_EIP, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_EIP) & 0xFFFFFF00));
|
|
|
|
if(scmp(string, "dr0"))
|
|
return SetContextDataEx(hActiveThread, UE_DR0, value);
|
|
if(scmp(string, "dr1"))
|
|
return SetContextDataEx(hActiveThread, UE_DR1, value);
|
|
if(scmp(string, "dr2"))
|
|
return SetContextDataEx(hActiveThread, UE_DR2, value);
|
|
if(scmp(string, "dr3"))
|
|
return SetContextDataEx(hActiveThread, UE_DR3, value);
|
|
if(scmp(string, "dr6") or scmp(string, "dr4"))
|
|
return SetContextDataEx(hActiveThread, UE_DR6, value);
|
|
if(scmp(string, "dr7") or scmp(string, "dr5"))
|
|
return SetContextDataEx(hActiveThread, UE_DR7, value);
|
|
|
|
if(scmp(string, "cip"))
|
|
return SetContextDataEx(hActiveThread, UE_CIP, value);
|
|
if(scmp(string, "csp"))
|
|
return SetContextDataEx(hActiveThread, UE_CSP, value);
|
|
if(scmp(string, "cflags"))
|
|
return SetContextDataEx(hActiveThread, UE_CFLAGS, value);
|
|
|
|
#ifdef _WIN64
|
|
if(scmp(string, "rax"))
|
|
return SetContextDataEx(hActiveThread, UE_RAX, value);
|
|
if(scmp(string, "rbx"))
|
|
return SetContextDataEx(hActiveThread, UE_RBX, value);
|
|
if(scmp(string, "rcx"))
|
|
return SetContextDataEx(hActiveThread, UE_RCX, value);
|
|
if(scmp(string, "rdx"))
|
|
return SetContextDataEx(hActiveThread, UE_RDX, value);
|
|
if(scmp(string, "rdi"))
|
|
return SetContextDataEx(hActiveThread, UE_RDI, value);
|
|
if(scmp(string, "rsi"))
|
|
return SetContextDataEx(hActiveThread, UE_RSI, value);
|
|
if(scmp(string, "rbp"))
|
|
return SetContextDataEx(hActiveThread, UE_RBP, value);
|
|
if(scmp(string, "rsp"))
|
|
return SetContextDataEx(hActiveThread, UE_RSP, value);
|
|
if(scmp(string, "rip"))
|
|
return SetContextDataEx(hActiveThread, UE_RIP, value);
|
|
if(scmp(string, "rflags"))
|
|
return SetContextDataEx(hActiveThread, UE_RFLAGS, value);
|
|
if(scmp(string, "r8"))
|
|
return SetContextDataEx(hActiveThread, UE_R8, value);
|
|
if(scmp(string, "r9"))
|
|
return SetContextDataEx(hActiveThread, UE_R9, value);
|
|
if(scmp(string, "r10"))
|
|
return SetContextDataEx(hActiveThread, UE_R10, value);
|
|
if(scmp(string, "r11"))
|
|
return SetContextDataEx(hActiveThread, UE_R11, value);
|
|
if(scmp(string, "r12"))
|
|
return SetContextDataEx(hActiveThread, UE_R12, value);
|
|
if(scmp(string, "r13"))
|
|
return SetContextDataEx(hActiveThread, UE_R13, value);
|
|
if(scmp(string, "r14"))
|
|
return SetContextDataEx(hActiveThread, UE_R14, value);
|
|
if(scmp(string, "r15"))
|
|
return SetContextDataEx(hActiveThread, UE_R15, value);
|
|
|
|
if(scmp(string, "r8d"))
|
|
return SetContextDataEx(hActiveThread, UE_R8, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R8) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r9d"))
|
|
return SetContextDataEx(hActiveThread, UE_R9, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R9) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r10d"))
|
|
return SetContextDataEx(hActiveThread, UE_R10, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R10) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r11d"))
|
|
return SetContextDataEx(hActiveThread, UE_R11, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R11) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r12d"))
|
|
return SetContextDataEx(hActiveThread, UE_R12, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R12) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r13d"))
|
|
return SetContextDataEx(hActiveThread, UE_R13, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R13) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r14d"))
|
|
return SetContextDataEx(hActiveThread, UE_R14, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R14) & 0xFFFFFFFF00000000));
|
|
if(scmp(string, "r15d"))
|
|
return SetContextDataEx(hActiveThread, UE_R15, (value & 0xFFFFFFFF) | (GetContextDataEx(hActiveThread, UE_R15) & 0xFFFFFFFF00000000));
|
|
|
|
if(scmp(string, "r8w"))
|
|
return SetContextDataEx(hActiveThread, UE_R8, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R8) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r9w"))
|
|
return SetContextDataEx(hActiveThread, UE_R9, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R9) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r10w"))
|
|
return SetContextDataEx(hActiveThread, UE_R10, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R10) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r11w"))
|
|
return SetContextDataEx(hActiveThread, UE_R11, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R11) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r12w"))
|
|
return SetContextDataEx(hActiveThread, UE_R12, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R12) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r13w"))
|
|
return SetContextDataEx(hActiveThread, UE_R13, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R13) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r14w"))
|
|
return SetContextDataEx(hActiveThread, UE_R14, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R14) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r15w"))
|
|
return SetContextDataEx(hActiveThread, UE_R15, (value & 0xFFFF) | (GetContextDataEx(hActiveThread, UE_R15) & 0xFFFFFFFFFFFF0000));
|
|
if(scmp(string, "r8b"))
|
|
return SetContextDataEx(hActiveThread, UE_R8, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R8) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r9b"))
|
|
return SetContextDataEx(hActiveThread, UE_R9, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R9) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r10b"))
|
|
return SetContextDataEx(hActiveThread, UE_R10, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R10) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r11b"))
|
|
return SetContextDataEx(hActiveThread, UE_R11, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R11) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r12b"))
|
|
return SetContextDataEx(hActiveThread, UE_R12, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R12) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r13b"))
|
|
return SetContextDataEx(hActiveThread, UE_R13, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R13) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r14b"))
|
|
return SetContextDataEx(hActiveThread, UE_R14, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R14) & 0xFFFFFFFFFFFFFF00));
|
|
if(scmp(string, "r15b"))
|
|
return SetContextDataEx(hActiveThread, UE_R15, (value & 0xFF) | (GetContextDataEx(hActiveThread, UE_R15) & 0xFFFFFFFFFFFFFF00));
|
|
#endif // _WIN64
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
\brief Gets the address of an API from a name.
|
|
\param name The name of the API, see the command help for more information about valid constructions.
|
|
\param [out] value The address of the retrieved API. Cannot be null.
|
|
\param [out] value_size This function sets this value to the size of the address, sizeof(uint).
|
|
\param printall true to print all possible API values to the console.
|
|
\param silent true to have no console output. If true, the \p printall parameter is ignored.
|
|
\param [out] hexonly If set to true, the values should be printed in hex only. Usually this function sets it to true.
|
|
\return true if the API was found and a value retrieved, false otherwise.
|
|
*/
|
|
bool valapifromstring(const char* name, uint* value, int* value_size, bool printall, bool silent, bool* hexonly)
|
|
{
|
|
if(!value or !DbgIsDebugging())
|
|
return false;
|
|
//explicit API handling
|
|
const char* apiname = strchr(name, ':'); //the ':' character cannot be in a path: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions
|
|
bool noexports = false;
|
|
if(!apiname) //not found
|
|
{
|
|
apiname = strrchr(name, '.'); //kernel32.GetProcAddress support
|
|
if(!apiname) //not found
|
|
{
|
|
apiname = strchr(name, '?'); //the '?' character cannot be in a path either
|
|
noexports = true;
|
|
}
|
|
}
|
|
if(apiname)
|
|
{
|
|
char modname[MAX_MODULE_SIZE] = "";
|
|
if(name == apiname) //:[expression] <= currently selected module
|
|
{
|
|
SELECTIONDATA seldata;
|
|
memset(&seldata, 0, sizeof(seldata));
|
|
GuiSelectionGet(GUI_DISASSEMBLY, &seldata);
|
|
if(!ModNameFromAddr(seldata.start, modname, true))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
strcpy_s(modname, name);
|
|
modname[apiname - name] = 0;
|
|
}
|
|
apiname++;
|
|
if(!strlen(apiname))
|
|
return false;
|
|
uint modbase = ModBaseFromName(modname);
|
|
wchar_t szModName[MAX_PATH] = L"";
|
|
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)modbase, szModName, MAX_PATH))
|
|
{
|
|
if(!silent)
|
|
dprintf("could not get filename of module "fhex"\n", modbase);
|
|
}
|
|
else
|
|
{
|
|
HMODULE mod = LoadLibraryExW(szModName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
|
if(!mod)
|
|
{
|
|
if(!silent)
|
|
dprintf("unable to load library %s\n", szModName);
|
|
}
|
|
else
|
|
{
|
|
uint addr = noexports ? 0 : (uint)GetProcAddress(mod, apiname);
|
|
if(addr) //found exported function
|
|
addr = modbase + (addr - (uint)mod); //correct for loaded base
|
|
else //not found
|
|
{
|
|
if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base
|
|
addr = modbase;
|
|
else if(scmp(apiname, "entry") or scmp(apiname, "oep") or scmp(apiname, "ep")) //get entry point
|
|
addr = modbase + GetPE32DataW(szModName, 0, UE_OEP);
|
|
else if(*apiname == '$') //RVA
|
|
{
|
|
uint rva;
|
|
if(valfromstring(apiname + 1, &rva))
|
|
addr = modbase + rva;
|
|
}
|
|
else if(*apiname == '#') //File Offset
|
|
{
|
|
uint offset;
|
|
if(valfromstring(apiname + 1, &offset))
|
|
addr = valfileoffsettova(modname, offset);
|
|
}
|
|
else
|
|
{
|
|
if(noexports) //get the exported functions with the '?' delimiter
|
|
{
|
|
addr = (uint)GetProcAddress(mod, apiname);
|
|
if(addr) //found exported function
|
|
addr = modbase + (addr - (uint)mod); //correct for loaded base
|
|
}
|
|
else
|
|
{
|
|
uint ordinal;
|
|
if(valfromstring(apiname, &ordinal))
|
|
{
|
|
addr = (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF));
|
|
if(addr) //found exported function
|
|
addr = modbase + (addr - (uint)mod); //correct for loaded base
|
|
else if(!ordinal) //support for getting the image base using <modname>:0
|
|
addr = modbase;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FreeLibrary(mod);
|
|
if(addr) //found!
|
|
{
|
|
if(value_size)
|
|
*value_size = sizeof(uint);
|
|
if(hexonly)
|
|
*hexonly = true;
|
|
*value = addr;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
int found = 0;
|
|
int kernel32 = -1;
|
|
DWORD cbNeeded = 0;
|
|
Memory<uint*> addrfound;
|
|
if(EnumProcessModules(fdProcessInfo->hProcess, 0, 0, &cbNeeded))
|
|
{
|
|
addrfound.realloc(cbNeeded * sizeof(uint), "valapifromstring:addrfound");
|
|
Memory<HMODULE*> hMods(cbNeeded * sizeof(HMODULE), "valapifromstring:hMods");
|
|
if(EnumProcessModules(fdProcessInfo->hProcess, hMods, cbNeeded, &cbNeeded))
|
|
{
|
|
for(unsigned int i = 0; i < cbNeeded / sizeof(HMODULE); i++)
|
|
{
|
|
wchar_t szModuleName[MAX_PATH] = L"";
|
|
if(GetModuleFileNameExW(fdProcessInfo->hProcess, hMods[i], szModuleName, MAX_PATH))
|
|
{
|
|
wchar_t* szBaseName = wcsrchr(szModuleName, L'\\');
|
|
if(szBaseName)
|
|
{
|
|
szBaseName++;
|
|
HMODULE hModule = LoadLibraryExW(szModuleName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
|
if(hModule)
|
|
{
|
|
ULONG_PTR funcAddress = (ULONG_PTR)GetProcAddress(hModule, name);
|
|
if(funcAddress)
|
|
{
|
|
if(!_wcsicmp(szBaseName, L"kernel32.dll"))
|
|
kernel32 = found;
|
|
uint rva = funcAddress - (uint)hModule;
|
|
addrfound[found] = (uint)hMods[i] + rva;
|
|
found++;
|
|
}
|
|
FreeLibrary(hModule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!found)
|
|
return false;
|
|
if(value_size)
|
|
*value_size = sizeof(uint);
|
|
if(hexonly)
|
|
*hexonly = true;
|
|
if(kernel32 != -1) //prioritize kernel32 exports
|
|
{
|
|
*value = addrfound[kernel32];
|
|
if(!printall or silent)
|
|
return true;
|
|
for(int i = 0; i < found; i++)
|
|
if(i != kernel32)
|
|
dprintf(fhex"\n", addrfound[i]);
|
|
}
|
|
else
|
|
{
|
|
*value = *addrfound;
|
|
if(!printall or silent)
|
|
return true;
|
|
for(int i = 1; i < found; i++)
|
|
dprintf(fhex"\n", addrfound[i]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\brief Check if a string is a valid decimal number. This function also accepts "-" or "." as prefix.
|
|
\param string The string to check.
|
|
\return true if the string is a valid decimal number.
|
|
*/
|
|
static bool isdecnumber(const char* string)
|
|
{
|
|
if(*string != '.' or !string[1]) //dec indicator/no number
|
|
return false;
|
|
int decAdd = 1;
|
|
if(string[1] == '-') //minus
|
|
{
|
|
if(!string[2]) //no number
|
|
return false;
|
|
decAdd++;
|
|
}
|
|
int len = (int)strlen(string + decAdd);
|
|
for(int i = 0; i < len; i++)
|
|
if(!isdigit(string[i + decAdd]))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\brief Check if a string is a valid hexadecimal number. This function also accepts "0x" or "x" as prefix.
|
|
\param string The string to check.
|
|
\return true if the string is a valid hexadecimal number.
|
|
*/
|
|
static bool ishexnumber(const char* string)
|
|
{
|
|
int add = 0;
|
|
if(*string == '0' and string[1] == 'x') //0x prefix
|
|
add = 2;
|
|
else if(*string == 'x') //hex indicator
|
|
add = 1;
|
|
if(!string[add]) //only an indicator, no number
|
|
return false;
|
|
int len = (int)strlen(string + add);
|
|
for(int i = 0; i < len; i++)
|
|
if(!isxdigit(string[i + add])) //all must be hex digits
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\brief Gets a value from a string. This function can parse expressions, memory locations, registers, flags, API names, labels, symbols and variables.
|
|
\param string The string to parse.
|
|
\param [out] value The value of the expression. This value cannot be null.
|
|
\param silent true to not output anything to the console.
|
|
\param baseonly true to skip parsing API names, labels, symbols and variables (basic expressions only).
|
|
\param [out] value_size This function can output the value size parsed (for example memory location size or register size). Can be null.
|
|
\param [out] isvar This function can output if the expression is variable (for example memory locations, registers or variables are variable). Can be null.
|
|
\param [out] hexonly This function can output if the output value should only be printed as hexadecimal (for example addresses). Can be null.
|
|
\return true if the expression was parsed successfull, false otherwise.
|
|
*/
|
|
bool valfromstring(const char* string, uint* value, bool silent, bool baseonly, int* value_size, bool* isvar, bool* hexonly)
|
|
{
|
|
if(!value or !string)
|
|
return false;
|
|
if(!*string)
|
|
{
|
|
*value = 0;
|
|
return true;
|
|
}
|
|
else if(mathcontains(string)) //handle math
|
|
{
|
|
int len = (int)strlen(string);
|
|
Memory<char*> newstring(len * 2, "valfromstring:newstring");
|
|
if(strstr(string, "[")) //memory brackets: []
|
|
{
|
|
for(int i = 0, j = 0; i < len; i++)
|
|
{
|
|
if(string[i] == ']')
|
|
j += sprintf(newstring + j, ")");
|
|
else if(isdigit(string[i]) and string[i + 1] == ':' and string[i + 2] == '[') //n:[
|
|
{
|
|
j += sprintf(newstring + j, "@%c:(", string[i]);
|
|
i += 2;
|
|
}
|
|
else if(string[i] == '[')
|
|
j += sprintf(newstring + j, "@(");
|
|
else
|
|
j += sprintf(newstring + j, "%c", string[i]);
|
|
}
|
|
}
|
|
else
|
|
strcpy_s(newstring, len * 2, string);
|
|
Memory<char*> string_(len + 256, "valfromstring:string_");
|
|
strcpy_s(string_, len + 256, newstring);
|
|
int add = 0;
|
|
bool negative = (*string_ == '-');
|
|
while(mathisoperator(string_[add + negative]) > 2)
|
|
add++;
|
|
if(!mathhandlebrackets(string_ + add, silent, baseonly))
|
|
return false;
|
|
return mathfromstring(string_ + add, value, silent, baseonly, value_size, isvar);
|
|
}
|
|
else if(*string == '-') //negative value
|
|
{
|
|
uint val;
|
|
if(!valfromstring(string + 1, &val, silent, baseonly, value_size, isvar, hexonly))
|
|
return false;
|
|
val *= ~0;
|
|
if(value)
|
|
*value = val;
|
|
return true;
|
|
}
|
|
else if(*string == '@' or strstr(string, "[")) //memory location
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging");
|
|
*value = 0;
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
int len = (int)strlen(string);
|
|
Memory<char*> newstring(len * 2, "valfromstring:newstring");
|
|
if(strstr(string, "["))
|
|
{
|
|
for(int i = 0, j = 0; i < len; i++)
|
|
{
|
|
if(string[i] == ']')
|
|
j += sprintf(newstring + j, ")");
|
|
else if(isdigit(string[i]) and string[i + 1] == ':' and string[i + 2] == '[') //n:[
|
|
{
|
|
j += sprintf(newstring + j, "@%c:(", string[i]);
|
|
i += 2;
|
|
}
|
|
else if(string[i] == '[')
|
|
j += sprintf(newstring + j, "@(");
|
|
else
|
|
j += sprintf(newstring + j, "%c", string[i]);
|
|
}
|
|
}
|
|
else
|
|
strcpy_s(newstring, len * 2, string);
|
|
int read_size = sizeof(uint);
|
|
int add = 1;
|
|
if(newstring[2] == ':' and isdigit((newstring[1]))) //@n: (number of bytes to read)
|
|
{
|
|
add += 2;
|
|
int new_size = newstring[1] - 0x30;
|
|
if(new_size < read_size)
|
|
read_size = new_size;
|
|
}
|
|
if(!valfromstring(newstring + add, value, silent, baseonly))
|
|
return false;
|
|
uint addr = *value;
|
|
*value = 0;
|
|
if(!MemRead((void*)addr, value, read_size, 0))
|
|
{
|
|
if(!silent)
|
|
dputs("failed to read memory");
|
|
return false;
|
|
}
|
|
if(value_size)
|
|
*value_size = read_size;
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
else if(isregister(string)) //register
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging!");
|
|
*value = 0;
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
*value = getregister(value_size, string);
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
else if(*string == '!' and isflag(string + 1)) //flag
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging");
|
|
*value = 0;
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
uint eflags = GetContextDataEx(hActiveThread, UE_CFLAGS);
|
|
if(valflagfromstring(eflags, string + 1))
|
|
*value = 1;
|
|
else
|
|
*value = 0;
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
else if(isdecnumber(string)) //decimal numbers come 'first'
|
|
{
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = false;
|
|
sscanf(string + 1, "%"fext"u", value);
|
|
return true;
|
|
}
|
|
else if(ishexnumber(string)) //then hex numbers
|
|
{
|
|
if(value_size)
|
|
*value_size = 0;
|
|
if(isvar)
|
|
*isvar = false;
|
|
//hexadecimal value
|
|
int inc = 0;
|
|
if(*string == 'x')
|
|
inc = 1;
|
|
sscanf(string + inc, "%"fext"x", value);
|
|
return true;
|
|
}
|
|
if(baseonly)
|
|
return false;
|
|
else if(valapifromstring(string, value, value_size, true, silent, hexonly)) //then come APIs
|
|
return true;
|
|
else if(LabelFromString(string, value)) //then come labels
|
|
return true;
|
|
else if(SymAddrFromName(string, value)) //then come symbols
|
|
return true;
|
|
else if(varget(string, value, value_size, 0)) //finally variables
|
|
{
|
|
if(isvar)
|
|
*isvar = true;
|
|
return true;
|
|
}
|
|
if(!silent)
|
|
dprintf("invalid value: \"%s\"!\n", string);
|
|
return false; //nothing was OK
|
|
}
|
|
|
|
/**
|
|
\brief Checks if a string is long enough.
|
|
\param str The string to check.
|
|
\param min_length The minimum length of \p str.
|
|
\return true if the string is long enough, false otherwise.
|
|
*/
|
|
static bool longEnough(const char* str, size_t min_length)
|
|
{
|
|
size_t length = 0;
|
|
while(str[length] && length < min_length)
|
|
length++;
|
|
if(length == min_length)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
\brief Checks if a string starts with another string.
|
|
\param pre The desired prefix of the string.
|
|
\param str The complete string.
|
|
\return true if \p str starts with \p pre.
|
|
*/
|
|
static bool startsWith(const char* pre, const char* str)
|
|
{
|
|
size_t lenpre = strlen(pre);
|
|
return longEnough(str, lenpre) ? StrNCmpI(str, pre, (int) lenpre) == 0 : false;
|
|
}
|
|
|
|
#define MxCsr_PRE_FIELD_STRING "MxCsr_"
|
|
#define x87SW_PRE_FIELD_STRING "x87SW_"
|
|
#define x87CW_PRE_FIELD_STRING "x87CW_"
|
|
#define x87TW_PRE_FIELD_STRING "x87TW_"
|
|
#define MMX_PRE_FIELD_STRING "MM"
|
|
#define XMM_PRE_FIELD_STRING "XMM"
|
|
#define YMM_PRE_FIELD_STRING "YMM"
|
|
#define x8780BITFPU_PRE_FIELD_STRING "x87r"
|
|
#define STRLEN_USING_SIZEOF(string) (sizeof(string) - 1)
|
|
|
|
/**
|
|
\brief Sets an FPU value (MXCSR fields, MMX fields, etc.) by name.
|
|
\param string The name of the FPU value to set.
|
|
\param value The value to set.
|
|
*/
|
|
static void setfpuvalue(const char* string, uint value)
|
|
{
|
|
uint xorval = 0;
|
|
uint flags = 0;
|
|
uint flag = 0;
|
|
bool set = false;
|
|
|
|
if(value)
|
|
set = true;
|
|
|
|
if(startsWith(MxCsr_PRE_FIELD_STRING, string))
|
|
{
|
|
if(StrNCmpI(string + STRLEN_USING_SIZEOF(MxCsr_PRE_FIELD_STRING), "RC", (int) strlen("RC")) == 0)
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_MXCSR);
|
|
int i = 3;
|
|
i <<= 13;
|
|
flags &= ~i;
|
|
value <<= 13;
|
|
flags |= value;
|
|
SetContextDataEx(hActiveThread, UE_MXCSR, flags);
|
|
}
|
|
else
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_MXCSR);
|
|
flag = getmxcsrflagfromstring(string + STRLEN_USING_SIZEOF(MxCsr_PRE_FIELD_STRING));
|
|
if(flags & flag and !set)
|
|
xorval = flag;
|
|
else if(set)
|
|
xorval = flag;
|
|
SetContextDataEx(hActiveThread, UE_MXCSR, flags ^ xorval);
|
|
}
|
|
}
|
|
else if(startsWith(x87TW_PRE_FIELD_STRING, string))
|
|
{
|
|
unsigned int i;
|
|
|
|
string += STRLEN_USING_SIZEOF(x87TW_PRE_FIELD_STRING);
|
|
i = atoi(string);
|
|
|
|
if(i > 7)
|
|
return;
|
|
|
|
flags = GetContextDataEx(hActiveThread, UE_X87_TAGWORD);
|
|
|
|
flag = 3;
|
|
flag <<= i * 2;
|
|
|
|
flags &= ~flag;
|
|
|
|
flag = value;
|
|
flag <<= i * 2;
|
|
|
|
flags |= flag;
|
|
|
|
SetContextDataEx(hActiveThread, UE_X87_TAGWORD, (unsigned short) flags);
|
|
|
|
}
|
|
else if(startsWith(x87SW_PRE_FIELD_STRING, string))
|
|
{
|
|
if(StrNCmpI(string + STRLEN_USING_SIZEOF(x87SW_PRE_FIELD_STRING), "TOP", (int) strlen("TOP")) == 0)
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_X87_STATUSWORD);
|
|
int i = 7;
|
|
i <<= 11;
|
|
flags &= ~i;
|
|
value <<= 11;
|
|
flags |= value;
|
|
SetContextDataEx(hActiveThread, UE_X87_STATUSWORD, flags);
|
|
}
|
|
else
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_X87_STATUSWORD);
|
|
flag = getx87statuswordflagfromstring(string + STRLEN_USING_SIZEOF(x87SW_PRE_FIELD_STRING));
|
|
if(flags & flag and !set)
|
|
xorval = flag;
|
|
else if(set)
|
|
xorval = flag;
|
|
SetContextDataEx(hActiveThread, UE_X87_STATUSWORD, flags ^ xorval);
|
|
}
|
|
}
|
|
else if(startsWith(x87CW_PRE_FIELD_STRING, string))
|
|
{
|
|
if(StrNCmpI(string + STRLEN_USING_SIZEOF(x87CW_PRE_FIELD_STRING), "RC", (int) strlen("RC")) == 0)
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_X87_CONTROLWORD);
|
|
int i = 3;
|
|
i <<= 10;
|
|
flags &= ~i;
|
|
value <<= 10;
|
|
flags |= value;
|
|
SetContextDataEx(hActiveThread, UE_X87_CONTROLWORD, flags);
|
|
}
|
|
else if(StrNCmpI(string + STRLEN_USING_SIZEOF(x87CW_PRE_FIELD_STRING), "PC", (int) strlen("PC")) == 0)
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_X87_CONTROLWORD);
|
|
int i = 3;
|
|
i <<= 8;
|
|
flags &= ~i;
|
|
value <<= 8;
|
|
flags |= value;
|
|
SetContextDataEx(hActiveThread, UE_X87_CONTROLWORD, flags);
|
|
}
|
|
else
|
|
{
|
|
uint flags = GetContextDataEx(hActiveThread, UE_X87_CONTROLWORD);
|
|
flag = getx87controlwordflagfromstring(string + STRLEN_USING_SIZEOF(x87CW_PRE_FIELD_STRING));
|
|
if(flags & flag and !set)
|
|
xorval = flag;
|
|
else if(set)
|
|
xorval = flag;
|
|
SetContextDataEx(hActiveThread, UE_X87_CONTROLWORD, flags ^ xorval);
|
|
}
|
|
}
|
|
else if(StrNCmpI(string, "x87TagWord", (int) strlen(string)) == 0)
|
|
{
|
|
SetContextDataEx(hActiveThread, UE_X87_TAGWORD, (unsigned short) value);
|
|
}
|
|
else if(StrNCmpI(string, "x87StatusWord", (int) strlen(string)) == 0)
|
|
{
|
|
SetContextDataEx(hActiveThread, UE_X87_STATUSWORD, (unsigned short) value);
|
|
}
|
|
else if(StrNCmpI(string, "x87ControlWord", (int) strlen(string)) == 0)
|
|
{
|
|
SetContextDataEx(hActiveThread, UE_X87_CONTROLWORD, (unsigned short) value);
|
|
}
|
|
else if(StrNCmpI(string, "MxCsr", (int) strlen(string)) == 0)
|
|
{
|
|
SetContextDataEx(hActiveThread, UE_MXCSR, value);
|
|
}
|
|
else if(startsWith(x8780BITFPU_PRE_FIELD_STRING, string))
|
|
{
|
|
string += STRLEN_USING_SIZEOF(x8780BITFPU_PRE_FIELD_STRING);
|
|
DWORD registerindex;
|
|
bool found = true;
|
|
switch(*string)
|
|
{
|
|
case '0':
|
|
registerindex = UE_x87_r0;
|
|
break;
|
|
|
|
case '1':
|
|
registerindex = UE_x87_r1;
|
|
break;
|
|
|
|
case '2':
|
|
registerindex = UE_x87_r2;
|
|
break;
|
|
|
|
case '3':
|
|
registerindex = UE_x87_r3;
|
|
break;
|
|
|
|
case '4':
|
|
registerindex = UE_x87_r4;
|
|
break;
|
|
|
|
case '5':
|
|
registerindex = UE_x87_r5;
|
|
break;
|
|
|
|
case '6':
|
|
registerindex = UE_x87_r6;
|
|
break;
|
|
|
|
case '7':
|
|
registerindex = UE_x87_r7;
|
|
break;
|
|
|
|
default:
|
|
found = false;
|
|
break;
|
|
}
|
|
if(found)
|
|
SetContextDataEx(hActiveThread, registerindex, value);
|
|
}
|
|
else if(startsWith(MMX_PRE_FIELD_STRING, string))
|
|
{
|
|
string += STRLEN_USING_SIZEOF(MMX_PRE_FIELD_STRING);
|
|
DWORD registerindex;
|
|
bool found = true;
|
|
switch(*string)
|
|
{
|
|
case '0':
|
|
registerindex = UE_MMX0;
|
|
break;
|
|
|
|
case '1':
|
|
registerindex = UE_MMX1;
|
|
break;
|
|
|
|
case '2':
|
|
registerindex = UE_MMX2;
|
|
break;
|
|
|
|
case '3':
|
|
registerindex = UE_MMX3;
|
|
break;
|
|
|
|
case '4':
|
|
registerindex = UE_MMX4;
|
|
break;
|
|
|
|
case '5':
|
|
registerindex = UE_MMX5;
|
|
break;
|
|
|
|
case '6':
|
|
registerindex = UE_MMX6;
|
|
break;
|
|
|
|
case '7':
|
|
registerindex = UE_MMX7;
|
|
break;
|
|
|
|
default:
|
|
found = false;
|
|
break;
|
|
}
|
|
if(found)
|
|
SetContextDataEx(hActiveThread, registerindex, value);
|
|
}
|
|
else if(startsWith(XMM_PRE_FIELD_STRING, string))
|
|
{
|
|
string += STRLEN_USING_SIZEOF(XMM_PRE_FIELD_STRING);
|
|
DWORD registerindex;
|
|
bool found = true;
|
|
switch(atoi(string))
|
|
{
|
|
case 0:
|
|
registerindex = UE_XMM0;
|
|
break;
|
|
|
|
case 1:
|
|
registerindex = UE_XMM1;
|
|
break;
|
|
|
|
case 2:
|
|
registerindex = UE_XMM2;
|
|
break;
|
|
|
|
case 3:
|
|
registerindex = UE_XMM3;
|
|
break;
|
|
|
|
case 4:
|
|
registerindex = UE_XMM4;
|
|
break;
|
|
|
|
case 5:
|
|
registerindex = UE_XMM5;
|
|
break;
|
|
|
|
case 6:
|
|
registerindex = UE_XMM6;
|
|
break;
|
|
|
|
case 7:
|
|
registerindex = UE_XMM7;
|
|
break;
|
|
|
|
case 8:
|
|
registerindex = UE_XMM8;
|
|
break;
|
|
|
|
case 9:
|
|
registerindex = UE_XMM9;
|
|
break;
|
|
|
|
case 10:
|
|
registerindex = UE_XMM10;
|
|
break;
|
|
|
|
case 11:
|
|
registerindex = UE_XMM11;
|
|
break;
|
|
|
|
case 12:
|
|
registerindex = UE_XMM12;
|
|
break;
|
|
|
|
case 13:
|
|
registerindex = UE_XMM13;
|
|
break;
|
|
|
|
case 14:
|
|
registerindex = UE_XMM14;
|
|
break;
|
|
|
|
case 15:
|
|
registerindex = UE_XMM15;
|
|
break;
|
|
|
|
default:
|
|
found = false;
|
|
break;
|
|
}
|
|
if(found)
|
|
SetContextDataEx(hActiveThread, registerindex, value);
|
|
}
|
|
else if(startsWith(YMM_PRE_FIELD_STRING, string))
|
|
{
|
|
string += STRLEN_USING_SIZEOF(YMM_PRE_FIELD_STRING);
|
|
DWORD registerindex;
|
|
bool found = true;
|
|
switch(atoi(string))
|
|
{
|
|
case 0:
|
|
registerindex = UE_YMM0;
|
|
break;
|
|
|
|
case 1:
|
|
registerindex = UE_YMM1;
|
|
break;
|
|
|
|
case 2:
|
|
registerindex = UE_YMM2;
|
|
break;
|
|
|
|
case 3:
|
|
registerindex = UE_YMM3;
|
|
break;
|
|
|
|
case 4:
|
|
registerindex = UE_YMM4;
|
|
break;
|
|
|
|
case 5:
|
|
registerindex = UE_YMM5;
|
|
break;
|
|
|
|
case 6:
|
|
registerindex = UE_YMM6;
|
|
break;
|
|
|
|
case 7:
|
|
registerindex = UE_YMM7;
|
|
break;
|
|
|
|
case 8:
|
|
registerindex = UE_YMM8;
|
|
break;
|
|
|
|
case 9:
|
|
registerindex = UE_YMM9;
|
|
break;
|
|
|
|
case 10:
|
|
registerindex = UE_YMM10;
|
|
break;
|
|
|
|
case 11:
|
|
registerindex = UE_YMM11;
|
|
break;
|
|
|
|
case 12:
|
|
registerindex = UE_YMM12;
|
|
break;
|
|
|
|
case 13:
|
|
registerindex = UE_YMM13;
|
|
break;
|
|
|
|
case 14:
|
|
registerindex = UE_YMM14;
|
|
break;
|
|
|
|
case 15:
|
|
registerindex = UE_YMM15;
|
|
break;
|
|
|
|
default:
|
|
found = false;
|
|
break;
|
|
}
|
|
if(found)
|
|
SetContextDataEx(hActiveThread, registerindex, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
\brief Sets a register, variable, flag, memory location or FPU value by name.
|
|
\param string The name of the thing to set.
|
|
\param value The value to set.
|
|
\param silent true to not have output to the console.
|
|
\return true if the value was set successfully, false otherwise.
|
|
*/
|
|
bool valtostring(const char* string, uint value, bool silent)
|
|
{
|
|
if(!*string)
|
|
return false;
|
|
else if(*string == '@' or strstr(string, "[")) //memory location
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging");
|
|
return false;
|
|
}
|
|
int len = (int)strlen(string);
|
|
Memory<char*> newstring(len * 2, "valfromstring:newstring");
|
|
if(strstr(string, "[")) //memory brackets: []
|
|
{
|
|
for(int i = 0, j = 0; i < len; i++)
|
|
{
|
|
if(string[i] == ']')
|
|
j += sprintf(newstring + j, ")");
|
|
else if(isdigit(string[i]) and string[i + 1] == ':' and string[i + 2] == '[') //n:[
|
|
{
|
|
j += sprintf(newstring + j, "@%c:(", string[i]);
|
|
i += 2;
|
|
}
|
|
else if(string[i] == '[')
|
|
j += sprintf(newstring + j, "@(");
|
|
else
|
|
j += sprintf(newstring + j, "%c", string[i]);
|
|
}
|
|
}
|
|
else
|
|
strcpy_s(newstring, len * 2, string);
|
|
int read_size = sizeof(uint);
|
|
int add = 1;
|
|
if(newstring[2] == ':' and isdigit((newstring[1])))
|
|
{
|
|
add += 2;
|
|
int new_size = newstring[1] - 0x30;
|
|
if(new_size < read_size)
|
|
read_size = new_size;
|
|
}
|
|
uint temp;
|
|
if(!valfromstring(newstring + add, &temp, silent, false))
|
|
{
|
|
return false;
|
|
}
|
|
uint value_ = value;
|
|
if(!MemPatch((void*)temp, &value_, read_size, 0))
|
|
{
|
|
if(!silent)
|
|
dputs("failed to write memory");
|
|
return false;
|
|
}
|
|
GuiUpdateAllViews(); //repaint gui
|
|
GuiUpdatePatches(); //update patch dialog
|
|
return true;
|
|
}
|
|
else if(isregister(string)) //register
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging!");
|
|
return false;
|
|
}
|
|
bool ok = setregister(string, value);
|
|
int len = (int)strlen(string);
|
|
Memory<char*> regName(len + 1, "valtostring:regname");
|
|
strcpy_s(regName, len + 1, string);
|
|
_strlwr(regName);
|
|
if(strstr(regName, "ip"))
|
|
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), false); //update disassembly + register view
|
|
else if(strstr(regName, "sp")) //update stack
|
|
{
|
|
uint csp = GetContextDataEx(hActiveThread, UE_CSP);
|
|
GuiStackDumpAt(csp, csp);
|
|
GuiUpdateRegisterView();
|
|
}
|
|
else
|
|
GuiUpdateAllViews(); //repaint gui
|
|
return ok;
|
|
}
|
|
else if((*string == '_')) //FPU values
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging!");
|
|
return false;
|
|
}
|
|
setfpuvalue(string + 1, value);
|
|
GuiUpdateAllViews(); //repaint gui
|
|
return true;
|
|
}
|
|
else if(*string == '!' and isflag(string + 1)) //flag
|
|
{
|
|
if(!DbgIsDebugging())
|
|
{
|
|
if(!silent)
|
|
dputs("not debugging");
|
|
return false;
|
|
}
|
|
bool set = false;
|
|
if(value)
|
|
set = true;
|
|
setflag(string + 1, set);
|
|
GuiUpdateAllViews(); //repaint gui
|
|
return true;
|
|
}
|
|
return varset(string, value, false); //variable
|
|
}
|
|
|
|
/**
|
|
\brief Converts a file offset to a virtual address.
|
|
\param modname The name (not the path) of the module the file offset is in.
|
|
\param offset The file offset.
|
|
\return The VA of the file offset, 0 when there was a problem with the conversion.
|
|
*/
|
|
uint valfileoffsettova(const char* modname, uint offset)
|
|
{
|
|
char modpath[MAX_PATH] = "";
|
|
if(ModPathFromName(modname, modpath, MAX_PATH))
|
|
{
|
|
HANDLE FileHandle;
|
|
DWORD LoadedSize;
|
|
HANDLE FileMap;
|
|
ULONG_PTR FileMapVA;
|
|
if(StaticFileLoadW(StringUtils::Utf8ToUtf16(modpath).c_str(), UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
|
|
{
|
|
ULONGLONG rva = ConvertFileOffsetToVA(FileMapVA, //FileMapVA
|
|
FileMapVA + (ULONG_PTR)offset, //Offset inside FileMapVA
|
|
false); //Return without ImageBase
|
|
StaticFileUnloadW(StringUtils::Utf8ToUtf16(modpath).c_str(), true, FileHandle, LoadedSize, FileMap, FileMapVA);
|
|
return offset < LoadedSize ? (duint)rva + ModBaseFromName(modname) : 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Converts a virtual address to a file offset.
|
|
\param va The virtual address (must be inside a module).
|
|
\return The file offset. 0 when there was a problem with the conversion.
|
|
*/
|
|
uint valvatofileoffset(uint va)
|
|
{
|
|
char modpath[MAX_PATH] = "";
|
|
if(ModPathFromAddr(va, modpath, MAX_PATH))
|
|
{
|
|
HANDLE FileHandle;
|
|
DWORD LoadedSize;
|
|
HANDLE FileMap;
|
|
ULONG_PTR FileMapVA;
|
|
if(StaticFileLoadW(StringUtils::Utf8ToUtf16(modpath).c_str(), UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
|
|
{
|
|
ULONGLONG offset = ConvertVAtoFileOffsetEx(FileMapVA, LoadedSize, 0, va - ModBaseFromAddr(va), true, false);
|
|
StaticFileUnloadW(StringUtils::Utf8ToUtf16(modpath).c_str(), true, FileHandle, LoadedSize, FileMap, FileMapVA);
|
|
return (duint)offset;
|
|
}
|
|
}
|
|
return 0;
|
|
} |