_GetProcAddress - Attempt to retrieve address of function of `Module`, given `lpProcName` Meant to be used for function lookups without calling GetProcAddress explicitly (may require dynamic analysis instead of static for an attacker) */
| 576 | Meant to be used for function lookups without calling GetProcAddress explicitly (may require dynamic analysis instead of static for an attacker) |
| 577 | */ |
| 578 | FARPROC Process::_GetProcAddress(__in const PCSTR Module, __in const LPCSTR lpProcName) |
| 579 | { |
| 580 | if (Module == nullptr || lpProcName == nullptr) |
| 581 | return (FARPROC)NULL; |
| 582 | |
| 583 | DWORD* dNameRVAs(0); //array: addresses of export names |
| 584 | DWORD* dFunctionRVAs(0); |
| 585 | WORD* dOrdinalRVAs(0); |
| 586 | |
| 587 | _IMAGE_EXPORT_DIRECTORY* ImageExportDirectory = NULL; |
| 588 | unsigned long cDirSize = 0; |
| 589 | _LOADED_IMAGE LoadedImage; |
| 590 | char* sName = NULL; |
| 591 | |
| 592 | uintptr_t AddressFound = NULL; |
| 593 | |
| 594 | uintptr_t ModuleBase = (uintptr_t)GetModuleHandleA(Module); //last remaining artifacts for detection. TODO: Use PEB to fetch this instead of API |
| 595 | |
| 596 | if (ModuleBase == NULL) |
| 597 | return NULL; |
| 598 | |
| 599 | if (MapAndLoad(Module, NULL, &LoadedImage, TRUE, TRUE)) |
| 600 | { |
| 601 | ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*)ImageDirectoryEntryToData(LoadedImage.MappedAddress, false, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize); |
| 602 | |
| 603 | if (ImageExportDirectory != NULL) |
| 604 | { |
| 605 | dNameRVAs = (DWORD*)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, ImageExportDirectory->AddressOfNames, NULL); |
| 606 | dFunctionRVAs = (DWORD*)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, ImageExportDirectory->AddressOfFunctions, NULL); |
| 607 | dOrdinalRVAs = (WORD*)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, ImageExportDirectory->AddressOfNameOrdinals, NULL); |
| 608 | |
| 609 | for (size_t i = 0; i < ImageExportDirectory->NumberOfFunctions; i++) |
| 610 | { |
| 611 | sName = (char*)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, dNameRVAs[i], NULL); |
| 612 | |
| 613 | if (strcmp(sName, lpProcName) == 0) |
| 614 | { |
| 615 | AddressFound = ModuleBase + dFunctionRVAs[dOrdinalRVAs[i]]; |
| 616 | break; |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | else |
| 621 | { |
| 622 | Logger::logf(Err, "ImageExportDirectory was NULL @ Process::_GetProcAddress with module %s and function %s", Module, lpProcName); |
| 623 | UnMapAndLoad(&LoadedImage); |
| 624 | return NULL; |
| 625 | } |
| 626 | |
| 627 | UnMapAndLoad(&LoadedImage); |
| 628 | } |
| 629 | else |
| 630 | { |
| 631 | Logger::logf(Err, "MapAndLoad failed @ Process::_GetProcAddress with module %s and function %s", Module, lpProcName); |
| 632 | return (FARPROC)NULL; |
| 633 | } |
| 634 | |
| 635 | return (FARPROC)AddressFound; |
nothing calls this directly
no outgoing calls
no test coverage detected