• <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隱藏的入口點(diǎn)

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



            TLS簡(jiǎn)介
            1. 什么是TLS?
             
            TLS是Thread Local Storage(線程局部存儲(chǔ))的簡(jiǎn)稱,是一項(xiàng)解決多線程內(nèi)部變量使用問(wèn)題的技術(shù)。用于將某些數(shù)據(jù)和一特定線程關(guān)聯(lián)起來(lái),即,這些數(shù)據(jù)為關(guān)聯(lián)線程所獨(dú)有(私有)。在多線程編程中, 同一個(gè)變量, 如果要讓多個(gè)線程共享訪問(wèn), 那么這個(gè)變量可以使用關(guān)鍵字volatile進(jìn)行聲明; 而如果一個(gè)變量不想被多個(gè)線程共享訪問(wèn), 那么就應(yīng)該使用TLS。
             
            2. 如何使用TLS編程?

            TLS使用非常簡(jiǎn)單, 只要對(duì)變量聲明時(shí)使用__declspec(thread)修飾就可以了。例如:
            _declspec(thread) int g_nData = 0;

            3. 一個(gè)使用TLS的例子
            //--------------------------------------------------------------------------------------------------------
            #include <windows.h> 
            #include 
            <stdio.h> 
             
            #define THREADCOUNT 4 
            DWORD dwTlsIndex; 
             
            int iNUM_OF_CALL_COMMON=0;
            int iNUM_OF_CALL_THREAD=0;
             
            VOID ErrorExit(LPSTR); 
             
            VOID CommonFunc(VOID) 

               LPVOID lpvData; 
             
            // Retrieve a data pointer for the current thread. 
             iNUM_OF_CALL_COMMON++;
             
               lpvData 
            = TlsGetValue(dwTlsIndex); 
               
            if ((lpvData == 0&& (GetLastError() != ERROR_SUCCESS)) 
                  ErrorExit(
            "TlsGetValue error"); 
             
            // Use the data stored for the current thread. 
                printf("common: thread %d: lpvData=%lx\n"
                  GetCurrentThreadId(), lpvData); 
             
               Sleep(
            5000); 
            }
             
             
            DWORD WINAPI ThreadFunc(VOID) 

               LPVOID lpvData; 
             
            // Initialize the TLS index for this thread. 
             iNUM_OF_CALL_THREAD++;
             
               lpvData 
            = (LPVOID) LocalAlloc(LPTR, 256); 
               
            if (! TlsSetValue(dwTlsIndex, lpvData)) 
                  ErrorExit(
            "TlsSetValue error"); 
             
               printf(
            "thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData); 
             
               CommonFunc(); 
             
            // Release the dynamic memory before the thread returns. 
                lpvData = TlsGetValue(dwTlsIndex); 
               
            if (lpvData != 0
                  LocalFree((HLOCAL) lpvData); 
             
               
            return 0
            }
             
             
            int main(VOID) 

               DWORD IDThread; 
               HANDLE hThread[THREADCOUNT]; 
               
            int i; 
             
            // Allocate a TLS index. 
                if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
                  ErrorExit(
            "TlsAlloc failed"); 
             
            // Create multiple threads. 
                for (i = 0; i < THREADCOUNT; i++
               

                  hThread[i] 
            = CreateThread(NULL, // default security attributes 
                     0,                           // use default stack size 
                     (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function 
                     NULL,                    // no thread function argument 
                     0,                       // use default creation flags 
                     &IDThread);              // returns thread identifier 
             
               
            // Check the return value for success. 
                  if (hThread[i] == NULL) 
                     ErrorExit(
            "CreateThread error\n"); 
               }
             
             
              
            // printf("All threads were created.\n");
               for (i = 0; i < THREADCOUNT; i++
                  WaitForSingleObject(hThread[i], INFINITE); 
             
               TlsFree(dwTlsIndex);
             
               printf(
            "The nums of thread is: %d\n",iNUM_OF_CALL_THREAD);
               printf(
            "The nums of call is: %d\n",iNUM_OF_CALL_COMMON);
             
               
            return 0
            }
             
             
            VOID ErrorExit (LPSTR lpszMessage) 
            {  
               fprintf(stderr, 
            "%s\n", lpszMessage); 
               ExitProcess(
            0); 
            }
              
            //--------------------------------------------------------------------------------------------------------

            4. T L S的內(nèi)部數(shù)據(jù)結(jié)構(gòu)
             
            1.jpg
            圖1 用于管理T L S的內(nèi)部數(shù)據(jù)結(jié)構(gòu)
             
             
            每個(gè)標(biāo)志均可設(shè)置為FREE或者INUSE,表示TLS槽( s l o t )是否正在使用。Microsoft保證至少TLS_MINIMUM_AVAILABLE位標(biāo)志是可供使用的。
             
            5. 相關(guān)API
             
            Windows TLS的API: TlsAlloc, TlsFree, TlsSetValue, TlsGetValue。
             
            ● DWORD TlsAlloc(); //(若要使用動(dòng)態(tài)T L S,首先必須調(diào)用TlsAlloc函數(shù))
             
            這個(gè)函數(shù)命令系統(tǒng)對(duì)進(jìn)程中的位標(biāo)志進(jìn)行掃描,并找出一個(gè)FREE標(biāo)志。然后系統(tǒng)將該標(biāo)志從FREE改為INUSE,并且TlsAlloc返回位數(shù)組中的標(biāo)志的索引。DLL(或APP)通常將該索引保存在一個(gè)全局變量中,因?yàn)樗闹凳敲總€(gè)進(jìn)程而不是每個(gè)線程使用的值。
             
            ● BOOL TlsSetValue( //將一個(gè)值放入線程的數(shù)組中
             
            DWORD dwTlsIndex,
             
            PVOID pvTlsValue);
             
            ● PVOID TlsGetValue(DWORD dwTlsIndex); //要從線程的數(shù)組中檢索一個(gè)值
             
            ● BOOL TlsFree(DWORD dwTlsIndex); //當(dāng)在所有線程中不再需要保留TLS槽時(shí)
             
             
             
            參考資料:Jeffrey Richter《《Programming Applications for Microsoft Windows (4th Ed.)》》Chapter 21
             
            6. TLS目錄
             
            7.JPG
            TLS Callback Functions
            這是線程建立和退出時(shí)的回調(diào)函數(shù), 包括主線程和其他線程.AddressOfCallBacks 是指向函數(shù)指針數(shù)組的指針, 以 0 結(jié)束.
            typedef struct _TEB {
            NT_TIB Tib;
            PVOID EnvironmentPointer;
            CLIENT_ID Cid;
            PVOID ActiveRpcInfo;
            PVOID ThreadLocalStoragePointer; ; 2ch
            PPEB Peb; ; 30h
            ULONG LastErrorValue; ; 34h
            …}


            TLS目錄 #define IMAGE_DIRECTORY_ENTRY_TLS 9 (第十個(gè)目錄)
             
             
             
            Tls隱藏的入口點(diǎn)利用
             
             
            就是利用Address of Callbacks字段,寫入要執(zhí)行的代碼的地址就可以了.
             
             
            測(cè)試對(duì)象:test.exe
             
            程序類型:delphi編寫
             
             
             
            PeEditor檢測(cè)Tls信息(文件偏移59400H處)如下:
            2.jpg
             
            TLS信息
             
            ------------------------------------------
             
             
             
            目錄表: 0045D000
             
            TLS數(shù)據(jù): 0045D010
             
            索引變量: 004570A0
             
            調(diào)用返回地址: 0045E010 (調(diào)用返回地址)
             
            ------------------------------------------
             
             
             
            我們打算讓系統(tǒng)在0045E010處執(zhí)行我們的代碼,就需要在這個(gè)地方對(duì)應(yīng)的文件偏移處寫入我們的代碼。
             
             
             
            觀察節(jié)表信息
             
            VA=0045E010,按照文件不需要重定位去計(jì)算則RVA=0005E010
             
            觀察節(jié)表信息,這個(gè)值處于.rdata節(jié)內(nèi)。
             
            .rdata節(jié)起始RVA=0005E000,起始Offset為00059400
             
            則callback地址對(duì)應(yīng)的Offset=(0005E010 - 0005E000)+ 00059400 =00059410
             
            注意在這里(00059410H)應(yīng)該寫入一個(gè)函數(shù)地址。

            打造一個(gè)簡(jiǎn)單的代碼:

            ----------------------------------------------------------------
             
            .386
             
            .model flat,stdcall
             
            option casemap
            :none
             
             
             
            include windows
            .inc
             
            include user32
            .inc
             
             
             
            includelib user32
            .lib
             
             
             
            .code
             
            start
            :
             
            jmp 
            @F
             
             
             
            db 
            'Run thru Tls entry point.',0
             
            @@
            : 
             
            mov eax
            ,$
             
            sub eax,26
             
            call 
            @delta
             
            @delta:
             
            pop ebp
             
            sub ebp,offset @delta
             
            add eax
            ,ebp
             
            invoke MessageBox
            ,NULL,eax,NULL,0
             
            ret
             
            end start
             
            ----------------------------------------------------------------

            編譯生成可執(zhí)行文件,這只是一個(gè)簡(jiǎn)單的彈出對(duì)話框的程序。
            3.jpg
             
            打開(kāi)16進(jìn)制工具,載入msgbox.exe,復(fù)制代碼:
            4.jpg
             
            注意00402000H處存放的是MessageBox的入口地址,我把它固化下來(lái),動(dòng)態(tài)跟蹤發(fā)現(xiàn)是8A05D577H。(當(dāng)然在編程時(shí)可以動(dòng)態(tài)搜尋我們需要的API,為簡(jiǎn)單起見(jiàn)這里Hard-code一下。)
             
            打開(kāi)16進(jìn)制工具,載入藝術(shù)字體2.exe,定位到00059410。
            5.jpg
             
            我們把代碼復(fù)制在偏移00059410處,對(duì)應(yīng)的VA=0045E030H,則把0045E030存入偏移00059410。
             
            還要注意最后的 MessageBox的入口地址我們使用硬編碼的方式,我們把這個(gè)地址寫入在00059480處了。保存修改,然后運(yùn)行程序。程序首先彈出兩個(gè)對(duì)話框(一個(gè)是TLS模板,一個(gè)是主線程創(chuàng)建),結(jié)束程序運(yùn)行還會(huì)彈出一個(gè)對(duì)話框,不過(guò)這個(gè)對(duì)話框太丑了:
             
            6.jpg
             
             
            說(shuō)明:我在看一本介紹病毒知識(shí)的書籍時(shí)看到作者提及到這么一句話,大概意思是說(shuō)他們公司某人發(fā)現(xiàn)了這個(gè)秘密,一直沒(méi)有公布,不過(guò)后來(lái)由于rgb利用此技術(shù)制造了病毒,也就無(wú)所謂秘密可言了。由于Tls入口要比OEP先執(zhí)行,所以在加殼與脫殼中都有利用的價(jià)值。

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


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


            亚洲国产成人精品女人久久久 | 国产精品女同久久久久电影院| 一级做a爰片久久毛片16| 久久夜色精品国产噜噜噜亚洲AV| 亚洲欧洲中文日韩久久AV乱码| 久久本道综合久久伊人| 国产精品日韩深夜福利久久| 久久午夜电影网| 日本免费一区二区久久人人澡 | 久久久久久国产精品无码下载| 国产欧美一区二区久久| 国产精品久久99| 国产精品美女久久久久网| 久久精品人人做人人妻人人玩| 久久天天躁夜夜躁狠狠| 久久99精品久久久大学生| 亚洲中文字幕无码一久久区 | 精品国产乱码久久久久久人妻| 久久这里有精品| 久久久国产打桩机| 人妻少妇久久中文字幕 | 99久久国产综合精品网成人影院| 国产一久久香蕉国产线看观看 | 久久亚洲国产成人影院网站| 欧美日韩成人精品久久久免费看 | 无码人妻精品一区二区三区久久 | 人妻丰满AV无码久久不卡| 久久精品毛片免费观看| 久久福利青草精品资源站| 久久精品国产欧美日韩| 久久精品中文字幕大胸| 熟妇人妻久久中文字幕| 99国产欧美久久久精品蜜芽| 99久久99久久精品国产| 国产精品久久久香蕉| 久久A级毛片免费观看| 国产叼嘿久久精品久久| 97久久国产综合精品女不卡| 99久久精品国产高清一区二区| 久久精品无码一区二区三区免费 | 99久久精品国产高清一区二区 |