[misc] add an address resolver for internal DLL function calls

* Not sure if we'll use this to hook into FfuCaptureImage()/FfuApplyImage()/FfuMountImage()
  directly. But at least, if we ever need it, it's there...
This commit is contained in:
Pete Batard 2023-07-05 18:36:58 +01:00
parent ef345bf106
commit 0363bfe503
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
8 changed files with 160 additions and 20 deletions

View File

@ -606,6 +606,9 @@ t MSG_341 "a Windows Recovery Screen (BSOD) with '%s'"
t MSG_342 "Compressed VHDX Image"
t MSG_343 "Uncompressed VHD Image"
t MSG_344 "Full Flash Update Image"
t MSG_345 "Some additional data must be downloaded from Microsoft to use this functionality:\n"
"- Select 'Yes' to connect to the Internet and download it\n"
"- Select 'No' to cancel the operation"
# The following messages are for the Windows Store listing only and are not used by the application
t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc."
t MSG_901 "Official site: %s"

View File

@ -1541,7 +1541,7 @@ static BOOL StoreEspInfo(GUID* guid)
static_sprintf(key_name[0], "ToggleEsp%02u", j);
str = ReadSettingStr(key_name[0]);
if ((str == NULL) || (str[0] == 0))
return WriteSettingStr(key_name[0], GuidToString(guid));
return WriteSettingStr(key_name[0], GuidToString(guid, TRUE));
}
// All slots are used => Move every key down and add to last slot
// NB: No, we don't care that the slot we remove may not be the oldest.
@ -1550,7 +1550,7 @@ static BOOL StoreEspInfo(GUID* guid)
static_sprintf(key_name[1], "ToggleEsp%02u", j + 1);
WriteSettingStr(key_name[0], ReadSettingStr(key_name[1]));
}
return WriteSettingStr(key_name[1], GuidToString(guid));
return WriteSettingStr(key_name[1], GuidToString(guid, TRUE));
}
static GUID* GetEspGuid(uint8_t index)
@ -1990,7 +1990,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
case PARTITION_STYLE_GPT:
SelectedDrive.PartitionStyle = PARTITION_STYLE_GPT;
suprintf("Partition type: GPT, NB Partitions: %d", DriveLayout->PartitionCount);
suprintf("Disk GUID: %s", GuidToString(&DriveLayout->Gpt.DiskId));
suprintf("Disk GUID: %s", GuidToString(&DriveLayout->Gpt.DiskId, TRUE));
suprintf("Max parts: %d, Start Offset: %" PRIi64 ", Usable = %" PRIi64 " bytes",
DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
for (i = 0; i < DriveLayout->PartitionCount; i++) {
@ -2006,7 +2006,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
suprintf(" Name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name);
suprintf(" Detected File System: %s", GetFsName(hPhysical, DriveLayout->PartitionEntry[i].StartingOffset));
suprintf(" ID: %s\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64,
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId),
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId, TRUE),
SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
DriveLayout->PartitionEntry[i].PartitionLength,
DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize,
@ -2646,5 +2646,5 @@ const char* GetGPTPartitionType(const GUID* guid)
{
int i;
for (i = 0; (i < ARRAYSIZE(gpt_type)) && !CompareGUID(guid, gpt_type[i].guid); i++);
return (i < ARRAYSIZE(gpt_type)) ? gpt_type[i].name : GuidToString(guid);
return (i < ARRAYSIZE(gpt_type)) ? gpt_type[i].name : GuidToString(guid, TRUE);
}

View File

@ -915,7 +915,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param)
// thinking that Rufus is doing something malicious...
IGNORE_RETVAL(CoCreateGuid(&guid));
// coverity[fixed_size_dest]
strcpy(&pipe[9], GuidToString(&guid));
strcpy(&pipe[9], GuidToString(&guid, TRUE));
static_sprintf(icon_path, "%s%s.ico", temp_dir, APPLICATION_NAME);
ExtractAppIcon(icon_path, TRUE);
@ -973,7 +973,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param)
assert((fido_script != NULL) && (fido_len != 0));
static_sprintf(script_path, "%s%s.ps1", temp_dir, GuidToString(&guid));
static_sprintf(script_path, "%s%s.ps1", temp_dir, GuidToString(&guid, TRUE));
hFile = CreateFileU(script_path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
uprintf("Unable to create download script '%s': %s", script_path, WindowsErrorString());

View File

@ -860,7 +860,7 @@ BOOL ParseSKUSiPolicy(void)
goto out;
}
if (!CompareGUID(&Header->PolicyTypeGUID, &SKU_CODE_INTEGRITY_POLICY)) {
uprintf("ParseSKUSiPolicy: Unexpected Policy Type GUID %s", GuidToString(&Header->PolicyTypeGUID));
uprintf("ParseSKUSiPolicy: Unexpected Policy Type GUID %s", GuidToString(&Header->PolicyTypeGUID, TRUE));
goto out;
}

View File

@ -1861,7 +1861,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
IGNORE_RETVAL(_chdirU(app_data_dir));
IGNORE_RETVAL(_mkdir(FILES_DIR));
IGNORE_RETVAL(_chdir(FILES_DIR));
if (DownloadToFileOrBufferEx(DISKCOPY_URL, tmp, DISKCOPY_USER_AGENT, NULL, hMainDialog, FALSE) != DISKCOPY_SIZE) {
if (DownloadToFileOrBufferEx(DISKCOPY_URL, tmp, SYMBOL_SERVER_USER_AGENT, NULL, hMainDialog, FALSE) != DISKCOPY_SIZE) {
ret = BOOTCHECK_DOWNLOAD_ERROR;
goto out;
}
@ -3787,7 +3787,18 @@ extern int TestHashes(void);
// Ctrl-T => Alternate Test mode that doesn't require a full rebuild
if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN)))
&& (msg.wParam == 'T')) {
TestHashes();
// TestHashes();
dll_resolver_t resolver = { 0 };
resolver.path = "C:\\Windows\\System32\\Dism\\FfuProvider.dll";
resolver.count = 3;
resolver.name = calloc(resolver.count, sizeof(char*));
resolver.address = calloc(resolver.count, sizeof(uint32_t));
resolver.name[0] = "FfuCaptureImage";
resolver.name[1] = "FfuApplyImage";
resolver.name[2] = "FfuMountImage";
uprintf("Got %d resolved addresses", ResolveDllAddress(&resolver));
free(resolver.name);
free(resolver.address);
continue;
}
#endif

View File

@ -121,10 +121,10 @@
#define SEVENZIP_URL "https://7-zip.org/"
// Generated by following https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/
#define DISKCOPY_URL "https://msdl.microsoft.com/download/symbols/diskcopy.dll/54505118173000/diskcopy.dll"
#define DISKCOPY_USER_AGENT "Microsoft-Symbol-Server/10.0.22621.755"
#define DISKCOPY_SIZE 0x16ee00
#define DISKCOPY_IMAGE_OFFSET 0x66d8
#define DISKCOPY_IMAGE_SIZE 0x168000
#define SYMBOL_SERVER_USER_AGENT "Microsoft-Symbol-Server/10.0.22621.755"
#define DEFAULT_ESP_MOUNT_POINT "S:\\"
#define IS_POWER_OF_2(x) ((x != 0) && (((x) & ((x) - 1)) == 0))
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
@ -472,6 +472,14 @@ typedef struct ext_t {
const char** description;
} ext_t;
/* DLL address resolver */
typedef struct {
char* path;
uint32_t count;
char** name;
uint32_t* address; // 32-bit will do, as we're not dealing with >4GB DLLs...
} dll_resolver_t;
#ifndef __VA_GROUP__
#define __VA_GROUP__(...) __VA_ARGS__
#endif
@ -613,7 +621,7 @@ extern void _UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_
#define UpdateProgressWithInfoForce(op, msg, processed, total) _UpdateProgressWithInfo(op, msg, processed, total, TRUE)
#define UpdateProgressWithInfoInit(hProgressDialog, bNoAltMode) UpdateProgressWithInfo(OP_INIT, (int)bNoAltMode, (uint64_t)(uintptr_t)hProgressDialog, 0);
extern const char* StrError(DWORD error_code, BOOL use_default_locale);
extern char* GuidToString(const GUID* guid);
extern char* GuidToString(const GUID* guid, BOOL bDecorated);
extern GUID* StringToGuid(const char* str);
extern char* SizeToHumanReadable(uint64_t size, BOOL copy_to_log, BOOL fake_units);
extern char* TimestampToHumanReadable(uint64_t ts);
@ -723,6 +731,7 @@ extern HICON CreateMirroredIcon(HICON hiconOrg);
extern HANDLE CreatePreallocatedFile(const char* lpFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, LONGLONG fileSize);
extern uint32_t ResolveDllAddress(dll_resolver_t* resolver);
#define GetTextWidth(hDlg, id) GetTextSize(GetDlgItem(hDlg, id), NULL).cx
DWORD WINAPI HashThread(void* param);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.2.2065"
CAPTION "Rufus 4.2.2066"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,2,2065,0
PRODUCTVERSION 4,2,2065,0
FILEVERSION 4,2,2066,0
PRODUCTVERSION 4,2,2066,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.2.2065"
VALUE "FileVersion", "4.2.2066"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.2.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.2.2065"
VALUE "ProductVersion", "4.2.2066"
END
END
BLOCK "VarFileInfo"

View File

@ -28,20 +28,25 @@
#include <string.h>
#include <stdlib.h>
#include <winternl.h>
#include <dbghelp.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include "rufus.h"
#include "missing.h"
#include "settings.h"
#include "resource.h"
#include "msapi_utf8.h"
#include "localization.h"
#define FACILITY_WIM 322
#define FACILITY_WIM 322
#define DEFAULT_BASE_ADDRESS 0x100000000ULL
/*
* Globals
*/
const HANDLE hRufus = (HANDLE)0x0000005275667573ULL; // "\0\0\0Rufus"
HWND hStatus;
size_t ubuffer_pos = 0;
char ubuffer[UBUFFER_SIZE]; // Buffer for ubpushf() messages we don't log right away
@ -683,12 +688,13 @@ const char *WindowsErrorString(void)
return err_string;
}
char* GuidToString(const GUID* guid)
char* GuidToString(const GUID* guid, BOOL bDecorated)
{
static char guid_string[MAX_GUID_STRING_LENGTH];
if (guid == NULL) return NULL;
sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
sprintf(guid_string, bDecorated ? "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}" :
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
(uint32_t)guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
@ -1143,3 +1149,114 @@ HANDLE CreatePreallocatedFile(const char* lpFileName, DWORD dwDesiredAccess,
return fileHandle;
}
// The following calls are used to resolve the addresses of DLL function calls
// that are not publicly exposed by Microsoft. This is accomplished by downloading
// the relevant .pdb and looking up the relevant address there. Once an address is
// found, it is stored in the Rufus settings so that it can be reused.
PF_TYPE_DECL(WINAPI, BOOL, SymInitialize, (HANDLE, PCSTR, BOOL));
PF_TYPE_DECL(WINAPI, DWORD64, SymLoadModuleEx, (HANDLE, HANDLE, PCSTR, PCSTR, DWORD64, DWORD, PMODLOAD_DATA, DWORD));
PF_TYPE_DECL(WINAPI, BOOL, SymGetModuleInfo64, (HANDLE, DWORD64, PIMAGEHLP_MODULE64));
PF_TYPE_DECL(WINAPI, BOOL, SymUnloadModule64, (HANDLE, DWORD64));
PF_TYPE_DECL(WINAPI, BOOL, SymEnumSymbols, (HANDLE, ULONG64, PCSTR, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID));
PF_TYPE_DECL(WINAPI, BOOL, SymCleanup, (HANDLE));
BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
{
dll_resolver_t* resolver = (dll_resolver_t*)UserContext;
uint32_t i;
for (i = 0; i < resolver->count; i++) {
if (safe_strcmp(pSymInfo->Name, resolver->name[i]) == 0) {
resolver->address[i] = (uint32_t)pSymInfo->Address;
#if defined(_DEBUG)
uprintf("%08x: %s", resolver->address[i], resolver->name[i]);
#endif
}
}
return TRUE;
}
uint32_t ResolveDllAddress(dll_resolver_t* resolver)
{
uint32_t r = 0;
uint32_t i;
char url[MAX_PATH], saved_id[MAX_PATH], path[MAX_PATH];
DWORD64 base_address;
IMAGEHLP_MODULE64 info = { sizeof(IMAGEHLP_MODULE64) };
PF_INIT(SymInitialize, DbgHelp);
PF_INIT(SymLoadModuleEx, DbgHelp);
PF_INIT(SymGetModuleInfo64, DbgHelp);
PF_INIT(SymUnloadModule64, DbgHelp);
PF_INIT(SymEnumSymbols, DbgHelp);
PF_INIT(SymCleanup, DbgHelp);
if (pfSymInitialize == NULL || pfSymLoadModuleEx == NULL || pfSymGetModuleInfo64 == NULL ||
pfSymUnloadModule64 == NULL || pfSymEnumSymbols == NULL || pfSymCleanup == NULL ||
resolver->count == 0 || resolver->path == NULL || resolver->name == NULL || resolver->address == NULL)
return 0;
if (!pfSymInitialize(hRufus, NULL, FALSE)) {
uprintf("Could not initialize DLL symbol handler");
return 0;
}
// Get the PDB unique address from the DLL
base_address = pfSymLoadModuleEx(hRufus, NULL, resolver->path, NULL, DEFAULT_BASE_ADDRESS, 0, NULL, 0);
if (base_address == 0ULL || !pfSymGetModuleInfo64(hRufus, base_address, &info)) {
uprintf("Could not obtain DLL symbol info");
goto out;
}
assert(base_address == DEFAULT_BASE_ADDRESS);
pfSymUnloadModule64(hRufus, base_address);
// Check settings to see if we have existing data for these DLL calls.
for (i = 0; i < resolver->count; i++) {
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
GuidToString(&info.PdbSig70, FALSE), (int)info.PdbAge, resolver->name[i]);
resolver->address[i] = ReadSetting32(saved_id);
if (resolver->address[i] == 0)
break;
}
if (i == resolver->count) {
// No need to download the PDB
r = resolver->count;
goto out;
}
// Download the PDB from Microsoft's symbol servers
if (MessageBoxExU(hMainDialog, lmprintf(MSG_345), lmprintf(MSG_115),
MB_YESNO | MB_ICONWARNING | MB_IS_RTL, selected_langid) != IDYES)
goto out;
static_sprintf(path, "%s\\%s.pdb", temp_dir, info.ModuleName);
static_sprintf(url, "http://msdl.microsoft.com/download/symbols/%s.pdb/%s%x/%s.pdb",
info.ModuleName, GuidToString(&info.PdbSig70, FALSE), (int)info.PdbAge, info.ModuleName);
if (DownloadToFileOrBufferEx(url, path, SYMBOL_SERVER_USER_AGENT, NULL, hMainDialog, FALSE) < 200 * KB)
goto out;
// NB: SymLoadModuleEx() does not load a PDB unless the file has an explicit '.pdb' extension
base_address = pfSymLoadModuleEx(hRufus, NULL, path, NULL, DEFAULT_BASE_ADDRESS, 0, NULL, 0);
assert(base_address == DEFAULT_BASE_ADDRESS);
pfSymEnumSymbols(hRufus, base_address, "*!*", EnumSymProc, resolver);
DeleteFileU(path);
// Store the addresses
r = 0;
for (i = 0; i < resolver->count; i++) {
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
GuidToString(&info.PdbSig70, FALSE), (int)info.PdbAge, resolver->name[i]);
if (resolver->address[i] != 0) {
WriteSetting32(saved_id, resolver->address[i]);
r++;
}
}
out:
pfSymUnloadModule64(hRufus, base_address);
pfSymCleanup(hRufus);
return r;
}