DBG+LAUNCHER: fix #1635 (.NET files are now processed correctly)
This commit is contained in:
parent
4631fbfc0f
commit
73a8a93cbe
|
@ -0,0 +1,105 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
enum class PeArch
|
||||
{
|
||||
Invalid,
|
||||
Native86,
|
||||
Native64,
|
||||
Dotnet86,
|
||||
Dotnet64,
|
||||
DotnetAnyCpu,
|
||||
DotnetAnyCpuPrefer32
|
||||
};
|
||||
|
||||
// Thanks to blaquee for the investigative work!
|
||||
static PeArch GetPeArch(const wchar_t* szFileName)
|
||||
{
|
||||
auto result = PeArch::Invalid;
|
||||
auto hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// SEC_IMAGE will load the file like the Windows loader would, saving us RVA -> File offset conversion crap.
|
||||
auto hMappedFile = CreateFileMappingW(hFile, nullptr, PAGE_READONLY | SEC_IMAGE, 0, 0, nullptr);
|
||||
if(hMappedFile)
|
||||
{
|
||||
auto fileMap = MapViewOfFile(hMappedFile, FILE_MAP_READ, 0, 0, 0);
|
||||
if(fileMap)
|
||||
{
|
||||
__try
|
||||
{
|
||||
auto pidh = PIMAGE_DOS_HEADER(fileMap);
|
||||
if(pidh->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
auto pnth = PIMAGE_NT_HEADERS(ULONG_PTR(fileMap) + pidh->e_lfanew);
|
||||
if(pnth->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
auto Machine = pnth->FileHeader.Machine;
|
||||
if(Machine == IMAGE_FILE_MACHINE_I386 || Machine == IMAGE_FILE_MACHINE_AMD64)
|
||||
{
|
||||
auto isDll = (pnth->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL;
|
||||
auto isFile86 = Machine == IMAGE_FILE_MACHINE_I386;
|
||||
|
||||
// Set the native architecture of the PE file (to still have something to show for if the COM directory is invalid).
|
||||
result = isFile86 ? PeArch::Native86 : PeArch::Native64;
|
||||
|
||||
// Get the address and size of the COM (.NET) directory.
|
||||
ULONG_PTR comAddr = 0, comSize = 0;
|
||||
if(isFile86) // x86
|
||||
{
|
||||
auto pnth32 = PIMAGE_NT_HEADERS32(pnth);
|
||||
comAddr = pnth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
|
||||
comSize = pnth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
|
||||
}
|
||||
else // x64
|
||||
{
|
||||
auto pnth64 = PIMAGE_NT_HEADERS64(pnth);
|
||||
comAddr = pnth64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
|
||||
comSize = pnth64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
|
||||
}
|
||||
|
||||
// Check if the file has a (valid) COM (.NET) directory.
|
||||
if(comAddr && comSize >= sizeof(IMAGE_COR20_HEADER))
|
||||
{
|
||||
// Find out which flavor of dotnet we're dealing with. Specifically,
|
||||
// "Any CPU" can be compiled with two flavors, "Prefer 32 bit" or not.
|
||||
// Without the 32bit preferred flag, the loader will load the .NET
|
||||
// environment based on the current platforms bitness (x86 or x64)
|
||||
// Class libraries (DLLs) cannot specify the "Prefer 32 bit".
|
||||
// https://mega.nz/#!vx5nVILR!jLafWGWhhsC0Qo5fE-3oEIc-uHBcRpraOo8L_KlUeXI
|
||||
|
||||
auto pcorh = PIMAGE_COR20_HEADER(ULONG_PTR(fileMap) + comAddr);
|
||||
if(pcorh->cb == sizeof(IMAGE_COR20_HEADER))
|
||||
{
|
||||
auto flags = pcorh->Flags;
|
||||
#define test(x) (flags & x) == x
|
||||
#define MY_COMIMAGE_FLAGS_32BITPREFERRED 0x00020000
|
||||
if(isFile86) // x86
|
||||
{
|
||||
if(test(COMIMAGE_FLAGS_32BITREQUIRED))
|
||||
result = !isDll && test(MY_COMIMAGE_FLAGS_32BITPREFERRED) ? PeArch::DotnetAnyCpuPrefer32 : PeArch::Dotnet86;
|
||||
else
|
||||
result = PeArch::DotnetAnyCpu;
|
||||
}
|
||||
else // x64
|
||||
result = PeArch::Dotnet64;
|
||||
#undef MY_COMIMAGE_FLAGS_32BITPREFERRED
|
||||
#undef test
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_ACCESS_VIOLATION)
|
||||
{
|
||||
}
|
||||
UnmapViewOfFile(fileMap);
|
||||
}
|
||||
CloseHandle(hMappedFile);
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -311,49 +311,6 @@ bool settingboolget(const char* section, const char* name)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets file architecture.
|
||||
\param szFileName UTF-8 encoded file path.
|
||||
\return The file architecture (::arch).
|
||||
*/
|
||||
arch GetFileArchitecture(const char* szFileName)
|
||||
{
|
||||
arch retval = notfound;
|
||||
HANDLE hFile = CreateFileW(StringUtils::Utf8ToUtf16(szFileName).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
IMAGE_DOS_HEADER idh;
|
||||
DWORD read = 0;
|
||||
if(ReadFile(hFile, &idh, sizeof(idh), &read, nullptr))
|
||||
{
|
||||
if(idh.e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
IMAGE_NT_HEADERS inth;
|
||||
memset(&inth, 0, sizeof(inth));
|
||||
PIMAGE_NT_HEADERS pnth = nullptr;
|
||||
if(SetFilePointer(hFile, idh.e_lfanew, nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
if(ReadFile(hFile, &inth, sizeof(inth), &read, nullptr))
|
||||
pnth = &inth;
|
||||
else if(ReadFile(hFile, &inth, sizeof(DWORD) + sizeof(WORD), &read, nullptr))
|
||||
pnth = &inth;
|
||||
}
|
||||
if(pnth && pnth->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
if(pnth->OptionalHeader.DataDirectory[15].VirtualAddress != 0 && pnth->OptionalHeader.DataDirectory[15].Size != 0 && (pnth->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0)
|
||||
retval = dotnet;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
||||
retval = x32;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
||||
retval = x64;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Query if x64dbg is running in Wow64 mode.
|
||||
\return true if running in Wow64, false otherwise.
|
||||
|
|
|
@ -37,15 +37,6 @@
|
|||
//defines
|
||||
#define deflen 1024
|
||||
|
||||
enum arch
|
||||
{
|
||||
notfound,
|
||||
invalid,
|
||||
x32,
|
||||
x64,
|
||||
dotnet
|
||||
};
|
||||
|
||||
//superglobal variables
|
||||
extern HINSTANCE hInst;
|
||||
|
||||
|
@ -72,7 +63,6 @@ bool GetFileNameFromHandle(HANDLE hFile, char* szFileName);
|
|||
bool GetFileNameFromProcessHandle(HANDLE hProcess, char* szFileName);
|
||||
bool GetFileNameFromModuleHandle(HANDLE hProcess, HMODULE hModule, char* szFileName);
|
||||
bool settingboolget(const char* section, const char* name);
|
||||
arch GetFileArchitecture(const char* szFileName);
|
||||
bool IsWow64();
|
||||
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize);
|
||||
void WaitForThreadTermination(HANDLE hThread, DWORD timeout = INFINITE);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "TraceRecord.h"
|
||||
#include "handle.h"
|
||||
#include "thread.h"
|
||||
#include "GetPeArch.h"
|
||||
|
||||
static bool skipInt3Stepping(int argc, char* argv[])
|
||||
{
|
||||
|
@ -66,7 +67,8 @@ bool cbDebugInit(int argc, char* argv[])
|
|||
dputs(QT_TRANSLATE_NOOP("DBG", "File does not exist!"));
|
||||
return false;
|
||||
}
|
||||
Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(arg1).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
auto arg1w = StringUtils::Utf8ToUtf16(arg1);
|
||||
Handle hFile = CreateFileW(arg1w.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Could not open file!"));
|
||||
|
@ -76,23 +78,28 @@ bool cbDebugInit(int argc, char* argv[])
|
|||
dprintf(QT_TRANSLATE_NOOP("DBG", "Debugging: %s\n"), arg1);
|
||||
hFile.Close();
|
||||
|
||||
auto arch = GetPeArch(arg1w.c_str());
|
||||
if(arch == PeArch::DotnetAnyCpu)
|
||||
arch = IsWow64() ? PeArch::Dotnet64 : PeArch::Dotnet86;
|
||||
|
||||
//do some basic checks
|
||||
switch(GetFileArchitecture(arg1))
|
||||
switch(GetPeArch(arg1w.c_str()))
|
||||
{
|
||||
case invalid:
|
||||
case PeArch::Invalid:
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Invalid PE file!"));
|
||||
return false;
|
||||
#ifdef _WIN64
|
||||
case x32:
|
||||
case PeArch::Native86:
|
||||
case PeArch::Dotnet86:
|
||||
case PeArch::DotnetAnyCpuPrefer32:
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Use x32dbg to debug this file!"));
|
||||
#else //x86
|
||||
case x64:
|
||||
case PeArch::Native64:
|
||||
case PeArch::Dotnet64:
|
||||
case PeArch::DotnetAnyCpu:
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Use x64dbg to debug this file!"));
|
||||
#endif //_WIN64
|
||||
return false;
|
||||
case dotnet:
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "This file is a dotNET application."));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ bool cbInstrGpa(int argc, char* argv[])
|
|||
|
||||
bool cbDebugSetJIT(int argc, char* argv[])
|
||||
{
|
||||
arch actual_arch = invalid;
|
||||
arch actual_arch = notfound;
|
||||
char* jit_debugger_cmd = "";
|
||||
Memory<char*> oldjit(MAX_SETTING_SIZE + 1);
|
||||
char path[JIT_ENTRY_DEF_SIZE];
|
||||
|
@ -493,7 +493,7 @@ bool cbDebugGetJIT(int argc, char* argv[])
|
|||
bool cbDebugGetJITAuto(int argc, char* argv[])
|
||||
{
|
||||
bool jit_auto = false;
|
||||
arch actual_arch = invalid;
|
||||
arch actual_arch = notfound;
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
|
|
|
@ -2743,6 +2743,8 @@ static void debugLoopFunction(void* lpParameter, bool attach)
|
|||
auto lastError = GetLastError();
|
||||
auto isElevated = IsProcessElevated();
|
||||
auto error = ErrorCodeToName(lastError);
|
||||
if(error.empty())
|
||||
error = StringUtils::sprintf("%d (0x%X)", lastError);
|
||||
if(lastError == ERROR_ELEVATION_REQUIRED && !isElevated)
|
||||
{
|
||||
auto msg = StringUtils::Utf8ToUtf16(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "The executable you are trying to debug requires elevation. Restart as admin?")));
|
||||
|
|
|
@ -17,6 +17,13 @@ typedef enum
|
|||
ERROR_RW_NOTADMIN
|
||||
} readwritejitkey_error_t;
|
||||
|
||||
enum arch
|
||||
{
|
||||
notfound,
|
||||
x32,
|
||||
x64,
|
||||
};
|
||||
|
||||
bool IsProcessElevated();
|
||||
bool dbggetjit(char jit_entry[JIT_ENTRY_MAX_SIZE], arch arch_in, arch* arch_out, readwritejitkey_error_t* rw_error_out);
|
||||
bool dbgsetjit(char* jit_cmd, arch arch_in, arch* arch_out, readwritejitkey_error_t* rw_error_out);
|
||||
|
|
|
@ -196,6 +196,7 @@
|
|||
<ClInclude Include="exprfunc.h" />
|
||||
<ClInclude Include="filemap.h" />
|
||||
<ClInclude Include="formatfunctions.h" />
|
||||
<ClInclude Include="GetPeArch.h" />
|
||||
<ClInclude Include="handles.h" />
|
||||
<ClInclude Include="exception.h" />
|
||||
<ClInclude Include="exhandlerinfo.h" />
|
||||
|
|
|
@ -958,5 +958,8 @@
|
|||
<ClInclude Include="formatfunctions.h">
|
||||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GetPeArch.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -10,6 +10,7 @@
|
|||
#include "../exe/resource.h"
|
||||
#include "../exe/LoadResourceString.h"
|
||||
#include "../exe/icon.h"
|
||||
#include "../dbg/GetPeArch.h"
|
||||
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
|
||||
|
@ -19,53 +20,6 @@ static bool FileExists(const TCHAR* file)
|
|||
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
enum arch
|
||||
{
|
||||
notfound,
|
||||
invalid,
|
||||
x32,
|
||||
x64,
|
||||
dotnet
|
||||
};
|
||||
|
||||
static arch GetFileArchitecture(const TCHAR* szFileName)
|
||||
{
|
||||
arch retval = notfound;
|
||||
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
IMAGE_DOS_HEADER idh;
|
||||
DWORD read = 0;
|
||||
if(ReadFile(hFile, &idh, sizeof(idh), &read, nullptr))
|
||||
{
|
||||
if(idh.e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
IMAGE_NT_HEADERS inth;
|
||||
memset(&inth, 0, sizeof(inth));
|
||||
PIMAGE_NT_HEADERS pnth = nullptr;
|
||||
if(SetFilePointer(hFile, idh.e_lfanew, nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
if(ReadFile(hFile, &inth, sizeof(inth), &read, nullptr))
|
||||
pnth = &inth;
|
||||
else if(ReadFile(hFile, &inth, sizeof(DWORD) + sizeof(WORD), &read, nullptr))
|
||||
pnth = &inth;
|
||||
}
|
||||
if(pnth && pnth->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
if(pnth->OptionalHeader.DataDirectory[15].VirtualAddress != 0 && pnth->OptionalHeader.DataDirectory[15].Size != 0 && (pnth->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0)
|
||||
retval = dotnet;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
||||
retval = x32;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
||||
retval = x64;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool BrowseFileOpen(HWND owner, const TCHAR* filter, const TCHAR* defext, TCHAR* filename, int filename_size, const TCHAR* init_dir)
|
||||
{
|
||||
OPENFILENAME ofstruct;
|
||||
|
@ -583,37 +537,50 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
|||
if(canDisableRedirect)
|
||||
rWow.DisableRedirect();
|
||||
|
||||
auto architecture = GetFileArchitecture(szPath);
|
||||
if(architecture == dotnet)
|
||||
architecture = isWoW64() ? x64 : x32;
|
||||
|
||||
//MessageBoxW(0, cmdLine.c_str(), L"x96dbg", MB_SYSTEMMODAL);
|
||||
//MessageBoxW(0, GetCommandLineW(), L"GetCommandLineW", MB_SYSTEMMODAL);
|
||||
//MessageBoxW(0, szCurDir, L"GetCurrentDirectory", MB_SYSTEMMODAL);
|
||||
|
||||
switch(architecture)
|
||||
auto load32 = [&]()
|
||||
{
|
||||
case x32:
|
||||
if(sz32Path[0])
|
||||
ShellExecute(nullptr, TEXT("open"), sz32Path, cmdLine.c_str(), sz32Dir, SW_SHOWNORMAL);
|
||||
else
|
||||
MessageBox(nullptr, LoadResString(IDS_INVDPATH32), LoadResString(IDS_ERROR), MB_ICONERROR);
|
||||
break;
|
||||
|
||||
case x64:
|
||||
};
|
||||
auto load64 = [&]()
|
||||
{
|
||||
if(sz64Path[0])
|
||||
ShellExecute(nullptr, TEXT("open"), sz64Path, cmdLine.c_str(), sz64Dir, SW_SHOWNORMAL);
|
||||
else
|
||||
MessageBox(nullptr, LoadResString(IDS_INVDPATH64), LoadResString(IDS_ERROR), MB_ICONERROR);
|
||||
break;
|
||||
};
|
||||
|
||||
case invalid:
|
||||
MessageBox(nullptr, argv[1], LoadResString(IDS_INVDPE), MB_ICONERROR);
|
||||
switch(GetPeArch(szPath))
|
||||
{
|
||||
case PeArch::Native86:
|
||||
case PeArch::Dotnet86:
|
||||
case PeArch::DotnetAnyCpuPrefer32:
|
||||
load32();
|
||||
break;
|
||||
|
||||
case notfound:
|
||||
MessageBox(nullptr, argv[1], LoadResString(IDS_FILEERR), MB_ICONERROR);
|
||||
case PeArch::Native64:
|
||||
case PeArch::Dotnet64:
|
||||
load64();
|
||||
break;
|
||||
case PeArch::DotnetAnyCpu:
|
||||
if(isWoW64())
|
||||
load64();
|
||||
else
|
||||
load32();
|
||||
break;
|
||||
case PeArch::Invalid:
|
||||
if(FileExists(szPath))
|
||||
MessageBox(nullptr, argv[1], LoadResString(IDS_INVDPE), MB_ICONERROR);
|
||||
else
|
||||
MessageBox(nullptr, argv[1], LoadResString(IDS_FILEERR), MB_ICONERROR);
|
||||
break;
|
||||
default:
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
LocalFree(argv);
|
||||
|
|
Loading…
Reference in New Issue