mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[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:
parent
ef345bf106
commit
0363bfe503
8 changed files with 160 additions and 20 deletions
|
@ -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"
|
||||
|
|
10
src/drive.c
10
src/drive.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
15
src/rufus.c
15
src/rufus.c
|
@ -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
|
||||
|
|
13
src/rufus.h
13
src/rufus.h
|
@ -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);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -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"
|
||||
|
|
123
src/stdio.c
123
src/stdio.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue