當(dāng)前位置:湖南陽光電子技術(shù)學(xué)校文章資訊技術(shù)園地電腦維修技術(shù)
招生辦公室電話:13308461099 13807313137 全國免費(fèi)電話:13807313137

“變速齒輪”再研究

減小字體 增大字體 作者:佚名  來源:本站整理  發(fā)布時(shí)間:2010-07-28 00:16:43
提起“變速齒輪”(以下簡(jiǎn)稱“齒輪”)這個(gè)軟件,大家應(yīng)該都知道吧,該軟件號(hào)稱
是全球第一款能改變游戲速度的程序。我起初用時(shí)覺得很神奇,久而久之就不禁思考其實(shí)現(xiàn)原理了,但苦于個(gè)人水平有限,始終不得其解,成了長駐于腦中揮散不去的大問號(hào)。

  偶然一天在BBS上看到了一篇名為《“變速齒輪”研究手記》(以下簡(jiǎn)稱《手記》)的文章,我如獲至寶,耐著性子把文章看完了,但之后還是有很多地方不解,不過還是有了比較模糊的認(rèn)識(shí):原來齒輪是通過截獲游戲程序?qū)r(shí)間相關(guān)函數(shù)的調(diào)用并修改返回結(jié)果實(shí)現(xiàn)的呀。

  為了徹徹底底地弄清齒輪的原理,我這次打算豁出去了�?紤]到《手記》的作者從是研究的“齒輪”的反匯編代碼的,那我也照樣從反匯編代碼開始。不過自認(rèn)為匯編功底不夠,又從圖書館借了幾本關(guān)于Windows底層機(jī)制和386匯編的書,在經(jīng)過差不多兩周的“修行”之后,自我感覺有點(diǎn)好啦,哈哈,我也有點(diǎn)要迫不及待地把“齒輪”大卸八塊了!

  在動(dòng)手之前,我又把《手記》看了一遍,這次可就清楚多了:通過調(diào)用門跳到Ring0級(jí)代碼段,修改各系統(tǒng)時(shí)間相關(guān)函數(shù)的前8個(gè)字節(jié)為jmp指令,轉(zhuǎn)跳到“齒輪”映射到2G之上的代碼,達(dá)到截獲對(duì)各系統(tǒng)時(shí)間相關(guān)函數(shù)的調(diào)用的目的。但同時(shí)我的疑惑也更明確了:
   1.“齒輪”怎樣建立指向自己映射到2G以上內(nèi)存的代碼的調(diào)用門描述符的;
   2.“齒輪”怎樣將自己的代碼映射到2G以上線性地址的;
   3.映射到2G之上的代碼是怎樣做到在代碼基址更改的情況仍能正確運(yùn)行的

  帶著這樣的疑問,我正式開始了對(duì)“齒輪”反匯編代碼的分析。工具嘛,不用說當(dāng)
然是Softice for Windows98、W32Dasm,OK,出發(fā)啦!

  我的“齒輪”版本是0.221 for win98和winme的,內(nèi)含有兩個(gè)文件(變速齒輪.exe
和Hook.dll)。先看看Hook.dll里面有些什么,用W32Dasm將Hook.dll反匯編,看看它的輸出函數(shù):

   __@@A">?ghWnd@@3PAUHWND__@@A
   ?gnHotKey1@@3KA
   ?gnHotKey2@@3KA
   ?gnHotKey3@@3KA
   ?gnHotKey4@@3KA
   ?nHook@@3HA
   __@@@Z">?SetHook@@YAHPAUHWND__@@@Z
   ?UnHook@@YAHXZ

  看函數(shù)名好象該dll只是安裝鉤子捕獲變速熱鍵的,與我的研究目的沒太大的關(guān)系, 跳過去!
  再看看變速齒輪.exe的導(dǎo)入函數(shù),timeGetTim、GetTickCount等時(shí)間相關(guān)的函數(shù)都
在里面。嘿,還有CreateFileMappingA和MapViewOfFileEx,看來“齒輪”是用這兩個(gè)函
數(shù)創(chuàng)建映射文件的。以下列出幾個(gè)關(guān)鍵的導(dǎo)入函數(shù):

   Hook.?gnHotKey1@@3KA
   Hook.?gnHotKey2@@3KA
   Hook.?gnHotKey3@@3KA
   Hook.?gnHotKey4@@3KA
   __@@@Z">Hook.?SetHook@@YAHPAUHWND__@@@Z
   KERNEL32.CreateFileMappingA
   KERNEL32.GetModuleFileNameA
   KERNEL32.GetModuleHandleA
   KERNEL32.GetTickCount
   KERNEL32.MapViewOfFileEx
   KERNEL32.QueryPerformanceCounte
   USER32.KillTimer
   USER32.SendMessageA
   USER32.SetTimer
   WINMM.timeGetTime
   WINMM.timeSetEvent

  既然“齒輪”截獲了timeGetTime,那我就跟蹤timeGetTime函數(shù)的執(zhí)行情況。

  我先寫了個(gè)Win32 APP (以下簡(jiǎn)稱APP),當(dāng)左擊客戶區(qū)時(shí)會(huì)調(diào)用timeGetTime并將返回的結(jié)果輸出至客戶區(qū)。運(yùn)行這個(gè)程序,打開“齒輪”,改變當(dāng)前速度。

  Ctrl + D 呼出Softice,bpx timeGetTime ,退出,再左擊APP客戶區(qū),Softice跳出。哈,果然timeGetTime函數(shù)的首指令成了jmp 8xxx 002A ,好F8繼續(xù)執(zhí)行,進(jìn)入了“ 齒輪”映射到2G線性地址之上的代碼。一路F8下去,發(fā)現(xiàn)接著“齒輪”把timeGetTime 首指令恢復(fù),并再次調(diào)用timeGetTime,這樣就得到了timeGetTime的正確結(jié)果,保存結(jié)果�!褒X輪”再把timeGetTime首指令又改為jmp 8xxx 002A 。接下來都猜得到“齒輪”要干什么了!沒錯(cuò),將得到的返回值修改后返回至調(diào)用timeGetTime的程序APP。

  我仔細(xì)分析了一下,“齒輪”修改返回值的公式如下:
           倍數(shù)*(返回值-第一次調(diào)用timeGetTime的返回值)
修改后的返回值=---------------------------------------------------+上一次修改后的返回值
                          100000
  公式中“上次修改后的返回值”是自己猜測(cè)的未經(jīng)證實(shí),僅供參考。

  代碼分析已經(jīng)進(jìn)行一部分了,可我之前的疑問仍未解決,“齒輪”是怎么將代碼映
射的?又是怎么得到修改代碼的權(quán)限的?

  既然“齒輪”中調(diào)用了CreateFileMappingA,我想其安裝調(diào)用門,映射代碼的初始化部分應(yīng)該就在調(diào)用該函數(shù)代碼的附近。好,沿著這個(gè)思路,呼出Softice,在CreateF ileMappingA處設(shè)置斷點(diǎn),將“齒輪”關(guān)閉后再運(yùn)行。Softice跳出,停在了CreateFile MappingA處,F(xiàn)11回到“齒輪”的代碼�?吹搅恕褒X輪”調(diào)用CreateFileMappingA的形式如下:

  CreateFileMappingA(FF,0,4,0,10000,0);
  可見“齒輪”創(chuàng)建了長度為0x10000的映射文件,繼續(xù),“齒輪”接著又調(diào)用MapViewOfFileEx,調(diào)用形式如下:
  MapViewOfFileEx(EDX,2,0,0,0,EAX);
  //EDX為CreateFileMappingA返回的映射文件句柄
  //EAX為申請(qǐng)映射代碼的基址,第一次調(diào)用時(shí)EAX為0x8000 0000

  這里就是關(guān)鍵了,“齒輪”要將映射文件映射至基址為0x8000 0000 的內(nèi)存空間中,可并不見得Windows就真的允許其映射呀?果然,“齒輪”在在調(diào)用之后判斷返回值是否有效,無效則將上次申請(qǐng)的基址加上0x1000,再次調(diào)用MapViewOfFileEx,一直循環(huán)到成功為止,再將返回的地址保存。

  接下來“齒輪”將原“齒輪”exe中的截獲API的代碼逐字節(jié)拷貝到映射區(qū)域去。至此,“齒輪”已經(jīng)將關(guān)鍵代碼映射到2G以上線性地址中了。

  我再F8,哈哈,和熟悉的SGDT指令打了個(gè)照面�!褒X輪”保存全局描述符表線性基 址,再用SLDT指令保存局部描述符表索引,計(jì)算出LDT基址。接著呢“齒輪”在局部描述表中創(chuàng)建了一個(gè)特權(quán)等級(jí)為0的代碼段指向需要利用Ring0特權(quán)修改代碼的“齒輪”自己的代碼,并把局部描述表中索引為2的調(diào)用門指向的地址改為“齒輪”映射到高于2G的代碼。

  然后“齒輪”依次調(diào)用各時(shí)間相關(guān)的API,保存其返回值留做計(jì)算返回時(shí)結(jié)果用。
“齒輪”又依次調(diào)用映射到高于2G的代碼修改各API的首指令。到了這里,“齒輪”的初始化部分就結(jié)束了,只等著還蒙在鼓里的游戲上鉤啦,哈哈!

  結(jié)束代碼只不過是作些恢復(fù)工作罷了,僅僅是初始化代碼的逆過程,所以就不再贅述(其實(shí)是我自己懶得看了,^_^!).
  至此,我對(duì)“齒輪”的加速原理已有大致的了解,深刻感受到“齒輪”代碼的精巧, 所以覺得有必要將"齒輪"中所運(yùn)用到的一些技巧作一個(gè)總結(jié):

1.基址無關(guān)代碼的編寫
  姑且以上面一句話作標(biāo)題,^_^。看了“齒輪”的初始化代碼,知道其映射代碼的基址差不多是隨機(jī)的,那么“齒輪”是怎么保證映射后的代碼能正常運(yùn)行的呢?如果 代碼是完全順序執(zhí)行的倒沒什么問題,但如果要調(diào)用自己映射代碼中的子程序呢?呵呵,就只有運(yùn)行時(shí)計(jì)算出子程序的入口地址并調(diào)用了,不過還是要先得到映射代碼所在的地址才行。“齒輪”簡(jiǎn)單地用兩條指令就得到當(dāng)前正在執(zhí)行的指令的地址,具體如下(地址為假設(shè)的):

  0:0  call 5
  0:5  pop esi

  現(xiàn)在esi中的值就是5了,哈哈!

  這里的call用的是近調(diào)用,整條指令為E800000000,即為調(diào)用下一條指令.所進(jìn)行的操作只不過是把下一條指令的地址入棧而已.再pop將返回地址(即pop指令本身的地址)取出.

