Windows rootkits of 2005, part two

Analysis_between_Chinese_and_Western_Architectural_Culture 关于中西方建筑艺术的比较,这是一篇英语论文 立即下载
 

1. Introduction

In our previous article, we discussed current rootkit development techniques. In this article, we take it a step further and focus upon upcoming, cutting edge trends in rootkit technologies. Then the third and final article in this series will discuss various methods of rootkit detection and countermeasures that can be used by security professionals.

The methods described in this article were presented in our proof of concept rootkit named Shadow Walker at Black Hat 2005. These methods make it possible for an attacker to hide both known and unknown malicious code from a security scanner by controlling its memory reads at the hardware level. Although we focus upon rootkits, the underlying implications are alarming because the technology can be applied to all forms of malicious code, ranging from worms to spyware.

1.1 Persistent versus memory-based rootkits

Generally speaking, there are two types of rootkits: persistent rootkits and memory-based rootkits. The primary difference between these two types of rootkits lies in their "persistence" on an infected machine after a reboot. Persistent rootkits are capable of surviving a system reboot whereas memory-based rootkits are not. In order to survive a reboot, two conditions must be met. First, they must have some means of permanently storing their code on the victim system (such as on the hard disk). Second, they must place a hook in the system boot sequence so that they can be loaded from disk into memory and begin execution.

Unlike persistent rootkits, in-memory rootkits make no effort to permanently store their code on disk or hook into the boot sequence. Their code exists only in volatile memory and they may be installed covertly via a software exploit. This makes them stealthier than their "persistent" brethren and confers anti-forensic advantages. While it may seem that an inability to survive a reboot would undermine the usefulness of these rootkits, server systems frequently remain online for days, weeks, or months at a time. In practice, the potential for losing the rootkit infection may be counter-balanced by an attacker's need for untraceability.

1.2 Hiding a rootkit's presence

Rootkit writers have developed a number of clever techniques for hiding their rootkit's presence on a system. These techniques range from various hooking tricks to direct kernel object manipulation (DKOM). Nevertheless, even the most sophisticated kernel rootkits like FU have an inherent flaw. [ref 1] Although these rootkits are experts at controlling the execution path, for the most part they have not demonstrated an ability to control the view of memory that is seen by other applications. Thus, these rootkits must address two primary issues if they are to remain undetected. First, they must be able to conceal the presence of their own executable code. Second, they must be able to conceal their memory-based modifications (i.e., hooks) in operating system components. Without these capabilities, even the most sophisticated public kernel rootkits are "sitting ducks" for primitive in-memory signature detection scans - the same type of scans anti-virus products have been using for the past 20 years. Persistent rootkits must furthermore deal with hiding their code on a long tem storage medium and concealing a permanent hook in the system boot sequence. In this article, we will be addressing the first two issues and ignoring the third. Practically speaking, this confines our discussion to memory-based rootkits.

The problem of hiding code and/or changes in memory is reminiscent of the problem early virus writers faced when attempting to hide their code on the file system. Virus writers reacted to file system signature scanners by developing polymorphic and metamorphic techniques. Polymorphism attempts to vary the superficial appearance of a block of code while maintaining functional equivalence. As a simple analogy, we can consider English synonyms (words that are spelled differently yet have exactly the same meaning). A polymorphic virus replaces instructions (words) with different opcodes (synonyms) that perform the same functionality. In this manner, the mutated virus superficially "looks different" and becomes immune to simple pattern-based detection.

Very few public rootkits have made any substantial effort to integrate viral polymorphic techniques. Though polymorphism could be effective for disguising a rootkit's code body from signature scans, it is not ideal because it does not lend itself well to hiding the changes a rootkit makes to existing binary code in other system components. In other words, hijacked system components remain vulnerable to in-memory integrity checking. A better solution, therefore, is not to alter the rootkit's code, but to alter how other system components "see" it. In the following sections, we show how the current architecture permits subversion of virtual memory management so that a non-polymorphic kernel mode rootkit is capable of controlling the memory reads of the operating system and other processes. In section 2, we review basic architectural and operating support for virtual memory. In section 3, we discuss how the Shadow Walker proof of concept rootkit subverts the virtual memory subsystem to hide executing code from a security scanner. Finally, in section 4, we discuss the implications of this technology for both security professionals and hackers.

2. Virtual memory concepts

Most modern architectures make a distinction between "virtual" and "physical" memory. Oftentimes, a system will have a great deal more virtual memory than physical memory. Consider a 32-bit system with 256 MB of installed RAM. On this machine we have 4 GB of virtual memory, even though our physical memory size is only 256 MB. In short, physical memory size is defined by the amount of physically installed RAM, and virtual memory size is defined by the width of the processor's address bus. Thus, with a 32 bit processor we are capable of addressing a maximum of 2^32 bytes, or 4 gigabytes of virtual memory. With a 64-bit machine, we would be capable of addressing 2^64 bytes, or over 16 exabytes of memory!

Virtual memory implementations come in a couple of different flavors including segmentation and paging schemes. The x86 architecture supports both; however, this article focuses on paging since that is the part Shadow Walker subverts. The basic idea behind paging is that the virtual and physical address spaces are divided into fixed size blocks. Virtual memory blocks are referred to as "pages" and they are mapped to blocks of physical memory known as "frames." Page tables and page directories hold the mapping information necessary to link virtual pages with their corresponding frames. They also hold protection and status information. One key point is that when paging is enabled, every memory access must be looked up to determine the physical frame to which it maps and whether that frame is present in main memory. This incurs a substantial performance overhead, especially when the architecture is based upon a two-level page table scheme like that found in the Intel Pentium.

By making a distinction between virtual and physical memory, the hardware and operating system are able to provide processes with the illusion that there is more memory than is actually, physically available. Paging is invisible to application processes. From the viewpoint of an application, it has 4 GB of virtual memory available for its personal use. It does not need to know how much RAM is actually installed or how the virtual addresses it uses map to physical memory. Since the virtual address space may be larger than the physical address space, it is possible that a process' demand for memory may exceed the amount of memory that is physically available. If this happens, the operating system will need to temporarily swap some of the data in physical memory to disk in order to make room for current memory demands. It does this by copying some frames to the pagefile and marking their corresponding page table entries as "not present." When these pages are accessed again, they will not be present in main memory and page faults will occur. A page fault will invoke the operating system's page fault handler, causing it to issue the I/O request necessary to bring in the requested page from the page file. If all of the available physical frames are still full, the handler may have to swap another page out before it can bring in the requested page.

In a two-level paging scheme, a memory access potentially involves the following sequence of steps.

 

  1. Lookup in the page directory to determine if the page table for the address is present in main memory.
  2. If not present, an I/O request is issued to bring in the page table from disk.
  3. Lookup in the page table to determine if the requested page is present in main memory.
  4. If not present, an I/O request is issued to bring in the page from disk.
  5. Lookup the requested byte (offset) in the page.

Figure 1 illustrates the process of x86 address translation. From the above steps we can see that, in the worst case, a single memory access may actually require three memory accesses plus two disk I/Os. Hardware designers developed the Translation Lookaside Buffer (TLB) to help with this problem. The TLB is a high speed cache that is used to hold frequently used virtual-to-physical mappings. When a memory access occurs, the TLB is searched first for the virtual-to-physical translation information before consulting the page directory / table. If the translation is found, it is termed a "hit". Otherwise, it is a "miss". Because the TLB can be searched much faster than performing an access to the page tables, memory accesses resolved via the TLB avoid most of the aforementioned performance penalty.

 


Figure 1. x86 virtual To physical address translation.

3. Shadow Walker: how it works

The Shadow Walker proof of concept currently consists of 2 drivers, a modified FU rootkit driver and a memory hook driver that is used to hide the FU rootkit. As Shadow Walker is intended only to be a proof of concept demonstration, it makes no effort to hide the memory hook driver or otherwise conceal the page fault handler and corresponding interrupt hook. It also possesses a number of implementational limitations, including lack of PAE (Physical Address Extension) and multiprocessor support. Shadow Walker is not intended to be a fully functional or weaponized rootkit and, in its current implementation, it is detectable from a variety of angles. Rather, it is intended to provide a chilling glimpse into the future of rootkit technology. A fully weaponized rootkit, worm, or spyware application based upon Shadow Walker is within reach of a skilled attacker and given the state of existing malicious code detection technology, it is a scary thought indeed. These methods make it possible for an attacker to hide both known and unknown malicious code from signature scanners, heuristic detectors, and integrity checkers. In the next paragraphs, we discuss the implementational details behind the virtual memory subversion techniques used by Shadow Walker.

3.1 Background information

Although it is common knowledge that there are three basic types of memory access (read, execute, and write), it is less common knowledge that there are, in fact, only two types supported for most of the 32-bit x86 processors (read/execute and write/execute). Execute access is implied, meaning that all memory is executable and there is no direct, supported means of marking it otherwise. This quirk of the architecture has been the bane of buffer overflow intrusion detection systems because it meant that there was no easy way to make the stack non-executable . [ref 2] Not to be outdone, a group of software security developers discovered that another quirk of the architecture made it possible to implement "no-execute" memory with additional software support under UNIX. [ref 3] This implementation became known as PaX. Shadow Walker takes advantage of some of the PaX team's research to hide executing code on Windows systems.

To recap: modern rootkits need to address two additional issues if they are to remain undetected.

 

  1. They must be able to conceal the presence of their own executable code from in memory signature scans.
  2. They must be able to conceal their memory based modifications (typically, hooks) in operating system components from heuristic detection (with tools like VICE) and integrity checkers. [ref 4]

In order to accomplish these goals, the rootkit must be capable of controlling the data returned from the raw memory reads performed by other applications, such as security scanners. Clearly, if a rootkit detects a read access to its own executable code section it is a reasonable heuristic that a scanner may be looking for it!

3.2 Shadow Walker's subversion of virtual memory

Shadow Walker must address three issues in its subversion of virtual memory. First, it must be able to differentiate and filter execute, read, and write accesses to certain memory ranges (i.e. the memory where its own executable code resides or the memory of some subverted operating system APIs). Second, it must be able to "fake" the read accesses when they are detected. Lastly, it must ensure that the performance of the victim system is not adversely affected.

The first issue is solved by marking the PTEs for the hidden pages "non present" and hooking the page fault (PF) handler. This ensures that Shadow Walker will be able to trap accesses to these pages and subsequently filter them in the page fault handler. In the page fault handler, we have access to the saved instruction pointer and the faulting address. If the instruction pointer is the same as the faulting address, we can conclude that the memory access was due to an execute. Otherwise, it is a read / write. One other point to note is that Shadow Walker needs to differentiate between page faults due to the memory hook and normal page faults which need to be serviced by the OS. It currently addresses this issue by ensuring that all hidden pages are in non-paged memory. This isn't a problem since Shadow Walker is currently designed to hide only driver pages that are usually non-paged anyway.

The second issue, that of faking read accesses, is somewhat tricky and is tied in with the third issue of not degrading performance. Once the page fault handler has been invoked and we have detected and verified a read access to a hidden page, it is possible for us to modify the PTE and alter the physical frame address "on the fly." Thus, we can ensure that execute accesses translate to our "subverted" frames while read / write accesses translate to "clean" frames. Remember, however, that the TLB is actually the first entity on the memory access path and that performing a memory access loads the TLB with the corresponding translation. The Pentium actually uses a "split" TLB architecture and Shadow Walker uses this fact to devious advantage. A split TLB architecture means that there are actually two TLBs, one to hold the translations for execute accesses (ITLB) and the other to hold the translations for read / write accesses (DTLB). Normally, the two TLBs are synchronized and maintain the same mapping information. It is, however, possible to de-synchronize the TLBs such that they hold different virtual-to-physical mapping information.

A rootkit like Shadow Walker can use this desynchronization trick to hide executing code. In other words, it loads the ITLB with the mapping information for the subverted pages, and the DTLB with the mapping information for a "clean" copy. The rootkit code runs, but all attempts to read this region of memory result in "clean" non-rootkit data being returned to the security scanner. TLB loading is performed in the page fault handler in response to faults generated by memory accesses to hidden pages. Figure 2 illustrates this concept. All other faults are passed down to the operating system page fault handler for service.

 


Figure 2: TLB Desynchronization

Once loaded, most memory references will be resolved via the TLB path and will not generate page faults. Faults, however, will occur on the first execute and data accesses to the page, on TLB cache line evictions, on context switches, and explicit TLB flushes. These few faults do not pose any problems and will simply result in the page fault handler being invoked to re-desynchronize the TLBs. Finally, this brings us to our last issue of maintaining system performance. The relatively low increase in the page fault rate caused by Shadow Walker coupled with the extremely high hit rates of modern TLBs results in virtually no noticeable performance impact.

4. Concluding part two

Shadow Walker provides an example of an ironic, however, common yin/yang theme in computer security. It takes an originally defensive solution to a security problem (with the PaX-based buffer overflow protection) and inverts it into an offensive exploitation technique. The recent controversy surrounding Sony's usage of rootkit technology to provide Digital Rights Management is yet another compelling example. The lines between protection and exploitation between the "hacker" and the "security professional" are not as clearly defined as many would like to believe.

In the first article of the series, we showed that security applications can't trust the integrity of operating system APIs. Now, we show that the violation of trust runs much deeper. Shadow Walker bids user mode malware scanners a final goodbye and places rootkit detection strictly within the kernel realm. In the third and final article of this series we will discuss rootkit detection and threat mitigation.

5. References

[ref 1] Fuzen, FU Rootkit. http://www.rootkit.com/project.php?id=12
[ref 2] Hardware support has subsequently been added for non-executable memory in 64-bit systems as well as some AMD Sempron and Intel Pentium 4 processors. Windows also provides limited software support in the form of Data Execution Prevention (DEP) as of Windows XP Service Pack 2 and Windows 2003 Server.
[ref 3] PaX. http://pax.grsecurity.net/docs/pax.txt
[ref 4] Butler, James, "VICE - Catch the hookers!" Black Hat, Las Vegas, July, 2004. www.blackhat.com/presentations/bh-usa-04/bh-us-04-butler/ bh-us-04-butler.pdf

5.1 Further reading

Rutkowska, Joanna. "Concepts For The Stealth Windows Rootkit", Sept 2003 http://www.invisiblethings.org/papers/chameleon_concepts.pdf

Russinovich, Mark and Solomon, David. Windows Internals, Fourth Edition.

6. About the authors

linux虚拟内存 国外讲操作系统虚拟内存最好的一本书,可以没有之一。 立即下载

相关推荐

Architectural Differences Between IMX51and 53

飞思卡尔为处理器IMX51与IMX53的区别

Architectural and OS support for Virtual Memory

Architectural and OS support for Virtual Memory

yiyeguzhou100的专栏 983

eVTOL热管理:从电动车到飞行器的技术跃迁与工程挑战

热管理系统是保障各类电动设备安全、高效运行的核心技术,其基本原理是通过冷却、加热和温度控制,确保电池、电机等关键部件在最佳工况下工作。在新能源汽车领域,热管理技术已相对成熟,但面对eVTOL(电动垂直起降飞行器)这一新兴领域,其设计逻辑需从二维地面转向三维空域,应对环境温度剧烈变化、重量约束极端严苛等全新挑战。eVTOL的热管理不仅是简单的技术移植,更涉及对电池瞬时高功率散热、乘员舱快速温控及多热源耦合等复杂工程问题的系统性解决,直接关系到飞行安全与商业航程。本文聚焦于**环境温度**和**有效载荷**等关

