TCP Idle Scan (-sI)
1998年,安全研究员Antirez(曾参与编辑nmap中有关hping2工具的相关文章)在Bugtraq邮件列表中发布了一篇关于新的端口扫描技术的文章。Idle
Scan,也就慢慢的为众人所了解,它允许进行完全盲目的端口扫描。事实上,攻击者可以不用向目标发送数据包就完成扫描工作!相反,用猥琐的边信道攻击是能够让扫描映射到一个Zombie主机上的。除了极其隐蔽的情况,这种扫描方式允许挖掘机器之间基于IP的信任关系。

虽然idle 扫描方式比其他方式复杂许多,但是你不必对TCP/IP理解得像专家一样。孩纸你只需要知道这些就够了:

1.确认TCP端口已经打开,并且向这个端口发送一个SYN(建立了会话)包。如果端口是开放的,目标机器会返回一个SYN/ACK包响应。如果端口没开放,那我们只有另辟蹊径咯。这是前面讨论的SYN扫描的基础哟~

2.机器接受一个未经请求的SYN/ACK包会返回RST,一个未经请求的RST会被忽略。

3.任何数据包在互联网上都有一个片段标识号(IP ID),当数据包发送的时候,许多操作系统只是简单的增加了数字,未做其他处理。所以攻击者只需要探究IPID就可以知道最终发送了多少个包。

结合以上特征,就可以伪造身份去扫描目标网络,所以看起来就像是无辜的Zombie主机在扫描。

Idle Scan Step by Step

从本质上来看,Idle Scan只需要重复3个步骤就ok了。

1.探查Zombie的IP ID并记录下来。

2.在Zombie主机上伪造一个包,然后把包发送给目标主机端口。根据端口的状态,目标主机可能会也有可能不会导致Zombie主机IPID值增加。

3.再探查Zombie主机的IP ID。比较两次得到IPID值

经过这样一个流程,Zombie主机的IPID应该会增加1~2。如果只是增加了1,那么就可以说明Zombie主机还没有发出任何包,当然,响应攻击者的探查请求除外。没有发送包也就意味着目标端口没有被打开(也可能是目标主机向Zombie主机发送了一个RST包,导致请求被忽略,或者是根本就是什么都没有做)。增加的如果是2,那就表明Zombie主机成功在两个探测器之间发送了包。这种情况一般情况都意味着目标端口是开着的(目标大概会向Zombie主机发送一个SYN/ACK包去响应攻击者伪造的SYN,从Zombie主机诱导RST包)。如果是增加了一个比2还大的数字,那么就说明Zombie主机太糟糕了!它可能不能胜任预测IPID数值,也可能是正在忙于其他与Idle Scan无关的事情。

虽然关闭了端口和被过滤的端口会发生的事情稍微有点点不同,但是攻击者处理的方法都一样,IPID都只是增加1。所以,在Idel Scan中无法区别端口到底是关闭的还是已经过滤了。当Nmap记录的IPID增加了1,也就被标记成了close丨filterred。

对于那些想知道更多细节的朋友,以下三张图大略可以说明端口被打开,关闭,过滤的情况。

the attacker, the zombie, and the target.

端口开放

端口关闭

端口被过滤

Idel Scan根本上来讲就是一个隐性扫描,Nmap提供了decoy scanning (-D),帮助使用者保护自己的身份。如果不是使用的(类似Idel Scan扫描方式)仍然需要攻击者通过自身真实IP向目标发送数据包以获取扫描结果。Idel Scan扫描结果其中之一就有入侵检测系统通常会发送一个Zombie主机已经开始扫描的通知。所以它可以作为一个框架去扫描另外一个目标,当你查阅入侵检测系统(IDS)时,请记住这种可能性。

Idel Scan的一个独特优势便是,它可以绕开某些过滤防火墙和路由器。IP源地址过滤,是一种常见的(虽然很弱)用于限制机器连接到敏感主机或者说网络上的安全机制。举个例子,一个公司数据库服务器,只允许公共网络连接。或者,家庭用户只允许SSH连接到工作机上面。

一个令人恐惧的场景,当公司高管需要网管打开一个防火墙突破口,让他可以在家中访问内部网络资源,当哪些高管无意或者是不会使用安全的VPN进行替代的时候就会发生这种情况。

Idel Scanning有时也可以被用来映射信任关系,关键在于Idel Scan最终会从Zombie主机获取开放端口列表。一个正常的扫描对于上述数据库服务器可能会显示没有端口开放,但是当将Zombie主机作为Web Sever的IP,使用Idel Scan就可能将数据库相关开放端口暴露出来。

映射出的这些信任关系就可能作为攻击者优先考虑的目标,上面所讨论的方式手法很猥琐哇!

Idel Scan有一个缺点就是它比其他一些扫描方式所花费的时间更长。尽管在《Idel Scan算法实现》章节中有对Idel Scan的优化算法,一个只需要15秒就可以完成的SYN,Idel Scan或许需要15分钟才能够完成。另一个问题就是你必须能够发送欺骗包,伪装成好像他们来自Zombie主机一般,让他们到达目标主机。许多ISP服务商(特别是拨号和住宅宽带供应商)目前执行出口过滤来防止这类数据包欺骗。高端供应商(比如说主机托管,T1-Services)就不太可能这么做。如果实际存在这个过滤,Nmap会在你尝试的每一个Zombie主机上显示一个快速错误消息。如果不能够更换ISP服务商,那么最好尝试在让ISP服务商给你更换一个IP。有时候这个过滤仅仅只是阻止了客户使用范围之外的欺骗IP地址。Idel Scan另外一个挑战就是你必须寻找一个正在工作的Zombie主机,这点我们会在下面小节中详细叙述。

Finding a Working Idle Scan Zombie Host

执行IP ID Idel Scan的第一个步骤就是寻找一个合适的Zombie主机。它需要在总体基础上分配IP ID增量数据包(而不是与它通信)。它应该是空闲的,作为无关流量将会提升它的的IP ID序列,导致扫描逻辑混乱。在攻击者与Zombie主机之间,Zombie主机与目标主机的延迟越小,扫描的速度就越快。

当试图尝试Idel Scan时,Nmap就会测试Zombie主机,并报告相关问题。如果其中一个不工作,就会自动尝试下一个。网络很大,有足够多的Zombie主机够我们来挑选,想找到一个合适的Zombie主机并不是很难。

一个常见的方法就是在Nmap下执行Ping扫描一些网络。你可以选择Nmap提供的随机IP选项(-iR),但是这很有可能造成与Zombie主机之间的大量延迟。选择一个离你源地址近的网络,或者选择一个离目标近的网络,取得的结果会好一些。你可以尝试Idel Scan使用每一个通过Ping扫描存活的有效主机,直到你找到你满意的那一个。通常,最好是在使用别人机器做一些比较隐蔽的事情,比如说看黄片,比如说进行Idel Scan之前得到别人许可。

在Zombie主机候选列表中执行一个端口扫描以及操作系统识别(-o)比简单的使用Ping命令筛选更容易找寻到合适的。只要启动了详细模式(-v),操作系统检测通常会确定IP ID增长方法,然后返回“IP ID Sequence Generation: Incremental”。如果这个类型被作为增长或是破损的低字节序增长量,那么这台机器绝逼是很好的Zombie主机。但还是无法保证他可以进行工作,在Solaris以及其他系统中,需要创建一个新的IP ID序列为每台主机构建通信连接。主机也可能是太忙了。操作系统检测,打开的端口列表可以帮助Idel去识别。

另一种识别Zombie主机的方法,在一个主机上运行ipidseq NSE脚本。这个脚本会探索主机上的IP ID生成方式并进行归类,然后就像是系统检测一样返回IP ID分类信息。像大多数NSE脚本,ipidseq.nse可以同时在多台主机上运行,这在扫描整个网络寻找合适主机的时候是个不错的选择。

当确定了一个Zombie主机后还需要进行一些初始化操作。

Executing an Idle Scan

一旦找到合适的Zombie主机,执行扫描就成为了一件十分简单的事情了。简单的指定Zombie主机名指向 -sI选项,并停止Nmap。Example 5.1 展示了一个对名为Kiosk的Adobe主机进行的Idel Scan。

Example 5.1. An idle scan against the RIAA

# nmap -Pn -p- -sI kiosk.adobe.com www.riaa.comStarting Nmap ( http://nmap.org )
Idlescan using zombie kiosk.adobe.com (192.150.13.111:80); Class: Incremental
Nmap scan report for 208.225.90.120
(The 65522 ports scanned but not shown below are in state: closed)Port       State       Service
21/tcp     open        ftp
25/tcp     open        smtp
80/tcp     open        http
111/tcp    open        sunrpc
135/tcp    open        loc-srv
443/tcp    open        https
1027/tcp   open        IIS
1030/tcp   open        iad1
2306/tcp   open        unknown
5631/tcp   open        pcanywheredata
7937/tcp   open        unknown
7938/tcp   open        unknown
36890/tcp  open        unknownNmap done: 1 IP address (1 host up) scanned in 2594.47 seconds

从上面的扫描中,我们可以知道RIAA的安全意识还不够(亮点自寻),显然他们没有安装防火墙,不太可能拥有系统入侵检测系统(IDS)。如果真是这样子,那么kiosk.adobe.com就成了这次扫描的罪魁祸首。-Ph选项阻止Nmap向RIAA机器发送初始Ping数据。这样就暴露出了真实地址。由于-p-指定扫描所有64K端口,会持续很长一段时间。

默认设置,Nmap从Zombie主机80端口伪造探测目标主机。你可以选择一个不同的端口,在Zombie主机后面添加上冒号,然后跟上端口号(e.g. –sI kiosk.adobe.com:91)。这个端口不能是被攻击者和目标过滤了的端口。在Zombie主机上一个SYN扫描,会返回该端口的是否打开的信息。

Idle Scan Implementation Algorithms

the section called “Idle Scan Step by Step”描述的是Idel Scan的基础水平。在Nmap上实现却是有些复杂,最关键的差异在于Nmap能够同时执行,而且误报少。

Parallelizing idle scan由于是间接推导出端口所以,他比其他扫描方式要更加的猥琐。如果Nmap探测目标主机上的多个端口,然后检测Zombie主机上新的IP ID值,IP ID的值增加了多少就显示出目标开放了多少个端口。实际上这并不是一个和严重的问题,绝大多数端口在大型扫描结果中基本上都是被关闭或者被过滤。由于只有开放端口才可以让IP ID值增加,Nmap会认为没有增加量,然后整个组的端口就被标记成了关闭或者被过滤。Nmap可以并行扫描一百组端口。如果Nmap在探测一组端口的时候Zombie主机IP ID同时也增加了,就说明在这一组端口中一定有开放的端口。Nmap继而使用二进制搜索发现开放的端口。它将数据组分成两份,分别发送探测信息,如果一个数据组显示没有开放端口,那么这一数据组的端口都将被标记为被关闭或者被过滤。如果一个数据组显示有开放端口,那么在把这个数据组分成两份,重复以上步骤,直到最终将开放端口都找出来。虽然这种方式更复杂,但是这种方式可以节约扫描时间。

可靠性是Idel Scan的另一个问题。如果Zombie主机在扫描时向任何不相干的机器发送数据包,其IP ID会增加。这就会让Nmap误以为已经寻找到开放的端口了。幸运的是,并行扫描在这里也是有很大作用的。如果Nmap在一个组中扫描100个端口,那么IP ID就会增加标识两个开放端口,Nmap将这组数据分成50端口一个小组。当Nmap同时在两个小组中进行IP ID扫描时,Zombie主机IP ID总的增加量就在加了一次。另外,Nmap如果探测到不一致,那么它会重新探测。基于检测可靠的Zombie主机,Nmap还会修改组大小以及扫描时间。如果Nmap发现有大量不一致的结果,它将退出,并提示用户选择更好的Zombie主机。

扫描实例:

有时候,对一个数据包的追踪就可以十分直观的理解这类复杂的算法以及技术。这部分剩下的内容提供了一个真实,7端口Idel Scan且带有注释的数据包追踪。其中IP地址修改为Attacker,Zombie,Target,为了简洁,一些无关紧要的东西已经清除。

Attacker# nmap -sI Zombie -Pn -p20-25,110 -r --packet-trace -v
Target
Starting Nmap ( http://nmap.org )

-Ph对于隐匿时非常重要的,此外ping包将从攻击者IP发送到目标。操作系统版本扫描也将会暴露真实地址,所以-sV没有被指定,-r选项(关闭端口随机),只是为了使这个案例更加容易执行。

Nmap首先通过发送6个SYN/ACK包到Zombie主机,测试的IP ID序列生成,然后分析Zombie主机返回的响应信息。这将帮助Nmap将不符合我们要求的Zombie主机踢出去。这一步也是必要的,因为某些系统(通常是Microsoft Windows机器)IP ID为每一个数据包增加256,而不是增加1。这将发生在低字节序机器上,因为机器可能没有将IP ID转换成网络字节顺序(高字节序)。Nmap会根据初始化探测,去解决这一问题。

SENT (0.0060s) TCP Attacker:51824 > Zombie:80 SA id=35996
SENT (0.0900s) TCP Attacker:51825 > Zombie:80 SA id=25914
SENT (0.1800s) TCP Attacker:51826 > Zombie:80 SA id=39591
RCVD (0.1550s) TCP Zombie:80 > Attacker:51824 R id=15669
SENT (0.2700s) TCP Attacker:51827 > Zombie:80 SA id=43604
RCVD (0.2380s) TCP Zombie:80 > Attacker:51825 R id=15670
SENT (0.3600s) TCP Attacker:51828 > Zombie:80 SA id=34186
RCVD (0.3280s) TCP Zombie:80 > Attacker:51826 R id=15671
SENT (0.4510s) TCP Attacker:51829 > Zombie:80 SA id=27949
RCVD (0.4190s) TCP Zombie:80 > Attacker:51827 R id=15672
RCVD (0.5090s) TCP Zombie:80 > Attacker:51828 R id=15673
RCVD (0.5990s) TCP Zombie:80 > Attacker:51829 R id=15674
Idlescan using zombie Zombie (Zombie:80);
Class: Incremental

这个测试显示Zombie主机运行正常。每一个IP ID都是在前一个的基础上增加1。似乎这个系统很容易通过Idel 进行攻击。获得的这些结果,在接下来测试中会有用到。如果发现有目标数据的到来,Nmap就会发送4个数据包到Zombie主机上进行欺骗,然后探测Zombie主机,确认IP ID是否增长。如果没有增长,那么很有可能就是攻击者的ISP提供商阻止了欺骗包的发送或者就是Zombie主机单独使用了一个IP ID计数器与其他机器通信。这两种情况都比较常见,所以Nmap总是会执行这个测试,从上面我们可以知道,Zombie主机IP ID最后为15674。

SENT (0.5990s) TCP Target:51823 > Zombie:80 SA id=1390
SENT (0.6510s) TCP Target:51823 > Zombie:80 SA id=24025
SENT (0.7110s) TCP Target:51823 > Zombie:80 SA id=15046
SENT (0.7710s) TCP Target:51823 > Zombie:80 SA id=48658
SENT (1.0800s) TCP Attacker:51987 > Zombie:80 SA id=27659
RCVD (1.2290s) TCP Zombie:80 > Attacker:51987 R id=15679

这四个欺骗数据包成对的从Attacker探测,导致Zombie主机的IP ID从15674增长到15679。Perfect!真正的扫描现在才开始,记住15679才是Zombie主机最后的IP ID。

Initiating Idlescan against Target
SENT (1.2290s) TCP Zombie:80 > Target:20 S id=13200
SENT (1.2290s) TCP Zombie:80 > Target:21 S id=3737
SENT (1.2290s) TCP Zombie:80 > Target:22 S id=65290
SENT (1.2290s) TCP Zombie:80 > Target:23 S id=10516
SENT (1.4610s) TCP Attacker:52050 > Zombie:80 SA id=33202
RCVD (1.6090s) TCP Zombie:80 > Attacker:52050 R id=15680

Nmap探测到20~23端口,然后探测Zombie主机,获取到IP ID为15680,仅仅比之前得到的数值增加了1。两个已知的数据包没有导致IP ID增加。说明20~23端口可能被关闭或者被过滤了。也有可能是从目标端口返回的SYN/ACK信息还没有到达。这种情况下,Zombie也就没有进行RST响应,IP ID也就没有增加。为了确保准确性,Nmap会在过一会再次测试这些端口。

SENT (1.8510s) TCP Attacker:51986 > Zombie:80 SA id=49278
RCVD (1.9990s) TCP Zombie:80 > Attacker:51986 R id=15681

Nmap会在上一次探测4/10秒过后再次进行探测。Zombie主机(不是 truly Idel)在这个探测过程中可以保持与其他主机的通信,当然只能是还没进行探测的主机,不然会导致错误发生的。幸运的是,这并没有发生:不出所料的话下一个IP ID就是15681

SENT (2.0000s) TCP Zombie:80 > Target:24 S id=23928
SENT (2.0000s) TCP Zombie:80 > Target:25 S id=50425
SENT (2.0000s) TCP Zombie:80 > Target:110 S id=14207
SENT (2.2300s) TCP Attacker:52026 > Zombie:80 SA id=26941
RCVD (2.3800s) TCP Zombie:80 > Attacker:52026 R id=15684

Nmap探测24,25,110端口然后查询Zombie主机的IP ID。IP ID从15681增长到15684,跳过了15682~15683.说明在这三个端口中有两个端口是开放的。Nmap不能直接告诉我们到底是哪两个端口是开放的,当然这个信息也有可能是错误的。所以Nmap会进一步深入探测,分成小组进行扫描。

SENT (2.6210s) TCP Attacker:51867 > Zombie:80 SA id=18869
RCVD (2.7690s) TCP Zombie:80 > Attacker:51867 R id=15685
SENT (2.7690s) TCP Zombie:80 > Target:24 S id=30023
SENT (2.7690s) TCP Zombie:80 > Target:25 S id=47253
SENT (3.0000s) TCP Attacker:51979 > Zombie:80 SA id=12077
RCVD (3.1480s) TCP Zombie:80 > Attacker:51979 R id=15687

24,25两个端口定位第一小组,IP ID从15685跳到15687,显然这两个端口中有一个端口是开放的。Nmap再进行一次分组,然后重复上面过程,分别对两个端口进行测试。

SENT (3.3910s) TCP Attacker:51826 > Zombie:80 SA id=32515
RCVD (3.5390s) TCP Zombie:80 > Attacker:51826 R id=15688
SENT (3.5390s) TCP Zombie:80 > Target:24 S id=47868
SENT (3.7710s) TCP Attacker:52012 > Zombie:80 SA id=14042
RCVD (3.9190s) TCP Zombie:80 > Attacker:52012 R id=15689

24端口,IP ID没有跳,所以这个端口没有开放。到目前为止,我们可以从返回的结果得知:

20~23端口不是被关闭就是被过滤了。

24,25,110中有两个端口是开放的。

24,25中有一个端口是开放的。

24端口不是被关闭就是被过滤了。

25端口,110端口是开放的,另外5个端口不是关闭就被过滤了。保持这个逻辑,Nmap可以停止扫描并且将最终扫描结果保存下来。以前就这么做,但是如果Zombie主机不是turly idel就会产生大量的不准确信息。所以,Nmap会继续进行扫描以保证结果的准确性。

SENT (4.1600s) TCP Attacker:51858 > Zombie:80 SA id=6225
RCVD (4.3080s) TCP Zombie:80 > Attacker:51858 R id=15690
SENT (4.3080s) TCP Zombie:80 > Target:25 S id=35713
SENT (4.5410s) TCP Attacker:51856 > Zombie:80 SA id=28118
RCVD (4.6890s) TCP Zombie:80 > Attacker:51856 R id=15692
Discovered open port 25/tcp on Target
SENT (4.6900s) TCP Zombie:80 > Target:110 S id=9943
SENT (4.9210s) TCP Attacker:51836 > Zombie:80 SA id=62254
RCVD (5.0690s) TCP Zombie:80 > Attacker:51836 R id=15694
Discovered open port 110/tcp on Target

正如我们先前推导的结果,25,110端口是开放的。

SENT (5.0690s) TCP Zombie:80 > Target:20 S id=8168
SENT (5.0690s) TCP Zombie:80 > Target:21 S id=36717
SENT (5.0690s) TCP Zombie:80 > Target:22 S id=4063
SENT (5.0690s) TCP Zombie:80 > Target:23 S id=54771
SENT (5.3200s) TCP Attacker:51962 > Zombie:80 SA id=38763
RCVD (5.4690s) TCP Zombie:80 > Attacker:51962 R id=15695
SENT (5.7910s) TCP Attacker:51887 > Zombie:80 SA id=61034
RCVD (5.9390s) TCP Zombie:80 > Attacker:51887 R id=15696

可以肯定的是,Nmap对20~23端口也重新尝试了一次。查询Zombie主机IP ID并没有增加。为了更加说明这个测试的准确性,我们就假设从Attacker主机到Zombie主机的SYN/ACK数据还没有到达,Nmap再次查询IP ID,这次查询依旧显示没有任何端口开放。现在Nmap就可以非常自信的将结果保存下来了。

The Idlescan took 5 seconds to scan 7 ports.
Nmap scan report for TargetPORT    STATE           SERVICE
20/tcp  closed|filtered ftp-data
21/tcp  closed|filtered ftp
22/tcp  closed|filtered ssh
23/tcp  closed|filtered telnet
24/tcp  closed|filtered priv-mail
25/tcp  open            smtp
110/tcp open            pop3Nmap finished: 1 IP address (1 host up) scanned in 5.949 seconds

更加完整的有关Nmap Idel Scan的详细细节,可以看看Nmap源码中的idle_scan.cc

Nmap端口扫描指南之Idle Scan相关推荐

  1. “诸神之眼”——Nmap端口扫描工具使用小手册

    "诸神之眼"--Nmap端口扫描工具使用小手册 1.Nmap介绍 1.1.Nmap简介 Nmap ("Network Mapper(网络映射器)") 是一款开放 ...

  2. 【Python脚本进阶】2.1、端口扫描器(下):NMAP端口扫描

    目录 一.简介 1.1.扩展 1.2.端口扫描类型 1.3.实现: 一.简介 1.1.扩展 由TCP连接扫描脚本,到其他类型的扫描,Nmap端口扫描工具包提供了大量的功能,如提供的ACK.RST.FI ...

  3. nmap端口扫描参数设置

    nmap端口扫描参数设置 nmap -sS -Pn -p 80 -n --open --min-hostgroup 1024 --min-parallelism 10 --host-timeout 3 ...

  4. Python编程--使用NMAP端口扫描

    Python编程–使用NMAP端口扫描 安装好Python-Namp模块,(pip install python-nmap).创建一个PortScanner()类对象,这使我们能用这个对象完成扫描操作 ...

  5. 关于nmap端口扫描与阻止恶意端口扫描的实验

    准备环境 Nmap Nmap用于允许系统管理员查看一个大的网络系统有哪些主机,以及其上运行何种服务.它支持多种协议的扫描,如UDP.TCP connect().TCP SYN(half open).f ...

  6. 网络安全——Nmap端口扫描

    网络安全--Nmap端口扫描 目录 一.实验目的要求 二.实验设备与环境 三.实验原理 四.实验步骤 五.实验现象.结果记录及整理. 六.分析讨论与思考题解答 一.实验目的要求: 1.了解网络端口扫描 ...

  7. Nmap端口扫描的几种状态介绍

    Nmap端口扫描的几种状态介绍 1.Nmap Nmap 是一种用来发现网络中主机和服务器的安全扫描工具,从而能够产生一个网络"地图",为了完成这个功能,Nmap会向每个目标主机发送 ...

  8. nmap 端口扫描王,查看端口是否可访问,是否对外开放

    NMap,也就是Network Mapper,最早是Linux下的网络扫描和嗅探工具包. 1 安装 apt-get install nmap 2 使用,查看ip下所有对外的端口 $ sudo nmap ...

  9. 【每天学习一点新知识】nmap端口扫描

    nmap所识别的6个端口状态 open(开放的) 应用程序正在该端口接收TCP 连接或者UDP报文.发现这一点常常是端口扫描 的主要目标.安全意识强的人们知道每个开放的端口 都是攻击的入口.攻击者或者 ...

最新文章

  1. 里约奥运会开幕了,一起观看“VR直播”约么?
  2. java环境变量(win10 java8)
  3. Android之MediaPlayer播放音乐并实现进度条实例
  4. 设计模式系列6:适配器模式(Adapter Pattern)
  5. MySQL left()函数
  6. 蓝桥杯 ADV-141 算法提高 判断名次
  7. 一只青蛙跳向三个台阶_9. 变态跳台阶
  8. php用win还是linux系统,做网站选择linux系统还是选择windows系统好?
  9. 一致性哈希算法 mysql_一致性哈希算法,在分布式开发中你必须会写,来看完整代码...
  10. iOS:下载/创建证书
  11. 基于Javafx制作的随机抽签软件
  12. 终面(HR面)_职业竞争力和职业规划
  13. Coprime AtCoder Beginner Contest 215
  14. Yii2 使用四 使用Gii生成代码
  15. eclipse 调整html编辑器
  16. 《Dive into Windbg系列》Explorer无法启动排查
  17. 分享30个高品质的抽象网页背景素材
  18. 小程序实战篇(一)——车辆使用登记
  19. web管理员登录页面
  20. PADS VX2.8 测量工具的使用方法

热门文章

  1. Css计算--calc()方法
  2. leetcode 16.最接近的三数之和
  3. 搞笑但又真实无比! 59条和程序员相关的名人语录,哪一条让你感同身受?
  4. sql查看数据库查看表
  5. 伤害世界怎么自建服务器,伤害世界(Hurtworld)最便捷开服架设服务器攻略 伤害世界怎么开私服...
  6. 地球上最伟大的奇迹:维生素C与晚期癌症治疗
  7. oracle截取4000字节,Oracle 插入超4000字节的CLOB字段的处理方法
  8. 汉字读半边,怎么会错上天?
  9. caused by java.io.io_springboot运行出错,Caused by: java.io.IOException
  10. HFCTF2022 Web ezphp