| 102 | } |
| 103 | |
| 104 | ULONG PEParser::GetExportByName(PCSTR exportName) { |
| 105 | ULONG offset = 0; |
| 106 | if (!HasExports()) |
| 107 | return 0; |
| 108 | |
| 109 | auto dir = GetDataDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT); |
| 110 | if (dir == nullptr || dir->Size == 0) |
| 111 | return 0; |
| 112 | |
| 113 | auto data = static_cast<IMAGE_EXPORT_DIRECTORY*>(GetAddress(dir->VirtualAddress)); |
| 114 | auto ordinals = (PUCHAR)(data->AddressOfNameOrdinals != 0 ? GetAddress(data->AddressOfNameOrdinals) : nullptr); |
| 115 | auto names = (PUCHAR)(data->AddressOfNames != 0 ? GetAddress(data->AddressOfNames) : nullptr); |
| 116 | auto functions = (PULONG)GetAddress(data->AddressOfFunctions); |
| 117 | auto ordinalBase = data->Base; |
| 118 | PCSTR name = nullptr; |
| 119 | |
| 120 | for (ULONG i = 0; i < data->NumberOfNames; ++i) { |
| 121 | int ordinal = i; |
| 122 | if (ordinals) { |
| 123 | ordinal = *(USHORT*)(ordinals + i * 2) + (USHORT)ordinalBase; |
| 124 | } |
| 125 | if (names) { |
| 126 | offset = *(ULONG*)(names + i * 4); |
| 127 | name = (PCSTR)GetAddress(offset); |
| 128 | } |
| 129 | auto address = *(functions + ordinal - ordinalBase); |
| 130 | if (address > dir->VirtualAddress && address < dir->VirtualAddress + dir->Size) { |
| 131 | // we ignore forwarded exports |
| 132 | continue; |
| 133 | } |
| 134 | // compare the export name to the requested export |
| 135 | if (name) { |
| 136 | if (!strcmp(name, exportName)) { |
| 137 | offset = RvaToFileOffset(address); |
| 138 | break; |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | return offset; |
| 144 | } |
| 145 | |
| 146 | PIMAGE_SECTION_HEADER PEParser::RvaToSection(PIMAGE_NT_HEADERS ntHeader, PVOID base, ULONG rva) { |
| 147 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(ntHeader); |
no outgoing calls
no test coverage detected