from:http://www.4ucode.com/Study/Topic/1407760

在本文中我们讨论了识别恶意代码的各种方法,它们彼此间在功能上(以及时间上)的联系,它们的技术以及特点。从一个方面讲,这里写到的许多技术和原理实际上并不仅仅可以用在反病毒方面,还可以用在计算机安全系统里更为广泛的环境下。从另一方面讲,有很多技术,它们确实重要,但只用在反病毒方面,如脱壳和流特征检测,对这样的技术本文没有讨论。

引言

最初的搜索恶意程序的技术是基于特征码的。特征码是一段能唯一确定恶意程序的一段代码。随着病毒的演化,病毒检测技术也日益复杂。这些先进的技术——各种启发式分析和行为分析——都可以统称为非特征检测技术。

尽管从标题看本文似乎涉及到了所有的恶意代码检测技术,但实际上本文主要聚焦与非特征检测技术——关于特征扫描技术已经没什么可说的了,这种技术很直观,也很原始。目前,用户对非特征检测技术都还比较陌生。在“启发式”、“主动检测”、“行为检测”、“HIPS”这些名称背后的到底是些什么呢?这些技术彼此间有什么关系呢?它们又有什么有缺点呢?给出这些问题的答案就是本文的目的。另外,本文和前一篇《恶意程序自保护技术的演化》一样,目的就是系统地总结并最为客观地研究一些恶意程序及其防御上的

一些特别的问题。本文预期的读者是对反病毒技术有基本的认识但不是这个恶意程序防御领域专家的人。

恶意程序防御系统模型

首先我们来看下恶意代码搜索技术。为此,我使用以下模型。

在任何防御系统中都有两个组件:技术组件和分析组件。在模块层面或算法层面上,这两个组件的区分倒不一定明显,而在功能层面上,它们却有着显著的区别。

技术组件是用某些算法为分析组件提供分析数据的程序的集合。例如,文件字节代码,文件中的文本字符串,程序独有的行为或行为序列。

分析组件是做出判决的系统。它是一个算法,分析提交给它的数据并给出某些判定结果。根据这些结果和安全策略,反病毒软件(或其它安全软件)会采取相应的行动:通知用户,询问处理方式,将文件隔离,阻断未认证的程序行为等等。

举个例子。我们来看一下经典的基于特征码检测的防御恶意程序的方法。对这种方法来说,技术组件就是获取文件系统、文件数量及内容等信息的系统,而分析组件就仅仅是一个比较字节序列的操作。也就是说,简单说来,分析组件的输入就是文件代码,而输出就是判定结果——文件是否有害。

在这种模型框架下,任何防御系统都可以表示成一个“复数”——两个独立对象的联合体:技术组件与分析组件。用这种观点来分析技术,我们很容易看出它们的关系和它们的优缺点。特别地,借助于这个模型我们可以很容易地解决技术定义中的歧义。例如,后面会证明,“启发式”,作为一种判定的方法,只是应该归在分析组件中,而不是一种独立的技术。而HIPS (Host Intrusion Prevention System),只是一种技术组件,是一种搜集数据的方法。由此得出结论,这些术语,首先形式上彼此不矛盾,第二,不能完整地刻画它们所描述的技术。说到启发式,我们可以不确定启发式分析所用到的数据,而说到HIPS系统,我们可以不知道它的判定标准。

关于这些技术的更为详细的信息将在相应的章节里讨论,现在我们来看恶意代码搜索技术原理本身:技术的——信息收集手段,和分析的——信息处理手段。

技术组件

构成恶意程序检测系统的技术组件收集用于分析的数据。

恶意程序,首先是具有一定内容的文件,其次是在操作系统中进行的一组行为,第三,是操作系统中作用效果的集合。因此对恶意程序的识别可以从不同的层面上进行:通过字节序列,通过行为,通过对操作系统的影响等等。

一般来讲,要使恶意程序现形可以通过以下方法:

1. 将文件作为字节序列处理。
   2. 模拟程序代码。
   3. 在沙箱中运行程序(sandbox)(以及其它类似的虚拟技术)。
   4. 监视系统事件。
   5. 搜索系统异常。

上面的方法是按处理代码时抽象级别由低到高排列的。这里抽象级别的意思就是我们用什么样的角度来看可执行程序:作为原始的数字对象(字节串),作为行为(字节串的结果,更为抽象)施动者或是作为对操作系统产生的效果(行为的结果,进一步抽象)的集合。反病毒技术大概就是按照这个向量来发展的:处理文件本身,根据文件处理事件,根据事件处理文件,处理环境本身——所以给出的列表很自然地按时间顺序排列下来。

