• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Статья Поиск модераторов групп ВК по картинкам GIF с помощью Python

Прочитал тут новость-инструкцию, как можно найти ссылку на страницу модератора-администратора группы. Многие пишут, что данная информация уже довольно старая. Но, тем не менее, я ее увидел в первый раз и подумал, что можно это дело слегка автоматизировать. То есть, для того, чтобы найти модератора, а иногда их несколько у группы, вовсе не обязательно искать gif на странице. Достаточно написать небольшой скрипт на Python, который будет делать это за вас. А вам останется только проверить результаты поиска.

photo-collage-example-0027_1280.jpg

Дисклеймер: Все данные, предоставленные в данной статье, взяты из открытых источников, не призывают к действию и являются только лишь данными для ознакомления, и изучения механизмов используемых технологий.


Что понадобиться?

Для начала установим основной инструмент, с помощью которого и будем работать с группами ВК. Пишем в терминале команду:

pip install vk-api

Чтобы вывод в терминал не был скучным, а заиграл новыми красками, установим colorama. Для этого пишем в терминале:

pip install colorama

Также вам понадобиться получить vk-api token. Где и как его получать, можете почитать вот в этой статье, в начале.
Токен я вынес в отдельный файл, чтобы не светить в коде. Импортируем то, что установили в скрипт и инициализируем colorama:

Python:
from colorama import Fore
from colorama import init
from vk_api import VkApi

from set import token

init()

Создадим сессию ВК в которую передадим токен.

session = VkApi(token=token)


Поиск информации в ленте группы с заданными параметрами

Создадим функцию get_group_photo(group_id). В нее нужно на входе передается id группы. Согласно условию поиска модераторов, нужно для начала найти все посты в ленте, в которых есть картинки с расширением «.gif». Причем, данные посты должны быть опубликованы именно от имени группы, а не просто случайным пользователем, если в группе разрешен свободный постинг сообщений.

Получим количество gif в ленте. Для этого воспользуемся методом wall.search, которые принимает следующие параметры: owner_id – id группы, которое должно передаваться с указанием «-» в начале, иначе поиск будет пытаться найти все на стене соответствующего id пользователя; access_token – полученный токен для доступа к api; query – поисковый запрос, в котором мы явно укажем, что хотим найти, а именно – «.gif»; owners_only – данный параметр имеет два значения, 1 и 0, что соответствует поиску 1 – только сообщений от имени группы, 0 – всех сообщений; offset – смещение, которое нужно для того, чтобы выполнить поиск по всем картинкам, так как поиск за один раз возвращает не более ста объектов, что указывается в следующем параметре; count – параметр, в котором указывается, сколько результатов поиска нужно отобразить, но не более 100; v – версия api. Также, укажем сразу же ключ json, из которого нужно получать информацию.

Python:
    count = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif', owners_only=1,
                                          offset=0, count=1, v=5.81)['count']

Теперь создадим множество, в которое будем складывать все id найденных модераторов, так как постов может быть много, а значит, и id будут повторяться. Вот, для того, чтобы избежать повторов, мы и будем использовать множество. Затем проверим, не является ли количество результатов поиска равным 0. Если да, возвращаем из функции пустое множество. Нет – выводим в терминал информацию о количестве найденных картинок.

Python:
    set_moder = set()

    if count == 0:
        return set_moder
    else:
        print(Fore.GREEN + f'Найдено: {count} картинок')

Как вы помните, если картинок более ста, нужно будет указывать смещение, для получения всех результатов. Пишем проверку, если количество результатов поиска больше 100, запускаем цикл по диапазону от 0 до количества результатов поиска, с шагом 100. Выводим на экран информацию, что ищем модераторов. И снова запускаем поиск с помощью метода wall.search, куда передаем смещение – offset, чтобы получить очередную порцию результатов.

Python:
    if count > 100:
        for offset in range(0, count, 100):
            print(Fore.YELLOW + f'\rПоиск модераторов. Смещение: {offset+100}', end='')
            search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                                   owners_only=1, offset=offset, count=100, v=5.81)['items']

Теперь в цикле пробегаемся по результатам поиска, которые приходят в виде json и добавляем в множество найденные id. ID ищется в ссылке на gif, то есть, для примера, у вас есть ссылка: https://vk.com/doc8893688_448695956. Здесь нужно забрать id, которое указывается после doc и до «_». То есть в данном случае это будет 8893688. Поэтому, забираем ссылку, если она есть, разбиваем ее по «/», забираем третий элемент списка, тут же разбиваем его по «_» и заменяем doc на пустоту. Таким образом мы получим идентификатор. Если же такого ключа нет, обработаем исключение, в котором укажем, что надо продолжать цикл.

