1
0
Fork 0
This commit is contained in:
Nukem 2015-07-13 17:16:06 -04:00
commit 6dfcfd99e7
51 changed files with 1075 additions and 967 deletions

View File

@ -16,7 +16,7 @@ AnalysisPass::AnalysisPass(uint VirtualStart, uint VirtualEnd, BBlockArray & Mai
m_DataSize = VirtualEnd - VirtualStart;
m_Data = (unsigned char*)BridgeAlloc(m_DataSize);
if(!MemRead(VirtualStart, m_Data, m_DataSize, nullptr))
if(!MemRead(VirtualStart, m_Data, m_DataSize))
{
BridgeFree(m_Data);
assert(false);

View File

@ -50,7 +50,7 @@ FunctionPass::FunctionPass(uint VirtualStart, uint VirtualEnd, BBlockArray & Mai
m_FunctionInfo = BridgeAlloc(m_FunctionInfoSize);
if(m_FunctionInfo)
MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize, nullptr);
MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize);
}
}
}
@ -98,6 +98,8 @@ bool FunctionPass::Analyse()
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)
{
@ -130,7 +132,7 @@ void FunctionPass::AnalysisWorker(uint Start, uint End, std::vector<FunctionDef>
if(blockItr->GetFlag(BASIC_BLOCK_FLAG_INDIRPTR))
{
// Read it from memory
if(!MemRead(destination, &destination, sizeof(uint), nullptr))
if(!MemRead(destination, &destination, sizeof(uint)))
continue;
// Validity check
@ -168,6 +170,7 @@ void FunctionPass::AnalysisWorker(uint Start, uint End, std::vector<FunctionDef>
void FunctionPass::FindFunctionWorkerPrepass(uint Start, uint End, std::vector<FunctionDef>* Blocks)
{
return;
const uint minFunc = std::next(m_MainBlocks.begin(), Start)->VirtualStart;
const uint maxFunc = std::next(m_MainBlocks.begin(), End - 1)->VirtualEnd;

View File

@ -41,7 +41,7 @@ extern "C" DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint s
extern "C" DLL_EXPORT bool _dbg_memwrite(duint addr, const unsigned char* src, duint size, duint* written)
{
return MemWrite(addr, (void*)src, size, written);
return MemWrite(addr, src, size, written);
}
extern "C" DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap)
@ -134,7 +134,7 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR
if(disasmfast(addr, &basicinfo) && basicinfo.branch && !basicinfo.call && basicinfo.memory.value) //thing is a JMP
{
uint val = 0;
if(MemRead(basicinfo.memory.value, &val, sizeof(val), 0))
if(MemRead(basicinfo.memory.value, &val, sizeof(val)))
{
if(SafeSymFromAddr(fdProcessInfo->hProcess, (DWORD64)val, &displacement, pSymbol) && !displacement)
{
@ -785,6 +785,8 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
entry = strtok(0, ",");
}
}
BridgeSettingGet("Symbols", "CachePath", szSymbolCachePath);
}
break;

View File

@ -18,7 +18,7 @@ SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr)
SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size)
{
return (duint)MemAllocRemote(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
return (duint)MemAllocRemote(addr, size);
}
SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr)

View File

@ -10,7 +10,7 @@ SCRIPT_EXPORT duint Script::Pattern::Find(unsigned char* data, duint datasize, c
SCRIPT_EXPORT duint Script::Pattern::FindMem(duint start, duint size, const char* pattern)
{
Memory<unsigned char*> data(size, "Script::Pattern::FindMem::data");
if(!MemRead(start, data(), size, nullptr))
if(!MemRead(start, data(), size))
return -1;
return Pattern::Find(data(), data.size(), pattern) + start;
}
@ -23,10 +23,10 @@ SCRIPT_EXPORT void Script::Pattern::Write(unsigned char* data, duint datasize, c
SCRIPT_EXPORT void Script::Pattern::WriteMem(duint start, duint size, const char* pattern)
{
Memory<unsigned char*> data(size, "Script::Pattern::WriteMem::data");
if(!MemRead(start, data(), data.size(), nullptr))
if(!MemRead(start, data(), data.size()))
return;
patternwrite(data(), data.size(), pattern);
MemWrite(start, data(), data.size(), nullptr);
MemWrite(start, data(), data.size());
}
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplace(unsigned char* data, duint datasize, const char* searchpattern, const char* replacepattern)
@ -37,12 +37,12 @@ SCRIPT_EXPORT bool Script::Pattern::SearchAndReplace(unsigned char* data, duint
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplaceMem(duint start, duint size, const char* searchpattern, const char* replacepattern)
{
Memory<unsigned char*> data(size, "Script::Pattern::SearchAndReplaceMem::data");
if(!MemRead(start, data(), size, nullptr))
if(!MemRead(start, data(), size))
return false;
duint found = patternfind(data(), data.size(), searchpattern);
if(found == -1)
return false;
patternwrite(data() + found, data.size() - found, replacepattern);
MemWrite((start + found), data() + found, data.size() - found, nullptr);
MemWrite((start + found), data() + found, data.size() - found);
return true;
}

View File

@ -154,14 +154,14 @@ bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi));
uint size = mbi.RegionSize;
Memory<void*> buffer(size, "apienumexports:buffer");
if(!MemRead(base, buffer(), size, 0))
if(!MemRead(base, buffer(), size))
return false;
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)((uint)buffer() + GetPE32DataFromMappedFile((ULONG_PTR)buffer(), 0, UE_PE_OFFSET));
uint export_dir_rva = pnth->OptionalHeader.DataDirectory[0].VirtualAddress;
uint export_dir_size = pnth->OptionalHeader.DataDirectory[0].Size;
IMAGE_EXPORT_DIRECTORY export_dir;
memset(&export_dir, 0, sizeof(export_dir));
MemRead((export_dir_rva + base), &export_dir, sizeof(export_dir), 0);
MemRead((export_dir_rva + base), &export_dir, sizeof(export_dir));
unsigned int NumberOfNames = export_dir.NumberOfNames;
if(!export_dir.NumberOfFunctions || !NumberOfNames) //no named exports
return false;
@ -170,28 +170,28 @@ bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
uint original_name_va = export_dir.Name + base;
char original_name[deflen] = "";
memset(original_name, 0, sizeof(original_name));
MemRead(original_name_va, original_name, deflen, 0);
MemRead(original_name_va, original_name, deflen);
char* AddrOfFunctions_va = (char*)(export_dir.AddressOfFunctions + base); //not a valid local pointer
char* AddrOfNames_va = (char*)(export_dir.AddressOfNames + base); //not a valid local pointer
char* AddrOfNameOrdinals_va = (char*)(export_dir.AddressOfNameOrdinals + base); //not a valid local pointer
for(DWORD i = 0; i < NumberOfNames; i++)
{
DWORD curAddrOfName = 0;
MemRead((uint)(AddrOfNames_va + sizeof(DWORD)*i), &curAddrOfName, sizeof(DWORD), 0);
MemRead((uint)(AddrOfNames_va + sizeof(DWORD)*i), &curAddrOfName, sizeof(DWORD));
char* cur_name_va = (char*)(curAddrOfName + base);
char cur_name[deflen] = "";
memset(cur_name, 0, deflen);
MemRead((uint)cur_name_va, cur_name, deflen, 0);
MemRead((uint)cur_name_va, cur_name, deflen);
WORD curAddrOfNameOrdinals = 0;
MemRead((uint)(AddrOfNameOrdinals_va + sizeof(WORD)*i), &curAddrOfNameOrdinals, sizeof(WORD), 0);
MemRead((uint)(AddrOfNameOrdinals_va + sizeof(WORD)*i), &curAddrOfNameOrdinals, sizeof(WORD));
DWORD curFunctionRva = 0;
MemRead((uint)(AddrOfFunctions_va + sizeof(DWORD)*curAddrOfNameOrdinals), &curFunctionRva, sizeof(DWORD), 0);
MemRead((uint)(AddrOfFunctions_va + sizeof(DWORD)*curAddrOfNameOrdinals), &curFunctionRva, sizeof(DWORD));
if(curFunctionRva >= export_dir_rva && curFunctionRva < export_dir_rva + export_dir_size)
{
char forwarded_api[deflen] = "";
memset(forwarded_api, 0, deflen);
MemRead((curFunctionRva + base), forwarded_api, deflen, 0);
MemRead((curFunctionRva + base), forwarded_api, deflen);
int len = (int)strlen(forwarded_api);
int j = 0;
while(forwarded_api[j] != '.' && j < len)

View File

@ -6,7 +6,7 @@ Analysis::Analysis(uint base, uint size)
_base = base;
_size = size;
_data = new unsigned char[_size + MAX_DISASM_BUFFER];
MemRead(_base, _data, _size, 0);
MemRead(_base, _data, _size);
}
Analysis::~Analysis()

View File

@ -9,7 +9,7 @@ class Analysis
public:
explicit Analysis(uint base, uint size);
Analysis(const Analysis & that) = delete;
~Analysis();
virtual ~Analysis();
virtual void Analyse() = 0;
virtual void SetMarkers() = 0;

View File

@ -67,12 +67,12 @@ bool assembleat(uint addr, const char* instruction, int* size, char* error, bool
if(size)
*size = destSize;
bool ret = MemPatch(addr, dest, destSize, 0);
bool ret = MemPatch(addr, dest, destSize);
if(ret && fillnop && nopsize)
{
if(size)
*size += nopsize;
if(!MemPatch((addr + destSize), nops, nopsize, 0))
if(!MemPatch((addr + destSize), nops, nopsize))
ret = false;
}
GuiUpdatePatches();

View File

@ -1,8 +1,61 @@
#include "controlflowanalysis.h"
#include "console.h"
#include "module.h"
#include "TitanEngine/TitanEngine.h"
#include "memory.h"
ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size) : Analysis(base, size)
ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size, bool exceptionDirectory) : Analysis(base, size)
{
_functionInfoData = nullptr;
#ifdef _WIN64
// This will only be valid if the address range is within a loaded module
_moduleBase = ModBaseFromAddr(base);
if(exceptionDirectory && _moduleBase != 0)
{
char modulePath[MAX_PATH];
memset(modulePath, 0, sizeof(modulePath));
ModPathFromAddr(_moduleBase, 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);
_functionInfoSize = (uint)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
_functionInfoData = emalloc(_functionInfoSize);
if(_functionInfoData)
MemRead(virtualOffset + _moduleBase, _functionInfoData, _functionInfoSize);
}
}
}
#endif //_WIN64
}
ControlFlowAnalysis::~ControlFlowAnalysis()
{
if(_functionInfoData)
efree(_functionInfoData);
}
void ControlFlowAnalysis::Analyse()
@ -11,9 +64,17 @@ void ControlFlowAnalysis::Analyse()
DWORD ticks = GetTickCount();
BasicBlockStarts();
BasicBlocks();
dprintf("Basic block starts in %ums!\n", GetTickCount() - ticks);
ticks = GetTickCount();
dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks);
BasicBlocks();
dprintf("Basic blocks in %ums!\n", GetTickCount() - ticks);
ticks = GetTickCount();
Functions();
dprintf("Functions in %ums!\n", GetTickCount() - ticks);
dprintf("Analysis finished!\n");
}
void ControlFlowAnalysis::SetMarkers()
@ -21,14 +82,16 @@ void ControlFlowAnalysis::SetMarkers()
dprintf("digraph ControlFlow {\n");
int i = 0;
std::map<uint, int> nodeMap;
for(auto block : _blocks)
for(const auto & it : _blocks)
{
const auto & block = it.second;
nodeMap.insert({ block.start, i });
dprintf(" node%u [label=\"start=%p, end=%p\"];\n", i, block.start, block.end);
dprintf(" node%u [label=\"s=%p, e=%p, f=%p\"];\n", i, block.start, block.end, block.function);
i++;
}
for(auto block : _blocks)
for(auto it : _blocks)
{
const auto & block = it.second;
int startNode = nodeMap[block.start];
if(block.left)
{
@ -65,26 +128,26 @@ void ControlFlowAnalysis::BasicBlockStarts()
uint addr = _base + i;
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
{
if(bSkipFilling) //handle filling skip mode
if(bSkipFilling) //handle filling skip mode
{
if(!_cp.IsFilling()) //do nothing until the filling stopped
if(!_cp.IsFilling()) //do nothing until the filling stopped
{
bSkipFilling = false;
_blockStarts.insert(addr);
}
}
else if(_cp.InGroup(CS_GRP_RET) || _cp.InGroup(CS_GRP_INT)) //RET/INT break control flow
else if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3) //RET/INT3 break control flow
{
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
}
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
{
uint dest1 = GetBranchOperand();
uint dest1 = GetReferenceOperand();
uint dest2 = 0;
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
dest2 = addr + _cp.Size();
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
bSkipFilling = true;
if(dest1)
_blockStarts.insert(dest1);
@ -93,13 +156,16 @@ void ControlFlowAnalysis::BasicBlockStarts()
}
else if(_cp.InGroup(CS_GRP_CALL))
{
uint dest1 = GetBranchOperand();
uint dest1 = GetReferenceOperand();
if(dest1)
{
_blockStarts.insert(dest1);
_functionStarts.insert(dest1);
}
}
else
{
uint dest1 = GetBranchOperand();
uint dest1 = GetReferenceOperand();
if(dest1)
_blockStarts.insert(dest1);
}
@ -126,32 +192,181 @@ void ControlFlowAnalysis::BasicBlocks()
prevaddr = addr;
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
{
if(_cp.InGroup(CS_GRP_RET))
if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3)
{
_blocks.push_back(BasicBlock(start, addr, 0, 0)); //leaf block
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
break;
}
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
{
uint dest1 = GetBranchOperand();
uint dest1 = GetReferenceOperand();
uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
_blocks.push_back(BasicBlock(start, addr, dest1, dest2));
insertBlock(BasicBlock(start, addr, dest1, dest2));
insertParent(dest1, start);
insertParent(dest2, start);
break;
}
addr += _cp.Size();
}
else
addr++;
if(addr == nextStart) //special case handling overlapping blocks
if(addr == nextStart) //special case handling overlapping blocks
{
_blocks.push_back(BasicBlock(start, prevaddr, 0, nextStart));
insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
insertParent(nextStart, start);
break;
}
}
}
_blockStarts.clear();
#ifdef _WIN64
int count = 0;
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
{
const uint funcAddr = _moduleBase + Function->BeginAddress;
const uint funcEnd = _moduleBase + Function->EndAddress;
// If within limits...
if(funcAddr >= _base && funcAddr < _base + _size)
_functionStarts.insert(funcAddr);
count++;
return true;
});
dprintf("%u functions from the exception directory...\n", count);
#endif // _WIN64
dprintf("%u basic blocks, %u function starts detected...\n", _blocks.size(), _functionStarts.size());
}
uint ControlFlowAnalysis::GetBranchOperand()
void ControlFlowAnalysis::Functions()
{
typedef std::pair<BasicBlock*, UintSet*> DelayedBlock;
std::vector<DelayedBlock> delayedBlocks;
for(auto & it : _blocks)
{
BasicBlock* block = &it.second;
UintSet* parents = findParents(block->start);
if(!block->function)
{
if(!parents || _functionStarts.count(block->start)) //no parents = function start
{
uint functionStart = block->start;
block->function = functionStart;
UintSet functionBlocks;
functionBlocks.insert(functionStart);
_functions[functionStart] = functionBlocks;
}
else //in function
{
uint function = findFunctionStart(block, parents);
if(!function) //this happens with loops sometimes
delayedBlocks.push_back(DelayedBlock(block, parents));
else
block->function = function;
}
}
else
DebugBreak(); //this should not happen
}
int delayedCount = (int)delayedBlocks.size();
dprintf("%u/%u delayed blocks...\n", delayedCount, _blocks.size());
int resolved = 0;
for(auto & delayedBlock : delayedBlocks)
{
BasicBlock* block = delayedBlock.first;
UintSet* parents = delayedBlock.second;
uint function = findFunctionStart(block, parents);
if(!function)
{
continue;
/*dprintf("unresolved block %s\n", blockToString(block).c_str());
if(parents)
{
dprintf("parents:\n");
for(auto parent : *parents)
dprintf(" %s\n", blockToString(findBlock(parent)).c_str());
}
else
dprintf("parents: null");
dprintf("left: %s\n", blockToString(findBlock(block->left)).c_str());
dprintf("right: %s\n", blockToString(findBlock(block->right)).c_str());
return;*/
}
block->function = function;
resolved++;
}
dprintf("%u/%u delayed blocks resolved (%u/%u still left, probably unreferenced functions)\n", resolved, delayedCount, delayedCount - resolved, _blocks.size());
dprintf("%u functions found!\n", _functions.size());
}
void ControlFlowAnalysis::insertBlock(BasicBlock block)
{
if(_blocks.find(block.start) != _blocks.end())
DebugBreak();
_blocks[block.start] = block;
}
ControlFlowAnalysis::BasicBlock* ControlFlowAnalysis::findBlock(uint start)
{
if(!start)
return nullptr;
auto found = _blocks.find(start);
return found != _blocks.end() ? &found->second : nullptr;
}
void ControlFlowAnalysis::insertParent(uint child, uint parent)
{
if(!child || !parent)
return;
auto found = _parentMap.find(child);
if(found == _parentMap.end())
{
UintSet parents;
parents.insert(parent);
_parentMap[child] = parents;
}
else
found->second.insert(parent);
}
ControlFlowAnalysis::UintSet* ControlFlowAnalysis::findParents(uint child)
{
if(!child)
return nullptr;
auto found = _parentMap.find(child);
return found != _parentMap.end() ? &found->second : nullptr;
}
uint ControlFlowAnalysis::findFunctionStart(BasicBlock* block, ControlFlowAnalysis::UintSet* parents)
{
if(!block)
return 0;
if(block->function)
return block->function;
BasicBlock* left = findBlock(block->left);
if(left && left->function)
return left->function;
BasicBlock* right = findBlock(block->right);
if(right && right->function)
return right->function;
for(auto start : *parents)
{
BasicBlock* parent = findBlock(start);
if(parent->function)
return parent->function;
}
return 0;
}
String ControlFlowAnalysis::blockToString(BasicBlock* block)
{
if(!block)
return String("null");
return block->toString();
}
uint ControlFlowAnalysis::GetReferenceOperand()
{
for(int i = 0; i < _cp.x86().op_count; i++)
{
@ -164,4 +379,23 @@ uint ControlFlowAnalysis::GetBranchOperand()
}
}
return 0;
}
}
#ifdef _WIN64
void ControlFlowAnalysis::EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback)
{
if(!_functionInfoData)
return;
// Get the table pointer and size
auto functionTable = (PRUNTIME_FUNCTION)_functionInfoData;
uint totalCount = (_functionInfoSize / sizeof(RUNTIME_FUNCTION));
// Enumerate each entry
for(ULONG i = 0; i < totalCount; i++)
{
if(!Callback(&functionTable[i]))
break;
}
}
#endif // _WIN64

