No binaries provided because
1) It would be pointless; This is just some proof of concept code.
2) I don't want to deal with all the retards yelling keylogger! because it makes http connections to the MS symbol server.
Uses dbghelp.dll and symsrv.dll from Hardware Developer Debugging Tools for Windows 32-bit version
You probably want to change the symbol search path to your own preference..
Credits:
Cypher - Stole his exception handling code from HadesMem
MSDN
SymbolHandler.h
Code:
#pragma once
#include <Windows.h>
// Set DbgHelp to use unicode strings
#define DBGHELP_TRANSLATE_TCHAR
#include <DbgHelp.h>
#include <string>
#include <boost/exception/all.hpp>
namespace MSoft
{
// Exception handling code stolen from HadesMem
typedef boost::error_info<struct TagErrorString, std::string> ErrorString;
typedef boost::error_info<struct TagErrorCode, DWORD> ErrorCode;
class SHError : public virtual std::exception, public virtual boost::exception
{
};
class SymbolHandler
{
public:
SymbolHandler();
SymbolHandler(HANDLE process);
SymbolHandler(HANDLE process, const std::wstring& searchPath);
~SymbolHandler();
void LoadSymbolsForModule(const std::wstring& moduleName);
LPVOID GetAddressFromSymbol(const std::wstring& name, bool throwOnFailure = true);
private:
void Init(HANDLE process, const std::wstring& searchPath);
void Cleanup();
HANDLE _process;
};
}
SymbolHandler.cpp
Code:
#include "SymbolHandler.h"
#include <vector>
#pragma comment(lib, "dbghelp")
namespace MSoft
{
SymbolHandler::SymbolHandler()
{
_process = NULL;
Init(GetCurrentProcess(), NULL);
}
SymbolHandler::SymbolHandler(HANDLE process)
{
_process = NULL;
Init(process, NULL);
}
SymbolHandler::SymbolHandler(HANDLE process, const std::wstring& searchPath)
{
_process = NULL;
Init(process, searchPath);
}
SymbolHandler::~SymbolHandler()
{
Cleanup();
}
void SymbolHandler::Init(HANDLE process, const std::wstring& searchPath)
{
if(_process)
Cleanup();
// SYMOPT_DEBUG is not really needed, but debug output is always good
// if something goes wrong
SymSetOptions(SYMOPT_DEBUG | SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
if(!SymInitialize(process, searchPath.c_str(), FALSE))
BOOST_THROW_EXCEPTION(SHError() << ErrorString("SymInitialize() failed") << ErrorCode(GetLastError()));
_process = process;
}
void SymbolHandler::Cleanup()
{
if(_process)
{
if(!SymCleanup(_process))
BOOST_THROW_EXCEPTION(SHError() << ErrorString("SymCleanup() failed") << ErrorCode(GetLastError()));
_process = NULL;
}
}
void SymbolHandler::LoadSymbolsForModule(const std::wstring& moduleName)
{
HMODULE h = GetModuleHandle(moduleName.c_str());
if(!SymLoadModuleEx(_process, NULL, moduleName.c_str(), NULL, (DWORD64)h, 0, NULL, 0))
BOOST_THROW_EXCEPTION(SHError() << ErrorString("SymLoadModuleEx() failed") << ErrorCode(GetLastError()));
}
LPVOID SymbolHandler::GetAddressFromSymbol(const std::wstring& name, bool throwOnFailure)
{
std::vector<char> buffer;
buffer.resize(sizeof(SYMBOL_INFO) + name.length() * sizeof(wchar_t) + 1);
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer.data();
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = name.length() * sizeof(wchar_t) + 1;
LPVOID ret = NULL;
if(!SymFromName(_process, name.c_str(), pSymbol))
{
// If you know your symbol name is valid then this most likely happens
// because symsrv.dll isn't loaded.
if(throwOnFailure)
BOOST_THROW_EXCEPTION(SHError() << ErrorString("SymFromName() failed") << ErrorCode(GetLastError()));
else
return NULL;
}
return (LPVOID)pSymbol->Address;
}
}
DllMain.cpp
Code:
#include "SymbolHandler.h"
using MSoft::SymbolHandler;
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID)
{
return TRUE;
}
void __declspec(dllexport) Load(const char* str)
{
std::wstring searchPath = L"SRV*C:\\ProgramData\\Symbols*http://msdl.microsoft.com/download/symbols";
try
{
SymbolHandler sh(GetCurrentProcess(), searchPath);
sh.LoadSymbolsForModule(L"d3d9");
LPVOID address = sh.GetAddressFromSymbol(L"CD3DBase::EndScene");
std::wostringstream str;
str << "EndScene address: 0x" << std::hex << address;
MessageBox(NULL, str.str().c_str(), L"Info", MB_ICONINFORMATION);
}
catch(std::exception const& e)
{
MessageBoxA(NULL, boost::diagnostic_information(e).c_str(), "Error!", MB_ICONERROR);
}
}