设为首页 加入收藏

TOP

6.2 Sunday搜索内存特征(二)
2023-09-23 15:43:50 】 浏览:277
Tags:6.2 Sunday 索内存
如果已经处理到缓冲区的末尾 if ((i + SignatureCodeLength) >= size) { return; } int num = Next[MemoryData[i + SignatureCodeLength]]; // 如果特征码中有问号,从问号处开始匹配 if (num == -1) { // 如果特征码有问号,就从问号处开始匹配,如果没有就 i += -1 i += (SignatureCodeLength - Next[256]); } else { // 否则从匹配失败的位置开始 i += (SignatureCodeLength - num); } } }

6.2.3 搜索整块内存区域

SearchMemory函数,该函数用于在指定进程的内存空间中搜索给定特征码的内存块,并把搜索到的内存地址存入结果数组中。函数为一层循环枚举给定的内存块,内部则调用SearchMemoryBlock函数进行内存块搜索。其中,参数hProcess为指向要搜索内存块所在进程的句柄,SignatureCode为给定特征码的字符串指针,StartAddress为搜索的起始地址,EndAddress为搜索的结束地址,InitSize为搜索结果数组初始空间大小,ResultArray为存储搜索结果的数组引用。

该函数首先通过调用VirtualQueryEx函数获取可读可写和可读可写可执行的内存块信息,并遍历每个内存块,对内存块进行搜索。之所以不直接搜索整个内存区域,是因为那样可以减少非必要的搜索,提高效率。

内存块的搜索通过调用SearchMemoryBlock函数实现。搜索采用了KMP算法,先通过GetNextArray函数和GetSignatureCodeArray函数将特征码转换为对应的变量,再对每个内存块逐个匹配,在匹配过程中若找到与特征码中的字节码不匹配的字节,就根据Next数组记录的回溯位置从失配的位置开始重新匹配,以降低匹配的时间复杂度。在内存块搜索过程中,若匹配成功,则将特征码匹配的起始地址存入结果数组中,最终函数返回结果数组大小。

// 实现搜索整个程序
int SearchMemory(HANDLE hProcess, char* SignatureCode, unsigned __int64 StartAddress, unsigned __int64 EndAddress, int InitSize, vector<unsigned __int64>& ResultArray)
{
    int i = 0;
    unsigned long BlockSize;
    MEMORY_BASIC_INFORMATION mbi;

    WORD SignatureCodeLength = strlen(SignatureCode) / 3 + 1;
    WORD* SignatureCodeArray = new WORD[SignatureCodeLength];

    // 实现特征码字符串与数组转换
    GetSignatureCodeArray(SignatureCode, SignatureCodeArray);
    GetNextArray(Next, SignatureCodeArray, SignatureCodeLength);

    // 初始化结果数组
    ResultArray.clear();
    ResultArray.reserve(InitSize);

    // 查询内存属性并循环
    while (VirtualQueryEx(hProcess, (LPCVOID)StartAddress, &mbi, sizeof(mbi)) != 0)
    {
        // 判断并获取具有PAGE_READWRITE读写,或者PAGE_EXECUTE_READWRITE读写执行权限的内存
        if (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE)
        {
            i = 0;

            // 得到当前块长度
            BlockSize = mbi.RegionSize;
            
            // 搜索这块内存
            while (BlockSize >= BLOCKMAXSIZE)
            {
                // 调用内存块搜索功能依次搜索内存
                SearchMemoryBlock(hProcess, SignatureCodeArray, SignatureCodeLength, StartAddress + (BLOCKMAXSIZE * i), BLOCKMAXSIZE, ResultArray);
                BlockSize -= BLOCKMAXSIZE;
                i++;
            }
            SearchMemoryBlock(hProcess, SignatureCodeArray, SignatureCodeLength, StartAddress + (BLOCKMAXSIZE * i), BlockSize, ResultArray);
        }

        // 开始地址增加下一块长度继续搜索
        StartAddress += mbi.RegionSize;
        if (EndAddress != 0 && StartAddress > EndAddress)
        {
            return ResultArray.size();
        }
    }

    // 释放特征码数组并返回搜索计数器
    free(SignatureCodeArray);
    return ResultArray.size();
}

将上述代码理解后读者可以自行使用

int main(int argc, char *argv[])
{
    // 通过进程名获取进程PID号
    DWORD Pid = GetPidByName("PlantsVsZombies.exe");
    printf("[*] 获取进程PID = %d \n", Pid);

    // 初始化MemoryData大小
    MemoryData = new BYTE[BLOCKMAXSIZE];

    // 存储搜索返回值
    vector<unsigned __int64> ResultArray;

    // 通过进程ID获取进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, Pid);

    // 开始搜索
    // 搜索特征码 FF 25 ?? 从0x0000000到0xFFFFFFF 初始长度为3 返回值放入ResultArray
    SearchMemory(hProcess, "FF 25 ??", 0x0000000, 0xFFFFFFF, 3, ResultArray);

    // 输出结果
    for (vector<unsigned __int64>::iterator it = ResultArray.begin(); it != ResultArray.end(); it++)
    {
        printf("0x%08X \n", *it);
    }

    system("pause");
    return 0;
}

编译并运行上述程序片段,则会枚举hProcess进程内特征码时FF 25 ??的片段,枚举位置为0x0000000-0xFFFFFFF枚举长度为3个特征,最终将枚举结果输出到ResultArray数组内,输出效果图如下所示;

本文作

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇5.2 磁盘CRC32完整性检测 下一篇模板特化的多维度挖掘

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目