Cuckoo沙箱-模拟点击事件


背景介绍

很多恶意样本并不一定直接运行就能表现出恶意行为。例如msi格式,就需要先行安装。 或者有部分exe执行需要点击按钮才能继续下一步,因此就很有必要在样本执行的时候自动去点击按钮,以便样本继续运行,挖掘出其恶意行为。

Talk is cheap, Show me the code


	"""
	@author: vevenlcf
	@time: 20190712
	@dec: 模拟鼠标点击事件
	@email: vevenlcf@gmail.com
	@blog: https://vevenlcf.github.io/blog/
	"""
	from ctypes import *
	import random
	USER32   = windll.user32
	KERNEL32 = windll.kernel32
	import re
	
	WM_CLOSE = 0x00000010
	WM_GETTEXT = 0x0000000D
	WM_GETTEXTLENGTH = 0x0000000E
	BM_CLICK = 0x000000F5
	
	# 获取系统分辨率 、窗体显示区域的宽度和高度
	RESOLUTION = {
	    "x": USER32.GetSystemMetrics(0),
	    "y": USER32.GetSystemMetrics(1)
	}
	
	#随机挪动鼠标
	def move_mouse():
	    x = random.randint(0, RESOLUTION["x"])
	    y = random.randint(0, RESOLUTION["y"])
	    print(x,y)
	    # Originally was:
	    # USER32.mouse_event(0x8000, x, y, 0, None)
	    # Changed to SetCurorPos, since using GetCursorPos would not detect
	    # the mouse events. This actually moves the cursor around which might
	    # cause some unintended activity on the desktop. We might want to make
	    # this featur optional.
	    USER32.SetCursorPos(x, y)
	    #num = x/2
	    #USER32.SetCursorPos(int(num), 0)
	
	# 点击鼠标
	def click_mouse():
	    # Move mouse to top-middle position.
	    num = int(RESOLUTION["x"] / 2)
	    USER32.SetCursorPos(num, 0)
	    # Mouse down. 左键点击
	    USER32.mouse_event(2, 0, 0, 0, None)
	    KERNEL32.Sleep(50)
	    # Mouse up.   左键松开
	    USER32.mouse_event(4, 0, 0, 0, None)
	
	# 按钮点击
	def click(hwnd):
	    # 指定窗口激活到最顶层,键盘转到该窗口
	    USER32.SetForegroundWindow(hwnd)
	    KERNEL32.Sleep(1000)
	    # 发送按钮点击事件消息
	    USER32.SendMessageW(hwnd, BM_CLICK, 0, 0)
	
	# 遍历子窗口
	def foreach_child(hwnd, lparam):
	    print("=====================================================>>>>>>>>>>")
	    # List of partial buttons labels to click. 列举了一些窗口按钮标题!!!
	    buttons = [
	        "yes", "oui",
	        "ok",
	        "i accept",
	        "next", "suivant",
	        "new", "nouveau",
	        "install", "installer",
	        "file", "fichier",
	        "run", "start", "marrer", "cuter",
	        "i agree", "accepte",
	        "enable", "activer", "accord", "valider",
	        "don't send", "ne pas envoyer",
	        "don't save",
	        "continue", "continuer",
	        "personal", "personnel",
	        "scan", "scanner",
	        "unzip", "dezip",
	        "open", "ouvrir",
	        "close the program",
	        "execute", "executer",
	        "launch", "lancer",
	        "save", "sauvegarder",
	        "download", "load", "charger",
	        "end", "fin", "terminer"
	        "later",
	        "finish",
	        "end",
	        "allow access",
	        "remind me later",
	        "save", "sauvegarder",u"保存"
	    ]
	
	    # List of complete button texts to click. These take precedence.
	    buttons_complete = [
	        "&Ja",  # E.g., Dutch Office Word 2013.
	    ]
	
	    # List of buttons labels to not click.
	    dontclick = [
	        "don't run",
	        "i do not accept"
	    ]
	
	    classname = create_unicode_buffer(50)
	    USER32.GetClassNameW(hwnd, classname, 50)
	
	    print("classname.value:" , classname.value.lower())
	    # Check if the class of the child is button.
	    if "button" in classname.value.lower():
	        print("button=====================================")
	        # Get the text of the button.
	        length = USER32.SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0)
	        text = create_unicode_buffer(length + 1)
	        USER32.SendMessageW(hwnd, WM_GETTEXT, length + 1, text)
	        print("==>", classname.value, text.value)
	        if text.value in buttons_complete:
	            print("Found button %r, clicking it" % text.value)
	            click(hwnd)
	            return True
	
	        # Check if the button is set as "clickable" and click it.
	        textval = text.value.replace("&", "").lower()
	        for button in buttons:
	            if button in textval:
	                for btn in dontclick:
	                    if btn in textval:
	                        break
	                else:
	                    print("Found button %r, clicking it" % text.value)
	                    click(hwnd)
	
	    # Recursively search for childs (USER32.EnumChildWindows).
	    return True
	
	def foreach_window(hwnd, lparam):
	    # If the window is visible, enumerate its child objects, looking
	    # for buttons.
	    if USER32.IsWindowVisible(hwnd):
	        USER32.EnumChildWindows(hwnd, EnumChildProc(foreach_child), 0)
	    return True
	
	# Callback procedure invoked for every enumerated window.
	# Purpose is to close any office window
	def get_office_window(hwnd, lparam):
	    if USER32.IsWindowVisible(hwnd):
	        text = create_unicode_buffer(1024)
	        # 遍历 桌面窗口 标题
	        USER32.GetWindowTextW(hwnd, text, 1024)
	        print("text:" ,text.value)
	        # 注意界面框架 一定要是用符合accExplorer,发现标题为
	        if re.search("google", text.value):
	            print("find google window.")
	            if USER32.IsWindowVisible(hwnd):
	                USER32.EnumChildWindows(hwnd, EnumChildProc(foreach_child), 0)
	        # 发现office 相关!!!
	        # TODO Would " - Microsoft (Word|Excel|PowerPoint)$" be better?
	        # if re.search("- (Microsoft|Word|Excel|PowerPoint)", text.value):
	        #     USER32.SendNotifyMessageW(hwnd, WM_CLOSE, None, None)
	        #     print("Closed Office window.")
	    return True
	
	print (RESOLUTION["x"], RESOLUTION["y"])
	
	# 挪动鼠标
	move_mouse()
	# 点击鼠标
	click_mouse()
	
	EnumChildProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
	EnumWindowsProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
	
	#遍历桌面应用程序
	USER32.EnumWindows(EnumWindowsProc(get_office_window), 0)