當前位置:湖南陽光電子技術學校文章資訊技術園地電腦維修技術
招生辦公室電話:13308461099 13807313137 全國免費電話:13807313137

“變速齒輪”再研究

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

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

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

  在動手之前,我又把《手記》看了一遍,這次可就清楚多了:通過調用門跳到Ring0級代碼段,修改各系統時間相關函數的前8個字節為jmp指令,轉跳到“齒輪”映射到2G之上的代碼,達到截獲對各系統時間相關函數的調用的目的。但同時我的疑惑也更明確了:
  1.“齒輪”怎樣建立指向自己映射到2G以上內存的代碼的調用門描述符的;
  2.“齒輪”怎樣將自己的代碼映射到2G以上線性地址的;
  3.映射到2G之上的代碼是怎樣做到在代碼基址更改的情況仍能正確運行的

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

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

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

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

 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函數的執行情況。

  我先寫了個Win32 APP (以下簡稱APP),當左擊客戶區時會調用timeGetTime并將返回的結果輸出至客戶區。運行這個程序,打開“齒輪”,改變當前速度。

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

  我仔細分析了一下,“齒輪”修改返回值的公式如下:
  倍數*(返回值-第一次調用timeGetTime的返回值)
修改后的返回值=---------------------------------------------------+上一次修改后的返回值
  100000
  公式中“上次修改后的返回值”是自己猜測的未經證實,僅供參考。

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

  既然“齒輪”中調用了CreateFileMappingA,我想其安裝調用門,映射代碼的初始化部分應該就在調用該函數代碼的附近。好,沿著這個思路,呼出Softice,在CreateF ileMappingA處設置斷點,將“齒輪”關閉后再運行。Softice跳出,停在了CreateFile MappingA處,F11回到“齒輪”的代碼?吹搅恕褒X輪”調用CreateFileMappingA的形式如下:

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

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

  接下來“齒輪”將原“齒輪”exe中的截獲API的代碼逐字節拷貝到映射區域去。至此,“齒輪”已經將關鍵代碼映射到2G以上線性地址中了。

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

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

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

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

  0:0 call 5
  0:5 pop esi

  現在esi中的值就是5了,哈哈!

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

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

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

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

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

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

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

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

   后要說的就是個人水平有限,文中難免出現錯誤,歡迎大家討論!^_^

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

附B:
 “齒輪”關鍵代碼完全注釋
 一、初始化部分(從"齒輪"調用CreateFileMappingA函數開始分析)
  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]
 ;調用CreateFileMappingA
 ;調用形式如右: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
  ;申請基址加0x10000
  0167:00401B3EMOV [EBP-14],EDX
  0167:00401B41MOV EAX,[EBP-14]
  0167:00401B44PUSHEAX;映射文件基址
  0167:00401B45PUSH00 ;映射的字節數
  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]
  ; 調用形式如右:MapViewOfFileEx(EDX,2,0,0,0,EAX)
  0167:00401B5DMOV ECX,[EBP-30]
  ;[EBP-30]為即將映射到2G之上
  0167:00401B60MOV [ECX+0000036C],EAX
  ; 的代碼的數據域的起始地址
  0167:00401B66MOV EDX,[EBP-30]
  0167:00401B69CMP DWORD PTR [EDX+0000036C],00
  ;檢查MapViewOfFileEx
  0167:00401B70JZ00401B74
  ;返回值,若為0則繼續調
  0167:00401B72JMP 00401B76 ;調用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
  ;將初次調用timeGetTime
 0167:00401BA0MOV ECX,[EBP-08]
  ;的返回值保存到[EBP-14]
 0167:00401BA3MOV EDX,[EBP-14]
  ;以及映射文件基址+FF30處
 0167:00401BA6MOV [ECX+0000FF30],EDX
 ...省略的代碼類似的保存調用初次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為遠調用的指令碼
 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為調用門描述符的索引
 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個字節
 0167:00401CA8MOV [EBP-14],EDX ;
 0167:00401CABMOV ESI,0040213B
  ;要復制的代碼的起始地址
 0167:00401CB0MOV EDI,[EBP-08]
  ;要復制代碼的目標地址(映射區域中)
 0167:00401CB3MOV ECX,00402688
  ;402688為要復制的代碼的末地址
 0167:00401CB8SUB ECX,ESI
 0167:00401CBAREPZMOVSB;將代碼全部復制到映射區域
 0167:00401CBCSGDTFWORD PTR [EBP-1C];這句開始就很關鍵了
 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 ;以上計算出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
 ;得到當前代碼段描述符號
 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此時為LDT線性基址
 0167:00401D1EMOV EAX,[EBP-30]
 0167:00401D21MOV EAX,[EAX+00000370]
