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


            亚洲国产成人久久综合一| 丁香色欲久久久久久综合网| 久久综合九色综合网站| 久久精品国产久精国产思思| 国产精品久久亚洲不卡动漫| 国产福利电影一区二区三区久久久久成人精品综合 | 色综合久久久久久久久五月| 亚洲狠狠婷婷综合久久蜜芽 | 中文无码久久精品| 亚洲国产精品久久久久婷婷老年| 人人狠狠综合88综合久久| 久久久久AV综合网成人| 青青青青久久精品国产h久久精品五福影院1421 | 国产成人精品综合久久久久| 久久综合偷偷噜噜噜色| 狠狠色丁香久久婷婷综合蜜芽五月| 久久久久久国产精品无码超碰| 国产精品女同一区二区久久| 亚洲午夜久久久影院伊人| 久久强奷乱码老熟女| 久久人人爽人人爽人人AV| 久久强奷乱码老熟女网站| 亚洲国产精品久久久久久| 久久青青草原亚洲av无码app| 精品久久久久久久国产潘金莲 | 99久久国产宗和精品1上映| 久久精品国产亚洲Aⅴ香蕉| 伊人久久大香线焦综合四虎| 日日噜噜夜夜狠狠久久丁香五月 | 国产精品VIDEOSSEX久久发布| 国内精品久久久久影院一蜜桃| 无码人妻少妇久久中文字幕蜜桃 | 久久精品国产亚洲AV无码麻豆 | 久久精品国产AV一区二区三区 | 国内精品久久久久久麻豆| 久久久久久综合一区中文字幕| 久久天堂AV综合合色蜜桃网| 久久成人国产精品| 91久久精品91久久性色| 香港aa三级久久三级| 国内精品久久久久国产盗摄|