2.修改調(diào)用門,生成jmp指令,修改代碼
  這些都是高度依賴于CPU的操作,技巧性也很強(qiáng),主要是鉆了操作系統(tǒng)的漏洞。比如“齒輪”就是用SGDT,SLDT獲得全局和局部描述符表基址來安裝調(diào)用門,通過訪問調(diào)用門來獲取RING0權(quán)限作一些平時(shí)不為系統(tǒng)所允許的操作;而CIH病毒是用SIDT獲得中斷描述符表基址安裝中斷門然后出發(fā)軟中斷獲取RING0權(quán)限的,原理都是一樣的。這些在水木上討論過很多遍,大家都很熟悉,所以也就不敢班門弄斧,寫到此為止。

3.64K代碼編寫
  由調(diào)用CreateFileMappingA函數(shù)參數(shù)可知“齒輪”只映射10000(64K)大小的區(qū)域,所以其映射在2G之上的代碼和數(shù)據(jù)決不能大于64K。我想作者之所以選擇64K為映射區(qū)域的大小,可能是與調(diào)用子程序或數(shù)據(jù)時(shí)容易計(jì)算地址有關(guān)。在映射代碼的任意一處得到當(dāng)前指令地址之后將其低16位置0即可得到映射代碼的基地址,再加上子程序入口或數(shù)據(jù)的偏移即可求得其絕對(duì)地址。
 
我的評(píng)論:

  一句話:佩服“齒輪”的作者王榮先生。

  “齒輪”的代碼表現(xiàn)他對(duì)windows運(yùn)行機(jī)制的深刻理解以及深厚的匯編功底還有豐富的想象力。對(duì)我來說“齒輪”仿佛就是一件精美的藝術(shù)品,每個(gè)細(xì)處都很值得玩味一 番,所以我才在看過“齒輪”代碼之后有了把我的分析過程用筆寫下來的沖動(dòng)。但同時(shí) 我又不得不承認(rèn)“齒輪”的功能的實(shí)現(xiàn)是依靠其高度技巧化的代碼實(shí)現(xiàn)的,換句話說就 是這種的方法局限性實(shí)在是太大了。不就是截獲API嘛,用的著這么麻煩嗎?

  為了證實(shí)自己的想法,我在Codeguru上直接找了個(gè)HOOK API 的代碼,該代碼是通過安裝WH_CBT類型全局鉤子在所有被插入DLL的進(jìn)程中修改進(jìn)程PE映像的輸入節(jié)達(dá)到截獲API的(這種方法在《windows核心編程》中有詳細(xì)說明)。把代碼稍做修改,就能工作了(在星際爭(zhēng)霸下試過,可以改變游戲速度)。盡管只在98下試過,但我覺得肯定也能在2000下用,因?yàn)榇a中只用了一兩句匯編指令,而且整個(gè)程序都是在RING3下運(yùn)行的,沒有作出什么出軌的舉動(dòng)。當(dāng)然這種方法也有缺點(diǎn),就是對(duì)用Loadlibrary加載WINMM.dll再用GetProcAddress獲取timeGetTime地址的API調(diào)用不起作用(原因在《windows核心編程》中有說明)。

  我打算在將測(cè)試用程序稍稍完善后再公布源代碼,屆時(shí)歡迎大家下載。
 
我的感謝:
  在我徹底弄清“齒輪”的代碼之后,已經(jīng)是第三天的上午了,無奈自己才疏學(xué)淺,全不像《手記》的作者只花了一個(gè)晚上就弄清楚,我可是花了一個(gè)上午、兩個(gè)下午、兩個(gè)晚上才結(jié)束了戰(zhàn)斗,實(shí)在是慚愧呀。

  自己之所以能自得其樂地堅(jiān)持了兩天多,是與寢室兄弟小強(qiáng)的支持分不開的。窮 困潦倒的我在這幾天不知道總共抽了他多少支煙,無以為報(bào),只有在這里說一聲謝謝了!另外還要感謝sunlie非常地閱讀本文,指出了原文中的錯(cuò)誤并提出了非常寶貴的意見!

   后要說的就是個(gè)人水平有限,文中難免出現(xiàn)錯(cuò)誤,歡迎大家討論!^_^

附A:
  使用工具:Softice for Windows98,W32Dasm,VisualC++ 6.0
  操作系統(tǒng):Window98 2nd
  分析目標(biāo):變速齒輪 for 98me 版本:0.221
  參考書籍或文章:
    80x86匯編語言程序設(shè)計(jì)教程   楊季文等編著  清華大學(xué)出版社
    windows剖析--初始化篇及內(nèi)核篇        清華大學(xué)出版社
    虛擬設(shè)備驅(qū)動(dòng)程序開發(fā)
    intel 32位系統(tǒng)軟件編程
    80x86指令參考手冊(cè)
    《“變速齒輪”研究手記》

附B:
  “齒輪”關(guān)鍵代碼完全注釋
  一、初始化部分(從"齒輪"調(diào)用CreateFileMappingA函數(shù)開始分析)
          0167:00401B0E PUSH   00
          0167:00401B10 PUSH   00010000
          0167:00401B15 PUSH   00
          0167:00401B17 PUSH   04
          0167:00401B19 PUSH   00
          0167:00401B1B PUSH   FF
          0167:00401B1D CALL   [KERNEL32!CreateFileMappingA]
  ;調(diào)用CreateFileMappingA
  ;調(diào)用形式如右:CreateFileMappingA(FF,0,4,0,10000,0)
          0167:00401B23 MOV    ECX,[EBP-30]
          0167:00401B26 MOV    [ECX+00000368],EAX
          0167:00401B2C MOV    DWORD PTR [EBP-14],80000000
          0167:00401B33 JMP    00401B41
          0167:00401B35 MOV    EDX,[EBP-14]
          0167:00401B38 ADD    EDX,00010000
  ;申請(qǐng)基址加0x10000
          0167:00401B3E MOV    [EBP-14],EDX
          0167:00401B41 MOV    EAX,[EBP-14]
          0167:00401B44 PUSH   EAX   ;映射文件基址
          0167:00401B45 PUSH   00    ;映射的字節(jié)數(shù)
          0167:00401B47 PUSH   00    ;文件偏移低32位
          0167:00401B49 PUSH   00    ;文件偏移高32位
          0167:00401B4B PUSH   02    ;訪問模式
          0167:00401B4D MOV    ECX,[EBP-30]
          0167:00401B50 MOV    EDX,[ECX+00000368]
          0167:00401B56 PUSH   EDX
  ;CreateFileMappingA返回的映射文件句柄
          0167:00401B57 CALL   [KERNEL32!MapViewOfFileEx]
  ; 調(diào)用形式如右:MapViewOfFileEx(EDX,2,0,0,0,EAX)
          0167:00401B5D MOV    ECX,[EBP-30]
  ;[EBP-30]為即將映射到2G之上
          0167:00401B60 MOV    [ECX+0000036C],EAX
  ; 的代碼的數(shù)據(jù)域的起始地址
          0167:00401B66 MOV    EDX,[EBP-30]
          0167:00401B69 CMP    DWORD PTR [EDX+0000036C],00
  ;檢查MapViewOfFileEx
          0167:00401B70 JZ     00401B74
         ;返回值,若為0則繼續(xù)調(diào)
          0167:00401B72 JMP    00401B76  ;調(diào)用MapViewOfFileEx
          0167:00401B74 JMP    00401B35  ;直至成功為止
          0167:00401B76 MOV    EAX,[EBP-30]
          0167:00401B79 MOV    ECX,[EAX+0000036C]
          0167:00401B7F MOV    [EBP-08],ECX
  ;映射文件起始地址存入[EBP-08]
          0167:00401B82 CALL   [WINMM!timeGetTime]
          0167:00401B88 MOV    [EBP-14],EAX
  ;將初次調(diào)用timeGetTime
         0167:00401BA0 MOV    ECX,[EBP-08]
  ;的返回值保存到[EBP-14]
         0167:00401BA3 MOV    EDX,[EBP-14]
  ;以及映射文件基址+FF30處
         0167:00401BA6 MOV    [ECX+0000FF30],EDX
 ...省略的代碼類似的保存調(diào)用初次GetTickCount,QueryPerformanceCounter的返回值
 
         0167:00401BED MOV    DWORD PTR [EBP-14],00000000
         0167:00401BF4 MOV    EDX,[EBP-30]
         0167:00401BF7 MOV    EAX,[EDX+0000036C]
         0167:00401BFD MOV    ECX,[EBP-14]
         0167:00401C00 MOV    BYTE PTR [ECX+EAX+0000F000],9A
  ;9a為遠(yuǎn)調(diào)用的指令碼
         0167:00401C08 MOV    EDX,[EBP-14]
         0167:00401C0B ADD    EDX,01
         0167:00401C0E MOV    [EBP-14],EDX
         0167:00401C11 MOV    EAX,[EBP-14]
         0167:00401C14 ADD    EAX,04
         0167:00401C17 MOV    [EBP-14],EAX
         0167:00401C1A MOV    ECX,[EBP-30]
         0167:00401C1D MOV    EDX,[ECX+0000036C]
         0167:00401C23 MOV    EAX,[EBP-14]
         0167:00401C26 MOV    BYTE PTR [EAX+EDX+0000F000],14
  ;14為調(diào)用門描述符的索引
         0167:00401C2E MOV    ECX,[EBP-14]
         0167:00401C31 ADD    ECX,01
         0167:00401C34 MOV    [EBP-14],ECX
         0167:00401C37 MOV    EDX,[EBP-30]
         0167:00401C3A MOV    EAX,[EDX+0000036C]
         0167:00401C40 MOV    ECX,[EBP-14]
         0167:00401C43 MOV    BYTE PTR [ECX+EAX+0000F000],00
  ;CALL指令其他部分
         0167:00401C4B MOV    EDX,[EBP-14]
         0167:00401C4E ADD    EDX,01
         0167:00401C51 MOV    [EBP-14],EDX
         0167:00401C54 MOV    EAX,[EBP-30]
         0167:00401C57 MOV    ECX,[EAX+0000036C]
         0167:00401C5D MOV    EDX,[EBP-14]
         0167:00401C60 MOV    BYTE PTR [EDX+ECX+0000F000],C2
         0167:00401C68 MOV    EAX,[EBP-14]
         0167:00401C6B ADD    EAX,01
         0167:00401C6E MOV    [EBP-14],EAX
         0167:00401C71 MOV    ECX,[EBP-30]
         0167:00401C74 MOV    EDX,[ECX+0000036C]
         0167:00401C7A MOV    EAX,[EBP-14]
         0167:00401C7D MOV    BYTE PTR [EAX+EDX+0000F000],00
         0167:00401C85 MOV    ECX,[EBP-14]
         0167:00401C88 ADD    ECX,01
         0167:00401C8B MOV    [EBP-14],ECX
         0167:00401C8E MOV    EDX,[EBP-30]
         0167:00401C91 MOV    EAX,[EDX+0000036C]
         0167:00401C97 MOV    ECX,[EBP-14]
         0167:00401C9A MOV    BYTE PTR [ECX+EAX+0000F000],00
         0167:00401CA2 MOV    EDX,[EBP-14]
  ;以上代碼為在映射代碼偏移F000處寫入指令CALL 0014:0000
         0167:00401CA5 ADD    EDX,01
  ;指令 A91400C20000共6個(gè)字節(jié)
         0167:00401CA8 MOV    [EBP-14],EDX ;
         0167:00401CAB MOV    ESI,0040213B
  ;要復(fù)制的代碼的起始地址
         0167:00401CB0 MOV    EDI,[EBP-08]
  ;要復(fù)制代碼的目標(biāo)地址(映射區(qū)域中)
         0167:00401CB3 MOV    ECX,00402688
  ;402688為要復(fù)制的代碼的末地址
         0167:00401CB8 SUB    ECX,ESI
         0167:00401CBA REPZ   MOVSB ;將代碼全部復(fù)制到映射區(qū)域
         0167:00401CBC SGDT   FWORD PTR [EBP-1C] ;這句開始就很關(guān)鍵了
         0167:00401CC0 LEA    EAX,[EBP-001C]
         0167:00401CC6 MOV    EAX,[EAX+02]    ;取GDT線性基址
         0167:00401CC9 XOR    EBX,EBX
         0167:00401CCB SLDT   BX         ;取LDT在GDT中的偏移
         0167:00401CCE AND    BX,-08
         0167:00401CD2 ADD    EAX,EBX
         0167:00401CD4 MOV    ECX,[EAX+02]
         0167:00401CD7 SHL    ECX,08
         0167:00401CDA MOV    CL,[EAX+07]
         0167:00401CDD ROR    ECX,08       ;以上計(jì)算出LDT線性基址
         0167:00401CE0 MOV    [EBP-0C],ECX    ;保存
         0167:00401CE3 MOV    EAX,[EBP-30]
         0167:00401CE6 MOV    ECX,[EBP-0C]
         0167:00401CE9 MOV    [EAX+00000370],ECX
         0167:00401CEF MOV    EDX,[EBP-30]
         0167:00401CF2 MOV    EAX,[EDX+0000036C]
         0167:00401CF8 MOV    ECX,[EBP-0C]
         0167:00401CFB MOV    [EAX+0000FE00],ECX
  ;將LDT線性基址保存至映射代碼中
         0167:00401D01 MOV    AX,CS
  ;得到當(dāng)前代碼段描述符號(hào)
         0167:00401D04 AND    AX,FFF8
         0167:00401D08 MOV    [EBP-10],AX
         0167:00401D0C MOV    EDX,[EBP-10]
         0167:00401D0F AND    EDX,0000FFFF
  ;EDX為代碼段描述符在LDT中的偏移量
         0167:00401D15 MOV    EAX,[EBP-30]
         0167:00401D18 MOV  ECX,[EAX+00000370] ;ECX此時(shí)為LDT線性基址
         0167:00401D1E MOV    EAX,[EBP-30]
         0167:00401D21 MOV   EAX,[EAX+00000370] 
