Статьи Пишем бот Win программ. (Комикс в картинках).

Discussion in 'Статьи' started by IIIMbIrA, 17 Jan 2011.

  1. IIIMbIrA

    IIIMbIrA New Member

    Joined:
    14 Jan 2011
    Messages:
    3
    Likes Received:
    2
    Reputations:
    2
    Разберём технологию написания бота. Когда мне понадобился такой бот, я похожей
    статьи не нашёл (может плохо искал - теперь уже неважно). Бота я написал, пусть
    будет теперь и статья.

    Что нам понадобится?
    1) Spy++ (Входит в состав MS Visual Studio).
    2) Любая среда программирования, которая позволяет обращаться к Windows API. Лично я считаю
    что работать с API и не иметь нормальных указателей - это не правильно. Поэтому я буду
    пользоваться С++ Builder.

    Будем писать бота для программы "МегаФон Интернет", которая будет автоматически рассылать
    СМС. Точнее сказать программу то я уже написал давно, целей своих не добился (СМС-спам
    рассылка), т. к. реальная скорость рассылки не превышает 10-15 СМС в минуту. Но полученный
    опыт, как говориться, не пропьёшь.

    Немного теории. Все элементы интерфеса программ Windows: кнопки, поля для ввода, меню, ...
    все они являются окнами. Окну можно передавать сообщения функциями SendMessage(),
    PostMessage(). Например SendMessage(ht, WM_LBUTTONDOWN, 0, 0) - нажатие левой кнопки
    мыши на окне ht. Что такое ht? А это и есть главный описатель/указатель/идентификатор
    окна - хэндл. Таким образом написание бота это поиск хэндлов нужных элементов и отправка
    этим элементам нужных сообщений. Ещё важно напомнить что все окна в Windows выстроены в
    древовидную структуру. Корень дерева - рабочий стол (его хэндл можно получить функцией
    GetDesktopWindow()). Имея хэндл окна можно обратиться к соседнему окну справа, слева, выше
    или ниже в дереве. Можно при желании обойти всё дерево. Это нам не понадобиться, а вот
    определить положение нужного элемента относительно главного окна программы и затем
    добраться до его хэндла, имея хэндл главного окна - это как раз то, чем и придётся
    заниматься.

    Начнём. Создаём проект и пишем такой код:

    Code:
    HWND ht
    	ht = FindWindow(NULL, "МегаФон Интернет");
    То есть ищем хэндл главного окна программы, по его имени.
    Включаем Spy++.Находим там нашу программу.

    [​IMG]

    Для отправки СМС нам нужно сначала нажать кнопку "Новое".

    [​IMG]

    Ищем её смещение относительно главного окна. Для этого перебираем все окна поддерева нашей
    программы. И задаём в Spy++ вести лог событий для окна. И будем выводить в этот лог
    только сообщение нажатия левой кнопки мыши WM_LBUTTONDOWN. CTRL+M вкладка Messages.
    На вкладке Window ставим галочку Child Window. Это значит, что в лог будет записываться
    не только сообщения для выбранного окна, а для всего поддерева. Так мы быстрее доберёмся
    до нужного элемента.

    [​IMG]

    Выбираем первое поддерево программы. Настраиваем лог, как я написал. Запускаем Spy++.
    Нажимаем кнопку - ничего не пишется значит не то поддерево. Берём следующее поддерево.
    Оп, вот оно сообщение.

    [​IMG]

    Дальше раскрываем поддерево и делаем всё тоже самое для его веток.
    Так постепенно добираемся до самого нужного окна - кнопки "Новое". То есть мы нашли его
    смещение относительно главного окна.

    [​IMG]

    Чтобы программно симитиривать нажатие левой кнопки мыши на кнопке "Новое", добираемся
    до её хэндла. Будет выглядеть примерно так:

    Code:
    ht = FindWindow(NULL, "МегаФон Интернет");
             ht = GetWindow(ht, GW_CHILD);
             ht = GetWindow(ht, GW_HWNDNEXT);
              ht = GetWindow(ht, GW_CHILD);
              ht = GetWindow(ht, GW_HWNDNEXT);
               ht = GetWindow(ht, GW_CHILD);
                ht = GetWindow(ht, GW_CHILD);
                ht = GetWindow(ht, GW_HWNDNEXT);
                ht = GetWindow(ht, GW_HWNDNEXT);
                ht = GetWindow(ht, GW_HWNDNEXT);
                ht = GetWindow(ht, GW_HWNDNEXT);
                ht = GetWindow(ht, GW_HWNDNEXT);
                 ht = GetWindow(ht, GW_CHILD);
                  ht = GetWindow(ht, GW_CHILD);
    GW_HWNDNEXT - получаем хэндл следующего окна на том же уровне дерева. GW_CHILD - получаем
    хэндл первого окна, на следующем уровне дерева.
    Отправляем сообщения:

    Code:
     SendMessage(ht, WM_LBUTTONDOWN, 0, 0);
            SendMessage(ht, WM_LBUTTONUP,   0, 0);
    Кнопку нужно не только нажать но и отпустить.

    После этого у нас выскакивает новое окно, которое так и называется "Новое". Ищем его в
    трее Spy++. На этом окне нам нужно будет вбивать номера телефонов, текст самого
    сообщения и нажимать кнопку "Отправить". Как нажимать кнопку объяснять ещё раз не буду.
    Не буду объяснять и как найти хэндлы нужных элементов - всё как в первом случае. А вот
    как вписать текст в поле для ввода объясню:

    Code:
    SendMessage(ht, WM_SETTEXT, 0, LPARAM("Превед!"));
    Вот почти и всё, но не совсем. Прежде чем отправлять следуещее СМС, нужно дождаться
    окончания отправки текущего СМС. Это называется интерактивность. Я это решил просто.
    Пока окно "Новое" открыто, СМС ещё отправляется, когда окно закроется - СМС отправлено:

    Code:
    for(;;)
                    if(FindWindow(NULL, "Новое") == NULL) break;
    Вот и всё.
    Конечно задачи ботов могут быть намного сложнее. Например если нужно не дожидаясь
    завершения одного действия начинать второе - тогда нужны потоки. Определить завершение
    действия тоже может быть сложной задачей. Например по завершению действия, какой нибудь
    значёк может окраситься в другой цвет. Но если есть Spy++, зацепиться всегда есть за что.
    Самое гавное забыл написать - есть программы для написания простого бота (типа
    запись макроса в MS Word). Можете их нагуглить и скачать. Вот только проблему
    интерактивности они не решают, потоки в них также не создашь.

    Всем удачи!
     
    2 people like this.
  2. yak

    yak Member

    Joined:
    17 Nov 2007
    Messages:
    11
    Likes Received:
    5
    Reputations:
    0
    Писал такого бота года три назад для прибивания надоедливого окошка, когда закачиваешь много шрифтов разом и для автоматического нажатия кнопки "удалить" при обнаружении вируса в каспере. Только я пользовался не Spy++, какой-то самопальной программой, исходники которой были на пиратском диске со студией. Эта софтина позволяла искать данные любого окна, наводя на него мышкой, а не перекапывая 9000 логов.
     
  3. IIIMbIrA

    IIIMbIrA New Member

    Joined:
    14 Jan 2011
    Messages:
    3
    Likes Received:
    2
    Reputations:
    2
    to yak

    Да в общем и в Spy++ есть Finder Tool. Зажимаешь его мышью и наводишь на элементы управления. Но им можно до нужной кнопки и не добраться. Например если кнопка находится на Toolbar, но не является его CHILD WINDOW. Он найдёт только Toolbar, а кнопка будет в другом поддереве. Так что вопрос этот мутный и я сомневаюсь, что есть такая программа, которая прям от корня до самого элемента покажет весь путь при наведении мыши. Ведь элементы могут находиться один над другим и не факт, что тебе нужен именно самый верхний из них или самый нижний. Так что перебор всего дерева Spy++ может оказаться единственным выходом.
     
  4. WALKMAN

    WALKMAN Elder - Старейшина

    Joined:
    30 Dec 2007
    Messages:
    61
    Likes Received:
    2
    Reputations:
    0
    У меня вопрос. А бот будет работать если сама программа будет свернута, а физичесская мышка будет заниматься своими делами)
     
  5. IIIMbIrA

    IIIMbIrA New Member

    Joined:
    14 Jan 2011
    Messages:
    3
    Likes Received:
    2
    Reputations:
    2
    1)При отправке окну сообщений оно скорее всего всё равно будет разворачивоться. (Есть решение - после отправки сообщений контролам, также программно сворачивать и главное окно. Не пробовал, но должно сработать).
    2)Работа бота никак не затрагивает "физическую" мышку, даже курсор никуда не перемещается.