• <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),開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            2008-05-31 12:48
            這是我在http://www.codeproject.com .學(xué)習(xí)時看到的一個驅(qū)動程序,學(xué)習(xí)后對其整理的筆記

            下面這個驅(qū)動程序的作用:監(jiān)控準(zhǔn)備運(yùn)行的可執(zhí)行文件。(由用戶決定是不是讓它運(yùn)行)所以我們要做以下工作:

            首先是修改(NtCreateSection)SSDT索引號,(索引號從用戶程序中得到)HOOK NtCreateSection()這個函數(shù),然后通過文件句柄獲得文件名,判斷它是不是可執(zhí)行文件,檢測其屬性與判斷用戶是否允許它執(zhí)行,如果允許就運(yùn)行原來NtCreateSection這個函數(shù),否則返回STATUS_ACCESS_DENIED。

            如果我們截獲一個NtCreateSection()的請求,該請求要求映射可執(zhí)行文件作為SEC_IMAGE屬性,通過結(jié)合頁保護(hù)屬性,我們能夠知道進(jìn)程將要執(zhí)行了,因此我們在這個時候作出決定:是否讓其執(zhí)行。如果不想讓它執(zhí)行,EAX 返回值為STATUS_ACCESS_DENIED。

            因?yàn)檎{(diào)用是從ntdll. dll 以一條 MOV EAX, ServiceIndex五字節(jié)指令開始的,第一個字節(jié)是MOV EAX,后四字節(jié)是索引號,所以我們可以得到索引號(后四字節(jié))然后將它進(jìn)行修改成我們自己的函數(shù)索引。當(dāng)然在修改之前要將原服務(wù)函數(shù)地址保存在全局變量中。


            if(loc->Parameters.DeviceIoControl.IoControlCode==1000)
            {
            buff=(UCHAR*)Irp->AssociatedIrp.SystemBuffer;

            // hook service dispatch table
            memmove(&Index,buff,4);//所有的調(diào)用都是從ntdll.dll以一條五字節(jié)指令MOV EAX, ServiceIndex開始,四字節(jié)是索引號
            a=4*Index+(ULONG)KeServiceDescriptorTable->ServiceTable;//從用戶程序中得到索引號,a指向服務(wù)函數(shù)地址

            base=(ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a),4,0);//將物理地址映射到非分頁池,因此可以進(jìn)行讀寫,減少讀寫服務(wù)表保護(hù)屬性的麻煩
            a=(ULONG)&Proxy;//a指向Proxy函數(shù)的地址

            _asm
            {
            mov eax,base

            mov ebx,dword ptr[eax]

            mov RealCallee,ebx//將原服務(wù)函數(shù)地址保存在全局變量中
            mov ebx,a

            mov dword ptr[eax],ebx//Proxy函數(shù)地址寫進(jìn)服務(wù)函數(shù)表中
            }

            memmove(&a,&buff[4],4);
            output=(char*)MmMapIoSpace(MmGetPhysicalAddress((void*)a),256,0);
            }


            下面是我們自己函數(shù)的實(shí)現(xiàn):
            //這個函數(shù)決定是否 NtCreateSection() 被成功調(diào)用
            ULONG __stdcall check(PULONG arg)//獲得指向服務(wù)參數(shù)指針
            {

            ?? HANDLE hand=0;PFILE_OBJECT file=0;

            ?? POBJECT_HANDLE_INFORMATION info=0;ULONG a;char*buff;
            ?? ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;

            if((arg[4]&0xf0)==0)return 1;//檢測標(biāo)志
            if((arg[5]&0x01000000)==0)return 1;//檢測屬性


            //通過文件句柄獲得文件名
            hand=(HANDLE)arg[6];//獲得執(zhí)行文件句柄

            ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,info);//&file獲得對象體指針
            if(!file)return 1;

            RtlUnicodeStringToAnsiString(&str,&file->FileName,1);

            a=str.Length;buff=str.Buffer;

            while(1)//通過循環(huán)判斷是不是有". "標(biāo)志
            {
            ??
            if(buff[a]=='.')
            {a++;break;}

            ?? a--;

            }
            ObDereferenceObject(file);


            if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}//判斷是否為可執(zhí)行文件



            KeWaitForSingleObject(&event,Executive,KernelMode,0,0);//將當(dāng)前線程置于等待狀態(tài)知道信號態(tài)


            strcpy(&output[8],buff);//將string復(fù)制進(jìn)buff
            RtlFreeAnsiString(&str);

            a=1;//用戶的決定通過a的制來反映
            memmove(&output[0],&a,4);
            while(1)
            {
            KeDelayExecutionThread(KernelMode,0,&li);//在一個固定時間間隔內(nèi)當(dāng)前線程處于等待狀態(tài)
            memmove(&a,&output[0],4);
            if(!a)break;
            }
            memmove(&a,&output[4],4);

            KeSetEvent(&event,0,0);

            return a;
            }



            //保存執(zhí)行文件上下文,調(diào)用check()函數(shù)
            _declspec(naked) Proxy()
            {

            _asm{

            pushfd
            pushad
            mov ebx,esp

            add ebx,40
            push ebx

            call check

            cmp eax,1//由check()的返回值判斷是否讓可執(zhí)行文件繼續(xù)執(zhí)行
            jne block


            popad
            popfd
            jmp RealCallee//通過,調(diào)用ntcreatesection


            block:popad
            mov ebx, dword ptr[esp+8]

            mov dword ptr[ebx],0
            mov eax,0xC0000022L//不讓其通過,返回STATUS_ACCESS_DENIED
            popfd
            ret 32

            }
            }

            到此,驅(qū)動程序的工作基本完成,所以在用戶程序中用到一個線程來等待驅(qū)動的判斷結(jié)果。
            char*name=(char*)&outputbuff[8];

            ???????? for(x=0;x<stringcount;x++)

            ???????? {
            ???????????? if(!stricmp(name,strings[x])){a=1;goto skip;}

            ???????? }
            ???????? strcpy(msgbuff, "Do you want to run ");
            ???????? strcat(msgbuff,&outputbuff[8]);

            ????????
            ???????? if(IDYES==MessageBox(0, msgbuff,"WARNING",
            ??????????? MB_YESNO|MB_ICONQUESTION|0x00200000L))

            ???????? {a=1; strings[stringcount]=_strdup(name);stringcount++;}
            ???????? else a=0;
            ????
            ???????? // write response to the buffer, and driver will get it
            ???????? skip:memmove(&outputbuff[4],&a,4);

            ???????? //讓驅(qū)動繼續(xù)
            ???????? a=0;
            ???????? memmove(&outputbuff[0],&a,4);
            亚洲国产精品成人久久蜜臀| 久久精品国产WWW456C0M| 精品久久久久久无码人妻热| 九九精品99久久久香蕉| 新狼窝色AV性久久久久久| 久久婷婷午色综合夜啪| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 久久天天躁狠狠躁夜夜躁2O2O| 亚洲精品97久久中文字幕无码| 狠狠色伊人久久精品综合网| 99久久精品久久久久久清纯| 超级碰久久免费公开视频| 大美女久久久久久j久久| 品成人欧美大片久久国产欧美| 久久AAAA片一区二区| 久久国产热这里只有精品| 欧美午夜A∨大片久久 | 久久久久久综合一区中文字幕| 国内精品久久国产大陆| 伊人色综合久久| 久久99精品国产麻豆蜜芽| 久久久久亚洲AV无码去区首| 天天做夜夜做久久做狠狠| 久久久久久久久久久精品尤物| 亚洲乱码精品久久久久..| 久久96国产精品久久久| 久久成人18免费网站| 久久亚洲精品无码aⅴ大香| 久久精品aⅴ无码中文字字幕不卡| 99久久无码一区人妻a黑| 国产精品一区二区久久精品无码 | 亚洲av成人无码久久精品| 久久99中文字幕久久| 无码人妻少妇久久中文字幕| 无码人妻久久一区二区三区免费丨| 久久久综合九色合综国产| 日本精品久久久久影院日本 | 国产精品嫩草影院久久| 久久精品人妻中文系列| 91精品免费久久久久久久久| 色青青草原桃花久久综合|