;EAX此時為LDT線性基址

 0167:00401D27MOV ESI,[EDX+ECX]
 0167:00401D2AMOV [EAX+08],ESI
 0167:00401D2DMOV ECX,[EDX+ECX+04]
  ;以上將當前代碼段描述符復制到
 0167:00401D31MOV [EAX+0C],ECX;LDT第1項
 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項的DPL為0,則當由調用門轉到該段代碼時即獲得RING0權限
 0167:00401D4FMOV EAX,[EBP-0C]
 0167:00401D52ADD EAX,10 ;獲得LDT中索引為2的調用門地址
 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;調用門修改完畢
 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函數前8個字節指令
 ...省略部分依次保存GetTickCount,GetMessageTime,timeSetEvent,timeGetSystemTime , QueryPerformanceCounter前8個字節指令
 0167:00401E6DMOV BYTE PTR [ECX+0000FE90],E9
 0167:00401E74MOV EAX,00402165
 0167:00401E79SUB EAX,0040213B
  ;EAX為截獲代碼在映射代碼中的偏移
 0167:00401E7EADD EAX,ECX;計算出截獲代碼的線性入口地址
 0167:00401E80SUB EAX,[WINMM!timeGetTime]
 0167:00401E86SUB EAX,05 ;JMP指令總長5個字節
 0167:00401E89MOV [ECX+0000FE91],EAX
  ;計算生成從timeGetTime跳到截獲代碼的JMP指令并保存
 
 ...省略部分依次計算并生成GetTickCount,GetMessageTime,timeSetEvent,timeGetSystemTime , QueryPerformanceCounter跳到截獲代碼的JMP指令并保存
 
 0167:00401F58CLI;關閉中斷,謹防修改代碼時發生意外
 0167:00401F59MOV EAX,004021F3 ;
 0167:00401F5ESUB EAX,0040213B;計算子程序在映射代碼中的偏移
 0167:00401F63ADD EAX,[EBP-08];EAX=8xxx 00B8
 0167:00401F66PUSHEAX;傳入參數EAX為修改timeGetTime代碼的
 ;子程序入口地址
 0167:00401F67MOV EAX,[EBP-08];調用8xxx 0000
 0167:00401F6ACALLEAX ;返回時timeGetTime首指令被更改
 
  ...省略部分依次修改GetTickCount,GetMessageTime,timeSetEvent,
  timeGetSystemTime , QueryPerformanceCounter函數的首指令
 
 0167:00401FF SETI;設置中斷,初始化代碼結束
  二、截獲時間函數部分(以timeGetTime為例子,代碼以跟蹤順序列出)
 timeGetTime
  JMP 832A 002A
  ;這是timeGetTime被修改后的首指令
 0167:832A 002A CLI
  ;此時[esp]=40BF2C,即游戲程序中調用timeGetTime函數的下一條指令
  ...(6個)各寄存器分別入棧 且MOV EBP,ESP
 0167:832A 0033 CALL 832A 0038
  ;將當前EIP入棧(即下一條指令的地址)
 0167:832A 0038 POPEDI ;取出當前指令地址
  XORDI , DI
  MOVESI , EDI
 ;將64K內存首地址賦給ESI
 ;此時ESI=EDI=832A 0000
  ADDESI , 0040 2102
  SUBESI , 0040 213B ;求出映射代碼首地址
  PUSH ESI
 0167:832A 004B CALL EDI;ESI為傳進的參數
 ;返回時已經將timeGetTime代碼還原
 0167:832A 004D CALL 832A 0052;
 0167:832A 0052 POPEDI
  XORDI ,DI;故技重施
  CALL [EDI + 0000FEED];調用原timeGetTime函數
  SUBEAX,[EDI + 0000 FF30]
  ;減去第一次調用timeGetTime的結果
  MULDWORD PTR [EDI+0000 FE30]
  ;乘以用戶所指定的倍數
  MOVEBX ,00100000
  DIVEBX
  ;除以常數100000
  ADDEAX ,[EDI+ 0000FE20]
  MOVEAX,004021F3
  SUBEAX,0040213B
  ADDEAX,EDI
  ;以上指令為修改timeGetTime函數返回值
  PUSH EAX
  ;EAX為傳進的參數
  CALL EDI
  ;返回時又將timeGetTime首指令換成JMP
  ...恢復各寄存器的值,EAX中為修改后的返回值
  RET ;此時[ESP]=40BF2C,執行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的調用門描述符的偏移改為傳入的參數
 ...
  MOVEAX,0000 0F00
  CALL EAX
  ;調用子程序修改timeGetTime代碼
 0167:832A 0027 , ;RET4
  ;彈出參數,返回
  ;
 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個字節為原timeGetTime函數的指令
  EDI+0000 FEE0保存著timeGetTime函數的入口地址
  以上即恢復timeGetTime前8個字節的代碼
  ;
 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個字節保存著JMP 832A 002A 指令
  是由“齒輪”初始化部分代碼計算出來的,以上代碼將JMP 832A 002A
  寫入timeGetTime函數
  湖南省陽光電子技術學校常年開設:手機維修培訓、家電維修培訓、電工培訓、電腦維修培訓、焊工培訓--面向全國火爆招生!網址:http://www.hnygpx.com 報名電話:13807313137)。安置就業。考試合格頒發全國通用權威證書。采用我校多年來獨創的“模塊教學法”,理論與實踐相結合、原理+圖紙+機器三位一體的教學模式,半天理論,半天實踐,通俗易懂,確保無任何基礎者也能全面掌握維修技能、成為同行業中的佼佼者。工作(一期不會,免費學會為止)。

Tags:變速齒輪 研究

作者:佚名
[]
電工培訓學校 電動車維修學校 摩托車維修學校 摩托車維修培訓 手機維修培訓 家電維修培訓 電腦維修培訓 電動工具維修培訓 液晶電視維修培訓 安防監控培訓 空調維修培訓 網絡營銷培訓 網站設計培訓 淘寶網店培訓 電器維修培訓 家電維修學校 電工培訓 焊工培訓 電工學校 電工培訓學校 電動車維修學校 摩托車維修學校 摩托車維修培訓 手機維修培訓 家電維修培訓 電腦維修培訓 電動工具維修培訓 液晶電視維修培訓 安防監控培訓 空調維修培訓 網絡營銷培訓 網站設計培訓 淘寶網店培訓 電器維修培訓 家電維修學校 電工培訓 焊工培訓 電工學校 電工培訓學校 電動車維修學校 摩托車維修學校 摩托車維修培訓 手機維修培訓 家電維修培訓 電腦維修培訓 電動工具維修培訓 液晶電視維修培訓 安防監控培訓 空調維修培訓 網絡營銷培訓 網站設計培訓 淘寶網店培訓 電器維修培訓 家電維修學校 電工培訓 焊工培訓 電工學校 電工培訓學校 電動車維修學校 摩托車維修學校 摩托車維修培訓 手機維修培訓 家電維修培訓 電腦維修培訓 電動工具維修培訓 液晶電視維修培訓 安防監控培訓 空調維修培訓 網絡營銷培訓 網站設計培訓 淘寶網店培訓 電器維修培訓 家電維修學校 電工培訓 焊工培訓 電工學校
中山市,固原市,銀川市,玉樹,海東,隴南市,酒泉市,張掖市,天水市,金昌市,蘭州市,榆林市,延安市,渭南市,銅川市,阿里,山南,拉薩市,怒江,文山州,楚雄州,普洱市,昭通市,玉溪市,昆明市,畢節,銅仁,遵義市,貴陽市,甘孜州,資陽市,達州市,宜賓市,南充市,遂寧市,綿陽市,瀘州市,自貢市,三亞市,崇左市,河池市,玉林市,欽州市,梧州市,柳州市,梅州市,肇慶市,湛江市,佛山市,珠海市,韶關市,湘西州,懷化市,郴州市,張家界市,邵陽市,株洲市,仙桃市,隨州市,荊州市,荊門市,襄樊市,黃石市,駐馬店市,信陽市,南陽市,漯河市,中衛市,石嘴山市,海西,海南藏州,黃南州,海北,甘南,慶陽市,平涼市,武威市,白銀市,嘉峪關市,安康市,漢中市,咸陽市,寶雞市,林芝,日喀則,昌都,迪慶,德宏,大理,西雙版納,紅河州,臨滄市,麗江市,保山市,曲靖市,黔東州,黔西州,安順市,六盤水市,涼山州,阿壩州,雅安市,廣安市,眉山市,內江市,廣元市,德陽市,攀枝花市,成都市,?谑,來賓市,百色市,貴港市,北海市,桂林市,南寧市,云浮市,揭陽市,潮州市,清遠市,陽江市,汕尾市,惠州市,茂名市,江門市,汕頭市,深圳市,廣州市,婁底市,永州市,益陽市,岳陽市,湘潭市,長沙市,恩施州,黃岡市,孝感市,鄂州市,十堰市,武漢市,周口市,商丘市,三門峽市,許昌市,焦作市,安陽市,鶴壁市,平頂山市,開封市,鄭州市,聊城市,濱州市,德州市,萊蕪市,日照市,泰安市,煙臺市,濰坊市,東營市,淄博市,上饒市,濟南市,撫州市,宜春市,贛州市,新余市,九江市,景德鎮市,寧德市,南平市,泉州市,莆田市,廈門市,宣城市,亳州市,六安市,宿州市,黃山市,滁州市,安慶市,淮北市,馬鞍山市,蚌埠市,蕪湖市,合肥市,麗水市,舟山市,衢州市,金華市,湖州市,嘉興市,寧波市,宿遷市,鎮江市,鹽城市,連云港市,蘇州市,徐州市,南京市,綏化市,牡丹江市,佳木斯市,大慶市,鶴崗市,哈爾濱市,白城市,白山市,遼源市,吉林市,葫蘆島市,鐵嶺市,盤錦市,阜新市,錦州市,本溪市,鞍山市,沈陽市,錫林郭勒盟,通遼市,烏海市,呂梁市,忻州市,晉中市,晉城市,陽泉市,太原市,廊坊市,承德市,保定市,邯鄲市,唐山市,寧夏,甘肅省,西藏,貴州省,重慶市,廣西,湖南省,河南省,江西省,安徽省,江蘇省,黑龍江省,遼寧省,山西省,天津市,四平市,內蒙古,吳忠市,果洛,西寧市,定西市,商洛市,西安市,那曲,黔南州,巴中市,樂山市,賀州市,防城港市,東莞市,河源市,常德市,衡陽市,咸寧市,宜昌市,濮陽市,新鄉市,洛陽市,菏澤市,臨沂市,威海市,濟寧市,棗莊市,青島市,吉安市,鷹潭市,萍鄉市,南昌市,龍巖市,漳州市,三明市,福州市,池州市,巢湖市,阜陽市,銅陵市,淮南市,臺州市,紹興市,溫州市,杭州市,泰州市,揚州市,淮安市,南通市,常州市,無錫市,大興安嶺,黑河市,七臺河市,伊春市,雙鴨山市,雞西市,齊齊哈爾市,延邊,松原市,通化市,長春市,朝陽市,遼陽市,營口市,丹東市,撫順市,大連市,阿拉善盟,興安盟,烏蘭察布市,巴彥淖爾市,呼倫貝爾市,鄂爾多斯市,赤峰市,頭市,呼和浩特市,臨汾市,運城市,朔州市,長治市,大同市,衡水市,滄州市,張家口市,邢臺市,秦皇島市,石家莊市,青海省,陜西省,云南省,四川省,海南省,廣東省,湖北省,山東省,福建省,浙江省,上海市,吉林省,河北省,北京市 主站蜘蛛池模板: 一区二区三区福利视频 | 久久婷婷丁香五月色综合啪免费 | 果冻传媒视频在线播放 | 成人久久欧美日韩一区二区三区 | 久久精品国产色蜜蜜麻豆国语版 | 考好老师让你做一次H | 手机国产视频福利 | 恋夜秀场支持安卓版全部视频国产 | 免费国产综合视频在线看 | 少女亚洲free | 亚洲精品线在线观看 | 最新高清无码专区在线视频 | 欧美5g影院天天爽天天看 | 国产精品黄色大片 | 男女免费观看在线爽爽爽视频 | 人妻熟妇乱又伦精品视频中文字幕 | 亚洲九九精品 | 伊人网综合 | 四虎影视国产精品亚洲精品 | 日韩午夜影院 | 亚洲精品久久久久无码AV片软件 | 3D漫画H精品啪啪无码 | 青草国产超碰人人添人人碱 | 麻豆产精品一二三产区区 | 99视频在线精品免费观看18 | a久久99精品久久久久久蜜芽 | 2019欧洲hd | 国产在线视频分类精品 | 江苏电台在线收听 | 欧美人成人亚洲专区中文字幕 | 欧美大片免费观看 | 欧美91精品久久久久网免费 | 亚洲永久精品ww47 | 91综合久久久久婷婷 | YIN荡的老师系列第6部分视频 | 又亲又揉摸下面视频免费看 | 天天影视色欲 影视 | 91热久久免费精品99 | 男人边吃奶边摸边做刺激情话 | 超碰在线视频人人AV | 男女高潮又爽又黄又无遮挡 |