Изучая Skype — редактируем цитаты

По сравнению с предыдущей статьёй (которая, судя по изменениям моей кармы, не всем пришлась по нраву) эта совсем безобидная.

Можно ли доверять цитатам из Skype? Казалось бы, их нельзя редактировать, а после недавнего отключения поддержки html тэгов (в windows версиях), это должно быть невозможным. Ответ на вопрос на скриншоте ниже:



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

Предположим, что при копировании цитаты, Skype также дописывает в буфер обмена и информацию об авторе, дате и т.п., это наиболее простой путь, по которому, как оказалось позже, и пошли разработчики. Для дальнейшего изучения нам не понадобится дизассемблировать Skype, просто напишем свою программу (в лучших традициях Smart UI паттерна – это там где весь код в кнопках), которая «ковыряет» буфер обмена. По привычке, я буду использовать c#, в качестве UI для быстроты выберу win forms (да простят меня ненавистники этих технологий).
Итак, вот формочка с аскетичным дизайном:



По одной кнопке все данные из буфера обмена будут писаться в richEdit, по другой, будет происходить обратная операция. Начнём же изучение.Судя по всему для работы с буфером обмена тут подойдёт класс «System.Windows.Forms.Clipboard». В нём есть подходящий метод GetDataObject, который возвращает объект, реализующий интерфейс IDataObject (смотрим msdn). Метод GetData принимающий в качестве параметра Type нам не подходит, т.к. структуру объекта сохраняемого в буфер обмена законными способами узнать не получится, зато есть его перегрузка строку с «форматом». Это очень кстати, учитывая, что есть ещё и метод GetFormats. Итак, вот он, первый шаг к изучению того, что же Skype сохранил в буфер обмена:

private const string DataKey = "SkypeMessageFragment";
private Dictionary<string, object> clipboadData = new Dictionary<string, object>();
private string message;

private void buttonLoad_Click(object sender, EventArgs e)
{
    IDataObject iData = Clipboard.GetDataObject();
    foreach (var format in iData.GetFormats())
    {
        clipboadData[format] = iData.GetData(format);
    }

    using (StreamReader streamReader = new StreamReader(clipboadData[DataKey] as MemoryStream))
    {
        message = streamReader.ReadToEnd();
        (clipboadData[DataKey] as MemoryStream).Seek(0, SeekOrigin.Begin);
    }

    richTextBoxQuote.Text = message;
}



Пишем «test text» в skype, копируем свою цитату, вставляем в окошко скайпа, чтобы убедиться, что цитата скопировалась, и выполняем код.Посмотрим прямо в дебаге, что же сохранилось в clipboardData.



Не знаю как вас, а меня очень заинтересовало значение с ключом SkypeMessageFragment, может быть потому, что оно MemoryStream, хотя в остальных просто нет ничего интересного. Итак посмотрим что же лежит в этом стриме:

private Dictionary<string, object> clipboadData = new Dictionary<string, object>();

private void buttonLoad_Click(object sender, EventArgs e)
{
    IDataObject iData = Clipboard.GetDataObject();
    foreach (var format in iData.GetFormats())
    {
        clipboadData[format] = iData.GetData(format);
    }
}


Запустив это, в richedit можно увидеть вот что:



Честно говоря, я подумал, что на этом моё исследование закончилось провалом. Да, тут есть автор, время отправление в unix формате, сам текст цитаты, но кроме того тут есть значение guid, где хранится какой-то хэш. Увидев этот хэш, я понял, что это, скорее всего, что-то типа hmac. В любом случае, система цитат должна работать как-то так: Skype от всех данных цитаты считает хэш по своему супер секретному алгоритму (возможно используя суперсекретный ключ) и пишет получившийся хэш в буфер обмена, а когда человек вставляет цитату в окошко и отправляет её в чат, скайп проверяет верность подписи. Теория это хорошо, но давайте проверим, а так ли это, и сделаем сохранение richEdit обратно в буфер обмена:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SkypeQuote
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private const string DataKey = "SkypeMessageFragment";
        private Dictionary<string, object> clipboadData = new Dictionary<string, object>();
        private string message;

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            IDataObject iData = Clipboard.GetDataObject();
            foreach (var format in iData.GetFormats())
            {
                clipboadData[format] = iData.GetData(format);
            }

            using (StreamReader streamReader = new StreamReader(clipboadData[DataKey] as MemoryStream))
            {
                message = streamReader.ReadToEnd();
                (clipboadData[DataKey] as MemoryStream).Seek(0, SeekOrigin.Begin);
            }

            richTextBoxQuote.Text = message;
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            message = richTextBoxQuote.Text;
            MemoryStream memoryStream = new MemoryStream();
            StreamWriter streamWriter = new StreamWriter(memoryStream);

            streamWriter.Write(message);
            streamWriter.Flush();
            memoryStream.Seek(0, SeekOrigin.Begin);
            clipboadData[DataKey] = memoryStream;

            IDataObject iData = new DataObject();

            foreach (var item in clipboadData)
            {
                iData.SetData(item.Key, item.Value);
            }

            Clipboard.SetDataObject(iData, true);
        }

    }
}



