Skip to content

Instantly share code, notes, and snippets.

@RolfRolles
Created October 31, 2020 18:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RolfRolles/7e5103948266202458adfbfaee3265f1 to your computer and use it in GitHub Desktop.
Save RolfRolles/7e5103948266202458adfbfaee3265f1 to your computer and use it in GitHub Desktop.
Example showing how to cast member function pointers and use proxy stubs during DLL injection / code reuse
#undef USE_MAY20_VERSION
#define USE_OCT20_VERSION 1
#ifdef USE_OCT20_VERSION
#define OFFS_ValveBuffer_Constructor 0x83A9E0
#define OFFS_ValveBuffer_Destructor 0x83FC30
#define OFFS_ValveBuffer_PutByte 0x83C8D0
#define OFFS_ValveBuffer_PutByteBuffer 0x83BDA0
#define OFFS_ValveBuffer_PutString 0x44C940
#define OFFS_ValveBuffer_GetByteBuffer 0x44C070
#endif
// Code taken from StackExchange
template<typename classT, typename memberT>
union u_ptm_cast {
memberT classT::*pmember;
void *pvoid;
};
class ValveBuffer
{
protected:
typedef ValveBuffer *(ValveBuffer::constructor)(uint32_t GrowSize, uint32_t AllocationCount, uint8_t flags);
static u_ptm_cast<ValveBuffer,constructor> mFPConstructor;
typedef void (ValveBuffer::destructor)();
static u_ptm_cast<ValveBuffer, destructor> mFPDestructor;
typedef void (ValveBuffer::putByte)(uint8_t);
static u_ptm_cast<ValveBuffer, putByte> mFPPutByte;
typedef void (ValveBuffer::putByteBuffer)(uint8_t *, size_t);
static u_ptm_cast<ValveBuffer, putByteBuffer> mFPPutByteBuffer;
typedef bool (__cdecl *putString)(ValveBuffer *, const char *);
static putString mFPPutString;
typedef bool (__cdecl *getByteBuffer)(ValveBuffer *, uint8_t *, size_t);
static getByteBuffer mFPGetByteBuffer;
public:
static void InitFuncPtrs(void *DLLBase) {
//mFPConstructor.pvoid = NULL;
mFPConstructor.pvoid = (reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_Constructor);
mFPDestructor.pvoid = (reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_Destructor);
mFPPutByte.pvoid = (reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_PutByte);
mFPPutByteBuffer.pvoid = (reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_PutByteBuffer);
mFPPutString= reinterpret_cast<putString>(reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_PutString);
mFPGetByteBuffer = reinterpret_cast<getByteBuffer>(reinterpret_cast<char *>(DLLBase) + OFFS_ValveBuffer_GetByteBuffer);
}
ValveBuffer(uint32_t GrowSize = 64, uint32_t AllocationCount = 32, uint8_t flags = 0) {
auto x = mFPConstructor.pmember;
(this->*x)(GrowSize, AllocationCount, flags);
}
~ValveBuffer() {
(this->*mFPDestructor.pmember)();
}
void PutByte(uint8_t b) {
(this->*mFPPutByte.pmember)(b);
}
void PutWord(uint16_t w) {
PutByteBuffer((uint8_t *)&w, sizeof(uint16_t));
}
void PutDword(uint32_t d) {
PutByteBuffer((uint8_t *)&d, sizeof(uint32_t));
}
void PutQword(uint64_t q) {
PutByteBuffer((uint8_t *)&q, sizeof(uint64_t));
}
void PutByteBuffer(uint8_t *b, size_t n) {
(this->*mFPPutByteBuffer.pmember)(b, n);
}
void PutString(const char *str) {
mFPPutString(this, str);
}
bool GetByteBuffer(uint8_t *b, size_t n) {
return mFPGetByteBuffer(this, b, n);
}
bool GetByte(uint8_t *b) {
return GetByteBuffer(b, sizeof(uint8_t));
}
bool GetWord(uint16_t *w) {
return GetByteBuffer((uint8_t*)w, sizeof(uint16_t));
}
bool GetDword(uint32_t *d) {
return GetByteBuffer((uint8_t*)d, sizeof(uint32_t));
}
bool GetQword(uint64_t *q) {
return GetByteBuffer((uint8_t*)q, sizeof(uint64_t));
}
};
decltype(ValveBuffer::mFPConstructor) ValveBuffer::mFPConstructor;
decltype(ValveBuffer::mFPDestructor) ValveBuffer::mFPDestructor;
decltype(ValveBuffer::mFPPutByte) ValveBuffer::mFPPutByte;
decltype(ValveBuffer::mFPPutByteBuffer) ValveBuffer::mFPPutByteBuffer;
decltype(ValveBuffer::mFPGetByteBuffer) ValveBuffer::mFPGetByteBuffer;
decltype(ValveBuffer::mFPPutString) ValveBuffer::mFPPutString;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment