Open CodeXTF2 opened 2 years ago
I haven't had any issues with accessing resource sections as long as SRDI_CLEARHEADER
is not passed. Otherwise the PE header validation fails and the native APIs refuse to touch it. I would expect something like this to work:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
HRSRC rsc = FindResource(hModule, MAKEINTRESOURCE(IDI_ICON1), RT_GROUP_ICON);
...
}
If it helps, here is some extracted code which can parse the PE resource section manually:
static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(void* root, PIMAGE_RESOURCE_DIRECTORY resources, LPCTSTR key)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resources + 1);
PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
DWORD start;
DWORD end;
DWORD middle;
if (IS_INTRESOURCE(key)) {
WORD check = (WORD)(uintptr_t)key;
start = resources->NumberOfNamedEntries;
end = start + resources->NumberOfIdEntries;
while (end > start) {
WORD entryName;
middle = (start + end) >> 1;
entryName = (WORD)entries[middle].Name;
if (check < entryName) {
end = (end != middle ? middle : middle - 1);
}
else if (check > entryName) {
start = (start != middle ? middle : middle + 1);
}
else {
result = &entries[middle];
break;
}
}
}
else {
LPCWSTR searchKey;
size_t searchKeyLen = wcslen(key);
searchKey = key;
start = 0;
end = resources->NumberOfNamedEntries;
while (end > start) {
int cmp;
PIMAGE_RESOURCE_DIR_STRING_U resourceString;
middle = (start + end) >> 1;
resourceString = PIMAGE_RESOURCE_DIR_STRING_U((UINT_PTR)root + (entries[middle].Name & 0x7FFFFFFF));
cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length);
if (cmp == 0) {
// Handle partial match
if (searchKeyLen > resourceString->Length) {
cmp = 1;
}
else if (searchKeyLen < resourceString->Length) {
cmp = -1;
}
}
if (cmp < 0) {
end = (middle != end ? middle : middle - 1);
}
else if (cmp > 0) {
start = (middle != start ? middle : middle + 1);
}
else {
result = &entries[middle];
break;
}
}
}
return result;
}
#define RVA(type, base, rva) (type)((ULONG_PTR) base + rva)
std::string * GetResourceR(HMODULE hModule, LPCTSTR name, LPCTSTR type, WORD language)
{
PIMAGE_RESOURCE_DIRECTORY rootResources;
PIMAGE_RESOURCE_DIRECTORY nameResources;
PIMAGE_RESOURCE_DIRECTORY typeResources;
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType;
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName;
PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage;
if (language == 0) {
language = LANGIDFROMLCID(GetThreadLocale());
}
if (hModule == NULL)
return NULL;
PIMAGE_NT_HEADERS ntHeaders = RVA(PIMAGE_NT_HEADERS, hModule, ((PIMAGE_DOS_HEADER)hModule)->e_lfanew);
PIMAGE_DATA_DIRECTORY dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
if (!dataDir->Size)
return NULL;
rootResources = RVA(PIMAGE_RESOURCE_DIRECTORY, hModule, dataDir->VirtualAddress);
foundType = _MemorySearchResourceEntry(rootResources, rootResources, type);
if (foundType == NULL) {
SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
return NULL;
}
typeResources = RVA(PIMAGE_RESOURCE_DIRECTORY, hModule, dataDir->VirtualAddress + (foundType->OffsetToData & 0x7fffffff));
foundName = _MemorySearchResourceEntry(rootResources, typeResources, name);
if (foundName == NULL) {
SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
return NULL;
}
nameResources = RVA(PIMAGE_RESOURCE_DIRECTORY, hModule, dataDir->VirtualAddress + (foundName->OffsetToData & 0x7fffffff));
foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR)(uintptr_t)language);
if (foundLanguage == NULL) {
// requested language not found, use first available
if (nameResources->NumberOfIdEntries == 0) {
SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND);
return NULL;
}
foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(nameResources + 1);
}
PIMAGE_RESOURCE_DATA_ENTRY entry = RVA(PIMAGE_RESOURCE_DATA_ENTRY, hModule, dataDir->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff));
if (entry == NULL || !entry->OffsetToData) {
return NULL;
}
return new std::string(RVA(LPSTR, hModule, entry->OffsetToData), entry->Size);
}
Hi Nick,
I had the exact same issue. Once loaded, I couldn't use FindResource()
anymore.
But your workaround (https://github.com/monoxgas/sRDI/issues/24#issuecomment-972201094) worked like charms :)
Thanks!.
DLLs cannot use FindResource when converted into shellcode. Same code works when not loaded using sRDI. Issue seems to be the same as https://github.com/TheWover/donut/issues/70 where the PE stomping breaks the .rsrc section. EDIT: Based on PE structure, not sure if there is a workaround other than disabling the SRDI_CLEARHEADER flag. Any ideas? EDIT 2: Even with SRDI_CLEARHEADER it doesnt seem to work.