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

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開(kāi)心的工作
            簡(jiǎn)單、開(kāi)放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            ? 收藏的一些書 [轉(zhuǎn)載]從源碼看下載者生成器 ?

            [轉(zhuǎn)載]利用鉤子技術(shù)控制進(jìn)程創(chuàng)建

            信息來(lái)源:新浪網(wǎng)

            一、 簡(jiǎn)介

              最近,我了解到一個(gè)叫做Sanctuary的相當(dāng)有趣的安全產(chǎn)品。它能夠阻止任何程序的運(yùn)行-這些程序沒(méi)有顯示在軟件列表中-該表中的程序被允許在一個(gè)特定的機(jī)器上運(yùn)行。結(jié)果,PC用戶得到保護(hù)而免于各種插件間諜軟件、蠕蟲和特洛伊木馬的侵襲-就算能夠進(jìn)入他/她的計(jì)算機(jī),它們也沒(méi)有機(jī)會(huì)執(zhí)行,并因此沒(méi)有機(jī)會(huì)對(duì)該機(jī)器造成任何損害。當(dāng)然,我覺(jué)得這個(gè)特征相當(dāng)有趣;并且,在稍作思考以后,我就有了一個(gè)自己的實(shí)現(xiàn)。因此,本文將描述如何通過(guò)鉤住本機(jī)API的方式來(lái)實(shí)現(xiàn)監(jiān)控一個(gè)進(jìn)程的創(chuàng)建并在系統(tǒng)級(jí)上對(duì)之進(jìn)行控制。

              本文大膽假設(shè),目標(biāo)進(jìn)程是以一種用戶模式(外殼函數(shù),CreateProcess(),用一系列的本機(jī)API調(diào)用的手工的進(jìn)程創(chuàng)建,等等)創(chuàng)建的。盡管從理論上,一個(gè)進(jìn)程能夠以內(nèi)核方式啟動(dòng);不過(guò)從實(shí)際來(lái)看,如此的可能性是可以忽略不計(jì)的,因此我們不必為此擔(dān)心。為什么?請(qǐng)邏輯地思考一下-為了以內(nèi)核方式啟動(dòng)一個(gè)進(jìn)程,用戶必須裝載一個(gè)驅(qū)動(dòng)程序,該驅(qū)動(dòng)程序反過(guò)來(lái)首先要暗示某種用戶模式代碼的執(zhí)行。因此,為了防止未被授權(quán)程序的執(zhí)行,我們可以安全地在系統(tǒng)級(jí)上以用戶模式限制我們自己控制的進(jìn)程的創(chuàng)建。

              二、 定義策略

              首先讓我們明確,之所以這樣做的目的是為了在系統(tǒng)級(jí)上監(jiān)視和控制進(jìn)程創(chuàng)建。

              進(jìn)程創(chuàng)建是一件相當(dāng)復(fù)雜的事情-它包含相當(dāng)多的工作(如果你不相信我,可以反匯編CreateProcess(),這樣你就會(huì)親眼看到這點(diǎn))。為了啟動(dòng)一個(gè)進(jìn)程,可以使用下列步驟:

              1.可執(zhí)行文件必須被以FILE_EXECUTE存取方式打開(kāi)。

              2.可執(zhí)行映像必須被裝載進(jìn)RAM。

              3.必須建立進(jìn)程執(zhí)行對(duì)象(EPROCESS,KPROCESS和PEB結(jié)構(gòu))。

              4.必須為新建進(jìn)程分配地址空間。

              5.必須建立進(jìn)程的主線程的線程執(zhí)行對(duì)象(ETHREAD,KTHREAD和TEBstructures)。

              6.必須為主線程分配堆棧。

              7.必須建立進(jìn)程的主線程的執(zhí)行上下文。

              8.必須通知Win32子系統(tǒng)有關(guān)該新進(jìn)程的創(chuàng)建情況。

              為確保這些步驟中的任何一步的成功,所有其前面的步驟必須是成功執(zhí)行的(你不能夠在沒(méi)有一個(gè)可執(zhí)行區(qū)句柄的情況下建立一個(gè)可執(zhí)行進(jìn)程對(duì)象;沒(méi)有文件句柄的情況下你無(wú)法映射一個(gè)可執(zhí)行區(qū),等等)。因此,如果我們決定退出任何這些步驟,所有后面的步驟也會(huì)失敗,以至于整個(gè)進(jìn)程創(chuàng)建會(huì)失敗。上面所有的步驟都可以通過(guò)調(diào)用某些本機(jī)API函數(shù)的方式來(lái)實(shí)現(xiàn),這是可以理解的。因此,為了監(jiān)視和控制進(jìn)程創(chuàng)建,我們所有要做的就是鉤住這些API函數(shù)-它們無(wú)法旁路掉要?jiǎng)?chuàng)建一新進(jìn)程所要執(zhí)行的代碼。

              我們應(yīng)該鉤住哪些本機(jī)API函數(shù)呢?盡管NtCreateProcess()似乎是問(wèn)題的最顯然的答案,但是,這個(gè)答案是錯(cuò)誤的-有可能不需要調(diào)用這個(gè)函數(shù)也可以創(chuàng)建一個(gè)新的進(jìn)程。例如,CreateProcess()可以創(chuàng)建與進(jìn)程相關(guān)的內(nèi)核模式結(jié)構(gòu)而不是調(diào)用NtCreateProcess()。因此,這樣以來(lái)鉤住NtCreateProcess()對(duì)我們毫無(wú)幫助。

              為了監(jiān)視進(jìn)程的創(chuàng)建,我們必須或者鉤住NtCreateFile()和NtOpenFile(),或者鉤住NtCreateSection()-不經(jīng)調(diào)用這些API是絕對(duì)無(wú)法運(yùn)行任何可執(zhí)行文件的。如果我們決定監(jiān)視對(duì)NtCreateFile()和NtOpenFile()的調(diào)用,那么我們必須區(qū)別開(kāi)進(jìn)程創(chuàng)建和常規(guī)的文件IO操作。這項(xiàng)任務(wù)并不總是那么容易。例如,如果一些可執(zhí)行文件正在被以FILE_ALL_ACCESS存取方式打開(kāi),我們?cè)撛趺崔k?這僅是一個(gè)IO操作還是一個(gè)進(jìn)程創(chuàng)建的一部分?在這點(diǎn)上,是很難判斷的-我們需要了解調(diào)用線程下一步要干什么。因此,鉤住NtCreateFile()和NtOpenFile()不是最好的可能性選擇。

              鉤住NtCreateSection()是更為合理的-如果我們想攔截對(duì)NtCreateSection()的調(diào)用,發(fā)出的請(qǐng)求是作為一個(gè)映像(SEC_IMAGE屬性)映射可執(zhí)行文件(SEC_IMAGE屬性),同時(shí)請(qǐng)求允許執(zhí)行的頁(yè)面保護(hù);那么,我們可以確信該進(jìn)程將要被啟動(dòng)。在這一點(diǎn)上,我們是能夠作出決定的,并且在我們不想要?jiǎng)?chuàng)建該進(jìn)程的情況下,讓NtCreateSection()返回STATUS_ACCESS_DENIED。因此,為了完全控制目標(biāo)機(jī)器上的進(jìn)程創(chuàng)建,所有我們要做的是在系統(tǒng)級(jí)上鉤住NtCreateSection()。

              象來(lái)自于ntdll.dll中的任何其它代理一樣,NtCreateSection()用服務(wù)索引加載EAX,使EDX指向函數(shù)參數(shù),并且把執(zhí)行權(quán)傳遞到KiDispatchService()內(nèi)核模式例程(這是通過(guò)Windows NT/2000中的INT 0x2E指令或者Windows XP下的SYSENTER指令實(shí)現(xiàn)的)。在校驗(yàn)完函數(shù)參數(shù)之后,KiDispatchService()把執(zhí)行權(quán)傳遞到服務(wù)的實(shí)際實(shí)現(xiàn)部分-它的地址可用于服務(wù)描述表(指向這個(gè)表的指針由ntoskrnl.exe作為KeServiceDescriptorTable變量所輸出,所以它對(duì)于內(nèi)核模式驅(qū)動(dòng)程序是可用的)中。服務(wù)描述表通過(guò)下列結(jié)構(gòu)所描述:
            Copy code

              struct SYS_SERVICE_TABLE {

              void **ServiceTable;

              unsigned long CounterTable;

              unsigned long ServiceLimit;

              void **ArgumentsTable;

              };

              這個(gè)結(jié)構(gòu)中的ServiceTable字段指向一個(gè)數(shù)組-它擁有所有實(shí)現(xiàn)系統(tǒng)服務(wù)的函數(shù)的地址。因此,為了在系統(tǒng)級(jí)上鉤住任何本機(jī)API函數(shù),所有我們必須做的是把我們的代理函數(shù)的地址寫入被KeServiceDescriptorTable的ServiceTable字段所指向的數(shù)組的第i個(gè)入口(i是服務(wù)索引)。

              至此,看起來(lái)我們已了解了在系統(tǒng)級(jí)上監(jiān)視和控制進(jìn)程創(chuàng)建的一切。現(xiàn)在讓我們開(kāi)始實(shí)際的工作。


            ? 三、 控制進(jìn)程創(chuàng)建

              我們的解決方案由一個(gè)內(nèi)核模式驅(qū)動(dòng)程序和一個(gè)用戶模式應(yīng)用程序組成。為了開(kāi)始監(jiān)視進(jìn)程創(chuàng)建,我們的應(yīng)用程序要把服務(wù)索引(相應(yīng)于NtCreateSection())以及交換緩沖區(qū)的地址傳遞到我們的驅(qū)動(dòng)程序。這是由下列代碼所完成的:
            Copy code

            //打開(kāi)設(shè)備
            device=CreateFile("\\.\PROTECTOR",GENERIC_READ|GENERIC_WRITE,
            0,0,OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0);
            //得到NtCreateSection的索引并把它連同輸出緩沖區(qū)的地址傳遞給設(shè)備
            DWORD * addr=(DWORD *)
            (1+(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtCreateSection"));
            ZeroMemory(outputbuff,256);
            controlbuff[0]=addr[0];
            controlbuff[1]=(DWORD)&outputbuff[0];
            DeviceIoControl(device,1000,controlbuff,256,controlbuff,256,&dw,0);


              此代碼是顯然的-唯一需要注意的是我們得到服務(wù)索引的方式。所有來(lái)自于ntdll.dll的代理都從一行代碼MOV EAX,ServiceIndex開(kāi)始-它可以適用于任何版本和風(fēng)味的Windows NT。這是一條5字節(jié)長(zhǎng)的指令,以MOV EAX操作碼作第一字節(jié),服務(wù)索引作為留下的4字節(jié)。因此,為了得到相應(yīng)于一些特別的本機(jī)API函數(shù)的服務(wù)索引,所有你要做的是從該地址讀取4個(gè)字節(jié),-位于從這個(gè)代理開(kāi)始1字節(jié)距離的地方。

              現(xiàn)在讓我們看一下我們的驅(qū)動(dòng)程序做什么,當(dāng)它收到來(lái)自我們的應(yīng)用程序的IOCTL時(shí):

            Copy code

            NTSTATUS DrvDispatch(IN PDEVICE_OBJECT device,IN PIRP Irp)
            {
             UCHAR*buff=0; ULONG a,base;
             PIO_STACK_LOCATION loc=IoGetCurrentIrpStackLocation(Irp);
             if(loc->Parameters.DeviceIoControl.IoControlCode==1000)
             {
              buff=(UCHAR*)Irp->AssociatedIrp.SystemBuffer;
              //鉤住服務(wù)調(diào)度表
              memmove(&Index,buff,4);
              a=4*Index+(ULONG)KeServiceDescriptorTable->ServiceTable;
              base=(ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a),4,0);
              a=(ULONG)&Proxy;
              _asm
              {
               mov eax,base
               mov ebx,dword ptr[eax]
               mov RealCallee,ebx
               mov ebx,a
               mov dword ptr[eax],ebx
              }
              MmUnmapIoSpace(base,4);
              memmove(&a,&buff[4],4);
              output=(char*)MmMapIoSpace(MmGetPhysicalAddress((void*)a),256,0);
             }
             Irp->IoStatus.Status=0;
             IoCompleteRequest(Irp,IO_NO_INCREMENT);
             return 0;
            }



              正如你所見(jiàn),這里沒(méi)有什么特別的-我們只是通過(guò)MmMapIoSpace()來(lái)把交換緩沖區(qū)映射到內(nèi)核中,另外把我們的代理函數(shù)的地址寫到服務(wù)表(當(dāng)然,我們這是在把實(shí)際的服務(wù)執(zhí)行的地址保存到全局變量RealCallee以后這樣做的)。為了改寫服務(wù)表的適當(dāng)入口,我們通過(guò)MmMapIoSpace()來(lái)映射目標(biāo)地址。為什么我們要這樣做?不管怎么說(shuō),我們已經(jīng)可以存取服務(wù)表了,不是嗎?問(wèn)題是,服務(wù)表可能駐留在一段只讀內(nèi)存中。因此,我們必須檢查一下是否我們有對(duì)目標(biāo)空間寫的權(quán)限,而如果我們沒(méi)有這個(gè)權(quán)限,那么在改寫服務(wù)表之前,我們必須改變頁(yè)面保護(hù)。你不認(rèn)為這樣以來(lái)工作太多了嗎?因此,我們僅用MmMapIoSpace()來(lái)映射我們的目標(biāo)地址,這樣以來(lái),我們就不必?fù)?dān)心任何的頁(yè)面保護(hù)問(wèn)題了-從現(xiàn)在開(kāi)始,我們假定已有到目標(biāo)頁(yè)面寫的權(quán)限了。現(xiàn)在讓我們看一下我們的代理函數(shù):

            Copy code

            //這個(gè)函數(shù)用來(lái)確定是否我們應(yīng)該允許NtCreateSection()調(diào)用成功
            ULONG __stdcall check(PULONG arg)
            {
             HANDLE hand=0;PFILE_OBJECT file=0;
             POBJECT_HANDLE_INFORMATION info;ULONG a;char*buff;
             ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;
             //檢查標(biāo)志。如果所要求的存取方式不是PAGE_EXECUTE,
             //這并不要緊
             if((arg[4]&0xf0)==0)return 1;
             if((arg[5]&0x01000000)==0)return 1;
             //經(jīng)由文件句柄得到文件名
             hand=(HANDLE)arg[6];
             ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,&info);
             if(!file)return 1;
              RtlUnicodeStringToAnsiString(&str,&file->FileName,1);
              a=str.Length;buff=str.Buffer;
              while(1)
              {
               if(buff[a]=='.'){a++;break;}
               a--;
              }
              ObDereferenceObject(file);
              //如果它是不可執(zhí)行的,這也不要緊
              //返回1
              if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}
               //現(xiàn)在,我們要詢問(wèn)用戶的選擇。
               //把文件名寫入緩沖區(qū),并等待直到用戶顯示響應(yīng)
               //(第一個(gè)DWORD為1意味著我們可以繼續(xù))
               //同步存取該緩沖區(qū)
               KeWaitForSingleObject(&event,Executive,KernelMode,0,0);
               //把緩沖區(qū)的前兩個(gè)DWORD置為0,
               //把字符串復(fù)制到該緩沖區(qū)中,并循環(huán)下去,直到用戶把每一個(gè)
               //DWORD置為1.
               //第二個(gè)DWORD的值指明用戶的響應(yīng)
              strcpy(&output[8],buff);
              RtlFreeAnsiString(&str);
              a=1;
              memmove(&output[0],&a,4);
              while(1)
              {
               KeDelayExecutionThread(KernelMode,0,&li);
               memmove(&a,&output[0],4);
               if(!a)break;
              }
              memmove(&a,&output[4],4);
              KeSetEvent(&event,0,0);
              return a;
             }
             //僅保存執(zhí)行上下文并調(diào)用check()
             _declspec(naked) Proxy()
             {
              _asm{
               //保存執(zhí)行上下文并調(diào)用check()
               //-后面的依賴于check()所返回的值
               // 如果返回值是1,繼續(xù)實(shí)際的調(diào)用。
               //否則,返回STATUS_ACCESS_DENIED
               pushfd
               pushad
               mov ebx,esp
               add ebx,40
               push ebx
               call check
               cmp eax,1
               jne block
               //繼續(xù)實(shí)際的調(diào)用
               popad
               popfd
               jmp RealCallee
               //返回STATUS_ACCESS_DENIED
               block:popad
               mov ebx, dword ptr[esp+8]
               mov dword ptr[ebx],0
               mov eax,0xC0000022L
               popfd
               ret 32
              }
             }



              Proxy()保存寄存器和標(biāo)志,把一個(gè)指向服務(wù)參數(shù)的指針壓入棧中并調(diào)用check()。其它的依賴于check()所返回的值。如果check()返回TRUE(也就是,我們想要繼續(xù)請(qǐng)求),那么,Proxy()將恢復(fù)寄存器和標(biāo)志,并且把控制權(quán)交給服務(wù)實(shí)現(xiàn)部分。否則,Proxy()將把STATUS_ACCESS_DENIED寫入EAX,恢復(fù)ESP并返回-從調(diào)用者的觀點(diǎn)來(lái)看,這就象對(duì)NtCreateSection()的調(diào)用失敗一樣-以錯(cuò)誤狀態(tài)STATUS_ACCESS_DENIED返回。


            ? check()函數(shù)是怎樣做出決定的?一旦它收到一個(gè)指向服務(wù)參數(shù)的指針參數(shù),它就可以檢查這些參數(shù)。首先,它檢查標(biāo)志和屬性-如果有一部分沒(méi)有被要求作為一個(gè)可執(zhí)行映像映射,或如果要求的頁(yè)面保護(hù)不允許執(zhí)行,那么我們可以確定NtCreateSection()調(diào)用與進(jìn)程創(chuàng)建毫無(wú)關(guān)系。在這種情況下,check()直接返回TRUE。否則,它將檢查該潛在文件的擴(kuò)展-畢竟,SEC_IMAGE屬性和允許執(zhí)行的頁(yè)面保護(hù)可能被要求來(lái)映射某個(gè)DLL文件。如果該潛在文件不是一個(gè).exe文件,那么,check()將返回TRUE。否則,它給用戶模式代碼一個(gè)作出決定的機(jī)會(huì)。因此,它僅把文件名和路徑寫到交換緩沖區(qū),并且對(duì)它循環(huán)查詢,直到它得到響應(yīng)為止。

              在打開(kāi)我們的驅(qū)動(dòng)程序前,我們的應(yīng)用程序創(chuàng)建一個(gè)運(yùn)行下面函數(shù)的線程:

            Copy code

            void thread()
            {
             DWORD a,x; char msgbuff[512];
             while(1)
             {
              memmove(&a,&outputbuff[0],4);
              //如果什么也沒(méi)有,Sleep() 10毫秒并再檢查
              if(!a){Sleep(10);continue;}
              //看起來(lái)象我們的權(quán)限被詢問(wèn)。
              //如果被懷疑的文件已經(jīng)存在于空白列表中,
              // 則給出一個(gè)積極的響應(yīng)。
              char*name=(char*)&outputbuff[8];
              for(x=0;x<stringcount;x++)
              {
               if(!stricmp(name,strings[x])){a=1;goto skip;}
              }
              //要求用戶允許運(yùn)行該程序
              strcpy(msgbuff, "Do you want to run ");
              strcat(msgbuff,&outputbuff[8]);
              //如果用戶的答復(fù)是積極的,那么把這個(gè)程序添加到空白列表中
              if(IDYES==MessageBox(0, msgbuff,"WARNING",MB_YESNO|MB_ICONQUESTION|0x00200000L))
               {a=1; strings[stringcount]=_strdup(name);stringcount++;}
              else a=0;
              // 把響應(yīng)寫入緩沖區(qū)中,而由驅(qū)動(dòng)程序之后取回它
              skip:memmove(&outputbuff[4],&a,4);
              //告訴驅(qū)動(dòng)程序繼續(xù)
              a=0;
              memmove(&outputbuff[0],&a,4);
             }
            }


              這段代碼是顯然的-我們的線程每10毫秒查詢交換緩沖區(qū)。如果它發(fā)現(xiàn)我們的驅(qū)動(dòng)程序已經(jīng)把它的請(qǐng)求寄到了該緩沖區(qū)中,它就檢查被允許在本機(jī)上運(yùn)行的程序列表中的文件的文件名和路徑。如果發(fā)現(xiàn)匹配,它直接給出一個(gè)OK響應(yīng)。否則,它顯示一個(gè)消息窗口,詢問(wèn)用戶是否允許有問(wèn)題的程序執(zhí)行。如果響應(yīng)是積極的,我們就把有問(wèn)題的程序添加到允許在本機(jī)上運(yùn)行的軟件列表中。最后,我們把用戶響應(yīng)寫入緩沖區(qū),也就是說(shuō),把它傳遞到我們的驅(qū)動(dòng)程序。因此,該用戶就能完全控制它的PC上的進(jìn)程的創(chuàng)建-只要我們的程序運(yùn)行,在沒(méi)有用戶所給予權(quán)限的情況下,絕對(duì)沒(méi)有辦法來(lái)啟動(dòng)該P(yáng)C上的任何進(jìn)程。

              正如你所見(jiàn),我們讓內(nèi)核方式代碼等待用戶反應(yīng)。這是否是一種聰明的舉措呢?為了回答這個(gè)問(wèn)題,你必須問(wèn)你自己你是否正在堵住任何關(guān)鍵的系統(tǒng)資源-一切都依賴于具體的情況。在我們的情況下,一切發(fā)生在IRQLPASSIVE_LEVEL級(jí)上,并沒(méi)有包含對(duì)IRPs的處理,并且必須等待用戶響應(yīng)的線程并不十分重要。因此,在我們的情況下,一切工作正常。然而,本例僅為演示之目的而編寫。為了實(shí)際地使用它,以一個(gè)自動(dòng)啟動(dòng)的服務(wù)的方式來(lái)重寫我們的應(yīng)用程序是很重要的。在這種情況下,我建議我們解除LocalSystem帳戶,并且,在NtCreateSection()被用LocalSystem帳戶特權(quán)在一個(gè)線程的上下文中調(diào)用的情況下,可以繼續(xù)實(shí)際的服務(wù)實(shí)現(xiàn)而不施行任何檢查-不管怎么說(shuō),LocalSystem帳戶僅運(yùn)行那些在注冊(cè)表中指定的可執(zhí)行程序。因此,這樣的一種解除不會(huì)是與我們的安全相妥協(xié)的。

              四、 結(jié)論

              最后,我必須指出,鉤住本機(jī)API很明顯是現(xiàn)已存在的最強(qiáng)有力的編程技術(shù)之一。本文通過(guò)一個(gè)例子向你展示通過(guò)鉤住本機(jī)API可以實(shí)現(xiàn)的能力-正如你所見(jiàn),我們已設(shè)法防止未被授權(quán)的程序的執(zhí)行-這可以通過(guò)鉤住單一的本機(jī)API函數(shù)來(lái)實(shí)現(xiàn)。你可以進(jìn)一步擴(kuò)展這個(gè)方法,并且獲得對(duì)硬件設(shè)備、文件IO操作、網(wǎng)絡(luò)流量等等的完全控制。然而,我們現(xiàn)在的解決方案并不是準(zhǔn)備為內(nèi)核模式API調(diào)用者所用-一旦內(nèi)核模式代碼被允許直接調(diào)用ntoskrnl.exe的輸出,則這些調(diào)用就不需要經(jīng)由系統(tǒng)服務(wù)發(fā)送者進(jìn)行了。

              本文源碼在運(yùn)行Windows XP SP2的若干機(jī)器上成功地測(cè)試過(guò)。盡管我還沒(méi)在任何另外的環(huán)境下面測(cè)試它,我相信它應(yīng)該到處工作正常-不管怎么說(shuō),它從未使用任何系統(tǒng)特定的結(jié)構(gòu)。為了運(yùn)行這個(gè)示例,所有你要做的是放置protector.exe和protector.sys到相同的目錄下,并且運(yùn)行protector.exe。直到protector.exe的應(yīng)用程序窗口被關(guān)閉為止;否則,每次你都會(huì)被提示你試圖運(yùn)行任何可執(zhí)行程序。
            午夜不卡久久精品无码免费| 国产精品免费久久| 久久久久久久久久免免费精品 | 国产成人无码精品久久久久免费| 99久久免费国产精品特黄| 欧美日韩中文字幕久久伊人| 五月丁香综合激情六月久久| 性高朝久久久久久久久久| 久久久久久狠狠丁香| a高清免费毛片久久| 亚洲中文字幕无码久久综合网| 久久精品这里只有精99品| 免费精品99久久国产综合精品| 99久久精品国产一区二区| 亚洲精品久久久www| 久久久久99精品成人片| 亚洲精品国产成人99久久| 久久精品国产亚洲av日韩| 久久久久人妻一区二区三区 | 亚洲精品午夜国产va久久| 精品久久人人做人人爽综合| 老司机国内精品久久久久| 97久久国产亚洲精品超碰热| 日韩久久久久久中文人妻| 欧美精品九九99久久在观看| 亚洲日韩欧美一区久久久久我| 国内精品久久久久久不卡影院| 久久精品国产半推半就| 国产91色综合久久免费| 91精品国产综合久久精品| 久久99国产精品99久久| 久久电影网一区| 热久久这里只有精品| 亚洲国产成人久久综合一| 91精品日韩人妻无码久久不卡 | 久久人人爽人人爽人人AV东京热| 久久综合久久美利坚合众国| 亚洲国产一成人久久精品| 精品久久久久久亚洲精品| 成人久久久观看免费毛片| 色综合久久88色综合天天|