;EAX此時(shí)為LDT線性基址     

         0167:00401D27 MOV    ESI,[EDX+ECX]
         0167:00401D2A MOV    [EAX+08],ESI
         0167:00401D2D MOV    ECX,[EDX+ECX+04]
  ;以上將當(dāng)前代碼段描述符復(fù)制到
         0167:00401D31 MOV    [EAX+0C],ECX  ;LDT第1項(xiàng)
         0167:00401D34 MOV    EDX,[EBP-30]
         0167:00401D37 MOV    EAX,[EDX+00000370]
         0167:00401D3D MOV    CL,[EAX+0D]
         0167:00401D40 AND    CL,9F
         0167:00401D43 MOV    EDX,[EBP-30]
         0167:00401D46 MOV    EAX,[EDX+00000370]
         0167:00401D4C MOV    [EAX+0D],CL
  ;以上修改LDT第1項(xiàng)的DPL為0,則當(dāng)由調(diào)用門轉(zhuǎn)到該段代碼時(shí)即獲得RING0權(quán)限
         0167:00401D4F MOV    EAX,[EBP-0C]
         0167:00401D52 ADD    EAX,10    ;獲得LDT中索引為2的調(diào)用門地址
         0167:00401D55 MOV    EBX,0040213B
         0167:00401D5A MOV    [EAX],EBX
         0167:00401D5C MOV    [EAX+04],EBX
         0167:00401D5F MOV    WORD PTR [EAX+02],000C
         0167:00401D65 MOV    WORD PTR [EAX+04],EC00 ;調(diào)用門修改完畢
         0167:00401D6B MOV    ECX,[EBP-08]
         0167:00401D6E MOV    EDX,[WINMM!timeGetTime]
         0167:00401D74 MOV    [ECX+0000FEE0]

