Skip to content

Commit

Permalink
add scanners for datamap funcs, vprof funcs; implement more mod stuff…
Browse files Browse the repository at this point in the history
…, fixes
  • Loading branch information
sigsegv-mvm committed Jan 19, 2016
1 parent 1695aa5 commit 2612cc3
Show file tree
Hide file tree
Showing 28 changed files with 602 additions and 94 deletions.
1 change: 1 addition & 0 deletions AMBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ sourceFiles = [
'util/backtrace.cpp',
'stub/baseentity.cpp',
'stub/gamerules.cpp',
'stub/misc.cpp',
'stub/nav.cpp',
'stub/path.cpp',
'stub/populators.cpp',
Expand Down
3 changes: 3 additions & 0 deletions MSVC14/sigsegv.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<RemoveUnreferencedCodeData>false</RemoveUnreferencedCodeData>
<ForcedIncludeFiles>common.h</ForcedIncludeFiles>
<PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
<ObjectFileName>$(IntDir)\%(Directory)\</ObjectFileName>
</ClCompile>
<Link>
<AdditionalDependencies>$(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;$(HL2SDKOBVALVE)\lib\public\mathlib.lib;legacy_stdio_definitions.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand Down Expand Up @@ -110,6 +111,7 @@ copy $(TargetDir)\sigsegv.ext.2.tf2.pdb $(SolutionDir)\..\build\package\addons\s
<RemoveUnreferencedCodeData>false</RemoveUnreferencedCodeData>
<ForcedIncludeFiles>common.h</ForcedIncludeFiles>
<PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
<ObjectFileName>$(IntDir)\%(Directory)\</ObjectFileName>
</ClCompile>
<Link>
<AdditionalDependencies>$(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;$(HL2SDKOBVALVE)\lib\public\mathlib.lib;legacy_stdio_definitions.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand Down Expand Up @@ -169,6 +171,7 @@ copy $(TargetDir)\sigsegv.ext.2.tf2.pdb $(SolutionDir)\..\build\package\addons\s
<ClCompile Include="..\sm\MemoryUtils.cpp" />
<ClCompile Include="..\stub\baseentity.cpp" />
<ClCompile Include="..\stub\gamerules.cpp" />
<ClCompile Include="..\stub\misc.cpp" />
<ClCompile Include="..\stub\nav.cpp" />
<ClCompile Include="..\stub\path.cpp" />
<ClCompile Include="..\stub\populators.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions MSVC14/sigsegv.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
<ClCompile Include="..\mod\mod_botmulticlassitem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\stub\misc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\mod.h">
Expand Down
1 change: 1 addition & 0 deletions PackageScript
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ CopyFiles('include', 'addons/sourcemod/scripting/include',
CopyFiles('gamedata/sigsegv', 'addons/sourcemod/gamedata/sigsegv',
[
'sigsegv.vtable.txt',
'sigsegv.datamap.txt',
'sigsegv.globals.txt',
'sigsegv.nextbot.action.txt',
'sigsegv.nextbot.eventresponder.txt',
Expand Down
173 changes: 172 additions & 1 deletion addr/addr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void IAddr::Init()

if (result) {
this->m_State = State::OK;
// DevMsg("IAddr::Init \"%s\" OK 0x%08x\n", this->GetName(), this->m_iAddr);
DevMsg("IAddr::Init \"%s\" OK 0x%08x\n", this->GetName(), this->m_iAddr);
} else {
this->m_State = State::FAIL;
DevMsg("IAddr::Init \"%s\" FAIL\n", this->GetName());
Expand Down Expand Up @@ -158,6 +158,44 @@ bool IAddr_VTable::FindAddrWin(uintptr_t& addr) const
}


bool IAddr_DataDescMap::FindAddrWin(uintptr_t& addr) const
{
CSingleScan scan1(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".rdata"), 1, new CStringScanner(ScanResults::ALL, this->GetClassName()));
if (scan1.Matches().size() != 1) {
DevMsg("IAddr_DataDescMap: \"%s\": found %u matches for class name string\n", this->GetName(), scan1.Matches().size());
return false;
}
auto p_str = (const char *)scan1.Matches()[0];

CSingleScan scan2(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".data"), 4, new CBasicScanner(ScanResults::ALL, (const void *)&p_str, 0x4));
struct GetDataDescMap { uint8_t buf[6]; };
std::vector<IScanner *> scanners;
for (auto match : scan2.Matches()) {
GetDataDescMap gddm;
gddm.buf[0x00] = 0xb8; // mov eax,[????????]
*(uint32_t *)(&gddm.buf[0x01]) = (uint32_t)match - offsetof(datamap_t, dataClassName);
gddm.buf[0x05] = 0xc3; // ret

scanners.push_back(new CBasicScanner(ScanResults::ALL, (const void *)&gddm, 0x6));
}

CMultiScan scan3(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".text"), 0x10, scanners);
std::vector<const void *> results;
for (auto scanner : scanners) {
if (scanner->Matches().size() == 1) {
results.push_back(scanner->Matches()[0]);
}
}
if (results.size() != 1) {
DevMsg("IAddr_DataDescMap: \"%s\": found %u matches for GetDataDescMap func\n", this->GetName(), results.size());
return false;
}

addr = *(uintptr_t *)((uintptr_t)results[0] + 1);
return true;
}


bool IAddr_Func_KnownVTIdx::FindAddrWin(uintptr_t& addr) const
{
auto p_VT = (const uintptr_t *)AddrManager::GetAddr(this->GetVTableName());
Expand All @@ -171,6 +209,94 @@ bool IAddr_Func_KnownVTIdx::FindAddrWin(uintptr_t& addr) const
}


bool IAddr_Func_DataMap_VThunk::FindAddrWin(uintptr_t& addr) const
{
auto p_DM = (const datamap_t *)AddrManager::GetAddr(this->GetDataMapName());
if (p_DM == nullptr) {
DevMsg("IAddr_Func_DataMap_VThunk: \"%s\": no addr for datamap\n", this->GetName());
return false;
}

bool found_entry = false;
void *p_VThunk = nullptr;
for (int i = 0; i < p_DM->dataNumFields; ++i) {
const typedescription_t *td = p_DM->dataDesc + i;

if (td->fieldName != nullptr && strcmp(td->fieldName, this->GetFuncName()) == 0) {
union {
inputfunc_t inputFunc;
void *voidptr;
} u;

u.inputFunc = td->inputFunc;
p_VThunk = u.voidptr;

found_entry = true;
break;
}
}
if (!found_entry) {
DevMsg("IAddr_Func_DataMap_VThunk: \"%s\": could not find func entry in datamap\n", this->GetName());
return false;
}

constexpr uint8_t thunk[] = {
0x8b, 0x01, // mov eax,[ecx]
0xff, 0xa0, // jmp dword ptr [eax+0x????????]
};
if (memcmp(p_VThunk, thunk, 0x4) != 0) {
DevMsg("IAddr_Func_DataMap_VThunk: \"%s\": virtual thunk doesn't look quite right\n", this->GetName());
return false;
}
uint32_t vt_off = *(uint32_t *)((uintptr_t)p_VThunk + 0x4);
if (vt_off % 4 != 0) {
DevMsg("IAddr_Func_DataMap_VThunk: \"%s\": vt_off 0x%x isn't a multiple of 4\n", this->GetName(), vt_off);
return false;
}
uint32_t vt_idx = vt_off / 4;

auto p_VT = (const uintptr_t *)AddrManager::GetAddr(this->GetVTableName());
if (p_VT == nullptr) {
DevMsg("IAddr_Func_DataMap_VThunk: \"%s\": no addr for vtable\n", this->GetName());
return false;
}

addr = p_VT[vt_idx];
return true;
}


bool IAddr_Func_EBPPrologue_UniqueRef::FindAddrWin(uintptr_t& addr) const
{
auto p_ref = AddrManager::GetAddr(this->GetUniqueSymbol());
if (p_ref == nullptr) {
DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": no addr for ostensibly unique symbol\n", this->GetName());
return false;
}

CSingleScan scan1(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".text"), 1, new CBasicScanner(ScanResults::ALL, (const void *)&p_ref, 0x4));
if (scan1.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": found %u refs to ostensibly unique symbol\n", this->GetName(), scan1.Matches().size());
return false;
}
auto p_in_func = (const char **)scan1.Matches()[0];

constexpr uint8_t prologue[] = {
0x55, // +0000 push ebp
0x8b, 0xec, // +0001 mov ebp,esp
};
CSingleScan scan2(ScanDir::REVERSE, CAddrOffBounds(p_in_func, -0x1000), 0x10, new CBasicScanner(ScanResults::FIRST, (const void *)prologue, sizeof(prologue)));
if (scan2.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": could not locate EBP prologue\n", this->GetName());
return false;
}
auto p_func = (uintptr_t)scan2.Matches()[0];

addr = p_func;
return true;
}


bool IAddr_Func_EBPPrologue_UniqueStr::FindAddrWin(uintptr_t& addr) const
{
CSingleScan scan1(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".rdata"), 1, new CStringScanner(ScanResults::ALL, this->GetUniqueStr()));
Expand Down Expand Up @@ -245,3 +371,48 @@ bool IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx::FindAddrWin(uintptr_t& addr) c
addr = p_func;
return true;
}


bool IAddr_Func_EBPPrologue_VProf::FindAddrWin(uintptr_t& addr) const
{
CSingleScan scan1(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".rdata"), 1, new CStringScanner(ScanResults::ALL, this->GetVProfName()));
if (scan1.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": found %u matches for VProf name string\n", this->GetName(), scan1.Matches().size());
return false;
}
auto p_name = (const char *)scan1.Matches()[0];

CSingleScan scan2(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".rdata"), 1, new CStringScanner(ScanResults::ALL, this->GetVProfGroup()));
if (scan2.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": found %u matches for VProf group string\n", this->GetName(), scan2.Matches().size());
return false;
}
auto p_group = (const char *)scan2.Matches()[0];

uint8_t vprof[] = {
0x68, 0x00, 0x00, 0x00, 0x00, // push 0x????????
0x68, 0x00, 0x00, 0x00, 0x00, // push 0x????????
};
*(const char **)(vprof + 0x01) = p_name;
*(const char **)(vprof + 0x06) = p_group;
CSingleScan scan3(ScanDir::FORWARD, CLibSegBounds(this->GetLibrary(), ".text"), 1, new CBasicScanner(ScanResults::FIRST, (const void *)vprof, sizeof(vprof)));
if (scan3.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": could not locate VPROF_BUDGET\n", this->GetName());
return false;
}
auto p_in_func = scan3.Matches()[0];

constexpr uint8_t prologue[] = {
0x55, // +0000 push ebp
0x8b, 0xec, // +0001 mov ebp,esp
};
CSingleScan scan4(ScanDir::REVERSE, CAddrOffBounds(p_in_func, -0x1000), 0x10, new CBasicScanner(ScanResults::FIRST, (const void *)prologue, sizeof(prologue)));
if (scan4.Matches().size() != 1) {
DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": could not locate EBP prologue\n", this->GetName());
return false;
}
auto p_func = (uintptr_t)scan4.Matches()[0];

addr = p_func;
return true;
}
123 changes: 120 additions & 3 deletions addr/addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,32 @@ class CAddr_VTable : public IAddr_VTable
};


class IAddr_DataDescMap : public IAddr_Sym
{
public:
virtual bool FindAddrWin(uintptr_t& addr) const override;

protected:
virtual const char *GetClassName() const = 0;
};

class CAddr_DataDescMap : public IAddr_DataDescMap
{
public:
CAddr_DataDescMap(const std::string& name, const std::string& sym, const std::string& class_name) :
m_strName(name), m_strSymbol(sym), m_strClassName(class_name) {}

virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetClassName() const override { return this->m_strClassName.c_str(); }

private:
std::string m_strName;
std::string m_strSymbol;
std::string m_strClassName;
};


/* address finder for functions with these traits:
* 1. func is virtual and has a confidently known vtable index
*/
Expand Down Expand Up @@ -156,6 +182,68 @@ class CAddr_Func_KnownVTIdx : public IAddr_Func_KnownVTIdx
};


