他人の空似自作物置場

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