如何从零写一个病毒专杀工具

逆向病毒分析 1年前 (2022) admin
544 0 0

0x00 前言

最近有这样一个需求,需要对某病毒写一个专杀工具,针对这款病毒进行查杀。这个病毒样本是今年2月份发现的,该病毒相对来说比较友好,没有采用加密,也没有删除原文件,也没有网络传播行为。只是会感染可执行文件,会将原文件修改名字,生成一个与原文件同名的感染文件,运行后可继续感染其他文件。接下来首先从非专业的角度来简单看一下该病毒是如何运行的。

0x01 病毒分析

运行病毒文件,一旦找到可感染的可执行文件,病毒会将其复制为 g<原始文件名>.exe,并将其隐藏。然后用原程序的名称和图标复制自己;如果原文件的资源中不存在该图标,病毒将使用自己的图标,并留下一个0大小的文件g<原始文件名>.ico。生成的文件大小为522k左右。

如何从零写一个病毒专杀工具
img

如上图,python.exe感染后会生成gpython.exe(原始程序并隐藏,此时python.exe(感染程序相当于一个加载器,运行时会执行病毒程序同时运行gpython.exe

如果文件夹中文件exe文件是g开头,则不感染。

如何从零写一个病毒专杀工具
img

当点击替换后的可执行文件后,病毒会启动恶意主程序ground.exe,感染其他可执行文件,并设置开机启动项。

如何从零写一个病毒专杀工具
img

启动项

如何从零写一个病毒专杀工具
img

通过非专业的角度对病毒文件的运行进行了简单的分析,病毒查杀的话就是全盘或指定路径扫描可执行文件,根据病毒文件的特征码来判断该文件是否是病毒文件,如果是则进行删除,然后将原文件进行恢复。大致流程如下图:

如何从零写一个病毒专杀工具
img

0x02 代码编写

根据上面的流程图,查杀代码可以分为三部分:1.实现可执行文件的扫描功能;2.实现病毒特征识别功能;3.删除病毒,恢复原文件。语言采用了C++,面向必(C)应(V)编程。

1.文件扫描实现

其实就是递归遍历目录下的所有可执行文件,这里实现的方式有多种。例如可以采用filesystem(C++17以上)、io.hwinApi等。这里采用的是winApi。

主要代码如下:

 1#include <string>
2#include <Windows.h>
3using namespace std;
4#include <vector>
5vector<string>  result;
6bool  search(const  char* path = "C:\"char* file = "exe")
7    
{
8        HANDLE hFile;
9        char   buffer[MAX_PATH] = { 0, };
10        WIN32_FIND_DATA pNextInfo;  //搜索得到的文件信息将储存在pNextInfo中;
11        sprintf_s(buffer, "%s\*.*", path);
12        hFile = FindFirstFile(buffer, &pNextInfo);//请注意是 &pNextInfo , 不是 pNextInfo;
13        if (!hFile) {
14
15            return false;
16        }
17        string  t;
18        //cout << buffer << endl;
19        while (FindNextFile(hFile, &pNextInfo))
20        {
21
22            if (pNextInfo.cFileName[0] == '.')//过滤.和..
23                continue;
24            //cout << pNextInfo.cFileName << endl;
25            if (pNextInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
26            {
27                ZeroMemory(buffer, MAX_PATH);
28                sprintf_s(buffer, "%s\%s", path, pNextInfo.cFileName);
29                //cout << buffer << endl;
30                search(buffer, file);
31            }
32            t.assign(path);
33            t += '\';
34            t.append(pNextInfo.cFileName);
35            int len = strlen(file);
36            if (t.substr(t.size() - len) == file)
37            {
38                result.push_back(t);//对t对象进行深复制
39            }
40
41        }
42        return true;
43    }
44
45int main() {
46
47    search("E:\");
48    printf("%d", result.size());
49
50}

主要就是递归搜索所有exe后缀的文件,然后存在vector中。

2.病毒特征码提取

特征码可能是病毒的感染标记,也可能是若干计算机指令组成的一段计算机程序。特征码的提取方式有多种,例如该病毒中存在字符串Groud,可以以此作为特征码。

如何从零写一个病毒专杀工具
img

搜索字符串Ground,有多处存在,挑选一处。如上图所示,如果位置0x59B530x59B5947 72 6F 75 6E 64则认为该文件为病毒文件。这是根据字符串特征来搜索的,可能会不太准确,也可以采用病毒查杀的方式来定位特征码。可以使用工具MYCCL3.0或者VirTest5.0。这里使用的是VirTest5.0。

根据工具的使用说明来制作测试文件和载入测试文件。

如何从零写一个病毒专杀工具
img

接下来就是定位特征了,这里杀软使用了某绒。

如何从零写一个病毒专杀工具
img

最终定位到了偏移0x290-0x294,内容为046AF6EB。我们来验证一下。将偏移0x290-0x294的数据nop后,针对该文件以及该文件感染的文件,用huorong杀毒扫描,提示无风险。

如何从零写一个病毒专杀工具
img

而且执行感染的文件,杀软也不会对其进行拦截。

如何从零写一个病毒专杀工具
img

当然可能由于这里是虚拟机,所以部分杀软某些功能未启动而导致。不过这里作为特征码也够了。

有特征码了,就可以根据该特征码来判断文件是否是病毒文件,当然为了以防万一,可以综合多个特征码来进行判断。主要代码如下:

 1// 扫描特征码,对比
2bool GetPeSignature(LPCSTR FilePath)
3
{
4    boolean flag = false;
5    int count = 0;
6    typedef struct _SIGN
7    {

8        char FileName[64];         // 存储文件名或特征描述
9        LONG FileOffset;           // 存储检测文件偏移地址
10        BYTE VirusSign[4 + 1];    // 存储特征码大小4,其中的1是结束符.
11    }SIGN, *pSIGN;
12
13    // 定义特征码与特征描述信息
14    SIGN Sign[] = {
15        {
16            "HuoRong",
17            0x2970,
18            "x04x6axf6xeb"
19        },
20        {
21            "360_1",
22            0x61c6b,
23            "x8Bx75xF0x8B"
24        },
25        {
26            "360_2",
27            0x738E5,
28            "xC4x07x00xBC"
29        }
30    };
31
32    DWORD dwNum = 0;
33    BYTE buffer[4 + 1];
34    HANDLE hFile = NULL;
35
36    // 获取到FilePath路径下文件的句柄信息
37    hFile = CreateFile(FilePath, GENERIC_READ , NULL,
38        NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
39    /*DWORD error = GetLastError();
40    cout << hFile << error << endl;*/

41    for (int x = 0; x < (sizeof(Sign) / sizeof(Sign[0])); x++)
42    {
43        // 将待检测程序的文件指针指向特征码的偏移位置
44        SetFilePointer(hFile, Sign[x].FileOffset, NULL, FILE_BEGIN);
45        // 读取目标程序指定位置的特征码到内存中
46        ReadFile(hFile, buffer, sizeof(buffer), &dwNum, NULL);
47        // 对比内存中两个特征码是否相等
48        if (memcmp(Sign[x].VirusSign, buffer, 4) == 0)
49        {
50            count++;
51            //printf("匹配特征: %s n", Sign[x].FileName);
52        }   
53    }
54    if (count == sizeof(Sign) / sizeof(Sign[0])) {
55        flag = true;
56    }
57    CloseHandle(hFile);
58    return flag;
59}

3.删除病毒,恢复原文件

接下来就是删除病毒和恢复文件了,可以直接使用remove()来删除文件,但是为了防止删错文件,因此这里将文件删除到了回收站。

 1BOOL delFiletoRecycle(LPCTSTR pszPath, BOOL bDelete/*=FALSE*/)
2
{
3    SHFILEOPSTRUCT  shDelFile;
4    memset(&shDelFile, 0sizeof(SHFILEOPSTRUCT));
5    shDelFile.fFlags |= FOF_SILENT;      // don't report progress
6    shDelFile.fFlags |= FOF_NOERRORUI;     // don't report errors
7    shDelFile.fFlags |= FOF_NOCONFIRMATION;    // don't confirm delete
8
9    TCHAR buf[_MAX_PATH + 1]; // allow one more character
10    strcpy_s(buf, pszPath);   // copy caller's pathname
11    buf[strlen(buf) + 1] = 0;   // need two NULLs at end
12
13                                 // Set SHFILEOPSTRUCT params for delete operation
14    shDelFile.wFunc = FO_DELETE;       // REQUIRED: delete operation
15    shDelFile.pFrom = buf;         // REQUIRED: which file(s)
16    shDelFile.pTo = NULL;          // MUST be NULL
17    if (bDelete)
18    {         // if delete requested..
19        shDelFile.fFlags &= ~FOF_ALLOWUNDO;    // ..don't use Recycle Bin
20    }
21    else
22    {           // otherwise..
23        shDelFile.fFlags |= FOF_ALLOWUNDO;    // ..send to Recycle Bin
24    }
25
26
27    return SHFileOperation(&shDelFile);    // do it!
28}

删除完毕后,如果存在原文件,就将原文件恢复。

如何从零写一个病毒专杀工具
img

命令行的话可以使用attirb,这里代码的话采用了SetFileAttributes。并使用rename将原文件恢复原名。主要代码:

1SetFileAttributes("gtest.exe", FILE_ATTRIBUTE_NORMAL);
2rename("gtest.exe""test.exe");

然后将上面的代码整合一下运行,添加日志记录。运行效果:

如何从零写一个病毒专杀工具
img

这里执行的是感染后的”专杀”工具,可以看到又起了一个窗口,并执行了专杀工具。最终也会将该文件恢复。图上显示的仍为g开头,需要刷新一下即可。

可以看到成功将病毒文件删除到回收站,并恢复原文件。

如何从零写一个病毒专杀工具
img

删除的文件放在了回收站中。但从执行情况来看,有删除失败的文件,这是由于病毒文件正在执行,所以未能删除。要删除也可以,找到对应的pid,结束任务,再进行删除。这里就不再进行操作了。

0x03 总结

本文简单实现了一个病毒专杀工具,用的比较简单和基础的方法,没有涉及太多复杂的内容。可能存在问题较多,还有许多需要完善的地方,不过针对当前这款病毒查杀暂时没多大问题。最重要的一点就是如何去确定病毒的特征码,这将作为能否删除病毒文件的关键。


原文始发于微信公众号(猎户攻防实验室):如何从零写一个病毒专杀工具

版权声明:admin 发表于 2022年10月28日 上午8:06。
转载请注明:如何从零写一个病毒专杀工具 | CTF导航

相关文章

暂无评论

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