进程内存(Win32)的进程创建时间

时间:2014-06-15 20:15:49

标签: windows debugging windbg

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

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

感谢Adv。

3 个答案:

答案 0 :(得分:4)

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

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从内核转储中获取地址。

答案 1 :(得分:4)

您需要使用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

答案 2 :(得分:1)

在命令提示符下使用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会话,如下所示(/ os vista中的/ debug switch reqd +)

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:\>