1.从产品角度的宏观结构及特点

1.1 宏观结构

产品组成

客户端:
负责ui显示与获取用户输入。
执行端:
1.负责对客户本地环境的信息收集与环境提取
2.负责控制客户本地环境的修改与操作
查杀端:
云端数据库(知识产权保护)。
文件大小:
1.负责病毒库与其他识别特征的存储
2.负责样本的匹配与识别

产品逻辑

静态查杀的逻辑:
文件落地—–>执行端——>提取文件和环境信息并做信息简化—–>查杀端—–>判断识别—–>如果是恶意文件—–>返回给执行端—–>给客户端—–>弹框—–>如果要查杀—–>发送给执行端执行。
动态查杀的逻辑:
运行程序——>监控——>匹配行为——>把这个进程对应的静态文件信息提取出来——>查杀端——>判断识别——>如果是恶意文件——>返回给执行端——>给客户端——>弹框——>如果要查杀——>发送给执行端执行。

1.2 特点与思考

杀毒软件作为产品需要的特点:

1.查杀速度快

为了提高查杀速度,杀软获取木马特征时可能只获取部分程序的地址信息,这时可以将恶意代码写到其他不检测的地址里。

2.占用空间少

为了减少杀软在客户的电脑内存,杀软会将病毒库放在云端数据库。

3.误杀率低

为了减少误杀率,杀软会将常用的系统api加入白名单,这时使用白名单api来调用恶意代码就可以绕过杀软。

2.从代码角度的处理细节分析

2.1 读取二进制文件内容

 
#include <iostream> 
#include <Windows.h> 
#include <stdlib.h> 
#include <stdio.h> 
OVERLAPPED __Overlapped = { 0 };
void main()
{    
    unsigned long lpNumber=0;
    char lpBuffer[]="";//文件读取的内容
    char IP_path[]="test.exe";
    
    
    HANDLE hFile= CreateFile(IP_path,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hFile==INVALID_HANDLE_VALUE)
    {   
        MessageBox(NULL,"创建文件句柄出错","error",MB_OK);
    }
    int filesucc=ReadFileEx(hFile,lpBuffer,sizeof(lpBuffer),//读取文件中多少内容
        &__Overlapped,  NULL);
    CloseHandle(hFile);
    printf("内容是:%x",lpBuffer);
    if(filesucc==0)
    {    
        MessageBox(NULL,"读取文件失败","error",MB_OK);
    }
    return;
}

 

 

2.2 内存扫描

2.2.1 内存内容扫描

#include <windows.h>
#include <stdio.h>
void main() {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    HANDLE hProcess = NULL;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    if (!CreateProcess(L".\\test.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
    {
        printf("CreateProcess2 failed (%d)\n", GetLastError());
    }
    WaitForSingleObject(pi.hProcess, 1000);//创建了一个进程
    byte* readtemp = new byte[256 * 16];//定义要存放的长度
    DWORD dwNumberOfBytesRead;//每个循环读取出来存放的位置
    
    hProcess = OpenProcess(PROCESS_ALL_ACCESS,
        FALSE, pi.dwProcessId);//句柄:位置--权限
    if (hProcess != NULL)
    {
        int i = 0x00020000;//读取位置开始的地方
        while (!ReadProcessMemory(hProcess, (LPCVOID)i, readtemp, 0x10, &dwNumberOfBytesRead)) {
            i++;
        }
        //读取的流程
        /*
        读到的东西做一些正则匹配
        */
        printf("readsuccess:");
        for (int i = 0; i < dwNumberOfBytesRead; i++) {
            printf("\n");
            printf("\\x%X", readtemp[i]);
        }
        printf("\n");
    }//显示的流程
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

 

读取内存内容实例:

2.2.2 内存属性扫描

#include <iostream>
#include <windows.h>
#include <Psapi.h>
#pragma comment(lib,"psapi.lib")
VOID ScanProcessMemory(HANDLE hProc)
{
    SIZE_T stSize = 0;
    PBYTE pAddress = (PBYTE)0;
    SYSTEM_INFO sysinfo;
    MEMORY_BASIC_INFORMATION mbi = { 0 };
    //MemoryBasicInformation
    //获取页的大小
    ZeroMemory(&sysinfo, sizeof(SYSTEM_INFO));
    GetSystemInfo(&sysinfo);
    // 得到的镜像基地址
    pAddress = (PBYTE)sysinfo.lpMinimumApplicationAddress;
    printf("------------------------------------------------------------------------ \n");
    printf("开始地址 \t 结束地址 \t\t 大小 \t 状态 \t 内存类型 \n");
    printf("------------------------------------------------------------------------ \n");
    // 判断只要当前地址小于最大地址就循环
    while (pAddress < (PBYTE)sysinfo.lpMaximumApplicationAddress)
    {
        ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
        stSize = VirtualQueryEx(hProc, pAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
        if (stSize == 0)
        {
            pAddress += sysinfo.dwPageSize;
            continue;
        }
        printf("0x%08X \t 0x%08X \t %8d K \t ", mbi.BaseAddress,
            ((DWORD)mbi.BaseAddress + (DWORD)mbi.RegionSize), mbi.RegionSize >> 10);
        switch (mbi.State)
        {
        case MEM_FREE: printf("空闲 \t"); break;
        case MEM_RESERVE: printf("保留 \t"); break;
        case MEM_COMMIT: printf("提交 \t"); break;
        default: printf("未知 \t"); break;
        }
        switch (mbi.Type)
        {
        case MEM_PRIVATE:   printf("私有  \t"); break;
        case MEM_MAPPED:    printf("映射  \t"); break;
        case MEM_IMAGE:     printf("镜像  \t"); break;
        default: printf("未知  \t"); break;
        }
        if (mbi.Protect == 0)
            printf("---");
        else if (mbi.Protect & PAGE_EXECUTE)
            printf("E--");
        else if (mbi.Protect & PAGE_EXECUTE_READ)
            printf("ER-");
        else if (mbi.Protect & PAGE_EXECUTE_READWRITE)
            printf("ERW");
        else if (mbi.Protect & PAGE_READONLY)
            printf("-R-");
        else if (mbi.Protect & PAGE_READWRITE)
            printf("-RW");
        else if (mbi.Protect & PAGE_WRITECOPY)
            printf("WCOPY");
        else if (mbi.Protect & PAGE_EXECUTE_WRITECOPY)
            printf("EWCOPY");
        printf("\n");
        // 每次循环累加内存块的位置
        pAddress = (PBYTE)mbi.BaseAddress + mbi.RegionSize;
    }
}
int main(int argc, char* argv[])
{
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
    ScanProcessMemory(hProc);
    CloseHandle(hProc);
    system("pause");
    return 0;
}

 

读取内存属性实例:

2.3 注册表监控

#include <Windows.h>
#include <iostream>
#include <string>
#include <tchar.h>
using namespace std;
bool RegeditNotifyChanged(HKEY hKey_, char* path_)
{
    // 1.创建事件
    //类似于回调函数的效果
    /*
    回调函数:
    函数A(函数B)
    当触发函数A的条件的时候,执行函数B。
    */
    HANDLE hNotify = CreateEvent(NULL, FALSE, TRUE, "RegeditNotifyChanged");
    if (hNotify == INVALID_HANDLE_VALUE)
    {
        cout << "监控事件创建失败" << endl;
        CloseHandle(hNotify);
        return false;
    }
    //2. 打开注册表对应位置
    HKEY hRegKey;
    if (RegOpenKeyEx(hKey_, path_, 0, KEY_NOTIFY, &hRegKey) != ERROR_SUCCESS)
    {
        cout << "打开注册表失败" << endl;
        CloseHandle(hNotify);
        RegCloseKey(hRegKey);
        return false;
    }
    //3.使用RegNotifyChangeKeyValue进行监控
    if (RegNotifyChangeKeyValue(hRegKey, TRUE, REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET, hNotify, TRUE) != ERROR_SUCCESS)
    {
        cout << "监控失败" << endl;
        CloseHandle(hNotify);
        RegCloseKey(hRegKey);
        return false;
    }
    if (WaitForSingleObject(hNotify, INFINITE) != WAIT_FAILED)
    {
        cout << "监控项发生改变" << endl;
        //知道谁改的话   RegQueryValue   路径
        CloseHandle(hNotify);
        RegCloseKey(hRegKey);
        return true;
    }
    CloseHandle(hNotify);
    RegCloseKey(hRegKey);
    return false;
}
void main(void)
{
    //根键、子键名称和到子键的句柄
    HKEY hRoot = HKEY_CURRENT_USER;
    char* szSubKey = (char*)"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
    RegeditNotifyChanged(hRoot,szSubKey);
}

 

监控注册表实例:

转载:https://mp.weixin.qq.com/s/GQVVQhsxCr_csorSIbGKCA

发表回复

后才能评论

评论(2)