Пример #1
0
  void GetCallbacks(OutputIterator callbacks) const
  {
    using OutputIteratorCategory =
      typename std::iterator_traits<OutputIterator>::iterator_category;
    HADESMEM_DETAIL_STATIC_ASSERT(
      std::is_base_of<std::output_iterator_tag, OutputIteratorCategory>::value);

    auto const image_base = GetRuntimeBase(*process_, *pe_file_);
    auto callbacks_raw = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(
      RvaToVa(*process_,
              *pe_file_,
              static_cast<DWORD>(GetAddressOfCallBacks() - image_base)));
    if (!callbacks_raw)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"TLS callbacks are invalid."});
    }

    for (auto callback = Read<PIMAGE_TLS_CALLBACK>(*process_, callbacks_raw);
         callback;
         callback = Read<PIMAGE_TLS_CALLBACK>(*process_, ++callbacks_raw))
    {
      auto const callback_offset =
        reinterpret_cast<ULONGLONG>(callback) - image_base;
      *callbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK>(
        static_cast<ULONG_PTR>(callback_offset));
      ++callbacks;
    }
  }
Пример #2
0
inline ModuleRegionInfo GetModuleInfo(Process const& process,
                                      std::wstring const& module)
{
  ModuleRegionInfo mod_info;

  if (module.empty())
  {
    mod_info.module = std::make_shared<Module>(process, nullptr);
  }
  else
  {
    mod_info.module = std::make_shared<Module>(process, module);
  }

  auto const base =
    reinterpret_cast<std::uint8_t*>(mod_info.module->GetHandle());
  PeFile const pe_file{process, base, hadesmem::PeFileType::Image, 0};
  DosHeader const dos_header{process, pe_file};
  NtHeaders const nt_headers{process, pe_file};
  SectionList const sections{process, pe_file};
  for (auto const& s : sections)
  {
    bool const is_code_section =
      !!(s.GetCharacteristics() & IMAGE_SCN_CNT_CODE);
    bool const is_data_section =
      !!(s.GetCharacteristics() & IMAGE_SCN_CNT_INITIALIZED_DATA);
    if (!is_code_section && !is_data_section)
    {
      continue;
    }

    auto const section_beg = static_cast<std::uint8_t*>(
      RvaToVa(process, pe_file, s.GetVirtualAddress()));
    if (section_beg == nullptr)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error() << ErrorString("Could not get section base address."));
    }

    DWORD const section_size = s.GetVirtualSize();
    if (!section_size)
    {
      continue;
    }

    auto const section_end = section_beg + section_size;

    auto& regions =
      is_code_section ? mod_info.code_regions : mod_info.data_regions;
    regions.emplace_back(section_beg, section_end);
  }

  if (mod_info.code_regions.empty() && mod_info.data_regions.empty())
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error() << ErrorString("No valid sections to scan found."));
  }

  return mod_info;
}
Пример #3
0
 void SetHint(WORD hint)
 {
   std::uint8_t* const name_import = static_cast<PBYTE>(
     RvaToVa(*process_, *pe_file_, static_cast<DWORD>(GetAddressOfData())));
   return Write(
     *process_, name_import + offsetof(IMAGE_IMPORT_BY_NAME, Hint), hint);
 }
Пример #4
0
  explicit RelocationBlockIterator(Process const& process,
                                   PeFile const& pe_file)
  {
    try
    {
      NtHeaders const nt_headers{process, pe_file};

      DWORD const data_dir_va =
        nt_headers.GetDataDirectoryVirtualAddress(PeDataDir::BaseReloc);
      DWORD const size = nt_headers.GetDataDirectorySize(PeDataDir::BaseReloc);
      if (!data_dir_va || !size)
      {
        return;
      }

      auto base =
        static_cast<std::uint8_t*>(RvaToVa(process, pe_file, data_dir_va));
      if (!base)
      {
        return;
      }

      // Cast to integer and back to avoid pointer overflow UB.
      auto const reloc_dir_end = reinterpret_cast<void const*>(
        reinterpret_cast<std::uintptr_t>(base) + size);
      auto const file_end =
        static_cast<std::uint8_t*>(pe_file.GetBase()) + pe_file.GetSize();
      // Sample: virtrelocXP.exe
      if (pe_file.GetType() == PeFileType::Data &&
          (reloc_dir_end < base || reloc_dir_end > file_end))
      {
        return;
      }

      // TODO: Dump should warn for this.
      RelocationBlock const relocation_block{
        process,
        pe_file,
        reinterpret_cast<IMAGE_BASE_RELOCATION*>(base),
        reloc_dir_end};
      if (relocation_block.IsInvalid())
      {
        return;
      }

      impl_ = std::make_shared<Impl>(
        process, pe_file, relocation_block, reloc_dir_end);
    }
    catch (std::exception const& /*e*/)
    {
      // Nothing to do here.
    }
  }
Пример #5
0
 std::string GetName() const
 {
   auto const name_import = static_cast<std::uint8_t*>(
     RvaToVa(*process_, *pe_file_, static_cast<DWORD>(GetAddressOfData())));
   if (!name_import)
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"Invalid import name and hint."});
   }
   return detail::CheckedReadString<char>(
     *process_, *pe_file_, name_import + offsetof(IMAGE_IMPORT_BY_NAME, Name));
 }
Пример #6
0
  explicit TlsDir(Process const& process, PeFile const& pe_file)
    : process_{&process}, pe_file_{&pe_file}
  {
    NtHeaders const nt_headers{process, pe_file};

    DWORD const data_dir_va =
      nt_headers.GetDataDirectoryVirtualAddress(PeDataDir::TLS);
    // Windows will load images which don't specify a size for the
    // TLS directory.
    if (!data_dir_va)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"PE file has no TLS directory."});
    }

    base_ = static_cast<std::uint8_t*>(RvaToVa(process, pe_file, data_dir_va));
    if (!base_)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"TLS directory is invalid."});
    }

    UpdateRead();
  }
Пример #7
0
BOOL ImportEnumerate(HINSTANCE hInst)
{
    PBYTE pbBase = (PBYTE)hInst;
	PIMAGE_NT_HEADERS pNtHeader;					// Read & Write
	PIMAGE_SECTION_HEADER pSectionHeaders;
	DWORD nPeOffset;
	DWORD nSectionsOffset;
	
	////////////////////////////////////////////////////// Process DOS Header.
	//
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbBase;
	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
		return FALSE;
	}
	nPeOffset = pDosHeader->e_lfanew;

	/////////////////////////////////////////////////////// Process PE Header.
	//
    pNtHeader = (PIMAGE_NT_HEADERS)RvaToVa(pbBase, nPeOffset);
	if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
		return FALSE;
	}
	if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
		return FALSE;
	}
	nSectionsOffset = nPeOffset
		+ sizeof(pNtHeader->Signature)
		+ sizeof(pNtHeader->FileHeader)
		+ pNtHeader->FileHeader.SizeOfOptionalHeader;

	///////////////////////////////////////////////// Process Section Headers.
	//
    pSectionHeaders = (PIMAGE_SECTION_HEADER)RvaToVa(pbBase, nSectionsOffset);

	//////////////////////////////////////////////////////// Get Import Table.
	//
	DWORD rvaImageDirectory = pNtHeader->OptionalHeader
		.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
	PIMAGE_IMPORT_DESCRIPTOR iidp
		= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(pbBase, rvaImageDirectory);
    
	if (iidp == NULL) {
		return FALSE;
	}

    for (DWORD nFiles = 0; iidp[nFiles].Characteristics != 0; nFiles++) {
        // Count the files.
    }
    
    for (DWORD n = 0; n < nFiles; n++, iidp++) {
        DWORD rvaName = iidp->Name;
        PCHAR pszName = (PCHAR)RvaToVa(pbBase, rvaName);
        
        DWORD rvaThunk = (DWORD)iidp->OriginalFirstThunk;
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk);
        rvaThunk = (DWORD)iidp->FirstThunk;
        PIMAGE_THUNK_DATA pBoundThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk);

        Syelog(SYELOG_SEVERITY_INFORMATION,
               "%s [%08x %08x]\n", pszName, pThunk, pBoundThunk);
        
        DWORD nNames = 0;
        if (pThunk == NULL) {
            break;
        }
        
        for (; pThunk[nNames].u1.Ordinal; nNames++) {
            // Count the imports.
        }   

        for (DWORD f = 0; f < nNames; f++) {
            DWORD nOrdinal = 0;
            PCHAR pszName = NULL;
            PDWORD pFunc = (PDWORD)pBoundThunk[f].u1.Function;
            
            DWORD rvaName = pThunk[f].u1.Ordinal;
            if (rvaName & IMAGE_ORDINAL_FLAG) {
                nOrdinal = IMAGE_ORDINAL(rvaName);
            }
            else {
                PIMAGE_IMPORT_BY_NAME pName
                    = (PIMAGE_IMPORT_BY_NAME)RvaToVa(pbBase, rvaName);
                if (pName) {
                    pszName = (PCHAR)pName->Name;
                }
            }
            Syelog(SYELOG_SEVERITY_INFORMATION,
                   "  %-32.32s %4d %08x\n", pszName, nOrdinal, pFunc);
        }
    }
	return TRUE;
}