/** @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 :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 addrfound; if(EnumProcessModules(fdProcessInfo->hProcess, 0, 0, &cbNeeded)) { addrfound.realloc(cbNeeded * sizeof(uint), "valapifromstring:addrfound"); Memory 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 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 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 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 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 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; }