1
0
Fork 0

PROJECT: fixed line endings (hopefully for good now)

This commit is contained in:
mrexodia 2015-11-24 01:50:17 +01:00
parent 6508104c81
commit 1731e1dee5
363 changed files with 80868 additions and 80868 deletions

Binary file not shown.

View File

@ -1,326 +1,326 @@
#ifndef _UTF8INI_H
#define _UTF8INI_H
#include <string>
#include <map>
#include <vector>
class Utf8Ini
{
public:
/**
\brief Serialize to the INI file format.
*/
inline std::string Serialize() const
{
std::string output;
for(const auto & section : _sections)
{
if(output.length())
appendLine(output, "");
appendLine(output, makeSectionText(section.first));
for(const auto & keyvalue : section.second)
if(keyvalue.first.length())
appendLine(output, makeKeyValueText(keyvalue.first, keyvalue.second));
}
return output;
}
/**
\brief Deserialize from the INI file format.
\param data The INI data.
\param [out] errorLine The error line (only has a meaning when this function failed).
\return true if it succeeds, false if it fails.
*/
inline bool Deserialize(const std::string & data, int & errorLine)
{
//initialize
errorLine = 0;
Clear();
//read lines
std::vector<std::string> lines;
std::string curLine;
for(auto ch : data)
{
switch(ch)
{
case '\r':
break;
case '\n':
lines.push_back(trim(curLine));
curLine.clear();
break;
default:
curLine += ch;
}
}
if(curLine.length())
lines.push_back(trim(curLine));
//parse lines
std::string section = "";
for(const auto & line : lines)
{
errorLine++;
switch(getLineType(line))
{
case LineType::Invalid:
MessageBoxA(0, line.c_str(), "line", 0);
return false;
case LineType::Comment:
case LineType::Empty:
continue;
case LineType::KeyValue:
{
std::string key;
std::string value;
if(!section.length() ||
!parseKeyValueLine(line, key, value) ||
!SetValue(section, key, value))
return false;
}
break;
case LineType::Section:
if(!parseSectionLine(line, section))
return false;
}
}
return true;
}
/**
\brief Sets a value. This will overwrite older values.
\param section The section. Must have a length greater than one.
\param key The key. Must have a length greater than one.
\param value The value. Can be empty (effectively removing the value).
\return true if the value was set successfully, false otherwise.
*/
inline bool SetValue(const std::string & section, const std::string & key, const std::string & value)
{
auto trimmedSection = trim(section);
auto trimmedKey = trim(key);
if(!trimmedSection.length() || !trimmedKey.length())
return false;
auto found = _sections.find(trimmedSection);
if(found != _sections.end())
found->second[trimmedKey] = value;
else
{
KeyValueMap keyValueMap;
keyValueMap[trimmedKey] = value;
_sections[trimmedSection] = keyValueMap;
}
return true;
}
/**
\brief Removes all key/value pairs from a section.
\param section The section to clear.
\return true if it succeeds, false otherwise.
*/
inline bool ClearSection(const std::string & section)
{
auto trimmedSection = trim(section);
if(!trimmedSection.length())
return false;
auto found = _sections.find(trimmedSection);
if(found == _sections.end())
return false;
_sections.erase(found);
return true;
}
/**
\brief Removes all sections.
*/
inline void Clear()
{
_sections.clear();
}
/**
\brief Gets a value.
\param section The section.
\param key The key.
\param [in,out] value The value.
\return The value. Empty string when the value was not found or empty.
*/
inline std::string GetValue(const std::string & section, const std::string & key) const
{
auto trimmedSection = trim(section);
auto trimmedKey = trim(key);
if(!trimmedSection.length() || !trimmedKey.length())
return "";
auto sectionFound = _sections.find(trimmedSection);
if(sectionFound == _sections.end())
return "";
const auto & keyValueMap = sectionFound->second;
auto keyFound = keyValueMap.find(trimmedKey);
if(keyFound == keyValueMap.end())
return "";
return keyFound->second;
}
private:
typedef std::map<std::string, std::string> KeyValueMap;
std::map<std::string, KeyValueMap> _sections;
enum class LineType
{
Invalid,
Empty,
Section,
KeyValue,
Comment
};
static inline LineType getLineType(const std::string & line)
{
auto len = line.length();
if(!len)
return LineType::Empty;
if(line[0] == '[' && line[len - 1] == ']')
return LineType::Section;
if(line[0] == ';')
return LineType::Comment;
if(line.find('=') != std::string::npos)
return LineType::KeyValue;
return LineType::Invalid;
}
static inline std::string trim(const std::string & str)
{
auto len = str.length();
if(!len)
return "";
size_t pre = 0;
while(str[pre] == ' ')
pre++;
size_t post = 0;
while(str[len - post - 1] == ' ' && post < len)
post++;
auto sublen = len - post - pre;
return sublen > 0 ? str.substr(pre, len - post - pre) : "";
}
static inline bool parseKeyValueLine(const std::string & line, std::string & key, std::string & value)
{
auto pos = line.find('=');
key = trim(line.substr(0, pos));
value = trim(line.substr(pos + 1));
auto len = value.length();
if(len && value[0] == '\"' && value[len - 1] == '\"')
value = unescapeValue(value);
return true;
}
static inline bool parseSectionLine(const std::string & line, std::string & section)
{
section = trim(line.substr(1, line.length() - 2));
return section.length() > 0;
}
static inline void appendLine(std::string & output, const std::string & line)
{
if(output.length())
output += "\r\n";
output += line;
}
static inline std::string makeSectionText(const std::string & section)
{
return "[" + section + "]";
}
static inline std::string makeKeyValueText(const std::string & key, const std::string & value)
{
return key + "=" + escapeValue(value);
}
static inline bool needsEscaping(const std::string & value)
{
auto len = value.length();
return len && (value[0] == ' ' || value[len - 1] == ' ' ||
value.find('\n') != std::string::npos ||
value.find('\"') != std::string::npos);
}
static inline std::string escapeValue(const std::string & value)
{
if(!needsEscaping(value))
return value;
std::string escaped = "\"";
for(auto ch : value)
{
switch(ch)
{
case '\"':
escaped += "\\\"";
break;
case '\\':
escaped += "\\\\";
break;
case '\r':
escaped += "\\r";
break;
case '\n':
escaped += "\\n";
break;
case '\t':
escaped += "\\t";
default:
escaped += ch;
}
}
return escaped + "\"";
}
static inline std::string unescapeValue(const std::string & str)
{
std::string result;
bool bEscaped = false;
for(auto ch : str)
{
if(!bEscaped)
{
switch(ch)
{
case '\"':
break;
case '\\':
bEscaped = true;
break;
default:
result += ch;
}
}
else
{
switch(ch)
{
case 'r':
result += '\r';
break;
case 'n':
result += '\n';
break;
case 't':
result += '\t';
break;
default:
result += ch;
}
bEscaped = false;
}
}
if(bEscaped)
result += '\\';
return result;
}
};
#ifndef _UTF8INI_H
#define _UTF8INI_H
#include <string>
#include <map>
#include <vector>
class Utf8Ini
{
public:
/**
\brief Serialize to the INI file format.
*/
inline std::string Serialize() const
{
std::string output;
for(const auto & section : _sections)
{
if(output.length())
appendLine(output, "");
appendLine(output, makeSectionText(section.first));
for(const auto & keyvalue : section.second)
if(keyvalue.first.length())
appendLine(output, makeKeyValueText(keyvalue.first, keyvalue.second));
}
return output;
}
/**
\brief Deserialize from the INI file format.
\param data The INI data.
\param [out] errorLine The error line (only has a meaning when this function failed).
\return true if it succeeds, false if it fails.
*/
inline bool Deserialize(const std::string & data, int & errorLine)
{
//initialize
errorLine = 0;
Clear();
//read lines
std::vector<std::string> lines;
std::string curLine;
for(auto ch : data)
{
switch(ch)
{
case '\r':
break;
case '\n':
lines.push_back(trim(curLine));
curLine.clear();
break;
default:
curLine += ch;
}
}
if(curLine.length())
lines.push_back(trim(curLine));
//parse lines
std::string section = "";
for(const auto & line : lines)
{
errorLine++;
switch(getLineType(line))
{
case LineType::Invalid:
MessageBoxA(0, line.c_str(), "line", 0);
return false;
case LineType::Comment:
case LineType::Empty:
continue;
case LineType::KeyValue:
{
std::string key;
std::string value;
if(!section.length() ||
!parseKeyValueLine(line, key, value) ||
!SetValue(section, key, value))
return false;
}
break;
case LineType::Section:
if(!parseSectionLine(line, section))
return false;
}
}
return true;
}
/**
\brief Sets a value. This will overwrite older values.
\param section The section. Must have a length greater than one.
\param key The key. Must have a length greater than one.
\param value The value. Can be empty (effectively removing the value).
\return true if the value was set successfully, false otherwise.
*/
inline bool SetValue(const std::string & section, const std::string & key, const std::string & value)
{
auto trimmedSection = trim(section);
auto trimmedKey = trim(key);
if(!trimmedSection.length() || !trimmedKey.length())
return false;
auto found = _sections.find(trimmedSection);
if(found != _sections.end())
found->second[trimmedKey] = value;
else
{
KeyValueMap keyValueMap;
keyValueMap[trimmedKey] = value;
_sections[trimmedSection] = keyValueMap;
}
return true;
}
/**
\brief Removes all key/value pairs from a section.
\param section The section to clear.
\return true if it succeeds, false otherwise.
*/
inline bool ClearSection(const std::string & section)
{
auto trimmedSection = trim(section);
if(!trimmedSection.length())
return false;
auto found = _sections.find(trimmedSection);
if(found == _sections.end())
return false;
_sections.erase(found);
return true;
}
/**
\brief Removes all sections.
*/
inline void Clear()
{
_sections.clear();
}
/**
\brief Gets a value.
\param section The section.
\param key The key.
\param [in,out] value The value.
\return The value. Empty string when the value was not found or empty.
*/
inline std::string GetValue(const std::string & section, const std::string & key) const
{
auto trimmedSection = trim(section);
auto trimmedKey = trim(key);
if(!trimmedSection.length() || !trimmedKey.length())
return "";
auto sectionFound = _sections.find(trimmedSection);
if(sectionFound == _sections.end())
return "";
const auto & keyValueMap = sectionFound->second;
auto keyFound = keyValueMap.find(trimmedKey);
if(keyFound == keyValueMap.end())
return "";
return keyFound->second;
}
private:
typedef std::map<std::string, std::string> KeyValueMap;
std::map<std::string, KeyValueMap> _sections;
enum class LineType
{
Invalid,
Empty,
Section,
KeyValue,
Comment
};
static inline LineType getLineType(const std::string & line)
{
auto len = line.length();
if(!len)
return LineType::Empty;
if(line[0] == '[' && line[len - 1] == ']')
return LineType::Section;
if(line[0] == ';')
return LineType::Comment;
if(line.find('=') != std::string::npos)
return LineType::KeyValue;
return LineType::Invalid;
}
static inline std::string trim(const std::string & str)
{
auto len = str.length();
if(!len)
return "";
size_t pre = 0;
while(str[pre] == ' ')
pre++;
size_t post = 0;
while(str[len - post - 1] == ' ' && post < len)
post++;
auto sublen = len - post - pre;
return sublen > 0 ? str.substr(pre, len - post - pre) : "";
}
static inline bool parseKeyValueLine(const std::string & line, std::string & key, std::string & value)
{
auto pos = line.find('=');
key = trim(line.substr(0, pos));
value = trim(line.substr(pos + 1));
auto len = value.length();
if(len && value[0] == '\"' && value[len - 1] == '\"')
value = unescapeValue(value);
return true;
}
static inline bool parseSectionLine(const std::string & line, std::string & section)
{
section = trim(line.substr(1, line.length() - 2));
return section.length() > 0;
}
static inline void appendLine(std::string & output, const std::string & line)
{
if(output.length())
output += "\r\n";
output += line;
}
static inline std::string makeSectionText(const std::string & section)
{
return "[" + section + "]";
}
static inline std::string makeKeyValueText(const std::string & key, const std::string & value)
{
return key + "=" + escapeValue(value);
}
static inline bool needsEscaping(const std::string & value)
{
auto len = value.length();
return len && (value[0] == ' ' || value[len - 1] == ' ' ||
value.find('\n') != std::string::npos ||
value.find('\"') != std::string::npos);
}
static inline std::string escapeValue(const std::string & value)
{
if(!needsEscaping(value))
return value;
std::string escaped = "\"";
for(auto ch : value)
{
switch(ch)
{
case '\"':
escaped += "\\\"";
break;
case '\\':
escaped += "\\\\";
break;
case '\r':
escaped += "\\r";
break;
case '\n':
escaped += "\\n";
break;
case '\t':
escaped += "\\t";
default:
escaped += ch;
}
}
return escaped + "\"";
}
static inline std::string unescapeValue(const std::string & str)
{
std::string result;
bool bEscaped = false;
for(auto ch : str)
{
if(!bEscaped)
{
switch(ch)
{
case '\"':
break;
case '\\':
bEscaped = true;
break;
default:
result += ch;
}
}
else
{
switch(ch)
{
case 'r':
result += '\r';
break;
case 'n':
result += '\n';
break;
case 't':
result += '\t';
break;
default:
result += ch;
}
bEscaped = false;
}
}
if(bEscaped)
result += '\\';
return result;
}
};
#endif //_UTF8INI_H

View File

@ -1,26 +1,26 @@
#include "_global.h"
GUIGUIINIT _gui_guiinit;
GUISENDMESSAGE _gui_sendmessage;
GUISENDMESSAGEASYNC _gui_sendmessageasync;
DBGDBGINIT _dbg_dbginit;
DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
DBGMEMREAD _dbg_memread;
DBGMEMWRITE _dbg_memwrite;
DBGDBGCMDEXEC _dbg_dbgcmdexec;
DBGMEMMAP _dbg_memmap;
DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
DBGVALFROMSTRING _dbg_valfromstring;
DBGISDEBUGGING _dbg_isdebugging;
DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
DBGADDRINFOGET _dbg_addrinfoget;
DBGADDRINFOSET _dbg_addrinfoset;
DBGBPGETTYPEAT _dbg_bpgettypeat;
DBGGETREGDUMP _dbg_getregdump;
DBGVALTOSTRING _dbg_valtostring;
DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
DBGGETBPLIST _dbg_getbplist;
DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
DBGSENDMESSAGE _dbg_sendmessage;
#include "_global.h"
GUIGUIINIT _gui_guiinit;
GUISENDMESSAGE _gui_sendmessage;
GUISENDMESSAGEASYNC _gui_sendmessageasync;
DBGDBGINIT _dbg_dbginit;
DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
DBGMEMREAD _dbg_memread;
DBGMEMWRITE _dbg_memwrite;
DBGDBGCMDEXEC _dbg_dbgcmdexec;
DBGMEMMAP _dbg_memmap;
DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
DBGVALFROMSTRING _dbg_valfromstring;
DBGISDEBUGGING _dbg_isdebugging;
DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
DBGADDRINFOGET _dbg_addrinfoget;
DBGADDRINFOSET _dbg_addrinfoset;
DBGBPGETTYPEAT _dbg_bpgettypeat;
DBGGETREGDUMP _dbg_getregdump;
DBGVALTOSTRING _dbg_valtostring;
DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
DBGGETBPLIST _dbg_getbplist;
DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
DBGSENDMESSAGE _dbg_sendmessage;

View File

@ -1,61 +1,61 @@
#ifndef _GLOBAL_H
#define _GLOBAL_H
#include <windows.h>
#include "bridgemain.h"
//GUI typedefs
typedef int (*GUIGUIINIT)(int, char**);
typedef void* (*GUISENDMESSAGE)(GUIMSG type, void* param1, void* param2);
typedef void (*GUISENDMESSAGEASYNC)(GUIMSG type, void* param1, void* param2);
//GUI functions
extern GUIGUIINIT _gui_guiinit;
extern GUISENDMESSAGE _gui_sendmessage;
extern GUISENDMESSAGEASYNC _gui_sendmessageasync;
//DBG typedefs
typedef const char* (*DBGDBGINIT)();
typedef duint (*DBGMEMFINDBASEADDR)(duint addr, duint* size);
typedef bool (*DBGMEMREAD)(duint addr, unsigned char* dest, duint size, duint* read);
typedef bool (*DBGMEMWRITE)(duint addr, const unsigned char* src, duint size, duint* written);
typedef bool (*DBGDBGCMDEXEC)(const char* cmd);
typedef bool (*DBGMEMMAP)(MEMMAP* memmap);
typedef void (*DBGDBGEXITSIGNAL)();
typedef bool (*DBGVALFROMSTRING)(const char* string, duint* value);
typedef bool (*DBGISDEBUGGING)();
typedef bool (*DBGISJUMPGOINGTOEXECUTE)(duint addr);
typedef bool (*DBGADDRINFOGET)(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
typedef bool (*DBGADDRINFOSET)(duint addr, ADDRINFO* addrinfo);
typedef BPXTYPE (*DBGBPGETTYPEAT)(duint addr);
typedef bool (*DBGGETREGDUMP)(REGDUMP* regdump);
typedef bool (*DBGVALTOSTRING)(const char* string, duint value);
typedef bool (*DBGMEMISVALIDREADPTR)(duint addr);
typedef int (*DBGGETBPLIST)(BPXTYPE type, BPMAP* bplist);
typedef bool (*DBGDBGCMDEXECDIRECT)(const char* cmd);
typedef duint (*DBGGETBRANCHDESTINATION)(duint addr);
typedef duint (*DBGSENDMESSAGE)(DBGMSG type, void* param1, void* param2);
//DBG functions
extern DBGDBGINIT _dbg_dbginit;
extern DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
extern DBGMEMREAD _dbg_memread;
extern DBGMEMWRITE _dbg_memwrite;
extern DBGDBGCMDEXEC _dbg_dbgcmdexec;
extern DBGMEMMAP _dbg_memmap;
extern DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
extern DBGVALFROMSTRING _dbg_valfromstring;
extern DBGISDEBUGGING _dbg_isdebugging;
extern DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
extern DBGADDRINFOGET _dbg_addrinfoget;
extern DBGADDRINFOSET _dbg_addrinfoset;
extern DBGBPGETTYPEAT _dbg_bpgettypeat;
extern DBGGETREGDUMP _dbg_getregdump;
extern DBGVALTOSTRING _dbg_valtostring;
extern DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
extern DBGGETBPLIST _dbg_getbplist;
extern DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
extern DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
extern DBGSENDMESSAGE _dbg_sendmessage;
#endif // _GLOBAL_H
#ifndef _GLOBAL_H
#define _GLOBAL_H
#include <windows.h>
#include "bridgemain.h"
//GUI typedefs
typedef int (*GUIGUIINIT)(int, char**);
typedef void* (*GUISENDMESSAGE)(GUIMSG type, void* param1, void* param2);
typedef void (*GUISENDMESSAGEASYNC)(GUIMSG type, void* param1, void* param2);
//GUI functions
extern GUIGUIINIT _gui_guiinit;
extern GUISENDMESSAGE _gui_sendmessage;
extern GUISENDMESSAGEASYNC _gui_sendmessageasync;
//DBG typedefs
typedef const char* (*DBGDBGINIT)();
typedef duint (*DBGMEMFINDBASEADDR)(duint addr, duint* size);
typedef bool (*DBGMEMREAD)(duint addr, unsigned char* dest, duint size, duint* read);
typedef bool (*DBGMEMWRITE)(duint addr, const unsigned char* src, duint size, duint* written);
typedef bool (*DBGDBGCMDEXEC)(const char* cmd);
typedef bool (*DBGMEMMAP)(MEMMAP* memmap);
typedef void (*DBGDBGEXITSIGNAL)();
typedef bool (*DBGVALFROMSTRING)(const char* string, duint* value);
typedef bool (*DBGISDEBUGGING)();
typedef bool (*DBGISJUMPGOINGTOEXECUTE)(duint addr);
typedef bool (*DBGADDRINFOGET)(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
typedef bool (*DBGADDRINFOSET)(duint addr, ADDRINFO* addrinfo);
typedef BPXTYPE (*DBGBPGETTYPEAT)(duint addr);
typedef bool (*DBGGETREGDUMP)(REGDUMP* regdump);
typedef bool (*DBGVALTOSTRING)(const char* string, duint value);
typedef bool (*DBGMEMISVALIDREADPTR)(duint addr);
typedef int (*DBGGETBPLIST)(BPXTYPE type, BPMAP* bplist);
typedef bool (*DBGDBGCMDEXECDIRECT)(const char* cmd);
typedef duint (*DBGGETBRANCHDESTINATION)(duint addr);
typedef duint (*DBGSENDMESSAGE)(DBGMSG type, void* param1, void* param2);
//DBG functions
extern DBGDBGINIT _dbg_dbginit;
extern DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
extern DBGMEMREAD _dbg_memread;
extern DBGMEMWRITE _dbg_memwrite;
extern DBGDBGCMDEXEC _dbg_dbgcmdexec;
extern DBGMEMMAP _dbg_memmap;
extern DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
extern DBGVALFROMSTRING _dbg_valfromstring;
extern DBGISDEBUGGING _dbg_isdebugging;
extern DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
extern DBGADDRINFOGET _dbg_addrinfoget;
extern DBGADDRINFOSET _dbg_addrinfoset;
extern DBGBPGETTYPEAT _dbg_bpgettypeat;
extern DBGGETREGDUMP _dbg_getregdump;
extern DBGVALTOSTRING _dbg_valtostring;
extern DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
extern DBGGETBPLIST _dbg_getbplist;
extern DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
extern DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
extern DBGSENDMESSAGE _dbg_sendmessage;
#endif // _GLOBAL_H

View File

@ -1,129 +1,129 @@
#ifndef _LIST_H
#define _LIST_H
typedef struct
{
int count; //Number of element in the list.
size_t size; //Size of list in bytes (used for type checking).
void* data; //Pointer to the list contents. Must be deleted by the caller using BridgeFree (or List::Free).
} ListInfo;
#define ListOf(Type) ListInfo*
#ifdef __cplusplus
#include <vector>
/**
\brief A list object. This object is NOT thread safe.
\tparam Type List contents type.
*/
template<typename Type>
class List
{
public:
/**
\brief List constructor.
\param _freeData (Optional) the free function.
*/
explicit inline List()
{
memset(&_listInfo, 0, sizeof(_listInfo));
}
/**
\brief List destructor.
*/
inline ~List()
{
cleanup();
}
/**
\brief Gets the list data.
\return Returns ListInfo->data. Can be null if the list was never initialized. Will be destroyed once this object goes out of scope!
*/
inline Type* data() const
{
return reinterpret_cast<Type*>(_listInfo.data);
}
/**
\brief Gets the number of elements in the list. This will crash the program if the data is not consistent with the specified template argument.
\return The number of elements in the list.
*/
inline int count() const
{
if(_listInfo.size != _listInfo.count * sizeof(Type)) //make sure the user is using the correct type.
__debugbreak();
return _listInfo.count;
}
/**
\brief Cleans up the list, freeing the list data when it is not null.
*/
inline void cleanup()
{
if(_listInfo.data)
{
BridgeFree(_listInfo.data);
_listInfo.data = nullptr;
}
}
/**
\brief Reference operator (cleans up the previous list)
\return Pointer to the ListInfo.
*/
inline ListInfo* operator&()
{
cleanup();
return &_listInfo;
}
/**
\brief Array indexer operator. This will crash if you try to access out-of-bounds.
\param index Zero-based index of the item you want to get.
\return Reference to a value at that index.
*/
inline Type & operator[](size_t index) const
{
if(index >= size_t(count())) //make sure the out-of-bounds access is caught as soon as possible.
__debugbreak();
return data()[index];
}
/**
\brief Copies data to a ListInfo structure..
\param [out] listInfo If non-null, information describing the list.
\param listData Data to copy in the ListInfo structure.
\return true if it succeeds, false if it fails.
*/
static inline bool CopyData(ListInfo* listInfo, const std::vector<Type> & listData)
{
if(!listInfo)
return false;
listInfo->count = int(listData.size());
listInfo->size = listInfo->count * sizeof(Type);
if(listInfo->count)
{
listInfo->data = BridgeAlloc(listInfo->size);
Type* curItem = reinterpret_cast<Type*>(listInfo->data);
for(const auto & item : listData)
{
*curItem = item;
++curItem;
}
}
else
listInfo->data = nullptr;
return true;
}
private:
ListInfo _listInfo;
};
#endif //__cplusplus
#ifndef _LIST_H
#define _LIST_H
typedef struct
{
int count; //Number of element in the list.
size_t size; //Size of list in bytes (used for type checking).
void* data; //Pointer to the list contents. Must be deleted by the caller using BridgeFree (or List::Free).
} ListInfo;
#define ListOf(Type) ListInfo*
#ifdef __cplusplus
#include <vector>
/**
\brief A list object. This object is NOT thread safe.
\tparam Type List contents type.
*/
template<typename Type>
class List
{
public:
/**
\brief List constructor.
\param _freeData (Optional) the free function.
*/
explicit inline List()
{
memset(&_listInfo, 0, sizeof(_listInfo));
}
/**
\brief List destructor.
*/
inline ~List()
{
cleanup();
}
/**
\brief Gets the list data.
\return Returns ListInfo->data. Can be null if the list was never initialized. Will be destroyed once this object goes out of scope!
*/
inline Type* data() const
{
return reinterpret_cast<Type*>(_listInfo.data);
}
/**
\brief Gets the number of elements in the list. This will crash the program if the data is not consistent with the specified template argument.
\return The number of elements in the list.
*/
inline int count() const
{
if(_listInfo.size != _listInfo.count * sizeof(Type)) //make sure the user is using the correct type.
__debugbreak();
return _listInfo.count;
}
/**
\brief Cleans up the list, freeing the list data when it is not null.
*/
inline void cleanup()
{
if(_listInfo.data)
{
BridgeFree(_listInfo.data);
_listInfo.data = nullptr;
}
}
/**
\brief Reference operator (cleans up the previous list)
\return Pointer to the ListInfo.
*/
inline ListInfo* operator&()
{
cleanup();
return &_listInfo;
}
/**
\brief Array indexer operator. This will crash if you try to access out-of-bounds.
\param index Zero-based index of the item you want to get.
\return Reference to a value at that index.
*/
inline Type & operator[](size_t index) const
{
if(index >= size_t(count())) //make sure the out-of-bounds access is caught as soon as possible.
__debugbreak();
return data()[index];
}
/**
\brief Copies data to a ListInfo structure..
\param [out] listInfo If non-null, information describing the list.
\param listData Data to copy in the ListInfo structure.
\return true if it succeeds, false if it fails.
*/
static inline bool CopyData(ListInfo* listInfo, const std::vector<Type> & listData)
{
if(!listInfo)
return false;
listInfo->count = int(listData.size());
listInfo->size = listInfo->count * sizeof(Type);
if(listInfo->count)
{
listInfo->data = BridgeAlloc(listInfo->size);
Type* curItem = reinterpret_cast<Type*>(listInfo->data);
for(const auto & item : listData)
{
*curItem = item;
++curItem;
}
}
else
listInfo->data = nullptr;
return true;
}
private:
ListInfo _listInfo;
};
#endif //__cplusplus
#endif //_LIST_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,157 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="bridgemain.cpp" />
<ClCompile Include="_global.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="bridgemain.h" />
<ClInclude Include="bridgelist.h" />
<ClInclude Include="Utf8Ini.h" />
<ClInclude Include="_global.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{944D9923-CB1A-6F6C-BCBC-9E00A71954C1}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x32\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>x32bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x32\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>x32bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
<TargetName>x64bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
<TargetName>x64bridge</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="bridgemain.cpp" />
<ClCompile Include="_global.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="bridgemain.h" />
<ClInclude Include="bridgelist.h" />
<ClInclude Include="Utf8Ini.h" />
<ClInclude Include="_global.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{944D9923-CB1A-6F6C-BCBC-9E00A71954C1}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x32\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>x32bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x32\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>x32bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
<TargetName>x64bridge</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
<TargetName>x64bridge</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,301 +1,301 @@
#include "capstone_wrapper.h"
#include <windows.h>
csh Capstone::mHandle = 0;
void Capstone::GlobalInitialize()
{
#ifdef _WIN64
cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
}
void Capstone::GlobalFinalize()
{
if(mHandle) //close handle
cs_close(&mHandle);
}
Capstone::Capstone()
{
mInstr = nullptr;
mSuccess = false;
}
Capstone::~Capstone()
{
if(mInstr) //free last disassembled instruction
cs_free(mInstr, 1);
}
bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
return Disassemble(addr, data, MAX_DISASM_BUFFER);
}
bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
if(!data)
return false;
if(mInstr) //free last disassembled instruction
{
cs_free(mInstr, 1);
mInstr = nullptr;
}
return mSuccess = !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
}
const cs_insn* Capstone::GetInstr() const
{
if(!Success())
return nullptr;
return mInstr;
}
bool Capstone::Success() const
{
return mSuccess;
}
const char* Capstone::RegName(x86_reg reg) const
{
return cs_reg_name(mHandle, reg);
}
bool Capstone::InGroup(cs_group_type group) const
{
if(!Success())
return false;
return cs_insn_group(mHandle, mInstr, group);
}
std::string Capstone::OperandText(int opindex) const
{
if(!Success() || opindex >= mInstr->detail->x86.op_count)
return "";
const auto & op = mInstr->detail->x86.operands[opindex];
std::string result;
char temp[32] = "";
switch(op.type)
{
case X86_OP_REG:
{
result = RegName(x86_reg(op.reg));
}
break;
case X86_OP_IMM:
{
sprintf_s(temp, "%llX", op.imm);
result = temp;
}
break;
case X86_OP_MEM:
{
const auto & mem = op.mem;
if(op.mem.base == X86_REG_RIP) //rip-relative
{
sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
result += temp;
}
else //normal
{
bool prependPlus = false;
if(mem.base)
{
result += RegName(x86_reg(mem.base));
prependPlus = true;
}
if(mem.index)
{
if(prependPlus)
result += "+";
result += RegName(x86_reg(mem.index));
sprintf_s(temp, "*%X", mem.scale);
result += temp;
prependPlus = true;
}
if(mem.disp)
{
char operatorText = '+';
if(mem.disp < 0)
{
operatorText = '-';
sprintf_s(temp, "%llX", mem.disp * -1);
}
else
sprintf_s(temp, "%llX", mem.disp);
if(prependPlus)
result += operatorText;
result += temp;
}
}
}
break;
case X86_OP_FP:
case X86_OP_INVALID:
{
}
break;
}
return result;
}
int Capstone::Size() const
{
if(!Success())
return 1;
return GetInstr()->size;
}
size_t Capstone::Address() const
{
if(!Success())
return 0;
return size_t(GetInstr()->address);
}
const cs_x86 & Capstone::x86() const
{
if(!Success())
DebugBreak();
return GetInstr()->detail->x86;
}
bool Capstone::IsFilling() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_NOP:
case X86_INS_INT3:
return true;
default:
return false;
}
}
bool Capstone::IsLoop() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_LOOP:
case X86_INS_LOOPE:
case X86_INS_LOOPNE:
return true;
default:
return false;
}
}
x86_insn Capstone::GetId() const
{
if(!Success())
DebugBreak();
return x86_insn(mInstr->id);
}
std::string Capstone::InstructionText() const
{
if(!Success())
return "???";
std::string result = Mnemonic();
if(OpCount())
{
result += " ";
result += mInstr->op_str;
}
return result;
}
int Capstone::OpCount() const
{
if(!Success())
return 0;
return x86().op_count;
}
cs_x86_op Capstone::operator[](int index) const
{
if(!Success() || index >= OpCount())
DebugBreak();
return x86().operands[index];
}
bool Capstone::IsNop() const
{
return GetId() == X86_INS_NOP;
}
bool Capstone::IsInt3() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_INT3:
return true;
case X86_INS_INT:
{
cs_x86_op op = x86().operands[0];
return op.type == X86_OP_IMM && op.imm == 3;
}
default:
return false;
}
}
std::string Capstone::Mnemonic() const
{
if(!Success())
return "???";
return mInstr->mnemonic;
}
const char* Capstone::MemSizeName(int size) const
{
switch(size)
{
case 1:
return "byte";
case 2:
return "word";
case 4:
return "dword";
case 6:
return "fword";
case 8:
return "qword";
case 10:
return "tword";
case 16:
return "dqword";
case 32:
return "yword";
case 64:
return "zword";
default:
return nullptr;
}
}
size_t Capstone::BranchDestination() const
{
if(!Success())
return 0;
if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
{
const auto & op = x86().operands[0];
if(op.type == CS_OP_IMM)
return size_t(op.imm);
}
return 0;
#include "capstone_wrapper.h"
#include <windows.h>
csh Capstone::mHandle = 0;
void Capstone::GlobalInitialize()
{
#ifdef _WIN64
cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
}
void Capstone::GlobalFinalize()
{
if(mHandle) //close handle
cs_close(&mHandle);
}
Capstone::Capstone()
{
mInstr = nullptr;
mSuccess = false;
}
Capstone::~Capstone()
{
if(mInstr) //free last disassembled instruction
cs_free(mInstr, 1);
}
bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
return Disassemble(addr, data, MAX_DISASM_BUFFER);
}
bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
if(!data)
return false;
if(mInstr) //free last disassembled instruction
{
cs_free(mInstr, 1);
mInstr = nullptr;
}
return mSuccess = !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
}
const cs_insn* Capstone::GetInstr() const
{
if(!Success())
return nullptr;
return mInstr;
}
bool Capstone::Success() const
{
return mSuccess;
}
const char* Capstone::RegName(x86_reg reg) const
{
return cs_reg_name(mHandle, reg);
}
bool Capstone::InGroup(cs_group_type group) const
{
if(!Success())
return false;
return cs_insn_group(mHandle, mInstr, group);
}
std::string Capstone::OperandText(int opindex) const
{
if(!Success() || opindex >= mInstr->detail->x86.op_count)
return "";
const auto & op = mInstr->detail->x86.operands[opindex];
std::string result;
char temp[32] = "";
switch(op.type)
{
case X86_OP_REG:
{
result = RegName(x86_reg(op.reg));
}
break;
case X86_OP_IMM:
{
sprintf_s(temp, "%llX", op.imm);
result = temp;
}
break;
case X86_OP_MEM:
{
const auto & mem = op.mem;
if(op.mem.base == X86_REG_RIP) //rip-relative
{
sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
result += temp;
}
else //normal
{
bool prependPlus = false;
if(mem.base)
{
result += RegName(x86_reg(mem.base));
prependPlus = true;
}
if(mem.index)
{
if(prependPlus)
result += "+";
result += RegName(x86_reg(mem.index));
sprintf_s(temp, "*%X", mem.scale);
result += temp;
prependPlus = true;
}
if(mem.disp)
{
char operatorText = '+';
if(mem.disp < 0)
{
operatorText = '-';
sprintf_s(temp, "%llX", mem.disp * -1);
}
else
sprintf_s(temp, "%llX", mem.disp);
if(prependPlus)
result += operatorText;
result += temp;
}
}
}
break;
case X86_OP_FP:
case X86_OP_INVALID:
{
}
break;
}
return result;
}
int Capstone::Size() const
{
if(!Success())
return 1;
return GetInstr()->size;
}
size_t Capstone::Address() const
{
if(!Success())
return 0;
return size_t(GetInstr()->address);
}
const cs_x86 & Capstone::x86() const
{
if(!Success())
DebugBreak();
return GetInstr()->detail->x86;
}
bool Capstone::IsFilling() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_NOP:
case X86_INS_INT3:
return true;
default:
return false;
}
}
bool Capstone::IsLoop() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_LOOP:
case X86_INS_LOOPE:
case X86_INS_LOOPNE:
return true;
default:
return false;
}
}
x86_insn Capstone::GetId() const
{
if(!Success())
DebugBreak();
return x86_insn(mInstr->id);
}
std::string Capstone::InstructionText() const
{
if(!Success())
return "???";
std::string result = Mnemonic();
if(OpCount())
{
result += " ";
result += mInstr->op_str;
}
return result;
}
int Capstone::OpCount() const
{
if(!Success())
return 0;
return x86().op_count;
}
cs_x86_op Capstone::operator[](int index) const
{
if(!Success() || index >= OpCount())
DebugBreak();
return x86().operands[index];
}
bool Capstone::IsNop() const
{
return GetId() == X86_INS_NOP;
}
bool Capstone::IsInt3() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_INT3:
return true;
case X86_INS_INT:
{
cs_x86_op op = x86().operands[0];
return op.type == X86_OP_IMM && op.imm == 3;
}
default:
return false;
}
}
std::string Capstone::Mnemonic() const
{
if(!Success())
return "???";
return mInstr->mnemonic;
}
const char* Capstone::MemSizeName(int size) const
{
switch(size)
{
case 1:
return "byte";
case 2:
return "word";
case 4:
return "dword";
case 6:
return "fword";
case 8:
return "qword";
case 10:
return "tword";
case 16:
return "dqword";
case 32:
return "yword";
case 64:
return "zword";
default:
return nullptr;
}
}
size_t Capstone::BranchDestination() const
{
if(!Success())
return 0;
if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
{
const auto & op = x86().operands[0];
if(op.type == CS_OP_IMM)
return size_t(op.imm);
}
return 0;
}

View File

@ -1,44 +1,44 @@
#ifndef _CAPSTONE_WRAPPER_H
#define _CAPSTONE_WRAPPER_H
#include "../dbg/capstone/capstone.h"
#include <string>
#define MAX_DISASM_BUFFER 16
class Capstone
{
public:
static void GlobalInitialize();
static void GlobalFinalize();
Capstone();
~Capstone();
bool Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER]);
bool Disassemble(size_t addr, const unsigned char* data, int size);
const cs_insn* GetInstr() const;
bool Success() const;
const char* RegName(x86_reg reg) const;
bool InGroup(cs_group_type group) const;
std::string OperandText(int opindex) const;
int Size() const;
size_t Address() const;
const cs_x86 & x86() const;
bool IsFilling() const;
bool IsLoop() const;
x86_insn GetId() const;
std::string InstructionText() const;
int OpCount() const;
cs_x86_op operator[](int index) const;
bool IsNop() const;
bool IsInt3() const;
std::string Mnemonic() const;
const char* MemSizeName(int size) const;
size_t BranchDestination() const;
private:
static csh mHandle;
cs_insn* mInstr;
bool mSuccess;
};
#ifndef _CAPSTONE_WRAPPER_H
#define _CAPSTONE_WRAPPER_H
#include "../dbg/capstone/capstone.h"
#include <string>
#define MAX_DISASM_BUFFER 16
class Capstone
{
public:
static void GlobalInitialize();
static void GlobalFinalize();
Capstone();
~Capstone();
bool Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER]);
bool Disassemble(size_t addr, const unsigned char* data, int size);
const cs_insn* GetInstr() const;
bool Success() const;
const char* RegName(x86_reg reg) const;
bool InGroup(cs_group_type group) const;
std::string OperandText(int opindex) const;
int Size() const;
size_t Address() const;
const cs_x86 & x86() const;
bool IsFilling() const;
bool IsLoop() const;
x86_insn GetId() const;
std::string InstructionText() const;
int OpCount() const;
cs_x86_op operator[](int index) const;
bool IsNop() const;
bool IsInt3() const;
std::string Mnemonic() const;
const char* MemSizeName(int size) const;
size_t BranchDestination() const;
private:
static csh mHandle;
cs_insn* mInstr;
bool mSuccess;
};
#endif //_CAPSTONE_WRAPPER_H

View File

@ -1,95 +1,95 @@
#include <assert.h>
#include <thread>
#include "AnalysisPass.h"
#include "memory.h"
AnalysisPass::AnalysisPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks) : m_MainBlocks(MainBlocks)
{
assert(VirtualEnd > VirtualStart);
// Internal class data
m_VirtualStart = VirtualStart;
m_VirtualEnd = VirtualEnd;
m_InternalMaxThreads = 0;
// Read remote instruction data to local memory
m_DataSize = VirtualEnd - VirtualStart;
m_Data = (unsigned char*)emalloc(m_DataSize, "AnalysisPass:m_Data");
if(!MemRead(VirtualStart, m_Data, m_DataSize))
{
BridgeFree(m_Data);
assert(false);
}
}
AnalysisPass::~AnalysisPass()
{
if(m_Data)
efree(m_Data);
}
BasicBlock* AnalysisPass::FindBBlockInRange(duint Address)
{
// NOTE: __MUST__ BE A SORTED VECTOR
//
// Use a binary search
duint indexLo = 0;
duint indexHi = m_MainBlocks.size();
// Get a pointer to pure data
const auto blocks = m_MainBlocks.data();
while(indexHi > indexLo)
{
duint indexMid = (indexLo + indexHi) / 2;
auto entry = &blocks[indexMid];
if(Address < entry->VirtualStart)
{
// Continue search in lower half
indexHi = indexMid;
}
else if(Address >= entry->VirtualEnd)
{
// Continue search in upper half
indexLo = indexMid + 1;
}
else
{
// Address is within limits, return entry
return entry;
}
}
// Not found
return nullptr;
}
duint AnalysisPass::FindBBlockIndex(BasicBlock* Block)
{
// Fast pointer arithmetic to find index
return ((duint)Block - (duint)m_MainBlocks.data()) / sizeof(BasicBlock);
}
duint AnalysisPass::IdealThreadCount()
{
if(m_InternalMaxThreads == 0)
{
// Determine the maximum hardware thread count at once
duint maximumThreads = max(std::thread::hardware_concurrency(), 1);
// Don't consume 100% of the CPU, adjust accordingly
if(maximumThreads > 1)
maximumThreads -= 1;
SetIdealThreadCount(maximumThreads);
}
return m_InternalMaxThreads;
}
void AnalysisPass::SetIdealThreadCount(duint Count)
{
m_InternalMaxThreads = (BYTE)min(Count, 255);
#include <assert.h>
#include <thread>
#include "AnalysisPass.h"
#include "memory.h"
AnalysisPass::AnalysisPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks) : m_MainBlocks(MainBlocks)
{
assert(VirtualEnd > VirtualStart);
// Internal class data
m_VirtualStart = VirtualStart;
m_VirtualEnd = VirtualEnd;
m_InternalMaxThreads = 0;
// Read remote instruction data to local memory
m_DataSize = VirtualEnd - VirtualStart;
m_Data = (unsigned char*)emalloc(m_DataSize, "AnalysisPass:m_Data");
if(!MemRead(VirtualStart, m_Data, m_DataSize))
{
BridgeFree(m_Data);
assert(false);
}
}
AnalysisPass::~AnalysisPass()
{
if(m_Data)
efree(m_Data);
}
BasicBlock* AnalysisPass::FindBBlockInRange(duint Address)
{
// NOTE: __MUST__ BE A SORTED VECTOR
//
// Use a binary search
duint indexLo = 0;
duint indexHi = m_MainBlocks.size();
// Get a pointer to pure data
const auto blocks = m_MainBlocks.data();
while(indexHi > indexLo)
{
duint indexMid = (indexLo + indexHi) / 2;
auto entry = &blocks[indexMid];
if(Address < entry->VirtualStart)
{
// Continue search in lower half
indexHi = indexMid;
}
else if(Address >= entry->VirtualEnd)
{
// Continue search in upper half
indexLo = indexMid + 1;
}
else
{
// Address is within limits, return entry
return entry;
}
}
// Not found
return nullptr;
}
duint AnalysisPass::FindBBlockIndex(BasicBlock* Block)
{
// Fast pointer arithmetic to find index
return ((duint)Block - (duint)m_MainBlocks.data()) / sizeof(BasicBlock);
}
duint AnalysisPass::IdealThreadCount()
{
if(m_InternalMaxThreads == 0)
{
// Determine the maximum hardware thread count at once
duint maximumThreads = max(std::thread::hardware_concurrency(), 1);
// Don't consume 100% of the CPU, adjust accordingly
if(maximumThreads > 1)
maximumThreads -= 1;
SetIdealThreadCount(maximumThreads);
}
return m_InternalMaxThreads;
}
void AnalysisPass::SetIdealThreadCount(duint Count)
{
m_InternalMaxThreads = (BYTE)min(Count, 255);
}

View File

@ -1,41 +1,41 @@
#pragma once
#include "_global.h"
#include "BasicBlock.h"
class AnalysisPass
{
public:
AnalysisPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~AnalysisPass();
virtual const char* GetName() = 0;
virtual bool Analyse() = 0;
protected:
duint m_VirtualStart;
duint m_VirtualEnd;
duint m_DataSize;
unsigned char* m_Data;
BBlockArray & m_MainBlocks;
inline unsigned char* AnalysisPass::TranslateAddress(duint Address)
{
assert(ValidateAddress(Address));
return &m_Data[Address - m_VirtualStart];
}
inline bool AnalysisPass::ValidateAddress(duint Address)
{
return (Address >= m_VirtualStart && Address < m_VirtualEnd);
}
BasicBlock* FindBBlockInRange(duint Address);
duint FindBBlockIndex(BasicBlock* Block);
duint IdealThreadCount();
void SetIdealThreadCount(duint Count);
private:
BYTE m_InternalMaxThreads;
#pragma once
#include "_global.h"
#include "BasicBlock.h"
class AnalysisPass
{
public:
AnalysisPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~AnalysisPass();
virtual const char* GetName() = 0;
virtual bool Analyse() = 0;
protected:
duint m_VirtualStart;
duint m_VirtualEnd;
duint m_DataSize;
unsigned char* m_Data;
BBlockArray & m_MainBlocks;
inline unsigned char* AnalysisPass::TranslateAddress(duint Address)
{
assert(ValidateAddress(Address));
return &m_Data[Address - m_VirtualStart];
}
inline bool AnalysisPass::ValidateAddress(duint Address)
{
return (Address >= m_VirtualStart && Address < m_VirtualEnd);
}
BasicBlock* FindBBlockInRange(duint Address);
duint FindBBlockIndex(BasicBlock* Block);
duint IdealThreadCount();
void SetIdealThreadCount(duint Count);
private:
BYTE m_InternalMaxThreads;
};

View File

@ -1,80 +1,80 @@
#pragma once
#include "_global.h"
enum BasicBlockFlags : duint
{
BASIC_BLOCK_FLAG_NONE = 0, // No flag
BASIC_BLOCK_FLAG_FUNCTION = (1 << 1), // Scanned; also part of a known function
BASIC_BLOCK_FLAG_ORPHANED = (1 << 2), // No targets ever reach this block
BASIC_BLOCK_FLAG_CUTOFF = (1 << 3), // Ends prematurely because of another JMP to location
BASIC_BLOCK_FLAG_DELETE = (1 << 4), // Delete element at the next possible time
BASIC_BLOCK_FLAG_CALL = (1 << 5), // The block ends with a call
BASIC_BLOCK_FLAG_RET = (1 << 6), // The block ends with a retn
BASIC_BLOCK_FLAG_ABSJMP = (1 << 7), // Branch is absolute
BASIC_BLOCK_FLAG_INDIRECT = (1 << 8), // This block ends with an indirect branch
BASIC_BLOCK_FLAG_INDIRPTR = (1 << 9), // This block ends with an indirect branch; pointer known
BASIC_BLOCK_FLAG_PREPAD = (1 << 10), // Block ends because there was padding afterwards
BASIC_BLOCK_FLAG_PAD = (1 << 11), // Block is only a series of padding instructions
};
struct BasicBlock
{
duint VirtualStart; // Inclusive
duint VirtualEnd; // Exclusive
duint Flags;
duint Target;
__forceinline bool GetFlag(duint Flag)
{
return (Flags & Flag) == Flag;
}
__forceinline void SetFlag(duint Flag)
{
Flags |= Flag;
}
__forceinline duint Size()
{
return VirtualEnd - VirtualStart;
}
bool operator< (const BasicBlock & b) const
{
return VirtualStart < b.VirtualStart;
}
bool operator== (const BasicBlock & b) const
{
return VirtualStart == b.VirtualStart;
}
};
struct FunctionDef
{
duint VirtualStart; // Inclusive
duint VirtualEnd; // Exclusive
duint BBlockStart; // Index of first basic block
duint BBlockEnd; // Index of last basic block
bool operator< (const FunctionDef & b) const
{
if(VirtualStart == b.VirtualStart)
return VirtualEnd > b.VirtualEnd;
return VirtualStart < b.VirtualStart;
}
bool operator== (const FunctionDef & b) const
{
return VirtualStart == b.VirtualStart;
}
};
typedef std::vector<BasicBlock> BBlockArray;
#pragma once
#include "_global.h"
enum BasicBlockFlags : duint
{
BASIC_BLOCK_FLAG_NONE = 0, // No flag
BASIC_BLOCK_FLAG_FUNCTION = (1 << 1), // Scanned; also part of a known function
BASIC_BLOCK_FLAG_ORPHANED = (1 << 2), // No targets ever reach this block
BASIC_BLOCK_FLAG_CUTOFF = (1 << 3), // Ends prematurely because of another JMP to location
BASIC_BLOCK_FLAG_DELETE = (1 << 4), // Delete element at the next possible time
BASIC_BLOCK_FLAG_CALL = (1 << 5), // The block ends with a call
BASIC_BLOCK_FLAG_RET = (1 << 6), // The block ends with a retn
BASIC_BLOCK_FLAG_ABSJMP = (1 << 7), // Branch is absolute
BASIC_BLOCK_FLAG_INDIRECT = (1 << 8), // This block ends with an indirect branch
BASIC_BLOCK_FLAG_INDIRPTR = (1 << 9), // This block ends with an indirect branch; pointer known
BASIC_BLOCK_FLAG_PREPAD = (1 << 10), // Block ends because there was padding afterwards
BASIC_BLOCK_FLAG_PAD = (1 << 11), // Block is only a series of padding instructions
};
struct BasicBlock
{
duint VirtualStart; // Inclusive
duint VirtualEnd; // Exclusive
duint Flags;
duint Target;
__forceinline bool GetFlag(duint Flag)
{
return (Flags & Flag) == Flag;
}
__forceinline void SetFlag(duint Flag)
{
Flags |= Flag;
}
__forceinline duint Size()
{
return VirtualEnd - VirtualStart;
}
bool operator< (const BasicBlock & b) const
{
return VirtualStart < b.VirtualStart;
}
bool operator== (const BasicBlock & b) const
{
return VirtualStart == b.VirtualStart;
}
};
struct FunctionDef
{
duint VirtualStart; // Inclusive
duint VirtualEnd; // Exclusive
duint BBlockStart; // Index of first basic block
duint BBlockEnd; // Index of last basic block
bool operator< (const FunctionDef & b) const
{
if(VirtualStart == b.VirtualStart)
return VirtualEnd > b.VirtualEnd;
return VirtualStart < b.VirtualStart;
}
bool operator== (const FunctionDef & b) const
{
return VirtualStart == b.VirtualStart;
}
};
typedef std::vector<BasicBlock> BBlockArray;
typedef std::vector<FunctionDef> FuncDefArray;

View File

@ -1,92 +1,92 @@
#include "AnalysisPass.h"
#include "CodeFollowPass.h"
CodeFollowPass::CodeFollowPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
}
CodeFollowPass::~CodeFollowPass()
{
}
const char* CodeFollowPass::GetName()
{
return "Code Follower";
}
bool CodeFollowPass::Analyse()
{
// First gather all possible function references with certain tables
//
// This includes:
// Main entry
// Module exports
// Module import references (?)
// Control flow guard
// RUNTIME_FUNCTION
// TLS callbacks
// FLS callbacks
return false;
}
duint CodeFollowPass::GetReferenceOperand(const cs_x86 & Context)
{
for(int i = 0; i < Context.op_count; i++)
{
auto operand = Context.operands[i];
// Looking for immediate references
if(operand.type == X86_OP_IMM)
{
duint dest = (duint)operand.imm;
if(ValidateAddress(dest))
return dest;
}
}
return 0;
}
duint CodeFollowPass::GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect)
{
if(Context.op_count <= 0)
return 0;
// Only the first operand matters
auto operand = Context.operands[0];
// Jumps and calls only
if(Disasm.InGroup(CS_GRP_CALL) || Disasm.InGroup(CS_GRP_JUMP))
{
// Looking for memory references
if(operand.type == X86_OP_MEM)
{
// Notify if the operand was indirect
if(Indirect)
{
if(operand.mem.base != X86_REG_INVALID ||
operand.mem.index != X86_REG_INVALID ||
operand.mem.scale != 0)
{
*Indirect = true;
return 0;
}
}
// TODO: Read pointer
// TODO: Find virtual tables (new pass?)
// TODO: Translate RIP-Relative
return 0;
duint dest = (duint)operand.mem.disp;
if(ValidateAddress(dest))
return dest;
}
}
return 0;
#include "AnalysisPass.h"
#include "CodeFollowPass.h"
CodeFollowPass::CodeFollowPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
}
CodeFollowPass::~CodeFollowPass()
{
}
const char* CodeFollowPass::GetName()
{
return "Code Follower";
}
bool CodeFollowPass::Analyse()
{
// First gather all possible function references with certain tables
//
// This includes:
// Main entry
// Module exports
// Module import references (?)
// Control flow guard
// RUNTIME_FUNCTION
// TLS callbacks
// FLS callbacks
return false;
}
duint CodeFollowPass::GetReferenceOperand(const cs_x86 & Context)
{
for(int i = 0; i < Context.op_count; i++)
{
auto operand = Context.operands[i];
// Looking for immediate references
if(operand.type == X86_OP_IMM)
{
duint dest = (duint)operand.imm;
if(ValidateAddress(dest))
return dest;
}
}
return 0;
}
duint CodeFollowPass::GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect)
{
if(Context.op_count <= 0)
return 0;
// Only the first operand matters
auto operand = Context.operands[0];
// Jumps and calls only
if(Disasm.InGroup(CS_GRP_CALL) || Disasm.InGroup(CS_GRP_JUMP))
{
// Looking for memory references
if(operand.type == X86_OP_MEM)
{
// Notify if the operand was indirect
if(Indirect)
{
if(operand.mem.base != X86_REG_INVALID ||
operand.mem.index != X86_REG_INVALID ||
operand.mem.scale != 0)
{
*Indirect = true;
return 0;
}
}
// TODO: Read pointer
// TODO: Find virtual tables (new pass?)
// TODO: Translate RIP-Relative
return 0;
duint dest = (duint)operand.mem.disp;
if(ValidateAddress(dest))
return dest;
}
}
return 0;
}

View File

@ -1,19 +1,19 @@
#pragma once
#include "AnalysisPass.h"
#include "BasicBlock.h"
#include <capstone_wrapper.h>
class CodeFollowPass : public AnalysisPass
{
public:
CodeFollowPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~CodeFollowPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
private:
duint GetReferenceOperand(const cs_x86 & Context);
duint GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect);
#pragma once
#include "AnalysisPass.h"
#include "BasicBlock.h"
#include <capstone_wrapper.h>
class CodeFollowPass : public AnalysisPass
{
public:
CodeFollowPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~CodeFollowPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
private:
duint GetReferenceOperand(const cs_x86 & Context);
duint GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect);
};

View File

@ -1,22 +1,22 @@
#ifndef _DEVICENAMERESOLVER_H
#define _DEVICENAMERESOLVER_H
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) bool DevicePathToPathW(const wchar_t* szDevicePath, wchar_t* szPath, size_t nSize);
__declspec(dllexport) bool DevicePathToPathA(const char* szDevicePath, char* szPath, size_t nSize);
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t* szDevicePath, size_t nSize);
__declspec(dllexport) bool DevicePathFromFileHandleA(HANDLE hFile, char* szDevicePath, size_t nSize);
__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath, size_t nSize);
__declspec(dllexport) bool PathFromFileHandleA(HANDLE hFile, char* szPath, size_t nSize);
#ifdef __cplusplus
}
#endif
#endif // _DEVICENAMERESOLVER_H
#ifndef _DEVICENAMERESOLVER_H
#define _DEVICENAMERESOLVER_H
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) bool DevicePathToPathW(const wchar_t* szDevicePath, wchar_t* szPath, size_t nSize);
__declspec(dllexport) bool DevicePathToPathA(const char* szDevicePath, char* szPath, size_t nSize);
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t* szDevicePath, size_t nSize);
__declspec(dllexport) bool DevicePathFromFileHandleA(HANDLE hFile, char* szDevicePath, size_t nSize);
__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath, size_t nSize);
__declspec(dllexport) bool PathFromFileHandleA(HANDLE hFile, char* szPath, size_t nSize);
#ifdef __cplusplus
}
#endif
#endif // _DEVICENAMERESOLVER_H

View File

@ -1,359 +1,359 @@
#include "FunctionPass.h"
#include <ppl.h>
#include "memory.h"
#include "console.h"
#include "debugger.h"
#include "module.h"
#include "function.h"
FunctionPass::FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
// Zero values
m_FunctionInfo = nullptr;
m_FunctionInfoSize = 0;
// This will only be valid if the address range is within a loaded module
m_ModuleStart = ModBaseFromAddr(VirtualStart);
if(m_ModuleStart != 0)
{
char modulePath[MAX_PATH];
memset(modulePath, 0, sizeof(modulePath));
ModPathFromAddr(m_ModuleStart, modulePath, ARRAYSIZE(modulePath));
HANDLE fileHandle;
DWORD fileSize;
HANDLE fileMapHandle;
ULONG_PTR fileMapVa;
if(StaticFileLoadW(
StringUtils::Utf8ToUtf16(modulePath).c_str(),
UE_ACCESS_READ,
false,
&fileHandle,
&fileSize,
&fileMapHandle,
&fileMapVa))
{
// Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use
ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET);
m_FunctionInfoSize = (ULONG)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE);
// Unload the file
StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa);
// Get a copy of the function table
if(virtualOffset)
{
// Read the table into a buffer
m_FunctionInfo = BridgeAlloc(m_FunctionInfoSize);
if(m_FunctionInfo)
MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize);
}
}
}
}
FunctionPass::~FunctionPass()
{
if(m_FunctionInfo)
BridgeFree(m_FunctionInfo);
}
const char* FunctionPass::GetName()
{
return "Function Analysis";
}
bool FunctionPass::Analyse()
{
// THREAD_WORK = ceil(TOTAL / # THREADS)
duint workAmount = (m_MainBlocks.size() + (IdealThreadCount() - 1)) / IdealThreadCount();
// Initialize thread vector
auto threadFunctions = new std::vector<FunctionDef>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), m_MainBlocks.size());
// Memory allocation optimization
// TODO: Option to conserve memory
threadFunctions[i].reserve(30000);
// Execute
AnalysisWorker(threadWorkStart, threadWorkStop, &threadFunctions[i]);
});
std::vector<FunctionDef> funcs;
// Merge thread vectors into single local
for(duint i = 0; i < IdealThreadCount(); i++)
std::move(threadFunctions[i].begin(), threadFunctions[i].end(), std::back_inserter(funcs));
// Sort and remove duplicates
std::sort(funcs.begin(), funcs.end());
funcs.erase(std::unique(funcs.begin(), funcs.end()), funcs.end());
dprintf("%u functions\n", funcs.size());
FunctionClear();
for(auto & func : funcs)
{
FunctionAdd(func.VirtualStart, func.VirtualEnd - 1, true);
}
GuiUpdateAllViews();
delete[] threadFunctions;
return true;
}
void FunctionPass::AnalysisWorker(duint Start, duint End, std::vector<FunctionDef>* Blocks)
{
// Step 1: Use any defined functions in the PE function table
FindFunctionWorkerPrepass(Start, End, Blocks);
// Step 2: for each block that contains a CALL flag,
// add it to a local function start array
//
// NOTE: *Some* indirect calls are included
auto blockItr = std::next(m_MainBlocks.begin(), Start);
for(duint i = Start; i < End; i++, ++blockItr)
{
if(blockItr->GetFlag(BASIC_BLOCK_FLAG_CALL))
{
duint destination = blockItr->Target;
// Was it a pointer?
if(blockItr->GetFlag(BASIC_BLOCK_FLAG_INDIRPTR))
{
// Read it from memory
if(!MemRead(destination, &destination, sizeof(duint)))
continue;
// Validity check
if(!MemIsValidReadPtr(destination))
continue;
dprintf("Indirect pointer: 0x%p 0x%p\n", blockItr->Target, destination);
}
// Destination must be within analysis limits
if(!ValidateAddress(destination))
continue;
FunctionDef def;
def.VirtualStart = destination;
def.VirtualEnd = 0;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
}
// Step 3: Sort and remove duplicates
std::sort(Blocks->begin(), Blocks->end());
Blocks->erase(std::unique(Blocks->begin(), Blocks->end()), Blocks->end());
// Step 4: Find the end of functions
FindFunctionWorker(Blocks);
dprintf("Total detected functions: %d\n", Blocks->size());
// Step 5: Find all orphaned blocks and repeat analysis process
// TODO
}
void FunctionPass::FindFunctionWorkerPrepass(duint Start, duint End, std::vector<FunctionDef>* Blocks)
{
const duint minFunc = std::next(m_MainBlocks.begin(), Start)->VirtualStart;
const duint maxFunc = std::next(m_MainBlocks.begin(), End - 1)->VirtualEnd;
#ifdef _WIN64
// RUNTIME_FUNCTION exception information
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
{
const duint funcAddr = m_ModuleStart + Function->BeginAddress;
const duint funcEnd = m_ModuleStart + Function->EndAddress;
// If within limits...
if(funcAddr >= minFunc && funcAddr < maxFunc)
{
// Add the descriptor
FunctionDef def;
def.VirtualStart = funcAddr;
def.VirtualEnd = funcEnd;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
return true;
});
#endif // _WIN64
// Module exports (return value ignored)
apienumexports(m_ModuleStart, [&](duint Base, const char* Module, const char* Name, duint Address)
{
// If within limits...
if(Address >= minFunc && Address < maxFunc)
{
// Add the descriptor
FunctionDef def;
def.VirtualStart = Address;
def.VirtualEnd = 0;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
});
}
void FunctionPass::FindFunctionWorker(std::vector<FunctionDef>* Blocks)
{
// Cached final block
BasicBlock* finalBlock = &m_MainBlocks.back();
// Enumerate all function entries for this thread
for(auto & block : *Blocks)
{
// Sometimes the ending address is already supplied, so
// check first
if(block.VirtualEnd != 0)
{
if(ResolveKnownFunctionEnd(&block))
continue;
}
// Now the function end must be determined by heuristics (find manually)
ResolveFunctionEnd(&block, finalBlock);
}
}
bool FunctionPass::ResolveKnownFunctionEnd(FunctionDef* Function)
{
// Helper to link final blocks to function
auto startBlock = FindBBlockInRange(Function->VirtualStart);
auto endBlock = FindBBlockInRange(Function->VirtualEnd);
if(!startBlock || !endBlock)
return false;
// Find block start/end indices
Function->BBlockStart = FindBBlockIndex(startBlock);
Function->BBlockEnd = FindBBlockIndex(endBlock);
// Set the flag for blocks that have been scanned
for(BasicBlock* block = startBlock; (duint)block <= (duint)endBlock; block++)
block->SetFlag(BASIC_BLOCK_FLAG_FUNCTION);
return true;
}
bool FunctionPass::ResolveFunctionEnd(FunctionDef* Function, BasicBlock* LastBlock)
{
ASSERT_TRUE(Function->VirtualStart != 0);
// Find the first basic block of the function
BasicBlock* block = FindBBlockInRange(Function->VirtualStart);
if(!block)
{
ASSERT_ALWAYS("Block should exist at this point");
return false;
}
// The maximum address is determined by any jump that extends past
// a RET or other terminating basic block. A function may have multiple
// return statements.
duint maximumAddr = 0;
// Loop forever until the end is found
for(; (duint)block <= (duint)LastBlock; block++)
{
// Block is now in use
block->SetFlag(BASIC_BLOCK_FLAG_FUNCTION);
// Calculate max from just linear instructions
maximumAddr = max(maximumAddr, block->VirtualEnd - 1);
// Find maximum jump target
if(!block->GetFlag(BASIC_BLOCK_FLAG_CALL) && !block->GetFlag(BASIC_BLOCK_FLAG_INDIRECT))
{
if(block->Target != 0)
{
// Here's a problem: Compilers add tail-call elimination with a jump.
// Solve this by creating a maximum jump limit: +/- 512 bytes from the end.
//
// abs(block->VirtualEnd - block->Target) -- unsigned
if(min(block->VirtualEnd - block->Target, block->Target - block->VirtualEnd) <= 512)
maximumAddr = max(maximumAddr, block->Target);
}
}
// Sanity check
ASSERT_TRUE(maximumAddr >= block->VirtualStart);
// Does this node contain the maximum address?
if(maximumAddr >= block->VirtualStart && maximumAddr < block->VirtualEnd)
{
// It does! There's 4 possibilities next:
//
// 1. Return
// 2. Tail-call elimination
// 3. Optimized loop
// 4. Function continues to next block
//
// 1.
if(block->GetFlag(BASIC_BLOCK_FLAG_RET))
break;
if(block->Target != 0)
{
// NOTE: Both must be an absolute jump
if(block->GetFlag(BASIC_BLOCK_FLAG_ABSJMP))
{
// 2.
//
// abs(block->VirtualEnd - block->Target) -- unsigned
if(min(block->VirtualEnd - block->Target, block->Target - block->VirtualEnd) > 128)
break;
// 3.
if(block->Target >= Function->VirtualStart && block->Target < block->VirtualEnd)
break;
}
}
// 4. Continue
}
}
// Loop is done. Set the information in the function structure.
Function->VirtualEnd = block->VirtualEnd;
Function->BBlockEnd = FindBBlockIndex(block);
return true;
}
#ifdef _WIN64
void FunctionPass::EnumerateFunctionRuntimeEntries64(std::function<bool (PRUNTIME_FUNCTION)> Callback)
{
if(!m_FunctionInfo)
return;
// Get the table pointer and size
auto functionTable = (PRUNTIME_FUNCTION)m_FunctionInfo;
ULONG totalCount = (m_FunctionInfoSize / sizeof(RUNTIME_FUNCTION));
// Enumerate each entry
for(ULONG i = 0; i < totalCount; i++)
{
if(!Callback(&functionTable[i]))
break;
}
}
#include "FunctionPass.h"
#include <ppl.h>
#include "memory.h"
#include "console.h"
#include "debugger.h"
#include "module.h"
#include "function.h"
FunctionPass::FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
// Zero values
m_FunctionInfo = nullptr;
m_FunctionInfoSize = 0;
// This will only be valid if the address range is within a loaded module
m_ModuleStart = ModBaseFromAddr(VirtualStart);
if(m_ModuleStart != 0)
{
char modulePath[MAX_PATH];
memset(modulePath, 0, sizeof(modulePath));
ModPathFromAddr(m_ModuleStart, modulePath, ARRAYSIZE(modulePath));
HANDLE fileHandle;
DWORD fileSize;
HANDLE fileMapHandle;
ULONG_PTR fileMapVa;
if(StaticFileLoadW(
StringUtils::Utf8ToUtf16(modulePath).c_str(),
UE_ACCESS_READ,
false,
&fileHandle,
&fileSize,
&fileMapHandle,
&fileMapVa))
{
// Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use
ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET);
m_FunctionInfoSize = (ULONG)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE);
// Unload the file
StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa);
// Get a copy of the function table
if(virtualOffset)
{
// Read the table into a buffer
m_FunctionInfo = BridgeAlloc(m_FunctionInfoSize);
if(m_FunctionInfo)
MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize);
}
}
}
}
FunctionPass::~FunctionPass()
{
if(m_FunctionInfo)
BridgeFree(m_FunctionInfo);
}
const char* FunctionPass::GetName()
{
return "Function Analysis";
}
bool FunctionPass::Analyse()
{
// THREAD_WORK = ceil(TOTAL / # THREADS)
duint workAmount = (m_MainBlocks.size() + (IdealThreadCount() - 1)) / IdealThreadCount();
// Initialize thread vector
auto threadFunctions = new std::vector<FunctionDef>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), m_MainBlocks.size());
// Memory allocation optimization
// TODO: Option to conserve memory
threadFunctions[i].reserve(30000);
// Execute
AnalysisWorker(threadWorkStart, threadWorkStop, &threadFunctions[i]);
});
std::vector<FunctionDef> funcs;
// Merge thread vectors into single local
for(duint i = 0; i < IdealThreadCount(); i++)
std::move(threadFunctions[i].begin(), threadFunctions[i].end(), std::back_inserter(funcs));
// Sort and remove duplicates
std::sort(funcs.begin(), funcs.end());
funcs.erase(std::unique(funcs.begin(), funcs.end()), funcs.end());
dprintf("%u functions\n", funcs.size());
FunctionClear();
for(auto & func : funcs)
{
FunctionAdd(func.VirtualStart, func.VirtualEnd - 1, true);
}
GuiUpdateAllViews();
delete[] threadFunctions;
return true;
}
void FunctionPass::AnalysisWorker(duint Start, duint End, std::vector<FunctionDef>* Blocks)
{
// Step 1: Use any defined functions in the PE function table
FindFunctionWorkerPrepass(Start, End, Blocks);
// Step 2: for each block that contains a CALL flag,
// add it to a local function start array
//
// NOTE: *Some* indirect calls are included
auto blockItr = std::next(m_MainBlocks.begin(), Start);
for(duint i = Start; i < End; i++, ++blockItr)
{
if(blockItr->GetFlag(BASIC_BLOCK_FLAG_CALL))
{
duint destination = blockItr->Target;
// Was it a pointer?
if(blockItr->GetFlag(BASIC_BLOCK_FLAG_INDIRPTR))
{
// Read it from memory
if(!MemRead(destination, &destination, sizeof(duint)))
continue;
// Validity check
if(!MemIsValidReadPtr(destination))
continue;
dprintf("Indirect pointer: 0x%p 0x%p\n", blockItr->Target, destination);
}
// Destination must be within analysis limits
if(!ValidateAddress(destination))
continue;
FunctionDef def;
def.VirtualStart = destination;
def.VirtualEnd = 0;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
}
// Step 3: Sort and remove duplicates
std::sort(Blocks->begin(), Blocks->end());
Blocks->erase(std::unique(Blocks->begin(), Blocks->end()), Blocks->end());
// Step 4: Find the end of functions
FindFunctionWorker(Blocks);
dprintf("Total detected functions: %d\n", Blocks->size());
// Step 5: Find all orphaned blocks and repeat analysis process
// TODO
}
void FunctionPass::FindFunctionWorkerPrepass(duint Start, duint End, std::vector<FunctionDef>* Blocks)
{
const duint minFunc = std::next(m_MainBlocks.begin(), Start)->VirtualStart;
const duint maxFunc = std::next(m_MainBlocks.begin(), End - 1)->VirtualEnd;
#ifdef _WIN64
// RUNTIME_FUNCTION exception information
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
{
const duint funcAddr = m_ModuleStart + Function->BeginAddress;
const duint funcEnd = m_ModuleStart + Function->EndAddress;
// If within limits...
if(funcAddr >= minFunc && funcAddr < maxFunc)
{
// Add the descriptor
FunctionDef def;
def.VirtualStart = funcAddr;
def.VirtualEnd = funcEnd;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
return true;
});
#endif // _WIN64
// Module exports (return value ignored)
apienumexports(m_ModuleStart, [&](duint Base, const char* Module, const char* Name, duint Address)
{
// If within limits...
if(Address >= minFunc && Address < maxFunc)
{
// Add the descriptor
FunctionDef def;
def.VirtualStart = Address;
def.VirtualEnd = 0;
def.BBlockStart = 0;
def.BBlockEnd = 0;
Blocks->push_back(def);
}
});
}
void FunctionPass::FindFunctionWorker(std::vector<FunctionDef>* Blocks)
{
// Cached final block
BasicBlock* finalBlock = &m_MainBlocks.back();
// Enumerate all function entries for this thread
for(auto & block : *Blocks)
{
// Sometimes the ending address is already supplied, so
// check first
if(block.VirtualEnd != 0)
{
if(ResolveKnownFunctionEnd(&block))
continue;
}
// Now the function end must be determined by heuristics (find manually)
ResolveFunctionEnd(&block, finalBlock);
}
}
bool FunctionPass::ResolveKnownFunctionEnd(FunctionDef* Function)
{
// Helper to link final blocks to function
auto startBlock = FindBBlockInRange(Function->VirtualStart);
auto endBlock = FindBBlockInRange(Function->VirtualEnd);
if(!startBlock || !endBlock)
return false;
// Find block start/end indices
Function->BBlockStart = FindBBlockIndex(startBlock);
Function->BBlockEnd = FindBBlockIndex(endBlock);
// Set the flag for blocks that have been scanned
for(BasicBlock* block = startBlock; (duint)block <= (duint)endBlock; block++)
block->SetFlag(BASIC_BLOCK_FLAG_FUNCTION);
return true;
}
bool FunctionPass::ResolveFunctionEnd(FunctionDef* Function, BasicBlock* LastBlock)
{
ASSERT_TRUE(Function->VirtualStart != 0);
// Find the first basic block of the function
BasicBlock* block = FindBBlockInRange(Function->VirtualStart);
if(!block)
{
ASSERT_ALWAYS("Block should exist at this point");
return false;
}
// The maximum address is determined by any jump that extends past
// a RET or other terminating basic block. A function may have multiple
// return statements.
duint maximumAddr = 0;
// Loop forever until the end is found
for(; (duint)block <= (duint)LastBlock; block++)
{
// Block is now in use
block->SetFlag(BASIC_BLOCK_FLAG_FUNCTION);
// Calculate max from just linear instructions
maximumAddr = max(maximumAddr, block->VirtualEnd - 1);
// Find maximum jump target
if(!block->GetFlag(BASIC_BLOCK_FLAG_CALL) && !block->GetFlag(BASIC_BLOCK_FLAG_INDIRECT))
{
if(block->Target != 0)
{
// Here's a problem: Compilers add tail-call elimination with a jump.
// Solve this by creating a maximum jump limit: +/- 512 bytes from the end.
//
// abs(block->VirtualEnd - block->Target) -- unsigned
if(min(block->VirtualEnd - block->Target, block->Target - block->VirtualEnd) <= 512)
maximumAddr = max(maximumAddr, block->Target);
}
}
// Sanity check
ASSERT_TRUE(maximumAddr >= block->VirtualStart);
// Does this node contain the maximum address?
if(maximumAddr >= block->VirtualStart && maximumAddr < block->VirtualEnd)
{
// It does! There's 4 possibilities next:
//
// 1. Return
// 2. Tail-call elimination
// 3. Optimized loop
// 4. Function continues to next block
//
// 1.
if(block->GetFlag(BASIC_BLOCK_FLAG_RET))
break;
if(block->Target != 0)
{
// NOTE: Both must be an absolute jump
if(block->GetFlag(BASIC_BLOCK_FLAG_ABSJMP))
{
// 2.
//
// abs(block->VirtualEnd - block->Target) -- unsigned
if(min(block->VirtualEnd - block->Target, block->Target - block->VirtualEnd) > 128)
break;
// 3.
if(block->Target >= Function->VirtualStart && block->Target < block->VirtualEnd)
break;
}
}
// 4. Continue
}
}
// Loop is done. Set the information in the function structure.
Function->VirtualEnd = block->VirtualEnd;
Function->BBlockEnd = FindBBlockIndex(block);
return true;
}
#ifdef _WIN64
void FunctionPass::EnumerateFunctionRuntimeEntries64(std::function<bool (PRUNTIME_FUNCTION)> Callback)
{
if(!m_FunctionInfo)
return;
// Get the table pointer and size
auto functionTable = (PRUNTIME_FUNCTION)m_FunctionInfo;
ULONG totalCount = (m_FunctionInfoSize / sizeof(RUNTIME_FUNCTION));
// Enumerate each entry
for(ULONG i = 0; i < totalCount; i++)
{
if(!Callback(&functionTable[i]))
break;
}
}
#endif // _WIN64

View File

@ -1,32 +1,32 @@
#pragma once
#include <functional>
#include "AnalysisPass.h"
#include "BasicBlock.h"
class FunctionPass : public AnalysisPass
{
public:
FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~FunctionPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
private:
duint m_ModuleStart;
PVOID m_FunctionInfo;
ULONG m_FunctionInfoSize;
void AnalysisWorker(duint Start, duint End, std::vector<FunctionDef>* Blocks);
void FindFunctionWorkerPrepass(duint Start, duint End, std::vector<FunctionDef>* Blocks);
void FindFunctionWorker(std::vector<FunctionDef>* Blocks);
bool ResolveKnownFunctionEnd(FunctionDef* Function);
bool ResolveFunctionEnd(FunctionDef* Function, BasicBlock* LastBlock);
#ifdef _WIN64
void EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback);
#endif // _WIN64
#pragma once
#include <functional>
#include "AnalysisPass.h"
#include "BasicBlock.h"
class FunctionPass : public AnalysisPass
{
public:
FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~FunctionPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
private:
duint m_ModuleStart;
PVOID m_FunctionInfo;
ULONG m_FunctionInfoSize;
void AnalysisWorker(duint Start, duint End, std::vector<FunctionDef>* Blocks);
void FindFunctionWorkerPrepass(duint Start, duint End, std::vector<FunctionDef>* Blocks);
void FindFunctionWorker(std::vector<FunctionDef>* Blocks);
bool ResolveKnownFunctionEnd(FunctionDef* Function);
bool ResolveFunctionEnd(FunctionDef* Function, BasicBlock* LastBlock);
#ifdef _WIN64
void EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback);
#endif // _WIN64
};

View File

@ -1,327 +1,327 @@
#include <thread>
#include <ppl.h>
#include "AnalysisPass.h"
#include "LinearPass.h"
#include <capstone_wrapper.h>
LinearPass::LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
// This is a fix for when the total data analysis size is less
// than what parallelization can support. The minimum size requirement
// is ((# THREADS) * (512)) bytes. If the requirement isn't met,
// scale to use a single thread.
if((512 * IdealThreadCount()) >= m_DataSize)
SetIdealThreadCount(1);
}
LinearPass::~LinearPass()
{
}
const char* LinearPass::GetName()
{
return "Linear Scandown";
}
bool LinearPass::Analyse()
{
// Divide the work up between each thread
// THREAD_WORK = (TOTAL / # THREADS)
duint workAmount = m_DataSize / IdealThreadCount();
// Initialize thread vector
auto threadBlocks = new std::vector<BasicBlock>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = m_VirtualStart + (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), m_VirtualEnd);
// Allow a 256-byte variance of scanning because of
// integer rounding errors and instruction overlap
if(threadWorkStart > m_VirtualStart)
{
threadWorkStart = max((threadWorkStart - 256), m_VirtualStart);
threadWorkStop = min((threadWorkStop + 256), m_VirtualEnd);
}
// Memory allocation optimization
// TODO: Option to conserve memory
threadBlocks[i].reserve(100000);
// Execute
AnalysisWorker(threadWorkStart, threadWorkStop, &threadBlocks[i]);
});
// Clear old data and combine vectors
m_MainBlocks.clear();
for(duint i = 0; i < IdealThreadCount(); i++)
{
std::move(threadBlocks[i].begin(), threadBlocks[i].end(), std::back_inserter(m_MainBlocks));
// Free old elements to conserve memory further
BBlockArray().swap(threadBlocks[i]);
}
// Free memory ASAP
delete[] threadBlocks;
// Sort and remove duplicates
std::sort(m_MainBlocks.begin(), m_MainBlocks.end());
m_MainBlocks.erase(std::unique(m_MainBlocks.begin(), m_MainBlocks.end()), m_MainBlocks.end());
// Run overlap analysis sub-pass
AnalyseOverlaps();
return true;
}
void LinearPass::AnalyseOverlaps()
{
// Goal of this function:
//
// Remove all overlapping
// basic blocks because of threads not ending or
// starting at absolutely defined points.
// (Example: one thread starts in the middle of
// an instruction)
//
// This also checks for basic block targets jumping into
// the middle of other basic blocks.
//
// THREAD_WORK = ceil(TOTAL / # THREADS)
duint workTotal = m_MainBlocks.size();
duint workAmount = (workTotal + (IdealThreadCount() - 1)) / IdealThreadCount();
// Initialize thread vectors
auto threadInserts = new std::vector<BasicBlock>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), workTotal);
// Again, allow an overlap of +/- 1 entry
if(threadWorkStart > 0)
{
threadWorkStart = max((threadWorkStart - 1), 0);
threadWorkStop = min((threadWorkStop + 1), workTotal);
}
// Execute
AnalysisOverlapWorker(threadWorkStart, threadWorkStop, &threadInserts[i]);
});
// THREAD VECTOR
std::vector<BasicBlock> overlapInserts;
{
for(duint i = 0; i < IdealThreadCount(); i++)
std::move(threadInserts[i].begin(), threadInserts[i].end(), std::back_inserter(overlapInserts));
// Sort and remove duplicates
std::sort(overlapInserts.begin(), overlapInserts.end());
overlapInserts.erase(std::unique(overlapInserts.begin(), overlapInserts.end()), overlapInserts.end());
delete[] threadInserts;
}
// GLOBAL VECTOR
{
// Erase blocks marked for deletion
m_MainBlocks.erase(std::remove_if(m_MainBlocks.begin(), m_MainBlocks.end(), [](BasicBlock & Elem)
{
return Elem.GetFlag(BASIC_BLOCK_FLAG_DELETE);
}));
// Insert
std::move(overlapInserts.begin(), overlapInserts.end(), std::back_inserter(m_MainBlocks));
// Final sort
std::sort(m_MainBlocks.begin(), m_MainBlocks.end());
}
}
void LinearPass::AnalysisWorker(duint Start, duint End, BBlockArray* Blocks)
{
Capstone disasm;
duint blockBegin = Start; // BBlock starting virtual address
duint blockEnd; // BBlock ending virtual address
bool blockPrevPad = false; // Indicator if the last instruction was padding
BasicBlock* lastBlock = nullptr;// Avoid an expensive call to std::vector::back()
for(duint i = Start; i < End;)
{
if(!disasm.Disassemble(i, TranslateAddress(i)))
{
// Skip instructions that can't be determined
i++;
continue;
}
// Increment counter
i += disasm.Size();
blockEnd = i;
// The basic block ends here if it is a branch
bool call = disasm.InGroup(CS_GRP_CALL); // CALL
bool jmp = disasm.InGroup(CS_GRP_JUMP); // JUMP
bool ret = disasm.InGroup(CS_GRP_RET); // RETURN
bool padding = disasm.IsFilling(); // INSTRUCTION PADDING
if(padding)
{
// PADDING is treated differently. They are all created as their
// own separate block for more analysis later.
duint realBlockEnd = blockEnd - disasm.Size();
if((realBlockEnd - blockBegin) > 0)
{
// The next line terminates the BBlock before the INT instruction.
// Early termination, faked as an indirect JMP. Rare case.
lastBlock = CreateBlockWorker(Blocks, blockBegin, realBlockEnd, false, false, false, false);
lastBlock->SetFlag(BASIC_BLOCK_FLAG_PREPAD);
blockBegin = realBlockEnd;
}
}
if(call || jmp || ret || padding)
{
// Was this a padding instruction?
if(padding && blockPrevPad)
{
// Append it to the previous block
lastBlock->VirtualEnd = blockEnd;
}
else
{
// Otherwise use the default route: create a new entry
auto block = lastBlock = CreateBlockWorker(Blocks, blockBegin, blockEnd, call, jmp, ret, padding);
// Figure out the operand type
auto operand = disasm.x86().operands[0];
if(operand.type == X86_OP_IMM)
{
// Branch target immediate
block->Target = (duint)operand.imm;
// Check if absolute jump
if(disasm.GetId() == X86_INS_JMP)
block->SetFlag(BASIC_BLOCK_FLAG_ABSJMP);
}
else
{
// Indirects
block->SetFlag(BASIC_BLOCK_FLAG_INDIRECT);
if(operand.type == X86_OP_MEM &&
operand.mem.base == X86_REG_INVALID &&
operand.mem.index == X86_REG_INVALID &&
operand.mem.scale == 1)
{
block->SetFlag(BASIC_BLOCK_FLAG_INDIRPTR);
block->Target = (duint)operand.mem.disp;
}
}
}
// Reset the loop variables
blockBegin = i;
blockPrevPad = padding;
}
}
}
void LinearPass::AnalysisOverlapWorker(duint Start, duint End, BBlockArray* Insertions)
{
// Comparison function to see if two blocks overlap
auto BlockOverlapsRemove = [](BasicBlock * A, BasicBlock * B) -> BasicBlock*
{
// Do the blocks overlap?
if(max(A->VirtualStart, B->VirtualStart) <= min((A->VirtualEnd - 1), (B->VirtualEnd - 1)))
{
// Return the block that should be removed
if(A->Size() > B->Size())
return B;
return A;
}
return nullptr;
};
// Get a pointer to pure data
const auto blocks = m_MainBlocks.data();
for(duint i = Start; i < End; i++)
{
const auto curr = &blocks[i];
const auto next = &blocks[i + 1];
// Current versus next (overlap -> delete)
BasicBlock* removal = BlockOverlapsRemove(curr, next);
if(removal)
removal->SetFlag(BASIC_BLOCK_FLAG_DELETE);
// Find blocks that need to be split in two because
// of CALL/JMP targets
//
// Find targets in the virtual range
if(ValidateAddress(curr->Target))
{
removal = FindBBlockInRange(curr->Target);
// If the target does not equal the block start...
if(removal && curr->Target != removal->VirtualStart)
{
// Mark for deletion
removal->SetFlag(BASIC_BLOCK_FLAG_DELETE);
// Block part 1
BasicBlock block1;
block1.VirtualStart = removal->VirtualStart;
block1.VirtualEnd = curr->Target;
block1.Target = 0;
block1.Flags = BASIC_BLOCK_FLAG_CUTOFF;
// Block part 2
BasicBlock block2;
block2.VirtualStart = curr->Target;
block2.VirtualEnd = removal->VirtualEnd;
block2.Target = removal->Target;
block2.Flags = removal->Flags;
Insertions->push_back(block1);
Insertions->push_back(block2);
}
}
}
}
BasicBlock* LinearPass::CreateBlockWorker(std::vector<BasicBlock>* Blocks, duint Start, duint End, bool Call, bool Jmp, bool Ret, bool Pad)
{
BasicBlock block;
block.VirtualStart = Start;
block.VirtualEnd = End;
block.Flags = 0;
block.Target = 0;
// Check for calls
if(Call)
block.SetFlag(BASIC_BLOCK_FLAG_CALL);
// Check for returns
if(Ret)
block.SetFlag(BASIC_BLOCK_FLAG_RET);
// Check for interrupts
if(Pad)
block.SetFlag(BASIC_BLOCK_FLAG_PAD);
Blocks->push_back(block);
return &Blocks->back();
#include <thread>
#include <ppl.h>
#include "AnalysisPass.h"
#include "LinearPass.h"
#include <capstone_wrapper.h>
LinearPass::LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
// This is a fix for when the total data analysis size is less
// than what parallelization can support. The minimum size requirement
// is ((# THREADS) * (512)) bytes. If the requirement isn't met,
// scale to use a single thread.
if((512 * IdealThreadCount()) >= m_DataSize)
SetIdealThreadCount(1);
}
LinearPass::~LinearPass()
{
}
const char* LinearPass::GetName()
{
return "Linear Scandown";
}
bool LinearPass::Analyse()
{
// Divide the work up between each thread
// THREAD_WORK = (TOTAL / # THREADS)
duint workAmount = m_DataSize / IdealThreadCount();
// Initialize thread vector
auto threadBlocks = new std::vector<BasicBlock>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = m_VirtualStart + (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), m_VirtualEnd);
// Allow a 256-byte variance of scanning because of
// integer rounding errors and instruction overlap
if(threadWorkStart > m_VirtualStart)
{
threadWorkStart = max((threadWorkStart - 256), m_VirtualStart);
threadWorkStop = min((threadWorkStop + 256), m_VirtualEnd);
}
// Memory allocation optimization
// TODO: Option to conserve memory
threadBlocks[i].reserve(100000);
// Execute
AnalysisWorker(threadWorkStart, threadWorkStop, &threadBlocks[i]);
});
// Clear old data and combine vectors
m_MainBlocks.clear();
for(duint i = 0; i < IdealThreadCount(); i++)
{
std::move(threadBlocks[i].begin(), threadBlocks[i].end(), std::back_inserter(m_MainBlocks));
// Free old elements to conserve memory further
BBlockArray().swap(threadBlocks[i]);
}
// Free memory ASAP
delete[] threadBlocks;
// Sort and remove duplicates
std::sort(m_MainBlocks.begin(), m_MainBlocks.end());
m_MainBlocks.erase(std::unique(m_MainBlocks.begin(), m_MainBlocks.end()), m_MainBlocks.end());
// Run overlap analysis sub-pass
AnalyseOverlaps();
return true;
}
void LinearPass::AnalyseOverlaps()
{
// Goal of this function:
//
// Remove all overlapping
// basic blocks because of threads not ending or
// starting at absolutely defined points.
// (Example: one thread starts in the middle of
// an instruction)
//
// This also checks for basic block targets jumping into
// the middle of other basic blocks.
//
// THREAD_WORK = ceil(TOTAL / # THREADS)
duint workTotal = m_MainBlocks.size();
duint workAmount = (workTotal + (IdealThreadCount() - 1)) / IdealThreadCount();
// Initialize thread vectors
auto threadInserts = new std::vector<BasicBlock>[IdealThreadCount()];
concurrency::parallel_for(duint (0), IdealThreadCount(), [&](duint i)
{
duint threadWorkStart = (workAmount * i);
duint threadWorkStop = min((threadWorkStart + workAmount), workTotal);
// Again, allow an overlap of +/- 1 entry
if(threadWorkStart > 0)
{
threadWorkStart = max((threadWorkStart - 1), 0);
threadWorkStop = min((threadWorkStop + 1), workTotal);
}
// Execute
AnalysisOverlapWorker(threadWorkStart, threadWorkStop, &threadInserts[i]);
});
// THREAD VECTOR
std::vector<BasicBlock> overlapInserts;
{
for(duint i = 0; i < IdealThreadCount(); i++)
std::move(threadInserts[i].begin(), threadInserts[i].end(), std::back_inserter(overlapInserts));
// Sort and remove duplicates
std::sort(overlapInserts.begin(), overlapInserts.end());
overlapInserts.erase(std::unique(overlapInserts.begin(), overlapInserts.end()), overlapInserts.end());
delete[] threadInserts;
}
// GLOBAL VECTOR
{
// Erase blocks marked for deletion
m_MainBlocks.erase(std::remove_if(m_MainBlocks.begin(), m_MainBlocks.end(), [](BasicBlock & Elem)
{
return Elem.GetFlag(BASIC_BLOCK_FLAG_DELETE);
}));
// Insert
std::move(overlapInserts.begin(), overlapInserts.end(), std::back_inserter(m_MainBlocks));
// Final sort
std::sort(m_MainBlocks.begin(), m_MainBlocks.end());
}
}
void LinearPass::AnalysisWorker(duint Start, duint End, BBlockArray* Blocks)
{
Capstone disasm;
duint blockBegin = Start; // BBlock starting virtual address
duint blockEnd; // BBlock ending virtual address
bool blockPrevPad = false; // Indicator if the last instruction was padding
BasicBlock* lastBlock = nullptr;// Avoid an expensive call to std::vector::back()
for(duint i = Start; i < End;)
{
if(!disasm.Disassemble(i, TranslateAddress(i)))
{
// Skip instructions that can't be determined
i++;
continue;
}
// Increment counter
i += disasm.Size();
blockEnd = i;
// The basic block ends here if it is a branch
bool call = disasm.InGroup(CS_GRP_CALL); // CALL
bool jmp = disasm.InGroup(CS_GRP_JUMP); // JUMP
bool ret = disasm.InGroup(CS_GRP_RET); // RETURN
bool padding = disasm.IsFilling(); // INSTRUCTION PADDING
if(padding)
{
// PADDING is treated differently. They are all created as their
// own separate block for more analysis later.
duint realBlockEnd = blockEnd - disasm.Size();
if((realBlockEnd - blockBegin) > 0)
{
// The next line terminates the BBlock before the INT instruction.
// Early termination, faked as an indirect JMP. Rare case.
lastBlock = CreateBlockWorker(Blocks, blockBegin, realBlockEnd, false, false, false, false);
lastBlock->SetFlag(BASIC_BLOCK_FLAG_PREPAD);
blockBegin = realBlockEnd;
}
}
if(call || jmp || ret || padding)
{
// Was this a padding instruction?
if(padding && blockPrevPad)
{
// Append it to the previous block
lastBlock->VirtualEnd = blockEnd;
}
else
{
// Otherwise use the default route: create a new entry
auto block = lastBlock = CreateBlockWorker(Blocks, blockBegin, blockEnd, call, jmp, ret, padding);
// Figure out the operand type
auto operand = disasm.x86().operands[0];
if(operand.type == X86_OP_IMM)
{
// Branch target immediate
block->Target = (duint)operand.imm;
// Check if absolute jump
if(disasm.GetId() == X86_INS_JMP)
block->SetFlag(BASIC_BLOCK_FLAG_ABSJMP);
}
else
{
// Indirects
block->SetFlag(BASIC_BLOCK_FLAG_INDIRECT);
if(operand.type == X86_OP_MEM &&
operand.mem.base == X86_REG_INVALID &&
operand.mem.index == X86_REG_INVALID &&
operand.mem.scale == 1)
{
block->SetFlag(BASIC_BLOCK_FLAG_INDIRPTR);
block->Target = (duint)operand.mem.disp;
}
}
}
// Reset the loop variables
blockBegin = i;
blockPrevPad = padding;
}
}
}
void LinearPass::AnalysisOverlapWorker(duint Start, duint End, BBlockArray* Insertions)
{
// Comparison function to see if two blocks overlap
auto BlockOverlapsRemove = [](BasicBlock * A, BasicBlock * B) -> BasicBlock*
{
// Do the blocks overlap?
if(max(A->VirtualStart, B->VirtualStart) <= min((A->VirtualEnd - 1), (B->VirtualEnd - 1)))
{
// Return the block that should be removed
if(A->Size() > B->Size())
return B;
return A;
}
return nullptr;
};
// Get a pointer to pure data
const auto blocks = m_MainBlocks.data();
for(duint i = Start; i < End; i++)
{
const auto curr = &blocks[i];
const auto next = &blocks[i + 1];
// Current versus next (overlap -> delete)
BasicBlock* removal = BlockOverlapsRemove(curr, next);
if(removal)
removal->SetFlag(BASIC_BLOCK_FLAG_DELETE);
// Find blocks that need to be split in two because
// of CALL/JMP targets
//
// Find targets in the virtual range
if(ValidateAddress(curr->Target))
{
removal = FindBBlockInRange(curr->Target);
// If the target does not equal the block start...
if(removal && curr->Target != removal->VirtualStart)
{
// Mark for deletion
removal->SetFlag(BASIC_BLOCK_FLAG_DELETE);
// Block part 1
BasicBlock block1;
block1.VirtualStart = removal->VirtualStart;
block1.VirtualEnd = curr->Target;
block1.Target = 0;
block1.Flags = BASIC_BLOCK_FLAG_CUTOFF;
// Block part 2
BasicBlock block2;
block2.VirtualStart = curr->Target;
block2.VirtualEnd = removal->VirtualEnd;
block2.Target = removal->Target;
block2.Flags = removal->Flags;
Insertions->push_back(block1);
Insertions->push_back(block2);
}
}
}
}
BasicBlock* LinearPass::CreateBlockWorker(std::vector<BasicBlock>* Blocks, duint Start, duint End, bool Call, bool Jmp, bool Ret, bool Pad)
{
BasicBlock block;
block.VirtualStart = Start;
block.VirtualEnd = End;
block.Flags = 0;
block.Target = 0;
// Check for calls
if(Call)
block.SetFlag(BASIC_BLOCK_FLAG_CALL);
// Check for returns
if(Ret)
block.SetFlag(BASIC_BLOCK_FLAG_RET);
// Check for interrupts
if(Pad)
block.SetFlag(BASIC_BLOCK_FLAG_PAD);
Blocks->push_back(block);
return &Blocks->back();
}

View File

@ -1,20 +1,20 @@
#pragma once
#include "AnalysisPass.h"
#include "BasicBlock.h"
class LinearPass : public AnalysisPass
{
public:
LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~LinearPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
void AnalyseOverlaps();
private:
void AnalysisWorker(duint Start, duint End, BBlockArray* Blocks);
void AnalysisOverlapWorker(duint Start, duint End, BBlockArray* Insertions);
BasicBlock* CreateBlockWorker(BBlockArray* Blocks, duint Start, duint End, bool Call, bool Jmp, bool Ret, bool Pad);
#pragma once
#include "AnalysisPass.h"
#include "BasicBlock.h"
class LinearPass : public AnalysisPass
{
public:
LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks);
virtual ~LinearPass();
virtual const char* GetName() override;
virtual bool Analyse() override;
void AnalyseOverlaps();
private:
void AnalysisWorker(duint Start, duint End, BBlockArray* Blocks);
void AnalysisOverlapWorker(duint Start, duint End, BBlockArray* Insertions);
BasicBlock* CreateBlockWorker(BBlockArray* Blocks, duint Start, duint End, bool Call, bool Jmp, bool Ret, bool Pad);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,53 @@
#ifndef _XEDPARSE_H
#define _XEDPARSE_H
#include <windows.h>
//XEDParse defines
#ifdef XEDPARSE_BUILD
#define XEDPARSE_EXPORT __declspec(dllexport)
#else
#define XEDPARSE_EXPORT __declspec(dllimport)
#endif //XEDPARSE_BUILD
#define XEDPARSE_CALL //calling convention
#define XEDPARSE_MAXBUFSIZE 256
#define XEDPARSE_MAXASMSIZE 16
//typedefs
typedef bool (XEDPARSE_CALL* CBXEDPARSE_UNKNOWN)(const char* text, ULONGLONG* value);
//XEDParse enums
enum XEDPARSE_STATUS
{
XEDPARSE_ERROR = 0,
XEDPARSE_OK = 1
};
//XEDParse structs
#pragma pack(push,8)
struct XEDPARSE
{
bool x64; // use 64-bit instructions
ULONGLONG cip; //instruction pointer (for relative addressing)
unsigned int dest_size; //destination size (returned by XEDParse)
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
};
#pragma pack(pop)
#ifdef __cplusplus
extern "C"
{
#endif
XEDPARSE_EXPORT XEDPARSE_STATUS XEDPARSE_CALL XEDParseAssemble(XEDPARSE* XEDParse);
#ifdef __cplusplus
}
#endif
#endif // _XEDPARSE_H
#ifndef _XEDPARSE_H
#define _XEDPARSE_H
#include <windows.h>
//XEDParse defines
#ifdef XEDPARSE_BUILD
#define XEDPARSE_EXPORT __declspec(dllexport)
#else
#define XEDPARSE_EXPORT __declspec(dllimport)
#endif //XEDPARSE_BUILD
#define XEDPARSE_CALL //calling convention
#define XEDPARSE_MAXBUFSIZE 256
#define XEDPARSE_MAXASMSIZE 16
//typedefs
typedef bool (XEDPARSE_CALL* CBXEDPARSE_UNKNOWN)(const char* text, ULONGLONG* value);
//XEDParse enums
enum XEDPARSE_STATUS
{
XEDPARSE_ERROR = 0,
XEDPARSE_OK = 1
};
//XEDParse structs
#pragma pack(push,8)
struct XEDPARSE
{
bool x64; // use 64-bit instructions
ULONGLONG cip; //instruction pointer (for relative addressing)
unsigned int dest_size; //destination size (returned by XEDParse)
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
};
#pragma pack(pop)
#ifdef __cplusplus
extern "C"
{
#endif
XEDPARSE_EXPORT XEDPARSE_STATUS XEDPARSE_CALL XEDParseAssemble(XEDPARSE* XEDParse);
#ifdef __cplusplus
}
#endif
#endif // _XEDPARSE_H

View File

@ -1,238 +1,238 @@
/**
@file _dbgfunctions.cpp
@brief Implements the dbgfunctions class.
*/
#include "_global.h"
#include "_dbgfunctions.h"
#include "assemble.h"
#include "debugger.h"
#include "jit.h"
#include "patches.h"
#include "memory.h"
#include "disasm_fast.h"
#include "stackinfo.h"
#include "symbolinfo.h"
#include "module.h"
static DBGFUNCTIONS _dbgfunctions;
const DBGFUNCTIONS* dbgfunctionsget()
{
return &_dbgfunctions;
}
static bool _assembleatex(duint addr, const char* instruction, char* error, bool fillnop)
{
return assembleat(addr, instruction, nullptr, error, fillnop);
}
static bool _sectionfromaddr(duint addr, char* section)
{
HMODULE hMod = (HMODULE)ModBaseFromAddr(addr);
if(!hMod)
return false;
wchar_t curModPath[MAX_PATH] = L"";
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, hMod, curModPath, MAX_PATH))
return false;
HANDLE FileHandle;
DWORD LoadedSize;
HANDLE FileMap;
ULONG_PTR FileMapVA;
if(StaticFileLoadW(curModPath, UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
{
duint rva = addr - (duint)hMod;
int sectionNumber = GetPE32SectionNumberFromVA(FileMapVA, GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMAGEBASE) + rva);
if(sectionNumber >= 0)
{
const char* name = (const char*)GetPE32DataFromMappedFile(FileMapVA, sectionNumber, UE_SECTIONNAME);
if(section)
strcpy_s(section, MAX_SECTION_SIZE, name); //maxi
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
return true;
}
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
}
return false;
}
static bool _patchget(duint addr)
{
return PatchGet(addr, nullptr);
}
static bool _patchinrange(duint start, duint end)
{
if(start > end)
std::swap(start, end);
for(duint i = start; i <= end; i++)
{
if(_patchget(i))
return true;
}
return false;
}
static bool _mempatch(duint va, const unsigned char* src, duint size)
{
return MemPatch(va, src, size, nullptr);
}
static void _patchrestorerange(duint start, duint end)
{
if(start > end)
std::swap(start, end);
for(duint i = start; i <= end; i++)
PatchDelete(i, true);
GuiUpdatePatches();
}
static bool _patchrestore(duint addr)
{
return PatchDelete(addr, true);
}
static void _getcallstack(DBGCALLSTACK* callstack)
{
stackgetcallstack(GetContextDataEx(hActiveThread, UE_CSP), (CALLSTACK*)callstack);
}
static bool _getjitauto(bool* jit_auto)
{
return dbggetjitauto(jit_auto, notfound, NULL, NULL);
}
static bool _getcmdline(char* cmd_line, size_t* cbsize)
{
if(!cmd_line && !cbsize)
return false;
char* cmdline;
if(!dbggetcmdline(&cmdline, NULL))
return false;
if(!cmd_line && cbsize)
*cbsize = strlen(cmdline) + sizeof(char);
else if(cmd_line)
strcpy(cmd_line, cmdline);
efree(cmdline, "_getcmdline:cmdline");
return true;
}
static bool _setcmdline(const char* cmd_line)
{
return dbgsetcmdline(cmd_line, nullptr);
}
static bool _getjit(char* jit, bool jit64)
{
arch dummy;
char jit_tmp[JIT_ENTRY_MAX_SIZE] = "";
if(jit != NULL)
{
if(!dbggetjit(jit_tmp, jit64 ? x64 : x32, &dummy, NULL))
return false;
strcpy_s(jit, MAX_SETTING_SIZE, jit_tmp);
}
else // if jit input == NULL: it returns false if there are not an OLD JIT STORED.
{
char oldjit[MAX_SETTING_SIZE] = "";
if(!BridgeSettingGet("JIT", "Old", (char*) & oldjit))
return false;
}
return true;
}
bool _getprocesslist(DBGPROCESSINFO** entries, int* count)
{
std::vector<PROCESSENTRY32> list;
if(!dbglistprocesses(&list))
return false;
*count = (int)list.size();
if(!*count)
return false;
*entries = (DBGPROCESSINFO*)BridgeAlloc(*count * sizeof(DBGPROCESSINFO));
for(int i = 0; i < *count; i++)
{
(*entries)[*count - i - 1].dwProcessId = list.at(i).th32ProcessID;
strcpy_s((*entries)[*count - i - 1].szExeFile, list.at(i).szExeFile);
}
return true;
}
static void _memupdatemap()
{
MemUpdateMap();
GuiUpdateMemoryView();
}
static duint _getaddrfromline(const char* szSourceFile, int line)
{
LONG displacement = 0;
IMAGEHLP_LINE64 lineData;
memset(&lineData, 0, sizeof(lineData));
lineData.SizeOfStruct = sizeof(lineData);
if(!SymGetLineFromName64(fdProcessInfo->hProcess, NULL, szSourceFile, line, &displacement, &lineData))
return 0;
return (duint)lineData.Address;
}
static bool _getsourcefromaddr(duint addr, char* szSourceFile, int* line)
{
char sourceFile[MAX_STRING_SIZE] = "";
if(!SymGetSourceLine(addr, sourceFile, line))
return false;
if(!FileExists(sourceFile))
return false;
if(szSourceFile)
strcpy_s(szSourceFile, MAX_STRING_SIZE, sourceFile);
return true;
}
static bool _valfromstring(const char* string, duint* value)
{
return valfromstring(string, value);
}
void dbgfunctionsinit()
{
_dbgfunctions.AssembleAtEx = _assembleatex;
_dbgfunctions.SectionFromAddr = _sectionfromaddr;
_dbgfunctions.ModNameFromAddr = ModNameFromAddr;
_dbgfunctions.ModBaseFromAddr = ModBaseFromAddr;
_dbgfunctions.ModBaseFromName = ModBaseFromName;
_dbgfunctions.ModSizeFromAddr = ModSizeFromAddr;
_dbgfunctions.Assemble = assemble;
_dbgfunctions.PatchGet = _patchget;
_dbgfunctions.PatchInRange = _patchinrange;
_dbgfunctions.MemPatch = _mempatch;
_dbgfunctions.PatchRestoreRange = _patchrestorerange;
_dbgfunctions.PatchEnum = (PATCHENUM)PatchEnum;
_dbgfunctions.PatchRestore = _patchrestore;
_dbgfunctions.PatchFile = (PATCHFILE)PatchFile;
_dbgfunctions.ModPathFromAddr = ModPathFromAddr;
_dbgfunctions.ModPathFromName = ModPathFromName;
_dbgfunctions.DisasmFast = disasmfast;
_dbgfunctions.MemUpdateMap = _memupdatemap;
_dbgfunctions.GetCallStack = _getcallstack;
_dbgfunctions.SymbolDownloadAllSymbols = SymDownloadAllSymbols;
_dbgfunctions.GetJit = _getjit;
_dbgfunctions.GetJitAuto = _getjitauto;
_dbgfunctions.GetDefJit = dbggetdefjit;
_dbgfunctions.GetProcessList = _getprocesslist;
_dbgfunctions.GetPageRights = MemGetPageRights;
_dbgfunctions.SetPageRights = MemSetPageRights;
_dbgfunctions.PageRightsToString = MemPageRightsToString;
_dbgfunctions.IsProcessElevated = IsProcessElevated;
_dbgfunctions.GetCmdline = _getcmdline;
_dbgfunctions.SetCmdline = _setcmdline;
_dbgfunctions.FileOffsetToVa = valfileoffsettova;
_dbgfunctions.VaToFileOffset = valvatofileoffset;
_dbgfunctions.GetAddrFromLine = _getaddrfromline;
_dbgfunctions.GetSourceFromAddr = _getsourcefromaddr;
_dbgfunctions.ValFromString = _valfromstring;
}
/**
@file _dbgfunctions.cpp
@brief Implements the dbgfunctions class.
*/
#include "_global.h"
#include "_dbgfunctions.h"
#include "assemble.h"
#include "debugger.h"
#include "jit.h"
#include "patches.h"
#include "memory.h"
#include "disasm_fast.h"
#include "stackinfo.h"
#include "symbolinfo.h"
#include "module.h"
static DBGFUNCTIONS _dbgfunctions;
const DBGFUNCTIONS* dbgfunctionsget()
{
return &_dbgfunctions;
}
static bool _assembleatex(duint addr, const char* instruction, char* error, bool fillnop)
{
return assembleat(addr, instruction, nullptr, error, fillnop);
}
static bool _sectionfromaddr(duint addr, char* section)
{
HMODULE hMod = (HMODULE)ModBaseFromAddr(addr);
if(!hMod)
return false;
wchar_t curModPath[MAX_PATH] = L"";
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, hMod, curModPath, MAX_PATH))
return false;
HANDLE FileHandle;
DWORD LoadedSize;
HANDLE FileMap;
ULONG_PTR FileMapVA;
if(StaticFileLoadW(curModPath, UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
{
duint rva = addr - (duint)hMod;
int sectionNumber = GetPE32SectionNumberFromVA(FileMapVA, GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMAGEBASE) + rva);
if(sectionNumber >= 0)
{
const char* name = (const char*)GetPE32DataFromMappedFile(FileMapVA, sectionNumber, UE_SECTIONNAME);
if(section)
strcpy_s(section, MAX_SECTION_SIZE, name); //maxi
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
return true;
}
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
}
return false;
}
static bool _patchget(duint addr)
{
return PatchGet(addr, nullptr);
}
static bool _patchinrange(duint start, duint end)
{
if(start > end)
std::swap(start, end);
for(duint i = start; i <= end; i++)
{
if(_patchget(i))
return true;
}
return false;
}
static bool _mempatch(duint va, const unsigned char* src, duint size)
{
return MemPatch(va, src, size, nullptr);
}
static void _patchrestorerange(duint start, duint end)
{
if(start > end)
std::swap(start, end);
for(duint i = start; i <= end; i++)
PatchDelete(i, true);
GuiUpdatePatches();
}
static bool _patchrestore(duint addr)
{
return PatchDelete(addr, true);
}
static void _getcallstack(DBGCALLSTACK* callstack)
{
stackgetcallstack(GetContextDataEx(hActiveThread, UE_CSP), (CALLSTACK*)callstack);
}
static bool _getjitauto(bool* jit_auto)
{
return dbggetjitauto(jit_auto, notfound, NULL, NULL);
}
static bool _getcmdline(char* cmd_line, size_t* cbsize)
{
if(!cmd_line && !cbsize)
return false;
char* cmdline;
if(!dbggetcmdline(&cmdline, NULL))
return false;
if(!cmd_line && cbsize)
*cbsize = strlen(cmdline) + sizeof(char);
else if(cmd_line)
strcpy(cmd_line, cmdline);
efree(cmdline, "_getcmdline:cmdline");
return true;
}
static bool _setcmdline(const char* cmd_line)
{
return dbgsetcmdline(cmd_line, nullptr);
}
static bool _getjit(char* jit, bool jit64)
{
arch dummy;
char jit_tmp[JIT_ENTRY_MAX_SIZE] = "";
if(jit != NULL)
{
if(!dbggetjit(jit_tmp, jit64 ? x64 : x32, &dummy, NULL))
return false;
strcpy_s(jit, MAX_SETTING_SIZE, jit_tmp);
}
else // if jit input == NULL: it returns false if there are not an OLD JIT STORED.
{
char oldjit[MAX_SETTING_SIZE] = "";
if(!BridgeSettingGet("JIT", "Old", (char*) & oldjit))
return false;
}
return true;
}
bool _getprocesslist(DBGPROCESSINFO** entries, int* count)
{
std::vector<PROCESSENTRY32> list;
if(!dbglistprocesses(&list))
return false;
*count = (int)list.size();
if(!*count)
return false;
*entries = (DBGPROCESSINFO*)BridgeAlloc(*count * sizeof(DBGPROCESSINFO));
for(int i = 0; i < *count; i++)
{
(*entries)[*count - i - 1].dwProcessId = list.at(i).th32ProcessID;
strcpy_s((*entries)[*count - i - 1].szExeFile, list.at(i).szExeFile);
}
return true;
}
static void _memupdatemap()
{
MemUpdateMap();
GuiUpdateMemoryView();
}
static duint _getaddrfromline(const char* szSourceFile, int line)
{
LONG displacement = 0;
IMAGEHLP_LINE64 lineData;
memset(&lineData, 0, sizeof(lineData));
lineData.SizeOfStruct = sizeof(lineData);
if(!SymGetLineFromName64(fdProcessInfo->hProcess, NULL, szSourceFile, line, &displacement, &lineData))
return 0;
return (duint)lineData.Address;
}
static bool _getsourcefromaddr(duint addr, char* szSourceFile, int* line)
{
char sourceFile[MAX_STRING_SIZE] = "";
if(!SymGetSourceLine(addr, sourceFile, line))
return false;
if(!FileExists(sourceFile))
return false;
if(szSourceFile)
strcpy_s(szSourceFile, MAX_STRING_SIZE, sourceFile);
return true;
}
static bool _valfromstring(const char* string, duint* value)
{
return valfromstring(string, value);
}
void dbgfunctionsinit()
{
_dbgfunctions.AssembleAtEx = _assembleatex;
_dbgfunctions.SectionFromAddr = _sectionfromaddr;
_dbgfunctions.ModNameFromAddr = ModNameFromAddr;
_dbgfunctions.ModBaseFromAddr = ModBaseFromAddr;
_dbgfunctions.ModBaseFromName = ModBaseFromName;
_dbgfunctions.ModSizeFromAddr = ModSizeFromAddr;
_dbgfunctions.Assemble = assemble;
_dbgfunctions.PatchGet = _patchget;
_dbgfunctions.PatchInRange = _patchinrange;
_dbgfunctions.MemPatch = _mempatch;
_dbgfunctions.PatchRestoreRange = _patchrestorerange;
_dbgfunctions.PatchEnum = (PATCHENUM)PatchEnum;
_dbgfunctions.PatchRestore = _patchrestore;
_dbgfunctions.PatchFile = (PATCHFILE)PatchFile;
_dbgfunctions.ModPathFromAddr = ModPathFromAddr;
_dbgfunctions.ModPathFromName = ModPathFromName;
_dbgfunctions.DisasmFast = disasmfast;
_dbgfunctions.MemUpdateMap = _memupdatemap;
_dbgfunctions.GetCallStack = _getcallstack;
_dbgfunctions.SymbolDownloadAllSymbols = SymDownloadAllSymbols;
_dbgfunctions.GetJit = _getjit;
_dbgfunctions.GetJitAuto = _getjitauto;
_dbgfunctions.GetDefJit = dbggetdefjit;
_dbgfunctions.GetProcessList = _getprocesslist;
_dbgfunctions.GetPageRights = MemGetPageRights;
_dbgfunctions.SetPageRights = MemSetPageRights;
_dbgfunctions.PageRightsToString = MemPageRightsToString;
_dbgfunctions.IsProcessElevated = IsProcessElevated;
_dbgfunctions.GetCmdline = _getcmdline;
_dbgfunctions.SetCmdline = _setcmdline;
_dbgfunctions.FileOffsetToVa = valfileoffsettova;
_dbgfunctions.VaToFileOffset = valvatofileoffset;
_dbgfunctions.GetAddrFromLine = _getaddrfromline;
_dbgfunctions.GetSourceFromAddr = _getsourcefromaddr;
_dbgfunctions.ValFromString = _valfromstring;
}

View File

@ -1,118 +1,118 @@
#ifndef _DBGFUNCTIONS_H
#define _DBGFUNCTIONS_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
typedef struct
{
char mod[MAX_MODULE_SIZE];
duint addr;
unsigned char oldbyte;
unsigned char newbyte;
} DBGPATCHINFO;
typedef struct
{
duint addr;
duint from;
duint to;
char comment[MAX_COMMENT_SIZE];
} DBGCALLSTACKENTRY;
typedef struct
{
int total;
DBGCALLSTACKENTRY* entries;
} DBGCALLSTACK;
typedef struct
{
DWORD dwProcessId;
char szExeFile[MAX_PATH];
} DBGPROCESSINFO;
typedef bool (*ASSEMBLEATEX)(duint addr, const char* instruction, char* error, bool fillnop);
typedef bool (*SECTIONFROMADDR)(duint addr, char* section);
typedef bool (*MODNAMEFROMADDR)(duint addr, char* modname, bool extension);
typedef duint (*MODBASEFROMADDR)(duint addr);
typedef duint (*MODBASEFROMNAME)(const char* modname);
typedef duint (*MODSIZEFROMADDR)(duint addr);
typedef bool (*ASSEMBLE)(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
typedef bool (*PATCHGET)(duint addr);
typedef bool (*PATCHINRANGE)(duint start, duint end);
typedef bool (*MEMPATCH)(duint va, const unsigned char* src, duint size);
typedef void (*PATCHRESTORERANGE)(duint start, duint end);
typedef bool (*PATCHENUM)(DBGPATCHINFO* patchlist, size_t* cbsize);
typedef bool (*PATCHRESTORE)(duint addr);
typedef int (*PATCHFILE)(DBGPATCHINFO* patchlist, int count, const char* szFileName, char* error);
typedef int (*MODPATHFROMADDR)(duint addr, char* path, int size);
typedef int (*MODPATHFROMNAME)(const char* modname, char* path, int size);
typedef bool (*DISASMFAST)(unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo);
typedef void (*MEMUPDATEMAP)();
typedef void (*GETCALLSTACK)(DBGCALLSTACK* callstack);
typedef void (*SYMBOLDOWNLOADALLSYMBOLS)(const char* szSymbolStore);
typedef bool (*GETJIT)(char* jit, bool x64);
typedef bool (*GETJITAUTO)(bool* jitauto);
typedef bool (*GETDEFJIT)(char* defjit);
typedef bool (*GETPROCESSLIST)(DBGPROCESSINFO** entries, int* count);
typedef bool (*GETPAGERIGHTS)(duint addr, char* rights);
typedef bool (*SETPAGERIGHTS)(duint addr, const char* rights);
typedef bool (*PAGERIGHTSTOSTRING)(DWORD protect, char* rights);
typedef bool (*ISPROCESSELEVATED)();
typedef bool (*GETCMDLINE)(char* cmdline, size_t* cbsize);
typedef bool (*SETCMDLINE)(const char* cmdline);
typedef duint (*FILEOFFSETTOVA)(const char* modname, duint offset);
typedef duint (*VATOFILEOFFSET)(duint va);
typedef duint (*GETADDRFROMLINE)(const char* szSourceFile, int line);
typedef bool (*GETSOURCEFROMADDR)(duint addr, char* szSourceFile, int* line);
typedef bool (*VALFROMSTRING)(const char* string, duint* value);
typedef struct DBGFUNCTIONS_
{
ASSEMBLEATEX AssembleAtEx;
SECTIONFROMADDR SectionFromAddr;
MODNAMEFROMADDR ModNameFromAddr;
MODBASEFROMADDR ModBaseFromAddr;
MODBASEFROMNAME ModBaseFromName;
MODSIZEFROMADDR ModSizeFromAddr;
ASSEMBLE Assemble;
PATCHGET PatchGet;
PATCHINRANGE PatchInRange;
MEMPATCH MemPatch;
PATCHRESTORERANGE PatchRestoreRange;
PATCHENUM PatchEnum;
PATCHRESTORE PatchRestore;
PATCHFILE PatchFile;
MODPATHFROMADDR ModPathFromAddr;
MODPATHFROMNAME ModPathFromName;
DISASMFAST DisasmFast;
MEMUPDATEMAP MemUpdateMap;
GETCALLSTACK GetCallStack;
SYMBOLDOWNLOADALLSYMBOLS SymbolDownloadAllSymbols;
GETJITAUTO GetJitAuto;
GETJIT GetJit;
GETDEFJIT GetDefJit;
GETPROCESSLIST GetProcessList;
GETPAGERIGHTS GetPageRights;
SETPAGERIGHTS SetPageRights;
PAGERIGHTSTOSTRING PageRightsToString;
ISPROCESSELEVATED IsProcessElevated;
GETCMDLINE GetCmdline;
SETCMDLINE SetCmdline;
FILEOFFSETTOVA FileOffsetToVa;
VATOFILEOFFSET VaToFileOffset;
GETADDRFROMLINE GetAddrFromLine;
GETSOURCEFROMADDR GetSourceFromAddr;
VALFROMSTRING ValFromString;
} DBGFUNCTIONS;
#ifdef BUILD_DBG
const DBGFUNCTIONS* dbgfunctionsget();
void dbgfunctionsinit();
#endif //BUILD_DBG
#endif //_DBGFUNCTIONS_H
#ifndef _DBGFUNCTIONS_H
#define _DBGFUNCTIONS_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
typedef struct
{
char mod[MAX_MODULE_SIZE];
duint addr;
unsigned char oldbyte;
unsigned char newbyte;
} DBGPATCHINFO;
typedef struct
{
duint addr;
duint from;
duint to;
char comment[MAX_COMMENT_SIZE];
} DBGCALLSTACKENTRY;
typedef struct
{
int total;
DBGCALLSTACKENTRY* entries;
} DBGCALLSTACK;
typedef struct
{
DWORD dwProcessId;
char szExeFile[MAX_PATH];
} DBGPROCESSINFO;
typedef bool (*ASSEMBLEATEX)(duint addr, const char* instruction, char* error, bool fillnop);
typedef bool (*SECTIONFROMADDR)(duint addr, char* section);
typedef bool (*MODNAMEFROMADDR)(duint addr, char* modname, bool extension);
typedef duint (*MODBASEFROMADDR)(duint addr);
typedef duint (*MODBASEFROMNAME)(const char* modname);
typedef duint (*MODSIZEFROMADDR)(duint addr);
typedef bool (*ASSEMBLE)(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
typedef bool (*PATCHGET)(duint addr);
typedef bool (*PATCHINRANGE)(duint start, duint end);
typedef bool (*MEMPATCH)(duint va, const unsigned char* src, duint size);
typedef void (*PATCHRESTORERANGE)(duint start, duint end);
typedef bool (*PATCHENUM)(DBGPATCHINFO* patchlist, size_t* cbsize);
typedef bool (*PATCHRESTORE)(duint addr);
typedef int (*PATCHFILE)(DBGPATCHINFO* patchlist, int count, const char* szFileName, char* error);
typedef int (*MODPATHFROMADDR)(duint addr, char* path, int size);
typedef int (*MODPATHFROMNAME)(const char* modname, char* path, int size);
typedef bool (*DISASMFAST)(unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo);
typedef void (*MEMUPDATEMAP)();
typedef void (*GETCALLSTACK)(DBGCALLSTACK* callstack);
typedef void (*SYMBOLDOWNLOADALLSYMBOLS)(const char* szSymbolStore);
typedef bool (*GETJIT)(char* jit, bool x64);
typedef bool (*GETJITAUTO)(bool* jitauto);
typedef bool (*GETDEFJIT)(char* defjit);
typedef bool (*GETPROCESSLIST)(DBGPROCESSINFO** entries, int* count);
typedef bool (*GETPAGERIGHTS)(duint addr, char* rights);
typedef bool (*SETPAGERIGHTS)(duint addr, const char* rights);
typedef bool (*PAGERIGHTSTOSTRING)(DWORD protect, char* rights);
typedef bool (*ISPROCESSELEVATED)();
typedef bool (*GETCMDLINE)(char* cmdline, size_t* cbsize);
typedef bool (*SETCMDLINE)(const char* cmdline);
typedef duint (*FILEOFFSETTOVA)(const char* modname, duint offset);
typedef duint (*VATOFILEOFFSET)(duint va);
typedef duint (*GETADDRFROMLINE)(const char* szSourceFile, int line);
typedef bool (*GETSOURCEFROMADDR)(duint addr, char* szSourceFile, int* line);
typedef bool (*VALFROMSTRING)(const char* string, duint* value);
typedef struct DBGFUNCTIONS_
{
ASSEMBLEATEX AssembleAtEx;
SECTIONFROMADDR SectionFromAddr;
MODNAMEFROMADDR ModNameFromAddr;
MODBASEFROMADDR ModBaseFromAddr;
MODBASEFROMNAME ModBaseFromName;
MODSIZEFROMADDR ModSizeFromAddr;
ASSEMBLE Assemble;
PATCHGET PatchGet;
PATCHINRANGE PatchInRange;
MEMPATCH MemPatch;
PATCHRESTORERANGE PatchRestoreRange;
PATCHENUM PatchEnum;
PATCHRESTORE PatchRestore;
PATCHFILE PatchFile;
MODPATHFROMADDR ModPathFromAddr;
MODPATHFROMNAME ModPathFromName;
DISASMFAST DisasmFast;
MEMUPDATEMAP MemUpdateMap;
GETCALLSTACK GetCallStack;
SYMBOLDOWNLOADALLSYMBOLS SymbolDownloadAllSymbols;
GETJITAUTO GetJitAuto;
GETJIT GetJit;
GETDEFJIT GetDefJit;
GETPROCESSLIST GetProcessList;
GETPAGERIGHTS GetPageRights;
SETPAGERIGHTS SetPageRights;
PAGERIGHTSTOSTRING PageRightsToString;
ISPROCESSELEVATED IsProcessElevated;
GETCMDLINE GetCmdline;
SETCMDLINE SetCmdline;
FILEOFFSETTOVA FileOffsetToVa;
VATOFILEOFFSET VaToFileOffset;
GETADDRFROMLINE GetAddrFromLine;
GETSOURCEFROMADDR GetSourceFromAddr;
VALFROMSTRING ValFromString;
} DBGFUNCTIONS;
#ifdef BUILD_DBG
const DBGFUNCTIONS* dbgfunctionsget();
void dbgfunctionsinit();
#endif //BUILD_DBG
#endif //_DBGFUNCTIONS_H

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,33 @@
#ifndef _EXPORTS_H
#define _EXPORTS_H
#include "_global.h"
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size);
DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read);
DLL_EXPORT bool _dbg_memwrite(duint addr, const unsigned char* src, duint size, duint* written);
DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap);
DLL_EXPORT bool _dbg_memisvalidreadptr(duint addr);
DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value);
DLL_EXPORT bool _dbg_isdebugging();
DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr);
DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo);
DLL_EXPORT int _dbg_bpgettypeat(duint addr);
DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump);
DLL_EXPORT bool _dbg_valtostring(const char* string, duint value);
DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* list);
DLL_EXPORT duint _dbg_getbranchdestination(duint addr);
DLL_EXPORT bool _dbg_functionoverlaps(duint start, duint end);
DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* param2);
#ifdef __cplusplus
}
#endif
#endif // _EXPORTS_H
#ifndef _EXPORTS_H
#define _EXPORTS_H
#include "_global.h"
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size);
DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read);
DLL_EXPORT bool _dbg_memwrite(duint addr, const unsigned char* src, duint size, duint* written);
DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap);
DLL_EXPORT bool _dbg_memisvalidreadptr(duint addr);
DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value);
DLL_EXPORT bool _dbg_isdebugging();
DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr);
DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo);
DLL_EXPORT int _dbg_bpgettypeat(duint addr);
DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump);
DLL_EXPORT bool _dbg_valtostring(const char* string, duint value);
DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* list);
DLL_EXPORT duint _dbg_getbranchdestination(duint addr);
DLL_EXPORT bool _dbg_functionoverlaps(duint start, duint end);
DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* param2);
#ifdef __cplusplus
}
#endif
#endif // _EXPORTS_H

View File

@ -1,348 +1,348 @@
/**
\file _global.cpp
\brief Implements the global class.
*/
#include "_global.h"
#include <objbase.h>
#include <shlobj.h>
/**
\brief x64dbg library instance.
*/
HINSTANCE hInst;
/**
\brief Number of allocated buffers by emalloc(). This should be 0 when x64dbg ends.
*/
static int emalloc_count = 0;
/**
\brief Path for debugging, used to create an allocation trace file on emalloc() or efree(). Not used.
*/
static char alloctrace[MAX_PATH] = "";
/**
\brief Allocates a new buffer.
\param size The size of the buffer to allocate (in bytes).
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* emalloc(size_t size, const char* reason)
{
ASSERT_NONZERO(size);
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size);
if(!a)
{
MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR);
ExitProcess(1);
}
memset(a, 0, size);
emalloc_count++;
/*
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d: alloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
fclose(file);
*/
return a;
}
/**
\brief Reallocates a buffer allocated with emalloc().
\param [in] Pointer to memory previously allocated with emalloc(). When NULL a new buffer will be allocated by emalloc().
\param size The new memory size.
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* erealloc(void* ptr, size_t size, const char* reason)
{
ASSERT_NONZERO(size);
// Free the memory if the pointer was set (as per documentation).
if (ptr)
efree(ptr);
return emalloc(size, reason);
}
/**
\brief Free memory previously allocated with emalloc().
\param [in] Pointer to the memory to free.
\param reason The reason for freeing, should be the same as the reason for allocating.
*/
void efree(void* ptr, const char* reason)
{
emalloc_count--;
/*
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d: free:" fhex ":%s\n", emalloc_count, ptr, reason);
fclose(file);
*/
GlobalFree(ptr);
}
void* json_malloc(size_t size)
{
return emalloc(size, "json:ptr");
}
void json_free(void* ptr)
{
efree(ptr, "json:ptr");
}
/**
\brief Gets the number of memory leaks. This number is only valid in _dbg_dbgexitsignal().
\return The number of memory leaks.
*/
int memleaks()
{
return emalloc_count;
}
/**
\brief Sets the path for the allocation trace file.
\param file UTF-8 filepath.
*/
void setalloctrace(const char* file)
{
strcpy_s(alloctrace, file);
}
/**
\brief A function to determine if a string is contained in a specifically formatted 'array string'.
\param cmd_list Array of strings separated by '\1'.
\param cmd The string to look for.
\return true if \p cmd is contained in \p cmd_list.
*/
bool arraycontains(const char* cmd_list, const char* cmd)
{
//TODO: fix this function a little
if(!cmd_list || !cmd)
return false;
char temp[deflen] = "";
strcpy_s(temp, cmd_list);
int len = (int)strlen(cmd_list);
if(len >= deflen)
return false;
for(int i = 0; i < len; i++)
if(temp[i] == 1)
temp[i] = 0;
if(!_stricmp(temp, cmd))
return true;
for(int i = (int)strlen(temp); i < len; i++)
{
if(!temp[i])
{
if(!_stricmp(temp + i + 1, cmd))
return true;
i += (int)strlen(temp + i + 1);
}
}
return false;
}
/**
\brief Compares two strings without case-sensitivity.
\param a The first string.
\param b The second string.
\return true if the strings are equal (case-insensitive).
*/
bool scmp(const char* a, const char* b)
{
if(_stricmp(a, b))
return false;
return true;
}
/**
\brief Formats a string to hexadecimal format (removes all non-hex characters).
\param [in,out] String to format.
*/
void formathex(char* string)
{
int len = (int)strlen(string);
_strupr(string);
Memory<char*> new_string(len + 1, "formathex:new_string");
for(int i = 0, j = 0; i < len; i++)
if(isxdigit(string[i]))
j += sprintf(new_string() + j, "%c", string[i]);
strcpy_s(string, len + 1, new_string());
}
/**
\brief Formats a string to decimal format (removed all non-numeric characters).
\param [in,out] String to format.
*/
void formatdec(char* string)
{
int len = (int)strlen(string);
_strupr(string);
Memory<char*> new_string(len + 1, "formatdec:new_string");
for(int i = 0, j = 0; i < len; i++)
if(isdigit(string[i]))
j += sprintf(new_string() + j, "%c", string[i]);
strcpy_s(string, len + 1, new_string());
}
/**
\brief Queries if a given file exists.
\param file Path to the file to check (UTF-8).
\return true if the file exists on the hard drive.
*/
bool FileExists(const char* file)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(file).c_str());
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
}
/**
\brief Queries if a given directory exists.
\param dir Path to the directory to check (UTF-8).
\return true if the directory exists.
*/
bool DirExists(const char* dir)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(dir).c_str());
return (attrib == FILE_ATTRIBUTE_DIRECTORY);
}
/**
\brief Gets file path from a file handle.
\param hFile File handle to get the path from.
\param [in,out] szFileName Buffer of size MAX_PATH.
\return true if it succeeds, false if it fails.
*/
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName)
{
wchar_t wszFileName[MAX_PATH] = L"";
if(!PathFromFileHandleW(hFile, wszFileName, sizeof(wszFileName)))
return false;
strcpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str());
return true;
}
/**
\brief Get a boolean setting from the configuration file.
\param section The section of the setting (UTF-8).
\param name The name of the setting (UTF-8).
\return true if the setting was set and equals to true, otherwise returns false.
*/
bool settingboolget(const char* section, const char* name)
{
duint setting;
if(!BridgeSettingGetUint(section, name, &setting))
return false;
if(setting)
return true;
return false;
}
/**
\brief Gets file architecture.
\param szFileName UTF-8 encoded file path.
\return The file architecture (::arch).
*/
arch GetFileArchitecture(const char* szFileName)
{
arch retval = notfound;
Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(szFileName).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
unsigned char data[0x1000];
DWORD read = 0;
DWORD fileSize = GetFileSize(hFile, 0);
DWORD readSize = sizeof(data);
if(readSize > fileSize)
readSize = fileSize;
if(ReadFile(hFile, data, readSize, &read, 0))
{
retval = invalid;
IMAGE_DOS_HEADER* pdh = (IMAGE_DOS_HEADER*)data;
if(pdh->e_magic == IMAGE_DOS_SIGNATURE && (size_t)pdh->e_lfanew < readSize)
{
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)(data + pdh->e_lfanew);
if(pnth->Signature == IMAGE_NT_SIGNATURE)
{
if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) //x32
retval = x32;
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) //x64
retval = x64;
}
}
}
}
return retval;
}
/**
\brief Query if x64dbg is running in Wow64 mode.
\return true if running in Wow64, false otherwise.
*/
bool IsWow64()
{
BOOL bIsWow64Process = FALSE;
//x64dbg supports WinXP SP3 and later only, so ignore the GetProcAddress crap :D
IsWow64Process(GetCurrentProcess(), &bIsWow64Process);
return !!bIsWow64Process;
}
//Taken from: http://www.cplusplus.com/forum/windows/64088/
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize)
{
if(szResolvedPath == NULL)
return SUCCEEDED(E_INVALIDARG);
//Initialize COM stuff
CoInitialize(NULL);
//Get a pointer to the IShellLink interface.
IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if(SUCCEEDED(hres))
{
//Get a pointer to the IPersistFile interface.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if(SUCCEEDED(hres))
{
//Load the shortcut.
hres = ppf->Load(szShortcutPath, STGM_READ);
if(SUCCEEDED(hres))
{
//Resolve the link.
hres = psl->Resolve(hwnd, 0);
if(SUCCEEDED(hres))
{
//Get the path to the link target.
char szGotPath[MAX_PATH] = {0};
hres = psl->GetPath(szGotPath, _countof(szGotPath), NULL, SLGP_SHORTPATH);
if(SUCCEEDED(hres))
{
strcpy_s(szResolvedPath, nSize, szGotPath);
}
}
}
//Release the pointer to the IPersistFile interface.
ppf->Release();
}
//Release the pointer to the IShellLink interface.
psl->Release();
}
//Uninitialize COM stuff
CoUninitialize();
return SUCCEEDED(hres);
}
void WaitForThreadTermination(HANDLE hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
/**
\file _global.cpp
\brief Implements the global class.
*/
#include "_global.h"
#include <objbase.h>
#include <shlobj.h>
/**
\brief x64dbg library instance.
*/
HINSTANCE hInst;
/**
\brief Number of allocated buffers by emalloc(). This should be 0 when x64dbg ends.
*/
static int emalloc_count = 0;
/**
\brief Path for debugging, used to create an allocation trace file on emalloc() or efree(). Not used.
*/
static char alloctrace[MAX_PATH] = "";
/**
\brief Allocates a new buffer.
\param size The size of the buffer to allocate (in bytes).
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* emalloc(size_t size, const char* reason)
{
ASSERT_NONZERO(size);
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size);
if(!a)
{
MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR);
ExitProcess(1);
}
memset(a, 0, size);
emalloc_count++;
/*
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d: alloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
fclose(file);
*/
return a;
}
/**
\brief Reallocates a buffer allocated with emalloc().
\param [in] Pointer to memory previously allocated with emalloc(). When NULL a new buffer will be allocated by emalloc().
\param size The new memory size.
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* erealloc(void* ptr, size_t size, const char* reason)
{
ASSERT_NONZERO(size);
// Free the memory if the pointer was set (as per documentation).
if (ptr)
efree(ptr);
return emalloc(size, reason);
}
/**
\brief Free memory previously allocated with emalloc().
\param [in] Pointer to the memory to free.
\param reason The reason for freeing, should be the same as the reason for allocating.
*/
void efree(void* ptr, const char* reason)
{
emalloc_count--;
/*
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d: free:" fhex ":%s\n", emalloc_count, ptr, reason);
fclose(file);
*/
GlobalFree(ptr);
}
void* json_malloc(size_t size)
{
return emalloc(size, "json:ptr");
}
void json_free(void* ptr)
{
efree(ptr, "json:ptr");
}
/**
\brief Gets the number of memory leaks. This number is only valid in _dbg_dbgexitsignal().
\return The number of memory leaks.
*/
int memleaks()
{
return emalloc_count;
}
/**
\brief Sets the path for the allocation trace file.
\param file UTF-8 filepath.
*/
void setalloctrace(const char* file)
{
strcpy_s(alloctrace, file);
}
/**
\brief A function to determine if a string is contained in a specifically formatted 'array string'.
\param cmd_list Array of strings separated by '\1'.
\param cmd The string to look for.
\return true if \p cmd is contained in \p cmd_list.
*/
bool arraycontains(const char* cmd_list, const char* cmd)
{
//TODO: fix this function a little
if(!cmd_list || !cmd)
return false;
char temp[deflen] = "";
strcpy_s(temp, cmd_list);
int len = (int)strlen(cmd_list);
if(len >= deflen)
return false;
for(int i = 0; i < len; i++)
if(temp[i] == 1)
temp[i] = 0;
if(!_stricmp(temp, cmd))
return true;
for(int i = (int)strlen(temp); i < len; i++)
{
if(!temp[i])
{
if(!_stricmp(temp + i + 1, cmd))
return true;
i += (int)strlen(temp + i + 1);
}
}
return false;
}
/**
\brief Compares two strings without case-sensitivity.
\param a The first string.
\param b The second string.
\return true if the strings are equal (case-insensitive).
*/
bool scmp(const char* a, const char* b)
{
if(_stricmp(a, b))
return false;
return true;
}
/**
\brief Formats a string to hexadecimal format (removes all non-hex characters).
\param [in,out] String to format.
*/
void formathex(char* string)
{
int len = (int)strlen(string);
_strupr(string);
Memory<char*> new_string(len + 1, "formathex:new_string");
for(int i = 0, j = 0; i < len; i++)
if(isxdigit(string[i]))
j += sprintf(new_string() + j, "%c", string[i]);
strcpy_s(string, len + 1, new_string());
}
/**
\brief Formats a string to decimal format (removed all non-numeric characters).
\param [in,out] String to format.
*/
void formatdec(char* string)
{
int len = (int)strlen(string);
_strupr(string);
Memory<char*> new_string(len + 1, "formatdec:new_string");
for(int i = 0, j = 0; i < len; i++)
if(isdigit(string[i]))
j += sprintf(new_string() + j, "%c", string[i]);
strcpy_s(string, len + 1, new_string());
}
/**
\brief Queries if a given file exists.
\param file Path to the file to check (UTF-8).
\return true if the file exists on the hard drive.
*/
bool FileExists(const char* file)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(file).c_str());
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
}
/**
\brief Queries if a given directory exists.
\param dir Path to the directory to check (UTF-8).
\return true if the directory exists.
*/
bool DirExists(const char* dir)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(dir).c_str());
return (attrib == FILE_ATTRIBUTE_DIRECTORY);
}
/**
\brief Gets file path from a file handle.
\param hFile File handle to get the path from.
\param [in,out] szFileName Buffer of size MAX_PATH.
\return true if it succeeds, false if it fails.
*/
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName)
{
wchar_t wszFileName[MAX_PATH] = L"";
if(!PathFromFileHandleW(hFile, wszFileName, sizeof(wszFileName)))
return false;
strcpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str());
return true;
}
/**
\brief Get a boolean setting from the configuration file.
\param section The section of the setting (UTF-8).
\param name The name of the setting (UTF-8).
\return true if the setting was set and equals to true, otherwise returns false.
*/
bool settingboolget(const char* section, const char* name)
{
duint setting;
if(!BridgeSettingGetUint(section, name, &setting))
return false;
if(setting)
return true;
return false;
}
/**
\brief Gets file architecture.
\param szFileName UTF-8 encoded file path.
\return The file architecture (::arch).
*/
arch GetFileArchitecture(const char* szFileName)
{
arch retval = notfound;
Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(szFileName).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
unsigned char data[0x1000];
DWORD read = 0;
DWORD fileSize = GetFileSize(hFile, 0);
DWORD readSize = sizeof(data);
if(readSize > fileSize)
readSize = fileSize;
if(ReadFile(hFile, data, readSize, &read, 0))
{
retval = invalid;
IMAGE_DOS_HEADER* pdh = (IMAGE_DOS_HEADER*)data;
if(pdh->e_magic == IMAGE_DOS_SIGNATURE && (size_t)pdh->e_lfanew < readSize)
{
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)(data + pdh->e_lfanew);
if(pnth->Signature == IMAGE_NT_SIGNATURE)
{
if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) //x32
retval = x32;
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) //x64
retval = x64;
}
}
}
}
return retval;
}
/**
\brief Query if x64dbg is running in Wow64 mode.
\return true if running in Wow64, false otherwise.
*/
bool IsWow64()
{
BOOL bIsWow64Process = FALSE;
//x64dbg supports WinXP SP3 and later only, so ignore the GetProcAddress crap :D
IsWow64Process(GetCurrentProcess(), &bIsWow64Process);
return !!bIsWow64Process;
}
//Taken from: http://www.cplusplus.com/forum/windows/64088/
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize)
{
if(szResolvedPath == NULL)
return SUCCEEDED(E_INVALIDARG);
//Initialize COM stuff
CoInitialize(NULL);
//Get a pointer to the IShellLink interface.
IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if(SUCCEEDED(hres))
{
//Get a pointer to the IPersistFile interface.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if(SUCCEEDED(hres))
{
//Load the shortcut.
hres = ppf->Load(szShortcutPath, STGM_READ);
if(SUCCEEDED(hres))
{
//Resolve the link.
hres = psl->Resolve(hwnd, 0);
if(SUCCEEDED(hres))
{
//Get the path to the link target.
char szGotPath[MAX_PATH] = {0};
hres = psl->GetPath(szGotPath, _countof(szGotPath), NULL, SLGP_SHORTPATH);
if(SUCCEEDED(hres))
{
strcpy_s(szResolvedPath, nSize, szGotPath);
}
}
}
//Release the pointer to the IPersistFile interface.
ppf->Release();
}
//Release the pointer to the IShellLink interface.
psl->Release();
}
//Uninitialize COM stuff
CoUninitialize();
return SUCCEEDED(hres);
}
void WaitForThreadTermination(HANDLE hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}

View File

@ -1,84 +1,84 @@
#ifndef _GLOBAL_H
#define _GLOBAL_H
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#define _WIN32_IE 0x0500
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <windows.h>
#include <psapi.h>
#include <shlwapi.h>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <tlhelp32.h>
#include "..\dbg_types.h"
#include "..\dbg_assert.h"
#include "..\bridge\bridgemain.h"
#include "jansson\jansson.h"
#include "jansson\jansson_x64dbg.h"
#include "yara\yara.h"
#include "DeviceNameResolver\DeviceNameResolver.h"
#include "handle.h"
#include "stringutils.h"
#include "dbghelp_safe.h"
#ifndef DLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#endif //DLL_IMPORT
#ifndef DLL_IMPORT
#define DLL_IMPORT __declspec(dllimport)
#endif //DLL_IMPORT
//defines
#define deflen 1024
#ifdef _WIN64 //defined by default
#define fhex "%.16llX"
#define fext "ll"
#else
#define fhex "%.8X"
#define fext ""
#endif // _WIN64
enum arch
{
notfound,
invalid,
x32,
x64
};
//superglobal variables
extern HINSTANCE hInst;
//functions
void* emalloc(size_t size, const char* reason = "emalloc:???");
void* erealloc(void* ptr, size_t size, const char* reason = "erealloc:???");
void efree(void* ptr, const char* reason = "efree:???");
void* json_malloc(size_t size);
void json_free(void* ptr);
int memleaks();
void setalloctrace(const char* file);
bool arraycontains(const char* cmd_list, const char* cmd);
bool scmp(const char* a, const char* b);
void formathex(char* string);
void formatdec(char* string);
bool FileExists(const char* file);
bool DirExists(const char* dir);
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName);
bool settingboolget(const char* section, const char* name);
arch GetFileArchitecture(const char* szFileName);
bool IsWow64();
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize);
void WaitForThreadTermination(HANDLE hThread);
#include "dynamicmem.h"
#endif // _GLOBAL_H
#ifndef _GLOBAL_H
#define _GLOBAL_H
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#define _WIN32_IE 0x0500
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <windows.h>
#include <psapi.h>
#include <shlwapi.h>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <tlhelp32.h>
#include "..\dbg_types.h"
#include "..\dbg_assert.h"
#include "..\bridge\bridgemain.h"
#include "jansson\jansson.h"
#include "jansson\jansson_x64dbg.h"
#include "yara\yara.h"
#include "DeviceNameResolver\DeviceNameResolver.h"
#include "handle.h"
#include "stringutils.h"
#include "dbghelp_safe.h"
#ifndef DLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#endif //DLL_IMPORT
#ifndef DLL_IMPORT
#define DLL_IMPORT __declspec(dllimport)
#endif //DLL_IMPORT
//defines
#define deflen 1024
#ifdef _WIN64 //defined by default
#define fhex "%.16llX"
#define fext "ll"
#else
#define fhex "%.8X"
#define fext ""
#endif // _WIN64
enum arch
{
notfound,
invalid,
x32,
x64
};
//superglobal variables
extern HINSTANCE hInst;
//functions
void* emalloc(size_t size, const char* reason = "emalloc:???");
void* erealloc(void* ptr, size_t size, const char* reason = "erealloc:???");
void efree(void* ptr, const char* reason = "efree:???");
void* json_malloc(size_t size);
void json_free(void* ptr);
int memleaks();
void setalloctrace(const char* file);
bool arraycontains(const char* cmd_list, const char* cmd);
bool scmp(const char* a, const char* b);
void formathex(char* string);
void formatdec(char* string);
bool FileExists(const char* file);
bool DirExists(const char* dir);
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName);
bool settingboolget(const char* section, const char* name);
arch GetFileArchitecture(const char* szFileName);
bool IsWow64();
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize);
void WaitForThreadTermination(HANDLE hThread);
#include "dynamicmem.h"
#endif // _GLOBAL_H

View File

@ -1,25 +1,25 @@
#ifndef _PLUGIN_DATA_H
#define _PLUGIN_DATA_H
#ifdef BUILD_DBG
#include "_global.h"
#else
#ifdef __GNUC__
#include "dbghelp\dbghelp.h"
#else
#include <dbghelp.h>
#endif // __GNUC__
#ifndef deflen
#define deflen 1024
#endif // deflen
#include "bridgemain.h"
#include "_dbgfunctions.h"
#endif // BUILD_DBG
#endif // _PLUGIN_DATA_H
#ifndef _PLUGIN_DATA_H
#define _PLUGIN_DATA_H
#ifdef BUILD_DBG
#include "_global.h"
#else
#ifdef __GNUC__
#include "dbghelp\dbghelp.h"
#else
#include <dbghelp.h>
#endif // __GNUC__
#ifndef deflen
#define deflen 1024
#endif // deflen
#include "bridgemain.h"
#include "_dbgfunctions.h"
#endif // BUILD_DBG
#endif // _PLUGIN_DATA_H

View File

@ -1,103 +1,103 @@
/**
@file _plugins.cpp
@brief Implements the plugins class.
*/
#include "_plugins.h"
#include "plugin_loader.h"
#include "console.h"
#include "debugger.h"
#include "threading.h"
///debugger plugin exports (wrappers)
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
{
pluginregistercallback(pluginHandle, cbType, cbPlugin);
}
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType)
{
return pluginunregistercallback(pluginHandle, cbType);
}
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly)
{
return plugincmdregister(pluginHandle, command, cbCommand, debugonly);
}
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command)
{
return plugincmdunregister(pluginHandle, command);
}
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...)
{
va_list args;
va_start(args, format);
dprintf_args(format, args);
va_end(args);
}
PLUG_IMPEXP void _plugin_logputs(const char* text)
{
dputs(text);
}
PLUG_IMPEXP void _plugin_debugpause()
{
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
dbgsetskipexceptions(false);
wait(WAITID_RUN);
}
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip)
{
dbgsetskipexceptions(skip);
}
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title)
{
return pluginmenuadd(hMenu, title);
}
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title)
{
return pluginmenuaddentry(hMenu, hEntry, title);
}
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu)
{
return pluginmenuaddseparator(hMenu);
}
PLUG_IMPEXP bool _plugin_menuclear(int hMenu)
{
return pluginmenuclear(hMenu);
}
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon)
{
pluginmenuseticon(hMenu, icon);
}
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon)
{
pluginmenuentryseticon(pluginHandle, hEntry, icon);
}
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript)
{
dbgstartscriptthread(cbScript);
}
PLUG_IMPEXP bool _plugin_waituntilpaused()
{
while(DbgIsDebugging() && dbgisrunning()) //wait until the debugger paused
Sleep(1);
return DbgIsDebugging();
/**
@file _plugins.cpp
@brief Implements the plugins class.
*/
#include "_plugins.h"
#include "plugin_loader.h"
#include "console.h"
#include "debugger.h"
#include "threading.h"
///debugger plugin exports (wrappers)
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
{
pluginregistercallback(pluginHandle, cbType, cbPlugin);
}
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType)
{
return pluginunregistercallback(pluginHandle, cbType);
}
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly)
{
return plugincmdregister(pluginHandle, command, cbCommand, debugonly);
}
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command)
{
return plugincmdunregister(pluginHandle, command);
}
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...)
{
va_list args;
va_start(args, format);
dprintf_args(format, args);
va_end(args);
}
PLUG_IMPEXP void _plugin_logputs(const char* text)
{
dputs(text);
}
PLUG_IMPEXP void _plugin_debugpause()
{
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
dbgsetskipexceptions(false);
wait(WAITID_RUN);
}
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip)
{
dbgsetskipexceptions(skip);
}
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title)
{
return pluginmenuadd(hMenu, title);
}
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title)
{
return pluginmenuaddentry(hMenu, hEntry, title);
}
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu)
{
return pluginmenuaddseparator(hMenu);
}
PLUG_IMPEXP bool _plugin_menuclear(int hMenu)
{
return pluginmenuclear(hMenu);
}
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon)
{
pluginmenuseticon(hMenu, icon);
}
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon)
{
pluginmenuentryseticon(pluginHandle, hEntry, icon);
}
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript)
{
dbgstartscriptthread(cbScript);
}
PLUG_IMPEXP bool _plugin_waituntilpaused()
{
while(DbgIsDebugging() && dbgisrunning()) //wait until the debugger paused
Sleep(1);
return DbgIsDebugging();
}

View File

@ -1,230 +1,230 @@
#ifndef _PLUGINS_H
#define _PLUGINS_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifndef PLUG_IMPEXP
#ifdef BUILD_DBG
#define PLUG_IMPEXP __declspec(dllexport)
#else
#define PLUG_IMPEXP __declspec(dllimport)
#endif //BUILD_DBG
#endif //PLUG_IMPEXP
#include "_plugin_types.h"
//default structure alignments forced
#ifdef _WIN64
#pragma pack(push, 16)
#else //x86
#pragma pack(push, 8)
#endif //_WIN64
//defines
#define PLUG_SDKVERSION 1
//structures
typedef struct
{
//provided by the debugger
int pluginHandle;
//provided by the pluginit function
int sdkVersion;
int pluginVersion;
char pluginName[256];
} PLUG_INITSTRUCT;
typedef struct
{
//provided by the debugger
HWND hwndDlg; //gui window handle
int hMenu; //plugin menu handle
int hMenuDisasm; //plugin disasm menu handle
int hMenuDump; //plugin dump menu handle
int hMenuStack; //plugin stack menu handle
} PLUG_SETUPSTRUCT;
typedef struct
{
void* data; //user data
} PLUG_SCRIPTSTRUCT;
//callback structures
typedef struct
{
const char* szFileName;
} PLUG_CB_INITDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_STOPDEBUG;
typedef struct
{
CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo;
IMAGEHLP_MODULE64* modInfo;
const char* DebugFileName;
PROCESS_INFORMATION* fdProcessInfo;
} PLUG_CB_CREATEPROCESS;
typedef struct
{
EXIT_PROCESS_DEBUG_INFO* ExitProcess;
} PLUG_CB_EXITPROCESS;
typedef struct
{
CREATE_THREAD_DEBUG_INFO* CreateThread;
DWORD dwThreadId;
} PLUG_CB_CREATETHREAD;
typedef struct
{
EXIT_THREAD_DEBUG_INFO* ExitThread;
DWORD dwThreadId;
} PLUG_CB_EXITTHREAD;
typedef struct
{
void* reserved;
} PLUG_CB_SYSTEMBREAKPOINT;
typedef struct
{
LOAD_DLL_DEBUG_INFO* LoadDll;
IMAGEHLP_MODULE64* modInfo;
const char* modname;
} PLUG_CB_LOADDLL;
typedef struct
{
UNLOAD_DLL_DEBUG_INFO* UnloadDll;
} PLUG_CB_UNLOADDLL;
typedef struct
{
OUTPUT_DEBUG_STRING_INFO* DebugString;
} PLUG_CB_OUTPUTDEBUGSTRING;
typedef struct
{
EXCEPTION_DEBUG_INFO* Exception;
} PLUG_CB_EXCEPTION;
typedef struct
{
BRIDGEBP* breakpoint;
} PLUG_CB_BREAKPOINT;
typedef struct
{
void* reserved;
} PLUG_CB_PAUSEDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_RESUMEDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_STEPPED;
typedef struct
{
DWORD dwProcessId;
} PLUG_CB_ATTACH;
typedef struct
{
PROCESS_INFORMATION* fdProcessInfo;
} PLUG_CB_DETACH;
typedef struct
{
DEBUG_EVENT* DebugEvent;
} PLUG_CB_DEBUGEVENT;
typedef struct
{
int hEntry;
} PLUG_CB_MENUENTRY;
typedef struct
{
MSG* message;
long* result;
bool retval;
} PLUG_CB_WINEVENT;
typedef struct
{
MSG* message;
bool retval;
} PLUG_CB_WINEVENTGLOBAL;
//enums
typedef enum
{
CB_INITDEBUG, //PLUG_CB_INITDEBUG
CB_STOPDEBUG, //PLUG_CB_STOPDEBUG
CB_CREATEPROCESS, //PLUG_CB_CREATEPROCESS
CB_EXITPROCESS, //PLUG_CB_EXITPROCESS
CB_CREATETHREAD, //PLUG_CB_CREATETHREAD
CB_EXITTHREAD, //PLUG_CB_EXITTHREAD
CB_SYSTEMBREAKPOINT, //PLUG_CB_SYSTEMBREAKPOINT
CB_LOADDLL, //PLUG_CB_LOADDLL
CB_UNLOADDLL, //PLUG_CB_UNLOADDLL
CB_OUTPUTDEBUGSTRING, //PLUG_CB_OUTPUTDEBUGSTRING
CB_EXCEPTION, //PLUG_CB_EXCEPTION
CB_BREAKPOINT, //PLUG_CB_BREAKPOINT
CB_PAUSEDEBUG, //PLUG_CB_PAUSEDEBUG
CB_RESUMEDEBUG, //PLUG_CB_RESUMEDEBUG
CB_STEPPED, //PLUG_CB_STEPPED
CB_ATTACH, //PLUG_CB_ATTACHED (before attaching, after CB_INITDEBUG)
CB_DETACH, //PLUG_CB_DETACH (before detaching, before CB_STOPDEBUG)
CB_DEBUGEVENT, //PLUG_CB_DEBUGEVENT (called on any debug event)
CB_MENUENTRY, //PLUG_CB_MENUENTRY
CB_WINEVENT, //PLUG_CB_WINEVENT
CB_WINEVENTGLOBAL //PLUG_CB_WINEVENTGLOBAL
} CBTYPE;
//typedefs
typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo);
typedef bool (*CBPLUGINCOMMAND)(int, char**);
typedef void (*CBPLUGINSCRIPT)();
//exports
#ifdef __cplusplus
extern "C"
{
#endif
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin);
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType);
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly);
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command);
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...);
PLUG_IMPEXP void _plugin_logputs(const char* text);
PLUG_IMPEXP void _plugin_debugpause();
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip);
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title);
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title);
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu);
PLUG_IMPEXP bool _plugin_menuclear(int hMenu);
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon);
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon);
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript);
PLUG_IMPEXP bool _plugin_waituntilpaused();
#ifdef __cplusplus
}
#endif
#pragma pack(pop)
#endif // _PLUGINS_H
#ifndef _PLUGINS_H
#define _PLUGINS_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifndef PLUG_IMPEXP
#ifdef BUILD_DBG
#define PLUG_IMPEXP __declspec(dllexport)
#else
#define PLUG_IMPEXP __declspec(dllimport)
#endif //BUILD_DBG
#endif //PLUG_IMPEXP
#include "_plugin_types.h"
//default structure alignments forced
#ifdef _WIN64
#pragma pack(push, 16)
#else //x86
#pragma pack(push, 8)
#endif //_WIN64
//defines
#define PLUG_SDKVERSION 1
//structures
typedef struct
{
//provided by the debugger
int pluginHandle;
//provided by the pluginit function
int sdkVersion;
int pluginVersion;
char pluginName[256];
} PLUG_INITSTRUCT;
typedef struct
{
//provided by the debugger
HWND hwndDlg; //gui window handle
int hMenu; //plugin menu handle
int hMenuDisasm; //plugin disasm menu handle
int hMenuDump; //plugin dump menu handle
int hMenuStack; //plugin stack menu handle
} PLUG_SETUPSTRUCT;
typedef struct
{
void* data; //user data
} PLUG_SCRIPTSTRUCT;
//callback structures
typedef struct
{
const char* szFileName;
} PLUG_CB_INITDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_STOPDEBUG;
typedef struct
{
CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo;
IMAGEHLP_MODULE64* modInfo;
const char* DebugFileName;
PROCESS_INFORMATION* fdProcessInfo;
} PLUG_CB_CREATEPROCESS;
typedef struct
{
EXIT_PROCESS_DEBUG_INFO* ExitProcess;
} PLUG_CB_EXITPROCESS;
typedef struct
{
CREATE_THREAD_DEBUG_INFO* CreateThread;
DWORD dwThreadId;
} PLUG_CB_CREATETHREAD;
typedef struct
{
EXIT_THREAD_DEBUG_INFO* ExitThread;
DWORD dwThreadId;
} PLUG_CB_EXITTHREAD;
typedef struct
{
void* reserved;
} PLUG_CB_SYSTEMBREAKPOINT;
typedef struct
{
LOAD_DLL_DEBUG_INFO* LoadDll;
IMAGEHLP_MODULE64* modInfo;
const char* modname;
} PLUG_CB_LOADDLL;
typedef struct
{
UNLOAD_DLL_DEBUG_INFO* UnloadDll;
} PLUG_CB_UNLOADDLL;
typedef struct
{
OUTPUT_DEBUG_STRING_INFO* DebugString;
} PLUG_CB_OUTPUTDEBUGSTRING;
typedef struct
{
EXCEPTION_DEBUG_INFO* Exception;
} PLUG_CB_EXCEPTION;
typedef struct
{
BRIDGEBP* breakpoint;
} PLUG_CB_BREAKPOINT;
typedef struct
{
void* reserved;
} PLUG_CB_PAUSEDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_RESUMEDEBUG;
typedef struct
{
void* reserved;
} PLUG_CB_STEPPED;
typedef struct
{
DWORD dwProcessId;
} PLUG_CB_ATTACH;
typedef struct
{
PROCESS_INFORMATION* fdProcessInfo;
} PLUG_CB_DETACH;
typedef struct
{
DEBUG_EVENT* DebugEvent;
} PLUG_CB_DEBUGEVENT;
typedef struct
{
int hEntry;
} PLUG_CB_MENUENTRY;
typedef struct
{
MSG* message;
long* result;
bool retval;
} PLUG_CB_WINEVENT;
typedef struct
{
MSG* message;
bool retval;
} PLUG_CB_WINEVENTGLOBAL;
//enums
typedef enum
{
CB_INITDEBUG, //PLUG_CB_INITDEBUG
CB_STOPDEBUG, //PLUG_CB_STOPDEBUG
CB_CREATEPROCESS, //PLUG_CB_CREATEPROCESS
CB_EXITPROCESS, //PLUG_CB_EXITPROCESS
CB_CREATETHREAD, //PLUG_CB_CREATETHREAD
CB_EXITTHREAD, //PLUG_CB_EXITTHREAD
CB_SYSTEMBREAKPOINT, //PLUG_CB_SYSTEMBREAKPOINT
CB_LOADDLL, //PLUG_CB_LOADDLL
CB_UNLOADDLL, //PLUG_CB_UNLOADDLL
CB_OUTPUTDEBUGSTRING, //PLUG_CB_OUTPUTDEBUGSTRING
CB_EXCEPTION, //PLUG_CB_EXCEPTION
CB_BREAKPOINT, //PLUG_CB_BREAKPOINT
CB_PAUSEDEBUG, //PLUG_CB_PAUSEDEBUG
CB_RESUMEDEBUG, //PLUG_CB_RESUMEDEBUG
CB_STEPPED, //PLUG_CB_STEPPED
CB_ATTACH, //PLUG_CB_ATTACHED (before attaching, after CB_INITDEBUG)
CB_DETACH, //PLUG_CB_DETACH (before detaching, before CB_STOPDEBUG)
CB_DEBUGEVENT, //PLUG_CB_DEBUGEVENT (called on any debug event)
CB_MENUENTRY, //PLUG_CB_MENUENTRY
CB_WINEVENT, //PLUG_CB_WINEVENT
CB_WINEVENTGLOBAL //PLUG_CB_WINEVENTGLOBAL
} CBTYPE;
//typedefs
typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo);
typedef bool (*CBPLUGINCOMMAND)(int, char**);
typedef void (*CBPLUGINSCRIPT)();
//exports
#ifdef __cplusplus
extern "C"
{
#endif
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin);
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType);
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly);
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command);
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...);
PLUG_IMPEXP void _plugin_logputs(const char* text);
PLUG_IMPEXP void _plugin_debugpause();
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip);
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title);
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title);
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu);
PLUG_IMPEXP bool _plugin_menuclear(int hMenu);
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon);
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon);
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript);
PLUG_IMPEXP bool _plugin_waituntilpaused();
#ifdef __cplusplus
}
#endif
#pragma pack(pop)
#endif // _PLUGINS_H

View File

@ -1,8 +1,8 @@
#ifndef _SCRIPT_API_H
#define _SCRIPT_API_H
#include "_plugins.h"
#define SCRIPT_EXPORT PLUG_IMPEXP
#ifndef _SCRIPT_API_H
#define _SCRIPT_API_H
#include "_plugins.h"
#define SCRIPT_EXPORT PLUG_IMPEXP
#endif //_SCRIPT_API_H

View File

@ -1,22 +1,22 @@
#include "_scriptapi_assembler.h"
#include "assemble.h"
SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction)
{
return assemble(addr, dest, size, instruction, nullptr);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error)
{
return assemble(addr, dest, size, instruction, error);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction)
{
return assembleat(addr, instruction, nullptr, nullptr, false);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop)
{
return assembleat(addr, instruction, size, error, fillnop);
#include "_scriptapi_assembler.h"
#include "assemble.h"
SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction)
{
return assemble(addr, dest, size, instruction, nullptr);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error)
{
return assemble(addr, dest, size, instruction, error);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction)
{
return assembleat(addr, instruction, nullptr, nullptr, false);
}
SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop)
{
return assembleat(addr, instruction, size, error, fillnop);
}

View File

@ -1,17 +1,17 @@
#ifndef _SCRIPTAPI_ASSEMBLER_H
#define _SCRIPTAPI_ASSEMBLER_H
#include "_scriptapi.h"
namespace Script
{
namespace Assembler
{
SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16]
SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE]
SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction);
SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE]
}; //Assembler
}; //Script
#ifndef _SCRIPTAPI_ASSEMBLER_H
#define _SCRIPTAPI_ASSEMBLER_H
#include "_scriptapi.h"
namespace Script
{
namespace Assembler
{
SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16]
SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE]
SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction);
SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE]
}; //Assembler
}; //Script
#endif //_SCRIPTAPI_ASSEMBLER_H

View File

@ -1,71 +1,71 @@
#include "_scriptapi_debug.h"
SCRIPT_EXPORT void Script::Debug::Wait()
{
_plugin_waituntilpaused();
}
SCRIPT_EXPORT void Script::Debug::Run()
{
DbgCmdExecDirect("run");
Wait();
}
SCRIPT_EXPORT void Script::Debug::Pause()
{
DbgCmdExecDirect("pause");
Wait();
}
SCRIPT_EXPORT void Script::Debug::Stop()
{
DbgCmdExecDirect("StopDebug");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepIn()
{
DbgCmdExecDirect("StepInto");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepOver()
{
DbgCmdExecDirect("StepOver");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepOut()
{
DbgCmdExecDirect("StepOut");
Wait();
}
SCRIPT_EXPORT bool Script::Debug::SetBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bp %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::DeleteBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bc %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::SetHardwareBreakpoint(duint address, HardwareType type)
{
char command[128] = "";
const char* types[] = { "rw", "w", "x" };
sprintf_s(command, "bphws %p, %s", address, types[type]);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::DeleteHardwareBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bphwc %p", address);
return DbgCmdExecDirect(command);
#include "_scriptapi_debug.h"
SCRIPT_EXPORT void Script::Debug::Wait()
{
_plugin_waituntilpaused();
}
SCRIPT_EXPORT void Script::Debug::Run()
{
DbgCmdExecDirect("run");
Wait();
}
SCRIPT_EXPORT void Script::Debug::Pause()
{
DbgCmdExecDirect("pause");
Wait();
}
SCRIPT_EXPORT void Script::Debug::Stop()
{
DbgCmdExecDirect("StopDebug");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepIn()
{
DbgCmdExecDirect("StepInto");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepOver()
{
DbgCmdExecDirect("StepOver");
Wait();
}
SCRIPT_EXPORT void Script::Debug::StepOut()
{
DbgCmdExecDirect("StepOut");
Wait();
}
SCRIPT_EXPORT bool Script::Debug::SetBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bp %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::DeleteBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bc %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::SetHardwareBreakpoint(duint address, HardwareType type)
{
char command[128] = "";
const char* types[] = { "rw", "w", "x" };
sprintf_s(command, "bphws %p, %s", address, types[type]);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::DeleteHardwareBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bphwc %p", address);
return DbgCmdExecDirect(command);
}

View File

@ -1,31 +1,31 @@
#ifndef _SCRIPTAPI_DEBUG_H
#define _SCRIPTAPI_DEBUG_H
#include "_scriptapi.h"
namespace Script
{
namespace Debug
{
enum HardwareType
{
HardwareAccess,
HardwareWrite,
HardwareExecute
};
SCRIPT_EXPORT void Wait();
SCRIPT_EXPORT void Run();
SCRIPT_EXPORT void Pause();
SCRIPT_EXPORT void Stop();
SCRIPT_EXPORT void StepIn();
SCRIPT_EXPORT void StepOver();
SCRIPT_EXPORT void StepOut();
SCRIPT_EXPORT bool SetBreakpoint(duint address);
SCRIPT_EXPORT bool DeleteBreakpoint(duint address);
SCRIPT_EXPORT bool SetHardwareBreakpoint(duint address, HardwareType type = HardwareExecute);
SCRIPT_EXPORT bool DeleteHardwareBreakpoint(duint address);
}; //Debug
}; //Script
#ifndef _SCRIPTAPI_DEBUG_H
#define _SCRIPTAPI_DEBUG_H
#include "_scriptapi.h"
namespace Script
{
namespace Debug
{
enum HardwareType
{
HardwareAccess,
HardwareWrite,
HardwareExecute
};
SCRIPT_EXPORT void Wait();
SCRIPT_EXPORT void Run();
SCRIPT_EXPORT void Pause();
SCRIPT_EXPORT void Stop();
SCRIPT_EXPORT void StepIn();
SCRIPT_EXPORT void StepOver();
SCRIPT_EXPORT void StepOut();
SCRIPT_EXPORT bool SetBreakpoint(duint address);
SCRIPT_EXPORT bool DeleteBreakpoint(duint address);
SCRIPT_EXPORT bool SetHardwareBreakpoint(duint address, HardwareType type = HardwareExecute);
SCRIPT_EXPORT bool DeleteHardwareBreakpoint(duint address);
}; //Debug
}; //Script
#endif //_SCRIPTAPI_DEBUG_H

View File

@ -1,116 +1,116 @@
#include "_scriptapi_flag.h"
#include "value.h"
static const char* flagTable[] =
{
"ZF",
"OF",
"CF",
"PF",
"SF",
"TF",
"AF",
"DF",
"IF"
};
SCRIPT_EXPORT bool Script::Flag::Get(FlagEnum flag)
{
duint value;
return valfromstring(flagTable[flag], &value) ? !!value : false;
}
SCRIPT_EXPORT bool Script::Flag::Set(FlagEnum flag, bool value)
{
return setflag(flagTable[flag], value);
}
SCRIPT_EXPORT bool Script::Flag::GetZF()
{
return Get(ZF);
}
SCRIPT_EXPORT bool Script::Flag::SetZF(bool value)
{
return Set(ZF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetOF()
{
return Get(OF);
}
SCRIPT_EXPORT bool Script::Flag::SetOF(bool value)
{
return Set(OF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetCF()
{
return Get(CF);
}
SCRIPT_EXPORT bool Script::Flag::SetCF(bool value)
{
return Set(CF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetPF()
{
return Get(PF);
}
SCRIPT_EXPORT bool Script::Flag::SetPF(bool value)
{
return Set(PF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetSF()
{
return Get(SF);
}
SCRIPT_EXPORT bool Script::Flag::SetSF(bool value)
{
return Set(SF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetTF()
{
return Get(TF);
}
SCRIPT_EXPORT bool Script::Flag::SetTF(bool value)
{
return Set(TF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetAF()
{
return Get(AF);
}
SCRIPT_EXPORT bool Script::Flag::SetAF(bool value)
{
return Set(AF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetDF()
{
return Get(DF);
}
SCRIPT_EXPORT bool Script::Flag::SetDF(bool value)
{
return Set(DF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetIF()
{
return Get(IF);
}
SCRIPT_EXPORT bool Script::Flag::SetIF(bool value)
{
return Set(IF, value);
#include "_scriptapi_flag.h"
#include "value.h"
static const char* flagTable[] =
{
"ZF",
"OF",
"CF",
"PF",
"SF",
"TF",
"AF",
"DF",
"IF"
};
SCRIPT_EXPORT bool Script::Flag::Get(FlagEnum flag)
{
duint value;
return valfromstring(flagTable[flag], &value) ? !!value : false;
}
SCRIPT_EXPORT bool Script::Flag::Set(FlagEnum flag, bool value)
{
return setflag(flagTable[flag], value);
}
SCRIPT_EXPORT bool Script::Flag::GetZF()
{
return Get(ZF);
}
SCRIPT_EXPORT bool Script::Flag::SetZF(bool value)
{
return Set(ZF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetOF()
{
return Get(OF);
}
SCRIPT_EXPORT bool Script::Flag::SetOF(bool value)
{
return Set(OF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetCF()
{
return Get(CF);
}
SCRIPT_EXPORT bool Script::Flag::SetCF(bool value)
{
return Set(CF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetPF()
{
return Get(PF);
}
SCRIPT_EXPORT bool Script::Flag::SetPF(bool value)
{
return Set(PF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetSF()
{
return Get(SF);
}
SCRIPT_EXPORT bool Script::Flag::SetSF(bool value)
{
return Set(SF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetTF()
{
return Get(TF);
}
SCRIPT_EXPORT bool Script::Flag::SetTF(bool value)
{
return Set(TF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetAF()
{
return Get(AF);
}
SCRIPT_EXPORT bool Script::Flag::SetAF(bool value)
{
return Set(AF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetDF()
{
return Get(DF);
}
SCRIPT_EXPORT bool Script::Flag::SetDF(bool value)
{
return Set(DF, value);
}
SCRIPT_EXPORT bool Script::Flag::GetIF()
{
return Get(IF);
}
SCRIPT_EXPORT bool Script::Flag::SetIF(bool value)
{
return Set(IF, value);
}

View File

@ -1,47 +1,47 @@
#ifndef _SCRIPTAPI_FLAG_H
#define _SCRIPTAPI_FLAG_H
#include "_scriptapi.h"
namespace Script
{
namespace Flag
{
enum FlagEnum
{
ZF,
OF,
CF,
PF,
SF,
TF,
AF,
DF,
IF
};
SCRIPT_EXPORT bool Get(FlagEnum flag);
SCRIPT_EXPORT bool Set(FlagEnum flag, bool value);
SCRIPT_EXPORT bool GetZF();
SCRIPT_EXPORT bool SetZF(bool value);
SCRIPT_EXPORT bool GetOF();
SCRIPT_EXPORT bool SetOF(bool value);
SCRIPT_EXPORT bool GetCF();
SCRIPT_EXPORT bool SetCF(bool value);
SCRIPT_EXPORT bool GetPF();
SCRIPT_EXPORT bool SetPF(bool value);
SCRIPT_EXPORT bool GetSF();
SCRIPT_EXPORT bool SetSF(bool value);
SCRIPT_EXPORT bool GetTF();
SCRIPT_EXPORT bool SetTF(bool value);
SCRIPT_EXPORT bool GetAF();
SCRIPT_EXPORT bool SetAF(bool value);
SCRIPT_EXPORT bool GetDF();
SCRIPT_EXPORT bool SetDF(bool value);
SCRIPT_EXPORT bool GetIF();
SCRIPT_EXPORT bool SetIF(bool value);
};
};
#ifndef _SCRIPTAPI_FLAG_H
#define _SCRIPTAPI_FLAG_H
#include "_scriptapi.h"
namespace Script
{
namespace Flag
{
enum FlagEnum
{
ZF,
OF,
CF,
PF,
SF,
TF,
AF,
DF,
IF
};
SCRIPT_EXPORT bool Get(FlagEnum flag);
SCRIPT_EXPORT bool Set(FlagEnum flag, bool value);
SCRIPT_EXPORT bool GetZF();
SCRIPT_EXPORT bool SetZF(bool value);
SCRIPT_EXPORT bool GetOF();
SCRIPT_EXPORT bool SetOF(bool value);
SCRIPT_EXPORT bool GetCF();
SCRIPT_EXPORT bool SetCF(bool value);
SCRIPT_EXPORT bool GetPF();
SCRIPT_EXPORT bool SetPF(bool value);
SCRIPT_EXPORT bool GetSF();
SCRIPT_EXPORT bool SetSF(bool value);
SCRIPT_EXPORT bool GetTF();
SCRIPT_EXPORT bool SetTF(bool value);
SCRIPT_EXPORT bool GetAF();
SCRIPT_EXPORT bool SetAF(bool value);
SCRIPT_EXPORT bool GetDF();
SCRIPT_EXPORT bool SetDF(bool value);
SCRIPT_EXPORT bool GetIF();
SCRIPT_EXPORT bool SetIF(bool value);
};
};
#endif //_SCRIPTAPI_FLAG_H

View File

@ -1,152 +1,152 @@
#include "_scriptapi_gui.h"
#include "_scriptapi_misc.h"
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(DisassemblyWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(DisassemblyWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetStart()
{
return Gui::SelectionGetStart(DisassemblyWindow);
}
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetEnd()
{
return Gui::SelectionGetEnd(DisassemblyWindow);
}
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(DumpWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(DumpWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetStart()
{
return Gui::SelectionGetStart(DumpWindow);
}
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetEnd()
{
return Gui::SelectionGetEnd(DumpWindow);
}
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(StackWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(StackWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetStart()
{
return Gui::SelectionGetStart(StackWindow);
}
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd()
{
return Gui::SelectionGetEnd(StackWindow);
}
static inline int windowToBridge(Script::Gui::Window window)
{
switch(window)
{
case Script::Gui::DisassemblyWindow:
return GUI_DISASSEMBLY;
case Script::Gui::DumpWindow:
return GUI_DUMP;
case Script::Gui::StackWindow:
return GUI_STACK;
default:
return GUI_DISASSEMBLY;
}
}
SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end)
{
SELECTIONDATA selection;
if(!GuiSelectionGet(windowToBridge(window), &selection))
return false;
if(start)
*start = selection.start;
if(end)
*end = selection.end;
return true;
}
SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end)
{
SELECTIONDATA selection;
selection.start = start;
selection.end = end;
return GuiSelectionSet(windowToBridge(window), &selection);
}
SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window)
{
duint start;
return Gui::SelectionGet(window, &start, nullptr) ? start : 0;
}
SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window)
{
duint end;
return Gui::SelectionGet(window, nullptr, &end) ? end : 0;
}
SCRIPT_EXPORT void Script::Gui::Message(const char* message)
{
GuiScriptMessage(message);
}
SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message)
{
return !!GuiScriptMsgyn(message);
}
SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text)
{
return GuiGetLineWindow(title, text);
}
SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value)
{
Memory<char*> line(GUI_MAX_LINE_SIZE);
if(!GuiGetLineWindow(title, line()))
return false;
return Misc::ParseExpression(line(), value);
}
SCRIPT_EXPORT void Script::Gui::Refresh()
{
GuiUpdateAllViews();
}
SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget)
{
GuiAddQWidgetTab(qWidget);
}
SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget)
{
GuiShowQWidgetTab(qWidget);
}
SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget)
{
GuiCloseQWidgetTab(qWidget);
#include "_scriptapi_gui.h"
#include "_scriptapi_misc.h"
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(DisassemblyWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(DisassemblyWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetStart()
{
return Gui::SelectionGetStart(DisassemblyWindow);
}
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetEnd()
{
return Gui::SelectionGetEnd(DisassemblyWindow);
}
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(DumpWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(DumpWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetStart()
{
return Gui::SelectionGetStart(DumpWindow);
}
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetEnd()
{
return Gui::SelectionGetEnd(DumpWindow);
}
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionGet(duint* start, duint* end)
{
return Gui::SelectionGet(StackWindow, start, end);
}
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionSet(duint start, duint end)
{
return Gui::SelectionSet(StackWindow, start, end);
}
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetStart()
{
return Gui::SelectionGetStart(StackWindow);
}
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd()
{
return Gui::SelectionGetEnd(StackWindow);
}
static inline int windowToBridge(Script::Gui::Window window)
{
switch(window)
{
case Script::Gui::DisassemblyWindow:
return GUI_DISASSEMBLY;
case Script::Gui::DumpWindow:
return GUI_DUMP;
case Script::Gui::StackWindow:
return GUI_STACK;
default:
return GUI_DISASSEMBLY;
}
}
SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end)
{
SELECTIONDATA selection;
if(!GuiSelectionGet(windowToBridge(window), &selection))
return false;
if(start)
*start = selection.start;
if(end)
*end = selection.end;
return true;
}
SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end)
{
SELECTIONDATA selection;
selection.start = start;
selection.end = end;
return GuiSelectionSet(windowToBridge(window), &selection);
}
SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window)
{
duint start;
return Gui::SelectionGet(window, &start, nullptr) ? start : 0;
}
SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window)
{
duint end;
return Gui::SelectionGet(window, nullptr, &end) ? end : 0;
}
SCRIPT_EXPORT void Script::Gui::Message(const char* message)
{
GuiScriptMessage(message);
}
SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message)
{
return !!GuiScriptMsgyn(message);
}
SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text)
{
return GuiGetLineWindow(title, text);
}
SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value)
{
Memory<char*> line(GUI_MAX_LINE_SIZE);
if(!GuiGetLineWindow(title, line()))
return false;
return Misc::ParseExpression(line(), value);
}
SCRIPT_EXPORT void Script::Gui::Refresh()
{
GuiUpdateAllViews();
}
SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget)
{
GuiAddQWidgetTab(qWidget);
}
SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget)
{
GuiShowQWidgetTab(qWidget);
}
SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget)
{
GuiCloseQWidgetTab(qWidget);
}

View File

@ -1,60 +1,60 @@
#ifndef _SCRIPTAPI_GUI_H
#define _SCRIPTAPI_GUI_H
#include "_scriptapi.h"
namespace Script
{
namespace Gui
{
namespace Disassembly
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Disassembly
namespace Dump
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Dump
namespace Stack
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Stack
}; //Gui
namespace Gui
{
enum Window
{
DisassemblyWindow,
DumpWindow,
StackWindow
};
SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart(Window window);
SCRIPT_EXPORT duint SelectionGetEnd(Window window);
SCRIPT_EXPORT void Message(const char* message);
SCRIPT_EXPORT bool MessageYesNo(const char* message);
SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE]
SCRIPT_EXPORT bool InputValue(const char* title, duint* value);
SCRIPT_EXPORT void Refresh();
SCRIPT_EXPORT void AddQWidgetTab(void* qWidget);
SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget);
SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget);
}; //Gui
}; //Script
#ifndef _SCRIPTAPI_GUI_H
#define _SCRIPTAPI_GUI_H
#include "_scriptapi.h"
namespace Script
{
namespace Gui
{
namespace Disassembly
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Disassembly
namespace Dump
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Dump
namespace Stack
{
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart();
SCRIPT_EXPORT duint SelectionGetEnd();
}; //Stack
}; //Gui
namespace Gui
{
enum Window
{
DisassemblyWindow,
DumpWindow,
StackWindow
};
SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end);
SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end);
SCRIPT_EXPORT duint SelectionGetStart(Window window);
SCRIPT_EXPORT duint SelectionGetEnd(Window window);
SCRIPT_EXPORT void Message(const char* message);
SCRIPT_EXPORT bool MessageYesNo(const char* message);
SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE]
SCRIPT_EXPORT bool InputValue(const char* title, duint* value);
SCRIPT_EXPORT void Refresh();
SCRIPT_EXPORT void AddQWidgetTab(void* qWidget);
SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget);
SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget);
}; //Gui
}; //Script
#endif //_SCRIPTAPI_GUI_H

View File

@ -1,87 +1,87 @@
#include "_scriptapi_memory.h"
#include "memory.h"
SCRIPT_EXPORT bool Script::Memory::Read(duint addr, void* data, duint size, duint* sizeRead)
{
return MemRead(addr, data, size, sizeRead);
}
SCRIPT_EXPORT bool Script::Memory::Write(duint addr, const void* data, duint size, duint* sizeWritten)
{
return MemWrite(addr, (void*)data, size, sizeWritten);
}
SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr)
{
return MemIsValidReadPtr(addr);
}
SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size)
{
return (duint)MemAllocRemote(addr, size);
}
SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr)
{
return MemFreeRemote(addr);
}
SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr)
{
unsigned char data;
Read(addr, &data, sizeof(data), nullptr);
return data;
}
SCRIPT_EXPORT bool Script::Memory::WriteByte(duint addr, unsigned char data)
{
return Write(addr, &data, sizeof(data), nullptr);
}
SCRIPT_EXPORT unsigned short Script::Memory::ReadWord(duint addr)