【杀软对抗】杀毒软件的基本结构

渗透技巧 1年前 (2023) admin
251 0 0

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 结束地址 tt 大小 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);}

监控注册表实例:

【杀软对抗】杀毒软件的基本结构



原文始发于微信公众号(ZackSecurity):【杀软对抗】杀毒软件的基本结构

版权声明:admin 发表于 2023年7月6日 下午4:03。
转载请注明:【杀软对抗】杀毒软件的基本结构 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...