2e957d9d208c3786089687e5df67e642.png

在使用模拟软件的COM接口进行样本自动生成的时候,经常会发生意外终止的情况,造成大量的时间浪费,所以有必要对程序进行保护。

经过总结和观察,程序意外终止的情况主要有三类:

1.程序未响应

2.内部错误弹窗

3.CPU占用过低或者过高(事实上不是由于电脑性能的问题,是因为同时开了多个虚拟机榨干了最后一点内存或者cpu算力)

程序未响应

首先要有一个杀死进程的按钮:

import os

def killRsim():
    os.system('taskkill /F /IM petro-sim.exe')

判断程序是否未响应我们需要借助windows内部的C++写好的方法,以及获得窗口句柄的方式,这里我们选择主程序的进程之一HyEditBar进行捕获即可

import win32gui
import ctypes

def isRsimHung():
    hwnd_Rsim = win32gui.FindWindow('HyEditBar', None)
    IsHungAppWindow = ctypes.windll.user32.IsHungAppWindow
    return IsHungAppWindow (hwnd_Rsim)

内部错误弹窗

内部错误弹窗一样可以通过句柄来捕获弹出的窗口,进而判断是否需要杀掉进程。

def isRsimFC():
    hwnd_RsimFC = win32gui.FindWindow('#32770', 'petro-sim')
    if hwnd_RsimFC != 0:
        return 1
    else:
        return 0

CPU占用过低或者过高

CPU长期过低或者过高的占用说明程序内部可能发生了错误,这里使用psutil来进行进程的CPU占用检测。

通过任意子进程获取进程ID即可。注意函数cpu_percent(interval = 180)则说明程序需要在这里等待180秒收集数据,所以相当于暂停了3分钟。

import win32process
import psutil

def isRsimBoom():
    hwnd_Rsim = win32gui.FindWindow('HyEditBar', None)
    RPID = win32process.GetWindowThreadProcessId(hwnd_Rsim)[1]
    try:
        p1 = psutil.Process(RPID)
        #the time must be longer than the longest restarting of Petro-sim, which depends on your hardware condition
        percent = p1.cpu_percent(interval = 180)
    except psutil.NoSuchProcess:
        return 0
    else:
        print ('CPU Usage : {}%'.format(percent))
        if percent == 0.0 or percent >= psutil.cpu_count() * 100:
            return 1
        else:
            return 0

特别注意,本脚本需要和生成样本的脚本在不同的进程下运行,属于后台程序。

import time

def Checker():
    def killRsim():
        os.system('taskkill /F /IM petro-sim.exe')
    def isRsimHung():
        hwnd_Rsim = win32gui.FindWindow('HyEditBar', None)
        IsHungAppWindow = ctypes.windll.user32.IsHungAppWindow
        return IsHungAppWindow (hwnd_Rsim)
    def isRsimFC():
        hwnd_RsimFC = win32gui.FindWindow('#32770', 'petro-sim')
        if hwnd_RsimFC != 0:
            return 1
        else:
            return 0
    def isRsimBoom():
        hwnd_Rsim = win32gui.FindWindow('HyEditBar', None)
        RPID = win32process.GetWindowThreadProcessId(hwnd_Rsim)[1]
        try:
            p1 = psutil.Process(RPID)
            #the time must be longer than the longest restarting of Petro-sim, which depends on your hardware condition
            percent = p1.cpu_percent(interval = 180)
        except psutil.NoSuchProcess:
            return 0
        else:
            print ('CPU Usage : {}%'.format(percent))
            if percent == 0.0 or percent >= psutil.cpu_count() * 100:
                return 1
            else:
                return 0
    if isRsimHung() or isRsimFC() or isRsimBoom():
        killRsim()
        print('No Response : {}; Internal Error : {}; High Usage : {}.'.format(bool(isRsimHung()), bool(isRsimFC()), bool(isRsimBoom())))
        print('RSIM died @ : ', time.asctime(time.localtime(time.time())))

最后是自制的进程信息观测器:

import pandas as pd

Windows = {'Title' : [], 'Class' : [], 'hWnd' : [], 'PID' : [], 'Name' : [], 
           'No Response' : []}
def foo(hwnd, mouse):
    #if IsWindow(hwnd) and IsWindowEnable(hwnd) and IsWindowVisible(hwnd):
    Windows['Title'].append(win32gui.GetWindowText(hwnd))
    Windows['Class'].append(win32gui.GetClassName(hwnd))
    Windows['hWnd'].append(hwnd)
    Windows['PID'].append(win32process.GetWindowThreadProcessId(hwnd)[1])
    Windows['Name'].append(psutil.Process(win32process.GetWindowThreadProcessId(hwnd)[1]).name())
    Windows['No Response'].append(bool(ctypes.windll.user32.IsHungAppWindow(hwnd)))
win32gui.EnumWindows(foo, 0)
Datas = pd.DataFrame(Windows).sort_values(by = 'PID', ascending = True)
for index in Datas.index:
    if Datas['No Response'][index]:
        print('Class : %s, Title : %s', Datas['Class'][index], Datas['Title'][index])
        print(Datas['Title'][index])

希望以上内容可以帮到你

更多推荐