他人の空似自作物置場

cmd_logger.zip/src/main.cpp


#include <string.h>

#include <string>
#include <vector>

#include <windows.h>

#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>

boost::filesystem::path GetDllDir() {
  wchar_t buffer[MAX_PATH];
  if (0 == ::GetModuleFileNameW(::GetModuleHandleW(L"cmd_logger.dll"), buffer, _countof(buffer))) {
    return boost::filesystem::path();
  }
  return boost::filesystem::path(buffer).remove_filename();
}

BOOL WINAPI d_ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, PCONSOLE_READCONSOLE_CONTROL lpReserved) {
  const BOOL result = ::ReadConsoleW(hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved);
  if (result == FALSE || *lpNumberOfCharsRead == 0 ||
    reinterpret_cast<const wchar_t*>(lpBuffer)[*lpNumberOfCharsRead-1] == L'\t')
  {
    return result;
  }
  const boost::filesystem::path path = GetDllDir() / L"command_history.txt";
  boost::filesystem::wofstream ofs(path, std::ios::app | std::ios::binary);
  ofs << std::wstring(reinterpret_cast<const wchar_t*>(lpBuffer), &reinterpret_cast<const wchar_t*>(lpBuffer)[*lpNumberOfCharsRead]);
  return result;
}

bool ChangeIAT(HMODULE module) {
  struct TargetProcInfo {
    std::string dllName;
    std::string procName;
    unsigned int procAddress;
  };
  const TargetProcInfo targetList[] ={
    {"kernel32.dll", "ReadConsoleW", reinterpret_cast<unsigned int>(d_ReadConsoleW)}, // WindowsXP vista 7
    {"api-ms-win-core-console-l1-1-0.dll", "ReadConsoleW", reinterpret_cast<unsigned int>(d_ReadConsoleW)}, // Windows8
  };
  unsigned char * const baseAddr = reinterpret_cast<unsigned char *>(module == NULL ? ::GetModuleHandleA(NULL) : module);
  const IMAGE_DOS_HEADER &mz = *reinterpret_cast<const IMAGE_DOS_HEADER *>(baseAddr);
  const IMAGE_NT_HEADERS32 &pe = *reinterpret_cast<const IMAGE_NT_HEADERS32 *>(baseAddr + mz.e_lfanew);
  const IMAGE_IMPORT_DESCRIPTOR *desc = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR *>(baseAddr + pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  for (; desc->OriginalFirstThunk != 0; desc = ++desc) {
    const char * const dllName = reinterpret_cast<const char *>(baseAddr + desc->Name);
    const unsigned int *in = reinterpret_cast<unsigned int *>(baseAddr + desc->OriginalFirstThunk);
    unsigned int *out = reinterpret_cast<unsigned int *>(baseAddr + desc->FirstThunk);
    for (; *in != 0; ++in, ++out) {
      if ((*in & 0x80000000) != 0) {
        continue;
      }
      const char * const procName = reinterpret_cast<const char *>(baseAddr + *in + 2);
      BOOST_FOREACH(const TargetProcInfo &target, targetList) {
        if (::_stricmp(target.dllName.c_str(), dllName) != 0 || target.procName != procName) {
          continue;
        }
        DWORD oldProtect;
        ::VirtualProtect(out, 4, PAGE_READWRITE, &oldProtect);
        *out = target.procAddress;
        ::VirtualProtect(out, 4, oldProtect, &oldProtect);
      }
    }
  }
  return true;
}

BOOL APIENTRY DllMain(HANDLE , DWORD ul_reason_for_call, LPVOID) {
  static HMODULE h_original = NULL;
  switch(ul_reason_for_call) {
    case DLL_PROCESS_ATTACH: {
      if (!ChangeIAT(NULL)) {
        return FALSE;
      }
      break;
    }
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    case DLL_PROCESS_DETACH:
      break;
  }
  return TRUE;
}