Upgrade to Pro — share decks privately, control downloads, hide ads and more …

從技術面簡介線上遊戲外掛

 從技術面簡介線上遊戲外掛

從技術面探討遊戲外掛運行的原理,討論三大類遊戲外掛:記憶體修改外掛、自動化外掛、封包修改外掛;尤其著重於記憶體修改外掛及自動化外掛,介紹這些外掛一般撰寫的所需要用到的 API 以及技巧。另外也會對逆向工程以及 Rootkit 兩項撰寫遊戲外掛必備的技術做簡介,以方便觀眾了解本篇中其他內容。最後探討反外掛程式,他們透過哪些方式來防堵外掛,例如 Signature-based Detection 以及 API Hooking,再來討論外掛作者可以使用哪些方法來破解這些方法。

Chen John L

March 15, 2014
Tweet

More Decks by Chen John L

Other Decks in Programming

Transcript

  1. Who am I? • 2006 年左右活耀於 Cheat Engine Forum, 為其

    Underground 成員 • 當年主要玩楓之谷外掛 , 專門破解 nProtect GameGuard (rev641~12xx) • MzBot 作者
  2. Who am I? • 台科大不分系大五 – 主修資工 , 電子 ,

    輔修機械 , 企管 • chr00t 資安社群成員 • 2010 趨勢雲端程式競賽第一名 • 2013 International Future Energy Challenge – Grand Prize
  3. 自動化外掛 (俗稱 按鍵精靈 ) 記憶體修改外掛 封包修改外掛 是否有作弊的效果 ? 無 有

    理論上是否能防堵 ? 不能 能 運作原理 無聊的事情 由電腦代勞 欺騙遊戲伺服器
  4. INPUT inp[2]; inp[0].type = inp[1].type = INPUT_KEYBOARD; inp[0].ki.wScan = inp[1].ki.wScan

    = 0; inp[0].ki.time = inp[1].ki.time = 0; inp[0].ki.dwExtraInfo = 0; inp[1].ki.dwExtraInfo = 0; inp[0].ki.wVk = inp[1].ki.wVk = VK_RETURN; inp[0].ki.dwFlags = 0; inp[1].ki.dwFlags = KEYEVENTF_KEYUP; SendInput( 2, inp, sizeof(INPUT) );
  5. HDC GetDC( _In_ HWND hWnd ); COLORREF GetPixel( _In_ HDC

    hdc, _In_ int nXPos, _In_ int nYPos );
  6. 遊戲 伺服器 遊戲 客戶端 螢幕上有 : 怪 A, 怪 B,

    玩家 玩家攻擊怪 A 傷害 9999 OS: 你說的我 都相信 ! 超自然嘛 ~ 玩家資訊 : … 攻擊力 50+/-15 玩家輸入 攻擊怪 A 計算傷害 = 56 記憶體修改 封包修改 移除怪 A 經驗值 +xx
  7. 常見指令 • MOV 目的地 , 來源 ( 把來源複製到目的地 ) –

    MOV EAX, EBX => EAX = EBX; – MOV EAX, [0x005C] => EAX = *((int*)0x005C); • ADD 目的地 , 來源 ( 把來源加到目的地 ) – ADD ECX, 5 => ECX += 5; – ADD ECX, [x] => ECX += x; • SUB, XOR, OR, AND... 等指令 , 一樣的用法
  8. 常見指令 • CMP A, B ( 比較 A 跟 B,

    結果寫到 FLAGS) – CMP EAX, 5 – CMP ECX, EDX • JMP 地址 ( 跳到地址去 ) – JMP 0x7FFE0300 • JE 地址 ( 如果上次比較時 , A==B, 就跳 ) – JE 0x00401753 • JNE, JGE, JG, JL, JLE... 等等是不同的比較狀 況 C F P F A F Z F S F
  9. if ( x == 3 ) { // ooo }

    else { // xxx } MOV EAX, [x] CMP EAX, 3 JNE NEXT ; ooo JMP END NEXT: ; xxx END:
  10. 堆疊 ... :0x080 ... :0x07C ... :0x078 ... :0x074 ...

    :0x070 ... :0x06C ... :0x068 ... :0x064 ESP
  11. 常見指令 • PUSH 來源 ( 把來源 Push 到堆疊上 ) –

    PUSH 5 => ESP-=4; *((int*)ESP)=5; – PUSH EAX => ESP-=4; *((int*)ESP)=EAX; • POP 目的地 ( 把堆疊最上面 Pop 到目的 地 ) – POP EAX => EAX=*((int*)ESP); ESP+=4; • CALL 地址 ( 呼叫在地址的函數 ) – CALL 0x004027A0 => PUSH EIP, JMP 0x004027A0 • RET ( 從目前函數 Return) – RET => POP EIP
  12. 函數呼叫 新函數變數 :0x080 原函數 EBP :0x07C RET 地址 :0x078 新函數參數

    :0x074 新函數參數 :0x070 新函數參數 :0x06C 原函數變數 :0x068 原函數變數 :0x064 ESP
  13. ... DEC [EBX+047C] ... ... FF 8B 7C 04 00

    00 ... ... NOP NOP NOP NOP NOP NOP ... ... 90 90 90 90 90 90 ...
  14. ... DEC [EBX+047C] ... ... FF 8B 7C 04 00

    00 ... ... NOP NOP NOP NOP NOP NOP ... ... 90 90 90 90 90 90 ...
  15. if ( Player.ID != 1 ) { Player.health--; } ...

    MOV EAX, [EBX+010] CMP EAX, 1 JE END DEC [EBX+047C] END: ...
  16. alloc(newmem,2048) label(returnhere) label(originalcode) label(exit) Newmem: mov EAX, [EBX+010] cmp EAX,

    1 je END dec [EBX+047C] end: jmp returnhere 00426E99: jmp newmem nop returnhere:
  17. ... 00426E99: DEC [EBX+047C] ... ... 00426E99: JMP Newmem ...

    Newmem: mov EAX, [EBX+010] cmp EAX, 1 je END dec [EBX+047C] end: jmp returnhere
  18. int main( int argc, char** argv ) int CALLBACK WinMain(

    HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
  19. BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )

    { if ( fwdReason == DLL_PROCESS_ATTACH ) { CreateThread( ... ); } return TRUE; };
  20. LPVOID WINAPI VirtualAlloc( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_

    DWORD flAllocationType, _In_ DWORD flProtect ); unsigned char *mem = VirtualAlloc( NULL, 2048, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); mem[0] = ...;
  21. 載入 DLL 前 : … CALL printf … printf: jmp

    xxxx 載入 DLL 後 : … CALL printf … printf: jmp 10A0573C
  22. OEP: PUSH XXX PUSH XXX CALL XXX XOR EBX, EBX

    PUSH EBX MOV EDI, [GetModuleHandleA] CALL EDI ...
  23. .exe User mode (Ring 3) Kernel mode (Ring 0) ntoskrnl.exe

    Kernel32.dll User32.dll GDI32.dll ntdll.dll SSDT
  24. Kernel32.dll • OpenProcess() • ReadProcessMemory() • WriteProcessMemory() • VirtualAlloc() •

    CreateThread() • TerminateProcess() User32.dll • CreateWindow() • PostMessage() • SendInput() • GetDC() GDI32.dll • bitblt()
  25. .exe User mode (Ring 3) Kernel mode (Ring 0) ntoskrnl.exe

    Kernel32.dll User32.dll GDI32.dll ntdll.dll SSDT Detour/IAT Hook Detour/IAT Hook
  26. typedef void(*FuncPtr)( … ); FuncPtr SSDT[xxx] = { KernelFunction1, KernelFunction2,

    … } void onSysenter( int callID, … ) { (SSDT[callID])( … ); }
  27. .exe User mode (Ring 3) Kernel mode (Ring 0) ntoskrnl.exe

    Kernel32.dll User32.dll GDI32.dll ntdll.dll SSDT SSDT Hook
  28. .exe User mode (Ring 3) Kernel mode (Ring 0) ntoskrnl.exe

    Kernel32.dll User32.dll GDI32.dll ntdll.dll SSDT Detour Hook