蓝天资源网
当前位置:蓝天资源网 / 汇编逆向 / 正文

病毒分析远古熊猫烧香病毒例子

作者:忆笙发布时间:2021-09-07 01:00浏览数量:517次评论数量:0次

“熊猫烧香”,是一款拥有自动传播、自动感染硬盘能力和强大的破坏能力的病毒,它不但能感染系统中exe,com,pif,src,html,asp等文件,它还能终止大量的反病毒软件进程并且会删除扩展名为gho的文件(该类文件是一系统备份工具“GHOST”的备份文件,删除后会使用户的系统备份文件丢失。被感染的用户系统中所有.exe可执行文件全部被改成熊猫举着三根香的模样。

图片描述

运行被感染的程序

图片描述

提取样本

使用PCHunter32查看进程

图片描述

右键-定位到进程文件

图片描述

把定位的病毒样本提取出来

图片描述

病毒样本提取(spo0lsv.exe)出来后,放到虚拟机中做进一步分析

图片描述

手工查杀结束进程

图片描述

查看启动项

图片描述

删除改启动项

右击-删除(启动信息和文件)

图片描述

行为分析

获取样本之后,在虚拟机中,使用监控工具监视样本的运行

等待病毒执行的差不多后,分别查看病毒行为

1.文件操作,主要查看文件创建、修改、删除等操作

2.注册表操作,主要看注册表设置、创建等操作

3.进程操作,主要看创建进程、写入内存等操作

4.网络操作,主要看网络链接地址、IP信息等

监控病毒运行

这里的监控使用火绒剑

图片描述

将病毒(熊猫烧香)拖拽到火绒剑中

弹出以下窗口,在动作选项中的子选项框全部勾选,以便后续分别筛选分析

图片描述

点击确定

图片描述

事件过多,正好用到火绒剑的筛选功能

左上角过滤-动作过滤

图片描述

执行监控

图片描述

图片描述

文件监控

图片描述

在动作中去掉其它选项,在文件监控的子选项勾选、、文件修改、、文件写入

注:熊猫烧香感染的基本原理基本上是修改了文件

图片描述

图片描述

然后发现所有的web文件都加入了这么一条链接

注册表监控

动作过滤-选择设置注册表项

图片描述

图片描述

进程监控

不太清楚具体对进程做了什么,所以在动作过滤-进程监控直接勾选

图片描述

图片描述

可以通过双击来查看详情

图片描述

枚举进程基本上是为了查看当前进程中是否有杀软

网络监控

由于并不清楚他会对网络做什么操作,所以直接勾选网络监控

图片描述

图片描述

火绒剑的网络监控好像不是很强

使用WSExplorer查看病毒网络行为

图片描述

行为总结

火绒剑的动作过滤中的,行为监控选项是火绒剑安全策略中过滤出恶意的行为

图片描述

图片描述

点开来查看详情

图片描述

通过这个界面基本可以看出这个病毒干了些什么

分析监控日志后,能够分析出的恶意行为:

1.自我复制样本到C盘(C://Windows/driver)

2.在每一个目录下创建Desktop_.ini文件

3.在C盘根目录创建autorun.inf文件(里面指定了自启动文件为根目录下的setup.exe样本)

4.对程序目录下的exe文件进行感染,图标变为熊猫烧香

5.设置注册表启动项为C:/Windows/driver/spo0lsv.exe

6.设置注册表键值为隐藏

逆向分析脱壳

通过PEID工具发现熊猫烧香这个病毒是带壳的,就需要先脱壳了

图片描述

拖入OD中开始单步

填充IAT

图片描述

解密填充

图片描述

找到OEP

图片描述

F7进入

图片描述

确认IAT是否正常

图片描述

图片描述

图片描述

很明显的IAT表中参杂着0x7FFFFFFF,需要把IAT表中0x7FFFFFFF更改成0即可,不然脱壳后修复IAT的时候会影响寻址

图片描述

大概更改了十来个

Dump

回到OEP处dump

图片描述

然后点击脱壳,取个名称保存

图片描述

修复IAT

图片描述

图片描述

图片描述

之后会产生一个新文件(就是已脱壳的熊猫烧香)

IDA&OD分析

使用IDA的签名工具可以更好的识别库代码

  1. 将Dump修复后的文件使用IDA打开

  2. 在IDA中使用Shift + F5 打开签名窗口

  3. 在签名窗口Ctrl + F搜索Delphi

  4. 找到Delphi对应的特征库,应用用后可以识别更多是库函数

使用PEID查看(脱完壳的熊猫烧香)深度扫描

图片描述

发现是Delphi编写的

使用IDA打开

图片描述

添加签名

Shift + F5 ---> 右键 ----> Apply new signature...

图片描述

Ctrl + F搜索

图片描述

图片描述

到OEP处,使用快捷键F5,查看伪代码

OD打开

通过OD找到第一个函数 (405250)进行动静结构分析

图片描述

在第一个函数(405250)下一个断点,直接运行到这查看

图片描述

单步

图片描述

跳转到了函数(40891C)

F7进入

图片描述

打开IDA来查看一下(40819C)这个函数

函数40819C

找到关键代码

图片描述

逐一分析

函数4053AC

图片描述

函数405FC4

可以看出,这个函数是在遍历到指定的进程然后杀死

图片描述

图片描述

图片描述

那就,就近原则,选择JE 40845E(更改标志位,让其跳转到49845E)

函数 40D18C

一路单步

图片描述

使用IDA查看40D81C函数

图片描述

分析到这,一个个线程进去看一下

函数 49A5B0

图片描述

线程1 40A48C

图片描述

OD进入函数 407F00

图片描述

图片描述

继续单步

图片描述

走出循环,瞅一眼程序是否改变

图片描述

而且大小也变了

病毒大小 + 源文件大小

项当于是往后面追加的

手动恢复感染文件

图片描述

图片描述

用010Editor把0x00000 - 0x1F000这一段给删了(把后面附加的感染特征一并删除)

图片描述

图片描述

函数 40BACC

图片描述

函数 40D088

进入40D088,看到六个计时器

图片描述

分析每个计时器对应的函数分别是什么作用

函数 40CEE4

图片描述

函数 40D040

图片描述

函数 40D048

图片描述

函数 407430

图片描述

函数 40CC4C

图片描述

函数 407C28

图片描述

这个代码已经看了太多了,就是下载并执行

编写专杀工具

结束进程             “spo0lsv.exe”
删除病毒文件            "C:\\Windows\\System32\\drivers\\spo0lsv.exe"
修改注册表             “Software\\Microsoft\\Windows\\CurrentVersion\\Run\\”
                    "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL\\"
删除文件              “Desktop_.ini”
                    ”setup.exe“
恢复文件              删除文件头 - 0x1F000
                    删除含有"www.ac86.cn/66/index.htm"链接的这一行
#include <Windows.h>
#include <atlstr.h>     //CString
#include <tlhelp32.h>   //建立快照
#include <shlwapi.h>    //用于设置文件属性
#include <vector>        //保存盘符
 
using std::vector;
 
 
//获取进程ID
DWORD GetProcessPid(CString csProcessName)
{
    PROCESSENTRY32 pStc;
    pStc.dwSize = sizeof(pStc);
    HANDLE nSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 
    BOOL bRet = Process32First(nSnapShot, &pStc);
    while (bRet)
    {
        if (csProcessName == CString(pStc.szExeFile))
        {
            return pStc.th32ProcessID;
        }
        bRet = Process32Next(nSnapShot, &pStc);
    }
    return 0;
}
//获取驱动器
vector<CStringA> GetDriverList()
{
    vector<CStringA>nDiverList;
 
    TCHAR nDrive[MAX_PATH];
 
    GetLogicalDriveStrings(100, (LPWSTR)nDrive);
 
    TCHAR* pName = nDrive;
    //指针指向的地方不为零(表示有盘符)
    while (*pName != 0) {
        //添加到vector中
        nDiverList.push_back(pName);
        //printf("%S\n", pName);
        //指向下一个盘符
        pName += _tcslen(pName) + 1;   
    }
 
    return nDiverList;//返回vector
}
 
//恢复文件
void RecoveryFile(CStringA csFilePath, CStringA csFileName)
{
 
    int nFileType = 0;
 
    CStringA csFileType;
    csFileType = PathFindExtensionA(csFileName);
    csFileType.MakeUpper();
 
    //通过分析得知exe,scr,pif,com,htm,html,asp,php,jsp,aspx文件属于被感染类型
    if (csFileType == ".EXE" || csFileType == ".SCR" || csFileType == ".PIF" || csFileType == ".COM")
        nFileType = 1;
    else if (csFileType == ".HTML" || csFileType == ".HTM" || csFileType == ".ASP"
        || csFileType == ".ASPX" || csFileType == ".JSP" || csFileType == ".PHP")
        nFileType = 2;//网络文件
    else return;//不属于这些文件类型就没必要接下去的判断了
 
    //打开文件
    FILE* pFile = nullptr;
    char* cBuff = nullptr;
    int nFileSize = 0;
    fopen_s(&pFile, csFilePath, "rb");//读文件
    fseek(pFile, 0, SEEK_END);//将文件指针指向结尾
    nFileSize = ftell(pFile);//返回文件的偏移量(文件大小)
    rewind(pFile);                //重新指向文件的开头
    //读出来
    cBuff = new char[nFileSize] {};
    fread(cBuff, nFileSize, 1, pFile);
    fclose(pFile);
 
 
    if (nFileType == 1)
    {
        int i = 0;
        //感染特征,在文件的最后加上 .文件名.文件类型.文件类型.原文件大小.
        //文件类型.原文件大小.一边情况下不会超过12个字节
        for (; i < 13; i++)
        {
            //感染特征倒数第二个.的十六进制是0x02
            if (*(cBuff + nFileSize - 13 + i) == (char)0x02)
                break;
        }
 
        //特征的最后一个点的16进制是0x01
        if (i == 13 || (*(cBuff + nFileSize - 1) != (char)0x01))
        {       
            delete[]cBuff;
            return;
        }
 
        char cTemp[13]{};
        int nExeSize = 0;
        memcpy_s(cTemp, 13, cBuff + nFileSize - 13 + i + 1, 13 - i - 2);
        //得到源文件大小
        sscanf_s(cTemp, "%d", &nExeSize);
 
        //判断源文件大小
        if (nExeSize <= 0)
        {
            delete[]cBuff;
            return;
        }
 
        printf("被感染文件类型:%s\t被感染文件大小:%d \n", csFileType, nExeSize);
        //申请新的文件地址用于存放正确文件的缓冲区
        char* pcNewFile = new char[nExeSize] {};
        memcpy_s(pcNewFile, nExeSize, cBuff + 0x1F000, nExeSize);
        //删除被感染的文件
        if (!DeleteFileA(csFilePath))
        {
            printf("%s\t修复%s失败!\n", csFileType, csFilePath);
            delete[]pcNewFile;
            delete[]cBuff;
            return;
        }
        //把正确的文件写入源地址
        fopen_s(&pFile, csFilePath, "wb");
        fwrite(pcNewFile, nExeSize, 1, pFile);
        fclose(pFile);
 
        delete[]pcNewFile;
 
        printf("%s\t修复%s成功!\n", csFileType, csFilePath);
    }
    else if (nFileType == 2)
    {//删除网络文件中加入的链接
        CStringA csFileCode(cBuff);
        if (csFileCode.Find("www.ac86.cn/66/index.htm") != -1)
        {
            int nHtmlSize = nFileSize - 76;
            char* NewFile = new char[nHtmlSize] {};
 
            memcpy_s(NewFile, nHtmlSize, cBuff, nHtmlSize);
 
            fopen_s(&pFile, csFilePath, "wb");
            fwrite(NewFile, nHtmlSize, 1, pFile);
            fclose(pFile);
 
 
            delete[]NewFile;
            printf("%s\t修复%s成功!\n", csFileType, csFilePath);
        }
    }
    delete[]cBuff;
    cBuff = nullptr;
}
 
//遍历文件
void FindFile(CStringA csDir)
{
 
    WIN32_FIND_DATAA stcFileData = { 0 };
    HANDLE hFind = INVALID_HANDLE_VALUE;
    hFind = FindFirstFileA(csDir + L"\\*", &stcFileData);
    if (hFind == INVALID_HANDLE_VALUE) return;
 
    do {//排除两个隐藏路径(当前目录,上级目录)
        if (CStringA(stcFileData.cFileName) == "." || CStringA(stcFileData.cFileName) == "..")
        {
            continue;
        }
        //删除Desktop_.ini文件
        if (SetFileAttributesA(csDir + "\\Desktop_.ini", FILE_ATTRIBUTE_NORMAL))
        {
            DeleteFileA(csDir + "\\Desktop_.ini");
            printf("%s\\Desktop_.ini\t删除成功\n", csDir );
        }
 
        if (stcFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            FindFile(csDir + "\\" + stcFileData.cFileName);//目录拼接,递归查找
        else
        {
            //恢复文件
            RecoveryFile(csDir + "\\" + stcFileData.cFileName, stcFileData.cFileName);
        }
        //查找下一个文件
    } while (FindNextFileA(hFind, &stcFileData));
 
 
}
//结束进程(熊猫烧香)
void EndProcess()
{
 
    DWORD ID = GetProcessPid("spo0lsv.exe");
    if (ID != 0)
    {
        DWORD Flag = TerminateProcess(OpenProcess(PROCESS_ALL_ACCESS, FALSE, ID), 0);
        if (Flag == 0)
        {
            printf("熊猫烧香\t进程结束失败\n");
 
        }
    }
    else
    {
        printf("熊猫烧香\t进程未找到\n");
    }
}
//删除熊猫烧香文件
void DeletePandaFile()
{
    SetFileAttributesA("C:\\Windows\\System32\\drivers\\spo0lsv.exe", FILE_ATTRIBUTE_NORMAL); //去除属性
    DWORD Flag = DeleteFileA("C:\\Windows\\System32\\drivers\\spo0lsv.exe");
    if (Flag == 0)
    {
        printf("C:\\Windows\\System32\\drivers\\spo0lsv.exe\t不存在\n");
 
    }
}
 
//修改注册表
void ChangeReg()
{
    printf("注册表");
    //删除启动项svcshare
    HKEY hKey = NULL;
    int nError = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\", &hKey);
    if (nError != ERROR_SUCCESS)printf("\t打开失败(启动项)\n");
    RegDeleteValueA(hKey, "svcshare");
    RegCloseKey(hKey);
 
    //修改注册表 隐藏
    nError = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL\\", &hKey);
    if (nError != ERROR_SUCCESS)printf("\t打开失败(隐藏)\n");
    DWORD nVal = 1;
    RegSetValueExA(hKey, "CheckedValue", 0, REG_DWORD, (CONST BYTE*)&nVal, sizeof(DWORD));//0改为1 ,取消隐藏
    RegCloseKey(hKey);
    printf("\t清理成功\n");
}
 
//查杀
void FindKill()
{
    vector<CStringA>vecDiverList;
    vecDiverList = GetDriverList();//返回驱动器列表(以盘符组成的数组)
 
    for (auto& vecDriverItem : vecDiverList)
    {
        SetFileAttributesA(vecDriverItem + "\\autorun.inf", FILE_ATTRIBUTE_NORMAL);
        DeleteFileA(vecDriverItem + "\\autorun.inf");
        printf("%s\\autorun.inf..已删除\n", vecDriverItem);
        SetFileAttributesA(vecDriverItem + "\\setup.exe", FILE_ATTRIBUTE_NORMAL);
        DeleteFileA(vecDriverItem + "\\setup.exe");
        printf("%s\\setup.exe..已删除\n", vecDriverItem);
        //传入盘符遍历文件
        FindFile(vecDriverItem);
    };
}
//主逻辑
int main()
{
    //结束进程(熊猫烧香)
    EndProcess();
    //删除熊猫烧香文件
    DeletePandaFile();
    //修改注册表
    ChangeReg();
    //查杀(删除熊猫产生的文件,修改被更改的文件)
    FindKill();
 
    system("pause");
    return 0;
}


忆笙

忆笙 主页 联系他吧

人间山河远阔,只想与你同行。

欢迎 发表评论: