在Windbg中安装mona插件

1.从https://github.com/corelan/mona以及https://github.com/corelan/windbglib上分别下载windbglib以及mona文件,放在windbg的根目录下。

2.从https://githomelab.ru/pykd/pykd-ext下面,点击以下链接,下载pykd.dll,文件放在windbg目录下的winext文件夹下面。

3.Windbg里面尝试 .load pykd !py mona运行,可以看到如下信息,这是因为py2.7没有安装pykd库(很多网上的教程都没有说到这一点)

4.使用python2.7安装pykd库

5.复制windbglib中pykd03.zip压缩包里面的msdia120.dll到C:\Program Files (x86)\Common Files\microsoft shared\VC并注册

6.启用Windbg,加载插件

Windows计算CPU使用率为负数的排查

最近在项目中需要计算CPU的使用率,于是从网上找到了一些通用的代码,代码如下

DWORD WINAPI CPURateProc(PVOID pParam)
{   
    static UINT SystemBasicInformation = 0;
    static UINT SystemPerformanceInformation = 2;
    static UINT SystemTimeInformation = 3;

#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))

    typedef struct
    {
        DWORD dwUnknown1;
        ULONG uKeMaximumIncrement;
        ULONG uPageSize;
        ULONG uMmNumberOfPhysicalPages;
        ULONG uMmLowestPhysicalPage;
        ULONG uMmHighestPhysicalPage;
        ULONG uAllocationGranularity;
        PVOID pLowestUserAddress;
        PVOID pMmHighestUserAddress;
        ULONG uKeActiveProcessors;
        BYTE bKeNumberProcessors;
        BYTE bUnknown2;
        WORD wUnknown3;
    } SYSTEM_BASIC_INFORMATION;

    typedef struct
    {
        LARGE_INTEGER liIdleTime;
        DWORD dwSpare[152];
    } SYSTEM_PERFORMANCE_INFORMATION;

    typedef struct
    {
        LARGE_INTEGER liKeBootTime;
        LARGE_INTEGER liKeSystemTime;
        LARGE_INTEGER liExpTimeZoneBias;
        ULONG uCurrentTimeZoneId;
        DWORD dwReserved;
    } SYSTEM_TIME_INFORMATION;

    typedef LONG(WINAPI *PROCNTQSI)(UINT, PVOID, ULONG, PULONG);

    PROCNTQSI NtQuerySystemInformation;

    SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
    SYSTEM_TIME_INFORMATION SysTimeInfo;
    SYSTEM_BASIC_INFORMATION SysBaseInfo;
    double dbIdleTime;
    double dbSystemTime;
    LONG status;
    LARGE_INTEGER liOldIdleTime = { 0,0 };
    LARGE_INTEGER liOldSystemTime = { 0,0 };

    NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(GetModuleHandleW(L"ntdll"), "NtQuerySystemInformation");

    if (!NtQuerySystemInformation)
        return -1;

    // get number of processors in the system 
    status = NtQuerySystemInformation(SystemBasicInformation, &SysBaseInfo, sizeof(SysBaseInfo), NULL);
    if (status != NO_ERROR)
    {
        return -1;
    }

    for (int i = 0; i < 2; i++)
    {
        // get new system time 
        status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0);       ①
        if (status != NO_ERROR)
        {
            return -1;
        }

        // get new CPU's idle time 
        status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL);     ②
        if (status != NO_ERROR)
        {
            return -1;
        }

        // if it's a first call - skip it 
        if (liOldIdleTime.QuadPart != 0)
        {
            // CurrentValue = NewValue - OldValue 
            dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
            dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);

            // CurrentCpuIdle = IdleTime / SystemTime 
            dbIdleTime = dbIdleTime / dbSystemTime;

            // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors 
            dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;

            //PrintDbgInfo ((s));
            return (UINT)dbIdleTime;
        }

        // store new CPU's idle and system time 
        liOldIdleTime = SysPerfInfo.liIdleTime;
        liOldSystemTime = SysTimeInfo.liKeSystemTime;

        // wait one second 
        Sleep(1000);
    }

    return -1;
}

这里可以看出,计算CPU使用率的步骤主要有以下几步:

(1)获取空闲时间和系统时间

(2)休息一秒钟

(3)再次计算空闲时间和系统时间,通过差值计算CPU的使用率

但是在进行调试的时候,会偶尔发生出现CPU使用率为负值的情况,因为网上的代码怎么搜都大致都是千篇一律的,所以只能自己排查分析。打印各个变量值,找出问题的原因。

打印的出问题的情况时调试信息如下:

可以看出,dbSystemTime的值实际结果应为10000000(Sleep一秒钟),但是比实际值大了一些。原因是在我们在①处调用API获取结果时,也是会增加SystemTime的,所以实际的结果要比预测的结果偏大。dbIdleTime代表的是每个CPU空闲时间的总和(比如有8核CPU,Sleep 1秒以后获取的结果应为80000000)。可以看出,在②处调用时,因为是在①调用之后调用,误差会进一步增加。

导致的结果就是dbIdleTime = dbIdleTime / dbSystemTime;所计算出的值偏大(大于8)

所以导致最后的dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;
计算结果在误差很大的情况下会小于0(虽然加了0.5,但是并没有什么卵用)。这个问题在CPU核心数很多的情况下是,造成的误差会很大。

解决的方法很简单:可以考虑在误差较大时(计算出的偏差值大于CPU的核心数时)修正CPU的使用率为0

            // CurrentCpuIdle = IdleTime / SystemTime 
            dbIdleTime = dbIdleTime / dbSystemTime;

            //添加
            //空闲时间近似等于CPU核心数时,修正CPU使用率为0
            if ((int)dbIdleTime == SysBaseInfo.bKeNumberProcessors)
            {
                return 0;
            }

 

 

基于机器学习的病毒鉴定(antivirus_demo)学习

antivirus_demo(https://github.com/llSourcell/antivirus_demo)是一个基于机器学习的简单的病毒分析项目,基于大量已有的样本,分析其中的特征,并以此对未知的样本进行检测,这次主要总结一下最初的学习部分。

1.基于树划分构建特征树,选择最重要的特征(在checkpe中会使用到)

fsel = ske.ExtraTreesClassifier().fit(X, y)
model = SelectFromModel(fsel, prefit=True)
X_new = model.transform(X)
nb_features = X_new.shape[1]

X_train, X_test, y_train, y_test = cross_validation.train_test_split(X_new, y ,test_size=0.2)

features = []

print('%i features identified as important:' % nb_features)

2.对样本利用五种算法进行训练,并输出测试数据测试准确性,打分

algorithms = {
        "DecisionTree": tree.DecisionTreeClassifier(max_depth=10),   #决策树
        "RandomForest": ske.RandomForestClassifier(n_estimators=50),   #随机森林
        "GradientBoosting": ske.GradientBoostingClassifier(n_estimators=50),      #类似AdaBoost
        "AdaBoost": ske.AdaBoostClassifier(n_estimators=100),  #AdaBoost弱分类器
        "GNB": GaussianNB()              #高斯朴素贝叶斯
    }

results = {}
print("\nNow testing algorithms")
for algo in algorithms:
    clf = algorithms[algo]
    clf.fit(X_train, y_train)
    score = clf.score(X_test, y_test)
    print("%s : %f %%" % (algo, score*100))
    results[algo] = score

winner = max(results, key=results.get)
print('\nWinner algorithm is %s with a %f %% success' % (winner, results[winner]*100))

3.保存所有的预测结果至文件中,供后面checkpe使用

TF中avg_pool和conv2d使用示例和计算说明

import tensorflow as tf  
import numpy as np  

#https://blog.csdn.net/fengyuzhe13/article/details/78761298
  
#3*3大小的图片
M = np.array([  
        [[1],[-1],[0]],  
        [[-1],[2],[1]],  
        [[0],[2],[-2]]  
    ])  
  
print ("Matrix shape is: ",M.shape)  

#卷积核大小为2*2 通道数为1 卷积核个数为1 并初始化好对应的值
filter_weight = tf.get_variable('weights', [2, 2, 1, 1], initializer = tf.constant_initializer([ [1, -1],  
                                                 [0, 2]]))  
#初始化偏置参数
biases = tf.get_variable('biases', [1], initializer = tf.constant_initializer(1))  
  
M = np.asarray(M, dtype='float32')

#图片规格为1张 大小3*3  通道数为1
M = M.reshape(1, 3, 3, 1)  
print("Reshaped M: \n", M)  

#初始化参数x,后面会赋值为M  
x = tf.placeholder('float32', [1, None, None, 1]) 

# 在3x3的M的右边和下面补零,卷积窗口每次移动两个单位。得到的conv为2x2的矩阵,再转成高维矩阵--[1, 2, 2, 1]  
conv = tf.nn.conv2d(x, filter_weight, strides = [1, 2, 2, 1], padding = 'SAME')  

# 将卷积求得的值加上偏置就为所求值  
bias = tf.nn.bias_add(conv, biases)  

# 在3x3的M的右边和下面不补零,卷积窗口从左上角每次移动两个单位,遇到数据不足时,只取当前数据。  
# 得到的pool为2x2的矩阵,再转成高维矩阵--[1, 2, 2, 1]                                              
pool = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

#池化层计算方法:
#avg_pool:计算平均值
#左上:四个值加起来/4= (1+(-1)+(-1)+2)/4=0.25
#右上:因为padding='SAME所以只有两个值: (0+0+0+1)/2=0.5
#左下:(0+2+0+0)/2=1
#右下:只有一个值(-2)/1=-2

#(星号代表开始计算的点)
#padding='SAME' 时
#   *.*
#   ...
#   *.*


#padding='VAILD' 时
#  *..
#  ...
#  ...

with tf.Session() as sess:  
    tf.global_variables_initializer().run()  
    convoluted_M = sess.run(bias,feed_dict={x:M})  
    pooled_M = sess.run(pool,feed_dict={x:M})  
      
    print ("convoluted_M: \n", convoluted_M.reshape(2, 2))  
    print ("pooled_M: \n", pooled_M.reshape(2, 2))  

输出结果,可以看到池化层的结果(pooled_M)和上面手工计算的结果相同 :

当padding=’VAILD’时的输出结果,可以看出确实只有一个值

C++项目文件包含规则心得

今天花了2个小时对一个C++中等项目代码中的文件包含部分重新进行了整理,相信很多人都遇到过各种因为头文件包含顺序的问题导致的各种错误*100,正在停止编译。。看着一大堆错误真心下不了手,所以在项目的开始阶段,针对各个文件的包含需要有一个严格的规定。下面简单说一下个人对文件包含的理解。

1.新建项目时,利用一个头文件包含所有的公共头文件(项目中使用到的)

2.针对各个类的头文件,切记一定不要在头文件中包含任何的头文件!!!!!(很重要)

3.针对各个类的cpp文件,包含顺序如下:

(1)Gloabl.h公共头文件

(2)自己需要的其他类的定义文件(其他类最好头文件做到不包含任何模块)

(3)这个类本身的.h头文件

针对公共头文件的包含顺序:
1.基础库(STL等)
2.项目基础设施
3.其他需要包含的头文件

高斯函数与局部加权线性回归

高斯核函数的特性:离预测点远的点不参与统计,所以预测一个点时只需要根据那个点附近的几个点算回归线

b:尖峰中心的坐标 在局部加权线性回归时为待预测点的坐标
c:也就是峰的陡峭程度。当值越小时,峰越陡,此时局部加权线性回归中取到的局部点越少(实例代码取值默认为1)
x:输入参数(局部加权线性回归时为所有数据点形成的矩阵)

(x-b)^{2}

用矩阵的计算方式为 (mat(x)-b)*(mat(x)-b).T(转置)

关键处代码:

def lwlr(testPoint,xArr,yArr,k=1.0):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    m = np.shape(xMat)[0]
    weights = np.mat(np.eye((m)))
    for j in range(m):                      #next 2 lines create weights matrix
        #xMat[j,:] 把每一行的内容全部取出来
        diffMat = testPoint - xMat[j,:]   #x-b

        #高斯核函数
        #diffMat*diffMat.T其实就是(x-b)^2
        weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2))   #k即为高斯图上的c值
    xTx = xMat.T * (weights * xMat)
    if np.linalg.det(xTx) == 0.0:
        print ("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T * (weights * yMat))
    return testPoint * ws