• <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.¢%

            像打了激速一樣,以四倍的速度運轉(zhuǎn),開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            注明:本文是轉(zhuǎn)帖。希望中國計算機技術(shù)越來越好。

            論技術(shù),我還差得遠,而且網(wǎng)上關(guān)于SSDT的文章也多不勝數(shù)。但是還是想自己寫一下,因為我想試試我能不能用最簡單的語言來描述SSDT——這個對一般來人來說比較神秘的屬于內(nèi)核的地帶。引用EVA說的一句話,“以為寫個驅(qū)動就是內(nèi)核,還遠著了”——大概是這么個意思,記得不是很清楚。

            關(guān)于SSDT,描述得最清楚的應(yīng)該算《SSDT Hook的妙用-對抗ring0 inline hook》一文了,作者是墮落天才。這里引用一下他寫的開頭部分,略有個別字符的修改:

            內(nèi)核中有兩個系統(tǒng)服務(wù)描述符表,一個是KeServiceDescriptorTable,由ntoskrnl.exe導(dǎo)出,一個是KeServieDescriptorTableShadow,沒有導(dǎo)出。這兩者都是一個結(jié)構(gòu)體,結(jié)構(gòu)下面會給出。他們的區(qū)別是,KeServiceDescriptorTable僅有 ntoskrnel一項,而KeServieDescriptorTableShadow則包含了ntoskrnel和win32k。一般的Native API的服務(wù)地址由KeServiceDescriptorTable分派,而gdi.dll和
            user.dll的內(nèi)核API調(diào)用服務(wù)地址,由 KeServieDescriptorTableShadow分派。還有要清楚一點的是win32k.sys只有在GUI線程中才加載,一般情況下是不加載的。

            他們的結(jié)構(gòu)如下:
            代碼:


            typedef struct _SYSTEM_SERVICE_TABLE
            {
            ???? PVOID ServiceTableBase;???? //這個指向系統(tǒng)服務(wù)函數(shù)地址表
            ???? PULONG ServiceCounterTableBase;
            ???? ULONG NumberOfService; ???? //服務(wù)函數(shù)的個數(shù),NumberOfService*4 就是整個地址表的大小
            ???? ULONG ParamTableBase;
            }SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;

            typedef struct _SERVICE_DESCRIPTOR_TABLE
            {
            ???? SYSTEM_SERVICE_TABLE ntoskrnel;???? //ntoskrnl.exe的服務(wù)函數(shù)
            ???? SYSTEM_SERVICE_TABLE win32k;???? //win32k.sys的服務(wù)函數(shù),(gdi.dll/user.dll的內(nèi)核支持)
            ???? SYSTEM_SERVICE_TABLE NotUsed1;
            ???? SYSTEM_SERVICE_TABLE NotUsed2;
            }SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE;


            當(dāng)系統(tǒng)需要使用一個本機API的時候,就會去查找SYSTEM_DESCRIPTOR_TABLE這個表,也就是由ntoskrnl.exe導(dǎo)出的KeServiceDescriptorTable:

            代碼:

            nt!RtlpBreakWithStatusInstruction:
            80527fc8 cc?????????????? int???? 3
            kd> dd KeServiceDescriptorTable
            80553380?? 805021fc 00000000 0000011c 80502670
            80553390?? 00000000 00000000 00000000 00000000
            805533a0?? 00000000 00000000 00000000 00000000
            805533b0?? 00000000 00000000 00000000 00000000
            805533c0?? 00002710 bf80c227 00000000 00000000
            805533d0?? f9e6da80 f963a9e0 816850f0 806e0f40
            805533e0?? 00000000 00000000 00000000 00000000
            805533f0?? 97c5ac40 01c7abf5 00000000 00000000

            可以看到,KeServiceDescriptorTable的地址是80553380?,F(xiàn)在看看這個地址保存的是什么,因為這個地址的值就是SYSTEM_SERVICE_TABLE的起始地址。好了,我們看到這個地址保存的是805021fc,那么也就是說,系統(tǒng)服務(wù)的地址表起始地址為805021fc了??纯催@個表是些什么鬼東西:
            代碼:

            kd> dd 805021fc
            805021fc?? 80599746 805e6914 805ea15a 805e6946
            8050220c?? 805ea194 805e697c 805ea1d8 805ea21c
            8050221c?? 8060b880 8060c5d2 805e1cac 805e1904
            8050222c?? 805ca928 805ca8d8 8060bea6 805ab334
            8050223c?? 8060b4be 8059dbbc 805a5786 805cc406
            8050224c?? 804ffed0 8060c5c4 8056be64 805353f2
            8050225c?? 80604b90 805b19c0 805ea694 80619a56
            8050226c?? 805eeb86 80599e34 80619caa 805996e6

            這個過程是這樣的,最開始是SYSTEM_DESCRIPTOR_TABLE(80553380)保存了SYSTEM_SERVICE_TABLE的地址(805021fc),SYSTEM_SERVICE_TABLE的地址(805021fc)又保存了很多地址,這個地址就是系統(tǒng)服務(wù)的地址了,類似NtOpenProcess這樣的ring0的函數(shù)地址。這樣,系統(tǒng)就可以方便的找到每一個ring0函數(shù)去調(diào)用。

            我們先看看第一個地址80599746是個什么函數(shù),反匯編一下:
            代碼:

            kd> u 80599746
            nt!NtAcceptConnectPort:
            80599746 689c000000?????? push???? 9Ch
            8059974b 6820a14d80?????? push???? offset nt!_real+0x128 (804da120)
            80599750 e8abebf9ff?????? call???? nt!_SEH_prolog (80538300)
            80599755 64a124010000???? mov???? eax,dword ptr fs:[00000124h]
            8059975b 8a8040010000???? mov???? al,byte ptr [eax+140h]
            80599761 884590?????????? mov???? byte ptr [ebp-70h],al
            80599764 84c0???????????? test???? al,al
            80599766 0f84b9010000???? je?????? nt!NtAcceptConnectPort+0x1df (80599925)

            原來是NtAcceptConnectPort函數(shù),第二個805e6914呢?我們也看一下,
            代碼:

            kd> u 805e6914
            nt!NtAccessCheck:
            805e6914 8bff???????????? mov???? edi,edi
            805e6916 55?????????????? push???? ebp
            805e6917 8bec???????????? mov???? ebp,esp
            805e6919 33c0???????????? xor???? eax,eax
            805e691b 50?????????????? push???? eax
            805e691c ff7524?????????? push???? dword ptr [ebp+24h]
            805e691f ff7520?????????? push???? dword ptr [ebp+20h]
            805e6922 ff751c?????????? push???? dword ptr [ebp+1Ch]

            原來是NtAccessCheck函數(shù)。

            這樣我們可以清楚的看到,在這個起始地址為0x805021fc的表中,保存了各個ring0函數(shù)的地址。下面我來做個簡單的比喻。

            從前有一個很大的幫派,名字叫做Windows,功能很多并且很強大。因為這些各方面的能力由各個專人負責(zé),他們一個人做一件事情。隨著人員增多,幫主發(fā)現(xiàn)聯(lián)系起來越來越困了。有一天幫主要找竟然NtOpenProcess來調(diào)查一下他的一個手下是不是別的幫派派來的間諜,但是他發(fā)現(xiàn)NtOpenProcess跑不見了。

            于是軍師就想出了一個好辦法來解決這個問題:先建立一個封閉的密室,這個密室只有八袋長老以上的人才能進去。密室中間有一張紙條,上面寫著一個地址——溫家堡,還有這個地址放著多少人的聯(lián)系信息等內(nèi)容。這個密室就是Ntdll.dll,這個紙條就是SYSTEM_DESCRIPTOR_TABLE,上寫的地址就是SYSTEM_SERVICE_TABLE,也就是溫家堡了。這個溫家堡是一個有很多大房間的地方,每個房子有個房間號
            ,房間里面又放著一張紙條,上面寫著各個手下的住所。比如說編號為7A的房間,里面放的是NtOpenProcess的家庭住址。

            這樣一來,幫主要找人就容易了。先去密室找到紙條,看看上面寫的是溫家堡還是白云城,那個地方有多少個人的聯(lián)系信息等。如果是溫家堡就跑到那里去,看看要找誰,找NtOpenProcess就去7A房間。在這個房間里一看,啊,里面寫著NtOpenProcess現(xiàn)在就住在密室的旁邊……搞定。

            這里就有一個新的問題,幫主假設(shè)這個里面寫的東西都是正確的,沒有被人改過。于是就有了別派的間諜發(fā)現(xiàn)了,偷偷溜進密室,然后根據(jù)紙條的內(nèi)容,又跑到溫家堡。進到7A房間,神不知鬼不覺的把里面記錄的NtOpenProcess的地址改成了自己的家。于是,幫主再找人,發(fā)現(xiàn)找到對頭家里去了。這個就是傳說中的SSDT Hook了。

            攻擊者進入ring0之后,找到KeServiceDescriptorTable地址的值,即SYSTEM_SERVICE_TABLE的地址(進入密室,找到紙條寫的地址——溫家堡)。然后改寫SYSTEM_SERVICE_TABLE中一個特定函數(shù)的地址為自己定義的函數(shù)入口處,截獲了系統(tǒng)調(diào)用(來到溫家堡,改掉7A房間里面寫的住所,改成自己家)。一次HOOK就完成了。

            下面我給一段簡單的代碼,演示怎么樣讓一個特定的PID不會被殺死。這段代碼基本和《SSDT Hook的妙用-對抗ring0 inline hook》一文一樣,我只是注釋了一下而已,另外在MyNtOpenProcess處加了個判斷是不是某個特定PID的功能。
            代碼:


            /*
            演示HOOK系統(tǒng)服務(wù)調(diào)用表中的NtOpenProcess函數(shù),保護需要保護的進程被,防止被殺掉
            */

            #include<ntddk.h>

            /*
            KeServiceDescriptorTable僅有ntoskrnel一項,沒有包含win32k,而且后面的兩個字段都沒有使用,所

            以為了簡便直接把SystemServiceDescriptorTable定義成SYSTEM_SERVICE_TABLE,免得訪問多個結(jié)構(gòu)體的

            字段,麻煩。這里明白就行了。
            */
            typedef struct _SystemServiceDescriptorTable
            {
            ???? PVOID???? ServiceTableBase;
            ???? PULONG???? ServiceCounterTableBase;
            ???? ULONG???? NumberOfService;
            ???? ULONG???? ParamTableBase;
            }SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;

            // KeServiceDescriptorTable為ntoskrnl.exe導(dǎo)出
            extern???? PSystemServiceDescriptorTable???? KeServiceDescriptorTable;

            // 定義一下NtOpenProcess的原型,下面如果用匯編調(diào)用就不用定義了,但是我想盡量不用匯編
            typedef???? NTSTATUS???? (__stdcall *NTOPENPROCESS)( OUT PHANDLE ProcessHandle,
            ????????????????????????????????????????????????

            IN ACCESS_MASK AccessMask,
            ????????????????????????????????????????????????

            IN POBJECT_ATTRIBUTES ObjectAttributes,
            ????????????????????????????????????????????????

            IN PCLIENT_ID ClientId
            ????????????????????????????????????????????????

            );

            NTOPENPROCESS???? RealNtOpenProcess;

            // 定義函數(shù)原型
            VOID Hook();
            VOID Unhook();
            VOID OnUnload(IN PDRIVER_OBJECT DriverObject);

            // 真實的函數(shù)地址,我們會在自定義的函數(shù)中調(diào)用
            ULONG???? RealServiceAddress;

            // 需要被驅(qū)動保護的進程ID
            HANDLE???? MyPID;

            // 自定義的NtOpenProcess函數(shù)
            NTSTATUS __stdcall MyNtOpenProcess( OUT???? PHANDLE ProcessHandle,
            ???????????????????? IN???? ACCESS_MASK DesiredAccess,
            ???????????????????? IN???? POBJECT_ATTRIBUTES ObjectAttributes,
            ???????????????????? IN???? PCLIENT_ID ClientId )
            {
            ???? NTSTATUS???? rc;
            ???? ULONG???????? PID;
            ????
            ???? //DbgPrint( "NtOpenProcess() called.\n" );
            ????
            ???? rc = (NTSTATUS)(NTOPENPROCESS)RealNtOpenProcess( ProcessHandle, DesiredAccess,

            ObjectAttributes, ClientId );
            ????
            ???? if( (ClientId != NULL) )
            ???? {
            ???????? PID = (ULONG)ClientId->UniqueProcess;
            ???????? //DbgPrint( "%d was opened,Handle is %d.\n", PID, (ULONG)ProcessHandle );
            ????????
            ???????? // 如果進程PID是1520,直接返回權(quán)限不足,并將句柄設(shè)置為空
            ???????? if( PID == 1520 )
            ???????? {
            ???????????? DbgPrint( "Some want to open pid 1520!\n" );
            ????????????
            ???????????? ProcessHandle = NULL;
            ????????????????????????
            ???????????? rc = STATUS_ACCESS_DENIED;
            ???????? }
            ???? }
            ????
            ???? return rc;
            }

            // 驅(qū)動入口
            NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
            {
            ???? DriverObject->DriverUnload = OnUnload;

            ???? Hook();
            ????
            ???? return STATUS_SUCCESS;
            }

            // 驅(qū)動卸載
            VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
            {
            ???? Unhook( );
            }

            //?? 此處修改SSDT中的NtOpenProcess服務(wù)地址
            VOID Hook()
            {
            ???? ULONG???????????? Address;
            ????
            ???? // 0x7A為Winxp+SP2下NtOpenProcess服務(wù)ID號
            ???? // Adress是個地址A,這個地址的數(shù)據(jù)還是一個地址B,這個地址B就是NtOpenProcess的地址了
            ???? // (ULONG)KeServiceDescriptorTable->ServiceTableBase就是溫家堡的第一個房間
            ???? // Address是第7A個房間。
            ???? Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

            ???? // 取得地址A的值,也就是NtOpenProcess服務(wù)的地址了,保存原來NtOpenProcess的地址以后恢

            復(fù)用
            ???? RealServiceAddress = *(ULONG*)Address;
            ????
            ???? RealNtOpenProcess = (NTOPENPROCESS)RealServiceAddress;
            ????
            ???? DbgPrint( "Address of Real NtOpenProcess: 0x%08X\n", RealServiceAddress );

            ???? DbgPrint(" Address of MyNtOpenProcess: 0x%08X\n", MyNtOpenProcess );

            ???? // 去掉內(nèi)存保護
            ???? __asm
            ???? {
            ???????? cli
            ???????? mov???? eax, cr0
            ???????? and???? eax, not 10000h
            ???????? mov???? cr0, eax
            ???? }
            ????
            ???? // 修改SSDT中NtOpenProcess服務(wù)的地址
            ?? *((ULONG*)Address) = (ULONG)MyNtOpenProcess;

            ???? // 恢復(fù)內(nèi)存保護
            ???? __asm
            ???? {
            ???????? mov???? eax, cr0
            ???????? or???? eax, 10000h
            ???????? mov???? cr0, eax
            ???????? sti
            ???? }
            }

            //////////////////////////////////////////////////////
            VOID Unhook()
            {
            ?? ULONG?? Address;
            ?? Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

            ???? __asm
            ???? {
            ???????? cli
            ???????? mov???? eax, cr0
            ???????? and???? eax, not 10000h
            ???????? mov???? cr0, eax
            ???? }

            ???? // 還原SSDT
            ???? *((ULONG*)Address) = (ULONG)RealServiceAddress;
            ????
            ???? __asm
            ???? {
            ???????? mov???? eax, cr0
            ???????? or???? eax, 10000h
            ???????? mov???? cr0, eax
            ???????? sti
            ???? }

            ???? DbgPrint("Unhook");
            }
            補充:雖然是轉(zhuǎn)貼,我還是補充兩句,各抒己見。

            SSDT功能強大,猶如寶刀屠龍,號令天下,誰敢不從?那么SSDT必定是武林豪杰必爭之寶。引起江湖上的風(fēng)風(fēng)雨雨在所難免。

            黑道門派有:木馬,病毒,流氓軟件,無聊程序,下賤程序等幫派,如果被如此等流氓幫派得到SSDT如此寶物,必定腥風(fēng)血雨,天下不得安寧。

            白道門派有:卡巴,瑞星,諾頓,金山,殺毒軟件,防毒軟件,木馬清道夫,尾巴清道夫,流氓軟件清道夫等等門派。如果如此門派得到此寶,那必定造福于天下,是武林之福啊。

            中立門派有:外掛,反外掛,游戲防外掛等門派,如果他們得到此寶,影響較小,危害不大。

            SSDT并非專屬誰所有,所以誰要得到他,那就得憑真本事,勝者為王,敗者為寇的道理就不用多說了。介于上面種種原因,我們從江湖行情可以看出。經(jīng)常會出現(xiàn)病毒殺掉殺毒軟件,殺毒軟件干掉病毒的事情,刀劍無眼,這些都是不可避免的事情。但是經(jīng)常會覺得奇怪,為什么大家都同樣的用機器,我的就被病毒感染,別人的就沒有被感染呢?而且經(jīng)常會出現(xiàn),重裝系統(tǒng)后仍然有病毒,而且仍然kill殺毒軟件,甚至安裝不上。

            解釋就只有一個:先下手為強。重裝系統(tǒng)后任然有毒,并且安裝不上殺毒軟件只能說明一個問題,你先啟動了病毒,后安裝殺毒軟件。讓病毒先得到了SSDT的控制權(quán),殺毒軟件沒了那東西,自然威力大減,甚至發(fā)生滅門慘案。病毒被隱藏在其他盤了,在重裝系統(tǒng)后,以為平安無私了,掉以輕心去打開其他盤,導(dǎo)致病毒重新啟動。。。。

            現(xiàn)在的外掛制作也基本上涉及到了SSDT技術(shù),系統(tǒng)內(nèi)核層次也設(shè)計到 零環(huán) 和 3環(huán) 的對抗,為什么現(xiàn)在使用用戶態(tài)的鉤子,無法HOOK某些游戲做外掛,但是只要不HOOK游戲,在其他程序里跑又沒有問題呢?原因就是這個問題,你要HOOK某游戲,必定掛鉤到該進程,游戲可以在SSDT那里修改你要使用的HOOK函數(shù)地址,然后每當(dāng)你調(diào)用鉤子函數(shù)去控制游戲的時候,都要經(jīng)過該游戲的過濾層,非法操作則return什么都不做就可以了,但是其實這是個笨辦法。去HOOK游戲的時候,必須使用全局鉤子,必定注入到游戲進程,在外掛打開該游戲進程,調(diào)用OpenProccess或者NtOpenProccess時,直接HooK該函數(shù),然后在里面檢測打開的進程是不是該游戲進程,如果不是則正確調(diào)用該函數(shù)。如果是該游戲進程,那你就死定了,程序就返回一個假的進程值,比如說游戲進程開啟一個子進程,里面什么也不做,只讓他休眠。你以為打開了該游戲進程,其實你打開了一個什么也不做的游戲子進程。所以,無論你怎么做,游戲內(nèi)部都沒有反映。其實最強的游戲外掛是脫機外掛,不過這種外掛,哈哈···10有9都是游戲公司內(nèi)部做出來的,不然游戲通訊協(xié)議分析哪有那么容易,我現(xiàn)在看來覺得會很難。如果不是內(nèi)部人員做出來,或者透露出來的話,那么也就是說,協(xié)議分析很簡單咯,那么像網(wǎng)上銀行,支付寶早這些就被拿下了。或者說像QQ這種軟件,那些什么消息加密,早就拿下了吧,如果能破解通信協(xié)議,你破解的不僅僅是通信協(xié)議本身,而是破解了別人的心靈加密問題了,你已經(jīng)不是人,是神了。當(dāng)然不排除真正靠自己分析將協(xié)議分析出來的高手,我很佩服,我說過他們不是人,是神,哈哈···。


            ?

            精品综合久久久久久97超人| 久久久久青草线蕉综合超碰| 色综合久久久久| 久久久久久亚洲精品无码| 久久伊人精品一区二区三区 | 99久久婷婷免费国产综合精品| 久久婷婷国产麻豆91天堂| 久久精品国产久精国产果冻传媒| 精品久久8x国产免费观看| 久久无码国产| 国产精品无码久久综合网| 99精品国产99久久久久久97 | 国内精品九九久久精品| 国产精品久久久久久福利漫画| 伊人 久久 精品| 女人香蕉久久**毛片精品| 亚洲va中文字幕无码久久| 久久人妻少妇嫩草AV蜜桃| 久久久久一区二区三区| 久久人人爽人人人人片av| 久久久久人妻一区精品果冻| 精品久久久久久亚洲| 久久精品国产亚洲AV无码麻豆| 久久久久久精品成人免费图片| 亚洲国产精品一区二区三区久久| 国产精品嫩草影院久久| 亚洲天堂久久精品| 国产精品一久久香蕉国产线看| 亚洲va久久久噜噜噜久久| 亚洲国产另类久久久精品黑人| 久久久噜噜噜久久| 国产午夜福利精品久久| 精品国产青草久久久久福利| 日韩亚洲欧美久久久www综合网| 狠狠色丁香久久综合五月| 久久99国产精品久久久| 久久中文字幕一区二区| 久久国产精品免费一区二区三区| 久久这里只有精品首页| 久久强奷乱码老熟女| 久久经典免费视频|