class IAddr_Func_DataMap_VThunk : public IAddr_Sym
{
public:
virtual bool FindAddrWin(uintptr_t& addr) const override;

protected:
virtual const char *GetDataMapName() const = 0;
virtual const char *GetFuncName() const = 0;
virtual const char *GetVTableName() const = 0;
};

class CAddr_Func_DataMap_VThunk : public IAddr_Func_DataMap_VThunk
{
public:
CAddr_Func_DataMap_VThunk(const std::string& name, const std::string& sym, const std::string& dm_name, const std::string& func_name, const std::string& vt_name) :
m_strName(name), m_strSymbol(sym), m_strDataMapName(dm_name), m_strFuncName(func_name), m_strVTName(vt_name) {}

virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetDataMapName() const override { return this->m_strDataMapName.c_str(); }
virtual const char *GetFuncName() const override { return this->m_strFuncName.c_str(); }
virtual const char *GetVTableName() const override { return this->m_strVTName.c_str(); }

private:
std::string m_strName;
std::string m_strSymbol;
std::string m_strDataMapName;
std::string m_strFuncName;
std::string m_strVTName;
};


/* address finder for functions with these traits:
* 1. func body starts with "push ebp; mov ebp,esp"
* 2. func body contains a unique absolute symbol reference
*/
class IAddr_Func_EBPPrologue_UniqueRef : public IAddr_Sym
{
public:
virtual bool FindAddrWin(uintptr_t& addr) const override;

protected:
virtual const char *GetUniqueSymbol() const = 0;
};

class CAddr_Func_EBPPrologue_UniqueRef : public IAddr_Func_EBPPrologue_UniqueRef
{
public:
CAddr_Func_EBPPrologue_UniqueRef(const std::string& name, const std::string& sym, const std::string& uni_ref) :
m_strName(name), m_strSymbol(sym), m_strUniqueSymbol(uni_ref) {}

virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetUniqueSymbol() const override { return this->m_strUniqueSymbol.c_str(); }

private:
std::string m_strName;
std::string m_strSymbol;
std::string m_strUniqueSymbol;
};


/* address finder for functions with these traits:
* 1. func body starts with "push ebp; mov ebp,esp"
* 2. func body contains a unique string reference
Expand All @@ -175,9 +263,9 @@ class CAddr_Func_EBPPrologue_UniqueStr : public IAddr_Func_EBPPrologue_UniqueStr
CAddr_Func_EBPPrologue_UniqueStr(const std::string& name, const std::string& sym, const std::string& uni_str) :
m_strName(name), m_strSymbol(sym), m_strUniqueStr(uni_str) {}

virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetUniqueStr() const override { return this->m_strUniqueStr.c_str(); }
virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetUniqueStr() const override { return this->m_strUniqueStr.c_str(); }

private:
std::string m_strName;
Expand Down Expand Up @@ -223,4 +311,33 @@ class CAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx : public IAddr_Func_EBPPrologu
};


class IAddr_Func_EBPPrologue_VProf : public IAddr_Sym
{
public:
virtual bool FindAddrWin(uintptr_t& addr) const override;

protected:
virtual const char *GetVProfName() const = 0;
virtual const char *GetVProfGroup() const = 0;
};

class CAddr_Func_EBPPrologue_VProf : public IAddr_Func_EBPPrologue_VProf
{
public:
CAddr_Func_EBPPrologue_VProf(const std::string& name, const std::string& sym, const std::string& vprof_name, const std::string& vprof_group) :
m_strName(name), m_strSymbol(sym), m_strVProfName(vprof_name), m_strVProfGroup(vprof_group) {}

virtual const char *GetName() const override { return this->m_strName.c_str(); }
virtual const char *GetSymbol() const override { return this->m_strSymbol.c_str(); }
virtual const char *GetVProfName() const override { return this->m_strVProfName.c_str(); }
virtual const char *GetVProfGroup() const override { return this->m_strVProfGroup.c_str(); }

private:
std::string m_strName;
std::string m_strSymbol;
std::string m_strVProfName;
std::string m_strVProfGroup;
};


#endif
Loading

0 comments on commit 2612cc3

Please sign in to comment.