;EDX;保存timeGetTime入口地址
    ...省略部分依次保存GetTickCount,GetMessageTime,timeSetEvent,SetTimer,
       timeGetSystemTime,QueryPerformanceCounter入口地址
         0167:00401DD2 MOV    ECX,[EBP-08]
         0167:00401DD5 MOV    EAX,[WINMM!timeGetTime]
         0167:00401DDA MOV    EBX,[EAX]
         0167:00401DDC MOV    [ECX+0000FE40],EBX
         0167:00401DE2 MOV    EBX,[EAX+04]
         0167:00401DE5 MOV    [ECX+0000FE44],EBX
                  ;保存timeGetTime函數(shù)前8個(gè)字節(jié)指令
   ...省略部分依次保存GetTickCount,GetMessageTime,timeSetEvent,timeGetSystemTime , QueryPerformanceCounter前8個(gè)字節(jié)指令
         0167:00401E6D MOV    BYTE PTR [ECX+0000FE90],E9
         0167:00401E74 MOV    EAX,00402165
         0167:00401E79 SUB    EAX,0040213B
       ;EAX為截獲代碼在映射代碼中的偏移
         0167:00401E7E ADD    EAX,ECX  ;計(jì)算出截獲代碼的線性入口地址
         0167:00401E80 SUB    EAX,[WINMM!timeGetTime]
         0167:00401E86 SUB    EAX,05   ;JMP指令總長5個(gè)字節(jié)
         0167:00401E89 MOV    [ECX+0000FE91],EAX
       ;計(jì)算生成從timeGetTime跳到截獲代碼的JMP指令并保存
 
    ...省略部分依次計(jì)算并生成GetTickCount,GetMessageTime,timeSetEvent,    timeGetSystemTime , QueryPerformanceCounter跳到截獲代碼的JMP指令并保存
 
         0167:00401F58 CLI  ;關(guān)閉中斷,謹(jǐn)防修改代碼時(shí)發(fā)生意外
         0167:00401F59 MOV    EAX,004021F3     ;
         0167:00401F5E SUB    EAX,0040213B;計(jì)算子程序在映射代碼中的偏移
         0167:00401F63 ADD    EAX,[EBP-08]     ;EAX=8xxx 00B8
         0167:00401F66 PUSH   EAX  ;傳入?yún)?shù)EAX為修改timeGetTime代碼的
                              ;子程序入口地址
         0167:00401F67 MOV    EAX,[EBP-08]     ;調(diào)用8xxx 0000
         0167:00401F6A CALL   EAX    ;返回時(shí)timeGetTime首指令被更改
 
      ...省略部分依次修改GetTickCount,GetMessageTime,timeSetEvent,
       timeGetSystemTime , QueryPerformanceCounter函數(shù)的首指令
 
         0167:00401FF  SETI   ;設(shè)置中斷,初始化代碼結(jié)束
  二、截獲時(shí)間函數(shù)部分(以timeGetTime為例子,代碼以跟蹤順序列出)
      timeGetTime
             JMP 832A 002A
      ;這是timeGetTime被修改后的首指令
         0167:832A 002A     CLI
      ;此時(shí)[esp]=40BF2C,即游戲程序中調(diào)用timeGetTime函數(shù)的下一條指令
      ...(6個(gè))各寄存器分別入棧 且MOV EBP,ESP
         0167:832A 0033     CALL  832A 0038
      ;將當(dāng)前EIP入棧(即下一條指令的地址)
         0167:832A 0038     POP  EDI    ;取出當(dāng)前指令地址
                     XOR  DI  , DI
                     MOV  ESI , EDI
     ;將64K內(nèi)存首地址賦給ESI
     ;此時(shí)ESI=EDI=832A 0000
                     ADD  ESI , 0040 2102
                     SUB  ESI , 0040 213B ;求出映射代碼首地址
                     PUSH  ESI
         0167:832A 004B     CALL  EDI    ;ESI為傳進(jìn)的參數(shù)
                      ;返回時(shí)已經(jīng)將timeGetTime代碼還原
         0167:832A 004D     CALL  832A 0052  ;
         0167:832A 0052     POP  EDI
                     XOR  DI ,DI    ;故技重施
                     CALL  [EDI + 0000FEED];調(diào)用原timeGetTime函數(shù)
                     SUB  EAX,[EDI + 0000 FF30]
     ;減去第一次調(diào)用timeGetTime的結(jié)果
                     MUL  DWORD PTR [EDI+0000 FE30]
     ;乘以用戶所指定的倍數(shù)
                     MOV  EBX ,00100000
                     DIV  EBX
     ;除以常數(shù)100000
                     ADD  EAX ,[EDI+ 0000FE20]
                     MOV  EAX,004021F3
                     SUB  EAX,0040213B
                     ADD  EAX,EDI
     ;以上指令為修改timeGetTime函數(shù)返回值
                     PUSH  EAX
     ;EAX為傳進(jìn)的參數(shù)
                     CALL  EDI
     ;返回時(shí)又將timeGetTime首指令換成JMP
     ...恢復(fù)各寄存器的值,EAX中為修改后的返回值
                     RET ;此時(shí)[ESP]=40BF2C,執(zhí)行RET將返回到游戲中去
     ;
         0167:832A 0000     CALL  832A 0005
         0167:832A 0005     POP  EDI
                     XOR  DI ,DI      ;老套了撒^_^
                     MOV  ESI ,[EDI+0000 FE00]
     ;此地址保存著LDT的線性基址
                     MOV  EAX,[ESP+04]
                     MOV  [ESI +10],AX
                     SHR  EAX,10
                     MOV  [ESI+16],AX
     ;以上代碼將LDT中索引為2的調(diào)用門描述符的偏移改為傳入的參數(shù)
     ...
                     MOV  EAX,0000 0F00
                     CALL  EAX
     ;調(diào)用子程序修改timeGetTime代碼
     0167:832A 0027        , ; RET  4
     ;彈出參數(shù),返回
     ;
         0167:832A F000     CALL  0014:00000000
                     RET  0
     ;
         000C:832A 0097     CALL  832A 009C
         000C:832A 009C     POP  EDI
                     MOV  EAX,[EDI+0000 FE40]
                     MOV  EBX,[EDI+0000 FEE0]
                     MOV  [EBX],EAX
                     MOV  EAX,[EDI+0000 FE44]
                     MOV  [EBX+04],EAX
                     RETF
     注:EDI+0000 FE40起前8個(gè)字節(jié)為原timeGetTime函數(shù)的指令
       EDI+0000 FEE0保存著timeGetTime函數(shù)的入口地址
       以上即恢復(fù)timeGetTime前8個(gè)字節(jié)的代碼
     ;
         000C:832A 00B8     CALL  832A 00BD
         000C:832A 00BD     POP  EDI
                     XOR  DI ,DI
     ...
                     MOV  EAX,[EDI+0000 FE90]
                     MOV  EBX,[EDI+0000 FEE0]
                     MOV  [EBX],EAX
                     MOV  EAX,[EDI+0000FE94]
                     MOV  [EBX+04],EAX
                     RETF

     注:EDI+0000 FE90 起前8個(gè)字節(jié)保存著JMP 832A 002A 指令
       是由“齒輪”初始化部分代碼計(jì)算出來的,以上代碼將JMP 832A 002A
       寫入timeGetTime函數(shù)
  湖南省陽光電子技術(shù)學(xué)校常年開設(shè):手機(jī)維修培訓(xùn)、家電維修培訓(xùn)、電工培訓(xùn)、電腦維修培訓(xùn)、焊工培訓(xùn)--面向全國火爆招生!網(wǎng)址:http://www.hnygpx.com 報(bào)名電話:13807313137)。安置就業(yè)�?荚嚭细耦C發(fā)全國通用權(quán)威證書。采用我校多年來獨(dú)創(chuàng)的“模塊教學(xué)法”,理論與實(shí)踐相結(jié)合、原理+圖紙+機(jī)器三位一體的教學(xué)模式,半天理論,半天實(shí)踐,通俗易懂,確保無任何基礎(chǔ)者也能全面掌握維修技能、成為同行業(yè)中的佼佼者。工作(一期不會(huì),免費(fèi)學(xué)會(huì)為止)。