При записи в stream я намеренно не использовал конструкцию using (вызов метода Dispose у streamWriter портит мой MemoryStream)Итак, запускаем программу, копируем цитату из скайпа, правим её в нашем «редакторе», жмём Save и вставляем цитату обратно в Skype.



Честно говоря, я сильно удивился, что это сработало. Нет, я, конечно, искренне надеялся, что это сработает, но удивился я очень сильно. Хотя бы из-за моей теории с hash’ом, зачем тогда этот гуид, непонятно.
Настоящая цель этой статьи – предупредить общественность, что цитатам из skype доверять нельзя. Ведь это очень мощный инструмент, которым можно оклеветать/обмануть другого человека. В общем, это новое оружие в социальной инженерии, так что будьте бдительны, и не ленитесь проверять теорию практикой.

P.S. в последней секции «code» находятся все исходники, поэтому загружать на git не стал.P.P.S. прошу прощение за чрезмерное количество отступов в коде, при включении опции «Отключить автоматические переносы строк и создание ссылок.» та же ерунда. (подсвечивал код вот этим http://highlight.hohli.com/ там всё выглядело нормально)
+106
12 февраля 2012, 19:58
141
DjComandos 16,5

комментарии (31)

+14
Screatch #
Используйте конструкцию

<source lang="C#">
 код
</source>


для исходного кода
+3
DjComandos #
Спасибо, помогло.
+13
Maccimo #
Всю исследовательскую часть с выяснением содержимого буфера обмена можно было заменить на запуск clipbrd.exe из поставки Win XP с последующим сохранением содержимого буфера в *.clp-файл.
+1
twangel #
Действительно, сохранить буфер в clp, отредактировать в текстовом редакторе и обратно загрузить из нового clp.

Правда там весёлый файл получается. Часть в cp1251, часть в utf-8.
0
Maccimo #
Редактировать в таком виде неудобно — формат бинарный, проще пойти по пути автора.
А вот для «первичного осмотра» бинарность не помеха.

Что же до мешанины кодировок, то при вставке из буфера всегда используется один, наиболее подходящий формат из имеющихся. В нашем случае самый предпочтительный — SkypeMessageFragment, можно править только его.
0
ni_dasav #
Кстати, давно хотел узнать — есть ли или планируется ли настройка скайпа таким образом чтобы по Ctrl+C копировался только текст, а по Ctrl+Ins цитата, о которых идёт разговор в статье?
+32
Werat #
Если нажимать Ctrl+Shift+V, то вставляется только текст, а не цитата.
+4
ni_dasav #
Благодарю!
+1
nicolausYes #
Спасибо, любопытно.

Не придираюсь, но, как минимум, это место грозит быть местом падения программы, если буфер обмена пуст.
using (StreamReader streamReader = new StreamReader(clipboadData[DataKey] as MemoryStream))
{
        message = streamReader.ReadToEnd();
        (clipboadData[DataKey] as MemoryStream).Seek(0, SeekOrigin.Begin);
}


По аналогии с предыдущей статьей, Вы забыли добавить в конце что-то вроде «Это все только в исследовательских целях, ни в коем случае не стоит массово подменять цитаты» :)
+2
edogs #
Настоящая цель этой статьи – предупредить общественность, что цитатам из skype доверять нельзя.
Не хотелось бы придираться к статье, тем более было очень интересно почитать, но… справедливости ради, отквоченное не очень однозначно воспринимается.
Было бы наверное более правильно сказать, что свои собственные сообщения можно форматировать, в том числе и в виде оформления части текста как цитаты собеседника. Но опять же, это свои собственные сообщения, а не «цитаты собеседника», строго говоря.

Кроме того, вызывает ряд вопросов вот этот момент
Казалось бы, их нельзя редактировать, а после недавнего отключения поддержки html тэгов (в windows версиях), это должно быть невозможным.
Редактировать их может и нельзя было, но можно было создавать www.wikireality.ru/wiki/HTML_%D0%B2_%D0%A1%D0%BA%D0%B0%D0%B9%D0%BF%D0%B5 (смотреть оформление html тэгами, предпоследнее — как раз способ оформить как цитату), поэтому никто особо на цитаты и не полагался в том числе и по этой причине.
Если поддержка html тэгов отключена только в windows версиях, возможно в юниксах они еще работают в полной мере? Может кто-то проверить?
+6
edogs #
Более того.
Способ создания цитат в html работает и сейчас у нас. Винды 7-ка. Скайп 5.5.0.124. Вставляем
<quote author="edogs" authorname="edogs" conversation="edogs" 
timestamp="1329070172"><legacyquote>[12:12:12] DisplayedName: 
</legacyquote>Quoted text</quote>

зажимаем Shite+Ctrl и жмем мышкой кнопку отправить (как в инструкции выше с викиреалити), и видим цитатку отправленную — на скриншоте пруф.
+2
edogs #
Скрин не вставился сразу:(
+12
edogs #
Подумали еще немного — теперь как-то вообще стало непонятно о чем статья…
Коротко: в скайпе есть специальные тэги для форматирования своих сообщений, позволяющие оформить любой текст в виде цитаты (с указанием никнейма, текста и времени отправки). Эти тэги описаны на вики, общедоступны и легки в применении. Они работают в том числе в последней версии скайпа. Однако если применить C#, то написав код и занявшись отладкой, их можно найти более сложным и интересным способом, чем просто забив в гугл запрос «как оформить цитату в скайпе»:) Где-то тут должна быть картинка буханки в виде троллейбуса.
Простите если что не так:-\
+3
nicolausYes #
В предыдущей статье, в конце, было сказано, что в последней версии скайпа на сайте(5.8) это уже пофиксено. Проверил то, что Вы написали, в 5.5, работает, в 5.8 — нет.

0
edogs #
Мы бы репортили об этом как «в одной из версий skype под винды не работает способ отправки своих сообщений с html форматированием» (в других работает, протокол поддерживает, под юниксом все ок), а не как «уязвимость в скайпе позволяет подделывать чужие цитаты»:)
+1
tangro #
Вы немного путаете методики «написали в гугле запрос — ура, что-то нашли!» и «реверс-инжениринг программы с целью самостоятельного определения используемых алгоритмов работы и структур данных». Чувствуете разницу?
+1
Ryadovoy #
Shite+Ctrl, интересно :)
Наверное с кнопкой Shite (брит. = shit) намного легче говнокодить :)
0
Abarmotic #
Все верно, цитаты можно спокойно делать голыми руками:
<quote author="blabla" authorname="Василий Пупкин" conversation="blablabla" timestamp="1329215546"><legacyquote>[12:23:34] Василий Пупкин: </legacyquote>Все подумают что это сказал Василий Пупкин</quote>


image

Атрибуты author, conversation и время в квадратных скобках игнорируются когда показывается цитата, а все остальное можно задать как угодно. Единственная «сложность» с timestamp, но его легко сделать на любую желаемую дату-время.
+6
ValdikSS #
А в линуксовом скайпе это все редактируется просто текстом.
0
und #
Pressing Cntr+V will: Paste message as a plain text
+5
khoody #
По-моему, вы придаёте чрезмерное значение цитатам в каком-то там скайпе, это же не нотариальная копия, чтобы уж прямо вот так. Все мы приучены интернетом (почтой и форумами главным образом), что цитаты оформляются вручную и вписать туда можно что угодно, вряд ли автоматизация этого процесса в скайпе повышает доверие к содержимому до сколько-нибудь опасной степени.

Но само наблюдение и исследование интересное!
+1
Evengard #
Можно было пойти путем попроще — создать цитату, запостить в какой нить чат а потом открыть файлы хистори либо любым редактором этой хистори, либо любым просмотрщиком sqlite баз.
+1
pewpew #
Кому что проще
0
Abarmotic #
Я ничего не понимаю, о чем здесь речь и почему все так сложно? Зачем писать какие-то программы или ковыряться в базах?
Любая цитата легко делается руками из пары тегов.
–2
iFrolov #
-_-
0
DizzWebS #
А я для того, чтобы потроллить одного человека, создавал аккаунт-копию, и типа от него цитаты писал, потом ему копировал, и тот удивлялся очень:) В топике все, конечно намного универсальней и проще:)
0
JustLuckyGuy #
Кому что проще :)
0
Nedder #
А кто-то знает простую программу для чтения текстов чата Skype из chatsync?
+6
Genome_X #
>которая, судя по изменениям моей кармы, не всем пришлась по нраву
Насрать на карму, пишите еще статьи! Я с помощью ваших статьей очень здорово развлекал себя и своих друзей в контакт-листе скайпа. Так что конкретно я весьма признателен вам за ваш материал.
+1
Artima #
Интересно, а такой «глубокий» интерес к скайпу как-то связан с его приобретением MS? :-)
0
phaoost #
хотел плюсануть вас за обе статьи, но не хватает кармы, поэтому просто выражаю благодарность :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.