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

            牽著老婆滿街逛

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

            TLS 處理

            轉載自:http://bbs.pediy.com/showthread.php?threadid=17839

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

            英語又退步了唉,不準就不準吧湊或看。

            支持 TLS

            原文:Writing Your Own Packer - by BigBoote

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

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

            __declspec ( thread ) int tls_int_value = 0;


            每個線程可以通過名稱訪問它獨特的實例,就像訪問其他變量一樣。我不知道這種 TLS 形式是否有官方名稱,所以我叫它“簡化 TLS”。這種機制與操作系統兼容,并且 PE 文件中有對應的結構。這些結構包含在數據目錄的一個塊中:

            origdirinfo[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress

            問題是, 處理這信息發生在由 OS 在每個線程的創建時刻,在執行到線程開始地址之前。(這句翻譯的拗口,原文 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. )這通常不牽涉到我們,除了至少一個線程在我們解壓數據之前被執行:我們的線程!我們必須設置一個偽 TLS 處理區段捕獲 OS 在我們開始之前做的事情,然后在最后一步把這個信息傳遞給原程序。

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

            加殼器將會在運行期復制原始數據到 tls_orginal 為我們所用。tls_proxy 幾乎是一個精確的副本,除了2個項目將會被修改:
            tls_proxy.AddressOfIndex
            tls_proxy.AddressOfCallBacks

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

            設置一個全局雙字存儲 TLS slot(槽?)
            DWORD TLS_slot_index;

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

            當然還要添加兩個邏輯標志表示是否可以安全地調用原來的回調函數,和是否延期調用。這樣初始化它們:
            bool safe_to_callback_tls = false;
            bool delayed_tls_callback = false;

            再提供一些變量保存延遲調用的數據:
            PVOID TLS_dll_handle = NULL;
            DWORD TLS_reason 
            = 0;
            PVOID TLS_reserved 
            = NULL;

            編寫回調函數:
            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;
                    }

            }


            這樣會為 OS 提供一個存儲 slot 信息的地方,我們稍候恢復它,并且如果調用了我們的回調函數我們將捕獲參數,在解壓縮之后調用原來的回調函數。否則會出錯因為 0S 會在我們有機會解壓縮之前做這件事情。解壓縮之后,我們把參數傳遞給原來的回調函數。

            最后一步是這樣的:
            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 楊粼波 閱讀(494) 評論(0)  編輯 收藏 引用

            久久青草国产手机看片福利盒子| 国内精品久久久久久中文字幕| 99久久精品无码一区二区毛片 | 亚洲香蕉网久久综合影视| 精品熟女少妇aⅴ免费久久| 一本色道久久88加勒比—综合| 99re这里只有精品热久久| 久久精品国产精品亚洲毛片| 亚洲精品乱码久久久久久自慰| 中文字幕亚洲综合久久菠萝蜜| 少妇被又大又粗又爽毛片久久黑人| 草草久久久无码国产专区| 国产精品久久久久久久午夜片 | 国产一区二区精品久久岳| 91精品国产91久久久久久| 国产精品狼人久久久久影院| 精品久久久久久99人妻| 久久人人爽人人精品视频| 国产日韩欧美久久| 日日狠狠久久偷偷色综合免费| 污污内射久久一区二区欧美日韩| 久久精品无码一区二区日韩AV| 久久亚洲av无码精品浪潮| 久久久精品国产| 久久久久无码精品国产不卡| 国产日产久久高清欧美一区| 99久久99久久精品国产片果冻| 国产真实乱对白精彩久久| 久久综合久久综合亚洲| 久久精品国产亚洲AV无码娇色| 亚洲欧美日韩精品久久| 亚洲国产成人精品女人久久久 | 欧美久久久久久| 精品久久久久久久久午夜福利| 草草久久久无码国产专区| 久久精品人妻中文系列| 丁香五月网久久综合| 中文字幕精品久久久久人妻| 久久精品国产99久久久| 欧美精品福利视频一区二区三区久久久精品 | 国产精品久久99|