1
0
Fork 0

DBG+LAUNCHER: fix #1635 (.NET files are now processed correctly)

This commit is contained in:
mrexodia 2017-07-08 18:29:13 +02:00
parent 4631fbfc0f
commit 73a8a93cbe
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
10 changed files with 164 additions and 125 deletions

105
src/dbg/GetPeArch.h Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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);

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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?")));

View File

@ -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);

View File

@ -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" />

View File

@ -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>

View File

@ -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);