• <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),開心的工作
            簡(jiǎn)單、開放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            API-HOOK and ANTI-API-HOOK For Ring3

            Posted on 2010-03-15 14:36 S.l.e!ep.¢% 閱讀(850) 評(píng)論(0)  編輯 收藏 引用 所屬分類: RootKit
            標(biāo) 題: 【原創(chuàng)】API-HOOK and ANTI-API-HOOK For Ring3
            作 者: Anskya
            時(shí) 間: 2007-01-07,20:56:49
            鏈 接: http://bbs.pediy.com/showthread.php?t=37586

            <<API-HOOK?and?ANTI-API-HOOK?For?Ring3>>
            轉(zhuǎn)載請(qǐng)保留版權(quán).謝謝
            Anskya@Gmail.com

            今天突然看到"墮落天才"仁兄的兩篇文章
            感謝他的的文章和共享精神.謝謝...突然手癢..有感而發(fā)
            API-HOOK和ANTI-API-HOOK已經(jīng)不算什么新鮮的技術(shù)了
            一般大概用的技術(shù)都差不多

            [1]簡(jiǎn)要介紹API-HOOK
            1.IAT補(bǔ)丁
            介紹:
            一般調(diào)用函數(shù)都是call?[MessageBoxA]這樣的格式
            很明顯[MessageBoxA]下的地址就是函數(shù)的真正的地址
            代碼:
            Delphi:
            push?0
            push?0
            push?0
            push?0
            call?-$000467cd(這里是MessageBox在導(dǎo)入表的偏移)
            
            -$000467cd下的代碼就是:
            jmp?dword?ptr?[$004514b0]
            004514b0下的地址是---77D504EA(剛好就是MessageBoxA的地址)
            IAT補(bǔ)丁的意思就是修改jmp?dword?ptr?[$004514b0]這句為自己的鉤子地址
            然后鉤子返回的時(shí)候返回77D504EA地址
            (這里用Delphi的Debug是因?yàn)轫樖?還有一點(diǎn)就是..VC看不到棧值)

            優(yōu)點(diǎn):簡(jiǎn)單...
            缺點(diǎn):如果是動(dòng)態(tài)調(diào)用的函數(shù)導(dǎo)入表中是不會(huì)出現(xiàn)這種函數(shù)的
            所以就出現(xiàn)了下面的技術(shù)

            2.內(nèi)存補(bǔ)丁:
            介紹:
            由于IAT的缺點(diǎn)于是牛們就想到了動(dòng)態(tài)修改DLL函數(shù)的內(nèi)存
            還是以MessageBoxA為例子:
            代碼:
            77D504EA?>??8BFF????????????MOV?EDI,EDI
            77D504EC????55??????????????PUSH?EBP
            77D504ED????8BEC????????????MOV?EBP,ESP
            77D504EF????833D?BC04D777?0>CMP?DWORD?PTR?DS:[77D704BC],0
            77D504F6????74?24???????????JE?SHORT?USER32.77D5051C
            77D504F8????64:A1?18000000??MOV?EAX,DWORD?PTR?FS:[18]
            77D504FE????6A?00???????????PUSH?0
            77D50500????FF70?24?????????PUSH?DWORD?PTR?DS:[EAX+24]
            77D50503????68?240BD777?????PUSH?USER32.77D70B24
            77D50508????FF15?C812D177???CALL?DWORD?PTR?DS:[<&KERNEL32.Interlocke>;?
            
            kernel32.InterlockedCompareExchange
            77D5050E????85C0????????????TEST?EAX,EAX
            77D50510????75?0A???????????JNZ?SHORT?USER32.77D5051C
            77D50512????C705?200BD777?0>MOV?DWORD?PTR?DS:[77D70B20],1
            77D5051C????6A?00???????????PUSH?0
            77D5051E????FF75?14?????????PUSH?DWORD?PTR?SS:[EBP+14]
            77D50521????FF75?10?????????PUSH?DWORD?PTR?SS:[EBP+10]
            77D50524????FF75?0C?????????PUSH?DWORD?PTR?SS:[EBP+C]
            77D50527????FF75?08?????????PUSH?DWORD?PTR?SS:[EBP+8]
            77D5052A????E8?2D000000?????CALL?USER32.MessageBoxExA
            77D5052F????5D??????????????POP?EBP
            77D50530????C2?1000?????????RETN?10
            
            一般掛鉤法就是修改前5個(gè)字節(jié)
            mov?edi,edi
            push?ebp
            mov?ebp,esp
            剛好是5個(gè)字節(jié).jmp到HookProc的地址
            然后再調(diào)回到MessageBoxA+5的地方...

            優(yōu)點(diǎn):比較實(shí)用
            缺點(diǎn):Ring3很好用...如果非要弄個(gè)缺點(diǎn)就是
            有的時(shí)候函數(shù)代碼頭部未必是
            mov?edi,edi
            push?ebp
            mov?ebp,esp
            許多API函數(shù)的頭部都是這樣的但是一些cdecl調(diào)用格式
            或者非stdcall格式的函數(shù)無(wú)法掛鉤.但是配合脫鉤一起用會(huì)發(fā)現(xiàn)
            效果不錯(cuò)...可以當(dāng)bpx用..再配合一點(diǎn)匯編知識(shí)就可以獲取寄存器數(shù)據(jù)等

            3.深入上面的
            有許許多多的什么陷井技術(shù),棧填寫返回地址等...RelocationTable掛鉤技術(shù)
            其實(shí)就是內(nèi)存補(bǔ)丁技術(shù)...不過(guò)用了不同的方法填寫返回地址而已

            4.SEH?or?VEH掛鉤
            填寫Int3,Int1等指令讓程序產(chǎn)生異常然后調(diào)轉(zhuǎn)到鉤子執(zhí)行過(guò)程.
            個(gè)人很習(xí)慣這種方法VEH玩過(guò)一下...但是由于兼容性不強(qiáng).你可以在HookSpy的代碼
            找到VEH的代碼和相關(guān)應(yīng)用.配合著調(diào)試API用起來(lái)也很過(guò)癮
            至少你不用DebugActiveProcess函數(shù)去掛接進(jìn)程
            直接利用CreateRemoteThread函數(shù)注入DLL.注入方法很多看個(gè)人喜好
            具體查看羅聰前輩的<<用?SEH?技術(shù)實(shí)現(xiàn)?API?Hook>>
            VEH技術(shù)實(shí)現(xiàn)最近打算也寫一篇...正在孕釀(關(guān)于著方面的知識(shí)太少了)
            有個(gè)地方需要注意~SEH和VEH有點(diǎn)不太好調(diào)試~許多異常都會(huì)碑調(diào)試器捕獲到
            所以最好用OD或者專用的調(diào)試器...編程工具自帶的調(diào)試器會(huì)捕獲所有的異常

            5.調(diào)試寄存器
            不多說(shuō)了看EliCZ叔叔的文章和代碼吧

            說(shuō)了一大對(duì)無(wú)聊的東西現(xiàn)在來(lái)說(shuō)說(shuō)反調(diào)試的問(wèn)題

            [2]常用的ANTI-APIHOOK技術(shù)
            1.IAT-API-HOOK
            由于修改的導(dǎo)入表地址.
            最簡(jiǎn)單的方法就是你需要的函數(shù)全部使用GetProcAddress函數(shù)來(lái)獲取
            代碼:
            typedef?int(*TMessageBoxA)(HWND?hWnd,?LPCTSTR?lpText,?LPCTSTR?lpCaption,?
            
            UINT?uType);
            
            void?__fastcall?TForm1::Button1Click(TObject?*Sender)
            {
            ??TMessageBoxA?MsgBox;
            ??MsgBox?=?(TMessageBoxA)GetProcAddress(LoadLibrary("user32.dll"),?
            
            "MessageBoxA");
            ??MsgBox(0,?0,?0,?0);
            }
            
            2.反內(nèi)存補(bǔ)丁(著重介紹這里)

            1.相信許多人都用過(guò)Madshi的madCollection
            通過(guò)跟蹤發(fā)現(xiàn)他是
            一般掛鉤都是修改前5個(gè)字節(jié)
            代碼:
            77D504EA?>-?FF25?1E00055F???JMP?DWORD?PTR?DS:[5F05001E]--被補(bǔ)丁了.
            77D504F0????3D?BC04D777?????CMP?EAX,user32.77D704BC
            77D504F5????007424?64???????ADD?BYTE?PTR?SS:[ESP+64],DH
            77D504F9????A1?18000000?????MOV?EAX,DWORD?PTR?DS:[18]
            77D504FE????6A?00???????????PUSH?0
            77D50500????FF70?24?????????PUSH?DWORD?PTR?DS:[EAX+24]
            77D50503????68?240BD777?????PUSH?user32.77D70B24
            77D50508????FF15?C812D177???CALL?DWORD?PTR?DS:[<&KERNEL32.Interlocke>;?
            
            kernel32.InterlockedCompareExchange
            77D5050E????85C0????????????TEST?EAX,EAX
            77D50510????75?0A???????????JNZ?SHORT?user32.77D5051C
            77D50512????C705?200BD777?0>MOV?DWORD?PTR?DS:[77D70B20],1
            77D5051C????6A?00???????????PUSH?0
            77D5051E????FF75?14?????????PUSH?DWORD?PTR?SS:[EBP+14]
            77D50521????FF75?10?????????PUSH?DWORD?PTR?SS:[EBP+10]
            77D50524????FF75?0C?????????PUSH?DWORD?PTR?SS:[EBP+C]
            77D50527????FF75?08?????????PUSH?DWORD?PTR?SS:[EBP+8]
            77D5052A????E8?2D000000?????CALL?user32.MessageBoxExA
            77D5052F????5D??????????????POP?EBP
            77D50530????C2?1000?????????RETN?10
            
            知道就可以脫鉤了.那我們?nèi)绾闻袛嗨欠癖粧煦^呢?
            代碼:
            bool?IsHook(char?*lpChar)
            {
            ??if(*lpChar?==?0xFF)?return?true;
            }
            
            function?IsHook(lpFunc:?Pointer):?Boolean;
            begin
            ??Result?:=?False;
            ??if?(Char(lpFunc^)=#$FF)?then?Result?:=?True;
            end;
            
            判斷第一個(gè)字節(jié)是否是0xFF,你也可以根據(jù)一些特別的掛鉤修改
            例如有的是直接jmp?調(diào)轉(zhuǎn)到直接的地址...E9.或者call-F8(機(jī)器碼)

            2.棧保存地址..
            和上面一樣不過(guò)這里有一點(diǎn)點(diǎn)區(qū)別掛鉤方式被修改成
            代碼:
            77D504EA?>??68?04BF4000?????PUSH?40BF04------這里被寫成鉤子過(guò)程地址
            77D504EF????C3??????????????RETN-------------返回
            77D504F0????3D?BC04D777?????CMP?EAX,user32.77D704BC
            77D504F5????007424?64???????ADD?BYTE?PTR?SS:[ESP+64],DH
            77D504F9????A1?18000000?????MOV?EAX,DWORD?PTR?DS:[18]
            77D504FE????6A?00???????????PUSH?0
            77D50500????FF70?24?????????PUSH?DWORD?PTR?DS:[EAX+24]
            77D50503????68?240BD777?????PUSH?user32.77D70B24
            77D50508????FF15?C812D177???CALL?DWORD?PTR?DS:[<&KERNEL32.Interlocke>;?
            
            kernel32.InterlockedCompareExchange
            77D5050E????85C0????????????TEST?EAX,EAX
            77D50510????75?0A???????????JNZ?SHORT?user32.77D5051C
            77D50512????C705?200BD777?0>MOV?DWORD?PTR?DS:[77D70B20],1
            77D5051C????6A?00???????????PUSH?0
            77D5051E????FF75?14?????????PUSH?DWORD?PTR?SS:[EBP+14]
            77D50521????FF75?10?????????PUSH?DWORD?PTR?SS:[EBP+10]
            77D50524????FF75?0C?????????PUSH?DWORD?PTR?SS:[EBP+C]
            77D50527????FF75?08?????????PUSH?DWORD?PTR?SS:[EBP+8]
            77D5052A????E8?2D000000?????CALL?user32.MessageBoxExA
            77D5052F????5D??????????????POP?EBP
            77D50530????C2?1000?????????RETN?10
            
            執(zhí)行完畢后再調(diào)轉(zhuǎn)回來(lái)

            對(duì)付這種掛鉤方式...方法一般2種
            分析一下他是如何掛鉤的吧...首先他要先獲取你要掛鉤的函數(shù)地址
            填寫前六個(gè)字節(jié)
            1.你提前掛鉤...然后讓他掛你的鉤子.
            這樣你直接調(diào)用你自己的返回地址就好了最好可以多復(fù)制一點(diǎn).
            另外說(shuō)一點(diǎn).許多API函數(shù)都是調(diào)用xxxxW或者xxxxEx什么的
            所以一般A系函數(shù)都很短你甚至可以直接復(fù)制到自身進(jìn)程里面去執(zhí)行
            具體代碼和資料看下面的描述

            2.脫鉤.
            這里代碼很多.幾乎所有的API-Hook?library都有這個(gè)函數(shù)
            自己看一下吧.我就不多說(shuō)了


            3.利用反匯編引擎搜索鉤子返回地址!Cool.直接調(diào)用返回函數(shù)!!

            由于掛鉤的時(shí)候會(huì)把修改的代碼轉(zhuǎn)移到別的地方
            掛鉤需要使用6個(gè)字節(jié)的空間.所以掛鉤的時(shí)候就需要計(jì)算
            需要多長(zhǎng)的指令...(所以一般CodeHook?Library里面都自帶一個(gè)長(zhǎng)度反匯編引擎)
            看個(gè)人喜好...看你用的是什么庫(kù)了(29A等許多病毒代碼里面都有許多)
            常用的:
            Opcode?Length?Disassembler?Coded?By?Ms-Rem(ASM,C,Delphi版本)
            Length?Disassembler?Engine?By?Zombie
            其它的還有.剛在WASM上發(fā)現(xiàn)一個(gè)新的,沒(méi)有用過(guò)反正就那兩種原理
            也沒(méi)有多少測(cè)試...好了下面說(shuō)說(shuō)如何尋找返回地址

            鉤子都是需要返回地址的.不然這個(gè)函數(shù)就會(huì)被屏蔽.無(wú)效代碼
            可是返回地址如何獲取呢???既然是掛鉤那就肯定有一個(gè)返回地址..
            不然他自己怎么調(diào)用API函數(shù)?

            這里引入一個(gè)疑問(wèn)...
            返回地址一般都是最后~由于是跨段代碼調(diào)轉(zhuǎn),所以搜索ret后最后
            一個(gè)跨段調(diào)轉(zhuǎn)即可...
            1.判斷是否被掛鉤,
            一般API函數(shù)開頭都是
            代碼:
            mov?edi,?edi
            push?ebp
            mov?ebp,?esp
            
            or
            
            push?ebp
            mov?ebp,?esp
            
            第一種長(zhǎng)度2字節(jié),第二種長(zhǎng)度1字節(jié).一般說(shuō)來(lái)程序第一個(gè)字節(jié)都不太可能是
            E9,E8,FF之類的(為什么很少看到enter這個(gè)指令?據(jù)說(shuō)有BUG?)
            一旦超過(guò)5個(gè)字節(jié)就認(rèn)為他被掛鉤了!

            2.確定他復(fù)制走了多少地址
            (由于需要六個(gè)字節(jié),但是前面三條指令只有5個(gè)字節(jié).他就從第4行開始動(dòng)手,
            然后下來(lái)就是.開始計(jì)算了.)
            祭出LDE或者OLD.
            可以確定第一行指令是,push?0x00000000,jmp?0x00000000
            這樣的東東...如果有哪位仁兄使用了比較另類的掛鉤指令的話.那就需要特殊處理



            SizeOfCode(void?*Code,?unsigned?char?**pOpcode);返回指令長(zhǎng)度
            SizeOfProc(void?*Proc);獲取過(guò)程長(zhǎng)度.-她會(huì)從指針開頭反匯編.直到遇到ret
            (友情提示.代碼有個(gè)BUG)
            代碼:
            unsigned?long?__fastcall?SizeOfProc(void?*Proc)
            {
            ??ULONG??Length;
            ??PUCHAR?pOpcode;
            ??ULONG??Result?=?0;
            
            ??do
            ??{
            ????Length?=?SizeOfCode(Proc,?&pOpcode);
            ????Result?+=?Length;
            ????if?((Length?==?1)?&&?(*pOpcode?==?0xC3))?break;
            ????Proc?=?(PVOID)((ULONG)Proc?+?Length);
            ??}?while?(Length);
            ??return?Result;
            }
            
            當(dāng)指令長(zhǎng)度為1~機(jī)器碼為C3才認(rèn)為結(jié)束...許多stdcall都是自己恢復(fù)堆棧平衡的
            ...這里友情提示一下吧...自己編程的時(shí)候要小心.至于如何修改?嘿嘿..
            很容易我就不多說(shuō)了.省得別人說(shuō)我雞婆...

            使用SizeOfCode函數(shù)獲取指令長(zhǎng)度直到大于6或者等于6
            如果第一行就是5個(gè)字節(jié).取代碼指針.

            3.既然已經(jīng)獲取到了地址
            稍微跟蹤一下就會(huì)發(fā)現(xiàn)函數(shù)返回的地址是ret往上第一條指令!也就是最后一條指令
            由于是跨段調(diào)轉(zhuǎn)所以會(huì)使用call[]---機(jī)器碼FF的指令
            代碼:
            function?GetProcAddressEx(Proc:?Pointer):?Pointer;
            var
            ??lpCallRet:?Pointer;
            ??iCodeLen:?Integer;
            begin
            ??Result?:=?nil;
            ??lpCallRet?:=?nil;
            ??
            ??iCodeLen?:=?SizeOfCode(Proc);
            ??//??判斷第一行代碼是否為push?0xXXXXXXXX
            ??if?(iCodeLen?=?5)?and?(Byte(Proc^)?=?$68)?then
            ??begin
            ????//??獲取0xXXXXXXXX
            ????Proc?:=?Pointer(PDWORD(longword(Proc)?+?1)^);
            ????while?True?do
            ????begin
            ??????iCodeLen?:=?SizeOfCode(Proc);
            ??????//??判斷是否為call?dword?ptf[0xXXXXXXXX]
            ??????if?(iCodeLen?=?6)?and?(Byte(Proc^)?=?$FF)?and?(Byte(Pointer
            
            (longword(Proc)?+?1)^)?=?$15)?then
            ??????begin
            ????????//??獲取0xXXXXXXXX
            ????????lpCallRet?:=?Proc;
            ????????Break;
            ??????end;
            ??????//??函數(shù)結(jié)尾
            ??????if?(Byte(Proc^)?=?$C3)?then?Break;
            ??????Proc?:=?pointer(longword(Proc)?+?iCodeLen);
            ????end;
            ??end;
            ??if?lpCallRet?<>?nil?then
            ??begin
            ????Result?:=?Pointer(PDWORD(PDWORD(longword(lpCallRet)?+?2)^)^);
            ??end;
            end;
            
            不好意思...由于暫時(shí)沒(méi)有編程工具.文章里面出現(xiàn)的代碼是以前寫的
            這篇文章完全是一篇回憶錄...以前寫的代碼和資料全部丟失了..
            這里使用的是Ms-Rem的Opcode?Length?Disassembler?Engine

            這里描述的是如何bypass?堆跳轉(zhuǎn)掛鉤模式...jmp和call調(diào)轉(zhuǎn)模式
            都一樣的原理和代碼可以實(shí)現(xiàn).大家可以自己模擬作一下.關(guān)鍵是思路
            大家有什么好的方法希望提供...

            OLD引擎您可以從Ms-Rem的process_hunter?Src中獲取到
            www.wasm.ru

            再次感謝許許多多的知名的不知名的大俠們的文章和代碼.感謝
            thank:EliCZ,Madshi,Ms-Rem,Aphex...29A?Group
            轉(zhuǎn)載請(qǐng)保留版權(quán).謝謝
            Anskya@Gmail.com

            久久国产精品-久久精品| 99久久国产综合精品成人影院 | 99久久免费国产精精品| 久久精品视屏| 国产精品国色综合久久| 久久综合九色综合欧美就去吻| 色欲综合久久中文字幕网| 久久九九久精品国产免费直播| 一本久道久久综合狠狠爱| 久久亚洲电影| 精品人妻伦九区久久AAA片69| 亚洲AV日韩AV永久无码久久| 午夜精品久久久久久影视777| 久久久精品午夜免费不卡| 日本欧美久久久久免费播放网| 色婷婷噜噜久久国产精品12p| 久久中文娱乐网| 丰满少妇人妻久久久久久| 亚洲AV日韩AV永久无码久久| 香蕉久久夜色精品国产2020| 久久99精品九九九久久婷婷| 久久久久久狠狠丁香| 久久久国产乱子伦精品作者| 国产精品亚洲综合久久| 理论片午午伦夜理片久久| 亚洲国产精品久久66| 国产精品久久久久久| 久久久av波多野一区二区| 久久天天躁狠狠躁夜夜96流白浆| 热99RE久久精品这里都是精品免费| 精品久久久久国产免费| 91精品国产91久久久久久青草| 久久99毛片免费观看不卡| 99久久精品国产高清一区二区| 国产午夜福利精品久久2021| 人人狠狠综合久久88成人| 久久夜色精品国产噜噜噜亚洲AV| 亚洲精品无码久久久久sm| 亚洲va久久久噜噜噜久久| 亚洲国产精品无码久久一线 | 色婷婷久久综合中文久久一本|