• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            posts - 54, comments - 32, trackbacks - 0, articles - 0
            在一個(gè)線程出現(xiàn)異常行為時(shí),比如說(shuō)CPU占用率過(guò)高,拋出異常等,你一定想知道這個(gè)線程是由哪個(gè)模塊創(chuàng)建的。因此無(wú)論在哪個(gè)操作系統(tǒng)上,獲取線程名稱是診斷線程相關(guān)問(wèn)題的重要一步。

            從線程ID獲取線程名稱通常的方法是,先獲取該線程的入口地址,然后枚舉進(jìn)程內(nèi)所有已加載模塊,最后判斷線程入口地址落在哪個(gè)加載模塊范圍內(nèi)。枚舉進(jìn)程內(nèi)已加載模塊可用Win32標(biāo)準(zhǔn)的CreateToolhelp32Snapshot/Module32First/Module32Next系列ToolHelp API得到。獲取線程入口地址則沒(méi)有線程的Win32 API可用。不過(guò)在Windows NT based操作系統(tǒng)上(包括Windows NT 4.0/2000/XP/2003,等),有一個(gè)未公開(kāi)的Native API可用:NtQueryInformationThread。其聲明如下:

            DWORD WINAPI NtQueryInformationThread(
                            HANDLE ThreadHandle,
                            THREAD_INFORMATION_CLASS ThreadInformationClass,
                            PVOID ThreadInformation,
                            ULONG ThreadInformationLength,
                            PULONG ReturnLength
                            );

            獲取線程入口地址可用:

             

            DWORD GetThreadStartAddress(DWORD dwThreadId)
            {
                HANDLE hThread 
            = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);
                DWORD retaddr, len, error;
                retaddr 
            = len = 0;
                error 
            = NtQueryInformationThread( hThread, 9&retaddr, sizeof(retaddr), &len );
                CloseHandle(hThread);
                
            if( error != 0 )
                    retaddr 
            = 0;
                
            return retaddr;
            }

            在Windows CE上就沒(méi)這么幸運(yùn)了,沒(méi)有任何現(xiàn)成的API可用。官方Windows CE Base Team的blog對(duì)這個(gè)問(wèn)題的回答是可以用Remote Kernel Tracker,不過(guò)這需要你build一個(gè)特殊的kernel image,enable一些profiler功能-這在顯示的問(wèn)題診斷中顯然是不實(shí)際的。那么有沒(méi)有辦法不需要什么特殊的配置就可像Windows桌面操作系統(tǒng)那樣獲得入口地址呢?有是有的,不過(guò)需要一些hack手段。仔細(xì)研究CE下的Thread內(nèi)核數(shù)據(jù)結(jié)構(gòu),就會(huì)發(fā)現(xiàn)Thread結(jié)構(gòu)中有一項(xiàng)是記錄線程入口地址的。

             

            typedef struct Thread {
                DWORD _1[
            3];
                PPROCESS pProc; 
            /* 0C: pointer to current process */
                PPROCESS pOwnerProc; 
            /* 10: pointer to owner process */
                DWORD _2[
            18];
                DWORD dwStartAddr; 
            /* 5c: thread PC at creation, used to get thread name */
                DWORD _3[
            10];
            }
            THREAD, *PTHREAD; /* Thread */

            因此要做的就是想辦法根據(jù)線程ID或handle得到這個(gè)數(shù)據(jù)。再研究,發(fā)現(xiàn)線程的Thread內(nèi)核數(shù)據(jù)結(jié)構(gòu)可通過(guò)句柄得到:

             

            PTHREAD pTh = HandleToThread(ThreadHandle);

            而且,在Windows CE下,線程ID和其handle的值是一樣的!!因此我們可以寫一個(gè)這樣的函數(shù)從線程ID拿到入口地址:

             

             

            DWORD GetThreadStartAddress(DWORD dwThreadId)
            {
                DWORD dwStartAddress 
            = 0;
                BOOL fOldMode 
            = SetKMode(TRUE);
                PTHREAD pTh 
            = HandleToThread((HANDLE)dwThreadId);
                
            if (pTh)
                
            {
                    dwStartAddress 
            = (DWORD)MapPtrToProcess((LPVOID)pTh->dwStartAddr, pTh->pOwnerProc->hProc);
                }

                
            return dwStartAddress;
            }

            為了使用這些內(nèi)核數(shù)據(jù)結(jié)構(gòu),我們還需要另外一些輔助結(jié)構(gòu)和函數(shù),比較完整的代碼如下。當(dāng)然,官方肯定是不建議這么做的,但是重要的是解決問(wèn)題,你說(shuō)呢。

             

            typedef struct Process {
                DWORD _1[
            2];
                HANDLE hProc; 
            /* 08: handle for this process, needed only for SC_GetProcFromPtr */
            }
            PROCESS, *PPROCESS;
            typedef 
            struct Thread {
                DWORD _1[
            3];
                PPROCESS pProc; 
            /* 0C: pointer to current process */
                PPROCESS pOwnerProc; 
            /* 10: pointer to owner process */
                DWORD _2[
            18];
                DWORD dwStartAddr; 
            /* 5c: thread PC at creation, used to get thread name */
                DWORD _3[
            10];
            }
            THREAD, *PTHREAD; /* Thread */

            typedef 
            struct cinfo {
                
            char acName[4]; /* 00: object type ID string */
                uchar disp; 
            /* 04: type of dispatch */
                uchar type; 
            /* 05: api handle type */
                
            ushort cMethods; /* 06: # of methods in dispatch table */
                
            const PFNVOID *ppfnMethods;/* 08: ptr to array of methods (in server address space) */
                
            const DWORD *pdwSig; /* 0C: ptr to array of method signatures */
                PPROCESS pServer; 
            /* 10: ptr to server process */
            }
             CINFO; /* cinfo */
            typedef CINFO 
            *PCINFO;

            typedef 
            struct _HDATA HDATA, *PHDATA;
            struct _HDATA {
                DWORD _1[
            2]; /* 00: links for active handle list */
                HANDLE hValue; 
            /* 08: Current value of handle (nonce) */
                DWORD 
            lock/* 0C: access information */
                DWORD 
            ref/* 10: reference information */
                
            const CINFO *pci; /* 14: ptr to object class description structure */
                PVOID pvObj; 
            /* 18: ptr to object */
                DWORD dwInfo; 
            /* 1C: extra handle info */
            }
            /* 20: sizeof(HDATA) */

            #ifdef x86
            struct KDataStruct {
                LPDWORD lpvTls; 
            /* 0x000 Current thread local storage pointer */
                HANDLE ahSys[NUM_SYS_HANDLES]; 
            /* 0x004 If this moves, change kapi.h */
                DWORD _1[
            4];
                
            ulong handleBase; /* 0x094 base address of handle table */
            }
            /* KDataStruct */
            #endif
            #ifdef ARM
            struct KDataStruct {
                LPDWORD lpvTls; 
            /* 0x000 Current thread local storage pointer */
                HANDLE ahSys[NUM_SYS_HANDLES]; 
            /* 0x004 If this moves, change kapi.h */
                DWORD _1[
            6];
                
            ulong handleBase; /* 0x09c handle table base address */
            }
            /* KDataStruct */
            #endif

            #define HandleToThread(h) ((THREAD *)GetObjectPtrByType((h),SH_CURTHREAD))
            #define HANDLE_ADDRESS_MASK 0x1ffffffc

            void h2p(HANDLE h, PHDATA& phdRet)
            {
                
            if ((ulong)h < NUM_SYS_HANDLES+SYS_HANDLE_BASE && (ulong)h >= SYS_HANDLE_BASE)
                    h 
            = ((KDataStruct*)PUserKData)->ahSys[(uint)h-SYS_HANDLE_BASE];
                
            if (h)
                
            {
                    phdRet 
            = (PHDATA)(((ulong)h & HANDLE_ADDRESS_MASK) + ((KDataStruct*)PUserKData)->handleBase);
                    
            if (phdRet->hValue != h)
                        phdRet 
            = 0;
                }

                
            else
                    phdRet 
            = 0;
            }


            PVOID GetObjectPtrByType(HANDLE h, 
            int type)
            {
                PHDATA phd;
                h2p(h, phd);
                
            return (phd && phd->pci && phd->pci->type==type) ? phd->pvObj : 0;
            }


            extern "C" LPVOID WINAPI MapPtrToProcess(LPVOID lpv, HANDLE hProc);
            extern "C" BOOL WINAPI SetKMode(BOOL fMode);

            DWORD GetThreadStartAddress(DWORD dwThreadId)
            {
                DWORD dwStartAddress 
            = 0;
                BOOL fOldMode 
            = SetKMode(TRUE);
                PTHREAD pTh 
            = HandleToThread((HANDLE)dwThreadId);
                
            if (pTh)
                
            {
                    dwStartAddress 
            = (DWORD)MapPtrToProcess((LPVOID)pTh->dwStartAddr, pTh->pOwnerProc->hProc);
                }

                
            return dwStartAddress;
            }

            Feedback

            # re: [轉(zhuǎn)載]Hacking Windows CE: 如何從線程ID獲取線程名稱   回復(fù)  更多評(píng)論   

            2014-12-17 10:30 by 獵頭招聘
            這篇文章我找了很久,很實(shí)用,收下了。

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久综合九色综合网站| 久久久WWW成人免费精品| 尹人香蕉久久99天天拍| 亚洲伊人久久成综合人影院 | 国产成人精品久久一区二区三区av| 久久久免费精品re6| 成人免费网站久久久| 久久99精品国产麻豆宅宅| 国产精品欧美亚洲韩国日本久久| 国产精品久久久久久久久鸭| 久久精品国产亚洲av麻豆小说 | 久久久久亚洲AV成人网人人网站 | 精品久久久久久久久免费影院| 久久人妻无码中文字幕| 久久久久亚洲AV片无码下载蜜桃 | 99久久免费国产特黄| 成人国内精品久久久久影院| 久久―日本道色综合久久| 久久久久亚洲AV成人网人人网站| 国产精品久久久99| 亚洲综合婷婷久久| 亚洲精品国产自在久久| 久久强奷乱码老熟女网站| 亚洲中文字幕久久精品无码喷水 | 狠狠色丁香久久婷婷综合_中| 日韩欧美亚洲综合久久 | 伊人色综合久久天天| 亚洲成人精品久久| 精品一久久香蕉国产线看播放 | 精品无码久久久久久午夜| 99久久免费国产精品特黄| 国色天香久久久久久久小说| 99久久久国产精品免费无卡顿| 色综合久久88色综合天天| 精品乱码久久久久久夜夜嗨 | 亚洲AV无码久久精品狠狠爱浪潮| 久久精品国产一区二区电影| 超级碰碰碰碰97久久久久| 丁香五月网久久综合| 亚洲а∨天堂久久精品9966| 国内精品久久久久久久影视麻豆 |