要强调的是,上面列出的独立技术有几种,恶意程序数据收集技术的连续发展过程就有几个阶段。从一种技术发展过渡到另一种技术基本上都是渐进的。例如,对模拟来说,如果技术的实现只将文件作为字节序列,那么它就接近于简单的文件处理;如果完整地虚拟了系统函数,那它又接近于虚拟技术。

我们来详细地看一下这些方法。

1. 文件扫描

最早出现的反病毒软件都是将文件视为字节序列的。然而,我们却很难称之为分析技术。它仅仅是将字节序列和已知的特征做比较。但我们现在感兴趣的是这种技术的技术组件:

在搜索恶意程序过程中,数据被传递到判定组件,而这数据是从文件中抽取出的一个具有某种形式的有序字节序列。

这种方法的特点在于,反病毒软件只处理程序的字节码,而不关心它的行为。尽管方法比较老旧,但并没有过时,直到现在还用在所有现在的反病毒软件中,只是它已经不再是唯一的,甚至不再是主要的方法了,只是众多技术中的一种而已。

2. 模拟

模拟技术从程度上来说处于把程序视为字节序列的技术和把程序视为行为序列的技术之间。

虚拟机将程序字节代码划分为指令,并在虚拟的计算机环境中执行每一条指令。这样就可以监视程序的行为,不会像在真实环境中执行恶意程序那样会威胁操作系统和用户数据。

在抽象层级中模拟器位于中层。所以虚拟机的特点大致可以归结为:虚拟机仍然和文件打交道,但是所分析的实际上已经是事件了。虚拟机已经用在了许多反病毒软件中,主要是用作底层的文件引擎或高层引擎(沙箱、系统监视)的一种辅助。

3. 虚拟化: 沙箱

虚拟化技术使用了沙箱,是模拟技术的一种逻辑延伸。使用沙箱技术时,恶意程序已经是在真实的环境中运行了,只不过是被严格控制起来了。

沙箱这个名称就已经很好地反映了虚拟化的本质。通常意义上的沙箱就是封闭的环境,小孩子们可以在里面安全地玩耍。如果做个类比,把操作系统比作现实世界的话,那么扮演爱玩的孩子角色的就是恶意程序了,而这时封闭的环境就成了一组在操作系统中活动的准则。这些准则可以阻止恶意程序修改注册表,利用部分模拟技术提供有限的文件系统操作支持。例如,在沙箱中启动的程序会得到系统注册表的一个副本,这样这个程序对注册表做的修改不会影响到操作系统的正常工作。这样,我们可以虚拟出任何一个程序与环境的接触点:文件系统,注册表。

模拟技术与虚拟化技术之间的界线可能并不宽,但却很明显。前一种技术为程序的执行提供了环境(这样工作的进程就包含了被执行的程序并完全控制了程序的运行)。对后一种技术来说,作为运行环境的已经是真实的操作系统了,而这种技术就是用来控制程序与操作系统间的交互,这就是它和前一种技术的差别所在。

这样,前面所述的这些基于虚拟技术的防御手段的处理对象已经不再是文件,而是程序的行为——但还不是系统。

反病毒软件不会主动使用“沙箱”以及虚拟机这类的方法,主要是因为这些实现方法的程序需要占用大量的资源。带有沙箱的反病毒程序在程序启动和开始执行之间会有一个延时(成功识别出恶意程序的情况——即在恶意程序启动和反病毒软件检测到恶意程序并给出信息之间的延时),所以可以通过这一点判断反病毒程序是否有沙箱。目前硬件虚拟化方面的研究正在积极进行之中,这种情形不久就会改善。

目前只有几个防病毒软件使用了“沙箱”引擎。

4. 系统事件监控

系统事件监控是一种更为抽象的为暴露恶意程序而搜集信息的方法。如果说虚拟机或沙箱是观察每一个独立的程序的话,监控器则是通过监视操作系统和运行的程序中产生的所有事件来观察所有程序。

从技术上说,这种信息搜集的方法是通过挂钩操作系统函数来实现的。挂钩了某些系统函数调用后,挂钩函数就得到了某个确定程序在系统中进行某个确定行为的信息。作为功能的延伸,监控器会收集这些行为的统计信息并将它传给分析组件处理。

