aliast Опубликовано 9 февраля, 2011 Поделиться Опубликовано 9 февраля, 2011 Статья. Нахождение указателей на устройство на примере игры SoldatДа, понаделали они там глобальных изменений (это я про хостера своего бесплатного) и всё поудалялось... потом если найду статью перезалью. А пока вот статья про поиск Device pointers на примере игры Soldat. Что такое Device pointer я толком не понял, что-то связанное с DirectX программированием и созданием графических читов (wallhack - видеть сквозь стены и др.) путём перехвата DirectX функций. В общем для меня это всё тёмный лес, но статью понять можно. Осталось найти ей применение на практике =)Скажу сразу, в игре Soldat имеется защита от читинга и под голым Olly запустить игру я не смог, пока не скачал с нашего сайта сборку shadow (скачать сборку) с кучей плагинов и игра сразу запустилась. Оригинал статьиНахождение указателей на устройство на примере игры SoldatИтак, нам понадобится отладчик (OllyDbg – сборка shadow с набором плагинов) и DirectX8 игра (в данной статье речь пойдёт об игре Soldat). Можно применить всё нижеописанное и для DirectX9 игры, принцип тот же.Открываем игру в OllyDbg (игра Soldat запакована, поэтому когда нас спросят о проведении анализа кода, отказываемся):Рис.1Теперь запускаем игру кнопкой f9. Если у вас невзломанная версия игры, то перед запуском самой игры выскочит такое окошко:Рис.2И вот после этого окошка можно приступать к поиску Direct3D8 интерфейса, для чего установите бряк на вызов функции Direct3DCreate8 (или 9 в случае с DirectX9 игрой). Бряк можно поставить, введя в Commandline "bp Direct3DCreate8" (без кавычек):Рис.3Если у вас нет строки Commandline для ввода команд (обычно она располагается внизу под окном дампа), его можно вызвать через меню "Plugins->2 Command line->Command line" (где 2 может быть другой цифрой, у меня плагин был под номером 7).Поставив бряк, нажмите кнопку «OK» («Готово» в русской версии) в окне игры с просьбой о регистрации.Через 1-2 секунды сработает бряк внутри функции Direct3DCreate8 внутри библиотеки d3d8.dll (возможно, чтобы добраться до бряка понадобится пару раз нажать f9, только не перепрыгните наш бряк!): Рис.4Чтобы найти место вызова функции, нажмём Ctrl+f9 и выполним всю функцию до инструкции «ret»:Рис.5Теперь нажимаем f7 и возвращаемся в место вызова (вызов будет находиться строкой выше, на скриншоте вызов обозначен красной стрелкой):Рис.6Чтобы найти функцию IDirect3D->CreateDevice, которая нам понадобится при поиске device указателя, я объясню, что за код идёт после вызова Direct3DCreate8.Две инструкции mov вначале просто перемещают значения из регистра в регистр и нам это неинтересно. Первый call по всей видимости вызывает игровую функцию для проверки успешной инициализации Direct3D; это тоже нам не нужно. Инструкции cmp и je совершают прыжок, если D3D инциализировался с ошибкой. И это нам не нужно, но вот дальше смотрим внимательно. Инструкция "MOV EAX,DWORD PTR DS:[EBX]" идентична команде в с/с++: "eax = *ebx;". Она разыименовывает указатель. В нашем случае указатель на IDirect3D8 разыменовывается в ebx. Мы подбираемся всё ближе к нахождению createdivice. Следующая инструкция, "push eax", просто помещает eax в стек затем, чтобы потом командой "pop eax" легко восстановить eax, необходимый для вызова функции IDirect3D8. Далее мы видим "MOV EAX,DWORD PTR DS:[EAX]", разыменовывающая eax, т.к. ebx содержит указатель на указатель. Второй указатель – указатель на адресную таблицу функции IDirect3D8. Чтобы найти любую IDirect3D8 функцию со значением в eax, всё что нужно сделать, это выполнить "MOV EAX,DWORD PTR DS:[EAX+FUNCTIONINDEX]", где FUNCTIONINDEX – индекс IDirect3D8 функции в таблице. Далее, следующая и последняя инструкция, интересная для нас, это "CALL DWORD PTR DS:[EAX+8]", использующаяся вместо "MOV EAX,DWORD PTR DS:[EAX+FUNCTIONINDEX]", поскольку она не запоминает адрес функции, а просто напрямую её вызывает. Эту команду можно было бы заменить на "MOV EAX,DWORD PTR DS:[EAX+8] CALL EAX" и компилятор выполнил бы тоже самое. Теперь, когда вы узнали и поняли все эти вещи (я надеюсь) давайте наконец найдём CreateDevice.Чтобы найти CreateDevice нужно заменить "CALL DWORD PTR DS:[EAX+8]" на "MOV EAX,DWORD PTR DS:[EAX+3C]". Мы делаем так, потому что индекс функции CreateDevice равен 3C в hex. Этой инструкцией мы добываем адрес CreateDevice и запоминаем его в EAX. Сделав так, нажимаем f7 пока Olly не выполнит изменённую инструкцию: Рис.7На скриншоте видим в регистре EAX адрес функции CreateDevice, а модифицированная нами инструкция выделена красным прямоугольником.Запоминаем адрес в EAX и перезапускаем игру, нажав Ctrl+f2.Снова ставим бряк на Direct3DCreate8 и запускаем игру до бряка.Находясь на сработавшем бряке, ставим бряк на запомненном адресе функции CreateDevice.Снова запускаем игру (f9)Нажимаем Ctrl+f9, затем f7 и выходим в место вызова CreateDevice.Видим инструкцией выше "CALL DWORD PTR DS:[EAX+3c]":Рис.8Это и есть то, что мы искали.HRESULT CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD behaviorFlags,D3DPRESENT_PARAMETERS * pPresentationParameters,IDirect3DDevice8 ** ppReturnedDeviceInterface);Последний аргумент и есть указатель на указатель устройства.Чтобы найти их все, нужно вновь перезапустить игру (Ctrl+f2), поставить бряк на Direct3DCreate8. После срабатывания бряка, поставить бряк на "CALL DWORD PTR DS:[EAX+3c]". После срабатывания бряка нажать f7 и в стеке выше слов "Pointer to next SEH record" и будет записан указатель на указатель устройства: Рис.9Чтобы найти указатель на устройство (не указатель на указатель), просто воспользуйтесь оператором разыменования в c/c++.Что же мы нашли – адрес, в котором игра постоянно запоминает указатель на устройство. Теперь вы можете просто прочитать это значение, проверить больше ли оно нуля, и если да, сделать hook на D3D Device функцию, к примеру, EndScene. Текстовый дамп из olly:DISASSEMBLY-----------0049CA0B 50 PUSH EAX0049CA0C 68 FC005D00 PUSH Soldat.005D00FC0049CA11 6A 20 PUSH 200049CA13 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]0049CA16 50 PUSH EAX0049CA17 57 PUSH EDI0049CA18 56 PUSH ESI0049CA19 A1 FC925C00 MOV EAX,DWORD PTR DS:[5C92FC]0049CA1E 50 PUSH EAX0049CA1F 8B00 MOV EAX,DWORD PTR DS:[EAX]0049CA21 FF50 3C CALL DWORD PTR DS:[EAX+3C] ; d3d8.6D9C9BD0(CreateDevice)STACK AT 0049CA1F(CreateDevice Argument List)-----------------0012E8EC 00000000 \ (Adapter)0012E8F0 00000001 | (DeviceType)0012E8F4 0011038E | (hFocusWindow)0012E8F8 00000020 | (BehaviorFlags)0012E8FC 005D00FC Soldat.005D00FC | (pPresentationParameters)0012E900 005C9300 Soldat.005C9300 / (ppReturnedDeviceInterface)***Code:Надеюсь, эта статья хоть как-то вам поможет, а если вы ни разу не слышали про игру Soldat – Google вам в помощь.Спасибо mre521 за эту статьюПеревод на русский: aliastОт MasterGH (10.02.2011)Aliast, спасибо за статью. Я залил скриншоты на хост форума. Т.к. было бы очень жаль если бы какие-то скриншоты пропали со временем. Моё пожелание, заливать картинки на хостинг форума - нашего форума. У тебя есть эта возможность. Это просто пожелание, чтобы твой труд был более увековечен.Также советую всем и всегда хорошие статьи и инструменты копировать себе на хард, а то мало ли у нас рухнет хостинг. Хотя надеюсь что этого никогда не произойдёт иначе это будет траур. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 9 февраля, 2011 Поделиться Опубликовано 9 февраля, 2011 Нормальная статья. Её поймут только те, кто делали хуки на COM бъекты. Я правда не совсем понял зачем автор ставит бряки больше одного раза, когда можно было обойтись одним. Хотя может я и ошибаюсь, т.к. на память не помню описания DirectX-интерфейсов и инициализацию устройства... Если будет время, то я почитаю повнимательнее эту статью. А вообще автор статьи неправильно поступил описывая подробности как и что делать в OllyDbg без рисования сначала общей картины как он собирается вытаскивать указатель и из какой представляемой "логики кода" на коде С++ он собирается вытащить, и вообще какова логика кода стандартной инициализации устройства, и по каким смещения каких интерфейсов находятся методы возвращающие те или иные объекты... Будет время я прокомментирую эту статью нормально с примерами. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 13 февраля, 2011 Поделиться Опубликовано 13 февраля, 2011 По прежнему пока нет времени. Пока нашёл самый простой исходник по инициализации устройства.// Файл: CreateDevice.cpp//// Описание: Это первый туториал по использованию Direct3D. В этом туториале всё что// мы делаем - это создаём Direct3D устройство и используем его для очистки// окна.//// Copyright (c) Micro$oft Corporation. All rights reserved.//-----------------------------------------------------------------------------#include <d3d9.h>//-----------------------------------------------------------------------------// Глобальные переменные//-----------------------------------------------------------------------------LPDIRECT3D9 g_pD3D = NULL; // Используется для создания D3D устройстваLPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Наше устройство рендеринга//-----------------------------------------------------------------------------// Имя: InitD3D()// Описание: Инициализация Direct3D//-----------------------------------------------------------------------------HRESULT InitD3D( HWND hWnd ){ // Создаём D3D объект, который необходим для создания D3D устройства. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Если устройство создано - возвращаем S_OK return S_OK;}//-----------------------------------------------------------------------------// Имя: Cleanup()// Описание: Освобождаем все ранее инициализируемые объекты//-----------------------------------------------------------------------------VOID Cleanup(){ if( g_pd3dDevice != NULL) g_pd3dDevice->Release(); if( g_pD3D != NULL) g_pD3D->Release();}//-----------------------------------------------------------------------------// Имя: Render()// Описание: Рисование сцены//-----------------------------------------------------------------------------VOID Render(){ if( NULL == g_pd3dDevice ) return; // Очистка backbuffer'а в голубой цвет g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // начало сцены if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Рендеринг объектов сцены должен находиться здесь // Конец сцены g_pd3dDevice->EndScene(); } // Выводим содержимое backbuffer'a на экран g_pd3dDevice->Present( NULL, NULL, NULL, NULL );}//-----------------------------------------------------------------------------// Имя: MsgProc()// Описание: Обработка сообщений//-----------------------------------------------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam );}//-----------------------------------------------------------------------------// Имя: WinMain()// Описание: Точка входа приложения//-----------------------------------------------------------------------------INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ){ // Регистрируем класс окна WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3D Tutorial", NULL }; RegisterClassEx( &wc ); // Создание окна программы HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL ); // Инициализация Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { // Показываем окно ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Ввод петли сообщений MSG msg; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0;}//-----------------------------------------------------------------------------Статья "Hooking a DirectX/COM Interface" позволит мне позже вспомнить детали и сравнить со статьё про хукинг в OllyDbg.Так же напишу для чего нужно это всё. Перехват устройства позволит рисовать на поверхности различную графику, возможно даже обрабатывать реакцию курсора и клавиатуры. Это позволит например встраивать интерфейс трейнера в игру. Ссылка на комментарий Поделиться на другие сайты Поделиться
Ac1d Опубликовано 1 августа, 2011 Поделиться Опубликовано 1 августа, 2011 Вот пример меню для трейнера на C++ правда это чит для мультиплеера, но всё же оболочка присутствует:LPD3DXFONT m_pFont = NULL; D3DVIEWPORT9 ScreenViewport; .............................. //=======================================:[ Active Vars ]:================================= //-------------------------:[Visuals]:----------------------- //----------------------- bool *WallHack; bool *Lambert; //----------------------- bool *WpLambert; //----------------------- bool *ColoredPlayers; int *ClPl_ColorNumb; int *ClPl_ColorMode; ....... etc ....... //===================================== FrmMain = new MainMenu(m_pD3Ddev); int xx = (ScreenViewport.Width / 2) - 243; int yy = (ScreenViewport.Height / 2) - 170; FrmMain->CreateWND(NULL,xx,yy,44,true,MAKEINTRESOURCE(100),0); FrmMain->frWnd[0]->Controls->AddTabControl(18, 8, 452, 267); //===========================================================:[VISUALS]:=========================================== FrmMain->frWnd[0]->Controls->TabControls[0]->AddTab("Visuals"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddScrollBar(432,0,FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->scrly,200,&FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->scrly); /* Волхак */ int y = 19; FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Wallhack:",11,y,100,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Lambert (Static): ",230,y+27,300,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(360,y+29,MAKEINTRESOURCE(60),0xFFA9E005); WallHack = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[0]->checked; Lambert = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[1]->checked; y += 29+22; /* Weapoon Lambert */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Wpn Lambert (Static):",11,y,300,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); WpLambert = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[2]->checked; y += 29+22; /*Colored Players*/ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Colored Players:",11,y,300,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Color:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddColorBox(120, y+29, 35, 17, 4); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Mode: ",230,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddComboBox(290,y+29,80,17); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[0]->AddLine("Textures"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[0]->AddLine("Shaders"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",48,y+51,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(120,y+53,MAKEINTRESOURCE(60),0xFFA9E005); ColoredPlayers = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[3]->checked; ClPl_ColorNumb = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ColorBoxes[0]->value; ClPl_ColorMode = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[0]->value; y += 53+22; /*Chams*/ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Chams:",11,y,300,20,0xFFFFFFFF,0xFFFFFFFF); //+23 FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("HColor:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); //+23 FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddColorBox(120, y+29, 35, 17, 4); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("IColor:",48,y+51,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddColorBox(120, y+53, 35, 17, 1); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Mode: ",230,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddComboBox(290,y+29,80,17); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[1]->AddLine("Textures"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[1]->AddLine("Shaders"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",230,y+51,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(290,y+53,MAKEINTRESOURCE(60),0xFFA9E005); Chams = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[4]->checked; Chams_ColorNumb1 = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ColorBoxes[1]->value; Chams_ColorNumb2 = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ColorBoxes[2]->value; Chams_ColorMode = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ComboBoxes[1]->value; y += 53+22; /*xHair*/ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("XHair:",11,y,300,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Color:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddColorBox(120, y+29, 35, 17, 4); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",230,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(290,y+29,MAKEINTRESOURCE(60),0xFFA9E005); CrossHair = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[5]->checked; CrH_ColorNumb = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->ColorBoxes[3]->value; y += 29+22; /* WhiteWalls */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("WhiteWalls:",11,y,100,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); WhiteWalls = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[6]->checked; y += 29+22; /* AsusWallHack */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("AsusWallHack: ",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); AsusWallHack = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[0]->Controls->CheckBoxes[7]->checked; y += 29+22; //===========================================================:[REMOVALS]:=========================================== FrmMain->frWnd[0]->Controls->TabControls[0]->AddTab("Removals"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddScrollBar(432,0,FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->scrly,180,&FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->scrly); y = 19; /* NoFog */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Fog(Static):",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoFog = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[0]->checked; y += 29+22; /* NoSky */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("NoSky:",11,y,300,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Color:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddColorBox(120, y+29, 35, 17, 9); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Mode: ",230,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddComboBox(290,y+29,80,17); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->ComboBoxes[0]->AddLine("Textures"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->ComboBoxes[0]->AddLine("Shaders"); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+51,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+53,MAKEINTRESOURCE(60),0xFFA9E005); NoSky = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[1]->checked; Sky_ColorNumb = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->ColorBoxes[0]->value; Sky_ColorMode = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->ComboBoxes[0]->value; y += 53+22; /* NoGrass */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Grass:",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoGrass = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[2]->checked; y += 29+22; /* NoSun */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Sun:",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoSun = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[3]->checked; y += 29+22; /* NoShadows */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Shadows:",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoShadows = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[4]->checked; y += 29+22; /* No Spread */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Spread:",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoSpread = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[5]->checked; y += 29+22; /* No Recoil */ FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("No Recoil:",11,y,200,20,0xFFFFFFFF,0xFFFFFFFF); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddSeparator(11,y+20,409,1,0x99AAAAAA); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddTextArea("Enable:",48,y+27,100,20,0xFF6f6f6f,0xFF6f6f6f); FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->AddCheckBox(120,y+29,MAKEINTRESOURCE(60),0xFFA9E005); NoRecoil = &FrmMain->frWnd[0]->Controls->TabControls[0]->TabWindows[1]->Controls->CheckBoxes[6]->checked; y += 29+22; /// MainMenu *FrmMain; Не забываем про это:m_pFont->OnLostDevice(); FrmMain->OnLostDevice(); И конец:and in endscene: Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Chevyyy Опубликовано 2 января, 2012 Поделиться Опубликовано 2 января, 2012 Всем привет! Сделал все по вашему уроку, использовал игру более ранней версии, так что адреса могу чуть отличаться:Вот мой скриншот:Вот это у меня не получается:На скриншоте видим в регистре EAX адрес функции CreateDevice, а модифицированная нами инструкция выделена красным прямоугольником.Запоминаем адрес в EAX и перезапускаем игру, нажав Ctrl+f2.Снова ставим бряк на Direct3DCreate8 и запускаем игру до бряка.Находясь на сработавшем бряке, ставим бряк на запомненном адресе функции CreateDevice.Снова запускаем игру (f9)Нажимаем Ctrl+f9, затем f7 и выходим в место вызова CreateDevice.Видим инструкцией выше "CALL DWORD PTR DS:[EAX+3c]":У меня адрес EAX 00382C00Я так понял после нажатия Ctrl+f2, надо делать заново атач.После того как я сделал атач, снимаю с паузы игру и ставлю бряк на Direct3DCreate8На находящемся бряке поставил еще 1 бряк адрес (EAX)Нажал F9Нажал Ctrl+f9, затем f7 и вышел в меню вызова CreateDevice.Вот скриншот:Подскажите, правильно я сделал... Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 2 января, 2012 Поделиться Опубликовано 2 января, 2012 Я не могу дать точный ответ, потому что меня запутало представлять какие бряки и когда ставить.Я просто прокомментирую.Давайте вообще поймём, что в статье делается.Статья очень большая, а написать-то Автору первоисточника надо было чуть проще и статью читать с конца к началу.Наша задача найти указатель на устройство редеринга g_pd3dDevice.Т.е. g_pd3dDevice это адрес по которому располагается адрес устройства. LPDIRECT3D9 g_pD3D = NULL; // Используется для создания D3D устройства LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Наше устройство рендерингаHRESULT InitD3D( HWND hWnd ){ // Создаём D3D объект, который необходим для созданияD3D устройства. if( NULL == ( g_pD3D =Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; if( FAILED( g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Если устройство создано - возвращаем S_OK return S_OK;} Посмотрите последний абзац статьи, там где есть скриншот стека с выделенным последним адресом - т.е. g_pd3dDevice. Наша задача как в статье выйти на вызвов g_pD3D->CreateDevice(….,&g_pd3dDevice). Чтобы выйти на этот участок, мы должны найти указательна g_pD3D, прозвонить call [ [eax] + 3c], где eax= g_pD3D. Вот там где мы окажемся по call и будет вызов g_pD3D->CreateDevice(….,&g_pd3dDevice) и там мы снимем показания стека на бряке. Чтобы найти g_pD3D мы должны найти Direct3DCreate9 или иную смотря какая у васверсия дайректИкс dll-и.Теперь смотрим внимательно статью ещё раз и думаем как снять показания, когда и какие бряки ставить.Но я предлагаю совершенно другой вариант. В том же ollyDbg поставить условный бряк на функцию процедуры окна на сообщение WM_PAINT и искать машинный код вот такого условия сравнения с нулём if( NULL ==g_pd3dDevice ) return; Где после этого сравнения будут вызовы типа call [[g_pd3dDevice]+ смещение] или g_pd3dDevice->функция(..)://-----------------------------------------------------------------------------// Имя: Render()// Описание: Рисование сцены//-----------------------------------------------------------------------------VOIDRender(){ if( NULL == g_pd3dDevice ) return; // Очистка backbuffer'а в голубой цвет g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // начало сцены if( SUCCEEDED(g_pd3dDevice->BeginScene() ) ) { //Рендеринг объектов сцены должен находиться здесь // Конец сцены g_pd3dDevice->EndScene(); } // Выводим содержимое backbuffer'a на экран g_pd3dDevice->Present( NULL, NULL, NULL,NULL );}//-----------------------------------------------------------------------------// Имя: MsgProc()// Описание: Обработка сообщений//-----------------------------------------------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam );} Для проверки g_pd3dDevice посмотрите смещения call [[g_pd3dDevice]+ смещение] где смещение равновызову функции Clear(), вызову BeginScene(),вызову EndScene(),Present(). Если подобную манипуляцию сделать однажды, то потом установить адрес устройства редеринга будет проще чем через способ , который автор первоисточника написал в статье. Но он-то написал это на примере работы в отладчике в режиме отладки, а если его способ автоматизировать то его способ будет даже наверно попроще моего, т.к. мой способ автоматизировать будет сложнее. Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 9 января, 2012 Поделиться Опубликовано 9 января, 2012 Мм, продолжу тему. В конце статьи пишется про возможность хука ендсцены, etc. Имеем адрес устройсва, найденного заранее для игры на dx9. Пробую сделать хук:LPDIRECT3DDEVICE9 myGame;while(!myGame) myGame = (LPDIRECT3DDEVICE9)0x059457F8;// наш адрес д3д устройства//насколько я знаю EndScene находится под индексом 42 в виртуальной таблице//тогда можно использовать кодкейв, ничего лучше ms detours для этого нету ; )oEndScene=(tEndScene)DetourFunction((PBYTE)GameDevice[42],(PBYTE)&EndScene);...но нифига не работает есть у кого более глубокие знания? Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 9 января, 2012 Поделиться Опубликовано 9 января, 2012 Если почитать DXSDK внимательно, то указатель там двухуровневый. То есть, не указатель на устройство, а указатель на указатель на устройство. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 9 января, 2012 Поделиться Опубликовано 9 января, 2012 Мм, продолжу тему. В конце статьи пишется про возможность хука ендсцены, etc. Имеем адрес устройсва, найденного заранее для игры на dx9. Пробую сделать хук:LPDIRECT3DDEVICE9 myGame;while(!myGame) myGame = (LPDIRECT3DDEVICE9)0x059457F8;// наш адрес д3д устройства//насколько я знаю EndScene находится под индексом 42 в виртуальной таблицеDWORD* GameDevice = (DWORD*)myGame;GameDevice = (DWORD*)GameDevice[0];//тогда можно использовать кодкейв, ничего лучше ms detours для этого нету ; )oEndScene=(tEndScene)DetourFunction((PBYTE)GameDevice[42],(PBYTE)&EndScene);...но нифига не работает есть у кого более глубокие знания?Берёшь отладчик, берёшь справку, берёшь компилятор + DirectX SDK. И "получаешь более глубокие знания" Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 10 января, 2012 Поделиться Опубликовано 10 января, 2012 Есть, всё получилось, благо существует MSDN я ещё малость попарился с OnLostDevice, но оказывается там всё просто, Reset имеет индекс 16HRESULT WINAPI Reset( LPDIRECT3DDEVICE9 D3D_DEVICE, D3DPRESENT_PARAMETERS* pPresentationParameters ){ if(mFont){mFont->OnLostDevice();} HRESULT MY_RESULT = oReset( D3D_DEVICE, pPresentationParameters ); if(MY_RESULT==D3D_OK) {if(mFont){mFont->OnResetDevice();}} return MY_RESULT;}теперь меню трейнера можно делать в самой игре 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 10 января, 2012 Поделиться Опубликовано 10 января, 2012 Я абсолютно не сомневался, что у тебя получится задуманная идея.Мне как бы похвастаться по работе с голым ДаректИКС нечем, кроме компиляций и разбора с десяток примеров как простых так и примеров из DirectX SDK. Такой хук аналогичный твоему я тоже делал, только на Дельфи. Но могу посоветовать кое-что для дальнейшего развития и исследований.1) Посмотреть жизненный цикл пары программ из примеров из DirectX SDK. Таких моментов как потеря устройства, directX обработка ввода с клавиатуры и мышки, почитать какие события можно обработать, какие общие функции. Это может тебя заинтересовать и толкнуть на новые идеи, которые могут быть тебе будет интересны.2) Попробовать написать свое приложение с ДаректИКС в котором обрабатывается directX ввод с клавиатуры или с мышки. Обычно это вереница кейсов в свитчах. Это тоже толкает на некоторые интересные идеи по поиску в играх в отладчике нужного участка кода по вводу от польозвателя3) Если никогда не делал игровые сцены, то очень полезно на игровом движке посмотреть примеры игр. Советую Unity3D и пример AngryBots который идёт в комплекте. Обратить внимание на управление персонажем, управление камерой, на построение иерархии игровых объектов. Но а также советую пример сцены 3D - шутера:Пусть там язык C#, но зато понятно как работать с материалами, анимацией и др. На других примерах можно узнать что такое и как работать с шейдерами и системами частиц. Очень познавательно. Но а затем набравшись практики можно делать серьёзные читы похожие чем-то ближе к модам. Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 14 января, 2012 Поделиться Опубликовано 14 января, 2012 Если кому нужно, указатель на d3ddevice для CS:Source последней версии - shaderapidx9.dll+17C81C Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 2 февраля, 2012 Поделиться Опубликовано 2 февраля, 2012 Порылся ещё глубже, теперь осталось научится получать координаты моделек и можно сделать универсальный аимбот на все игры Выложу таблицу с вершинами и примитивами для команды контртеррористов на последнюю версию:Numvertices & PrimcountsGIGN3304 50032196 30611404 1919 811 989466 55068 4068 34Seal Team 3887 49742487 300673 59899 910513 451369 279SAS3417 50302245 29981498 1822929 1007499 533409 433GSG 93206 48722130 30041424 1858814 945457 51087 63343 344штук 5-6 я правда пропустил при поисках, т.к. чтобы на отходить на 1м и выискивать заново нужно иметь совсем железные нервы Ссылка на комментарий Поделиться на другие сайты Поделиться
ARM4ND0 Опубликовано 6 марта, 2012 Поделиться Опубликовано 6 марта, 2012 Уже четыре дня пробую и наконец получилось,спасибо Synapsе-у за объяснения. Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 13 марта, 2012 Поделиться Опубликовано 13 марта, 2012 (изменено) Посылаем туда же DirectX 10 Изменено 13 марта, 2012 пользователем Kvazimado Ссылка на комментарий Поделиться на другие сайты Поделиться
ARM4ND0 Опубликовано 13 марта, 2012 Поделиться Опубликовано 13 марта, 2012 А вот и мои chams'ы. Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 15 марта, 2012 Поделиться Опубликовано 15 марта, 2012 DX11 это нечто, надо же было стереть работу с рисование текста, пришлось юзать стороннюю библиотеку. Чтож, посылаем туда же Dx11:теперь у меня есть коллекция хуков dx начиная с .. dx 8ps. по-моему кроме меня и US никому эта тема не интересна ) Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 15 марта, 2012 Поделиться Опубликовано 15 марта, 2012 DX11 это нечто, надо же было стереть работу с рисование текста, пришлось юзать стороннюю библиотеку. Чтож, посылаем туда же Dx11:теперь у меня есть коллекция хуков dx начиная с .. dx 8ps. по-моему кроме меня и US никому эта тема не интересна )У меня пока что руки не дошли. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Chevyyy Опубликовано 19 марта, 2012 Поделиться Опубликовано 19 марта, 2012 Уже четыре дня пробую и наконец получилось,спасибо Synapsе-у за объяснения. Прикольно у тебя вышло, у меня по уроку в теме, не выходит хукать ендсцену в мв3, можно какую-нибудь отдельную статью именно на эту игру ?В современных играх как-то не так Ссылка на комментарий Поделиться на другие сайты Поделиться
Synapsehome Опубликовано 21 марта, 2012 Поделиться Опубликовано 21 марта, 2012 Хук и в африке хук, для любых функций Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 3 января, 2013 Поделиться Опубликовано 3 января, 2013 Статья. Нахождение указателей на устройство на примере игры SoldatДа, понаделали они там глобальных изменений (это я про хостера своего бесплатного) и всё поудалялось... потом если найду статью перезалью. А пока вот статья про поиск Device pointers на примере игры Soldat. Что такое Device pointer я толком не понял, что-то связанное с DirectX программированием и созданием графических читов (wallhack - видеть сквозь стены и др.) путём перехвата DirectX функций. В общем для меня это всё тёмный лес, но статью понять можно. Осталось найти ей применение на практике =)Скажу сразу, в игре Soldat имеется защита от читинга и под голым Olly запустить игру я не смог, пока не скачал с нашего сайта сборку shadow (скачать сборку) с кучей плагинов и игра сразу запустилась. Оригинал статьиРебята могу как нибудь скачать сборку? А то говорит что нет прав у меня. Ссылка на комментарий Поделиться на другие сайты Поделиться
ARM4ND0 Опубликовано 3 января, 2013 Поделиться Опубликовано 3 января, 2013 Google 3-яя ссылка.. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения