[Bug 44648] New: x64dbg crashes during process attach ( kernel32.GetFinalPathNameByHandle() doesn' t support process image file handles)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 3 14:38:04 CST 2018


https://bugs.winehq.org/show_bug.cgi?id=44648

            Bug ID: 44648
           Summary: x64dbg crashes during process attach
                    (kernel32.GetFinalPathNameByHandle() doesn't support
                    process image file handles)
           Product: Wine
           Version: 3.3
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ntdll
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

as it says.

* 64-bit process started
* attach with x64dbg to it

Relevant piece of trace log:

--- snip ---
...
004d:Call KERNEL32.DebugActiveProcess(0000003d,) ret=017a2abd
004d: debug_process( pid=003d, attach=1 )
004d: debug_process() = 0
004d:Ret  KERNEL32.DebugActiveProcess() retval=00000001 ret=017a2abd
004d:Call KERNEL32.GetModuleHandleA(017f3610 "kernel32.dll",) ret=017a2af0
004d:Ret  KERNEL32.GetModuleHandleA() retval=7b460000 ret=017a2af0
004d:Call KERNEL32.GetProcAddress(7b460000,017f35f0
"DebugSetProcessKillOnExit",) ret=017a2b00
004d:Ret  KERNEL32.GetProcAddress() retval=7b46ce5c ret=017a2b00
004d:Call KERNEL32.DebugSetProcessKillOnExit(00000001,) ret=017a2b0b
004d: set_debugger_kill_on_exit( kill_on_exit=1 )
004d: set_debugger_kill_on_exit() = 0
004d:Ret  KERNEL32.DebugSetProcessKillOnExit() retval=00000001 ret=017a2b0b
004d:Call KERNEL32.WaitForDebugEvent(0181e090,ffffffff,) ret=017c5e53
004d: wait_debug_event( get_handle=1 )
004d: wait_debug_event() = 0 { pid=003d, tid=003e, wait=0000,
event={create_process,file=0170,process=0168,thread=016c,base=140000000,offset=0,size=0,teb=7fffffea8000,start=00000000,name=00010a20,unicode=1}
}
004d:Ret  KERNEL32.WaitForDebugEvent() retval=00000001 ret=017c5e53
...
004d:Call KERNEL32.GetModuleHandleW(015ab490 L"kernel32.dll",) ret=015a27e0
004d:Ret  KERNEL32.GetModuleHandleW() retval=7b460000 ret=015a27e0
004d:Call KERNEL32.GetProcAddress(7b460000,015ab470
"GetFinalPathNameByHandleW",) ret=015a27f0
004d:Ret  KERNEL32.GetProcAddress() retval=7b46e800 ret=015a27f0
004d:Call
KERNEL32.GetFinalPathNameByHandleW(00000170,0ca8ca80,00000104,00000000,)
ret=015a2817
004d:trace:ntdll:NtQueryObject
(0x170,0x00000001,0xca8c5c0,0x00000228,0xca8c3ac)
004d: get_handle_unix_name( handle=0170 )
004d: get_handle_unix_name() = OBJECT_TYPE_MISMATCH { name_len=0, name="" }
004d: get_object_info( handle=0170 )
004d: get_object_info() = 0 { access=00120089, ref_count=00000002,
handle_count=00000001, total=0, name=L"" }
004d:Ret  KERNEL32.GetFinalPathNameByHandleW() retval=00000000 ret=015a2817
...
--- snip ---

0170 = handle to the process's image file, delivered through
CREATE_PROCESS_DEBUG_INFO structure in WaitForDebugEvent().

x64dbg source:

https://github.com/x64dbg/x64dbg/blob/development/src/dbg/debugger.cpp#L1324

--- snip ---
...
static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
{
    fdProcessInfo->hProcess = CreateProcessInfo->hProcess;
    fdProcessInfo->hThread = CreateProcessInfo->hThread;
    varset("$hp", (duint)fdProcessInfo->hProcess, true);

    void* base = CreateProcessInfo->lpBaseOfImage;

    char DebugFileName[deflen] = "";
    if(!GetFileNameFromHandle(CreateProcessInfo->hFile, DebugFileName) &&
!GetFileNameFromProcessHandle(CreateProcessInfo->hProcess, DebugFileName))
        strcpy_s(DebugFileName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "???
(GetFileNameFromHandle failed)")));
dprintf(QT_TRANSLATE_NOOP("DBG", "Process Started: %p %s\n"), base,
DebugFileName);
...
--- snip ---

'GetFileNameFromHandle' is implemented in a third-party library
'devicenameresolver', used by x64dbg.

https://bitbucket.org/mrexodia/devicenameresolver/src/0850d88fa6a759d79b3c859933870d9aa602aa79/DeviceNameResolver.cpp?at=master&fileviewer=file-view-default#DeviceNameResolver.cpp-79

--- snip ---
__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath,
size_t nSizeInChars)
{
    typedef DWORD (WINAPI * GETFINALPATHNAMEBYHANDLEW)(
        IN HANDLE /*hFile*/,
        OUT wchar_t* /*lpszFilePath*/,
        IN DWORD /*cchFilePath*/,
        IN DWORD /*dwFlags*/
    );
    static GETFINALPATHNAMEBYHANDLEW GetFPNBHW =
GETFINALPATHNAMEBYHANDLEW(GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
"GetFinalPathNameByHandleW"));
    if(GetFPNBHW && GetFPNBHW(hFile, szPath, DWORD(nSizeInChars), 0))
    {
        if(_wcsnicmp(szPath, L"\\\\?\\UNC\\", 8) == 0) // Server path
        {
            wcsncpy_s(szPath, nSizeInChars, L"\\\\", _TRUNCATE);
            wcsncat_s(szPath, nSizeInChars, &szPath[8], _TRUNCATE);
        }
        else if(_wcsnicmp(szPath, L"\\\\?\\", 4) == 0 && szPath[5] == L':') //
Drive path
        {
            wcsncpy_s(szPath, nSizeInChars, &szPath[4], _TRUNCATE);
        }
        return true;
    }
    if(!DevicePathFromFileHandleW(hFile, szPath, nSizeInChars))
        return false;
    std::wstring oldPath(szPath);
    if(!DevicePathToPathW(szPath, szPath, nSizeInChars))
        wcsncpy_s(szPath, nSizeInChars, oldPath.c_str(), _TRUNCATE);
    return true;
}
--- snip ---

'GetFinalPathNameByHandleW()' fails in Wine, it should not on valid process
image file handle?

There is a fallback path 'DevicePathFromFileHandleW()':

https://bitbucket.org/mrexodia/devicenameresolver/src/0850d88fa6a759d79b3c859933870d9aa602aa79/DeviceNameResolver.cpp?at=master&fileviewer=file-view-default#DeviceNameResolver.cpp-35

--- snip ---
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t*
szDevicePath, size_t nSizeInChars)
{
    NativeWinApi::initialize();
    ULONG ReturnLength;
    bool bRet = false;
    if(NativeWinApi::NtQueryObject(hFile, ObjectNameInformation, 0, 0,
&ReturnLength) == STATUS_INFO_LENGTH_MISMATCH)
    {
        ReturnLength += 0x2000; //on Windows XP SP3 ReturnLength will not be
set just add some buffer space to fix this
        POBJECT_NAME_INFORMATION NameInformation =
POBJECT_NAME_INFORMATION(GlobalAlloc(0, ReturnLength));
        if(NativeWinApi::NtQueryObject(hFile, ObjectNameInformation,
NameInformation, ReturnLength, 0) == STATUS_SUCCESS)
        {
            NameInformation->Name.Buffer[NameInformation->Name.Length / 2] =
L'\0'; //null-terminate the UNICODE_STRING
            wcsncpy_s(szDevicePath, nSizeInChars, NameInformation->Name.Buffer,
_TRUNCATE);
            bRet = true;
        }
        GlobalFree(NameInformation);
    }
    if(!bRet)
        return false;
    if(_wcsnicmp(szDevicePath, L"\\Device\\LanmanRedirector\\", 25) == 0) //
Win XP
    {
        wcsncpy_s(szDevicePath, nSizeInChars, L"\\\\", _TRUNCATE);
        wcsncat_s(szDevicePath, nSizeInChars, &szDevicePath[25], _TRUNCATE);
    }
    else if(_wcsnicmp(szDevicePath, L"\\Device\\Mup\\", 12) == 0) // Win 7
    {
        wcsncpy_s(szDevicePath, nSizeInChars, L"\\\\", _TRUNCATE);
        wcsncat_s(szDevicePath, nSizeInChars, &szDevicePath[12], _TRUNCATE);
    }
    return true;
}
--- snip ---

Corresponding Wine trace log:

--- snip ---
...
004d:Call ntdll.NtQueryObject(00000170,00000001,00000000,00000000,0ca8c9e8,)
ret=015a1c8b
004d:trace:ntdll:NtQueryObject (0x170,0x00000001,(nil),0x00000000,0xca8c9e8)
004d: get_handle_unix_name( handle=0170 )
004d: get_handle_unix_name() = OBJECT_TYPE_MISMATCH { name_len=0, name="" }
004d: get_object_info( handle=0170 )
004d: get_object_info() = 0 { access=00120089, ref_count=00000002,
handle_count=00000001, total=0, name=L"" }
004d:Ret  ntdll.NtQueryObject() retval=c0000004 ret=015a1c8b
004d:Call KERNEL32.GlobalAlloc(00000000,00002010,) ret=015a1cb2
004d:Ret  KERNEL32.GlobalAlloc() retval=034d3700 ret=015a1cb2
004d:Call ntdll.NtQueryObject(00000170,00000001,034d3700,00002010,00000000,)
ret=015a1cd4
004d:trace:ntdll:NtQueryObject (0x170,0x00000001,0x34d3700,0x00002010,(nil))
004d: get_handle_unix_name( handle=0170 )
004d: get_handle_unix_name() = OBJECT_TYPE_MISMATCH { name_len=0, name="" }
004d: get_object_info( handle=0170 )
004d: get_object_info() = 0 { access=00120089, ref_count=00000002,
handle_count=00000001, total=0, name=L"" }
004d:Ret  ntdll.NtQueryObject() retval=00000000 ret=015a1cd4
004d:Call KERNEL32.GetLastError() ret=015a58a8
004d:Ret  KERNEL32.GetLastError() retval=00000006 ret=015a58a8
...
004d:Call
ntdll.RtlVirtualUnwind(00000000,015a0000,015a483b,015b34b0,0ca8c3a0,0ca8c2e8,0ca8c2f0,00000000,)
ret=015a488c 
...
004d:Call KERNEL32.UnhandledExceptionFilter(0ca8c2d8,) ret=015a48d8 
...
004d:trace:seh:start_debugger Starting debugger "winedbg --auto 42 404" 
--- snip ---

'NtQueryObject()' fails first time with 'STATUS_INFO_LENGTH_MISMATCH'.
The second call of 'NtQueryObject()' doesn't fail but doesn't return any data,
which causes wcsncpy_s() to abort.

In any case, a least one code path should succeed.

$ sha1sum snapshot_2018-02-24_13-52.zip 
1d64a63153aad56e23c626dcdd9a0fd684f9064b  snapshot_2018-02-24_13-52.zip

$ du -sh snapshot_2018-02-24_13-52.zip 
33M    snapshot_2018-02-24_13-52.zip

$ wine --version
wine-3.3

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list