weixin_42521276的博客 614

Windows rootkits in 2005, part two

Windows rootkits in 2005, part twoJames Butler, Sherri Sparks 2005-11-171. IntroductionIn our previous article, we discussed current rootkit development techniques. In this article, we take it a step

eaglenet的专栏 1105

CMap与L1000技术解析:基因表达数据在药物发现中的应用

本文深入解析了CMap(连接图)与L1000技术在药物发现中的核心应用。CMap通过构建基因表达“关系网”,实现基于模式匹配的药物重定位;L1000技术则以低成本、高通量方式生成关键基因表达数据,支撑了LINCS超级数据库。文章以CLUE平台为例,手把手演示了如何利用疾病基因表达签名逆向筛选潜在治疗化合物,并拓展了其在解析药物机制、预测副作用等多场景下的价值。

weixin_29207533的博客 728

【CANoe16安装教程】亲测安装成功

CANoe16安装教程

qq_45302638的博客 2万+

RAM, Virtual Memory, PageFile and all that stuff

 This article explains some aspects of the Virtual Memory implementation in Windows 2000, XP, 2003 Server etc.  It is intended for a general audience that has an interest in the relationship between R...

weixin_33787529的博客 234

bugku渗透测试4-writeup

三、对这个主机进行全端口的扫描,发现存在22000 ssh端口,那么可以联想到时redis写入公钥来连接主机。又来了一个新的靶场,这个靶场打下来我觉得关键就是信息收集,走了很多的弯路。八、最后一个flag是要去看cms的数据库里面,这个数据库是sqlite。把这个数据库下载下来,登录密码是加密的,就直接用token。一、入口的漏洞是在登录的时候去抓包,修改action的值。六、没想到这个第一台机器的密码,在第二台里面。七、扫描第一台主机、使用之前的密码连接成功。获取最后一台主机的root密码。

vsdfbhsdhsdfh的博客 1303

【简记】Operating System—— virtual memory

This memo is based on the course of Dr.Li with Operating System as the reference book.本章内容: 虚拟内存的概念 按需调页 页置换 帧分配 系统抖动 9.1 背景研究实际程序会发现,在许多情况下并不需要将整个程序放到内存中: 程序通常有处理异常错误条件的代码。由于这些错误即使有也是很少发生,所以这种代码几乎不执行。

qqqqq1993qqqqq的博客 616

求无向图中所有的环 C++ python

求无向图中所有的环

random_repick的专栏 1152

CIC-IDS数据集特征介绍

###1、简介 通信安全机构(CSE)与加拿大网络安全研究所(CIC)合作项目,该项目对自1998年以来现有的11个数据集的评估表明,大多数数据集(比如经典的KDDCUP99,NSLKDD等)已经过时且不可靠。其中一些数据集缺乏流量多样性和容量,一些数据集没有涵盖各种已知的攻击,而另一些数据集将数据包有效载荷数据匿名化,这不能反映当前的趋势。有些还缺少特征集和元数据。 CIC-IDS-2017数据集包含良性和最新的常见攻击,类似真实世界数据(PCAPs)。 它的数据采集截至2017...

蓝亚之舟的博客 3万+

Windows rootkits of 2005, part two(翻译)

        上一篇文章中,我们谈到了当前的rootkit开发技术。本文更深入一点,将焦点集中在rootkit技术的最前沿。在第三篇,也就是本系列的最后一篇中,将重点论述rootkit侦测的各种方法及安全方面的专业的应对措施。        本文讲述的方法是在Black Hat 2005大会上介绍的Shadow Walker的rootkit原型试验时提出的。这些方法使得攻击者通过控制扫描器在

coding_hello的专栏 2085

【ESP32设备通信】-LoRaWAN网关

在物联网 (IoT) 时代,连接设备和收集数据变得比以往任何时候都更加容易和重要。 LoRaWAN(远程广域网)技术已成为远程、低功耗物联网通信的强大解决方案。 在本教程中,我们将使用 ESp32 构建 LoRaWAN 网关电路,并使用 ESP32 和 BME280 传感器构建传感器节点电路。 对于这两个电路,我们将使用基于 SX1278 (Ra-02) LoRa 模块在设备之间进行无线通信。 我们还将向您展示如何将传感器数据传输到流行的物联网平台 ThingSpeak。

视觉与物联智能 1584

操作系统 第五章 虚拟存储

  1、基于局部性原理 1)程序运行前,不需全部装入内存(打破一次性) 仅装入当前要运行的部分页面或段即可运行,其余部分暂留在外存上。 缺页/段的情况:要访问的页(段) 尚未调入内存。程序应利用OS所提供的请求调页(段)功能,将它们调入内存,使程序继续执行。 2)调入需要的页/段时,如果内存已满,无法再装入新页(段),通过置换功能将内存中暂时不用的页(段)调至外存,腾出足够的内存空间。(...

gh的博客 684

QT实现OPCUA服务端客户端(附完整源码)

QT实现OPCUA服务端客户端(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1824

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

循环嵌套(多层 for 循环)

表:order(订单表,order_id, user_id)、user(用户表,user_id, user_name)✅ 优化:先查所有订单,拿到所有 user_id 批量 in 查询,内存 join。✅ 优化:先把优惠券转 HashMap,单层循环查找(hash 查找 O (1))SQL 只有 2 次,O (1) 数据库查询,内存遍历 O (n)。需求:查询所有订单列表,同时带出每个订单对应的用户名称。需求:订单列表、优惠券列表,把订单匹配对应的优惠券名称。复杂度:O (M+N),非常快。

weixin_43732943的博客 215

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Python+Agent入门笔记(六):记忆和状态,从“一次性问答”到“能用助手”

滑动窗口的缺点很明显:被扔掉的信息就真没了。如果用户第一轮说“我不吃辣”,隔了二十轮让他推荐餐厅,模型已经忘了。定期把旧的对话压缩成一段总结,作为一条特殊的消息插进去。"""把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。"""# 把旧消息拼成纯文本,让模型总结content = f"[工具结果]把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。

qq_41241612的博客 108

ssm框架搭建

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

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

a bit 215

本地chatbot4--引入LangGraph

上一节实现了chatbot的连续调用工具的功能,但目前流程还是提示词→模型→解析→调用工具(可选)→输出线性的一条路走到底(LangChain)只适合简单线性任务(问答、摘要、简单RAG)agent的本质是:“模型决定调工具→执行→结果喂回模型→再决定……直到完成”。举例:读日志 → 解析 ─失败→ 重试(≤3次) ─→ 退出│成功↓算统计 → 对比历史 → 生成报告 → [人工审核卡点] → 发送。

weixin_45859446的博客 103

C# 数据结构和特殊类型

.NET Core(现称.NET)提供丰富数据结构,优化性能与开发效率。日常开发首选List<T>和Dictionary<TKey,TValue>;高性能场景推荐Span<T>与Memory<T>减少内存分配;并发环境使用ConcurrentDictionary等线程安全集合;避免非泛型集合如ArrayList。

cccloveforever的博客 746

C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?

第17课:用大白话讲清 list 的双向链表结构、哨兵头、push_back 四步、迭代器封装、merge 与 splice 的区别,以及 vector 排序为什么常比 list 快。

wo_jack的博客 251

list

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

xie0510_的博客 293

3.链表相关知识点

链表

2501_93884468的博客 436
上一篇: Windows rootkits of 2005, part one
下一篇: Windows rootkits of 2005, part three
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值