int main(int argc, char* argv[]) { try { std::cout << "HadesMem Dumper [" << HADESMEM_VERSION_STRING << "]\n"; TCLAP::CmdLine cmd("PE file format dumper", ' ', HADESMEM_VERSION_STRING); TCLAP::ValueArg<DWORD> pid_arg( "", "pid", "Target process id", false, 0, "DWORD"); TCLAP::ValueArg<std::string> name_arg( "", "name", "Target process name", false, "", "string"); TCLAP::MultiArg<std::string> path_arg( "", "path", "Target path (file or directory)", false, "string"); TCLAP::SwitchArg all_arg("", "all", "No target, dump everything"); std::vector<TCLAP::Arg*> xor_args{&pid_arg, &name_arg, &path_arg, &all_arg}; cmd.xorAdd(xor_args); TCLAP::SwitchArg warned_arg( "", "warned", "Dump list of files which cause warnings", cmd); TCLAP::ValueArg<std::string> warned_file_arg( "", "warned-file", "Dump warned list to file instead of stdout", false, "", "string", cmd); TCLAP::SwitchArg warned_file_dynamic_arg( "", "warned-file-dynamic", "Dump warnings to file on the fly rather than at the end", cmd); TCLAP::SwitchArg quiet_arg( "", "quiet", "Only output status messages (no dumping)", cmd); TCLAP::SwitchArg memonly_arg("", "memonly", "Only do PE memory dumps", cmd); TCLAP::ValueArg<int> warned_type_arg("", "warned-type", "Filter warned file using warned type", false, -1, "int", cmd); TCLAP::ValueArg<DWORD> threads_arg( "", "threads", "Number of threads", false, 0, "size_t", cmd); TCLAP::ValueArg<DWORD> queue_factor_arg( "", "queue-factor", "Thread queue factor", false, 0, "size_t", cmd); TCLAP::SwitchArg strings_arg("", "strings", "Dump strings", cmd); cmd.parse(argc, argv); g_quiet = quiet_arg.isSet(); g_strings = strings_arg.isSet(); SetWarningsEnabled(warned_arg.getValue()); SetDynamicWarningsEnabled(warned_file_dynamic_arg.getValue()); if (warned_file_arg.isSet()) { SetWarnedFilePath( hadesmem::detail::MultiByteToWideChar(warned_file_arg.getValue())); } if (GetDynamicWarningsEnabled() && GetWarnedFilePath().empty()) { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString( "Please specify a file path for dynamic warnings.")); } int const warned_type = warned_type_arg.getValue(); switch (warned_type) { case static_cast<int>(WarningType::kSuspicious): SetWarnedType(WarningType::kSuspicious); break; case static_cast<int>(WarningType::kUnsupported): SetWarnedType(WarningType::kUnsupported); break; case static_cast<int>(WarningType::kAll): SetWarnedType(WarningType::kAll); break; default: HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Unknown warned type.")); break; } try { hadesmem::GetSeDebugPrivilege(); std::wcout << "\nAcquired SeDebugPrivilege.\n"; } catch (std::exception const& /*e*/) { std::wcout << "\nFailed to acquire SeDebugPrivilege.\n"; } auto const threads = threads_arg.isSet() ? threads_arg.getValue() : 1; auto const queue_factor = queue_factor_arg.isSet() ? queue_factor_arg.getValue() : 1; hadesmem::detail::ThreadPool thread_pool{threads, queue_factor}; if (pid_arg.isSet()) { DWORD const pid = pid_arg.getValue(); hadesmem::ProcessList const processes; auto iter = std::find_if(std::begin(processes), std::end(processes), [pid](hadesmem::ProcessEntry const& process_entry) { return process_entry.GetId() == pid; }); if (iter != std::end(processes)) { DumpProcessEntry(*iter, memonly_arg.isSet()); } else { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Failed to find requested process.")); } } else if (name_arg.isSet()) { auto const proc_name = hadesmem::detail::MultiByteToWideChar(name_arg.getValue()); auto const proc_entry = hadesmem::GetProcessEntryByName(proc_name, false); DumpProcessEntry(proc_entry, memonly_arg.isSet()); } else if (path_arg.isSet()) { // TODO: Use backup semantics flags and try to get backup privilege in // order to make directory enumeration find more files. auto const path_args = path_arg.getValue(); for (auto const& path : path_args) { auto const path_wide = hadesmem::detail::MultiByteToWideChar(path); if (hadesmem::detail::IsDirectory(path_wide)) { DumpDir(path_wide, thread_pool); } else { DumpFile(path_wide); } } } else { DumpThreads(static_cast<DWORD>(-1)); DumpProcesses(memonly_arg.isSet()); std::wcout << "\nFiles:\n"; // TODO: Enumerate all volumes. std::wstring const self_path = hadesmem::detail::GetSelfPath(); std::wstring const root_path = hadesmem::detail::GetRootPath(self_path); DumpDir(root_path, thread_pool); } thread_pool.WaitForEmpty(); if (GetWarningsEnabled()) { if (!GetWarnedFilePath().empty() && !GetDynamicWarningsEnabled()) { std::unique_ptr<std::wfstream> warned_file_ptr( hadesmem::detail::OpenFile<wchar_t>(GetWarnedFilePath(), std::ios::out)); std::wfstream& warned_file = *warned_file_ptr; if (!warned_file) { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Failed to open warned file for output.")); } DumpWarned(warned_file); } else { DumpWarned(std::wcout); } } return 0; } catch (...) { std::cerr << "\nError!\n" << boost::current_exception_diagnostic_information() << '\n'; return 1; } }
int main(int argc, char* argv[]) { try { std::cout << "HadesMem Dumper [" << HADESMEM_VERSION_STRING << "]\n"; TCLAP::CmdLine cmd("PE file format dumper", ' ', HADESMEM_VERSION_STRING); TCLAP::ValueArg<DWORD> pid_arg( "", "pid", "Target process id", false, 0, "DWORD"); TCLAP::ValueArg<std::string> name_arg( "", "name", "Target process name", false, "", "string"); TCLAP::ValueArg<std::string> path_arg( "", "path", "Target path (file or directory)", false, "", "string"); TCLAP::SwitchArg all_arg("", "all", "No target, dump everything"); std::vector<TCLAP::Arg*> xor_args{&pid_arg, &name_arg, &path_arg, &all_arg}; cmd.xorAdd(xor_args); TCLAP::SwitchArg warned_arg( "", "warned", "Dump list of files which cause warnings", cmd); TCLAP::ValueArg<std::string> warned_file_arg( "", "warned-file", "Dump warned list to file instead of stdout", false, "", "string", cmd); TCLAP::SwitchArg warned_file_dynamic_arg( "", "warned-file-dynamic", "Dump warnings to file on the fly rather than at the end", cmd); TCLAP::ValueArg<int> warned_type_arg("", "warned-type", "Filter warned file using warned type", false, -1, "int", cmd); cmd.parse(argc, argv); SetWarningsEnabled(warned_arg.getValue()); SetDynamicWarningsEnabled(warned_file_dynamic_arg.getValue()); if (warned_file_arg.isSet()) { SetWarnedFilePath( hadesmem::detail::MultiByteToWideChar(warned_file_arg.getValue())); } if (GetDynamicWarningsEnabled() && GetWarnedFilePath().empty()) { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString( "Please specify a file path for dynamic warnings.")); } int const warned_type = warned_type_arg.getValue(); switch (warned_type) { case static_cast<int>(WarningType::kSuspicious): SetWarnedType(WarningType::kSuspicious); break; case static_cast<int>(WarningType::kUnsupported): SetWarnedType(WarningType::kUnsupported); break; case static_cast<int>(WarningType::kAll): SetWarnedType(WarningType::kAll); break; default: HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Unknown warned type.")); break; } try { hadesmem::GetSeDebugPrivilege(); std::wcout << "\nAcquired SeDebugPrivilege.\n"; } catch (std::exception const& /*e*/) { std::wcout << "\nFailed to acquire SeDebugPrivilege.\n"; } if (pid_arg.isSet()) { DWORD const pid = pid_arg.getValue(); hadesmem::ProcessList const processes; auto iter = std::find_if(std::begin(processes), std::end(processes), [pid](hadesmem::ProcessEntry const& process_entry) { return process_entry.GetId() == pid; }); if (iter != std::end(processes)) { DumpProcessEntry(*iter); } else { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Failed to find requested process.")); } } else if (name_arg.isSet()) { auto const proc_name = hadesmem::detail::MultiByteToWideChar(name_arg.getValue()); auto const proc_entry = hadesmem::GetProcessEntryByName(proc_name, false); DumpProcessEntry(proc_entry); } else if (path_arg.isSet()) { auto const path = hadesmem::detail::MultiByteToWideChar(path_arg.getValue()); if (hadesmem::detail::IsDirectory(path)) { DumpDir(path); } else { DumpFile(path); } } else { DumpThreads(static_cast<DWORD>(-1)); DumpProcesses(); std::wcout << "\nFiles:\n"; std::wstring const self_path = hadesmem::detail::GetSelfPath(); std::wstring const root_path = hadesmem::detail::GetRootPath(self_path); DumpDir(root_path); } if (GetWarningsEnabled()) { if (!GetWarnedFilePath().empty() && !GetDynamicWarningsEnabled()) { std::unique_ptr<std::wfstream> warned_file_ptr( hadesmem::detail::OpenFile<wchar_t>(GetWarnedFilePath(), std::ios::out)); std::wfstream& warned_file = *warned_file_ptr; if (!warned_file) { HADESMEM_DETAIL_THROW_EXCEPTION( hadesmem::Error() << hadesmem::ErrorString("Failed to open warned file for output.")); } DumpWarned(warned_file); } else { DumpWarned(std::wcout); } } return 0; } catch (...) { std::cerr << "\nError!\n" << boost::current_exception_diagnostic_information() << '\n'; if (!g_current_file_path.empty()) { std::wcerr << "\nCurrent file: " << g_current_file_path << "\n"; } return 1; } }