这种技术目前发展最为迅速。在某些较好的反病毒软件中,它已经成为了一种组件,占据了基础性低位,成为了一个独立的工具,专门用来监控系统(成为“HIPS工具”,“HIPS”就是像Prevx、CyberHawk这类的程序)。由于任何防御都可以被绕过,所以这种搜索恶意程序的方法并非是最有前途的。在真实环境中运行程序所带来的威胁会大大降低防御的效果。

5. 搜索系统异常

这是搜集可能被感染的系统中信息的最为抽象的方法。我这里首先是把它作为前面技术的一种自然延伸和抽象的极限而提出来的。

这种方法建立在以下前提之上:

操作系统和运行于其上的程序是一个完整的系统;
操作系统有内在的“系统状态”;
如果在操作系统中执行了恶意代码,则系统的状态就是“非健康的”,这种状态和系统中没有恶意代码时的“健康状态”是不同的。

从这些状态入手,将系统状态与标准状态(用作“系统健康”状态的标准状态)做对比或单独分析状态参数,我们就能评价系统的状况(从而能够判断系统中是否可能有恶意程序)。

为了有效地用分析异常的方法来检测恶意代码,分析系统必须足够强大——比如用专家系统或神经网络。这就引出了许多问题:如何定义“健康状态”,它和“非健康状态”的区别在哪里,有哪些离散的参数可供跟踪以及如何进行分析。由于这种复杂性,目前这种方法用得还很少。它的源头可以从某些anti-rootkit工具中找到。这些工具要么将系统状态和标准系统状态做对比(已过时的PatchFinder、Kaspersky Inspector),要么比较单独的参数(GMER, Rootkit Unhooker)。

有趣的比喻

前面“沙箱”部分做的孩子的比喻,还可以这样延伸:虚拟机就像个保姆,时刻照看着孩子,不让他有不良的行为;系统事件监控则像个私塾老师,监督着一群孩子;而搜索系统异常技术则给予了孩子们充分的自由,只是会在操行日志里给它们打分。这样打比方的话,那文件的字节分析就只是对孩子的设计,更确切的说就是在准父母的性格里寻找不安分的成分。

而且,就像孩子一样,技术也是在成长和发展的。

分析组件

病毒判定算法的复杂度可以是完全任意的。反病毒软件的分析系统大致可以分成三种,而在这三者中间可能还有许多中间变体。

简单比较

通过将单一对象与已有样本做比较而得出结论。比较的结果是排中的(即只有“是”或着“不是”)。一个例子就是用严格确定的字符序列去识别恶意程序。更高层次点的例子就是通过行为比较而发现可疑程序行为(比如向注册表关键部位或自启动文件夹中写入)。

2. 复合比较

将一个或几个对象与相应样本做比较而得出结果。比较的模式可以是可伸缩的,而比较的结果是一个概率。例如,使用几条字节特征中的一条来识别恶意代码,而这几条字节特征都是非严格的(每一个单独字节序列都是不确定的)。另一个更高层次点的例子就是通过几个恶意程序用到的并且用一定的参数非顺序调用的API函数来识别恶意代码。

3. 专家系统

通过对数据进行复杂的分析而得出结果。这可能会是个自身带有人工智能成分的系统。比如说:不使用严格给定的一组参数,而是从整体上多方面评估所有参数,考虑它们的潜在恶意性的权重并计算出总体结果。

技术的本质 — 什么是什么

我们现在来看这些恶意程序搜索具体技术的基础是些什么样的算法。

一般开发新技术的厂商都会给他们的新技术起一个全新的、独特的名字(例如Kaspersky Antivirus的“主动防御”,Panda的TruPrevent,F-Secure的DeepGuard)。这种做法是很正确的,因为这样可以避免用户受狭义术语的影响而对新技术有先入为主的错觉。然而,在用通俗的、技术味不浓的语言描述新技术时,使用像“启发式”、“虚拟机”、“沙箱”、“行为阻断”这样含义广泛的术语就不可避免了。

到这里,术语意义上的分歧开始出现了。这些术语都是没有严格定义的(理想状况下,一条术语的意义应该是单一的)。对于一条术语,这个人的理解可能是这样的,而那个人可能又有另外的理解。而且,术语作者为它赋予的清晰易懂的意义经常和专家们所理解的含义不同。这就解释了一个现象,即在反病毒软件厂商的网站上充斥着大量技术术语,但却找不到有关这种技术本质的信息。

例如,某些反病毒厂商称自己的产品装备了HIPS、“主动技术”或“非特征码技术”。如果用户将HIPS理解为有一个程序监控系统事件并分析是否存在恶意代码,那他就有可能被骗。实际上,靠这些术语,反病毒厂商可以掩盖所有他们想掩盖的信息——比如,装备有“启发式”系统的“虚拟机”引擎。还有一种情形经常会遇到,就是将某种技术描述为“启发式”的,但却没有任何更为详尽的信息。

需要强调的是,我们不是说反病毒厂商有意要欺骗用户——很有可能写那些描述的人自己都不明白那些术语的意思。我们只是说,那些对技术的描述都是给用户看的,而用户可能并不了解这些技术到底是什么东西,再有就是提醒用户在靠这些描述选购反病毒软件的时候应谨慎。

我们来详细看一下这些反病毒领域中的流行名词。

“特征码检测”的歧义最小:无论怎么说,从技术角度讲它都是和文件字节代码打交道的,而从分析角度讲它用的就是最初级的数据处理方法,一般就是简单比较。这种技术最为古老,但却最为可靠,所以尽管它有个最大的缺点,需要更新病毒库,但是直到今天各个反病毒软件仍都在使用。

前面列表中的“虚拟机”、“沙箱”也没什么其它的解释方法。用于它们的分析组件的算法复杂度也可以是任意的,从简单比较到专家系统。

而“启发式”这个词就有点朦胧了。奥日科夫俄语词典上的定义是:“启发——检测未知病毒的所有研究方法”。启发式首先是一种分析组件,而不是一种有着严格定义的技术。

离开了具体的上下文的话,那就会很像是用一种不确定的技术去解决一个不明了的问题。

在反病毒技术发展的初期,“启发式”刚开始使用的时候,它还是一种完全确定的技术——通过某种可变字节模式来识别病毒的技术,也就是说它是文件处理型技术组件和复杂比较型分析组件构成的一种系统。而现在“启发式”的含义已经变得更为广泛,成了“搜索未知恶意程序”的技术。换句话说,说到“启发式检测”,厂商就会暗示它是一种防御系统,这种系统的分析组件会进行模糊搜索来寻找解决办法(可能是用“复杂分析”或“专家系统”的分析组件)。用启发式的话,反病毒技术的基础——即为后续分析搜集信息的方法——可以任意,从文件处理到事件或操作系统状态的处理都可以使用。

“行为检测”、“主动检测”这类的名称也没什么确定的定义。他们包含的技术很广泛——从启发式到系统事件监控。

反病毒技术描述中经常会用到HIPS这个词,但不总是能用得恰当。尽管这个缩写词(Host Intrusion Prevention System)并没有反映出技术的本质,但在反病毒方面它的含义是明确的:HIPS是一种基于系统事件监控的防御技术。它可以搭配任意的分析组件——从对单一的可疑事件的处理到对一系列的程序行为的复杂分析。这样,在反病毒软件的描述中,用HIPS就可以掩盖一些事实。比如它只保护了几个关键的注册表项,还是在访问某个目录时会进行提示,还是会对程序行为进行更复杂的分析,还是使用了基于系统事件监控的其它技术。

恶意代码检测技术的优缺点

如果我们不是单一的看某一种恶意程序防御技术,而是从整体上来进行研究的话,从本文模型的观点看,有以下方面。

技术组件有以下属性:对系统资源的利用(其结果就是程序运行的快慢)、安全和防护。

“系统资源”就是在为系统提供连续或周期性保护并保证系统快速运行的同时所使用的处理器时间片和内存。模拟技术运行起来很慢,无论它是如何实现的:每一条被模拟的指令都会在人工环境中被分成几条指令。虚拟化技术也是一样。系统事件监控也一样会拖慢系统,但其程度则依赖于实现。文件检测和系统异常搜索就完全依赖于实现了。

“安全”反映了恶意程序识别过程中操作系统和用户数据的危险程度。恶意代码在操作系统中执行后,这种危险总是存在的。系统事件监控技术要等恶意程序运行起来后才能检测得到,而模拟技术和文件扫描技术在恶意代码执行前就可以检测到。

