1
0
Fork 0

Parse syscall indices and display the Nt function name in the comments

This commit is contained in:
Duncan Ogilvie 2020-10-22 01:22:42 +02:00
parent a73b4273cd
commit 8ef53a1931
6 changed files with 111 additions and 16 deletions

View File

@ -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));

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;