Python:
            for item in search:
                try:
                    set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", ""))
                except KeyError:
                    continue

Если количество результатов поиска меньше 100, то проделываем все то же самое, за исключением того, что здесь нам смещение не нужно, а значит, можно цикл по диапазону не запускать.

Python:
        search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                               owners_only=1, offset=0, count=count, v=5.81)['items']

        for num, item in enumerate(search):
            print(Fore.YELLOW + f'\rПоиск модераторов: {num + 1}', end='')
            try:
                set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", "id"))
            except KeyError:
                continue

В конце возвращаем множество из функции, даже если оно пустое.

Python:
def get_group_photo(group_id):
    count = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif', owners_only=1,
                                          offset=0, count=1, v=5.81)['count']

    set_moder = set()

    if count == 0:
        return set_moder
    else:
        print(Fore.GREEN + f'Найдено: {count} картинок')

    if count > 100:
        for offset in range(0, count, 100):
            print(Fore.YELLOW + f'\rПоиск модераторов. Смещение: {offset+100}', end='')
            search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                                   owners_only=1, offset=offset, count=100, v=5.81)['items']

            for item in search:
                try:
                    set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", ""))
                except KeyError:
                    continue
    else:
        search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                               owners_only=1, offset=0, count=count, v=5.81)['items']

        for num, item in enumerate(search):
            print(Fore.YELLOW + f'\rПоиск модераторов: {num + 1}', end='')
            try:
                set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", "id"))
            except KeyError:
                continue
    return set_moder


Получение информации о найденных модераторах

Много информации забирать не будем. В данном случае будет достаточно Ф.И.О. и ссылки на профиль, хотя, в теории, ссылка то уже есть, но, надо же чтобы было красиво. Поэтому, создадим функцию get_user_info(moder_list). На входе она получает список множество с найденными id модераторов. Объявим словарь для пользовательских данных. Суда мы будем добавлять то, что получили в запросе.

user_dict = dict()

Теперь в цикле пробежимся по полученному множеству и будем забирать оттуда id. Для получения данных о пользователе воспользуемся методом users.get, в который передавать, кроме user_id ничего не будем. Затем пробежимся в цикле по полученному json с данными. Так как мы не указывали, что желаем получить дополнительные параметры, нам в ответе прилетит немного информации, из которой мы заберем только имя и фамилию. Заодно будем определять, является ли аккаунт действующим, так как некоторые аккаунты уже удалены, по прошествии времени. То есть, мы попытаемся получить ключ «deactivated». Если ключ получен, значит не делаем ничего. Если же ключа нет, сработает исключение, и мы добавим данные о пользователе в словарь. После чего вернем словарь их функции.

Python:
def get_user_info(moder_list):
    user_dict = dict()

    for num, moder in enumerate(moder_list):
        print(Fore.YELLOW + f'\rПоиск информации о модераторах: {num+1}', end='')
        user_info = session.get_api().users.get(user_id=moder)
        for user in user_info:
            try:
                user['deactivated']
            except KeyError:
                user_dict.update({num: user})

    return user_dict


Вывод полученных данных в терминал

Создадим функцию print_data(user_dict, user_input). На вход функции передадим словарь с данными модераторов и название группы. Где мы его возьмем – об этом чуть ниже. Затем пробежимся в цикле по словарю и выведем в терминал Ф.И.О. и ссылку на страницу.

Python:
def print_data(user_dict, user_input):
    ln = len(f'ДАННЫЕ О МОДЕРАТОРАХ ГРУППЫ: {user_input.upper()}')
    print(Fore.GREEN + f'\n\nДАННЫЕ О МОДЕРАТОРАХ ГРУППЫ: {user_input.upper()}\n{"*"*ln}')
    for item in user_dict:
        print(Fore.RESET + f"   Ф.И.О.: {user_dict[item]['first_name']} {user_dict[item]['last_name']}")
        print(Fore.RESET + f"   Ссылка на страницу: https://vk.com/id{user_dict[item]['id']}\n   {'*'*55}")


Получение пользовательского ввода, определение id группы и ее названия

Создадим функцию main(). Здесь запросим у пользователя ссылку на группу. Ссылки на группы могут быть разного плана. У некоторых это публичная страница, у некоторых именно группа по интересам. И соответственно, в ссылке может отображаться то имя, которое указал пользователь, а не ее id. А если пользователь не указал, то просто club121545121, например. Вот мы все это чтобы не проверять, просто определим id. Для начала распилим полученную от пользователя ссылку по «/» и заберем последний элемент. Затем с помощью vk_api и его метода getById, передадим полученное имя в запросе, а также токен. В ответ нам прилетит json, в котором будет содержаться id группы, а также ее название. Вот их то нам оттуда и надо будет забрать.

Далее, запускаем поиск фото в ленте группы. Проверяем, не является ли найденное количество id 0. Если нет, запускаем функцию получения данных пользователя. Когда дынные пользователей будут получены, выводим их в терминал.

Python:
def main():
    user_input = input('Введите ссылку на группу: ')
    group_temp = user_input.split("/")[-1]

    group = session.get_api().groups.getById(group_id=group_temp, access_token=token, v=5.81)

    moder = get_group_photo(group[0]['id'])
    if len(moder) > 0:
        print(Fore.GREEN + f'\n\nНАЙДЕНО МОДЕРАТОРОВ: {len(moder)}')
        user_dict = get_user_info(moder)
        print_data(user_dict, group[0]['name'])
    else:
        print(Fore.RED + '\n[-] Данных о модераторах группы не найдено')

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

Вот, для примера, результаты поиска:

screenshot1.png

Python:
# pip install vk-api
# pip install colorama

from colorama import Fore
from colorama import init
from vk_api import VkApi

from set import token

init()
session = VkApi(token=token)


def get_group_photo(group_id):
    count = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif', owners_only=1,
                                          offset=0, count=1, v=5.81)['count']

    set_moder = set()

    if count == 0:
        return set_moder
    else:
        print(Fore.GREEN + f'Найдено: {count} картинок')

    if count > 100:
        for offset in range(0, count, 100):
            print(Fore.YELLOW + f'\rПоиск модераторов. Смещение: {offset+100}', end='')
            search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                                   owners_only=1, offset=offset, count=100, v=5.81)['items']

            for item in search:
                try:
                    set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", ""))
                except KeyError:
                    continue
    else:
        search = session.get_api().wall.search(owner_id=f'-{group_id}', access_token=token, query='.gif',
                                               owners_only=1, offset=0, count=count, v=5.81)['items']

        for num, item in enumerate(search):
            print(Fore.YELLOW + f'\rПоиск модераторов: {num + 1}', end='')
            try:
                set_moder.add(item["attachments"][0]["doc"]["url"].split("/")[3].split("_")[0].replace("doc", "id"))
            except KeyError:
                continue
    return set_moder


def get_user_info(moder_list):
    user_dict = dict()

    for num, moder in enumerate(moder_list):
        print(Fore.YELLOW + f'\rПоиск информации о модераторах: {num+1}', end='')
        user_info = session.get_api().users.get(user_id=moder)
        for user in user_info:
            try:
                user['deactivated']
            except KeyError:
                user_dict.update({num: user})

    return user_dict


def print_data(user_dict, user_input):
    ln = len(f'ДАННЫЕ О МОДЕРАТОРАХ ГРУППЫ: {user_input.upper()}')
    print(Fore.GREEN + f'\n\nДАННЫЕ О МОДЕРАТОРАХ ГРУППЫ: {user_input.upper()}\n{"*"*ln}')
    for item in user_dict:
        print(Fore.RESET + f"   Ф.И.О.: {user_dict[item]['first_name']} {user_dict[item]['last_name']}")
        print(Fore.RESET + f"   Ссылка на страницу: https://vk.com/id{user_dict[item]['id']}\n   {'*'*55}")


def main():
    user_input = input('Введите ссылку на группу: ')
    group_temp = user_input.split("/")[-1]

    group = session.get_api().groups.getById(group_id=group_temp, access_token=token, v=5.81)

    moder = get_group_photo(group[0]['id'])
    if len(moder) > 0:
        print(Fore.GREEN + f'\n\nНАЙДЕНО МОДЕРАТОРОВ: {len(moder)}')
        user_dict = get_user_info(moder)
        print_data(user_dict, group[0]['name'])
    else:
        print(Fore.RED + '\n[-] Данных о модераторах группы не найдено')


if __name__ == "__main__":
    main()

А на этом, пожалуй, все.

Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
 
Последнее редактирование:
  • Нравится
Реакции: dennykit25 и Faust_1st
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!