首頁 | 安全文章 | 安全工具 | Exploits | 本站原創 | 關于我們 | 網站地圖 | 安全論壇
  當前位置:主頁>安全文章>文章資料>網絡安全>文章內容
自動化操控虛擬戰爭
來源:[email protected]!cn 作者:Czy 發布時間:2010-05-13  

Copyright (c) 2010 Czy Invicta <[email protected]!cn>
All rights reserved.

自動化操控虛擬戰爭

簡介
~~~~~
本文概述利用內核代碼執行對數字游戲產生的影響,這樣做的理由是如果不掃描內核的話,游戲客戶端無法掃描外掛代碼,所有代碼從進程空間無法獲取,這和通常的外掛制作方法完全不同。

開工
~~~~~
為了達到本文所說的目的,可以將所有應用層代碼移至另一臺終端機,運行游戲的終端機通過通信鏈路與第一個終端機通信。這也是內核輔助工具的通用結構,兩臺機器之間使用TCP/IP通信,游戲客戶端進程被注入代碼,該代碼不通過注入DLL或線程實現,功能也非常簡單,從而難以檢測。另外,可以通過內核隱藏注入在游戲空間的代碼。關鍵部分就是注入游戲客戶端的代碼,它和Java虛擬機很類似,注入的代碼執行通用指令,相當于一個虛擬的CPU。

然而,我們還需要做得一件事情就是如何制作一個人工智能的自動化操控代碼。代碼組織的結構為:代碼保存了一系列的函數,每個函數完成固定的功能。例如:判斷對手類型、判斷玩家事件類型、受到傷害、使用技能攻擊……等。

使用全局變量標志玩家角色。代碼能檢查各種狀態,玩家可以通過代碼配置幫助和輔助角色自動操控。

ASSIST(character name)
{

接下來使用一系列回調函數對應不同事件。

OnActivate()
//協助時調用代碼被激活或停用
}

然后使用定時器處理通用狀態,主要用于玩家角色狀態。

OnTimer()
{

變量ME代表玩家角色。

//每秒調用一次,管理所有角色
if(ME.Buffs.Has("專注光環"))
{
}
else
{

Cast命令用于釋放技能。

Cast("專注光環");
}}

使用傷害檢測函數檢查當前傷害狀態是否容易導致死亡,玩家是否需要對自身進行防護等。

OnDamage()
{
  // 損失時調用
  if(RATE > 50%)
  {
    // RATE用來衡量對生命值損失的程度
    // 在最后一秒采取措施
   
    Cast("圣盾"); //施放咒語
    RETURN;
  }

  if(ME.Health < 20%)
  {
    TargetSelf();
    Cast("圣光");
    TargetLastTarget();
  }
}

下面的代碼僅作為示例,回調函數根據每個類型的對手而不同。如果有3個對手在攻擊范圍內。回調函數對3個對手分別調用,每個一次,最終,每個對手類型對應一個回調函數。

ForHunter()
{
  // 調用任意對手,檢查誰是Hunter

在回調函數中,如果玩家瞄準了一個對手,接下來發生一系列攻擊步驟。

if(ME.Target == HUNTER)
{
  if(RANGE < 30)
  {

下列偽代碼描述了戰士如何操作可以給對手最大化傷害。

if(ME.Buffs.Has("十字軍圣印"))
{
  Cast("審判");
  Cast("命令圣印");
}

EnsureMeleeMode();

if(ME.Buffs.Has("命令圣印"))
{

下列代碼檢查代碼是否有足夠的魔法值,以及命令圣印是否小于10秒,如果條件都滿足的話則使用審判技能。

if(ME.Mana > 10%)
{
if(ME.Buffs.TimeLeft("命令圣印") < 10)
{
  Cast("審判")
  Cast("命令圣印");
}}}}
else
{
if(ME.Mana > 60%)
  CastIfNotBuffed("十字軍圣印");
}}}

有些對手有寵物,也可以在回調函數中處理寵物攻擊。本例中,代碼會自動攻擊寵物,并通知玩家角色,該對手需要優先處理。

ForHunterPet()
{
  // 調用任何Hunter的寵物

  if(RANGE < 10)
  {
 // 關閉寵物
 if(PET.Target == ME OR PET.Owner ==ME)
 {
 // 這個對手擊暈了我們的寵物,我們將攻擊對手
 Target(PET);
 Cast("正義之盾");

 // 設置目標優先權5
 PriorityTarget(PET.Owner, 5);
 SelfMessage("攻擊HUNTER");
 }
  }
}

可以為其他對手類型設置類似的回調函數。當然,這只是一種可能的外掛實現方式,本文采用這種方法的原因是每種類型的對手需要使用不同的戰斗策略。

ForMage()
{
}

ForWarlock()
{
}

//等等……


外掛用戶界面
~~~~~~~~~~~~~
本文的此部分概述如何使用基于對話框的應用實現外掛控制功能。采用基于對話框的MFC應用創建外掛程序,可以使用Visual Studio應用向導自動生成應用框架。

自動化操控虛擬戰爭

使用Visual Studio應用向導自動生成基于對話框的應用框架

生成應用框架后,可在對話框界面添加各種各樣的控件,比如列表框控件可以用于列出游戲世界對象,按鈕用于控制行為等。下圖展示了如何生成對話框程序。使用Visual Studio的向導功能生成外掛界面非常方便。

自動化操控虛擬戰爭

通過程序向導,可以在對話框中加入各種功能,這可以輕松地使外掛具備豐富的界面

然而,大多數在線游戲使用絢麗的3D渲染效果構建虛擬世界。如果要想使外掛看上去和游戲很匹配的話,外掛界面也應當有3D渲染能力。OGRE庫由一系列C++類實現,使得3D圖像操作更加容易。可以從http://www.ogre3d.org下載OGRE庫,注意,該庫的使用需要遵循LGPL許可。

另外,模型可由其它一些三維軟件進行輸出,如3ds Max、Maya,通過它們還可以制作自己的三維模型文件并使用。如下圖所示:

自動化操控虛擬戰爭

通過3ds Max三維軟件建立的角色模型

下面代碼用于包含OGRE庫頭文件,在一個3D虛擬世界里實現基本的渲染:
#include "Ogre.h"
#include "OgreConfigFile.h"
#include "OgreKeyEvent.h"
#include "OgreEventListeners.h"
#include "OgreStringConverter.h"
#include "OgreException.h"
#include <map>

using namespace Ogre;
RenderWindow *   m_renderwindow;
Root *     m_root;
Camera *    m_camera;
RenderSystem *   m_RenderSystem;
SceneManager *   m_sceneMgr;
Viewport *    m_viewport;

Entity *    m_miner;
Entity *    m-bldg;
void Init(HWND hWindow);
void Update();
void Kill();
void UpdateObjectPosition(DWORD id, POINT p);

void MoveCamera(float distance);
void RotateCamera(float degrees);
void PitchCamera(float degrees);
void LookAt(int id);

BOOL selectRenderingPlugin(char *theName);
void loadResources();
void createDebugObjectsInScene();
void createPlane();

std::map<DWORD, SceneNode *> g_points;

下面的代碼需要調用者傳遞父窗口句柄。如果使用MFC框架創建應用,可以通過對話框對象的成員m_hWnd來獲取窗口句柄。下面的代碼創建OGRE 3D渲染窗口,放置該窗口在父窗口上。

void Init(HWND hWindow)
{
OGRE需要一個Root對象必須首先創建。
m_root=new Root("",""); //Root沒有配置文件

現在加載兩個圖像子系統,使用OpenGL。

m_root->loadPlugin("RenderSystem_Direct3D9");
m_root->loadPlugin("RenderSystem_GL");

// 使用OpenGL渲染
if(FALSE == selectRenderingPlugin("OpenGL")) return;

調用函數initialise后加載資源。資源包含場景中的紋理結構等素材。可以從網絡下載到很多工具,用于將對象轉換為OGRE資源文件。

m_root->initialise(false);
loadResources();

接下來創建渲染窗口。OGRE負責創建渲染窗口,開發人員只需使用getCustomAttribute獲取創建的窗口句柄即可。獲取窗口句柄后,使用SetWindowLong()修改窗口風格為WS_CHILD。
m_renderwindow =
 m_root->createRenderWindow(
"攝影機",
280, //寬
290, //高
false, //全屏或不是
0); //可選擇
HWND aHandle;
m_renderwindow->getCustomAttribute("HWND", &aHandle);
SetParent(aHandle, hWindow);
SetWindowLong(aHandle, GWL_STYLE,WS_CHILD | WS_BORDER | WS_VISIBLE);

現在獲取SceneManager,SceneManager為OGRE中非常重要的對象,該對象直接管理所有3D對象。

m_sceneMgr = m_root->getSceneManager(ST_EXTERIOR_CLOSE);

現在創建攝影機,用于移動場景位置,修改視角和觀察點。可以使用攝影機查看不同對象。

m_camera = m_sceneMgr->createCamera("MainCam");
m_camera->setNearClipDistance(1.0f);
m_camera->setFarClipDistance(50000.0f);

同時需要建立攝影機的視圖通道:

m_viewport = m_renderwindow->addViewport(m_camera);
m_camera->setAspectRatio(Real(m_viewport->getActualWidth()) / Real(m_viewport->getActualHeight()));

最后,加載資源和對象到創建的世界中。

//加載默認對象
m_miner = m_sceneMgr->createEntity("miner", "knot.mesh");
m_miner->setMaterialName("MinerMaterial");

m_bldg = m_sceneMgr->createEntity("bldg", "knot.mesh");
createPlane();
createDebugObjectsInScene();
}
void Kill()
{
 HWND aHandle;
 m_renderwindow->getCustomAttribute("HWND", &aHandle);
 DestroyWindow(aHandle);
}

void Update()
{
 m_renderwindow->reposition(260,27);
 m_renderwindow->resize(280.290);
 m_renderwindow->update();
}

// 用于測試,創建一個調試對象
void createDebugObjectsInScene()
{
 Entity* myKnot =
  m_sceneMgr->createEntity("knot", "knot.mesh");
 myKnot->setCastShadows(true);

 SceneNode* myNode1 =
  m_sceneMgr->getRootSceneNode()->createChildSceneNode("node_1");
 myNode1->attachObject(myKnot);

 // 設置節點的位置
 myNode1->setPosition(Vector3(0,0,0));
 m_camera->setPosition(Vector3(0,300,0));
 m_camera->lookAt(Vector3(0,0,0));

 // 設置環境光
 m_sceneMgr->setAmbientLight(ColourValue(0.4,0.4,0.1));

 // 創建一個燈光
 Light* l = m_sceneMgr->createLight("MainLight");
 l->setType(Light::LT_POINT);
 l->setDiffuseColour(200,200,200);
 l->setPosition(30,30,30);
}
BOOL selectRenderingPlugin(char *theName)
{
 assert(m_root != NULL);

 // 列出它們
 RenderSystemList *rList = m-root->getAvailableRenderers();
 RenderSystemList::iterator it = rList->begin();

 // 重復它們的實例
 while(it != rList->end())
 {
   RenderSystem *rSys = *it;
   it++;
   if(rSys->getName().find(theName))
  {
    m_root->setRenderSystem(rSys);
    m_RenderSystem = rSys;
    break;
  }
 }

 // 如果我們不能找到它們如何結束
 if(m_root->getRenderSystem() == NULL)
 {
   assert(m_RenderSystem == NULL);
   retrun FALSE;
 }
 retrun TRUE;
}

