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

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            TLS 處理

            轉(zhuǎn)載自:http://bbs.pediy.com/showthread.php?threadid=17839

            標(biāo) 題: 翻譯 TLS 處理
            作 者: forgot
            時(shí) 間: 2005-10-23,12:19
            鏈 接: http://bbs.pediy.com/showthread.php?t=17839

            英語又退步了唉,不準(zhǔn)就不準(zhǔn)吧湊或看。

            支持 TLS

            原文:Writing Your Own Packer - by BigBoote

            TLS(Thread Local Storage,線程局部存儲(chǔ))是一種便利的編程機(jī)制。我們通常不使用,因此并不太關(guān)心。但是要壓縮的原程序可能會(huì)用到它。事實(shí)上,Delphi 總是使用它,如果我們打算支持 Delphi 程序,最好兼容它。

            TLS 基本上是通過 API 實(shí)現(xiàn)。大致過程是,你分配一個(gè)“ Index(索引)”并存儲(chǔ)在一個(gè)全局變量中。通過這個(gè) Index 獲得針對(duì)每個(gè)線程的一個(gè)雙字值。通常使用這個(gè)值保存一個(gè)為每個(gè)線程分配好的內(nèi)存塊的指針。人們認(rèn)為這樣很乏味,一個(gè)特殊機(jī)制的出現(xiàn)使得實(shí)現(xiàn)它更容易些。因此,你可以這樣寫代碼:

            __declspec ( thread ) int tls_int_value = 0;


            每個(gè)線程可以通過名稱訪問它獨(dú)特的實(shí)例,就像訪問其他變量一樣。我不知道這種 TLS 形式是否有官方名稱,所以我叫它“簡化 TLS”。這種機(jī)制與操作系統(tǒng)兼容,并且 PE 文件中有對(duì)應(yīng)的結(jié)構(gòu)。這些結(jié)構(gòu)包含在數(shù)據(jù)目錄的一個(gè)塊中:

            origdirinfo[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress

            問題是, 處理這信息發(fā)生在由 OS 在每個(gè)線程的創(chuàng)建時(shí)刻,在執(zhí)行到線程開始地址之前。(這句翻譯的拗口,原文 The problem is that the processing of this information happens by the OS on the creation of every thread prior to execution being passed to the thread start address. )這通常不牽涉到我們,除了至少一個(gè)線程在我們解壓數(shù)據(jù)之前被執(zhí)行:我們的線程!我們必須設(shè)置一個(gè)偽 TLS 處理區(qū)段捕獲 OS 在我們開始之前做的事情,然后在最后一步把這個(gè)信息傳遞給原程序。

            為此,我在外部加殼器外部全局結(jié)構(gòu)添加了2個(gè)項(xiàng)目:
            GlobalExternVars
            {
            //(other stuff we previously described)
            IMAGE_TLS_DIRECTORY tls_original;
            IMAGE_TLS_DIRECTORY tls_proxy;
            }
            ;

            加殼器將會(huì)在運(yùn)行期復(fù)制原始數(shù)據(jù)到 tls_orginal 為我們所用。tls_proxy 幾乎是一個(gè)精確的副本,除了2個(gè)項(xiàng)目將會(huì)被修改:
            tls_proxy.AddressOfIndex
            tls_proxy.AddressOfCallBacks

            在這個(gè)塊中我們將要初始化 AddressOfIndex 指向一個(gè)正常的全局雙字變量,并且我們將初始化 AddressOfCallBacks 指向一個(gè)函數(shù)指針數(shù)組。它是一個(gè)線程創(chuàng)建時(shí)將會(huì)被調(diào)用的函數(shù)指針列表。用戶使用它定義 TLS 對(duì)象的初始化。唉,我沒見過一個(gè)編譯器使用它。此外,在 9x 下,這些函數(shù)不會(huì)被調(diào)用。盡管如此,我們還是要支持它以防萬一哪天它會(huì)被使用。我們令 AddressOfCallbacks 指向一個(gè)2個(gè)成員的數(shù)組,一個(gè)試我們將要執(zhí)行的函數(shù)指針,另一個(gè)是 NULL 作為列表結(jié)束符。

            設(shè)置一個(gè)全局雙字存儲(chǔ) TLS slot(槽?)
            DWORD TLS_slot_index;

            TLS 回調(diào)函數(shù)必須是這種原型:
            extern "C" void NTAPI TLS_callback ( PVOID DllHandle, DWORD Reason, PVOID Reserved );

            當(dāng)然還要添加兩個(gè)邏輯標(biāo)志表示是否可以安全地調(diào)用原來的回調(diào)函數(shù),和是否延期調(diào)用。這樣初始化它們:
            bool safe_to_callback_tls = false;
            bool delayed_tls_callback = false;

            再提供一些變量保存延遲調(diào)用的數(shù)據(jù):
            PVOID TLS_dll_handle = NULL;
            DWORD TLS_reason 
            = 0;
            PVOID TLS_reserved 
            = NULL;

            編寫回調(diào)函數(shù):
            extern "C" void NTAPI TLS_callback ( PVOID DllHandle, DWORD Reason, PVOID Reserved )
            {
                    
            if ( safe_to_callback_tls )
                    
            {
                            PIMAGE_TLS_CALLBACK
            * ppfn = g_pkrdat.m_tlsdirOrig.AddressOfCallBacks;
                            
            if ( ppfn )
                            
            {
                                    
            while ( *ppfn )
                                    
            {
                                    (
            *ppfn) ( DllHandle, Reason, Reserved );
                                    
            ++ppfn;
                                    }

                            }


                    }

                    
            else
                    
            {
                            delayed_tls_callback 
            = true;
                            TLS_dll_handle 
            = DllHandle;
                            TLS_reason 
            = Reason;
                            TLS_reserved 
            = Reserved;
                    }

            }


            這樣會(huì)為 OS 提供一個(gè)存儲(chǔ) slot 信息的地方,我們稍候恢復(fù)它,并且如果調(diào)用了我們的回調(diào)函數(shù)我們將捕獲參數(shù),在解壓縮之后調(diào)用原來的回調(diào)函數(shù)。否則會(huì)出錯(cuò)因?yàn)?nbsp;0S 會(huì)在我們有機(jī)會(huì)解壓縮之前做這件事情。解壓縮之后,我們把參數(shù)傳遞給原來的回調(diào)函數(shù)。

            最后一步是這樣的:
            void FinalizeTLSStuff()
            {
                    
            if ( origdirinfo[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0 )
                    
            {
                            
            *gev.tls_original.AddressOfIndex = TLS_slot_index;
                            
            void* TLS_data;

                            __asm
                            
            {
                            mov ecx, DWORD PTR TLS_slot_index;
                            mov edx, DWORD PTR fs:[02ch]
                            mov ecx, DWORD PTR [edx
            +ecx*4]
                            mov pvTLSData, ecx
                            }


                            
            int size = gev.tls_original.EndAddressOfRawData - gev.tls_original.StartAddressOfRawData;

                            memcpy ( pvTLSData, (
            void*) gev.tls_original.StartAddressOfRawData, size );
                            memset ( (
            void*) gev.tls_original.EndAddressOfRawData, 0,
                            gev.tls_original.SizeOfZeroFill );
                    }


                    safe_to_callback_tls 
            = true;
                    
            if ( delayed_tls_callback )
                    
            {
                            TLSCallbackThunk ( TLS_dll_handle TLS_reason TLS_reserved );
                    }

            }

            posted on 2008-04-29 14:46 楊粼波 閱讀(497) 評(píng)論(0)  編輯 收藏 引用


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


            久久人妻少妇嫩草AV无码蜜桃| …久久精品99久久香蕉国产| 久久久久99精品成人片牛牛影视| 久久天天日天天操综合伊人av| 狠狠色丁香久久婷婷综合图片| 久久99国产综合精品| 国产精品内射久久久久欢欢| 久久综合色老色| 国产成人精品久久二区二区| 欧美亚洲另类久久综合婷婷| 久久久精品人妻一区二区三区四| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久精品成人影院| 亚洲午夜久久久久久久久电影网 | 久久久精品午夜免费不卡| 久久亚洲综合色一区二区三区| 久久影院久久香蕉国产线看观看| 亚洲AV无码久久寂寞少妇| 久久久精品日本一区二区三区 | 久久笫一福利免费导航 | 久久精品国产久精国产一老狼| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 国产成人精品综合久久久久| 色成年激情久久综合| 久久男人Av资源网站无码软件 | 久久亚洲视频| 久久精品国产亚洲7777| 狠狠色丁香婷婷久久综合不卡| 亚洲综合日韩久久成人AV| 女同久久| 色诱久久av| 亚洲国产精品成人AV无码久久综合影院| 久久精品午夜一区二区福利| 东方aⅴ免费观看久久av | 国产精品久久网| 九九99精品久久久久久| 久久久久久亚洲Av无码精品专口| 久久99热这里只有精品66| 亚洲Av无码国产情品久久| 天天综合久久一二三区| 无码国内精品久久人妻麻豆按摩|