Tags:變速齒輪 研究

作者:佚名
[]
電工培訓(xùn)學(xué)校 電動(dòng)車維修學(xué)校 摩托車維修學(xué)校 摩托車維修培訓(xùn) 手機(jī)維修培訓(xùn) 家電維修培訓(xùn) 電腦維修培訓(xùn) 電動(dòng)工具維修培訓(xùn) 液晶電視維修培訓(xùn) 安防監(jiān)控培訓(xùn) 空調(diào)維修培訓(xùn) 網(wǎng)絡(luò)營銷培訓(xùn) 網(wǎng)站設(shè)計(jì)培訓(xùn) 淘寶網(wǎng)店培訓(xùn) 電器維修培訓(xùn) 家電維修學(xué)校 電工培訓(xùn) 焊工培訓(xùn) 電工學(xué)校 電工培訓(xùn)學(xué)校 電動(dòng)車維修學(xué)校 摩托車維修學(xué)校 摩托車維修培訓(xùn) 手機(jī)維修培訓(xùn) 家電維修培訓(xùn) 電腦維修培訓(xùn) 電動(dòng)工具維修培訓(xùn) 液晶電視維修培訓(xùn) 安防監(jiān)控培訓(xùn) 空調(diào)維修培訓(xùn) 網(wǎng)絡(luò)營銷培訓(xùn) 網(wǎng)站設(shè)計(jì)培訓(xùn) 淘寶網(wǎng)店培訓(xùn) 電器維修培訓(xùn) 家電維修學(xué)校 電工培訓(xùn) 焊工培訓(xùn) 電工學(xué)校 電工培訓(xùn)學(xué)校 電動(dòng)車維修學(xué)校 摩托車維修學(xué)校 摩托車維修培訓(xùn) 手機(jī)維修培訓(xùn) 家電維修培訓(xùn) 電腦維修培訓(xùn) 電動(dòng)工具維修培訓(xùn) 液晶電視維修培訓(xùn) 安防監(jiān)控培訓(xùn) 空調(diào)維修培訓(xùn) 網(wǎng)絡(luò)營銷培訓(xùn) 網(wǎng)站設(shè)計(jì)培訓(xùn) 淘寶網(wǎng)店培訓(xùn) 電器維修培訓(xùn) 家電維修學(xué)校 電工培訓(xùn) 焊工培訓(xùn) 電工學(xué)校 電工培訓(xùn)學(xué)校 電動(dòng)車維修學(xué)校 摩托車維修學(xué)校 摩托車維修培訓(xùn) 手機(jī)維修培訓(xùn) 家電維修培訓(xùn) 電腦維修培訓(xùn) 電動(dòng)工具維修培訓(xùn) 液晶電視維修培訓(xùn) 安防監(jiān)控培訓(xùn) 空調(diào)維修培訓(xùn) 網(wǎng)絡(luò)營銷培訓(xùn) 網(wǎng)站設(shè)計(jì)培訓(xùn) 淘寶網(wǎng)店培訓(xùn) 電器維修培訓(xùn) 家電維修學(xué)校 電工培訓(xùn) 焊工培訓(xùn) 電工學(xué)校
中山市,固原市,銀川市,玉樹,海東,隴南市,酒泉市,張掖市,天水市,金昌市,蘭州市,榆林市,延安市,渭南市,銅川市,阿里,山南,拉薩市,怒江,文山州,楚雄州,普洱市,昭通市,玉溪市,昆明市,畢節(jié),銅仁,遵義市,貴陽市,甘孜州,資陽市,達(dá)州市,宜賓市,南充市,遂寧市,綿陽市,瀘州市,自貢市,三亞市,崇左市,河池市,玉林市,欽州市,梧州市,柳州市,梅州市,肇慶市,湛江市,佛山市,珠海市,韶關(guān)市,湘西州,懷化市,郴州市,張家界市,邵陽市,株洲市,仙桃市,隨州市,荊州市,荊門市,襄樊市,黃石市,駐馬店市,信陽市,南陽市,漯河市,中衛(wèi)市,石嘴山市,海西,海南藏州,黃南州,海北,甘南,慶陽市,平?jīng)鍪?武威市,白銀市,嘉峪關(guān)市,安康市,漢中市,咸陽市,寶雞市,林芝,日喀則,昌都,迪慶,德宏,大理,西雙版納,紅河州,臨滄市,麗江市,保山市,曲靖市,黔東州,黔西州,安順市,六盤水市,涼山州,阿壩州,雅安市,廣安市,眉山市,內(nèi)江市,廣元市,德陽市,攀枝花市,成都市,�?谑�,來賓市,百色市,貴港市,北海市,桂林市,南寧市,云浮市,揭陽市,潮州市,清遠(yuǎn)市,陽江市,汕尾市,惠州市,茂名市,江門市,汕頭市,深圳市,廣州市,婁底市,永州市,益陽市,岳陽市,湘潭市,長沙市,恩施州,黃岡市,孝感市,鄂州市,十堰市,武漢市,周口市,商丘市,三門峽市,許昌市,焦作市,安陽市,鶴壁市,平頂山市,開封市,鄭州市,聊城市,濱州市,德州市,萊蕪市,日照市,泰安市,煙臺(tái)市,濰坊市,東營市,淄博市,上饒市,濟(jì)南市,撫州市,宜春市,贛州市,新余市,九江市,景德鎮(zhèn)市,寧德市,南平市,泉州市,莆田市,廈門市,宣城市,亳州市,六安市,宿州市,黃山市,滁州市,安慶市,淮北市,馬鞍山市,蚌埠市,蕪湖市,合肥市,麗水市,舟山市,衢州市,金華市,湖州市,嘉興市,寧波市,宿遷市,鎮(zhèn)江市,鹽城市,連云港市,蘇州市,徐州市,南京市,綏化市,牡丹江市,佳木斯市,大慶市,鶴崗市,哈爾濱市,白城市,白山市,遼源市,吉林市,葫蘆島市,鐵嶺市,盤錦市,阜新市,錦州市,本溪市,鞍山市,沈陽市,錫林郭勒盟,通遼市,烏海市,呂梁市,忻州市,晉中市,晉城市,陽泉市,太原市,廊坊市,承德市,保定市,邯鄲市,唐山市,寧夏,甘肅省,西藏,貴州省,重慶市,廣西,湖南省,河南省,江西省,安徽省,江蘇省,黑龍江省,遼寧省,山西省,天津市,四平市,內(nèi)蒙古,吳忠市,果洛,西寧市,定西市,商洛市,西安市,那曲,黔南州,巴中市,樂山市,賀州市,防城港市,東莞市,河源市,常德市,衡陽市,咸寧市,宜昌市,濮陽市,新鄉(xiāng)市,洛陽市,菏澤市,臨沂市,威海市,濟(jì)寧市,棗莊市,青島市,吉安市,鷹潭市,萍鄉(xiāng)市,南昌市,龍巖市,漳州市,三明市,福州市,池州市,巢湖市,阜陽市,銅陵市,淮南市,臺(tái)州市,紹興市,溫州市,杭州市,泰州市,揚(yáng)州市,淮安市,南通市,常州市,無錫市,大興安嶺,黑河市,七臺(tái)河市,伊春市,雙鴨山市,雞西市,齊齊哈爾市,延邊,松原市,通化市,長春市,朝陽市,遼陽市,營口市,丹東市,撫順市,大連市,阿拉善盟,興安盟,烏蘭察布市,巴彥淖爾市,呼倫貝爾市,鄂爾多斯市,赤峰市,頭市,呼和浩特市,臨汾市,運(yùn)城市,朔州市,長治市,大同市,衡水市,滄州市,張家口市,邢臺(tái)市,秦皇島市,石家莊市,青海省,陜西省,云南省,四川省,海南省,廣東省,湖北省,山東省,福建省,浙江省,上海市,吉林省,河北省,北京市 主站蜘蛛池模板: 99久久久A片无码国产精 | 亚洲国产日韩a精品乱码 | 美女被免费喷白浆视频 | 免费看黄色小说 | 狠狠国产欧美在线视频 | 久久精品美女久久 | 黑人玩弄极品人妻系列 | 九九免费高清在线观看视频 | 强奸日本美女小游戏 | 国产精品亚洲专一区二区三区 | 伊人久久大香线蕉综合99 | 99精品成人无码A片观看金桔 | 国产精品久久久久久久人热 | 亲胸揉胸膜下刺激视频网站APP | 国产成人无码精品久久久影院 | 嫩草AV久久伊人妇女 | 黄小说免费看 | 夜夜女人国产香蕉久久精品 | 麻豆啊传媒app黄版破解免费 | 国产精品99久久免费黑人人妻 | 亚洲AV久久无码高潮喷水 | 99久久综合国产精品免费 | 射死你天天日 | 亚洲成人日韩 | 欧美在线亚洲综合国产人 | 日韩精品AV一区二区三区 | 另类欧美尿交 | 扒开美女的内衣亲吻漫画 | 40岁东北老阿姨无码 | 灌饱娇嫩H将军公主最新章节 | 伊人角狠狠狠狠 | 黄瓜视频苹果直接安装 | AV97最新无码喷水叫床 | 草民电影网午夜伦理电影网 | 男人插曲视频大全免费网站 | 欧美午夜免费观看福利片 | 动漫在线观看免费肉肉 | 国产色播视频在线观看 | 免费国产足恋网站 | 福利片福利一区二区三区 | 国产成人无码精品久久久影院 |