• <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>
                  遠(yuǎn)程線程作為一項(xiàng)"合法"的代碼注入技術(shù),在windows上被大量使用, 它的本質(zhì)就是把一塊可執(zhí)行代碼寫(xiě)入到對(duì)方進(jìn)程,然后讓其起運(yùn)行起來(lái)。

                  一般它的實(shí)現(xiàn)過(guò)程是這樣的, 通過(guò)VirtualAllocEx在目標(biāo)進(jìn)程分配內(nèi)存空間,然后通過(guò)WriteProcessMemory將我們的可執(zhí)行代碼寫(xiě)入到目標(biāo)進(jìn)程,最后通過(guò)CreateRemoteThread讓我們的可執(zhí)行代碼在目標(biāo)進(jìn)程里運(yùn)行起來(lái)。

                 一般實(shí)現(xiàn)遠(yuǎn)程線程有2種方法, 一種是《windows核心編程》里介紹的,通過(guò)線程函數(shù)和LoadLibrary API函數(shù)申明的相似性, 直接在目標(biāo)進(jìn)程里調(diào)用LoadLibrary加載我們DLL,這樣我們只要在DLL_PROCESS_ATTACH里執(zhí)行我們的代碼就可以了。代碼如下, 通過(guò)InjectLib在目標(biāo)進(jìn)程加載我們的DLL, 通過(guò)EjectLib卸載我們的DLL:
            ///////////////////////////////////////////////////////////////////////////////
            BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) 
            {

               BOOL fOk = FALSE; // Assume that the function fails
               HANDLE hProcess = NULL, hThread = NULL;
               PWSTR pszLibFileRemote = NULL;

               __try {
                  // Get a handle for the target process.
                  hProcess = OpenProcess(
                     PROCESS_QUERY_INFORMATION |   // Required by Alpha
                     PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
                     PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
                     PROCESS_VM_WRITE,             // For WriteProcessMemory
                     FALSE, dwProcessId);
                  if (hProcess == NULL)
                  {
                      __leave;
                  }

                  // Calculate the number of bytes needed for the DLL's pathname
                  int cch = 1 + lstrlenW(pszLibFile);
                  int cb  = cch * sizeof(WCHAR);

                  // Allocate space in the remote process for the pathname
                  pszLibFileRemote = (PWSTR) 
                     VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
                  if (pszLibFileRemote == NULL)
                  {      
                     __leave;
                  }

                  // Copy the DLL's pathname to the remote process's address space
                  if (!WriteProcessMemory(hProcess, pszLibFileRemote, 
                     (PVOID) pszLibFile, cb, NULL))
                  {      
                     __leave;
                  }

                  // Get the real address of LoadLibraryW in Kernel32.dll
                  PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
                     GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
                  if (pfnThreadRtn == NULL)
                  {
                      __leave;
                  }


                  // Create a remote thread that calls LoadLibraryW(DLLPathname)
                  hThread = CreateRemoteThread(hProcess, NULL, 0, 
                     pfnThreadRtn, pszLibFileRemote, 0, NULL);
                  if (hThread == NULL)
                  {
                     __leave;
                  }

                  // Wait for the remote thread to terminate
                  WaitForSingleObject(hThread, INFINITE);

                  fOk = TRUE; // Everything executed successfully
               }
               __finally { // Now, we can clean everthing up

                  
            // Free the remote memory that contained the DLL's pathname
                  if (pszLibFileRemote != NULL) 
                     VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

                  if (hThread  != NULL) 
                     CloseHandle(hThread);

                  if (hProcess != NULL) 
                     CloseHandle(hProcess);
               }

               return(fOk);
            }


            ///////////////////////////////////////////////////////////////////////////////


            BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) 
            {

               // Allocate a (stack) buffer for the Unicode version of the pathname
               PWSTR pszLibFileW = (PWSTR) 
                  _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

               // Convert the ANSI pathname to its Unicode equivalent
               wsprintfW(pszLibFileW, L"%S", pszLibFile);

               // Call the Unicode version of the function to actually do the work.
               return(InjectLibW(dwProcessId, pszLibFileW));
            }


            ///////////////////////////////////////////////////////////////////////////////


            BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) 
            {

               BOOL fOk = FALSE; // Assume that the function fails
               HANDLE hthSnapshot = NULL;
               HANDLE hProcess = NULL, hThread = NULL;

               __try {
                  // Grab a new snapshot of the process
                  hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
                  if (hthSnapshot == INVALID_HANDLE_VALUE)
                  {
                     __leave;
                  }

                  // Get the HMODULE of the desired library
                  MODULEENTRY32W me = { sizeof(me) };
                  BOOL fFound = FALSE;
                  BOOL fMoreMods = Module32FirstW(hthSnapshot, &me);
                  for (; fMoreMods; fMoreMods = Module32NextW(hthSnapshot, &me)) {
                     fFound = (lstrcmpiW(me.szModule,  pszLibFile) == 0) || 
                              (lstrcmpiW(me.szExePath, pszLibFile) == 0);
                     if (fFound) break;
                  }
                  if (!fFound)
                  {
                     __leave;
                  }

                  // Get a handle for the target process.
                  hProcess = OpenProcess(
                     PROCESS_QUERY_INFORMATION |   // Required by Alpha
                     PROCESS_CREATE_THREAD     | 
                     PROCESS_VM_OPERATION,  // For CreateRemoteThread
                     FALSE, dwProcessId);
                  if (hProcess == NULL)
                  {    
                     __leave;
                  }

                  // Get the real address of LoadLibraryW in Kernel32.dll
                  PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
                     GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
                  if (pfnThreadRtn == NULL)
                  {
                     __leave;
                  }

                  // Create a remote thread that calls LoadLibraryW(DLLPathname)
                  hThread = CreateRemoteThread(hProcess, NULL, 0, 
                     pfnThreadRtn, me.modBaseAddr, 0, NULL);
                  if (hThread == NULL)
                  {
                     __leave;
                  }

                  // Wait for the remote thread to terminate
                  WaitForSingleObject(hThread, INFINITE);

                  fOk = TRUE; // Everything executed successfully
               }
               __finally { // Now we can clean everything up

                  if (hthSnapshot != NULL) 
                     CloseHandle(hthSnapshot);

                  if (hThread     != NULL) 
                     CloseHandle(hThread);

                  if (hProcess    != NULL) 
                     CloseHandle(hProcess);
               }

               return(fOk);
            }


            ///////////////////////////////////////////////////////////////////////////////


            BOOL WINAPI EjectLibA(DWORD dwProcessId, PCSTR pszLibFile)
            {

               // Allocate a (stack) buffer for the Unicode version of the pathname
               PWSTR pszLibFileW = (PWSTR) 
                  _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

               // Convert the ANSI pathname to its Unicode equivalent
               wsprintfW(pszLibFileW, L"%S", pszLibFile);

               // Call the Unicode version of the function to actually do the work.
               return(EjectLibW(dwProcessId, pszLibFileW));
            }


            ///////////////////////////////////////////////////////////////////////////////
                 上面這種方法注入的代碼它的優(yōu)點(diǎn)是開(kāi)發(fā)比較簡(jiǎn)單,我們只要用C++寫(xiě)一個(gè)DLL,然后調(diào)用InjectLibW(processID, dllName)就可以了,但是因?yàn)榇a是運(yùn)行在一個(gè)DLL里,別人可以通過(guò)一些枚舉模塊的工具看到我們的DLL,所以隱蔽性不是很好。

                  還有一種遠(yuǎn)程線程的實(shí)現(xiàn)方法是羅云彬Windows環(huán)境下32位匯編語(yǔ)言程序設(shè)計(jì)》里介紹的, 我們不通過(guò)DLL,而是直接把可執(zhí)行代碼拷貝到目標(biāo)進(jìn)程后運(yùn)行,所以它是真正的遠(yuǎn)程線程,通過(guò)這種方法,我們的代碼和目標(biāo)進(jìn)程已經(jīng)完全融為一體,其他人根本無(wú)法察覺(jué)。

                  用這種方法實(shí)現(xiàn), 它的要點(diǎn)是:

                  (1) Kernel32.DLL加載的基址在任何進(jìn)程里都是一樣的(其實(shí)上一種LoadLibrary方法也用到了這點(diǎn)), 所以
            GetProcAddress,GetModuleHandleA(W), LoadLibraryA(W)這些API的地址在任何進(jìn)程里都是一樣的, 所以我們?cè)谄渌M(jìn)程中用和本進(jìn)程相同的地址調(diào)用這些API。

                (2) 因?yàn)樯婕暗饺肿兞康闹囟ㄎ粏?wèn)題, 所以注入的代碼需要用匯編編寫(xiě), 并用以下匯編解決重定位問(wèn)題
            call @F
            @@:
            pop ebx
            sub ebx, offset @B

                 下面寫(xiě)了一個(gè)無(wú)DLL實(shí)現(xiàn)遠(yuǎn)程線程的測(cè)試代碼,他會(huì)在桌面Shell進(jìn)程(explorer.exe)里彈一個(gè)MessageBox,按照這個(gè)例子,我們已經(jīng)可以通過(guò)調(diào)用LoadLibraryA(W)和GetProcAddress來(lái)調(diào)用任何API了, 所以要實(shí)現(xiàn)一些復(fù)雜的功能也不是難事。

                  如果要避免用匯編來(lái)重定位,可以把全局變量都打包放在線程參數(shù)里,這樣單用C++就可以完全實(shí)現(xiàn)無(wú)DLL的遠(yuǎn)程線程了,當(dāng)然我們只能用Release版本(Debug版加了一些用到全局變量的調(diào)試信息, 堆棧檢測(cè)等)。

                 還有一個(gè)問(wèn)題是遠(yuǎn)程線程很難調(diào)試, 很多時(shí)候你在目標(biāo)進(jìn)程里注入代碼后可能就只會(huì)看到一個(gè)Crash的窗口,也不知道哪里代碼有問(wèn)題。如何才能單步調(diào)試呢? 我的方法是在CreateRemoteThread之前把線程的入口地址用MessageBox打印出來(lái),然后用Windbg  Attach到目標(biāo)進(jìn)程,在該地址上設(shè)置斷點(diǎn),這樣繼續(xù)運(yùn)行就可以用Windbg單步調(diào)試了(當(dāng)然只能以匯編的形式)。

            遠(yuǎn)程線程測(cè)試代碼下載(Asm): RemoteThreadTest
            遠(yuǎn)程線程測(cè)試代碼下載(C++): RemoteThreadTest_New
            posted on 2012-06-20 15:38 Richard Wei 閱讀(4015) 評(píng)論(5)  編輯 收藏 引用 所屬分類: windows desktop

            FeedBack:
            # re: 遠(yuǎn)程線程入門(mén)
            2012-06-20 21:06 | 飯中淹
            注入代碼其實(shí)無(wú)所謂用什么寫(xiě),線程有個(gè)LPVOID的參數(shù),把需要的數(shù)據(jù)全部事先寫(xiě)入遠(yuǎn)程進(jìn)程,然后把數(shù)據(jù)地址作為參數(shù)傳給遠(yuǎn)程線程就可以了。這樣無(wú)需訪問(wèn)全局變量。  回復(fù)  更多評(píng)論
              
            # re: 遠(yuǎn)程線程入門(mén)
            2012-06-20 21:30 | Richard Wei
            @飯中淹
            是的,我們可以先在目標(biāo)進(jìn)程中把需要的數(shù)據(jù)分配好,然后通過(guò)線程參數(shù)把地址傳進(jìn)去,這樣可以避免全局變量。
            關(guān)于代碼注入,這篇文章不錯(cuò):http://www.vckbase.com/index.php/wv/1580  回復(fù)  更多評(píng)論
              
            # re: 遠(yuǎn)程線程入門(mén)
            2012-06-20 23:53 | Richard Wei
            @飯中淹
            不依賴匯編重定位的代碼注入也做了下嘗試,發(fā)現(xiàn)挺好用的,測(cè)試代代碼也放上去了,單純用C++就可以了,就是注入代碼大小不太好算。  回復(fù)  更多評(píng)論
              
            # re: 遠(yuǎn)程線程入門(mén)
            2013-10-20 12:53 | flighta
            Dear,

            我碰到一種情況,需要將系統(tǒng)正在調(diào)用的dll文件,替換成新的dll文件. 它問(wèn)題的起因是我們?cè)谧鱿到y(tǒng)開(kāi)發(fā)時(shí),我是負(fù)責(zé)其中的一個(gè)dll文件,開(kāi)發(fā)需要不斷調(diào)試.但是每次打開(kāi)整個(gè)軟件需要比較長(zhǎng)的時(shí)間.我是想能否直接在軟件中將這個(gè)dll熱替換,避免重起開(kāi)啟整個(gè)軟件. (新舊兩個(gè)dll的接口完全相同)

            Best regards,
            Flighta  回復(fù)  更多評(píng)論
              
            # re: 遠(yuǎn)程線程入門(mén)
            2013-10-24 19:45 | Richard Wei
            @flighta
            如果別人已經(jīng)保存了你這個(gè)DLL的HINSTANCE,你想熱替換它,這個(gè)恐怕不好弄, 只能讓別人Free后再Load。  回復(fù)  更多評(píng)論
              
            久久综合给合久久国产免费| 草草久久久无码国产专区| 三级三级久久三级久久| 精品久久久无码人妻中文字幕| 亚洲AV成人无码久久精品老人| 久久免费国产精品一区二区| 久久精品二区| 久久99精品久久久久久hb无码| 久久国产精品一区| 嫩草伊人久久精品少妇AV| 久久久久亚洲AV无码去区首| 久久天堂AV综合合色蜜桃网 | 99久久精品国内| 成人久久精品一区二区三区| 色综合合久久天天给综看| 国产三级久久久精品麻豆三级| 久久久黄色大片| 国产精品九九久久免费视频 | 精品伊人久久大线蕉色首页| 一本一道久久精品综合| 久久精品黄AA片一区二区三区| 无码8090精品久久一区| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久这里的只有是精品23| 91精品无码久久久久久五月天| 成人综合伊人五月婷久久| 欧美激情精品久久久久久| 国产99久久九九精品无码| 久久涩综合| 久久精品国产精品亚洲下载| 久久这里只精品国产99热| 久久美女网站免费| 91久久成人免费| 久久精品国产精品亚洲艾草网美妙| 国产亚洲精品美女久久久| 久久久久亚洲AV无码专区体验| 亚洲精品tv久久久久久久久| 亚洲午夜久久久影院| 熟妇人妻久久中文字幕| 人妻无码精品久久亚瑟影视| 亚洲愉拍99热成人精品热久久|