DBG: various changes to the encodemap
This commit is contained in:
parent
7315183855
commit
2956b01962
|
@ -86,7 +86,9 @@ void DbSave(DbLoadSaveType saveType)
|
|||
break;
|
||||
}
|
||||
plugincbcall(CBTYPE::CB_SAVEDB, &pluginSaveDb);
|
||||
json_object_set_new(root, "plugins", pluginRoot);
|
||||
if(json_object_size(pluginRoot))
|
||||
json_object_set(root, "plugins", pluginRoot);
|
||||
json_decref(pluginRoot);
|
||||
}
|
||||
|
||||
auto wdbpath = StringUtils::Utf8ToUtf16(dbpath);
|
||||
|
@ -165,7 +167,7 @@ void DbLoad(DbLoadSaveType loadType)
|
|||
|
||||
|
||||
// Deserialize JSON and validate
|
||||
JSON root = json_loads(databaseText.c_str(), JSON_ALLOW_NUL, 0);
|
||||
JSON root = json_loads(databaseText.c_str(), 0, 0);
|
||||
|
||||
if(!root)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "datainst_helper.h"
|
||||
#include "encodemap.h"
|
||||
#include "stringutils.h"
|
||||
#include "value.h"
|
||||
#include <capstone_wrapper.h>
|
||||
|
||||
std::unordered_map<ENCODETYPE, std::string> disasmMap;
|
||||
|
||||
std::unordered_map<std::string, ENCODETYPE> assembleMap;
|
||||
|
||||
void initDataInstMap()
|
||||
|
@ -42,12 +42,8 @@ void initDataInstMap()
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String GetDataTypeString(void* buffer, duint size, ENCODETYPE type)
|
||||
{
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case enc_byte:
|
||||
|
@ -57,23 +53,23 @@ String GetDataTypeString(void* buffer, duint size, ENCODETYPE type)
|
|||
case enc_dword:
|
||||
return StringUtils::ToIntegralString<unsigned int>(buffer);
|
||||
case enc_fword:
|
||||
return StringUtils::ToHex((char*)buffer, 6, true);
|
||||
return StringUtils::ToHex((unsigned char*)buffer, 6, true);
|
||||
case enc_qword:
|
||||
return StringUtils::ToIntegralString<unsigned long long int>(buffer);
|
||||
case enc_tbyte:
|
||||
return StringUtils::ToHex((char*)buffer, 10, true);
|
||||
return StringUtils::ToHex((unsigned char*)buffer, 10, true);
|
||||
case enc_oword:
|
||||
return StringUtils::ToHex((char*)buffer, 16, true);
|
||||
return StringUtils::ToHex((unsigned char*)buffer, 16, true);
|
||||
case enc_mmword:
|
||||
case enc_xmmword:
|
||||
case enc_ymmword:
|
||||
return StringUtils::ToHex((char*)buffer, size, false);
|
||||
return StringUtils::ToHex((unsigned char*)buffer, size, false);
|
||||
case enc_real4:
|
||||
return StringUtils::ToFloatingString<float>(buffer);
|
||||
case enc_real8:
|
||||
return StringUtils::ToFloatingString<double>(buffer);
|
||||
case enc_real10:
|
||||
return StringUtils::ToHex((char*)buffer, 10, true);
|
||||
return StringUtils::ToHex((unsigned char*)buffer, 10, true);
|
||||
//return ToLongDoubleString(buffer);
|
||||
case enc_ascii:
|
||||
return String((const char*)buffer, size);
|
||||
|
@ -118,13 +114,13 @@ duint decodesimpledata(const unsigned char* buffer, ENCODETYPE type)
|
|||
struct DataInstruction
|
||||
{
|
||||
ENCODETYPE type;
|
||||
String oprand;
|
||||
String operand;
|
||||
};
|
||||
|
||||
bool parsedatainstruction(const char* instruction, DataInstruction & di)
|
||||
{
|
||||
di.type = enc_unknown;
|
||||
di.oprand = "";
|
||||
di.operand = "";
|
||||
String instStr = StringUtils::Trim(String(instruction));
|
||||
size_t pos = instStr.find_first_of(" \t");
|
||||
String opcode = instStr.substr(0, pos);
|
||||
|
@ -135,7 +131,7 @@ bool parsedatainstruction(const char* instruction, DataInstruction & di)
|
|||
pos = instStr.find_first_not_of(" \t", pos);
|
||||
if(pos == String::npos)
|
||||
return false;
|
||||
di.oprand = instStr.substr(pos);
|
||||
di.operand = instStr.substr(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -152,126 +148,161 @@ bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, c
|
|||
DataInstruction di;
|
||||
if(!parsedatainstruction(instruction, di))
|
||||
{
|
||||
if(di.oprand == "")
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "Missing oprand");
|
||||
if(di.operand == "")
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "missing operand");
|
||||
return false;
|
||||
}
|
||||
|
||||
duint retsize = 0;
|
||||
duint retsize = GetEncodeTypeSize(di.type);
|
||||
String buffer;
|
||||
try
|
||||
|
||||
switch(di.type)
|
||||
{
|
||||
switch(di.type)
|
||||
case enc_byte:
|
||||
case enc_word:
|
||||
case enc_dword:
|
||||
case enc_fword:
|
||||
case enc_qword:
|
||||
{
|
||||
unsigned long long result = 0;
|
||||
if(!convertLongLongNumber(di.operand.c_str(), result, 16))
|
||||
{
|
||||
case enc_byte:
|
||||
case enc_word:
|
||||
case enc_dword:
|
||||
case enc_fword:
|
||||
case enc_qword:
|
||||
case enc_tbyte:
|
||||
case enc_oword:
|
||||
{
|
||||
retsize = GetEncodeTypeSize(di.type);
|
||||
buffer = StringUtils::FromHex(di.oprand, retsize, true);
|
||||
break;
|
||||
}
|
||||
case enc_mmword:
|
||||
case enc_xmmword:
|
||||
case enc_ymmword:
|
||||
{
|
||||
retsize = GetEncodeTypeSize(di.type);
|
||||
if(retsize > destsize)
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "insufficient buffer");
|
||||
if(size)
|
||||
{
|
||||
*size = int(retsize); //return correct size
|
||||
return dest == nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
buffer = StringUtils::FromHex(di.oprand, retsize, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case enc_real4:
|
||||
{
|
||||
retsize = 4;
|
||||
float f = std::stof(di.oprand);
|
||||
buffer = String((char*)&f, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case enc_real8:
|
||||
{
|
||||
retsize = 8;
|
||||
double d = std::stod(di.oprand);
|
||||
buffer = String((char*)&d, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case enc_real10:
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported");
|
||||
return false; //80 bit float is not supported in MSVC, need to add other library
|
||||
case enc_ascii:
|
||||
{
|
||||
if(di.oprand.size() > destsize)
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
|
||||
if(size)
|
||||
{
|
||||
*size = int(di.oprand.size()); //return correct size
|
||||
return dest == nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retsize = di.oprand.size();
|
||||
buffer = di.oprand;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case enc_unicode:
|
||||
{
|
||||
WString unicode = StringUtils::Utf8ToUtf16(di.oprand);
|
||||
|
||||
if(unicode.size()*sizeof(wchar_t) > destsize)
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
|
||||
if(size)
|
||||
{
|
||||
retsize = unicode.size() * 2; //return correct size
|
||||
return dest == nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retsize = unicode.size() * 2;
|
||||
buffer = String((char*)unicode.c_str(), retsize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "failed to convert operand");
|
||||
return false;
|
||||
}
|
||||
auto buf = (char*)&result;
|
||||
for(auto i = retsize; i < sizeof(result); i++)
|
||||
if(buf[i])
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "operand value too big");
|
||||
return false;
|
||||
}
|
||||
buffer = String(buf, retsize);
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
break;
|
||||
|
||||
case enc_tbyte:
|
||||
case enc_oword:
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, e.what());
|
||||
std::vector<unsigned char> data;
|
||||
if(!StringUtils::FromHex(StringUtils::PadLeft(di.operand, retsize * 2, '0'), data, true))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "invalid operand (FromHex failed)");
|
||||
return false;
|
||||
}
|
||||
if(data.size() != retsize)
|
||||
{
|
||||
sprintf_s(error, MAX_ERROR_SIZE, "invalid size (expected %" fext "u, got %" fext "u)", retsize, data.size());
|
||||
return false;
|
||||
}
|
||||
buffer = String((char*)data.data(), data.size());
|
||||
}
|
||||
break;
|
||||
|
||||
case enc_mmword:
|
||||
case enc_xmmword:
|
||||
case enc_ymmword:
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
if(!StringUtils::FromHex(StringUtils::PadLeft(di.operand, retsize * 2, '0'), data, false))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "invalid operand (FromHex failed)");
|
||||
return false;
|
||||
}
|
||||
if(data.size() != retsize)
|
||||
{
|
||||
sprintf_s(error, MAX_ERROR_SIZE, "invalid size (expected %" fext "u, got %" fext "u)", retsize, data.size());
|
||||
return false;
|
||||
}
|
||||
buffer = String((char*)data.data(), data.size());
|
||||
}
|
||||
break;
|
||||
|
||||
case enc_real4:
|
||||
{
|
||||
retsize = 4;
|
||||
float f = std::stof(di.operand);
|
||||
buffer = String((char*)&f, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case enc_real8:
|
||||
{
|
||||
retsize = 8;
|
||||
double d = std::stod(di.operand);
|
||||
buffer = String((char*)&d, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case enc_real10:
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported");
|
||||
return false; //80 bit float is not supported in MSVC, need to add other library
|
||||
|
||||
case enc_ascii:
|
||||
{
|
||||
String unescaped;
|
||||
if(!StringUtils::Unescape(di.operand, unescaped))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "invalid string literal");
|
||||
return false;
|
||||
}
|
||||
if(unescaped.size() > size_t(destsize))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
|
||||
if(size)
|
||||
{
|
||||
*size = int(unescaped.size()); //return correct size
|
||||
return dest == nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
retsize = unescaped.size();
|
||||
buffer = unescaped;
|
||||
}
|
||||
break;
|
||||
|
||||
case enc_unicode:
|
||||
{
|
||||
String unescaped;
|
||||
if(!StringUtils::Unescape(di.operand, unescaped))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "invalid string literal");
|
||||
return false;
|
||||
}
|
||||
WString unicode = StringUtils::Utf8ToUtf16(unescaped);
|
||||
|
||||
if(unicode.size()*sizeof(wchar_t) > size_t(destsize))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
|
||||
if(size)
|
||||
{
|
||||
retsize = unicode.size() * 2; //return correct size
|
||||
return dest == nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
retsize = unicode.size() * 2;
|
||||
buffer = String((char*)unicode.c_str(), retsize);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if(retsize > size_t(destsize))
|
||||
{
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "dest buffer too small");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size)
|
||||
*size = int(retsize);
|
||||
|
||||
if(dest)
|
||||
memcpy_s((char*)dest, retsize, buffer.c_str(), retsize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
#include "_global.h"
|
||||
|
||||
void initDataInstMap();
|
||||
|
||||
bool isdatainstruction(const char* instruction);
|
||||
|
||||
bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error);
|
||||
|
||||
bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize);
|
||||
|
||||
bool trydisasmfast(const unsigned char* buffer, duint addr, BASIC_INSTRUCTION_INFO* basicinfo, duint codesize);
|
|
@ -1004,7 +1004,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
|||
if(!bFileIsDll && !bIsAttached) //Set entry breakpoint
|
||||
{
|
||||
pDebuggedBase = pCreateProcessBase; //debugged base = executable
|
||||
char command[256] = "";
|
||||
char command[deflen] = "";
|
||||
|
||||
if(settingboolget("Events", "TlsCallbacks"))
|
||||
{
|
||||
|
@ -1025,7 +1025,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
|||
duint callbackVA = TLSCallBacks()[i] - ImageBase + pDebuggedBase;
|
||||
if(MemIsValidReadPtr(callbackVA))
|
||||
{
|
||||
sprintf(command, "bp " fhex ",\"TLS Callback %d\",ss", callbackVA, i + 1);
|
||||
sprintf_s(command, "bp " fhex ",\"TLS Callback %d\",ss", callbackVA, i + 1);
|
||||
cmddirectexec(command);
|
||||
}
|
||||
else
|
||||
|
@ -1039,7 +1039,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
|||
|
||||
if(settingboolget("Events", "EntryBreakpoint"))
|
||||
{
|
||||
sprintf(command, "bp " fhex ",\"entry breakpoint\",ss", (duint)CreateProcessInfo->lpStartAddress);
|
||||
sprintf_s(command, "bp " fhex ",\"entry breakpoint\",ss", (duint)CreateProcessInfo->lpStartAddress);
|
||||
cmddirectexec(command);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "encodemap.h"
|
||||
#include <unordered_map>
|
||||
#include "addrinfo.h"
|
||||
#include <algorithm>
|
||||
#include <capstone_wrapper.h>
|
||||
|
||||
struct ENCODEMAP : AddrInfo
|
||||
|
@ -48,9 +47,8 @@ struct EncodeMapSerializer : AddrInfoSerializer<ENCODEMAP>
|
|||
{
|
||||
bool Save(const ENCODEMAP & value) override
|
||||
{
|
||||
|
||||
AddrInfoSerializer::Save(value);
|
||||
set("data", json_stringn((const char*)value.data, value.size));
|
||||
setString("data", StringUtils::ToCompressedHex(value.data, value.size).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,11 +56,17 @@ struct EncodeMapSerializer : AddrInfoSerializer<ENCODEMAP>
|
|||
{
|
||||
if(!AddrInfoSerializer::Load(value))
|
||||
return false;
|
||||
auto data = get("data");
|
||||
value.size = json_string_length(data);
|
||||
auto dataJson = get("data");
|
||||
if(!dataJson)
|
||||
return false;
|
||||
std::vector<unsigned char> data;
|
||||
if(!StringUtils::FromCompressedHex(json_string_value(dataJson), data))
|
||||
return false;
|
||||
value.size = data.size();
|
||||
value.data = (byte*)VirtualAlloc(NULL, value.size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
if(value.data == NULL) return false;
|
||||
memcpy(value.data, (byte*)json_string_value(data), value.size);
|
||||
if(!value.data)
|
||||
return false;
|
||||
memcpy(value.data, data.data(), data.size());
|
||||
IncreaseReferenceCount(value.data, false);
|
||||
return true;
|
||||
}
|
||||
|
@ -106,21 +110,19 @@ bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map)
|
|||
|
||||
void* EncodeMapGetBuffer(duint addr, bool create)
|
||||
{
|
||||
duint base, size;
|
||||
|
||||
if(!MemIsValidReadPtr(addr))
|
||||
return nullptr;
|
||||
base = MemFindBaseAddr(addr, &size);
|
||||
duint size;
|
||||
auto base = MemFindBaseAddr(addr, &size);
|
||||
|
||||
ENCODEMAP map;
|
||||
bool result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map);
|
||||
auto result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map);
|
||||
if(result)
|
||||
{
|
||||
duint offset = addr - base;
|
||||
if(offset >= map.size)
|
||||
return nullptr;
|
||||
IncreaseReferenceCount(map.data);
|
||||
return map.data;
|
||||
auto offset = addr - base;
|
||||
if(offset < map.size)
|
||||
{
|
||||
IncreaseReferenceCount(map.data);
|
||||
return map.data;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -136,25 +138,6 @@ void EncodeMapReleaseBuffer(void* buffer)
|
|||
EncodeMapReleaseBuffer(buffer, true);
|
||||
}
|
||||
|
||||
bool IsRangeConflict(byte* typebuffer, duint size, duint codesize)
|
||||
{
|
||||
if(codesize > size)
|
||||
return true;
|
||||
size = min(size, codesize);
|
||||
if(size <= 0)
|
||||
return false;
|
||||
ENCODETYPE type = (ENCODETYPE)typebuffer[0];
|
||||
if(type == enc_middle)
|
||||
return true;
|
||||
for(int i = 1; i < size; i++)
|
||||
{
|
||||
if((ENCODETYPE)typebuffer[i] != enc_unknown && (ENCODETYPE)typebuffer[i] != enc_middle)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
duint GetEncodeTypeSize(ENCODETYPE type)
|
||||
{
|
||||
switch(type)
|
||||
|
@ -194,73 +177,44 @@ duint GetEncodeTypeSize(ENCODETYPE type)
|
|||
}
|
||||
}
|
||||
|
||||
bool IsCodeType(ENCODETYPE type)
|
||||
static bool IsCodeType(ENCODETYPE type)
|
||||
{
|
||||
return type == enc_code || type == enc_junk;
|
||||
}
|
||||
|
||||
ENCODETYPE EncodeMapGetType(duint addr, duint codesize)
|
||||
{
|
||||
duint base, size;
|
||||
|
||||
base = MemFindBaseAddr(addr, &size);
|
||||
if(!base)
|
||||
return ENCODETYPE::enc_unknown;
|
||||
duint size;
|
||||
auto base = MemFindBaseAddr(addr, &size);
|
||||
|
||||
ENCODEMAP map;
|
||||
if(encmaps.Get(EncodeMap::VaKey(base), map))
|
||||
if(base && encmaps.Get(EncodeMap::VaKey(base), map))
|
||||
{
|
||||
duint offset = addr - base;
|
||||
auto offset = addr - base;
|
||||
if(offset >= map.size)
|
||||
return ENCODETYPE::enc_unknown;
|
||||
ENCODETYPE type = (ENCODETYPE)map.data[offset];
|
||||
|
||||
if((type == enc_unknown || type == enc_middle) && IsRangeConflict(map.data + offset, size - offset, codesize))
|
||||
return enc_byte;
|
||||
else
|
||||
return type;
|
||||
return enc_unknown;
|
||||
return ENCODETYPE(map.data[offset]);
|
||||
}
|
||||
|
||||
return ENCODETYPE::enc_unknown;
|
||||
return enc_unknown;
|
||||
}
|
||||
|
||||
duint EncodeMapGetSize(duint addr, duint codesize)
|
||||
{
|
||||
duint base;
|
||||
|
||||
base = MemFindBaseAddr(addr, 0);
|
||||
auto base = MemFindBaseAddr(addr, nullptr);
|
||||
if(!base)
|
||||
return codesize;
|
||||
|
||||
ENCODEMAP map;
|
||||
if(encmaps.Get(EncodeMap::VaKey(base), map))
|
||||
{
|
||||
duint offset = addr - base;
|
||||
auto offset = addr - base;
|
||||
if(offset >= map.size)
|
||||
return 1;
|
||||
ENCODETYPE type = (ENCODETYPE)map.data[offset];
|
||||
auto type = ENCODETYPE(map.data[offset]);
|
||||
|
||||
duint datasize = GetEncodeTypeSize(type);
|
||||
if(type == enc_unknown || type == enc_code || type == enc_junk)
|
||||
{
|
||||
if(IsRangeConflict(map.data + offset, map.size - offset, codesize) || codesize == 0)
|
||||
return datasize;
|
||||
else
|
||||
return codesize;
|
||||
}
|
||||
else if(type == enc_ascii || type == enc_unicode)
|
||||
{
|
||||
duint totalsize = 0;
|
||||
for(auto i = offset; i < map.size; i += datasize)
|
||||
{
|
||||
if(map.data[i] == type)
|
||||
totalsize += datasize;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return totalsize;
|
||||
}
|
||||
else
|
||||
auto datasize = GetEncodeTypeSize(type);
|
||||
if(!IsCodeType(type))
|
||||
return datasize;
|
||||
}
|
||||
|
||||
|
@ -269,19 +223,16 @@ duint EncodeMapGetSize(duint addr, duint codesize)
|
|||
|
||||
bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type)
|
||||
{
|
||||
duint base;
|
||||
|
||||
base = MemFindBaseAddr(addr, 0);
|
||||
auto base = MemFindBaseAddr(addr, nullptr);
|
||||
if(!base)
|
||||
return false;
|
||||
|
||||
|
||||
ENCODEMAP map;
|
||||
if(!EncodeMapGetorCreate(base, map))
|
||||
return false;
|
||||
duint offset = addr - base;
|
||||
auto offset = addr - base;
|
||||
size = min(map.size - offset, size);
|
||||
duint datasize = GetEncodeTypeSize(type);
|
||||
auto datasize = GetEncodeTypeSize(type);
|
||||
if(datasize == 1 && !IsCodeType(type))
|
||||
{
|
||||
memset(map.data + offset, (byte)type, size);
|
||||
|
@ -292,24 +243,20 @@ bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type)
|
|||
if(IsCodeType(type) && size > 1)
|
||||
{
|
||||
Capstone cp;
|
||||
unsigned char* buffer = new unsigned char[size];
|
||||
if(!MemRead(addr, buffer, size))
|
||||
{
|
||||
delete[] buffer;
|
||||
Memory<unsigned char*> buffer(size);
|
||||
if(!MemRead(addr, buffer(), size))
|
||||
return false;
|
||||
|
||||
}
|
||||
duint buffersize = size, bufferoffset = 0, cmdsize;
|
||||
for(auto i = offset; i < offset + size;)
|
||||
{
|
||||
map.data[i] = (byte)type;
|
||||
cp.Disassemble(base + i, buffer + bufferoffset, int(buffersize));
|
||||
cp.Disassemble(base + i, buffer() + bufferoffset, int(buffersize - bufferoffset));
|
||||
cmdsize = cp.Success() ? cp.Size() : 1;
|
||||
i += cmdsize;
|
||||
bufferoffset += cmdsize;
|
||||
buffersize -= cmdsize;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -2,25 +2,14 @@
|
|||
#include "_global.h"
|
||||
|
||||
void* EncodeMapGetBuffer(duint addr, bool create = false);
|
||||
|
||||
void EncodeMapReleaseBuffer(void* buffer);
|
||||
|
||||
ENCODETYPE EncodeMapGetType(duint addr, duint codesize);
|
||||
|
||||
duint EncodeMapGetSize(duint addr, duint codesize);
|
||||
|
||||
void EncodeMapDelSegment(duint addr);
|
||||
|
||||
void EncodeMapDelRange(duint addr, duint size);
|
||||
|
||||
bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type);
|
||||
|
||||
void EncodeMapDelRange(duint Start, duint End);
|
||||
|
||||
void EncodeMapCacheSave(JSON Root);
|
||||
|
||||
void EncodeMapCacheLoad(JSON Root);
|
||||
|
||||
void EncodeMapClear();
|
||||
|
||||
duint GetEncodeTypeSize(ENCODETYPE type);
|
|
@ -1,5 +1,6 @@
|
|||
#include "stringutils.h"
|
||||
#include "memory.h"
|
||||
#include "value.h"
|
||||
#include "dynamicmem.h"
|
||||
#include <windows.h>
|
||||
#include <cstdint>
|
||||
|
@ -71,6 +72,87 @@ String StringUtils::Escape(const String & s)
|
|||
return escaped;
|
||||
}
|
||||
|
||||
bool StringUtils::Unescape(const String & s, String & result, bool quoted)
|
||||
{
|
||||
int mLastChar;
|
||||
size_t i = 0;
|
||||
auto nextChar = [&]()
|
||||
{
|
||||
if(i == s.length())
|
||||
return mLastChar = EOF;
|
||||
return mLastChar = s[i++];
|
||||
};
|
||||
if(quoted)
|
||||
{
|
||||
nextChar();
|
||||
if(mLastChar != '\"') //start of quoted string literal
|
||||
return false; //invalid string literal
|
||||
}
|
||||
result.reserve(s.length());
|
||||
while(true)
|
||||
{
|
||||
nextChar();
|
||||
if(mLastChar == EOF) //end of file
|
||||
{
|
||||
if(!quoted)
|
||||
break;
|
||||
return false; //unexpected end of file in string literal (1)
|
||||
}
|
||||
if(mLastChar == '\r' || mLastChar == '\n')
|
||||
return false; //unexpected newline in string literal (1)
|
||||
if(quoted && mLastChar == '\"') //end of quoted string literal
|
||||
break;
|
||||
if(mLastChar == '\\') //escape sequence
|
||||
{
|
||||
nextChar();
|
||||
if(mLastChar == EOF)
|
||||
return false; //unexpected end of file in string literal (2)
|
||||
if(mLastChar == '\r' || mLastChar == '\n')
|
||||
return false; //unexpected newline in string literal (2)
|
||||
if(mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\')
|
||||
mLastChar = mLastChar;
|
||||
else if(mLastChar == 'a')
|
||||
mLastChar = '\a';
|
||||
else if(mLastChar == 'b')
|
||||
mLastChar = '\b';
|
||||
else if(mLastChar == 'f')
|
||||
mLastChar = '\f';
|
||||
else if(mLastChar == 'n')
|
||||
mLastChar = '\n';
|
||||
else if(mLastChar == 'r')
|
||||
mLastChar = '\r';
|
||||
else if(mLastChar == 't')
|
||||
mLastChar = '\t';
|
||||
else if(mLastChar == 'v')
|
||||
mLastChar = '\v';
|
||||
else if(mLastChar == '0')
|
||||
mLastChar = '\0';
|
||||
else if(mLastChar == 'x') //\xHH
|
||||
{
|
||||
auto ch1 = nextChar();
|
||||
auto ch2 = nextChar();
|
||||
if(isxdigit(ch1) && isxdigit(ch2))
|
||||
{
|
||||
char byteStr[3] = "";
|
||||
byteStr[0] = ch1;
|
||||
byteStr[1] = ch2;
|
||||
uint64_t hexData;
|
||||
auto error = convertLongLongNumber(byteStr, hexData, 16);
|
||||
if(error)
|
||||
return false; //convertNumber failed (%s) for hex sequence \"\\x%c%c\" in string literal
|
||||
mLastChar = hexData & 0xFF;
|
||||
}
|
||||
else
|
||||
return false; //invalid hex sequence \"\\x%c%c\" in string literal
|
||||
}
|
||||
else
|
||||
return false; //invalid escape sequence \"\\%c\" in string literal
|
||||
}
|
||||
result.push_back(mLastChar);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Trim functions taken from: http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring/16743707#16743707
|
||||
const String StringUtils::WHITESPACE = " \n\r\t";
|
||||
|
||||
|
@ -91,6 +173,17 @@ String StringUtils::TrimRight(const String & s, String delim)
|
|||
return (endpos == String::npos) ? "" : s.substr(0, endpos + 1);
|
||||
}
|
||||
|
||||
String StringUtils::PadLeft(const String & s, size_t minLength, char ch)
|
||||
{
|
||||
if(s.length() >= minLength)
|
||||
return s;
|
||||
String pad;
|
||||
pad.resize(minLength - s.length());
|
||||
for(size_t i = 0; i < pad.length(); i++)
|
||||
pad[i] = ch;
|
||||
return pad + s;
|
||||
}
|
||||
|
||||
//Conversion functions taken from: http://www.nubaria.com/en/blog/?p=289
|
||||
String StringUtils::Utf16ToUtf8(const WString & wstr)
|
||||
{
|
||||
|
@ -202,67 +295,115 @@ bool StringUtils::StartsWith(const String & h, const String & n)
|
|||
return strstr(h.c_str(), n.c_str()) == h.c_str();
|
||||
}
|
||||
|
||||
int char2int(char input)
|
||||
static int hex2int(char ch)
|
||||
{
|
||||
if(input >= '0' && input <= '9')
|
||||
return input - '0';
|
||||
if(input >= 'A' && input <= 'F')
|
||||
return input - 'A' + 10;
|
||||
if(input >= 'a' && input <= 'f')
|
||||
return input - 'a' + 10;
|
||||
throw std::invalid_argument("invalid character");
|
||||
if(ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
if(ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
if(ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
String StringUtils::FromHex(const String & s, size_t size, bool reverse)
|
||||
bool StringUtils::FromHex(const String & text, std::vector<unsigned char> & data, bool reverse)
|
||||
{
|
||||
std::stringstream ss;
|
||||
bool high = false;
|
||||
if(s.length() > size * 2)
|
||||
throw std::invalid_argument("string too long");
|
||||
char ch = 0;
|
||||
auto odd = s.size() % 2;
|
||||
size_t cursize = 0;
|
||||
for(dsint i = s.size() - 1; i >= 0; i--)
|
||||
auto size = text.size();
|
||||
if(size % 2)
|
||||
return false;
|
||||
data.resize(size / 2);
|
||||
for(size_t i = 0, j = 0; i < size; i += 2, j++)
|
||||
{
|
||||
ch |= char2int(s[i]) << (high ? 4 : 0);
|
||||
if(high || odd && i == 0)
|
||||
auto high = hex2int(text[i]);
|
||||
auto low = hex2int(text[i + 1]);
|
||||
if(high == -1 || low == -1)
|
||||
return false;
|
||||
data[reverse ? data.size() - j - 1 : j] = (high << 4) | low;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String StringUtils::ToHex(unsigned long long value)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf_s(buf, "%llX", value);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define HEXLOOKUP "0123456789ABCDEF"
|
||||
|
||||
String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
|
||||
{
|
||||
String result;
|
||||
result.resize(size * 2);
|
||||
for(size_t i = 0, j = 0; i < size; i++, j += 2)
|
||||
{
|
||||
auto ch = buffer[reverse ? size - i - 1 : i];
|
||||
result[j] = HEXLOOKUP[(ch >> 4) & 0xF];
|
||||
result[j + 1] = HEXLOOKUP[ch & 0xF];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String StringUtils::ToCompressedHex(unsigned char* buffer, size_t size)
|
||||
{
|
||||
if(!size)
|
||||
return "";
|
||||
String result;
|
||||
result.reserve(size * 2);
|
||||
for(size_t i = 0; i < size;)
|
||||
{
|
||||
size_t repeat = 0;
|
||||
auto lastCh = buffer[i];
|
||||
result.push_back(HEXLOOKUP[(lastCh >> 4) & 0xF]);
|
||||
result.push_back(HEXLOOKUP[lastCh & 0xF]);
|
||||
for(; i < size && buffer[i] == lastCh; i++)
|
||||
repeat++;
|
||||
result.append(StringUtils::sprintf("{%" fext "X}", repeat));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool StringUtils::FromCompressedHex(const String & text, std::vector<unsigned char> & data)
|
||||
{
|
||||
auto size = text.size();
|
||||
if(size < 2)
|
||||
return false;
|
||||
data.clear();
|
||||
data.reserve(size); //TODO: better initial estimate
|
||||
String repeatStr;
|
||||
for(size_t i = 0; i < size;)
|
||||
{
|
||||
auto high = hex2int(text[i++]); //eat high nibble
|
||||
if(i >= size)
|
||||
return false;
|
||||
auto low = hex2int(text[i++]); //eat low nibble
|
||||
if(high == -1 || low == -1)
|
||||
return false;
|
||||
auto lastCh = (high << 4) | low;
|
||||
data.push_back(lastCh);
|
||||
|
||||
if(i >= size)
|
||||
break;
|
||||
|
||||
if(text[i] == '{')
|
||||
{
|
||||
ss.put(ch);
|
||||
cursize++;
|
||||
ch = 0;
|
||||
repeatStr.clear();
|
||||
i++; //eat '{'
|
||||
while(text[i] != '}')
|
||||
{
|
||||
repeatStr.push_back(text[i++]); //eat character
|
||||
if(i >= size)
|
||||
return false;
|
||||
}
|
||||
i++; //eat '}'
|
||||
|
||||
duint repeat = 0;
|
||||
if(!convertNumber(repeatStr.c_str(), repeat, 16) || !repeat)
|
||||
return false;
|
||||
for(size_t j = 1; j < repeat; j++)
|
||||
data.push_back(lastCh);
|
||||
}
|
||||
high = !high;
|
||||
}
|
||||
for(auto i = cursize; i < size; i++)
|
||||
ss.put('\0');
|
||||
String res = ss.str();
|
||||
if(!reverse)
|
||||
std::reverse(res.begin(), res.end());
|
||||
return res;
|
||||
}
|
||||
|
||||
String StringUtils::ToHex(duint value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
ss << value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
String StringUtils::ToHex(void* buffer, size_t size, bool reverse)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
if(reverse)
|
||||
{
|
||||
for(dsint i = size - 1; i >= 0; i--)
|
||||
ss << ((char*)buffer)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < size; i++)
|
||||
ss << ((char*)buffer)[i];
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -18,9 +18,11 @@ public:
|
|||
static StringList Split(const String & s, char delim, std::vector<String> & elems);
|
||||
static StringList Split(const String & s, char delim);
|
||||
static String Escape(const String & s);
|
||||
static bool Unescape(const String & s, String & result, bool quoted = true);
|
||||
static String Trim(const String & s, String delim = StringUtils::WHITESPACE);
|
||||
static String TrimLeft(const String & s, String delim = StringUtils::WHITESPACE);
|
||||
static String TrimRight(const String & s, String delim = StringUtils::WHITESPACE);
|
||||
static String PadLeft(const String & s, size_t minLength, char ch);
|
||||
static String Utf16ToUtf8(const WString & wstr);
|
||||
static String Utf16ToUtf8(const wchar_t* wstr);
|
||||
static WString Utf8ToUtf16(const String & str);
|
||||
|
@ -31,9 +33,11 @@ public:
|
|||
static WString sprintf(const wchar_t* format, ...);
|
||||
static String ToLower(const String & s);
|
||||
static bool StartsWith(const String & h, const String & n);
|
||||
static String FromHex(const String & s, size_t size, bool reverse = false);
|
||||
static String ToHex(duint value);
|
||||
static String ToHex(void* buffer, size_t size, bool reverse = false);
|
||||
static bool FromHex(const String & text, std::vector<unsigned char> & data, bool reverse = false);
|
||||
static String ToHex(unsigned long long value);
|
||||
static String ToHex(unsigned char* buffer, size_t size, bool reverse = false);
|
||||
static String ToCompressedHex(unsigned char* buffer, size_t size);
|
||||
static bool FromCompressedHex(const String & text, std::vector<unsigned char> & data);
|
||||
|
||||
template<typename T>
|
||||
static String ToFloatingString(void* buffer)
|
||||
|
@ -51,7 +55,6 @@ public:
|
|||
return ToHex(value);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static const String WHITESPACE;
|
||||
};
|
||||
|
|
|
@ -1490,14 +1490,19 @@ static bool ishexnumber(const char* string)
|
|||
}
|
||||
|
||||
bool convertNumber(const char* str, duint & result, int radix)
|
||||
{
|
||||
unsigned long long llr;
|
||||
if(!convertLongLongNumber(str, llr, radix))
|
||||
return false;
|
||||
result = duint(llr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool convertLongLongNumber(const char* str, unsigned long long & result, int radix)
|
||||
{
|
||||
errno = 0;
|
||||
char* end;
|
||||
#ifdef _WIN64
|
||||
result = strtoull(str, &end, radix);
|
||||
#else
|
||||
result = strtoul(str, &end, radix);
|
||||
#endif //_WIN64
|
||||
if(!result && end == str)
|
||||
return false;
|
||||
if(result == ULLONG_MAX && errno)
|
||||
|
|
|
@ -8,6 +8,7 @@ bool valuesignedcalc();
|
|||
void valuesetsignedcalc(bool a);
|
||||
bool valapifromstring(const char* name, duint* value, int* value_size, bool printall, bool silent, bool* hexonly);
|
||||
bool convertNumber(const char* str, duint & result, int radix);
|
||||
bool convertLongLongNumber(const char* str, unsigned long long & result, int radix);
|
||||
bool valfromstring_noexpr(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
|
||||
bool valfromstring(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
|
||||
bool valflagfromstring(duint eflags, const char* string);
|
||||
|
|
Loading…
Reference in New Issue