【问题标题】:Process Creation Time from Process Memory (Win32)从进程内存创建进程时间 (Win32)
【发布时间】:2014-06-15 20:15:49
【问题描述】:

我必须从某个进程的 PID 中检索进程创建时间。我相信(不确定)Windows 将进程启动时间保存在进程内存(用户模式)中的某个位置。是否可以直接从内存中读取??

我知道 windbg 有一个选项 (.time) 可以做到这一点,但我想知道是否可以使用 windbg 或任何其他调试器手动获取它??

感谢 Adv.

【问题讨论】:

    标签: windows debugging windbg


    【解决方案1】:

    此信息存储在内核模式对象中:

    0:077> dt nt!_EPROCESS
    ntdll!_EPROCESS
       +0x000 Pcb              : _KPROCESS
       +0x06c ProcessLock      : _EX_PUSH_LOCK
       +0x070 CreateTime       : _LARGE_INTEGER
       +0x078 ExitTime         : _LARGE_INTEGER
       ...
    

    因此,在运行时获取此信息的唯一方法是通过对 GetProcessTimes() 的 API 调用,正如 Raymond Chen 或 .NET 中的 Process.StartTime 所述(可能在内部使用 API 调用)。

    要在调试器中手动获取信息,您需要一个指向 _EPROCESS 结构的指针,然后使用dt nt!_EPROCESS <address>。您可以使用!process 0 7 myapp.exe 从内核转储中获取地址。

    【讨论】:

    • 感谢您的信息..我真的很感激..使用用户区调试器似乎无法完成..本周末将通过反转 GetProcessTimes!Kernel32 来尝试一下,看看效果如何工作..
    • GetProcessTimes 使用 Processinfo 类 4 调用 ZwQueryInformtionProcess
    【解决方案2】:

    您需要使用GetProcessTimes。这需要进程的句柄,您可以使用OpenProcess 从指定的 PID 中检索该句柄。类似以下的内容应该会产生与 .time 类似的结果。

    void Process(_TCHAR* szPid)
    {
    _TCHAR* pEnd;
    DWORD pid = ::_tcstoul(szPid, &pEnd, 10);
    
    HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
    
    if (handle == NULL)
    {
               // Error handling omitted.
    }
    else
    {
        FILETIME createTime, exitTime, kernelTime, userTime;
    
        if (!GetProcessTimes(handle, &createTime, &exitTime, &kernelTime, &userTime))
        {
                        // Error handling omitted.
        }
        else
        {
            OutputToConsole(L"Process Uptime", &createTime);
            OutputToConsole(L"  Kernel time", &kernelTime);
            OutputToConsole(L"  User time", &userTime);
        }
    
        ::CloseHandle(handle);
    }
    }
    
     void OutputToConsole(TCHAR* descr, const FILETIME* lpFileTime)
     {
    SYSTEMTIME stDiff = FileTimeDiff(lpFileTime);
    _tprintf(TEXT("%s: %hu days %hu:%02hu:%02hu.%03hu\n"), descr, stDiff.wDay, stDiff.wHour, stDiff.wMinute, stDiff.wSecond, stDiff.wMilliseconds);
     }
    
     SYSTEMTIME FileTimeDiff(const FILETIME* ftDT)
     {
    SYSTEMTIME stNow;
    ::GetSystemTime(&stNow);
    FILETIME ftNow;
    ::SystemTimeToFileTime(&stNow, &ftNow);
    
    ULARGE_INTEGER uliNow, uliCurrent, uliDiff;
    uliNow.LowPart = ftNow.dwLowDateTime;
    uliNow.HighPart = ftNow.dwHighDateTime;
    
    uliCurrent.LowPart = ftDT->dwLowDateTime;
    uliCurrent.HighPart = ftDT->dwHighDateTime;
    
    uliDiff.QuadPart = uliNow.QuadPart - uliCurrent.QuadPart;
    FILETIME ftDiff;
    ftDiff.dwLowDateTime = uliDiff.LowPart;
    ftDiff.dwHighDateTime = uliDiff.HighPart;
    
    SYSTEMTIME stDiff;
    ::FileTimeToSystemTime(&ftDiff, &stDiff);
    
    return stDiff;
     }
    

    我的一个过程的结果如下:

    Process Uptime: 8 days 7:18:42.303
      Kernel time: 16 days 7:06:31.995
      User time: 16 days 7:11:16.462
    

    【讨论】:

    • 感谢您的详细解释..我真的很感激..但这实际上不是我要找的.. :(
    【解决方案3】:

    从命令提示符处使用 wmic CreationDate 将列出所有正在运行的进程的创建时间

    time:\>wmic process get processid , name , creationdate | grep opera
    20140616162551  opera.exe               1108
    
    time:\>tlist 1108 | grep Stack
    1108 opera.exe         windows - Process Creation Time from Process Memory (Win3
    2) - Stack Overflow - Opera
    
    time:\>
    

    如果不推荐使用 grep,请在 windows 中使用 findstr.exe 收件箱实用程序

    time:\>wmic process get processid,creationdate,name | findstr /C:opera
    20140616162551  opera.exe               1108
    

    如果你想从 windbg 获取它,请创建一个脚本文件并从命令提示符运行本地 kd 会话,如下所示(/debug switch reqd in os vista+)

    C:\>type printtimes.txt
    aS ${/v:ctime}  @@( ( ( nt!_EPROCESS * ) @#Process )->CreateTime.QuadPart ) ;
    aS ${/v:pid}    @@( ( ( nt!_EPROCESS * ) @#Process )->UniqueProcessId ) ;
    aS ${/v:imname} @@( ( ( nt!_EPROCESS * ) @#Process )->ImageFileName ) ;
    .block { !for_each_process ".printf \"%20ma\t%8d\t\",${imname},${pid};!filetime
    ${ctime}" }
    q
    C:\>kd -kl -c "$$>a< c:\\printtimes.txt" | findstr /c:opera
               opera.exe        1108         6/16/2014 16:25:51.500 (unknown)
    

    GetProcessTimes 是这样实现的

    #include <windows.h>
    #include <stdio.h>
    void printtimes(FILETIME *ft);
    int main(int argc, char * argv[])
    {
        if (argc != 2) { printf ("usage proctime.exe Pid\n"); return 0;}
        HANDLE      hProc = NULL;
        FILETIME    ft[4];
        memset(&ft,0,sizeof(ft));
        if ( ( hProc =  OpenProcess( 
            PROCESS_QUERY_INFORMATION, 
            FALSE, strtoul( argv[1], NULL, 10 ) ) ) != NULL )
        {
            __asm
            {
                push 0                  // retn value ignored
                    push 20h            // sizeof input buffer 
                    lea eax,ft  
                    push eax            // inputbuffer
                    push 4              // processinfoclass
                    push hProc          // Handle to Process
                    lea ecx,retback  
                    push ecx            // setup stack and index for sysenter
                    mov eax, 09ah       // index of NtQueryInformationProcess
                    mov edx,07ffe0300h  // sysenter in winxp sp3
                    call [edx]          // kuser KiFastSystemCall pointer
                retn 14h                
            }
    retback:
            printtimes(&ft[0]);
            CloseHandle(hProc);
        }
        else
        {
            printf("Could not open process quitting\n ");
        }
        return 0;
    }
    void printtimes(FILETIME *ft)
    {
        SYSTEMTIME  stime,ltime; 
        memset (&stime,0,sizeof(stime));
        memset (&ltime,0,sizeof(stime));
        FileTimeToSystemTime(ft,&stime);
        SystemTimeToTzSpecificLocalTime(NULL,&stime,&ltime);
        printf(
            "%02d-%02d-%04d %02d:%02d:%02d\n",
            ltime.wDay,ltime.wMonth,ltime.wYear,
            ltime.wHour,ltime.wMinute,ltime.wSecond);
    }
    

    结果

    time:\>proctimenew.exe
    usage proctime.exe Pid
    
    time:\>proctimenew.exe 1108
    16-06-2014 16:25:51
    
    time:\>
    

    【讨论】:

    • 谢谢...这也很有用..但我们不能在 windows 上使用 grep..我们需要使用 find.. :)
    • grep 可用于 gnuwin32 中的 windows,如果您不喜欢 grep,请在 windows 中使用 findstr 收件箱实用程序
    • cool..thnx..顺便说一句,我使用这个 wmic 进程获取 processid,name,creationdate |找到“iexplore”
    • @DavidA。这不是手动的,也不是使用调试器。这怎么能成为公认的答案?请更新您的问题,以便最终至少清楚您想要什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    相关资源
    最近更新 更多