sehop.zip/sehop/sehop/main.cpp
#include <stdio.h>
#include <boost/random.hpp>
#include <boost/filesystem.hpp>
#include <boost/version.hpp>
#include <Windows.h>
#include <org/click3/dll_hack_lib.h>
#pragma comment(lib, "winmm.lib")
struct SehRecord {
SehRecord *next;
const void *ptr;
};
SehRecord *GetFirstSehRecord() {
SehRecord *record;
__asm {
mov eax, FS:0
mov record, eax
}
return record;
}
const SehRecord *AddLastSeh(const void * const ptr) {
SehRecord *record = GetFirstSehRecord();
SehRecord *prev = record;
while (true) {
if (reinterpret_cast<unsigned int>(record->next) == 0xFFFFFFFF) {
break;
}
prev = record;
record = record->next;
}
SehRecord * const current = record - 1;
SehRecord * const prevRecord = current - 1;
prev->next = prevRecord;
prevRecord->ptr = record->ptr;
prevRecord->next = current;
current->ptr = ptr;
current->next = record + 1;
(record + 1)->ptr = record->ptr;
(record + 1)->next = reinterpret_cast<SehRecord *>(0xFFFFFFFF);
return current;
}
DWORD recordIndex;
DWORD ptrIndex;
void SetSehPtr(const void * const ptr) {
TlsSetValue(ptrIndex, reinterpret_cast<void *>(reinterpret_cast<unsigned int>(ptr) ^ 0xAAAAAAAA));
}
const void *GetSehPtr() {
return reinterpret_cast<const void *>(reinterpret_cast<unsigned int>(TlsGetValue(ptrIndex)) ^ 0xAAAAAAAA);
}
void SetSehRecord(const SehRecord * const record) {
TlsSetValue(recordIndex, reinterpret_cast<void *>(reinterpret_cast<unsigned int>(record) ^ 0xAAAAAAAA));
}
const SehRecord *GetSehRecord() {
return reinterpret_cast<const SehRecord *>(reinterpret_cast<unsigned int>(TlsGetValue(recordIndex)) ^ 0xAAAAAAAA);
}
void SetSehOp() {
boost::random::mt19937 gen(timeGetTime());
boost::random::uniform_int_distribution<unsigned int> dist(0, 0xFFFFFFFF);
boost::random::variate_generator<boost::random::mt19937&, boost::random::uniform_int_distribution<unsigned int> > rand(gen, dist);
SetSehPtr(reinterpret_cast<const void *>(rand()));
SetSehRecord(AddLastSeh(GetSehPtr()));
}
FARPROC KiUserExceptionDispatcher;
FARPROC KiUserExceptionDispatcher2;
void exception() {
for (const SehRecord *record = GetFirstSehRecord(); reinterpret_cast<unsigned int>(record) != 0xFFFFFFFF; record = record->next) {
if (record == GetSehRecord() && record->ptr == GetSehPtr()) {
return;
}
}
::abort();
}
__declspec(naked) void d_KiUserExceptionDispatcher() {
__asm {
pushad
}
exception();
__asm {
popad
CLD
MOV ECX,DWORD PTR SS:[ESP+4]
jmp KiUserExceptionDispatcher2
}
}
__declspec(naked) void d_KiUserExceptionDispatcherXP() {
__asm {
pushad
}
exception();
__asm {
popad
MOV ECX,DWORD PTR SS:[ESP+4]
MOV EBX,DWORD PTR SS:[ESP]
jmp KiUserExceptionDispatcher2
}
}
bool HookException() {
KiUserExceptionDispatcher = ::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"), "KiUserExceptionDispatcher");
if (KiUserExceptionDispatcher == NULL) {
return false;
}
KiUserExceptionDispatcher2 = reinterpret_cast<FARPROC>(reinterpret_cast<unsigned int>(KiUserExceptionDispatcher) + 5);
const unsigned char oldCode[] = {0xFC, 0x8B, 0x4C, 0x24, 0x04};
unsigned char newCode[_countof(oldCode)] = {0xE9};
*reinterpret_cast<unsigned int *>(&newCode[1]) = reinterpret_cast<unsigned int>(d_KiUserExceptionDispatcher) - reinterpret_cast<unsigned int>(KiUserExceptionDispatcher) - 5;
if (!org::click3::DllHackLib::ChangeCode(reinterpret_cast<unsigned int>(KiUserExceptionDispatcher), oldCode, newCode, sizeof(unsigned char) * _countof(oldCode))) {
const unsigned char oldCode[] = {0x8B, 0x4C, 0x24, 0x04, 0x8B, 0x1C, 0x24};
unsigned char newCode[_countof(oldCode)] = {0xE9, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
*reinterpret_cast<unsigned int *>(&newCode[1]) = reinterpret_cast<unsigned int>(d_KiUserExceptionDispatcherXP) - reinterpret_cast<unsigned int>(KiUserExceptionDispatcher) - 5;
if (!org::click3::DllHackLib::ChangeCode(reinterpret_cast<unsigned int>(KiUserExceptionDispatcher), oldCode, newCode, sizeof(unsigned char) * _countof(oldCode))) {
return false;
}
}
return true;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
recordIndex = ::TlsAlloc();
ptrIndex = ::TlsAlloc();
if (!HookException()) {
return FALSE;
}
// fall through
case DLL_THREAD_ATTACH:
SetSehOp();
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
exit(0);
break;
}
return true;
}