View File

@ -2,15 +2,17 @@
#define _CONTROLFLOWANALYSIS_H
#include "_global.h"
#include "capstone_wrapper.h"
#include "analysis.h"
#include "addrinfo.h"
#include <functional>
class ControlFlowAnalysis : public Analysis
{
public:
explicit ControlFlowAnalysis(uint base, uint size);
void Analyse();
void SetMarkers();
explicit ControlFlowAnalysis(uint base, uint size, bool exceptionDirectory);
~ControlFlowAnalysis();
void Analyse() override;
void SetMarkers() override;
private:
struct BasicBlock
@ -19,6 +21,7 @@ private:
uint end;
uint left;
uint right;
uint function;
BasicBlock()
{
@ -26,6 +29,7 @@ private:
this->end = 0;
this->left = 0;
this->right = 0;
this->function = 0;
}
BasicBlock(uint start, uint end, uint left, uint right)
@ -34,15 +38,40 @@ private:
this->end = end;
this->left = min(left, right);
this->right = max(left, right);
this->function = 0;
}
String toString()
{
return StringUtils::sprintf("start:%p,end:%p,left:%p,right:%p,func:%p", start, end, left, right, function);
}
};
std::set<uint> _blockStarts;
std::vector<BasicBlock> _blocks;
typedef std::set<uint> UintSet;
uint _moduleBase;
uint _functionInfoSize;
void* _functionInfoData;
UintSet _blockStarts;
UintSet _functionStarts;
std::map<uint, BasicBlock> _blocks; //start of block -> block
std::map<uint, UintSet> _parentMap; //start child -> parents
std::map<uint, UintSet> _functions; //function start -> function block starts
void BasicBlockStarts();
void BasicBlocks();
uint GetBranchOperand();
void Functions();
void insertBlock(BasicBlock block);
BasicBlock* findBlock(uint start);
void insertParent(uint child, uint parent);
UintSet* findParents(uint child);
uint findFunctionStart(BasicBlock* block, UintSet* parents);
String blockToString(BasicBlock* block);
uint GetReferenceOperand();
#ifdef _WIN64
void EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback);
#endif // _WIN64
};
#endif //_CONTROLFLOWANALYSIS_H

View File

@ -24,13 +24,13 @@ SafeSymUnloadModule64(
return SymUnloadModule64(hProcess, BaseOfDll);
}
BOOL
SafeSymSetSearchPath(
SafeSymSetSearchPathW(
__in HANDLE hProcess,
__in_opt PCSTR SearchPath
__in_opt PCWSTR SearchPath
)
{
EXCLUSIVE_ACQUIRE(LockSym);
return SymSetSearchPath(hProcess, SearchPath);
return SymSetSearchPathW(hProcess, SearchPath);
}
DWORD
SafeSymSetOptions(
@ -41,14 +41,14 @@ SafeSymSetOptions(
return SymSetOptions(SymOptions);
}
BOOL
SafeSymInitialize(
SafeSymInitializeW(
__in HANDLE hProcess,
__in_opt PCSTR UserSearchPath,
__in_opt PCWSTR UserSearchPath,
__in BOOL fInvadeProcess
)
{
EXCLUSIVE_ACQUIRE(LockSym);
return SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
return SymInitializeW(hProcess, UserSearchPath, fInvadeProcess);
}
BOOL
SafeSymRegisterCallback64(
@ -86,14 +86,14 @@ SafeSymGetModuleInfo64(
return SymGetModuleInfo64(hProcess, qwAddr, ModuleInfo);
}
BOOL
SafeSymGetSearchPath(
SafeSymGetSearchPathW(
__in HANDLE hProcess,
__out_ecount(SearchPathLength) PSTR SearchPath,
__out_ecount(SearchPathLength) PWSTR SearchPath,
__in DWORD SearchPathLength
)
{
EXCLUSIVE_ACQUIRE(LockSym);
return SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
return SymGetSearchPathW(hProcess, SearchPath, SearchPathLength);
}
BOOL
SafeSymEnumSymbols(

View File

@ -20,18 +20,18 @@ SafeSymUnloadModule64(
__in DWORD64 BaseOfDll
);
BOOL
SafeSymSetSearchPath(
SafeSymSetSearchPathW(
__in HANDLE hProcess,
__in_opt PCSTR SearchPath
__in_opt PCWSTR SearchPath
);
DWORD
SafeSymSetOptions(
__in DWORD SymOptions
);
BOOL
SafeSymInitialize(
SafeSymInitializeW(
__in HANDLE hProcess,
__in_opt PCSTR UserSearchPath,
__in_opt PCWSTR UserSearchPath,
__in BOOL fInvadeProcess
);
BOOL
@ -58,9 +58,9 @@ SafeSymGetModuleInfo64(
__out PIMAGEHLP_MODULE64 ModuleInfo
);
BOOL
SafeSymGetSearchPath(
SafeSymGetSearchPathW(
__in HANDLE hProcess,
__out_ecount(SearchPathLength) PSTR SearchPath,
__out_ecount(SearchPathLength) PWSTR SearchPath,
__in DWORD SearchPathLength
);
BOOL

View File

@ -569,7 +569,7 @@ static unsigned char getCIPch()
{
unsigned char ch = 0x90;
uint cip = GetContextDataEx(hActiveThread, UE_CIP);
MemRead(cip, &ch, 1, 0);
MemRead(cip, &ch, 1);
return ch;
}
@ -633,7 +633,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
GuiSymbolLogClear();
char szServerSearchPath[MAX_PATH * 2] = "";
sprintf_s(szServerSearchPath, "SRV*%s", szSymbolCachePath);
SafeSymInitialize(fdProcessInfo->hProcess, szServerSearchPath, false); //initialize symbols
SafeSymInitializeW(fdProcessInfo->hProcess, StringUtils::Utf8ToUtf16(szServerSearchPath).c_str(), false); //initialize symbols
SafeSymRegisterCallback64(fdProcessInfo->hProcess, SymRegisterCallbackProc64, 0);
SafeSymLoadModuleEx(fdProcessInfo->hProcess, CreateProcessInfo->hFile, DebugFileName, 0, (DWORD64)base, 0, 0, 0);
@ -965,7 +965,7 @@ static void cbOutputDebugString(OUTPUT_DEBUG_STRING_INFO* DebugString)
if(!DebugString->fUnicode) //ASCII
{
Memory<char*> DebugText(DebugString->nDebugStringLength + 1, "cbOutputDebugString:DebugText");
if(MemRead((uint)DebugString->lpDebugStringData, DebugText(), DebugString->nDebugStringLength, 0))
if(MemRead((uint)DebugString->lpDebugStringData, DebugText(), DebugString->nDebugStringLength))
{
String str = String(DebugText());
if(str != lastDebugText) //fix for every string being printed twice
@ -1047,7 +1047,7 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
if(nameInfo.dwType == 0x1000 && nameInfo.dwFlags == 0 && ThreadIsValid(nameInfo.dwThreadID)) //passed basic checks
{
Memory<char*> ThreadName(MAX_THREAD_NAME_SIZE, "cbException:ThreadName");
if(MemRead((uint)nameInfo.szName, ThreadName(), MAX_THREAD_NAME_SIZE - 1, 0))
if(MemRead((uint)nameInfo.szName, ThreadName(), MAX_THREAD_NAME_SIZE - 1))
{
String ThreadNameEscaped = StringUtils::Escape(ThreadName());
dprintf("SetThreadName(%X, \"%s\")\n", nameInfo.dwThreadID, ThreadNameEscaped.c_str());
@ -1805,7 +1805,6 @@ bool dbglistprocesses(std::vector<PROCESSENTRY32>* list)
static bool getcommandlineaddr(uint* addr, cmdline_error_t* cmd_line_error)
{
SIZE_T size;
uint pprocess_parameters;
cmd_line_error->addr = (uint)GetPEBLocation(fdProcessInfo->hProcess);
@ -1818,7 +1817,7 @@ static bool getcommandlineaddr(uint* addr, cmdline_error_t* cmd_line_error)
//cast-trick to calculate the address of the remote peb field ProcessParameters
cmd_line_error->addr = (uint) & (((PPEB) cmd_line_error->addr)->ProcessParameters);
if(!MemRead(cmd_line_error->addr, &pprocess_parameters, sizeof(pprocess_parameters), &size))
if(!MemRead(cmd_line_error->addr, &pprocess_parameters, sizeof(pprocess_parameters)))
{
cmd_line_error->type = CMDL_ERR_READ_PEBBASE;
return false;
@ -1832,11 +1831,10 @@ static bool patchcmdline(uint getcommandline, uint new_command_line, cmdline_err
{
uint command_line_stored = 0;
uint aux = 0;
SIZE_T size;
unsigned char data[100];
cmd_line_error->addr = getcommandline;
if(!MemRead(cmd_line_error->addr, & data, sizeof(data), & size))
if(!MemRead(cmd_line_error->addr, & data, sizeof(data)))
{
cmd_line_error->type = CMDL_ERR_READ_GETCOMMANDLINEBASE;
return false;
@ -1870,7 +1868,7 @@ static bool patchcmdline(uint getcommandline, uint new_command_line, cmdline_err
#endif
//update the pointer in the debuggee
if(!MemWrite(command_line_stored, &new_command_line, sizeof(new_command_line), &size))
if(!MemWrite(command_line_stored, &new_command_line, sizeof(new_command_line)))
{
cmd_line_error->addr = command_line_stored;
cmd_line_error->type = CMDL_ERR_WRITE_GETCOMMANDLINESTORED;
@ -1913,7 +1911,6 @@ bool dbgsetcmdline(const char* cmd_line, cmdline_error_t* cmd_line_error)
{
cmdline_error_t cmd_line_error_aux;
UNICODE_STRING new_command_line;
SIZE_T size;
uint command_line_addr;
if(cmd_line_error == NULL)
@ -1939,21 +1936,21 @@ bool dbgsetcmdline(const char* cmd_line, cmdline_error_t* cmd_line_error)
new_command_line.Buffer = command_linewstr();
uint mem = (uint)MemAllocRemote(0, new_command_line.Length * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
uint mem = (uint)MemAllocRemote(0, new_command_line.Length * 2);
if(!mem)
{
cmd_line_error->type = CMDL_ERR_ALLOC_UNICODEANSI_COMMANDLINE;
return false;
}
if(!MemWrite(mem, new_command_line.Buffer, new_command_line.Length, &size))
if(!MemWrite(mem, new_command_line.Buffer, new_command_line.Length))
{
cmd_line_error->addr = mem;
cmd_line_error->type = CMDL_ERR_WRITE_UNICODE_COMMANDLINE;
return false;
}
if(!MemWrite((mem + new_command_line.Length), (void*)cmd_line, strlen(cmd_line) + 1, &size))
if(!MemWrite((mem + new_command_line.Length), (void*)cmd_line, strlen(cmd_line) + 1))
{
cmd_line_error->addr = mem + new_command_line.Length;
cmd_line_error->type = CMDL_ERR_WRITE_ANSI_COMMANDLINE;
@ -1964,7 +1961,7 @@ bool dbgsetcmdline(const char* cmd_line, cmdline_error_t* cmd_line_error)
return false;
new_command_line.Buffer = (PWSTR) mem;
if(!MemWrite(command_line_addr, &new_command_line, sizeof(new_command_line), &size))
if(!MemWrite(command_line_addr, &new_command_line, sizeof(new_command_line)))
{
cmd_line_error->addr = command_line_addr;
cmd_line_error->type = CMDL_ERR_WRITE_PEBUNICODE_COMMANDLINE;
@ -1976,7 +1973,6 @@ bool dbgsetcmdline(const char* cmd_line, cmdline_error_t* cmd_line_error)
bool dbggetcmdline(char** cmd_line, cmdline_error_t* cmd_line_error)
{
SIZE_T size;
UNICODE_STRING CommandLine;
cmdline_error_t cmd_line_error_aux;
@ -1986,7 +1982,7 @@ bool dbggetcmdline(char** cmd_line, cmdline_error_t* cmd_line_error)
if(!getcommandlineaddr(&cmd_line_error->addr, cmd_line_error))
return false;
if(!MemRead(cmd_line_error->addr, &CommandLine, sizeof(CommandLine), &size))
if(!MemRead(cmd_line_error->addr, &CommandLine, sizeof(CommandLine)))
{
cmd_line_error->type = CMDL_ERR_READ_PROCPARM_PTR;
return false;
@ -1995,7 +1991,7 @@ bool dbggetcmdline(char** cmd_line, cmdline_error_t* cmd_line_error)
Memory<wchar_t*> wstr_cmd(CommandLine.Length + sizeof(wchar_t));
cmd_line_error->addr = (uint) CommandLine.Buffer;
if(!MemRead(cmd_line_error->addr, wstr_cmd(), CommandLine.Length, &size))
if(!MemRead(cmd_line_error->addr, wstr_cmd(), CommandLine.Length))
{
cmd_line_error->type = CMDL_ERR_READ_PROCPARM_CMDLINE;
return false;

View File

@ -238,7 +238,7 @@ CMDRESULT cbDebugSetBPX(int argc, char* argv[]) //bp addr [,name [,type]]
dprintf("Error setting breakpoint at "fhex"! (IsBPXEnabled)\n", addr);
return STATUS_ERROR;
}
else if(!MemRead(addr, &oldbytes, sizeof(short), 0))
else if(!MemRead(addr, &oldbytes, sizeof(short)))
{
dprintf("Error setting breakpoint at "fhex"! (memread)\n", addr);
return STATUS_ERROR;
@ -789,7 +789,7 @@ CMDRESULT cbDebugAlloc(int argc, char* argv[])
if(argc > 1)
if(!valfromstring(argv[1], &size, false))
return STATUS_ERROR;
uint mem = (uint)MemAllocRemote(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
uint mem = (uint)MemAllocRemote(0, size);
if(!mem)
dputs("VirtualAllocEx failed");
else
@ -1473,8 +1473,8 @@ CMDRESULT cbDebugDownloadSymbol(int argc, char* argv[])
}
char szModulePath[MAX_PATH] = "";
strcpy_s(szModulePath, StringUtils::Utf16ToUtf8(wszModulePath).c_str());
char szOldSearchPath[MAX_PATH] = "";
if(!SafeSymGetSearchPath(fdProcessInfo->hProcess, szOldSearchPath, MAX_PATH)) //backup current search path
wchar_t szOldSearchPath[MAX_PATH] = L"";
if(!SafeSymGetSearchPathW(fdProcessInfo->hProcess, szOldSearchPath, MAX_PATH)) //backup current search path
{
dputs("SymGetSearchPath failed!");
return STATUS_ERROR;
@ -1483,26 +1483,26 @@ CMDRESULT cbDebugDownloadSymbol(int argc, char* argv[])
if(argc > 2)
szSymbolStore = argv[2];
sprintf_s(szServerSearchPath, "SRV*%s*%s", szSymbolCachePath, szSymbolStore);
if(!SafeSymSetSearchPath(fdProcessInfo->hProcess, szServerSearchPath)) //set new search path
if(!SafeSymSetSearchPathW(fdProcessInfo->hProcess, StringUtils::Utf8ToUtf16(szServerSearchPath).c_str())) //set new search path
{
dputs("SymSetSearchPath (1) failed!");
return STATUS_ERROR;
}
if(!SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)modbase)) //unload module
{
SafeSymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath);
SafeSymSetSearchPathW(fdProcessInfo->hProcess, szOldSearchPath);
dputs("SymUnloadModule64 failed!");
return STATUS_ERROR;
}
if(!SafeSymLoadModuleEx(fdProcessInfo->hProcess, 0, szModulePath, 0, (DWORD64)modbase, 0, 0, 0)) //load module
{
dputs("SymLoadModuleEx failed!");
SafeSymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath);
SafeSymSetSearchPathW(fdProcessInfo->hProcess, szOldSearchPath);
return STATUS_ERROR;
}
if(!SafeSymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath))
if(!SafeSymSetSearchPathW(fdProcessInfo->hProcess, szOldSearchPath))
{
dputs("SymSetSearchPath (2) failed!");
dputs("SymSetSearchPathW (2) failed!");
return STATUS_ERROR;
}
GuiSymbolRefreshCurrent();
@ -1888,8 +1888,8 @@ CMDRESULT cbDebugLoadLib(int argc, char* argv[])
LoadLibThreadID = fdProcessInfo->dwThreadId;
HANDLE LoadLibThread = ThreadGetHandle((DWORD)LoadLibThreadID);
DLLNameMem = MemAllocRemote(0, strlen(argv[1]) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ASMAddr = MemAllocRemote(0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
DLLNameMem = MemAllocRemote(0, strlen(argv[1]) + 1);
ASMAddr = MemAllocRemote(0, 0x1000);
if(!DLLNameMem || !ASMAddr)
{
@ -1897,7 +1897,7 @@ CMDRESULT cbDebugLoadLib(int argc, char* argv[])
return STATUS_ERROR;
}
if(!MemWrite(DLLNameMem, argv[1], strlen(argv[1]), NULL))
if(!MemWrite(DLLNameMem, argv[1], strlen(argv[1])))
{
dprintf("Error: couldn't write process memory");
return STATUS_ERROR;

View File

@ -103,7 +103,7 @@ bool disasmfast(unsigned char* data, uint addr, BASIC_INSTRUCTION_INFO* basicinf
bool disasmfast(uint addr, BASIC_INSTRUCTION_INFO* basicinfo)
{
unsigned int data[16];
if(!MemRead(addr, data, sizeof(data), nullptr))
if(!MemRead(addr, data, sizeof(data)))
return false;
return disasmfast((unsigned char*)data, addr, basicinfo);
}

View File

@ -278,7 +278,7 @@ bool disasmispossiblestring(uint addr)
{
unsigned char data[11];
memset(data, 0, sizeof(data));
if(!MemRead(addr, data, sizeof(data) - 3, 0))
if(!MemRead(addr, data, sizeof(data) - 3))
return false;
uint test = 0;
memcpy(&test, data, sizeof(uint));
@ -294,7 +294,7 @@ bool disasmgetstringat(uint addr, STRING_TYPE* type, char* ascii, char* unicode,
if(!disasmispossiblestring(addr))
return false;
Memory<unsigned char*> data((maxlen + 1) * 2, "disasmgetstringat:data");
if(!MemRead(addr, data(), (maxlen + 1) * 2, 0))
if(!MemRead(addr, data(), (maxlen + 1) * 2))
return false;
uint test = 0;
memcpy(&test, data(), sizeof(uint));
@ -388,7 +388,7 @@ int disasmgetsize(uint addr, unsigned char* data)
int disasmgetsize(uint addr)
{
char data[MAX_DISASM_BUFFER];
if(!MemRead(addr, data, sizeof(data), 0))
if(!MemRead(addr, data, sizeof(data)))
return 1;
return disasmgetsize(addr, (unsigned char*)data);
}

View File

@ -0,0 +1,106 @@
#include "exceptiondirectoryanalysis.h"
#include "module.h"
#include "TitanEngine/TitanEngine.h"
#include "memory.h"
#include "console.h"
#include "function.h"
ExceptionDirectoryAnalysis::ExceptionDirectoryAnalysis(uint base, uint size) : Analysis(base, size)
{
_functionInfoData = nullptr;
#ifdef _WIN64
// This will only be valid if the address range is within a loaded module
_moduleBase = ModBaseFromAddr(base);
if(_moduleBase != 0)
{
char modulePath[MAX_PATH];
memset(modulePath, 0, sizeof(modulePath));
ModPathFromAddr(_moduleBase, 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);
_functionInfoSize = (uint)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
_functionInfoData = emalloc(_functionInfoSize);
if(_functionInfoData)
MemRead(virtualOffset + _moduleBase, _functionInfoData, _functionInfoSize);
}
}
}
#endif //_WIN64
}
ExceptionDirectoryAnalysis::~ExceptionDirectoryAnalysis()
{
if(_functionInfoData)
efree(_functionInfoData);
}
void ExceptionDirectoryAnalysis::Analyse()
{
#ifdef _WIN64
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
{
const uint funcAddr = _moduleBase + Function->BeginAddress;
const uint funcEnd = _moduleBase + Function->EndAddress;
// If within limits...
if(funcAddr >= _base && funcAddr < _base + _size)
_functions.push_back({ funcAddr, funcEnd });
return true;
});
dprintf("%u functions discovered!\n", _functions.size());
#else //x32
dprintf("This kind of analysis doesn't work on x32 executables...\n");
#endif // _WIN64
}
void ExceptionDirectoryAnalysis::SetMarkers()
{
FunctionDelRange(_base, _base + _size);
for(const auto & function : _functions)
FunctionAdd(function.first, function.second, false);
}
#ifdef _WIN64
void ExceptionDirectoryAnalysis::EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback)
{
if(!_functionInfoData)
return;
// Get the table pointer and size
auto functionTable = (PRUNTIME_FUNCTION)_functionInfoData;
uint totalCount = (_functionInfoSize / sizeof(RUNTIME_FUNCTION));
// Enumerate each entry
for(uint i = 0; i < totalCount; i++)
{
if(!Callback(&functionTable[i]))
break;
}
}
#endif // _WIN64

View File

@ -0,0 +1,26 @@
#ifndef _EXCEPTIONDIRECTORYANALYSIS_H
#define _EXCEPTIONDIRECTORYANALYSIS_H
#include "analysis.h"
#include <functional>
class ExceptionDirectoryAnalysis : public Analysis
{
public:
explicit ExceptionDirectoryAnalysis(uint base, uint size);
~ExceptionDirectoryAnalysis();
void Analyse() override;
void SetMarkers() override;
private:
uint _moduleBase;
uint _functionInfoSize;
void* _functionInfoData;
std::vector<std::pair<uint, uint>> _functions;
#ifdef _WIN64
void EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback);
#endif // _WIN64
};
#endif //_EXCEPTIONDIRECTORYANALYSIS_H

View File

@ -26,9 +26,10 @@
#include "module.h"
#include "stringformat.h"
#include "filereader.h"
#include "functionanalysis.h"
#include "linearanalysis.h"
#include "controlflowanalysis.h"
#include "analysis_nukem.h"
#include "exceptiondirectoryanalysis.h"
static bool bRefinit = false;
@ -187,7 +188,7 @@ CMDRESULT cbInstrMov(int argc, char* argv[])
data()[j] = res;
}
//Move data to destination
if(!MemWrite(dest, data(), data.size(), 0))
if(!MemWrite(dest, data(), data.size()))
{
dprintf("failed to write to "fhex"\n", dest);
return STATUS_ERROR;
@ -1067,7 +1068,7 @@ CMDRESULT cbInstrCopystr(int argc, char* argv[])
dprintf("invalid address \"%s\"!\n", argv[1]);
return STATUS_ERROR;
}
if(!MemPatch(addr, string(), strlen(string()), 0))
if(!MemPatch(addr, string(), strlen(string())))
{
dputs("memwrite failed!");
return STATUS_ERROR;
@ -1105,7 +1106,7 @@ CMDRESULT cbInstrFind(int argc, char* argv[])
return STATUS_ERROR;
}
Memory<unsigned char*> data(size, "cbInstrFind:data");
if(!MemRead(base, data(), size, 0))
if(!MemRead(base, data(), size))
{
dputs("failed to read memory!");
return STATUS_ERROR;
@ -1157,7 +1158,7 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[])
return STATUS_ERROR;
}
Memory<unsigned char*> data(size, "cbInstrFindAll:data");
if(!MemRead(base, data(), size, 0))
if(!MemRead(base, data(), size))
{
dputs("failed to read memory!");
return STATUS_ERROR;
@ -1217,7 +1218,7 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[])
if(findData)
{
Memory<unsigned char*> printData(searchpattern.size(), "cbInstrFindAll:printData");
MemRead(result, printData(), printData.size(), 0);
MemRead(result, printData(), printData.size());
for(size_t j = 0, k = 0; j < printData.size(); j++)
{
if(j)
@ -1712,7 +1713,7 @@ CMDRESULT cbInstrYara(int argc, char* argv[])
base = addr;
}
Memory<uint8_t*> data(size);
if(!MemRead(base, data(), size, 0))
if(!MemRead(base, data(), size))
{
dprintf("failed to read memory page %p[%X]!\n", base, size);
return STATUS_ERROR;
@ -1842,7 +1843,7 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[])
}
unsigned char data[16];
if(!MemRead(addr, data, sizeof(data), 0))
if(!MemRead(addr, data, sizeof(data)))
{
dprintf("could not read memory at %p\n", addr);
return STATUS_ERROR;
@ -1865,6 +1866,7 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[])
const cs_x86 & x86 = cp.x86();
int argcount = x86.op_count;
dprintf("%s %s\n", instr->mnemonic, instr->op_str);
dprintf("%d, NOP=%d\n", cp.GetId(), X86_INS_NOP);
for(int i = 0; i < argcount; i++)
{
const cs_x86_op & op = x86.operands[i];
@ -1915,7 +1917,7 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[])
GuiSelectionGet(GUI_DISASSEMBLY, &sel);
uint size = 0;
uint base = MemFindBaseAddr(sel.start, &size);
FunctionAnalysis anal(base, size);
LinearAnalysis anal(base, size);
anal.Analyse();
anal.SetMarkers();
GuiUpdateAllViews();
@ -1924,11 +1926,27 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[])
CMDRESULT cbInstrCfanalyse(int argc, char* argv[])
{
bool exceptionDirectory = false;
if(argc > 1)
exceptionDirectory = true;
SELECTIONDATA sel;
GuiSelectionGet(GUI_DISASSEMBLY, &sel);
uint size = 0;
uint base = MemFindBaseAddr(sel.start, &size);
ControlFlowAnalysis anal(base, size);
ControlFlowAnalysis anal(base, size, exceptionDirectory);
anal.Analyse();
//anal.SetMarkers();
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbInstrExanalyse(int argc, char* argv[])
{
SELECTIONDATA sel;
GuiSelectionGet(GUI_DISASSEMBLY, &sel);
uint size = 0;
uint base = MemFindBaseAddr(sel.start, &size);
ExceptionDirectoryAnalysis anal(base, size);
anal.Analyse();
anal.SetMarkers();
GuiUpdateAllViews();
@ -1963,7 +1981,7 @@ CMDRESULT cbInstrVisualize(int argc, char* argv[])
uint _base = start;
uint _size = maxaddr - start;
Memory<unsigned char*> _data(_size);
MemRead(_base, _data(), _size, nullptr);
MemRead(_base, _data(), _size);
FunctionClear();
//linear search with some trickery

View File

@ -72,5 +72,6 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[]);
CMDRESULT cbInstrVisualize(int argc, char* argv[]);
CMDRESULT cbInstrMeminfo(int argc, char* argv[]);
CMDRESULT cbInstrCfanalyse(int argc, char* argv[]);
CMDRESULT cbInstrExanalyse(int argc, char* argv[]);
#endif // _INSTRUCTIONS_H

View File

@ -1,13 +1,13 @@
#include "functionanalysis.h"
#include "linearanalysis.h"
#include "console.h"
#include "memory.h"
#include "function.h"
FunctionAnalysis::FunctionAnalysis(uint base, uint size) : Analysis(base, size)
LinearAnalysis::LinearAnalysis(uint base, uint size) : Analysis(base, size)
{
}
void FunctionAnalysis::Analyse()
void LinearAnalysis::Analyse()
{
dputs("Starting analysis...");
DWORD ticks = GetTickCount();
@ -19,7 +19,7 @@ void FunctionAnalysis::Analyse()
dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks);
}
void FunctionAnalysis::SetMarkers()
void LinearAnalysis::SetMarkers()
{
FunctionDelRange(_base, _base + _size);
for(auto & function : _functions)
@ -30,7 +30,7 @@ void FunctionAnalysis::SetMarkers()
}
}
void FunctionAnalysis::SortCleanup()
void LinearAnalysis::SortCleanup()
{
//sort & remove duplicates
std::sort(_functions.begin(), _functions.end());
@ -38,7 +38,7 @@ void FunctionAnalysis::SortCleanup()
_functions.erase(last, _functions.end());
}
void FunctionAnalysis::PopulateReferences()
void LinearAnalysis::PopulateReferences()
{
//linear immediate reference scan (call <addr>, push <addr>, mov [somewhere], <addr>)
for(uint i = 0; i < _size;)
@ -57,7 +57,7 @@ void FunctionAnalysis::PopulateReferences()
SortCleanup();
}
void FunctionAnalysis::AnalyseFunctions()
void LinearAnalysis::AnalyseFunctions()
{
for(size_t i = 0; i < _functions.size(); i++)
{
@ -79,7 +79,7 @@ void FunctionAnalysis::AnalyseFunctions()
}
}
uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr)
uint LinearAnalysis::FindFunctionEnd(uint start, uint maxaddr)
{
//disassemble first instruction for some heuristics
if(_cp.Disassemble(start, TranslateAddress(start), MAX_DISASM_BUFFER))
@ -132,7 +132,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr)
return end < jumpback ? jumpback : end;
}
uint FunctionAnalysis::GetReferenceOperand()
uint LinearAnalysis::GetReferenceOperand()
{
for(int i = 0; i < _cp.x86().op_count; i++)
{

View File

@ -1,16 +1,15 @@
#ifndef _FUNCTIONANALYSIS_H
#define _FUNCTIONANALYSIS_H
#ifndef _LINEARANALYSIS_H
#define _LINEARANALYSIS_H
#include "_global.h"
#include "capstone_wrapper.h"
#include "analysis.h"
class FunctionAnalysis : public Analysis
class LinearAnalysis : public Analysis
{
public:
explicit FunctionAnalysis(uint base, uint size);
void Analyse();
void SetMarkers();
explicit LinearAnalysis(uint base, uint size);
void Analyse() override;
void SetMarkers() override;
private:
struct FunctionInfo
@ -38,4 +37,4 @@ private:
uint GetReferenceOperand();
};
#endif //_FUNCTIONANALYSIS_H
#endif //_LINEARANALYSIS_H

View File

@ -173,7 +173,7 @@ uint MemFindBaseAddr(uint Address, uint* Size, bool Refresh)
return found->first.first;
}
bool MemRead(uint BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesRead)
bool MemRead(uint BaseAddress, void* Buffer, uint Size, uint* NumberOfBytesRead)
{
if(!MemIsCanonicalAddress((uint)BaseAddress))
return false;
@ -227,7 +227,7 @@ bool MemRead(uint BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesR
return (*NumberOfBytesRead > 0);
}
bool MemWrite(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesWritten)
bool MemWrite(uint BaseAddress, const void* Buffer, uint Size, uint* NumberOfBytesWritten)
{
if(!MemIsCanonicalAddress((uint)BaseAddress))
return false;
@ -281,7 +281,7 @@ bool MemWrite(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberO
return (*NumberOfBytesWritten > 0);
}
bool MemPatch(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesWritten)
bool MemPatch(uint BaseAddress, const void* Buffer, uint Size, uint* NumberOfBytesWritten)
{
// Buffer and size must be valid
if(!Buffer || Size <= 0)
@ -290,7 +290,7 @@ bool MemPatch(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberO
// Allocate the memory
Memory<unsigned char*> oldData(Size, "mempatch:oldData");
if(!MemRead(BaseAddress, oldData(), Size, nullptr))
if(!MemRead(BaseAddress, oldData(), Size))
{
// If no memory can be read, no memory can be written. Fail out
// of this function.
@ -306,7 +306,7 @@ bool MemPatch(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberO
bool MemIsValidReadPtr(uint Address)
{
unsigned char a = 0;
return MemRead(Address, &a, sizeof(unsigned char), nullptr);
return MemRead(Address, &a, sizeof(unsigned char));
}
bool MemIsCanonicalAddress(uint Address)

View File

@ -8,10 +8,10 @@ extern bool bListAllPages;
void MemUpdateMap();
uint MemFindBaseAddr(uint Address, uint* Size, bool Refresh = false);
bool MemRead(uint BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesRead);
bool MemWrite(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesWritten);
bool MemPatch(uint BaseAddress, const void* Buffer, SIZE_T Size, SIZE_T* NumberOfBytesWritten);
bool MemRead(uint BaseAddress, void* Buffer, uint Size, uint* NumberOfBytesRead = nullptr);
bool MemWrite(uint BaseAddress, const void* Buffer, uint Size, uint* NumberOfBytesWritten = nullptr);
bool MemPatch(uint BaseAddress, const void* Buffer, uint Size, uint* NumberOfBytesWritten = nullptr);
bool MemIsValidReadPtr(uint Address);
bool MemIsCanonicalAddress(uint Address);
uint MemAllocRemote(uint Address, uint Size, DWORD Type, DWORD Protect);
uint MemAllocRemote(uint Address, uint Size, DWORD Type = MEM_RESERVE | MEM_COMMIT, DWORD Protect = PAGE_EXECUTE_READWRITE);
bool MemFreeRemote(uint Address);

View File

@ -106,7 +106,7 @@ bool PatchDelete(uint Address, bool Restore)
// Restore the original byte at this address
if(Restore)
MemWrite((found->second.addr + ModBaseFromAddr(Address)), &found->second.oldbyte, sizeof(char), nullptr);
MemWrite((found->second.addr + ModBaseFromAddr(Address)), &found->second.oldbyte, sizeof(char));
// Finally remove it from the list
patches.erase(found);
@ -147,7 +147,7 @@ void PatchDelRange(uint Start, uint End, bool Restore)
{
// Restore the original byte if necessary
if(Restore)
MemWrite((currentPatch.addr + moduleBase), &currentPatch.oldbyte, sizeof(char), nullptr);
MemWrite((currentPatch.addr + moduleBase), &currentPatch.oldbyte, sizeof(char));
itr = patches.erase(itr);
}
@ -273,7 +273,6 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
if(!ptr)
continue;
dprintf("patch%.4d|%s[%.8X]:%.2X/%.2X->%.2X\n", i + 1, moduleName, ptr - fileMapVa, *ptr, List[i].oldbyte, List[i].newbyte);
*ptr = List[i].newbyte;
patchCount++;
}

View File

@ -40,7 +40,7 @@ int RefFind(uint Address, uint Size, CBREF Callback, void* UserData, bool Silent
// Allocate and read a buffer from the remote process
Memory<unsigned char*> data(scanSize, "reffind:data");
if(!MemRead(scanStart, data(), scanSize, nullptr))
if(!MemRead(scanStart, data(), scanSize))
{
if(!Silent)
dprintf("Error reading memory in reference search\n");

View File

@ -16,7 +16,7 @@ bool stackcommentget(uint addr, STACK_COMMENT* comment)
{
uint data = 0;
memset(comment, 0, sizeof(STACK_COMMENT));
MemRead(addr, &data, sizeof(uint), 0);
MemRead(addr, &data, sizeof(uint));
if(!MemIsValidReadPtr(data)) //the stack value is no pointer
return false;
@ -26,7 +26,7 @@ bool stackcommentget(uint addr, STACK_COMMENT* comment)
if(readStart < base)
readStart = base;
unsigned char disasmData[256];
MemRead(readStart, disasmData, sizeof(disasmData), 0);
MemRead(readStart, disasmData, sizeof(disasmData));
uint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1);
uint previousInstr = readStart + prev;
@ -202,7 +202,7 @@ void stackgetcallstack(uint csp, CALLSTACK* callstack)
while(i != stackbase + stacksize)
{
uint data = 0;
MemRead(i, &data, sizeof(uint), 0);
MemRead(i, &data, sizeof(uint));
if(MemIsValidReadPtr(data)) //the stack value is a pointer
{
uint size = 0;
@ -211,7 +211,7 @@ void stackgetcallstack(uint csp, CALLSTACK* callstack)
if(readStart < base)
readStart = base;
unsigned char disasmData[256];
MemRead(readStart, disasmData, sizeof(disasmData), 0);
MemRead(readStart, disasmData, sizeof(disasmData));
uint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1);
uint previousInstr = readStart + prev;
BASIC_INSTRUCTION_INFO basicinfo;

View File

@ -129,11 +129,11 @@ void SymDownloadAllSymbols(const char* SymbolStore)
return;
// Backup the current symbol search path
char oldSearchPath[MAX_PATH];
wchar_t oldSearchPath[MAX_PATH];
if(!SafeSymGetSearchPath(fdProcessInfo->hProcess, oldSearchPath, MAX_PATH))
if(!SafeSymGetSearchPathW(fdProcessInfo->hProcess, oldSearchPath, MAX_PATH))
{
dputs("SymGetSearchPath failed!");
dputs("SymGetSearchPathW failed!");
return;
}
@ -141,9 +141,9 @@ void SymDownloadAllSymbols(const char* SymbolStore)
char customSearchPath[MAX_PATH * 2];
sprintf_s(customSearchPath, "SRV*%s*%s", szSymbolCachePath, SymbolStore);
if(!SafeSymSetSearchPath(fdProcessInfo->hProcess, customSearchPath))
if(!SafeSymSetSearchPathW(fdProcessInfo->hProcess, StringUtils::Utf8ToUtf16(customSearchPath).c_str()))
{
dputs("SymSetSearchPath (1) failed!");
dputs("SymSetSearchPathW (1) failed!");
return;
}
@ -173,8 +173,8 @@ void SymDownloadAllSymbols(const char* SymbolStore)
}
// Restore the old search path
if(!SafeSymSetSearchPath(fdProcessInfo->hProcess, oldSearchPath))
dputs("SymSetSearchPath (2) failed!");
if(!SafeSymSetSearchPathW(fdProcessInfo->hProcess, oldSearchPath))
dputs("SymSetSearchPathW (2) failed!");
}
bool SymAddrFromName(const char* Name, uint* Address)

View File

@ -126,7 +126,7 @@ bool ThreadGetTeb(uint TEBAddress, TEB* Teb)
//
memset(Teb, 0, sizeof(TEB));
return MemRead(TEBAddress, Teb, sizeof(TEB), nullptr);
return MemRead(TEBAddress, Teb, sizeof(TEB));
}
int ThreadGetSuspendCount(HANDLE Thread)

View File

@ -1550,7 +1550,7 @@ bool valfromstring_noexpr(const char* string, uint* value, bool silent, bool bas
}
uint addr = *value;
*value = 0;
if(!MemRead(addr, value, read_size, 0))
if(!MemRead(addr, value, read_size))
{
if(!silent)
dputs("failed to read memory");
@ -2151,7 +2151,7 @@ bool valtostring(const char* string, uint value, bool silent)
return false;
}
uint value_ = value;
if(!MemPatch(temp, &value_, read_size, 0))
if(!MemPatch(temp, &value_, read_size))
{
if(!silent)
dputs("failed to write memory");

View File

@ -18,6 +18,7 @@
#include "_dbgfunctions.h"
#include "debugger_commands.h"
#include "capstone_wrapper.h"
#include "_scriptapi_gui.h"
static MESSAGE_STACK* gMsgStack = 0;
static COMMAND* command_list = 0;
@ -189,7 +190,6 @@ static void registercommands()
dbgcmdnew("yara", cbInstrYara, true); //yara test command
dbgcmdnew("yaramod", cbInstrYaramod, true); //yara rule on module
dbgcmdnew("analyse\1analyze\1anal", cbInstrAnalyse, true); //secret analysis command
dbgcmdnew("analyse_nukem\1analyze_nukem\1anal_nukem", cbInstrAnalyseNukem, true); //secret analysis command #2
//undocumented
dbgcmdnew("bench", cbDebugBenchmark, true); //benchmark test (readmem etc)
@ -202,6 +202,8 @@ static void registercommands()
dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis
dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs
dbgcmdnew("cfanal\1cfanalyse\1cfanalyze", cbInstrCfanalyse, true); //control flow analysis
dbgcmdnew("analyse_nukem\1analyze_nukem\1anal_nukem", cbInstrAnalyseNukem, true); //secret analysis command #2
dbgcmdnew("exanal\1exanalyse\1exanalyze", cbInstrExanalyse, true); //exception directory analysis
}
static bool cbCommandProvider(char* cmd, int maxlen)
@ -273,8 +275,25 @@ extern "C" DLL_EXPORT const char* _dbg_dbginit()
strcpy_s(dbbasepath, dir); //debug directory
strcat_s(dbbasepath, "\\db");
CreateDirectoryW(StringUtils::Utf8ToUtf16(dbbasepath).c_str(), 0); //create database directory
strcpy_s(szSymbolCachePath, dir);
strcat_s(szSymbolCachePath, "\\symbols");
char szLocalSymbolPath[MAX_PATH] = "";
strcpy_s(szLocalSymbolPath, dir);
strcat_s(szLocalSymbolPath, "\\symbols");
if(!BridgeSettingGet("Symbols", "CachePath", szSymbolCachePath) || !*szSymbolCachePath)
{
strcpy_s(szSymbolCachePath, szLocalSymbolPath);
BridgeSettingSet("Symbols", "CachePath", szLocalSymbolPath);
}
else
{
if(strstr(szSymbolCachePath, "http://") || strstr(szSymbolCachePath, "https://"))
{
if(Script::Gui::MessageYesNo("It is strongly discouraged to use symbol servers in your path directly (use the store option instead).\n\nDo you want me to fix this?"))
{
strcpy_s(szSymbolCachePath, szLocalSymbolPath);
BridgeSettingSet("Symbols", "CachePath", szLocalSymbolPath);
}
}
}
SetCurrentDirectoryW(StringUtils::Utf8ToUtf16(dir).c_str());
dputs("Allocating message stack...");
gMsgStack = MsgAllocStack();

View File

@ -40,10 +40,11 @@
<ClCompile Include="disasm_helper.cpp" />
<ClCompile Include="error.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="exceptiondirectoryanalysis.cpp" />
<ClCompile Include="expressionparser.cpp" />
<ClCompile Include="filereader.cpp" />
<ClCompile Include="function.cpp" />
<ClCompile Include="functionanalysis.cpp" />
<ClCompile Include="linearanalysis.cpp" />
<ClCompile Include="FunctionPass.cpp" />
<ClCompile Include="instruction.cpp" />
<ClCompile Include="Int3CoagulatorPass.cpp" />
@ -119,10 +120,11 @@
<ClInclude Include="dynamicmem.h" />
<ClInclude Include="error.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="exceptiondirectoryanalysis.h" />
<ClInclude Include="expressionparser.h" />
<ClInclude Include="filereader.h" />
<ClInclude Include="function.h" />
<ClInclude Include="functionanalysis.h" />
<ClInclude Include="linearanalysis.h" />
<ClInclude Include="FunctionPass.h" />
<ClInclude Include="handle.h" />
<ClInclude Include="instruction.h" />

View File

@ -216,9 +216,6 @@
<ClCompile Include="capstone_wrapper.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
<ClCompile Include="functionanalysis.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="filereader.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
@ -258,24 +255,30 @@
<ClCompile Include="Int3CoagulatorPass.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="controlflowanalysis.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_assembler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_misc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_stack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="analysis.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="analysis_nukem.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_assembler.cpp">
<Filter>Source Files\Interfaces/Exports\_scriptapi</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_misc.cpp">
<Filter>Source Files\Interfaces/Exports\_scriptapi</Filter>
</ClCompile>
<ClCompile Include="_scriptapi_stack.cpp">
<Filter>Source Files\Interfaces/Exports\_scriptapi</Filter>
</ClCompile>
<ClCompile Include="controlflowanalysis.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="exceptiondirectoryanalysis.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
<ClCompile Include="linearanalysis.cpp">
<Filter>Source Files\Analysis</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="x64_dbg.h">
@ -566,9 +569,6 @@
<ClInclude Include="capstone\xcore.h">
<Filter>Header Files\Third Party\capstone</Filter>
</ClInclude>
<ClInclude Include="functionanalysis.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="filereader.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
@ -614,23 +614,29 @@
<ClInclude Include="Int3CoagulatorPass.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="controlflowanalysis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_assembler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_misc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="analysis.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="analysis_nukem.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="controlflowanalysis.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_stack.h">
<Filter>Header Files\Interfaces/Exports\_scriptapi</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_assembler.h">
<Filter>Header Files\Interfaces/Exports\_scriptapi</Filter>
</ClInclude>
<ClInclude Include="_scriptapi_misc.h">
<Filter>Header Files\Interfaces/Exports\_scriptapi</Filter>
</ClInclude>
<ClInclude Include="exceptiondirectoryanalysis.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
<ClInclude Include="linearanalysis.h">
<Filter>Header Files\Analysis</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -21,7 +21,10 @@ Disassembly::Disassembly(QWidget* parent) : AbstractTableView(parent)
mHighlightToken.text = "";
mHighlightingMode = false;
mDisasm = new QBeaEngine();
int maxModuleSize = (int)ConfigUint("Disassembler", "MaxModuleSize");
Config()->writeUints();
mDisasm = new QBeaEngine(maxModuleSize);
mIsLastInstDisplayed = false;

View File

@ -52,16 +52,19 @@ void ReferenceView::setupContextMenu()
mFollowDumpAddress = new QAction("Follow in &Dump", this);
connect(mFollowDumpAddress, SIGNAL(triggered()), this, SLOT(followDumpAddress()));
mFollowApiAddress = new QAction("Follow &API Address", this);
connect(mFollowApiAddress, SIGNAL(triggered()), this, SLOT(followApiAddress()));
mToggleBreakpoint = new QAction("Toggle Breakpoint", this);
mToggleBreakpoint->setShortcutContext(Qt::WidgetShortcut);
this->addAction(mToggleBreakpoint);
addAction(mToggleBreakpoint);
mList->addAction(mToggleBreakpoint);
mSearchList->addAction(mToggleBreakpoint);
connect(mToggleBreakpoint, SIGNAL(triggered()), this, SLOT(toggleBreakpoint()));
mToggleBookmark = new QAction("Toggle Bookmark", this);
mToggleBookmark->setShortcutContext(Qt::WidgetShortcut);
this->addAction(mToggleBookmark);
addAction(mToggleBookmark);
mList->addAction(mToggleBookmark);
mSearchList->addAction(mToggleBookmark);
connect(mToggleBookmark, SIGNAL(triggered()), this, SLOT(toggleBookmark()));
@ -134,12 +137,12 @@ void ReferenceView::setSingleSelection(int index, bool scroll)
void ReferenceView::setSearchStartCol(int col)
{
if(col < mList->getColumnCount())
this->mSearchStartCol = col;
mSearchStartCol = col;
}
void ReferenceView::referenceContextMenu(QMenu* wMenu)
{
if(!this->mCurList->getRowCount())
if(!mCurList->getRowCount())
return;
QString text = mCurList->getCellContent(mCurList->getInitialSelection(), 0);
duint addr;
@ -149,6 +152,8 @@ void ReferenceView::referenceContextMenu(QMenu* wMenu)
return;
wMenu->addAction(mFollowAddress);
wMenu->addAction(mFollowDumpAddress);
if(apiAddressFromString(mCurList->getCellContent(mCurList->getInitialSelection(), 1)))
wMenu->addAction(mFollowApiAddress);
wMenu->addSeparator();
wMenu->addAction(mToggleBreakpoint);
wMenu->addAction(mToggleBookmark);
@ -156,13 +161,20 @@ void ReferenceView::referenceContextMenu(QMenu* wMenu)
void ReferenceView::followAddress()
{
DbgCmdExecDirect(QString("disasm " + this->mCurList->getCellContent(this->mCurList->getInitialSelection(), 0)).toUtf8().constData());
DbgCmdExecDirect(QString("disasm " + mCurList->getCellContent(mCurList->getInitialSelection(), 0)).toUtf8().constData());
emit showCpu();
}
void ReferenceView::followDumpAddress()
{
DbgCmdExecDirect(QString("dump " + this->mCurList->getCellContent(this->mCurList->getInitialSelection(), 0)).toUtf8().constData());
DbgCmdExecDirect(QString("dump " + mCurList->getCellContent(mCurList->getInitialSelection(), 0)).toUtf8().constData());
emit showCpu();
}
void ReferenceView::followApiAddress()
{
int_t apiValue = apiAddressFromString(mCurList->getCellContent(mCurList->getInitialSelection(), 1));
DbgCmdExecDirect(QString("disasm " + QString().sprintf("%p", apiValue)).toUtf8().constData());
emit showCpu();
}
@ -179,9 +191,9 @@ void ReferenceView::toggleBreakpoint()
if(!DbgIsDebugging())
return;
if(!this->mCurList->getRowCount())
if(!mCurList->getRowCount())
return;
QString addrText = this->mCurList->getCellContent(this->mCurList->getInitialSelection(), 0).toUtf8().constData();
QString addrText = mCurList->getCellContent(mCurList->getInitialSelection(), 0).toUtf8().constData();
duint wVA;
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
return;
@ -208,9 +220,9 @@ void ReferenceView::toggleBookmark()
if(!DbgIsDebugging())
return;
if(!this->mCurList->getRowCount())
if(!mCurList->getRowCount())
return;
QString addrText = this->mCurList->getCellContent(this->mCurList->getInitialSelection(), 0);
QString addrText = mCurList->getCellContent(mCurList->getInitialSelection(), 0);
duint wVA;
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
return;
@ -232,3 +244,17 @@ void ReferenceView::toggleBookmark()
}
GuiUpdateAllViews();
}
int_t ReferenceView::apiAddressFromString(const QString & s)
{
QRegExp regEx("call.+<(.+)>");
regEx.indexIn(s);
QStringList list = regEx.capturedTexts();
if(list.length() < 2)
return 0;
QString match = list[1];
if(match[0] == QChar('&'))
match.remove(0, 1);
duint value;
return DbgFunctions()->ValFromString(match.toUtf8().constData(), &value) && DbgMemIsValidReadPtr(value) ? value : 0;
}

View File

@ -24,6 +24,7 @@ private slots:
void referenceContextMenu(QMenu* wMenu);
void followAddress();
void followDumpAddress();
void followApiAddress();
void followGenericAddress();
void toggleBreakpoint();
void toggleBookmark();
@ -36,10 +37,13 @@ private:
QProgressBar* mSearchProgress;
QAction* mFollowAddress;
QAction* mFollowDumpAddress;
QAction* mFollowApiAddress;
QAction* mToggleBreakpoint;
QAction* mToggleBookmark;
bool mFollowDumpDefault;
QLabel* mCountLabel;
int_t apiAddressFromString(const QString & s);
};
#endif // REFERENCEVIEW_H

View File

@ -308,6 +308,7 @@ void StdTable::copyLineSlot()
QString title = mCopyTitles.at(i);
if(title.length())
finalText += title + "=";
while(cellContent.endsWith(" ")) cellContent.chop(1);
finalText += cellContent;
finalText += "\r\n";
}
@ -353,7 +354,7 @@ void StdTable::copyTableSlot()
finalRowText += " ";
QString cellContent = getCellContent(i, j);
int colWidth = getColumnWidth(j) / charwidth;
if(colWidth)
if(colWidth && j != colCount - 1)
finalRowText += cellContent.leftJustified(colWidth, QChar(' '), true);
else
finalRowText += cellContent;
@ -370,7 +371,9 @@ void StdTable::copyEntrySlot()
if(!action)
return;
int col = action->objectName().toInt();
Bridge::CopyToClipboard(getCellContent(getInitialSelection(), col));
QString finalText = getCellContent(getInitialSelection(), col);
while(finalText.endsWith(" ")) finalText.chop(1);
Bridge::CopyToClipboard(finalText);
}
void StdTable::setupCopyMenu(QMenu* copyMenu)

File diff suppressed because it is too large Load Diff

View File

@ -23,75 +23,18 @@ public:
static Bridge* getBridge();
static void initBridge();
// Message processing function
void* processMessage(GUIMSG type, void* param1, void* param2);
// Misc functions
static void CopyToClipboard(const QString & text);
//result function
void setResult(int_t result = 0);
// Exports Binding
void emitDisassembleAtSignal(int_t va, int_t eip);
void emitUpdateDisassembly();
void emitDbgStateChanged(DBGSTATE state);
void emitAddMsgToLog(QString msg);
void emitClearLog();
void emitUpdateRegisters();
void emitUpdateBreakpoints();
void emitUpdateWindowTitle(QString filename);
void emitDumpAt(int_t va);
void emitScriptAdd(int count, const char** lines);
void emitScriptClear();
void emitScriptSetIp(int line);
void emitScriptError(int line, QString message);
void emitScriptSetTitle(QString title);
void emitScriptSetInfoLine(int line, QString info);
void emitScriptMessage(QString message);
int emitScriptQuestion(QString message);
void emitScriptEnableHighlighting(bool enable);
void emitUpdateSymbolList(int module_count, SYMBOLMODULEINFO* modules);
void emitAddMsgToSymbolLog(QString msg);
void emitClearSymbolLog();
void emitSetSymbolProgress(int progress);
void emitReferenceAddColumnAt(int width, QString title);
void emitReferenceSetRowCount(int_t count);
void emitReferenceSetCellContent(int r, int c, QString s);
void emitReferenceReloadData();
void emitReferenceSetSingleSelection(int index, bool scroll);
void emitReferenceSetProgress(int progress);
void emitReferenceSetSearchStartCol(int col);
void emitReferenceInitialize(QString name);
void emitStackDumpAt(uint_t va, uint_t csp);
void emitUpdateDump();
void emitUpdateThreads();
void emitUpdateMemory();
void emitAddRecentFile(QString file);
void emitSetLastException(unsigned int exceptionCode);
void emitMenuAddToList(QWidget* parent, QMenu* menu, int hMenu, int hParentMenu = -1);
int emitMenuAddMenu(int hMenu, QString title);
int emitMenuAddMenuEntry(int hMenu, QString title);
void emitMenuAddSeparator(int hMenu);
void emitMenuClearMenu(int hMenu);
void emitMenuRemoveEntry(int hEntry);
bool emitSelectionGet(int hWindow, SELECTIONDATA* selection);
bool emitSelectionSet(int hWindow, const SELECTIONDATA* selection);
bool emitGetStrWindow(const QString title, QString* text);
void emitAutoCompleteAddCmd(const QString cmd);
void emitAutoCompleteDelCmd(const QString cmd);
void emitAutoCompleteClearAll();
void emitAddMsgToStatusBar(QString msg);
void emitUpdateSideBar();
void emitRepaintTableView();
void emitUpdatePatches();
void emitUpdateCallStack();
void emitSymbolRefreshCurrent();
//helper functions
void emitLoadSourceFile(const QString path, int line = 0, int selection = 0);
void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon);
void emitSetMenuIcon(int hMenu, const ICONDATA* icon);
void emitShowCpu();
void emitAddQWidgetTab(QWidget* qWidget);
void emitShowQWidgetTab(QWidget* qWidget);
void emitCloseQWidgetTab(QWidget* qWidget);
void emitExecuteOnGuiThread(void* cbGuiThread);
void emitMenuAddToList(QWidget* parent, QMenu* menu, int hMenu, int hParentMenu = -1);
//Public variables
void* winId;
@ -170,9 +113,6 @@ private:
QMutex* mBridgeMutex;
int_t bridgeResult;
volatile bool hasBridgeResult;
public:
};
#endif // BRIDGE_H

View File

@ -172,20 +172,26 @@ void BeaTokenizer::Mnemonic(BeaInstructionToken* instr, const DISASM* disasm)
}
}
QString BeaTokenizer::PrintValue(const BeaTokenValue* value, bool module)
QString BeaTokenizer::PrintValue(const BeaTokenValue* value, bool module, int maxModuleSize)
{
char labelText[MAX_LABEL_SIZE] = "";
char moduleText[MAX_MODULE_SIZE] = "";
char module_[MAX_MODULE_SIZE] = "";
QString moduleText;
int_t addr = value->value;
bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, labelText);
bool bHasModule = (module && DbgGetModuleAt(addr, moduleText) && !QString(labelText).startsWith("JMP.&"));
bool bHasModule = (module && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&"));
moduleText = QString(module_);
if(maxModuleSize != -1)
moduleText.truncate(maxModuleSize);
if(moduleText.length())
moduleText += ".";
QString addrText;
addrText = QString("%1").arg(addr & (uint_t) - 1, 0, 16, QChar('0')).toUpper();
QString finalText;
if(bHasLabel && bHasModule) //<module.label>
finalText = QString("<%1.%2>").arg(moduleText).arg(labelText);
finalText = QString("<%1%2>").arg(moduleText).arg(labelText);
else if(bHasModule) //module.addr
finalText = QString("%1.%2").arg(moduleText).arg(addrText);
finalText = QString("%1%2").arg(moduleText).arg(addrText);
else if(bHasLabel) //<label>
finalText = QString("<%1>").arg(labelText);
else
@ -204,7 +210,7 @@ QString BeaTokenizer::RegisterToString(int size, int reg)
return currentMap->find(regValue).value();
}
void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg)
void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg, int maxModuleSize)
{
if(arg->ArgType == NO_ARGUMENT || !arg->ArgMnemonic[0]) //empty/implicit argument
return;
@ -287,7 +293,7 @@ void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, co
BeaTokenType type = TokenValue;
if(DbgMemIsValidReadPtr(displacement.value)) //pointer
type = TokenAddress;
AddToken(instr, type, PrintValue(&printDisplacement, false), &displacement);
AddToken(instr, type, PrintValue(&printDisplacement, false, maxModuleSize), &displacement);
}
AddToken(instr, bracketsType, "]", 0);
}
@ -296,7 +302,7 @@ void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, co
BeaTokenValue value;
value.size = arg->ArgSize / 8;
value.value = disasm->Instruction.AddrValue;
AddToken(instr, TokenAddress, PrintValue(&value, true), &value);
AddToken(instr, TokenAddress, PrintValue(&value, true, maxModuleSize), &value);
}
else if((arg->ArgType & CONSTANT_TYPE) == CONSTANT_TYPE) //immediat
{
@ -326,7 +332,7 @@ void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, co
BeaTokenType type = TokenValue;
if(DbgMemIsValidReadPtr(value.value)) //pointer
type = TokenAddress;
AddToken(instr, type, PrintValue(&value, true), &value);
AddToken(instr, type, PrintValue(&value, true, maxModuleSize), &value);
}
else if((arg->ArgType & REGISTER_TYPE) == REGISTER_TYPE) //registers
{
@ -527,7 +533,7 @@ unsigned long BeaTokenizer::HashInstruction(const DISASM* disasm)
return hash;
}
void BeaTokenizer::TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm)
void BeaTokenizer::TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm, int maxModuleSize)
{
//initialization
instr->hash = HashInstruction(disasm); //hash instruction
@ -548,18 +554,18 @@ void BeaTokenizer::TokenizeInstruction(BeaInstructionToken* instr, const DISASM*
BeaTokenValue val;
val.size = 2;
val.value = segment;
AddToken(instr, TokenValue, PrintValue(&val, true), &val);
AddToken(instr, TokenValue, PrintValue(&val, true, maxModuleSize), &val);
AddToken(instr, TokenUncategorized, ":", 0);
val.size = 4;
val.value = address;
AddToken(instr, TokenAddress, PrintValue(&val, true), &val);
AddToken(instr, TokenAddress, PrintValue(&val, true, maxModuleSize), &val);
}
else
{
bool hadarg = false;
Argument(instr, disasm, &disasm->Argument1, &hadarg);
Argument(instr, disasm, &disasm->Argument2, &hadarg);
Argument(instr, disasm, &disasm->Argument3, &hadarg);
Argument(instr, disasm, &disasm->Argument1, &hadarg, maxModuleSize);
Argument(instr, disasm, &disasm->Argument2, &hadarg, maxModuleSize);
Argument(instr, disasm, &disasm->Argument3, &hadarg, maxModuleSize);
}
//remove spaces when needed

View File

@ -78,7 +78,7 @@ public:
static void Init();
static unsigned long HashInstruction(const DISASM* disasm);
static void TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm);
static void TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm, int maxModuleSize);
static void TokenToRichText(const BeaInstructionToken* instr, QList<RichTextPainter::CustomRichText_t>* richTextList, const BeaSingleToken* highlightToken);
static bool TokenFromX(const BeaInstructionToken* instr, BeaSingleToken* token, int x, int charwidth);
static bool IsHighlightableToken(const BeaSingleToken* token);
@ -99,9 +99,9 @@ private:
static void StringInstructionMemory(BeaInstructionToken* instr, int size, QString segment, ARGUMENTS_TYPE reg);
static void StringInstruction(QString mnemonic, BeaInstructionToken* instr, const DISASM* disasm);
static void Mnemonic(BeaInstructionToken* instr, const DISASM* disasm);
static QString PrintValue(const BeaTokenValue* value, bool module);
static QString PrintValue(const BeaTokenValue* value, bool module, int maxModuleSize);
static QString RegisterToString(int size, int reg);
static void Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg);
static void Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg, int maxModuleSize);
static void AddColorName(BeaTokenType type, QString color, QString backgroundColor);
};

View File

@ -1,7 +1,8 @@
#include "QBeaEngine.h"
QBeaEngine::QBeaEngine()
QBeaEngine::QBeaEngine(int maxModuleSize)
{
mMaxModuleSize = maxModuleSize;
// Reset the Disasm structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
BeaTokenizer::Init();
@ -182,7 +183,7 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, uint_t size, uint_t instIn
wInst.disasm = mDisasmStruct;
//tokenize
BeaTokenizer::TokenizeInstruction(&wInst.tokens, &mDisasmStruct);
BeaTokenizer::TokenizeInstruction(&wInst.tokens, &mDisasmStruct, mMaxModuleSize);
return wInst;
}

View File

@ -18,13 +18,14 @@ typedef struct _Instruction_t
class QBeaEngine
{
public:
explicit QBeaEngine();
explicit QBeaEngine(int maxModuleSize);
ulong DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t ip, int n);
ulong DisassembleNext(byte_t* data, uint_t base, uint_t size, uint_t ip, int n);
Instruction_t DisassembleAt(byte_t* data, uint_t size, uint_t instIndex, uint_t origBase, uint_t origInstRVA);
private:
DISASM mDisasmStruct;
int mMaxModuleSize;
};
#endif // QBEAENGINE_H

View File

@ -917,7 +917,7 @@ void CPUDisassembly::assembleAt()
mMemPage->read(reinterpret_cast<byte_t*>(wBuffer.data()), wRVA, wMaxByteCountToRead);
QBeaEngine disasm;
QBeaEngine disasm(-1);
Instruction_t instr = disasm.DisassembleAt(reinterpret_cast<byte_t*>(wBuffer.data()), wMaxByteCountToRead, 0, 0, wVA);
QString actual_inst = instr.instStr;

View File

@ -211,9 +211,22 @@ void SettingsDialog::LoadSettings()
{
ui->chkSetJIT->setDisabled(true);
ui->chkConfirmBeforeAtt->setDisabled(true);
ui->lbladminwarning->setText(QString("Warning: Run the debugger as Admin to enable JIT."));
ui->lblAdminWarning->setText(QString("<font color=\"red\"><b>Warning</b></font>: Run the debugger as Admin to enable JIT."));
}
else
ui->lblAdminWarning->setText("");
}
char setting[MAX_SETTING_SIZE] = "";
if(BridgeSettingGet("Symbols", "DefaultStore", setting))
ui->editSymbolStore->setText(QString(setting));
else
{
QString defaultStore = "http://msdl.microsoft.com/download/symbols";
ui->editSymbolStore->setText(defaultStore);
BridgeSettingSet("Symbols", "DefaultStore", defaultStore.toUtf8().constData());
}
if(BridgeSettingGet("Symbols", "CachePath", setting))
ui->editSymbolCache->setText(QString(setting));
bJitOld = settings.miscSetJIT;
bJitAutoOld = settings.miscSetJITAuto;
@ -279,6 +292,10 @@ void SettingsDialog::SaveSettings()
DbgCmdExecDirect("setjitauto off");
}
}
if(settings.miscSymbolStore)
BridgeSettingSet("Symbols", "DefaultStore", ui->editSymbolStore->text().toUtf8().constData());
if(settings.miscSymbolCache)
BridgeSettingSet("Symbols", "CachePath", ui->editSymbolCache->text().toUtf8().constData());
Config()->load();
DbgSettingsUpdated();
@ -594,3 +611,13 @@ void SettingsDialog::on_chkTabBetweenMnemonicAndArguments_stateChanged(int arg1)
{
settings.disasmTabBetweenMnemonicAndArguments = arg1 == Qt::Checked;
}
void SettingsDialog::on_editSymbolStore_textEdited(const QString & arg1)
{
settings.miscSymbolStore = true;
}
void SettingsDialog::on_editSymbolCache_textEdited(const QString & arg1)
{
settings.miscSymbolCache = true;
}

View File

@ -59,6 +59,8 @@ private slots:
//Misc tab
void on_chkSetJIT_stateChanged(int arg1);
void on_chkConfirmBeforeAtt_stateChanged(int arg1);
void on_editSymbolStore_textEdited(const QString & arg1);
void on_editSymbolCache_textEdited(const QString & arg1);
private:
//enums
@ -123,6 +125,8 @@ private:
//Misc Tab
bool miscSetJIT;
bool miscSetJITAuto;
bool miscSymbolStore;
bool miscSymbolCache;
};
//variables

View File

@ -426,60 +426,89 @@
<attribute name="title">
<string>Misc</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="chkSetJIT">
<property name="text">
<string>Set x64dbg as Just In Time Debugger</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>JIT:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editJIT">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="chkConfirmBeforeAtt">
<property name="text">
<string>Confirm before attaching</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbladminwarning">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>11</x>
<y>13</y>
<width>341</width>
<height>145</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Symbol Store:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Symbol Path:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLineEdit" name="editSymbolStore"/>
</item>
<item>
<widget class="QLineEdit" name="editSymbolCache"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="chkSetJIT">
<property name="text">
<string>Set x64dbg as Just In Time Debugger</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>JIT:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editJIT">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="chkConfirmBeforeAtt">
<property name="text">
<string>Confirm before attaching</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblAdminWarning">
<property name="text">
<string>&lt;font color=&quot;red&quot;&gt;DIE SCUM!&lt;/font&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>

View File

@ -40,7 +40,15 @@ void SourceView::setSelection(int line)
{
int offset = line - 1;
if(isValidIndex(offset, 0))
{
int rangefrom = getTableOffset();
int rangeto = rangefrom + getViewableRowsCount() - 1;
if(offset < rangefrom) //ip lays before the current view
setTableOffset(offset);
else if(offset > (rangeto - 1)) //ip lays after the current view
setTableOffset(offset - getViewableRowsCount() + 2);
setSingleSelection(offset);
}
reloadData(); //repaint
}

View File

@ -1,4 +1,5 @@
#include "StatusLabel.h"
#include <QTextDocument>
StatusLabel::StatusLabel(QStatusBar* parent) : QLabel(parent)
{
@ -55,8 +56,8 @@ void StatusLabel::logUpdate(QString message)
//only show the last line in the status label
QStringList lineList = labelText.split(QChar('\n'), QString::SkipEmptyParts);
if(lineList.size())
setText(lineList[lineList.length() - 1]);
setText(Qt::convertFromPlainText(lineList[lineList.length() - 1]));
else
setText(labelText);
setText(Qt::convertFromPlainText(labelText));
this->repaint();
}

View File

@ -170,6 +170,9 @@ Configuration::Configuration() : QObject()
QMap<QString, uint_t> hexdumpUint;
hexdumpUint.insert("DefaultView", 0);
defaultUints.insert("HexDump", hexdumpUint);
QMap<QString, uint_t> disasmUint;
disasmUint.insert("MaxModuleSize", -1);
defaultUints.insert("Disassembler", disasmUint);
//font settings
QFont font("Lucida Console", 8, QFont::Normal, false);
@ -295,7 +298,6 @@ Configuration* Config()
return mPtr;
}
void Configuration::load()
{
readColors();