<
  • Главная
Статьи

HackZone.RU - Злом ігор ВКонтакте: дослідження додатків ВКонтакте під мікроскопом

  1. Про онлайн-ігри
  2. Ідея!
  3. кодінг
  4. І це все?
  5. Підбиваючи підсумки

Так уже ми влаштовані, що багатьом з нас властива гонитва за суспільним статусом. Одні шукають собі сексуального чоловіка, інші оточують себе елементами розкоші, треті ж (в основному, люди ще молоді) обмежуються підтримкою віртуального статусу. У цій статті буде порушена частина цієї своєрідної індустрії - розраховані на багато користувачів браузерні онлайн-ігри і їх слабкі місця.

Про онлайн-ігри

Для початку пропоную розібратися, на які ж категорії можна розділити всі онлайн-гри з точки зору їх рівня безпеки. Перший тип - це платформозавісімие гри з власним движком, який зазвичай розробляється з нуля. Це такі ігри, як World of Warcraft, Lineage, Warhammer і інші. Як правило, вся інформація від клієнта до сервера передається за власним протоколу гри, і ступінь її захищеності визначається тільки фантазією розробників.

Другий тип - це Кросплатформені гри з власним движком і протоколом обміну даними. Це всілякі бійцівські клуби, ігри типу TimeZero та інші. На відміну від ігор першого типу, вони зазвичай виконані на базі Flash і Java. Їх плюс - в платформ, а невеликий мінус - у безпеці. Звичайно, з безпекою все не критично, але явно гірше, ніж у першого типу ігор, в силу обмеженості можливостей використовуваних технологій, особливо Flash. Проте, у ігор третього типу маневрів для підтримки досить хорошого рівня безпеки ще менше.

Третій тип - це підмножина другого типу, тобто браузерні онлайн-ігри, побудовані на схожому протоколі обміну даними, API або движку. До цього типу належать гри всередині таких відомих сервісів, як Mail.ru, Yahoo і ВКонтакте. Останньому і присвятимо нашу увагу.

Додатки ВКонтакте завоювали популярність в масах практично відразу ж після своєї появи. Ферми, покери і рисовалки на стінах в найкоротші терміни набрали сотні тисяч користувачів до своїх лав, а їх творці отримали непогану фінансову підживлення за рахунок любителів підняти свій рейтинг (і, як наслідок, віртуальний громадський статус) шляхом оплати тих чи інших послуг з рахунку ВКонтакте . Як буде показано далі, за допомогою нескладних маніпуляцій в деяких додатках можна домогтися бажаного результату, не витрачаючи багато часу, а всього лише написавши Автоматор (бот), який буде виконувати всю роботу за тебе. Так я і зробив в один прекрасний день.

Ідея!

З чого ж все почалося? А з того, що я, будучи любителем англійської мови, знайшов ВКонтакте додаток LinguaMania . Це тренажер для вивчення мов. Щоб навчання проходило веселіше, розробники реалізували систему заохочень у вигляді букв, з яких можна збирати слова, а потім "купувати" за них одяг і одягати свою віртуальну аватарку. Ну і, само собою, рейтинг. А ось про нього докладніше. Рейтинг дається не тільки за навчання по віртуальним "підручниками", але і за гру в вікторину, яка відразу мене зацікавила.

Так виглядає ігровий процес
Так виглядає ігровий процес

Перші кілька тижнів я чесно набивав окуляри тисячами, поки не набридло. Набравши 100 000 очок і відірвавшись від переслідувачів в 2-3 рази, я неабияк втомився і забив на цю справу. Щоправда, через кілька місяців мене стали наздоганяти в рейтингу. Тут-то і прокинувся мій егоцентризм: бажання зберегти першу сходинку рейтингу змусило мене обдумати шляхи набору очок без зайвої витрати часу.

Насамперед я поліз дивитися трафік програми: що куди передається, що приходить назад. Для аналізу HTTP-трафіку я ще не зустрічав інструменту краще, ніж додаток HTTPWatch для Internet Explorer'а. Отже, я запустив гру, натиснув кнопку "Record" в аддоні для запису логів ... і ось тут мені, як то кажуть, і "прийшли 2 туза на префлопе". Я побачив, що додаток передає всі свої дані як є, в відкриту.

Трафік очима HttpWatch
Трафік "очима" HttpWatch

Вивчивши трафік я виявив, що змінна state набуває таких значень: PHASE1, PHASE2, PHASE3, GUESS, LOSE. Це відповідає стадіях гри в кожному раунді: всі букви приховані, одна буква відкрита, дві букви відкриті, слово вгадано, слова не вгадано. Як бачиш, у відкриту передається question_id, що, як нескладно здогадатися, є номер питання. У разі перших трьох фаз в поле "question_mask" передається маска слова. Наприклад, якщо state = PHASE3, перша буква C, друга буква A, то маска слова - ?? С? A. Якщо поточна фаза - GUESS або LOSE, то слово буде відображено на екрані цілком, щоб показати користувачеві відповідь. Відповідно, в змінної question_mask це також відобразиться: там буде слово повністю, без знаків питання.

Дивись уважно. В кінці кожного раунду ми отримуємо номер питання і відповідь на нього. Саме це відкриття і навело мене на ідею автоматизувати процес. Адже кожного разу, коли ми отримуємо слово, ми заносимо його в нашу базу даних слів. Якщо ж такої question_id там вже є, то ми беремо слово і вписуємо його в віконце програми, за що отримуємо окуляри. Само собою, що перевірку на наявність слова в базі потрібно робити в той момент, коли state буде PHASE1, PHASE2 або PHASE3. Таким чином, наш бот буде самонавчальним: немає слова - запам'ятовуємо, є слово - відповідаємо на питання.

кодінг

Як же це все реалізувати на практиці? Для початку потрібно навчитися самим перехоплювати трафік. Розглянемо доступні нам варіанти. Їх буде три.

Перший варіант - це перехоплення пакетів мережевого інтерфейсу. Досить низькорівневий спосіб, що вимагає навичок взаємодії з зовнішніми бібліотеками, мережевими інтерфейсами і, в цілому, вміння працювати з операційною системою на низькому рівні. Тобі знадобиться бібліотека WinPCap, яка дозволяє отримувати пакети в чистому вигляді прямо з мережевого інтерфейсу. В іншому - Гугл в допомогу.

Другий шлях - це робота з Internet Explorer. Цей спосіб, мабуть, самий високорівнева, так як ми отримуємо вже готовий, оброблений трафік. Для перехоплення трафіку таким чином необхідно володіти COM-програмуванням: вміти підключатися до COM-об'єктів (яким є компонент IWebBrowser2 всередині вікна Internet Explorer'а), реалізовувати інтерфейси і працювати з ними. Спосіб вимагає серйозних знань в вищевказаної області, тому я вирішив робити "як дід вчив", третім способом. А це у нас реалізація проксі-сервера. Точніше кажучи, Socks 4/5 сервера. На цьому способі загострити нашу увагу. Загостримо трохи, так як стаття все ж не про створення Socks-сервера, тому навантажувати її кодом не буду.

Почати написання Socks-сервера варто з вивчення ось цього мануала . Для ледачих і англонемих будуть мої пояснення російською. Але спершу реалізуємо серверний додаток. Є кілька способів зробити додаток-сервер, починаючи зі старого ...

SOCKET mysocket
sockaddr_in local_addr
local_addr .sin _family = AF_INET
local_addr .sin _port = htons (MY_PORT)
local_addr .sin _addr .s _addr = 0
mysocket = socket (AF_INET, SOCK_STREAM, 0)
bind (mysocket, (sockaddr *) & local_addr, sizeof (local_addr))
listen (mysocket, 1080)
SOCKET client_socket
sockaddr_in client_addr
int client_addr_size = sizeof (client_addr)
while ((client_socket = accept (mysocket, (sockaddr *) & client_addr, & client_addr_size)))
{
DWORD thID
CreateThread (NULL, NULL, ClientThread, & client_socket, NULL, & thID)
}

... і закінчуючи цілком сучасним способом реалізації серверів під Windows, яким є робота з мережевими повідомленнями за допомогою функції WSAAsyncSelect (). Саму програму і її повний вихідний код на C ++ в середовищі Visual Studio 10 можна знайти на нашому DVD . Рамки статті не дозволяють детально описати процес створення Socks-сервера, тому я обмежуся лише поясненням структури програми і основних методів, які я використовував.

Почати написання такого додатка коштує приблизно c такого коду:

SOCKET server_socket
wSADATA wsaData
int server_port = 3128
int queue_size = 5
struct sockaddr_in server_address
#define SERVER_ACCEPT WM_USER + 1
#define CLIENT_EVENT WM_USER + 2
#define TARGET_EVENT WM_USER + 3
#define SOCKET_OPENED WM_USER + 4
#define SOCKET_CLOSED WM_USER + 5
int ServerStart (HWND hWnd)
{
int rc
WSACleanup ()
WSAStartup (0x0101, & wsaData)
server_socket = socket (AF_INET, SOCK_STREAM, 0)
server_address .sin _family = AF_INET
server_address .sin _addr .S _un .S _addr = inet_addr ( "127.0.0.1")
server_address .sin _port = htons (server_port)
bind (server_socket, (LPSOCKADDR) & server_address, sizeof (server_address))
listen (server_socket, queue_size)
rc = WSAAsyncSelect (server_socket, hWnd, SERVER_ACCEPT, FD_ACCEPT)
return 0
}

Чим же цей код відрізняється від першого? А тим, що в даному випадку нам не потрібно возитися з багатопоточність для обробки кожного підключення до сервера. Завдяки виділеної сходинці ми будемо в нашому вікні hWnd отримувати повідомлення SERVER_ACCEPT при кожному новому підключенні клієнта.

Тепер розглянемо момент підключення. У процедурі обробки повідомлень вікна ми ловимо повідомлення SERVER_ACCEPT і працюємо з ним. Як тільки клієнт підключився, викликається функція accept (), і далі реєструється подія CLIENT_EVENT, яке буде приходити головного вікна нашої програми, як тільки в сокет надійдуть дані або повідомлення про його закриття:

client_socket = accept (server_socket, (LPSOCKADDR) & socket_record-> client_address, & len)
rc = WSAAsyncSelect (socket_record-> client_socket, hWnd, CLIENT_EVENT, FD_READ | FD_CLOSE)

Повернемося знову в нашу віконну процедуру. У ній ми будемо обробляти вищезазначене подія CLIENT_EVENT. Значення lParam в даному випадку буде або FD_READ (якщо подія була викликана як сигнал про надходження даних в сокет), або FD_CLOSE (якщо сокет був закритий).

if (WSAGETSELECTEVENT (lParam) == FD_READ)
{
c = recv (socket_record-> client_socket, & bf [0], 1, 0);
...
}
if (WSAGETSELECTEVENT (lParam) == FD_CLOSE)
{
...
}

Таким чином, ми вже навчилися приймати підключення і читати дані з сокета. Але повернемося до реалізації Socks-протоколу, згадуваної вище. Тут я покажу, як працює Socks5, хоча в моїй програмі реалізована і 4-ая версія. Ось що говорить нам RFC.

Після підключення клієнт посилає Socks-серверу два байта: номер версії (4 або 5) і кількість методів аутентифікації: N. Після цього нам прийде ще N байт з номерами цих самих методів. Зазвичай приходять 3 цілих числа: 05h, 01h і 00h. Тобто п'ята версія і перший метод, значення якого 00h, що означає, що клієнт бажає працювати без аутентифікації. У відповідь ми повинні повернути два байта. Перший - це номер версії, тобто 05h, другий - значення обраного нами (сервером) методу аутентифікації з того списку, що нам запропонував клієнт. Так як клієнт зазвичай пропонує тільки 00f, то саме це ми назад і повернемо. З'ївши наша відповідь, клієнт надішле запит такого формату: перший байт - номер версії, другий - команда, третій - резервний байт, четвертий - тип адреси. Після чого буде йти група байт безпосередньо з самим адресою хоста-мети, а завершать пакет два байта з номером порту хоста-мети. Формат групи байт з адресою хоста-мети буде залежати від того, який тип адреси (четвертий байт) задається. Ми будемо працювати зі звичним IPv4, що відповідає значенню 01h для четвертого байта запиту. В цьому випадку група байт буде розміром 4, тобто стандартного формату IP-адреси з чотирьох цілих чисел. Номер порту хоста-мети обчислюється як перший байт * 256 + другий байт.

Отже, у нас є запит від клієнта, який потрібно виконати. Підключаємося до хосту-мети у даній нам адресою і порту, чекаємо даних. Чекати даних будемо як з сокета нашого клієнта, так і з щойно створеного сокета для хоста-мети, з яким клієнт бажає за допомогою нашого Socks-сервера поспілкуватися. Все, що прийде від клієнта, посилаємо хосту-мети. Все, що від хоста-мети, йде клієнту. Так і працює Socks-сервер.

У моїй програмі реалізована структура, яка містить дані про всі підключення, створених нами, щоб при прийнятті повідомлення FD_READ ми знали, який сокет що і куди посилає, клієнт це чи хост-мета, і в якому статусі перебуває процес спілкування з ним. Рамки статті не дозволяють детально описати цю структуру, так що дивись вихідний код.

Отже, ми навчилися перенаправляти трафік і, отже, слухати його. Тепер, думаю, тобі не важко буде написати парсинг необхідних даних. Обробляючи дані ми, як я вже позначив раніше, дивимося, чи є в нашій базі даних записи для шуканого id. Якщо немає, то в момент настання фази LOSE або GUESS ми заносимо це слово в базу даних. Якщо ж запис є, то настав час повідомити грі правильну відповідь. Це можна зробити двома способами.

Перший "дуже високорівнева" і одночасно складний. Полягає він у тому, що ми підключаємося до COM-об'єкту IWebBrowser2 всередині Internet Explorer'a, в якому у нас завантажена гра. Отримуємо інтерфейс Flash-ролика і вже безпосередньо з ним працюємо через Flash API, що дозволить нам вбити слово прямо в текстове поле і натиснути кнопку введення. Це дуже круто. І дуже складно :).

А що якщо ти не користуєшся Internet Explorer'ом? Та й реалізовувати все вищеописане не вистачає сил і бажання? Є старий добрий метод емуляції подій мишки і клавіатури. Полягає він у використанні системної функції SendInput. Це модернізована версія keydb_event () / mouse_event (), яка рекомендована виробником (Microsoft). Ось приклад натискання клавіші F5:

INPUT pInput
pInput .type = INPUT_KEYBOARD
pInput .ki .wVk = VK_F5
pInput .ki .time = 0
pInput .ki .wScan = 0
pInput .ki .dwFlags = KEYEVENTF_EXTENDEDKEY
SendInput (1, & pInput, sizeof (pInput))

Ура! Тепер ми вміємо слухати трафік через наш Socks-сервер, самонавчатися, розширюючи словник при кожному новому слові, і відповідати на питання, які нам вже зустрічалися. Мета досягнута!

Варто додати, що в програмі, викладеної за посиланням вище, відсутня функція введення даних. Тільки прослуховування трафіку і відображення слів на екрані. Мені не хотілося б, щоб кожен другий почав тероризувати описані додатки і накручувати рейтинг. Більш того, перед виходом цього номера журналу в світ автори додатків були проінформовані про наявність уразливості, що, ймовірно, призведе до її усунення. Якщо ж ти захочеш повторити щось схоже на картину нижче, то, будь добрий, напиши відсутню функцію відповіді на питання сам.

Ось що вийшло в підсумку
Ось що вийшло в підсумку

І це все?

І це буде цілком адекватний питання. Наявність уразливості такого класу не обмежується лише одним додатком. До слова сказати, весь цикл програм цього розробника схильний такого роду накрутці. А саме:

А також деякі інші.

Поверхневий пошук серед додатків ВКонтакте дав ще кілька плодів. Перший з них - це додаток " бульбашки ".

Гра Бульбашки
Гра "Бульбашки"

Якщо ти хороший алгоритмісти і можеш написати гідну програму для набору максимальної кількості очок на заданому полі, то для тебе є чудова новина. Розклад "галявини" перед вашими очима:

Ось що побачив Нео в Матриці
Ось що побачив Нео в Матриці

Любителям судоку ВКонтакте є своє містечко .

Такий ось розклад
Такий ось розклад

Все, що тут потрібно - це хороший і швидкий алгоритм вирішення поставленого завдання, благо її умова не потрібно отримувати розпізнаванням картинки на екрані, досить поглянути на трафік.

Як ти, сподіваюся, розумієш, різноманіття додатків ВКонтакте незрівнянно з відведеної під статтю квотою, тому залишаю пошук потенційних жертв тобі, дорогий читачу, в якості домашнього завдання.

Підбиваючи підсумки

На завершення поміркуємо про те, хто винен і що робити. Винними визнаються лінь і жага наживи розробників додатків, а також егоїзм тих, хто користується цими додатками, сидячи ночами безперервно і відрощуючи "віртуальний статевий орган". В іншому випадку ці додатки просто не розроблялися б для широкої публіки. Із шляхів вирішення проблеми, які бачу особисто я, запропоную такі.

Розробникам. Уважніше вивчати питання безпеки використання додатків. Впровадження простого "шифрування" зрушенням на пару байт вже має відбити у значної частки "зломщиків" бажання копатися в трафіку, не кажучи вже про більш досконалі методи захисту даних, які, в залежності від твоєї фантазії, в тій чи іншій мірі убезпечать додаток від неадекватних дій користувачів.

Зломщикам. Сподіватися на те, що на гачок попадеться серйозна рибка з проломи в безпеці, такими, як були описані вище, не варто. Розробники великих додатків (особливо тих, де відчувається присутність грошової складової) зазвичай вміють рахувати втрати від діяльності любителів "покопатися всередині". Так що візьми все вищесказане на замітку без зайвих ілюзій стосовно надвигідно застосування цих знань на практиці.

Тим, хто все ще грає. Перестань. Це всього лише точки на екрані. У багатьох іграх є цілком реальна можливість автоматизації процесу гри і всі твої багатогодинні, а в рідкісних клінічних випадках і багатоденні, зусилля будуть виглядати бідно в порівнянні з результатами роботи комп'ютерної програми. Програма не хоче ні спати, ні їсти. Вона не втомлюється і не здається. Не потрібно змагатися з програмою. Живи реальним життям, а не життям "ельфа 80-го рівня". Зазнавши все це свого часу на особистому досвіді, я кинув цим займатися. І ось, усвідомивши, що знанням варто поділитися з іншими, я відкрив текстовий редактор і написав перші рядки цієї статті.

З чого ж все почалося?
Наприклад, якщо state = PHASE3, перша буква C, друга буква A, то маска слова - ?
С?
А що якщо ти не користуєшся Internet Explorer'ом?
Та й реалізовувати все вищеописане не вистачає сил і бажання?


Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью