/Examples/Experimental/ManualMapper.cpp

http://hadesmem.googlecode.com/ · C++ · 185 lines · 141 code · 21 blank · 23 comment · 6 complexity · 1046526ea84f17ff19ac5a882acdb712 MD5 · raw file

  1. // Copyright Joshua Boyce 2011.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // This file is part of HadesMem.
  6. // <http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>
  7. // C++ Standard Library
  8. #include <string>
  9. #include <iostream>
  10. #include <exception>
  11. #include <algorithm>
  12. // Boost
  13. #ifdef HADES_GCC
  14. #pragma GCC diagnostic push
  15. #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
  16. #endif
  17. #include <boost/timer.hpp>
  18. #include <boost/version.hpp>
  19. #include <boost/filesystem.hpp>
  20. #include <boost/lexical_cast.hpp>
  21. #ifdef HADES_GCC
  22. #pragma GCC diagnostic pop
  23. #endif
  24. // Windows
  25. #include <Windows.h>
  26. #include <Shellapi.h>
  27. // Hades
  28. #include <HadesMemory/Memory.hpp>
  29. #include <HadesMemory/Detail/I18n.hpp>
  30. #include <HadesMemory/Experimental/ManualMap.hpp>
  31. #ifdef HADES_GCC
  32. int wmain(int argc, wchar_t* argv[]);
  33. int CALLBACK wWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
  34. LPWSTR /*lpCmdLine*/, int /*nCmdShow*/)
  35. {
  36. LPWSTR CmdLineW = GetCommandLine();
  37. int argc = 0;
  38. LPWSTR* argv = CommandLineToArgvW(CmdLineW, &argc);
  39. try
  40. {
  41. int result = wmain(argc, argv);
  42. LocalFree(argv);
  43. return result;
  44. }
  45. catch (...)
  46. {
  47. LocalFree(argv);
  48. }
  49. return 0;
  50. }
  51. #endif
  52. // Program entry point
  53. int wmain(int argc, wchar_t* argv[])
  54. {
  55. // Program timer
  56. boost::timer const ProgTimer;
  57. try
  58. {
  59. // Attempt to detect memory leaks in debug mode
  60. #ifdef _DEBUG
  61. int const CurrentFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  62. int NewFlags = (_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
  63. _CRTDBG_CHECK_ALWAYS_DF);
  64. _CrtSetDbgFlag(CurrentFlags | NewFlags);
  65. // Get default heap
  66. HANDLE const ProcHeap = GetProcessHeap();
  67. if (!ProcHeap)
  68. {
  69. DWORD const LastError = GetLastError();
  70. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  71. HadesMem::ErrorFunction("wmain") <<
  72. HadesMem::ErrorString("Could not get process heap.") <<
  73. HadesMem::ErrorCodeWinLast(LastError));
  74. }
  75. // Detect heap corruption
  76. if (!HeapSetInformation(ProcHeap, HeapEnableTerminationOnCorruption,
  77. NULL, 0))
  78. {
  79. DWORD const LastError = GetLastError();
  80. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  81. HadesMem::ErrorFunction("wmain") <<
  82. HadesMem::ErrorString("Could not set heap information.") <<
  83. HadesMem::ErrorCodeWinLast(LastError));
  84. }
  85. #endif
  86. // Version and copyright output
  87. #if defined(_M_X64)
  88. std::wcout << "Hades ManualMapper AMD64 [Version " <<
  89. HADES_VERSION_FULL_STRING << "]\n";
  90. #elif defined(_M_IX86)
  91. std::wcout << "Hades ManualMapper IA32 [Version " <<
  92. HADES_VERSION_FULL_STRING << "]\n";
  93. #else
  94. #error "[HadesMem] Unsupported architecture."
  95. #endif
  96. std::wcout << "Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).\n"
  97. << "<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>\n"
  98. << "Compiler: \"" << BOOST_COMPILER << "\", Standard Library: \""
  99. << BOOST_STDLIB << "\", Platform: \"" << BOOST_PLATFORM << "\", Boost: "
  100. << BOOST_VERSION << ".\n";
  101. std::wcout << "Built on " << __DATE__ << " at " << __TIME__ << ".\n"
  102. << std::endl;
  103. // Get target process ID from args
  104. if (argc < 2)
  105. {
  106. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  107. HadesMem::ErrorFunction("wmain") <<
  108. HadesMem::ErrorString("You must supply a valid process id."));
  109. }
  110. DWORD ProcId = 0;
  111. try
  112. {
  113. ProcId = boost::lexical_cast<DWORD>(argv[1]);
  114. }
  115. catch (std::exception const& /*e*/)
  116. {
  117. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  118. HadesMem::ErrorFunction("wmain") <<
  119. HadesMem::ErrorString("You must supply a valid process id."));
  120. }
  121. // Get target module from args
  122. if (argc < 3)
  123. {
  124. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  125. HadesMem::ErrorFunction("wmain") <<
  126. HadesMem::ErrorString("You must supply a valid module path."));
  127. }
  128. boost::filesystem::path ModulePath;
  129. try
  130. {
  131. ModulePath = argv[2];
  132. }
  133. catch (std::exception const& /*e*/)
  134. {
  135. BOOST_THROW_EXCEPTION(HadesMem::HadesMemError() <<
  136. HadesMem::ErrorFunction("wmain") <<
  137. HadesMem::ErrorString("You must supply a valid module path."));
  138. }
  139. // Get target export from args (optional)
  140. std::string Export;
  141. if (argc > 3)
  142. {
  143. Export = boost::lexical_cast<std::string>(static_cast<std::wstring>(
  144. argv[3]));
  145. }
  146. // Open memory manager
  147. HadesMem::MemoryMgr const MyMemory(ProcId == static_cast<DWORD>(-1) ?
  148. GetCurrentProcessId() : ProcId);
  149. // Create manual mapper
  150. HadesMem::ManualMap const MyManualMapper(MyMemory);
  151. // Manually map DLL
  152. PVOID const ModRemote = MyManualMapper.InjectDll(ModulePath.native(),
  153. Export);
  154. std::wcout << "Module successfully mapped. Base = " << ModRemote <<
  155. ".\n";
  156. }
  157. catch (std::exception const& e)
  158. {
  159. std::cout << boost::diagnostic_information(e) << "\n";
  160. }
  161. // Print elapsed time
  162. std::wcout << "\nElapsed Time: " << ProgTimer.elapsed() << "\n";
  163. return 0;
  164. }