Parse syscall indices and display the Nt function name in the comments
This commit is contained in:
parent
a73b4273cd
commit
8ef53a1931
|
@ -363,6 +363,21 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, BRID
|
|||
instr.arg[i].value = instr.arg[i].constant;
|
||||
}
|
||||
|
||||
if(addr == lastContext.cip && (cp.GetId() == ZYDIS_MNEMONIC_SYSCALL || (cp.GetId() == ZYDIS_MNEMONIC_INT && cp[0].imm.value.u == 0x2e)))
|
||||
{
|
||||
auto syscallName = SyscallToName(lastContext.cax);
|
||||
if(!syscallName.empty())
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(syscallName);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < instr.argcount; i++)
|
||||
{
|
||||
memset(&newinfo, 0, sizeof(BRIDGE_ADDRINFO));
|
||||
|
|
|
@ -9,6 +9,7 @@ static std::unordered_map<unsigned int, String> ExceptionNames;
|
|||
static std::unordered_map<unsigned int, String> NtStatusNames;
|
||||
static std::unordered_map<unsigned int, String> ErrorNames;
|
||||
static std::unordered_map<String, unsigned int> Constants;
|
||||
static std::unordered_map<unsigned int, String> SyscallIndices;
|
||||
|
||||
static bool UniversalCodeInit(const String & file, std::unordered_map<unsigned int, String> & names, unsigned char radix)
|
||||
{
|
||||
|
@ -181,3 +182,66 @@ std::vector<CONSTANTINFO> ErrorCodeList()
|
|||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
|
||||
bool SyscallInit()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockModules);
|
||||
auto retrieveSyscalls = [](const char* modname)
|
||||
{
|
||||
auto ntdll = GetModuleHandleA(modname);
|
||||
if(!ntdll)
|
||||
return false;
|
||||
char szModuleName[MAX_PATH];
|
||||
if(!GetModuleFileNameA(ntdll, szModuleName, _countof(szModuleName)))
|
||||
return false;
|
||||
if(!ModLoad((duint)ntdll, 1, szModuleName))
|
||||
return false;
|
||||
auto info = ModInfoFromAddr((duint)ntdll);
|
||||
if(info)
|
||||
{
|
||||
for(const MODEXPORT & export : info->exports)
|
||||
{
|
||||
if(strncmp(export.name.c_str(), "Nt", 2) != 0)
|
||||
continue;
|
||||
auto exportData = (const unsigned char*)ModRvaToOffset(info->fileMapVA, info->headers, export.rva);
|
||||
if(!exportData)
|
||||
continue;
|
||||
// https://github.com/mrexodia/TitanHide/blob/1c6ba9796e320f399f998b23fba2729122597e87/TitanHide/ntdll.cpp#L75
|
||||
DWORD index = -1;
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
if(exportData[i] == 0xC2 || exportData[i] == 0xC3) //RET
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(exportData[i] == 0xB8) //mov eax,X
|
||||
{
|
||||
index = *(DWORD*)(exportData + i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(index != -1)
|
||||
SyscallIndices.emplace(index, export.name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// TODO: support windows < 10 for user32
|
||||
// See: https://github.com/x64dbg/ScyllaHide/blob/6817d32581b7a420322f34e36b1a1c8c3e4b434c/Scylla/Win32kSyscalls.h
|
||||
auto result = retrieveSyscalls("ntdll.dll") && retrieveSyscalls("win32u.dll");
|
||||
ModClear(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
const String & SyscallToName(unsigned int index)
|
||||
{
|
||||
auto found = SyscallIndices.find(index);
|
||||
return found != SyscallIndices.end() ? found->second : emptyString;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _EXCEPTION_H
|
||||
#define _EXCEPTION_H
|
||||
|
||||
// TODO: rename this file
|
||||
|
||||
#define MS_VC_EXCEPTION 0x406D1388
|
||||
|
||||
#include "_global.h"
|
||||
|
@ -19,5 +21,7 @@ bool ExceptionNameToCode(const char* Name, unsigned int* ErrorCode);
|
|||
bool ConstantCodeInit(const String & constantFile);
|
||||
bool ConstantFromName(const String & name, duint & value);
|
||||
std::vector<CONSTANTINFO> ConstantList();
|
||||
bool SyscallInit();
|
||||
const String & SyscallToName(unsigned int index);
|
||||
|
||||
#endif // _EXCEPTION_H
|
|
@ -60,7 +60,7 @@ static NTSTATUS ImageNtHeaders(duint base, duint size, PIMAGE_NT_HEADERS* outHea
|
|||
}
|
||||
|
||||
// Use only with SEC_COMMIT mappings, not SEC_IMAGE! (in that case, just do VA = base + rva...)
|
||||
static ULONG64 RvaToVa(ULONG64 base, PIMAGE_NT_HEADERS ntHeaders, ULONG64 rva)
|
||||
ULONG64 ModRvaToOffset(ULONG64 base, PIMAGE_NT_HEADERS ntHeaders, ULONG64 rva)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
for(WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
||||
|
@ -96,7 +96,7 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
|
||||
auto rva2offset = [&Info](ULONG64 rva)
|
||||
{
|
||||
return RvaToVa(0, Info.headers, rva);
|
||||
return ModRvaToOffset(0, Info.headers, rva);
|
||||
};
|
||||
|
||||
auto addressOfFunctionsOffset = rva2offset(exportDir->AddressOfFunctions);
|
||||
|
@ -138,7 +138,7 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
auto & entry = Info.exports.back();
|
||||
entry.ordinal = i + exportDir->Base;
|
||||
entry.rva = addressOfFunctions[i];
|
||||
const auto entryVa = RvaToVa(FileMapVA, Info.headers, entry.rva);
|
||||
const auto entryVa = ModRvaToOffset(FileMapVA, Info.headers, entry.rva);
|
||||
entry.forwarded = entryVa >= (ULONG64)exportDir && entryVa < (ULONG64)exportDir + exportDirSize;
|
||||
if(entry.forwarded)
|
||||
{
|
||||
|
@ -232,7 +232,7 @@ static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
const ULONG64 ordinalFlag = IMAGE64(Info.headers) ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32;
|
||||
auto rva2offset = [&Info](ULONG64 rva)
|
||||
{
|
||||
return RvaToVa(0, Info.headers, rva);
|
||||
return ModRvaToOffset(0, Info.headers, rva);
|
||||
};
|
||||
|
||||
for(size_t moduleIndex = 0; importDescriptor->Name != 0; ++importDescriptor, ++moduleIndex)
|
||||
|
@ -326,7 +326,7 @@ static void ReadTlsCallbacks(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
return;
|
||||
|
||||
auto imageBase = HEADER_FIELD(Info.headers, ImageBase);
|
||||
auto tlsArrayOffset = RvaToVa(0, Info.headers, tlsDir->AddressOfCallBacks - imageBase);
|
||||
auto tlsArrayOffset = ModRvaToOffset(0, Info.headers, tlsDir->AddressOfCallBacks - imageBase);
|
||||
if(!tlsArrayOffset)
|
||||
return;
|
||||
|
||||
|
@ -463,7 +463,7 @@ static void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
const auto supported = [&Info](PIMAGE_DEBUG_DIRECTORY entry)
|
||||
{
|
||||
// Check for valid RVA
|
||||
const auto offset = RvaToVa(0, Info.headers, entry->AddressOfRawData);
|
||||
const auto offset = ModRvaToOffset(0, Info.headers, entry->AddressOfRawData);
|
||||
if(!offset)
|
||||
return false;
|
||||
|
||||
|
@ -556,7 +556,7 @@ static void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
}
|
||||
|
||||
// At this point we know the entry is a valid CV one
|
||||
auto cvData = (unsigned char*)(FileMapVA + RvaToVa(0, Info.headers, entry->AddressOfRawData));
|
||||
auto cvData = (unsigned char*)(FileMapVA + ModRvaToOffset(0, Info.headers, entry->AddressOfRawData));
|
||||
auto signature = *(DWORD*)cvData;
|
||||
if(signature == '01BN')
|
||||
{
|
||||
|
@ -757,7 +757,7 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
#undef GetUnsafeModuleInfo
|
||||
}
|
||||
|
||||
bool ModLoad(duint Base, duint Size, const char* FullPath)
|
||||
bool ModLoad(duint Base, duint Size, const char* FullPath, bool loadSymbols)
|
||||
{
|
||||
// Handle a new module being loaded
|
||||
if(!Base || !Size || !FullPath)
|
||||
|
@ -863,11 +863,14 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
|
|||
}
|
||||
|
||||
info.symbols = &EmptySymbolSource; // empty symbol source per default
|
||||
// TODO: setting to auto load symbols
|
||||
for(const auto & pdbPath : info.pdbPaths)
|
||||
|
||||
if(loadSymbols)
|
||||
{
|
||||
if(info.loadSymbols(pdbPath, bForceLoadSymbols))
|
||||
break;
|
||||
for(const auto & pdbPath : info.pdbPaths)
|
||||
{
|
||||
if(info.loadSymbols(pdbPath, bForceLoadSymbols))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add module to list
|
||||
|
@ -910,7 +913,7 @@ bool ModUnload(duint Base)
|
|||
return true;
|
||||
}
|
||||
|
||||
void ModClear()
|
||||
void ModClear(bool updateGui)
|
||||
{
|
||||
{
|
||||
// Clean up all the modules
|
||||
|
@ -925,7 +928,8 @@ void ModClear()
|
|||
}
|
||||
|
||||
// Tell the symbol updater
|
||||
GuiSymbolUpdateModuleList(0, nullptr);
|
||||
if(updateGui)
|
||||
GuiSymbolUpdateModuleList(0, nullptr);
|
||||
}
|
||||
|
||||
MODINFO* ModInfoFromAddr(duint Address)
|
||||
|
|
|
@ -138,9 +138,10 @@ struct MODINFO
|
|||
const MODEXPORT* findExport(duint rva) const;
|
||||
};
|
||||
|
||||
bool ModLoad(duint Base, duint Size, const char* FullPath);
|
||||
ULONG64 ModRvaToOffset(ULONG64 base, PIMAGE_NT_HEADERS ntHeaders, ULONG64 rva);
|
||||
bool ModLoad(duint Base, duint Size, const char* FullPath, bool loadSymbols = true);
|
||||
bool ModUnload(duint Base);
|
||||
void ModClear();
|
||||
void ModClear(bool updateGui = true);
|
||||
MODINFO* ModInfoFromAddr(duint Address);
|
||||
bool ModNameFromAddr(duint Address, char* Name, bool Extension);
|
||||
duint ModBaseFromAddr(duint Address);
|
||||
|
|
|
@ -608,6 +608,13 @@ static DWORD WINAPI loadDbThread(LPVOID)
|
|||
else
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Reading notes failed..."));
|
||||
|
||||
// Load syscall indices
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Retrieving syscall indices..."));
|
||||
if(SyscallInit())
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Syscall indices loaded!"));
|
||||
else
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to load syscall indices..."));
|
||||
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "File read thread finished!"));
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue