Kick the Heuristic Anti-virus out of the Rootkit

产业园区如何高效对接企业技术需求与高校科研成果?.docx 科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。 立即下载
 

Recently, Some friend complained to me that their rootkit driver had been killed by anti-virus software like McAfee and Nod32.So I began to find why.
I found that these "heuristic anti-virus" based on the export function mentioned in one of Jonna's article(BTW:Give my respect to Jonna).
First I take a look at McAfee, It has a strange heuristic strategy. if it found an export symbol "KeServiceDescriptorTable" ,while it didn`t found some normal driver function like "IoCreateDevice", It report the virus. So I think the first method is to find the KeServiceDescriptorTable dynamically.
With 90210's article "A more stable way to locate real KiServiceTable"(http://www.rootkit.com/newsread.php?newsid=176) and his help, I can find the KeServiceDescriptorTable's ServiceTableBase, it is enough.(Thank you 90210).
But I find NOD32 is more restrice, it will detect ZW* function and reported your driver as virus. So I must find a more common ways to locate export functions and symbols. Fortunately I found some pieces in from SVEN B. SCHREIBER. This book is cool!! The code is here:


代码

PVOID SpyMemoryCreate (DWORD dSize)
    {
    return ExAllocatePoolWithTag (PagedPool, max (dSize, 1),
                                  SPY_TAG);
    }

 

// -----------------------------------------------------------------

PVOID SpyMemoryDestroy (PVOID pData)
    {
    if (pData != NULL) ExFreePool (pData);
    return NULL;
    }

// ==============================================================
// MODULE INFO MANAGEMENT
// =================================================================

PMODULE_LIST SpyModuleList (PDWORD    pdData,
                            PNTSTATUS pns)
    {
    DWORD        dSize;
    DWORD        dData = 0;
    NTSTATUS     ns    = STATUS_INVALID_PARAMETER;
    PMODULE_LIST pml   = NULL;

    for (dSize = PAGE_SIZE; (pml == NULL) && dSize; dSize <<= 1)
        {
        if ((pml = SpyMemoryCreate (dSize)) == NULL)
            {
            ns = STATUS_NO_MEMORY;
            break;
            }
        ns = ZwQuerySystemInformation (SystemModuleInformation,
                                       pml, dSize, &dData);
        if (ns != STATUS_SUCCESS)
            {
            pml   = SpyMemoryDestroy (pml);
            dData = 0;

            if (ns != STATUS_INFO_LENGTH_MISMATCH) break;
            }
        }
    if (pdData != NULL) *pdData = dData;
    if (pns    != NULL) *pns    = ns;
    return pml;
    }

// -----------------------------------------------------------------

PMODULE_LIST SpyModuleFind (PBYTE     pbModule,
                            PDWORD    pdIndex,
                            PNTSTATUS pns)
    {
    DWORD        i;
    DWORD        dIndex = -1;
    NTSTATUS     ns     = STATUS_INVALID_PARAMETER;
    PMODULE_LIST pml    = NULL;

    if ((pml = SpyModuleList (NULL, &ns)) != NULL)
        {
        for (i = 0; i < pml->dModules; i++)
            {
            if (!_stricmp (pml->aModules [i].abPath +
                           pml->aModules [i].wNameOffset,
                           pbModule))
                {
                dIndex = i;
                break;
                }
            }
        if (dIndex == -1)
            {
            pml = SpyMemoryDestroy (pml);
            ns  = STATUS_NO_SUCH_FILE;
            }
        }
    if (pdIndex != NULL) *pdIndex = dIndex;
    if (pns     != NULL) *pns     = ns;
    return pml;
    }

// -----------------------------------------------------------------

PVOID SpyModuleBase (PBYTE     pbModule,
                     PNTSTATUS pns)
    {
    PMODULE_LIST pml;
    DWORD        dIndex;
    NTSTATUS     ns    = STATUS_INVALID_PARAMETER;
    PVOID        pBase = NULL;

    if ((pml = SpyModuleFind (pbModule, &dIndex, &ns)) != NULL)
        {
        pBase = pml->aModules [dIndex].pBase;
        SpyMemoryDestroy (pml);
        }
    if (pns != NULL) *pns = ns;
    return pBase;
    }

// -----------------------------------------------------------------

PIMAGE_NT_HEADERS SpyModuleHeader (PBYTE     pbModule,
                                   PVOID    *ppBase,
                                   PNTSTATUS pns)
    {
    PVOID             pBase = NULL;
    NTSTATUS          ns    = STATUS_INVALID_PARAMETER;
    PIMAGE_NT_HEADERS pinh  = NULL;

    if (((pBase = SpyModuleBase (pbModule, &ns)) != NULL) &&
        ((pinh  = RtlImageNtHeader (pBase))      == NULL))
        {
        ns = STATUS_INVALID_IMAGE_FORMAT;
        }
    if (ppBase != NULL) *ppBase = pBase;
    if (pns    != NULL) *pns    = ns;
    return pinh;
    }

// -----------------------------------------------------------------

PIMAGE_EXPORT_DIRECTORY SpyModuleExport (PBYTE     pbModule,
                                         PVOID    *ppBase,
                                         PNTSTATUS pns)
    {
    PIMAGE_NT_HEADERS       pinh;
    PIMAGE_DATA_DIRECTORY   pidd;
    PVOID                   pBase = NULL;
    NTSTATUS                ns    = STATUS_INVALID_PARAMETER;
    PIMAGE_EXPORT_DIRECTORY pied  = NULL;

    if ((pinh = SpyModuleHeader (pbModule, &pBase, &ns)) != NULL)
        {
        pidd = pinh->OptionalHeader.DataDirectory
               + IMAGE_DIRECTORY_ENTRY_EXPORT;

        if (pidd->VirtualAddress &&
            (pidd->Size >= IMAGE_EXPORT_DIRECTORY_))
            {
            pied = PTR_ADD (pBase, pidd->VirtualAddress);
            }
        else
            {
            ns = STATUS_DATA_ERROR;
            }
        }
    if (ppBase != NULL) *ppBase = pBase;
    if (pns    != NULL) *pns    = ns;
    return pied;
    }

// -----------------------------------------------------------------

PVOID SpyModuleSymbol (PBYTE     pbModule,
                       PBYTE     pbName,
                       PVOID     *ppBase,
                       PNTSTATUS pns)
    {
    PIMAGE_EXPORT_DIRECTORY pied;
    PDWORD                  pdNames, pdFunctions;
    WORD                    *pwOrdinals;
    DWORD                   i, j;
    PVOID                   pBase    = NULL;
    NTSTATUS                ns       = STATUS_INVALID_PARAMETER;
    PVOID                   pAddress = NULL;

    if ((pied = SpyModuleExport (pbModule, &pBase, &ns)) != NULL)
        {
        pdNames     = PTR_ADD (pBase, pied->AddressOfNames);
        pdFunctions = PTR_ADD (pBase, pied->AddressOfFunctions);
        pwOrdinals  = PTR_ADD (pBase, pied->AddressOfNameOrdinals);

        for (i = 0; i < pied->NumberOfNames; i++)
            {
            j = pwOrdinals [i];

            if (!strcmp (PTR_ADD (pBase, pdNames [i]), pbName))
                {
                if (j < pied->NumberOfFunctions)
                    {
                    pAddress = PTR_ADD (pBase, pdFunctions [j]);
                    }
                break;
                }
            }
        if (pAddress == NULL)
            {
            ns = STATUS_PROCEDURE_NOT_FOUND;
            }
        }
    if (ppBase != NULL) *ppBase = pBase;
    if (pns    != NULL) *pns    = ns;
    return pAddress;
    }

// -----------------------------------------------------------------

PVOID SpyModuleSymbolEx (PBYTE     pbSymbol,
                         PVOID     *ppBase,
                         PNTSTATUS pns)
{
    DWORD    i;
    BYTE     abModule [MAXIMUM_FILENAME_LENGTH] = "ntoskrnl.exe";
    PBYTE    pbName   = pbSymbol;
    PVOID    pBase    = NULL;
    NTSTATUS ns       = STATUS_INVALID_PARAMETER;
    PVOID    pAddress = NULL;
   
    for (i = 0; pbSymbol [i] && (pbSymbol [i] != '!'); i++);
   
    if (pbSymbol [i++])
    {
        if (i <= MAXIMUM_FILENAME_LENGTH)
        {
            memcpy (abModule, pbSymbol, i);
            pbName = pbSymbol + i;
        }
        else
        {
            pbName = NULL;
        }
    }
    if (pbName != NULL)
    {
        pAddress = SpyModuleSymbol (abModule, pbName, &pBase, &ns);
    }
    if (ppBase != NULL) *ppBase = pBase;
    if (pns    != NULL) *pns    = ns;
    return pAddress;
}

 


So Now we can get symbol like this:

pKeServiceDescriptorTable = SpyModuleSymbolEx("KeServiceDescriptorTable", NULL, &ns);

国央企创新负责人如何快速掌握本地科技资源分布与匹配情况?.docx 科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。 立即下载

相关推荐

脑电数据预处理八:基于 ICA 的伪迹去除

摘要: 脑电图(EEG)数据分析中,伪迹(如眼电、心电、肌电)与脑电信号频谱重叠时,独立成分分析(ICA)成为有效工具。ICA通过盲源分离将混合信号分解为统计独立的成分,识别并移除伪迹后重建干净信号。MNE-Python实现步骤包括:数据预处理(滤波、坏导处理)、ICA分解、人工与自动结合识别伪迹成分、剔除后重建数据。实践建议强调人工检查的重要性,避免过度使用ICA,并保存模型以提高效率。该方法显著提升数据质量,为后续分析奠定基础。

qq_32516809的博客 1659

Heuristic (computer science)

1

qq_66485519的博客 556

保姆级教程:在S32K312上配置C40驱动,实现Flash读写(基于RTD 4.4.2)

本文详细介绍了在S32K312微控制器上配置C40驱动实现Flash读写的全流程,基于RTD 4.4.2库。内容涵盖环境搭建、外设配置、Flash操作实战代码及高级应用场景,特别针对LLD驱动和FLS存储操作中的常见问题提供了解决方案,帮助开发者快速掌握嵌入式Flash存储技术。

weixin_28684757的博客 255

使用金山卫士的一些体会

  金山卫士已经在电脑里呆了一段时间,平时没见动静,今天检查出U盘上的病毒,总算有点反应了。顺便记下一些使用体会。

Purpleendurer@优快云 2995

命令行执行YOLO训练命令报错:1.PermissionError: [WinError 5] 拒绝访问 2.OMP: Error#15: Initializing libiomp5md.dll...

(已解决!)报错:1.PermissionError: [WinError 5] 拒绝访问 2.OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.

Gpengyuyan的博客 1125

Qt上位机实战:5步搞定STM32 IAP固件升级(附拖拽文件处理技巧)

本文详细介绍了如何使用Qt开发STM32 IAP固件升级上位机。通过五个核心步骤,包括理解IAP机制、搭建Qt环境、实现拖拽文件加载、封装串口通信以及设计可靠通信协议,帮助开发者快速构建一个稳定、易用且支持图形化操作的固件升级工具,显著提升嵌入式产品开发与维护效率。

ss78901的博客 1079

对抗杀毒软件Kick the Heuristic Anti-virus out of the Rootkit

By: drizt  Recently, Some friend complained to me that their rootkit driver had been killed by anti-virus software like McAfee and Nod32.So I began to find why.I found that these "heuristic anti-v

1941

Codesys软运动控制进阶:用SMC_FreeEncoder为ECAT轴搭建一个“虚拟手轮”调试工具

本文详细介绍了如何利用Codesys的SMC_FreeEncoder功能为ECAT轴搭建虚拟手轮调试工具,解决自动化设备开发中的硬件依赖问题。通过软件模拟手轮脉冲信号,实现无硬件依赖的运动控制逻辑验证,显著提升调试效率。适用于汇川AM400等PLC平台,特别适合机械安装滞后或伺服驱动器故障时的调试场景。

weixin_33737774的博客 478

list

的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。迭代到该位置,在这段位置上迭代需要线性的时间开销;最大的缺陷是不支持任意位置的随机访问,比如:要访问。还需要一些额外的空间,以保存每个节点的相关联信息。个元素,必须从已知的位置。

xie0510_的博客 274

【Claude Code 实战】第十章:DevOps 与 CI/CD 集成 / 光子AI

本章摘要:探讨Claude Code在DevOps与CI/CD集成中的应用。DevOps作为现代软件工程核心,结合AI技术实现自动化全流程,从代码提交到生产部署。通过CALMS模型(文化、自动化、精益、度量、分享)解析DevOps理念,对比传统瀑布模式与DevOps模式差异,展示AI如何加速Dockerfile编写、CI/CD配置等任务。典型示例显示AI可将原本30-60分钟的手动配置缩短至1-2分钟,大幅提升DevOps效率。

AI天才研究院 367

蓝牙芯片驱动开发-第11章第1题-WiFi蓝牙共存的关键策略有哪些

蓝牙芯片驱动开发-第11章第1题-WiFi蓝牙共存的关键策略有哪些

weixin_42162924的博客 30

Redis 数据类型详解:Hash 哈希与 List 列表

大 key 指单个 key 对应的 value 过大(如 Hash 字段数极多、List 元素极多)。危害包括:单次全量命令(

2303_77004089的博客 105

详解AUTOSAR:什么是AUTOSAR?(理论篇—1)

AUTOSAR是由全球各大汽车整车厂、汽车零部件供应商、汽车电子软件系统公司联合建立的一套标准协议,是对汽车技术开发一百多年来的经验总结。

不脱发的程序猿 1万+

【C++】【STL】list

list 是带头结点的双向循环链表,通过哨兵位消除首尾边界判断,实现任意位置插入删除的常数时间复杂度。其节点独立分配,不支持随机访问,迭代器仅支持前后移动。与 vector 对比,list 在中间插入/删除时更高效,但遍历缓存命中率低;vector 适合随机访问和连续遍历,但头部操作代价高。二者在内存布局、访问效率与适用场景上形成互补。

这里是Cocatrice的博客,感谢大家一直以来的支持和鼓励,如果对C/C++方向感兴趣的话,可以通过主页的微信名片加Cocatrice的好友,也可以通过邮箱:Chen31980094@163.com 联系,一同加油! 638

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java 集合框架(List、Set、Map)与常用基础

本文整理Java集合框架核心知识,涵盖集合体系、Collection接口API、List(ArrayList、LinkedList、Vector)、Set(HashSet、TreeSet)、Map(HashMap、TreeMap、Hashtable)实现类原理、泛型、增强for循环、可变参数与工具类,并附核心易错点速查表。

既然你都点开这里了,那可以给我点个关注吗?可以吗?可以吗? 487

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Bugku 326 Baby-heap1 题解:glibc 2.23 堆溢出到 FSOP 劫持 _IO_list_all(附完整 exp)

为什么 FSOP 在 2.23 这么好用?glibc 2.23 的_IO_FILE虚表调用没有 vtable 合法性检查是 2.24 才加入的),只要能把指向自己伪造的 FILE,就能让__overflow槽位指向任意函数。exit()一定会走因此把_mode置 0、置 1、置 0,就能进入;把fp首地址写成/bin/shsystem(fp)的参数就齐了。为什么用 fastbin attack 而不是?2.23 没有 tcache,fastbin 的fd。

kingx3的博客 211

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

List(下):LPOP / RPOP、BLPOP / BRPOP 与 LINDEX、LINSERT

这是《Redis C++ 实战笔记》系列的第 07 篇。上一篇是往列表里放,这一篇是往外拿——包括那个会"等"的弹出。

wbs_scy的博客 105

[C++]:7.STL:list

好久不见,firdawn小课堂又和大家见面啦。今天我们要学习的内容是list容器,list也是一种常用的数据结构。下面是本章的思维导图,那么让我们开始学习吧!自定义的list,由三个结构构成。分别是链表的最小组成单位,也就是链表节点。以及迭代器类和list类其实要特别说明的是, List的迭代器,它不是单纯的指针,因为我们如果对指针直接进行解引用操作的话,我们得到的是这个节点,而不是节点里面存储的值并且我们对这个指针加加,得到的也不是下一个节点的地址,而是所在节点的下一个单位的地址。

2301_80817679的博客 193

一个链表(Linked List)--为什么要用链表--deepseek

数组(如你定义的大盘子就像你在 FPGA 里例化了一块深度为 2500 的 BRAM。它必须是一块连续的、完整的内存。如果内存里全是碎片,凑不出 2500 个连续空位,数组就建立不起来。链表(Linked List)就像一堆散落在大街小巷的小仓库,每个仓库大小不固定,彼此不挨着。但是,每个仓库的门口都贴了一张小纸条,纸条上写着“下一个仓库的地址”。我们来画个图,这就是链表的核心——节点(Node)text。

AlibabaApple的博客 171

FreeRTos笔记(12c):从事件链表里删除节点 xTaskRemoveFromEventList、

(1) (2) 谢谢

zhangzhangkeji的博客 163

【C++初阶】list使用及相关实现,思路顺滑流畅!

list使用及相关实现

Severus_black的博客 208

List(上):LPUSH / RPUSH 与 LRANGE

这是《Redis C++ 实战笔记》系列的第 06 篇。String 讲完了,进入第二种类型:List。它是一串有顺序、可以重复的值,两头都能进出。

wbs_scy的博客 243

细粒度锁的线程安全list实现

【代码】细粒度锁的线程安全list实现。

weixin_43698578的博客 198

TypeError: must be str, not list

【代码】TypeError: must be str, not list。

Forerunner and Successor 先駆者と後継者 49

Java Arrays.asList 常见坑详解|UnsupportedOperationException、数组联动、基本类型 bug

解析 Arrays.asList 常见开发陷阱,演示 UnsupportedOperationException、底层数组引用共享、基本类型数组问题,区分 Arrays 内部 ArrayList 与 java.util.ArrayList,给出数组转 List 的各种场景正确代码。

weixin_42617033的博客 477
上一篇: Windows Shutdown API
下一篇: A more stable way to locate real KiServiceTable
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值