“防护”这一项反映了技术的脆弱性,即恶意代码能在多大程度上干扰识别过程。要对抗文件检测是很简单的:文件加壳就不错,或者使用多态,或者用rootkit技术隐藏文件。对抗模拟技术就要困难一些了,但也是可以的——可以在恶意程序的代码中嵌入虚拟机检测处理的代码。但要在系统监控下隐藏就很困难了——因为要隐藏行为是不太可能的。

结论:一般说来,防御技术的抽象层次越低,它的安全性就越好,但越容易被绕过。

分析组件有以下属性:主动性(是否依赖于反病毒软件的更新频率)、误报率和用户参与程度。

主动性反映的是对专家们尚未拿到的新未知恶意程序的检测能力。举个例子,像特征码检测这类最简单的分析类型技术(“简单比较”)的主动性就最差:用这种技术只能检测到已知的恶意程序。随着分析系统复杂度的提高,它的主动性也随之增强。和主动性直接相关的还有一个属性,那就是更新的频率。例如,病毒库就需要频繁地更新,更复杂的启发式系统保持有效状态的时限就要长一些,而专家分析系统则可以做到数月不更新都能很好地工作。

误报率和分析技术的复杂度也是有着直接的关系的。用定死的特征码或行为序列来识别恶意代码,如果特征(字节码、行为特征或其它)能足够长,那么就能唯一地确定恶意程序。特征码可以识别某一种确定的恶意程序,而不能识别出其它的。若识别算法试图识别出更多的恶意程序的话,那么它也会变得更不确定,结果会误报更多的非恶意程序。

用户参与度反映了需要用户参与制定防御策略和协助做出判定的程度。防御策略就是例外、白名单的规则,而协助判定就是对分析系统给出的可疑行为进行确认或否定。用户参与度依赖于实现,而且一般来说,离原始的字节比较技术越远的分析技术,其误报的可能性就越大。当然,误报可以修正,而这就需要用户参与了。

结论:分析系统越复杂,功能就越强大,误报的可能性也越高。误报需要与用户互动进行解决。

如果用这种模型来研究某种技术的话,就很容易从理论上评价它的优缺点。例如,带有复杂分析系统的虚拟机。这种系统非常安全(因为不会启动被检查的程序),但是会因为恶意程序使用了反虚拟机技术或是虚拟机本身实现上的缺陷而漏掉某些恶意程序。这种技术有着巨大的潜力,精心实现后会识别出大多数的恶意程序,但速度慢是一个不可避免的问题。

如何选择非特征码防御系统?

目前,在计算机安全领域里的解决方案大多都是以上某些技术的复合体。在经典的反病毒软件中,特征码检测通常都会和各式各样的系统事件监控、虚拟机、沙箱一同使用。如何面对自身实际情况选择恶意代码防御系统,最大程度地满足具体用户的需求呢?

首先要明白,万能的、“最好的”解决方案是不存在的。每一种技术都有自己的优缺点。例如,系统事件监控会长期占用处理器时间,但不易被绕过;用某些特殊指令就可以混过虚拟机的检查,但在用虚拟机检测恶意代码时,可以先发制人,使系统不受影响。另一个例子:行为规则越简单,用户参与度就越高,这样就会给用户提出一大堆问题,而复杂且“安静”的规则又会有很多误报。

对技术的选择就是对具体需求和环境的权衡。比如,在脆弱条件下(没打补丁的系统,允许使用浏览器插件和执行脚本等等)的人,很为自己系统的安全担心,同时他又有足够的资源,那他就适合用带有强大分析组件的“沙箱”类的系统。这种系统能提供最大的安全性,但目前实现这种系统的程序需要占用大量的内存和处理器时间,这就会拖慢操作系统。对于既希望能控制关键系统事件同时又想免受恶意代码困扰的专家来说,就可以选用实时监控系统。这种系统运行稳定,又不会拖慢系统,而且要求用户参与制定规则和例外情况。而系统资源有限,不想自己的机器因总处在监视下而被拖慢,而且想设置简单规则的用户可以选择更简单的启发式技术。总之,对于未知恶意程序检测来说,靠单一的一种技术是不够的,需要从整体入手。复杂的技术可以为简单的技术提供补充。

检测未知代码的非特征码系统可以分为两类。第一类就是独立的HIPS系统,如Prevx或Cyberhawk。第二类就是反病毒软件,它们在提高检测技术有效性的演化中发展到了非特征码技术阶段。两者的优势都很明显:前者的优势就是专注,从而有无限潜力去完善,而后者在对抗恶意程序的各个方面都有着丰富的经验。

在选择反病毒产品的时候建议参考独立评测的结果和可信用户的推荐。

恶意代码检测技术的演化相关推荐

  1. [系统安全] 三十三.恶意代码检测(3)基于机器学习的恶意代码检测技术

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  2. 恶意代码检测技术——签名、启发式、行为式

    随着恶意代码成为信息安全的重要威胁,恶意代码检测技术成为信息安全领域的重要研究方向.目前已经有基于签名.启发式.行为式等几种检测恶意代码的方法,应用最广泛也是最成熟的当属基于签名的检测技术,当前研究的 ...

  3. [系统安全] 四十六.Powershell恶意代码检测系列 (1)Powershell基础入门及管道和变量的用法

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  4. [网络安全提高篇] 一一五.Powershell恶意代码检测 (3)Token关键词自动提取

    "网络安全提高班"新的100篇文章即将开启,包括Web渗透.内网渗透.靶场搭建.CVE复现.攻击溯源.实战及CTF总结,它将更加聚焦,更加深入,也是作者的慢慢成长史.换专业确实挺难 ...

  5. 深度学习在恶意代码检测方面的应用简单调研

    随着互联网的繁荣,现阶段的恶意代码也呈现出快速发展的趋势,主要表现为变种数量多.传播速度快.影响范围广.在这样的形势下,传统的恶意代码检测方法已经无法满足人们对恶意代码检测的要求.比如基于签名特征码的 ...

  6. [系统安全] 三十四.恶意代码检测(4)编写代码自动提取IAT表、字符串及时间信息

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  7. 信息安全与技术——(十一)恶意代码检测与防范技术

    文章目录 1.恶意代码(Malicious Code) 2.恶意代码对系统带来的影响 3.典型病毒 3.1蠕虫病毒 3.2熊猫烧香病毒 3.3木马病毒 3.4DDoS攻击木马 3.5邮箱病毒 4.恶意 ...

  8. [系统安全] 三十一.恶意代码检测(1)恶意代码攻击溯源及恶意样本分析

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  9. 信息安全工程师笔记-恶意代码防范技术原理

    恶意代码定义 违背目标系统安全策略的程序代码,会造成目标系统信息泄漏.资源滥用,破坏系统的完整性及可用性: 它能够经过存储介质或网络进行传播,从一台计算机系统传到另外一台计算机系统,未经授权认证访问或 ...

最新文章

  1. 自己动手写C语言编译器(2)
  2. OAF_开发系列11_实现OAF通过DataBoundValues动态显示表列的左右对齐
  3. UA SIE545 优化理论基础1 例题2 Farkas定理与相关结论
  4. AI公开课:19.04.10颜水成—360副总裁《人工智能:观察与实践》课堂笔记以及个人感悟—191017再次更新
  5. VTK:Snippets之RestoreSceneFromFile
  6. snippet,让你编码效率翻倍
  7. 数据结构五——二叉树
  8. Python笔记-PyCharm远程连接到Linux进行代码同步并运行
  9. 深入理解es module
  10. 简单而常用的shell 命令
  11. 初步猜测,当map所在线程跟显存有关时,容易崩溃
  12. python循环抓取图片_【Python系列】第2篇:批量下载图片
  13. win7安装中文语言包
  14. 通过网页获取图片操作步骤
  15. 北邮“一号邮路”上的数学体验
  16. 视频主观质量评价方法总结
  17. 计算机等级考试四级网络工程师真题,计算机等级考试四级网络工程师试题
  18. 大学往事 第五章 计算机班的女生
  19. EKMA 曲线及大气 O3 来源解析
  20. Java — 慎用Executors类中newFixedThreadPool()和newCachedThreadPool()

热门文章

  1. [知识竞赛策划方案]作为一个普通的单位,由于不具备电视台专用的比赛平台,如果要搞一场极致专业的知识竞赛?同时花钱最少?
  2. Shopee商品主图和别人一样会不会被扣分?
  3. 基于RSocket的Java与浏览器JS通信
  4. MathType MTEF v.5学习文档
  5. 【Mathtype30天延续】简单快捷
  6. android4.1动态壁纸,动态壁纸大全APP
  7. 第二十课:电感和RL电路
  8. linux命令如何删除子目录文件,Linux如何删除目录下所有文件包括子目录
  9. 计算机大学实践报告范文,大学生计算机教学社会实践报告范文
  10. java入门知识_Java基础知识杂文