void UpdateObjectPosition(DWORD id, POINT p)
{
 if(g_point.find(id) == g_points.end())
 {
   char node_name[64];
   _snprintf(node_name, 62, "node_%d", id);

   // 它不存在,創建一個新的對象
   SceneNode* a_node = m_sceneMgr->getRootSceneNode()->createChildSceneNode(node_name);
   Entity *e = m_sceneMgr->createEntity(node_name, "ninja.mesh");
   e->setMaterialName("MinerMaterial");
   a_node->attachObject(e);
   a_node->setPosition(Vector3(p.x, 0, p.y));
   g_points[id] = a_node;
 }
 else
 {
   //它存在,所以更新其位置
   SceneNode *a_node = (SceneNode *)g_points[id];
   a_node->setPosition(Vector3(p.x, 0, p.y);
 }
}

void loadResources()
{
 ResourceGroupManager::getSingleton().addResourceLocation(
  "./media/models",
  "FileSystem",
  "General");

 ResourceGroupManager::getSingleton().addResourceLocation(
  "./media/scripts",
  "FileSystem",
  "General");

 ResourceGroupManager::getSingleton().addResourceLocation(
  "./media/textures",
  "FileSystem",
  "General");

 ResourceGroupManager::getSingleton().
  initialiseAllResourceGroups();
}

void MoveCamera(float distance)
{
 m_camera->moveRelative(Vector3(0,0,distrance));
 char _t[255];
 Vector3 v = m_camera->getPosition();
 _snprintf(_t, 252, "camera is %f %f %f", v.x, v.y, v.z);
 OutputDebugString(_t);
}

void RotateCamera(float degrees)
{
 m_camera->yaw(Radian(degrees));
 char _t[255];
 Vector3 v =m_camera->getDirection();
 _snprintf(_t,252,"camera direction at %f %f %f", v.x, v.y, v.z);
 OutputDebugString(_t);
}

void PitchCamera(float degrees)
{
 m_camera->pitch(Radian(degrees));
 char _t[255];
 Vector3 v = m_camera->getDirection();
 _snprintf(_t,252,"camera direction at %f %f %f",v.x, v.y, v.z);
 OutputDebugString(_t);
}

Void createPlane()
{
 Plane plane;
 plane.normal = Vector3::UNIT_Y;
 plane.d = 0;
 MeshManager::getSingleton().createPlane("plane_1",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,50000,50000,10,10,true,1,50,50,Vector3::UNIT_Z);

 Entity *aPlaneEntity_1 = m_sceneMgr->createEntity("e_plane_1","plane_1");
 aPlaneEntity_1->setCastShadows(false);
 SceneNode *aSceneNode_1 = m_sceneMgr->getRootSceneNode()->createChildSceneNode("n_plane_1");
 aSceneNode_1->attachObject(aPlaneEntity_1);
 aPlaneEntity_1->setMaterialName("PlaneMaterial");
 aSceneNode_1->setPosition(0,-1000,0);
}

void LookAt(int id)
{
 SceneNode *a_node = (SceneNode *)g_points[id];
 Vector3 v= a_node->getPosition();
 m_camera->setPosition(Vector3(v.x,v.y+500,v.z-200));
 m_camera->lookAt(v);
}

可以將用戶界面編寫的非常復雜,甚至達到重新創建客戶端的程度。實際上,一些外掛確實可以做到完全替換客戶端。


尾聲
~~~~~
本文簡單介紹了內核模式外掛和外掛用戶界面,外掛程序編寫是游戲逆向分析的中心議題,玩游戲的過程中要是有程序能自動操控虛擬角色進行清怪并贏得游戲是件很舒服的事情,特別是這種自動程序還可以帶來金錢利益的話就更再好不過了。本文概述的知識不針對某一款游戲,實際上,本文所概述的知識適用于任何在線數字游戲。

 

下載PDF版 http://www.esnips.com/doc/f145cc80-3658-4ff8-a507-67455c52d828/自動化操控虛擬戰爭

 

# HACKER NETSPY [CZY]


 
[推薦] [評論(0條)] [返回頂部] [打印本頁] [關閉窗口]  
匿名評論
評論內容:(不能超過250字,需審核后才會公布,請自覺遵守互聯網相關政策法規。
 §最新評論:
  熱點文章
·一句話木馬
·samcrypt.lib簡介
·教你輕松查看QQ空間加密后的好友
·web sniffer 在線嗅探/online ht
·SPIKE與Peach Fuzzer相關知識
·Cisco PIX525 配置備忘
·用Iptables+Fedora做ADSL 路由器
·檢查 Web 應用安全的幾款開源免
·asp,php,aspx一句話集合
·Md5(base64)加密與解密實戰
·NT下動態切換進程分析筆記
·風險評估中的滲透測試
  相關文章
·一句話木馬
·IDS規避與對策
·網絡滲透測試指導手冊
·系統監控:蜜罐分析技術
·SPIKE與Peach Fuzzer相關知識
·QQ2009正式版SP4文本信息和文件
·一臺肉雞能創造多少價值?為您講
·關于流量,木馬,插件,網馬賺錢
·【翻譯】 Metasploit:重現犯罪
·Soc運營中心的一次病毒處理
·檢查 Web 應用安全的幾款開源免
· 抵抗DDoS防火墻更新換代
  推薦廣告
CopyRight © 2002-2020 VFocuS.Net All Rights Reserved
期本期特码