这是我们的第二期NMAP备忘单(第一期在此)。基本上,我们将讨论一些高级NMAP扫描的技术,我们将进行一个中间人攻击(MITM)。现在,游戏开始了。

TCP SYN扫描

SYN扫描是默认的且最流行的扫描选项是有一定原因的。它可以在不受防火墙限制的高速网络每秒扫描数千个端口 。同时也是相对不显眼的和隐蔽的,因为它永远不会完成TCP连接。

命令:NMAP -sS 目标

TCP连接扫描

当SYN扫描不可用的时候,TCP连接扫描是默认的TCP扫描类型。这是在用户不具有发送RAW数据包的特权的情况下。不是像大多数其他扫描器那样写原始数据包,NMAP要求底层的操作系统通过发出连接系统调用来建立与目标机和端口的连接。

命令:NMAP -sT 目标

UDP扫描

虽然互联网上最流行的服务运行在TCP协议,但UDP服务也是广泛部署的。DNS,SNMP和DHCP(注册端口53,161/162,和67/68)这三种最常见的UDP服务。因为UDP扫描通常比TCP慢和更加困难,一些安全审计员忽略这些端口。这是一个错误,因为UDP服务是相当普遍,攻击者也不会忽略整个协议。

命令:NMAP -sU 目标

选项-data-length可以用来固定长度的随机有效载荷发送到每一个端口或(如果指定0值)来禁用有效载荷。如果返回一个ICMP端口不可达错误(类型3,代码3),那么端口是关闭的。其他ICMP不可达错误(类型3,编码1,2,9,10或13)标记端口过滤。有时服务会返回一个UDP包响应以证明它是开放的。如果重发后没有收到回应,端口被列为开放或者过滤。

命令:NMAP -sU–data-length=value 目标

SCTP INIT扫描

SCTP是对TCP和UDP协议的相对较新的替代方案,结合TCP和UDP最具特色的部分,同时也增加了新的功能,如多宿主和多流。它主要被用于SS7 / SIGTRAN相关的服务,但有可能被用于其他用途。 SCTP INIT扫描SCTP相当于TCP SYN扫描。它可以在不受防火墙限制的高速网络每秒扫描数千个端口。像SYN扫描,扫描INIT相对不显眼的和隐蔽的,因为它永远不会完成SCTP连接。

命令:NMAP -sY 目标

TCP NULL、FIN和Xmas扫描

· NULL扫描(-sN)

不设置任何位(TCP标志标头是0)。

· FIN扫描(-sF)

设置只是TCP FIN位。

· Xmas扫描(-sX)

设置FIN,PSH,URG和标志。

TCP ACK扫描

这种扫描跟其他方式不同的地方是因为它没有判断端口的开放情况。它是用来绘制出防火墙规则,对哪些端口进行了保护。

命令:NMAP -scanflags=value -sA target

该ACK扫描探测报文只具有ACK标志设置(除非您使用-scanflags)。当扫描未经过系统过滤,打开和关闭的端口都将返回一个RST包。 NMAP然后把它们标记为未过滤的,这意味着它们是ACK包可达的。

TCP窗口扫描

窗口扫描跟ACK扫描是几乎一样的,除了它利用某些系统的实现细节来区分端口的,而不是当返回一个RST时总是认为端口未经过滤。

命令:NMAP -sW 目标

TCP Maimon 扫描

Maimon 扫描的名字来源于它的发现者,Uriel Maimon。他在Phrack杂志问题#49(1996年11月)中描述的技术。这种技术与NULL,FIN和Xmas扫描类似,唯一的不同之处在于探针是FIN/ ACK。

命令:NMAP -sM 目标

自定义的TCP扫描使用-scanflag选项

对于渗透测试,一个渗透测试人员不会使用一般的TCP扫描比如ACK、FIN等,因为这些东西可以被IDS / IPS阻断。因此他们将通过指定“-scanflag”选项使用一些不同的技术。这也可以用于绕过防火墙。

该-scanflags的参数可以是一个数字标记值如9(PSH和FIN),但使用符号名称更容易。只是URG,ACK,PSH,RST,SYN和FIN的任意组合。例如,-scanflags URGACKPSHRSTSYNFIN所有设置,虽然扫描时不是非常有用的。

命令:NMAP –scanflags 目标

SCTP COOKIE ECHO扫描

SCTP COOKIE ECHO扫描是一种更先进的SCTP扫描。SCTP会默认丢弃开放端口返回的包含COOKIE ECHO数据包块,但如果端口关闭则发送中止。这种扫描方式优点是,它并不像INIT扫描一样明显。除此之外,无状态防火墙会阻断INIT块而不是COOKIE ECHO块。但一个优秀的IDS仍能够探测到SCTP COOKIE ECHO扫描SCTP COOKIE ECHO扫描的缺点是无法区分开放和过滤的端口。

命令:NMAP -sZ 目标

TCP空闲扫描

这种先进的扫描方法允许对目标进行一个真正的盲目TCP端口扫描(即没有数据包从你的真实IP地址发送到目标)。相反独特的侧信道攻击利用僵尸主机上可预测的IP分段ID序列生成来收集关于目标的开放端口的信息。IDS系统只会显示扫描是从您指定的僵尸机发起。这在进行MITM(中间人攻击)非常有用的。

命令:NMAP -sI zombie 目标

这里简单介绍下空闲的原理:

1、向僵尸主机发送SYN/ACK数据包,获得带有分片ID(IPID)的RST报文。

2、发送使用僵尸主机IP地址的伪数据包给目标主机。 如果目标主机端口关闭,就会向僵尸主机响应RST报文。如果目标端口开放,目标主机向僵尸主机响应SYN/ACK报文,僵尸主机发现这个非法连接响应,并向目标主机发送RST报文,此时IPID号开始增长。

3、通过向僵尸主机发送另一个SYN/ACK报文以退出上述循环并检查僵尸主机RST报文中的IPID是否每次增长2,同时目标主机的RST每次增长1。 重复上述步骤直到检测完所有的端口。

接下来是进行空闲扫描的步骤:

1、寻找合适的僵尸主机

一个常见的方法就是在NMAP下执行Ping扫描一些网络。你可以选择NMAP提供的随机IP选项(-iR),但是这很有可能造成与Zombie主机之间的大量延迟。

在Zombie主机候选列表中执行一个端口扫描以及操作系统识别(-o)比简单的使用Ping命令筛选更容易找寻到合适的。只要启动了详细模式(-v),操作系统检测通常会确定IP ID增长方法,然后返回“IP ID Sequence Generation: Incremental”。如果这个类型被作为增长或是破损的低字节序增长量,那么该机是不错的僵尸主机备选。

还有一种方法是对运行ipidseq  NSE脚本。该脚本探测一台主机的IP ID生成方法并进行分类,然后就像操作系统检测一样输出IP ID分级。

命令:NMAP --script ipidseq [ --script-args probeport=port] 目标

我们也可以使用hping用于发现僵尸主机。

首先选择使用Hping3发送数据包,并观察ID号是不是逐一增加,那么该主机就是空闲的。如果ID号随意增加,那么主机实际上不是空闲的,或者主机的操作系统没有可预测的IP ID。

hping3 -s 目标

发送伪造SYN包到你指定的目标主机上的端口。

hping3 -spoof 僵尸主机 -S p 22 目标

正如你所看到的,没有任何反应,这表明数据包100%的丢失。这意味着我们并没有发现僵尸主机。同时我们将检查确认以下的步骤。

检查PID值是否逐一增加:

hping3 -S 目标

2、使用NMAP进行攻击

命令: NMAP -Pn -p- -sI 僵尸主机 目标

首先我们用NMAP扫描僵尸主机的端口:

发现僵尸主机22端口是关闭着的。

我们指定利用僵尸主机的22端口进行空闲扫描,结果显而易见,无法攻击目标。

默认情况下,NMAP的伪造探针使用僵尸主机的80端口作为源端口。您可以通过附加一个冒号和端口号僵尸名选择一个不同的端口(例如www.baidu.com:90)。所选择的端口必须不能被攻击者或目标过滤。僵尸主机的SYN扫描会显示端口的开放状态。

这里解释下参数的含义:

-Pn:防止NMAP的发送初始数据包到目标机器。

-p-:将扫描所有65535个端口。

-sI:用于闲置扫描和发送数据包欺骗。

了解NMAP的内部

作为一个渗透测试人员,我们必须明白NMAP空闲扫描的内部运行过程,然后用我们自己的方法来实现同样的事情。为此,我们将使用NMAP的数据包跟踪选项。

命令:NMAP -sI 僵尸主机:113 -Pn -p20-80,110-180 -r - packet-trace -v 目标

-Pn是隐身的必要,否则ping数据包会用攻击者的真实地址发送到目标。未指定-sV选项是因为服务识别也将暴露真实地址。 -r选项(关闭端口随机化)让这个例子运行起来更简单。

正如我之前说的,成功的攻击需要选择一个合适的僵尸主机端口。

这种攻击的过程:

NMAP首先通过发送6个 SYN / ACK数据包并分析响应,测试僵尸主机的IP ID序列生成。在这里R表示复位包,意味该端口不可达。有关详细信息,请在NMAP手册空闲扫描。

所以下面提及的C代码是空闲扫描。编译C代码并运行程序。

这是一个不寻常的扫描代码,可以允许完全的空闲扫描(例如发送到目标的数据包不是来自自己的真实IP地址),并也可用于穿透防火墙和路由器ACL范围。

#include "idle_scan.h"

#include "timing.h"

#include "osscan2.h"

#include "NMAP.h"

#include "NMAPOps.h"

#include "services.h"

#include "Target.h"

#include "utils.h"

#include "output.h"

#include "struct_ip.h"

#include

extern NMAPOps o;

struct idle_proxy_info {   create a constructer and take all variable into it

Target host; /* contains name, IP, source IP, timing info, etc. */

int seqclass; /* IP ID sequence class (IPID_SEQ_* defined in NMAP.h) */

u16 latestid; /* The most recent IP ID we have received from the proxy */

u16 probe_port; /* The port we use for probing IP ID infoz */

u16 max_groupsz; /* We won't test groups larger than this ... */

u16 min_groupsz; /* We won't allow the group size to fall below this

level.  Affected by --min-parallelism */

double current_groupsz; /* Current group size being used ... depends on

conditions ... won't be higher than

max_groupsz */

int senddelay; /* Delay between sending pr0be SYN packets to target

(in microseconds) */

int max_senddelay; /* Maximum time we are allowed to wait between

sending pr0bes (when we send a bunch in a row.

In microseconds. */

pcap_t *pd; /* A Pcap descriptor which (starting in

initialize_idleproxy) listens for TCP packets from

the probe_port of the proxy box */

int rawsd; /* Socket descriptor for sending probe packets to the proxy */

struct eth_nfo eth; // For when we want to send probes via raw IP instead.

struct eth_nfo *ethptr; // points to eth if filled out, otherwise NULL

};

/* Sends an IP ID probe to the proxy machine and returns the IP ID.

This function handles retransmissions, and returns -1 if it fails.

Proxy timing is adjusted, but proxy->latestid is NOT ADJUSTED --

you'll have to do that yourself.   Probes_sent is set to the number

of probe packets sent during execution */

static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,

int *probes_rcvd) {

struct timeval tv_end;

int tries = 0;

int trynum;

int sent=0, rcvd=0;

int maxtries = 3; /* The maximum number of tries before we give up */

struct timeval tv_sent[3], rcvdtime;

int ipid = -1;

int to_usec;

unsigned int bytes;

int base_port;

struct ip *ip;

struct tcp_hdr *tcp;

static u32 seq_base = 0;

static u32 ack = 0;

static int packet_send_count = 0; /* Total # of probes sent by this program -- to ensure that our sequence # always changes */

if (o.magic_port_set)

base_port = o.magic_port;

else base_port = o.magic_port + get_random_u8();

if (seq_base == 0) seq_base = get_random_u32();

if (!ack) ack = get_random_u32();

do {

gettimeofday(&tv_sent[tries], NULL);

/* Time to send the pr0be!*/

send_tcp_raw(proxy->rawsd, proxy->ethptr,

proxy->host.v4sourceip(), proxy->host.v4hostip(),

o.ttl, false,

o.ipoptions, o.ipoptionslen,

base_port + tries, proxy->probe_port,

seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,

(u8 *) "\x02\x04\x05\xb4", 4,

NULL, 0);

sent++;

tries++;

/* Now it is time to wait for the response ... */

to_usec = proxy->host.to.timeout;

gettimeofday(&tv_end, NULL);

while((ipid == -1 || sent > rcvd) && to_usec > 0) {

to_usec = proxy->host.to.timeout - TIMEVAL_SUBTRACT(tv_end, tv_sent[tries-1]);

if (to_usec < 0) to_usec = 0; // Final no-block poll       ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true);

gettimeofday(&tv_end, NULL);

if (ip) {

if (bytes < ( 4 * ip->ip_hl) + 14U)

continue;

if (ip->ip_p == IPPROTO_TCP) {

tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));

if (ntohs(tcp->th_dport) < base_port || ntohs(tcp->th_dport) - base_port >= tries  || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) {

if (ntohs(tcp->th_dport) > o.magic_port && ntohs(tcp->th_dport) < (o.magic_port + 260)) {        if (o.debugging) {  error("Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d",        proxy->host.to.rttvar, (int) (proxy->host.to.rttvar * 1.2));

}

proxy->host.to.rttvar = (int) (proxy->host.to.rttvar * 1.2);

rcvd++;

}

else if (o.debugging > 1) {

error("Received unexpected response packet from %s during IP ID zombie probing:", inet_ntoa(ip->ip_src));

readtcppacket( (unsigned char *) ip,MIN(ntohs(ip->ip_len), bytes));

}

continue;

}

trynum = ntohs(tcp->th_dport) - base_port;

rcvd++;

ipid = ntohs(ip->ip_id);

adjust_timeouts2(&(tv_sent[trynum]), &rcvdtime, &(proxy->host.to));

}

}

}

} while(ipid == -1 && tries < maxtries);   if (probes_sent) *probes_sent = sent;   if (probes_rcvd) *probes_rcvd = rcvd;   return ipid; } /* Returns the number of increments between an early IP ID and a later    one, assuming the given IP ID Sequencing class.  Returns -1 if the    distance cannot be determined */ static int ipid_distance(int seqclass , u16 startid, u16 endid) {   if (seqclass == IPID_SEQ_INCR)     return endid - startid;   if (seqclass == IPID_SEQ_BROKEN_INCR) {     /* Convert to network byte order */     startid = htons(startid);     endid = htons(endid);     return endid - startid;   }   return -1; } static void initialize_proxy_struct(struct idle_proxy_info *proxy) {   proxy->seqclass = proxy->latestid = proxy->probe_port = 0;

proxy->max_groupsz = proxy->min_groupsz = 0;

proxy->current_groupsz = 0;

proxy->senddelay = 0;

proxy->max_senddelay = 0;

proxy->pd = NULL;

proxy->rawsd = -1;

proxy->ethptr = NULL;

}

/* takes a proxy name/IP, resolves it if necessary, tests it for IP ID

suitability, and fills out an idle_proxy_info structure.  If the

proxy is determined to be unsuitable, the function whines and exits

the program */

#define NUM_IPID_PROBES 6

static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,

const struct in_addr *first_target, const struct scan_lists * ports) {

int probes_sent = 0, probes_returned = 0;

int hardtimeout = 9000000; /* Generally don't wait more than 9 secs total */

unsigned int bytes, to_usec;

int timedout = 0;

char *p, *q;

char *endptr = NULL;

int seq_response_num;

int newipid;

int i;

char filter[512]; /* Libpcap filter string */

char name[MAXHOSTNAMELEN + 1];

struct sockaddr_storage ss;

size_t sslen;

u32 sequence_base;

u32 ack = 0;

struct timeval probe_send_times[NUM_IPID_PROBES], tmptv, rcvdtime;

u16 lastipid = 0;

struct ip *ip;

struct tcp_hdr *tcp;

int distance;

int ipids[NUM_IPID_PROBES];

u8 probe_returned[NUM_IPID_PROBES];

struct route_nfo rnfo;

assert(proxy);

assert(proxyName);

ack = get_random_u32();

for(i=0; i < NUM_IPID_PROBES; i++) probe_returned[i] = 0;   initialize_proxy_struct(proxy);   initialize_timeout_info(&proxy->host.to);

proxy->max_groupsz = (o.max_parallelism)? o.max_parallelism : 100;

proxy->min_groupsz = (o.min_parallelism)? o.min_parallelism : 4;

proxy->max_senddelay = 100000;

Strncpy(name, proxyName, sizeof(name));

q = strchr(name, ':');

if (q) {

*q++ = '';

proxy->probe_port = strtoul(q, &endptr, 10);

if (*q==0 || !endptr || *endptr != '' || !proxy->probe_port) {

fatal("Invalid port number given in IP ID zombie specification: %s", proxyName);

}

} else {

if (ports->syn_ping_count > 0) {

proxy->probe_port = ports->syn_ping_ports[0];

} else if (ports->ack_ping_count > 0) {

proxy->probe_port = ports->ack_ping_ports[0];

} else {

u16 *ports;

int count;

getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &ports, &count);

assert(count > 0);

proxy->probe_port = ports[0];

free(ports);

}

}

proxy->host.setHostName(name);

if (resolve(name, 0, 0, &ss, &sslen, o.pf()) == 0) {

fatal("Could not resolve idle scan zombie host: %s", name);

}

proxy->host.setTargetSockAddr(&ss, sslen);

/* Lets figure out the appropriate source address to use when sending

the pr0bez */

proxy->host.TargetSockAddr(&ss, &sslen);

if (!NMAP_route_dst(&ss, &rnfo))

fatal("Unable to find appropriate source address and device interface to use when sending packets to %s", proxyName);

if (o.spoofsource) {

o.SourceSockAddr(&ss, &sslen);

proxy->host.setSourceSockAddr(&ss, sslen);

proxy->host.setDeviceNames(o.device, o.device);

} else {

proxy->host.setDeviceNames(rnfo.ii.devname, rnfo.ii.devfullname);

proxy->host.setSourceSockAddr(&rnfo.srcaddr, sizeof(rnfo.srcaddr));

}

if (rnfo.direct_connect) {

proxy->host.setDirectlyConnected(true);

} else {

proxy->host.setDirectlyConnected(false);

proxy->host.setNextHop(&rnfo.nexthop,

sizeof(rnfo.nexthop));

}

proxy->host.setIfType(rnfo.ii.device_type);

if (rnfo.ii.device_type == devt_ethernet)

proxy->host.setSrcMACAddress(rnfo.ii.mac);

/* Now lets send some probes to check IP ID algorithm ... */

/* First we need a raw socket ... */

if ((o.sendpref & PACKET_SEND_ETH) &&  proxy->host.ifType() == devt_ethernet) {

if (!setTargetNextHopMAC(&proxy->host))

fatal("%s: Failed to determine dst MAC address for Idle proxy",

__func__);

memcpy(proxy->eth.srcmac, proxy->host.SrcMACAddress(), 6);

memcpy(proxy->eth.dstmac, proxy->host.NextHopMACAddress(), 6);

proxy->eth.ethsd = eth_open_cached(proxy->host.deviceName());

if (proxy->eth.ethsd == NULL)

fatal("%s: Failed to open ethernet device (%s)", __func__, proxy->host.deviceName());

proxy->rawsd = -1;

proxy->ethptr = &proxy->eth;

} else {

#ifdef WIN32

win32_fatal_raw_sockets(proxy->host.deviceName());

#endif

if ((proxy->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )       pfatal("socket troubles in %s", __func__);     unblock_socket(proxy->rawsd);

broadcast_socket(proxy->rawsd);

#ifndef WIN32

sethdrinclude(proxy->rawsd);

#endif

proxy->eth.ethsd = NULL;

proxy->ethptr = NULL;

}

/* Now for the pcap opening nonsense ... */

/* Note that the snaplen is 152 = 64 byte max IPhdr + 24 byte max link_layer

* header + 64 byte max TCP header. */

if((proxy->pd=my_pcap_open_live(proxy->host.deviceName(), 152,  (o.spoofsource)? 1 : 0, 50))==NULL)

fatal("%s", PCAP_OPEN_ERRMSG);

p = strdup(proxy->host.targetipstr());

q = strdup(inet_ntoa(proxy->host.v4source()));

Snprintf(filter, sizeof(filter), "tcp and src host %s and dst host %s and src port %hu", p, q, proxy->probe_port);

free(p);

free(q);

set_pcap_filter(proxy->host.deviceFullName(), proxy->pd,  filter);

if (o.debugging)

log_write(LOG_STDOUT, "Packet capture filter (device %s): %s\n", proxy->host.deviceFullName(), filter);

/* Windows nonsense -- I am not sure why this is needed, but I should

get rid of it at sometime */

sequence_base = get_random_u32();

/* Yahoo!  It is finally time to send our pr0beZ! */

while(probes_sent < NUM_IPID_PROBES) {     if (o.scan_delay) enforce_scan_delay(NULL);     else if (probes_sent) usleep(30000);     /* TH_SYN|TH_ACK is what the proxy will really be receiving from        the target, and is more likely to get through firewalls.  But        TH_SYN allows us to get a nonzero ACK back so we can associate        a response with the exact request for timing purposes.  So I        think I'll use TH_SYN, although it is a tough call. */     /* We can't use decoys 'cause that would screw up the IP IDs */     send_tcp_raw(proxy->rawsd, proxy->ethptr,

proxy->host.v4sourceip(), proxy->host.v4hostip(),

o.ttl, false,

o.ipoptions, o.ipoptionslen,

o.magic_port + probes_sent + 1, proxy->probe_port,

sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,

(u8 *) "\x02\x04\x05\xb4",4,

NULL, 0);

gettimeofday(&probe_send_times[probes_sent], NULL);

probes_sent++;

/* Time to collect any replies */

while(probes_returned < probes_sent && !timedout) {       to_usec = (probes_sent == NUM_IPID_PROBES)? hardtimeout : 1000;       ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true);

gettimeofday(&tmptv, NULL);

if (!ip) {

if (probes_sent < NUM_IPID_PROBES)    break;  if (TIMEVAL_SUBTRACT(tmptv, probe_send_times[probes_sent - 1]) >= hardtimeout) {

timedout = 1;

}

continue;

} else if (TIMEVAL_SUBTRACT(tmptv, probe_send_times[probes_sent - 1]) >=

hardtimeout)  {

timedout = 1;

}

if (lastipid != 0 && ip->ip_id == lastipid) {

continue; /* probably a duplicate */

}

lastipid = ip->ip_id;

if (bytes < ( 4 * ip->ip_hl) + 14U)

continue;

if (ip->ip_p == IPPROTO_TCP) {

tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));

if (ntohs(tcp->th_dport) < (o.magic_port+1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES  || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) {

if (o.debugging > 1) error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src));

continue;

}

seq_response_num = probes_returned;

/* The stuff below only works when we send SYN packets instead of

SYN|ACK, but then are slightly less stealthy and have less chance

of sneaking through the firewall.  Plus SYN|ACK is what they will

be receiving back from the target */

probes_returned++;

ipids[seq_response_num] = (u16) ntohs(ip->ip_id);

probe_returned[seq_response_num] = 1;

adjust_timeouts2(&probe_send_times[seq_response_num], &rcvdtime, &(proxy->host.to));

}

}

}

/* Yeah!  We're done sending/receiving probes ... now lets ensure all of our responses are adjacent in the array */

for(i=0,probes_returned=0; i < NUM_IPID_PROBES; i++) {     if (probe_returned[i]) {       if (i > probes_returned)

ipids[probes_returned] = ipids[i];

probes_returned++;

}

}

if (probes_returned == 0)

fatal("Idle scan zombie %s (%s) port %hu cannot be used because it has not returned any of our probes -- perhaps it is down or firewalled.",

proxy->host.HostName(), proxy->host.targetipstr(),

proxy->probe_port);

proxy->seqclass = get_ipid_sequence(probes_returned, ipids, 0);

switch(proxy->seqclass) {

case IPID_SEQ_INCR:

case IPID_SEQ_BROKEN_INCR:

log_write(LOG_PLAIN, "Idle scan using zombie %s (%s:%hu); Class: %s\n", proxy->host.HostName(), proxy->host.targetipstr(), proxy->probe_port, ipidclass2ascii(proxy->seqclass));

break;

default:

fatal("Idle scan zombie %s (%s) port %hu cannot be used because IP ID sequencability class is: %s.  Try another proxy.", proxy->host.HostName(), proxy->host.targetipstr(), proxy->probe_port, ipidclass2ascii(proxy->seqclass));

}

proxy->latestid = ipids[probes_returned - 1];

proxy->current_groupsz = MIN(proxy->max_groupsz, 30);

if (probes_returned < NUM_IPID_PROBES) {     /* Yikes!  We're already losing packets ... clamp down a bit ... */     if (o.debugging)       error("Idle scan initial zombie qualification test: %d probes sent, only %d returned", NUM_IPID_PROBES, probes_returned);     proxy->current_groupsz = MIN(12, proxy->max_groupsz);

proxy->current_groupsz = MAX(proxy->current_groupsz, proxy->min_groupsz);

proxy->senddelay += 5000;

}

/* OK, through experimentation I have found that some hosts (*cough*

Solaris) APPEAR to use simple IP ID incrementing, but in reality they

assign a new IP ID base to each host which connects with them.  This

is actually a good idea on several fronts, but it totally

frustrates our efforts (which rely on side-channel IP ID info

leaking to different hosts).  The good news is that we can easily

detect the problem by sending some spoofed packets "from" the first

target to the zombie and then probing to verify that the proxy IP ID

changed.  This will also catch the case where the NMAP user is

behind an egress filter or other measure that prevents this sort of

sp00fery */

if (first_target) {

for (probes_sent = 0; probes_sent < 4; probes_sent++) {       if (probes_sent) usleep(50000);       send_tcp_raw(proxy->rawsd, proxy->ethptr,

first_target, proxy->host.v4hostip(),

o.ttl, false,

o.ipoptions, o.ipoptionslen,

o.magic_port, proxy->probe_port,

sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,

(u8 *) "\x02\x04\x05\xb4",

4, NULL, 0);

}

/* Sleep a little while to give packets time to reach their destination */

usleep(300000);

newipid = ipid_proxy_probe(proxy, NULL, NULL);

if (newipid == -1)

newipid = ipid_proxy_probe(proxy, NULL, NULL); /* OK, we'll give it one more try */

if (newipid < 0) fatal("Your IP ID Zombie (%s; %s) is behaving strangely -- suddenly cannot obtain IP ID", proxy->host.HostName(), proxy->host.targetipstr());

distance = ipid_distance(proxy->seqclass, proxy->latestid, newipid);

if (distance <= 0) {       fatal("Your IP ID Zombie (%s; %s) is behaving strangely -- suddenly cannot obtain valid IP ID distance.", proxy->host.HostName(), proxy->host.targetipstr());

} else if (distance == 1) {

fatal("Even though your Zombie (%s; %s) appears to be vulnerable to IP ID sequence prediction (class: %s), our attempts have failed.  This generally means that either the zombie uses a separate IP ID base for each host (like Solaris), or because you cannot spoof IP packets (perhaps your ISP has enabled egress filtering to prevent IP spoofing), or maybe the target network recognizes the packet source as bogus and drops them", proxy->host.HostName(), proxy->host.targetipstr(), ipidclass2ascii(proxy->seqclass));

}

if (o.debugging && distance != 5) {

error("WARNING: IP ID spoofing test sent 4 packets and expected a distance of 5, but instead got %d", distance);

}

proxy->latestid = newipid;

}

}

/* Adjust timing parameters up or down given that an idle scan found a

count of 'testcount' while the 'realcount' is as given.  If the

testcount was correct, timing is made more aggressive, while it is

slowed down in the case of an error */

static void adjust_idle_timing(struct idle_proxy_info *proxy,

Target *target, int testcount,

int realcount) {

static int notidlewarning = 0;

if (o.debugging > 1)

log_write(LOG_STDOUT,

"%s: tested/true %d/%d -- old grpsz/delay: %f/%d ",

__func__, testcount, realcount, proxy->current_groupsz, proxy->senddelay);

else if (o.debugging && testcount != realcount) {

error("%s: testcount: %d  realcount: %d -- old grpsz/delay: %f/%d", __func__, testcount, realcount, proxy->current_groupsz, proxy->senddelay);

}

if (testcount < realcount) {       /* We must have missed a port -- our probe could have been   dropped, the response to proxy could have been dropped, or we   didn't wait long enough before probing the proxy IP ID.  The   third case is covered elsewhere in the scan, so we worry most   about the first two.  The solution is to decrease our group   size and add a sending delay */ /* packets could be dropped because too many were sent at once */       proxy->current_groupsz = MAX(proxy->min_groupsz, proxy->current_groupsz * 0.8);

proxy->senddelay += 10000;

proxy->senddelay = MIN(proxy->max_senddelay, proxy->senddelay);

/* No group size should be greater than .5s of send delays */

proxy->current_groupsz = MAX(proxy->min_groupsz, MIN(proxy->current_groupsz, 500000 / (proxy->senddelay + 1)));

} else if (testcount > realcount) {

/* Perhaps the proxy host is not really idle ... */

/* I guess all I can do is decrease the group size, so that if the proxy is not really idle, at least we may be able to scan chunks more quickly in between outside packets */

proxy->current_groupsz = MAX(proxy->min_groupsz, proxy->current_groupsz * 0.8);

if (!notidlewarning && o.verbose) {

notidlewarning = 1;

error("WARNING: idle scan has erroneously detected phantom ports -- is the proxy %s (%s) really idle?", proxy->host.HostName(), proxy->host.targetipstr());

}

} else {

/* W00p We got a perfect match.  That means we get a slight increase

in allowed group size and we can lightly decrease the senddelay */

proxy->senddelay = (int) (proxy->senddelay * 0.9);

if (proxy->senddelay < 500) proxy->senddelay = 0;

proxy->current_groupsz = MIN(proxy->current_groupsz * 1.1, 500000 / (proxy->senddelay + 1));

proxy->current_groupsz = MIN(proxy->max_groupsz, proxy->current_groupsz);

}

if (o.debugging > 1)

log_write(LOG_STDOUT, "-> %f/%d\n", proxy->current_groupsz, proxy->senddelay);

}

/* OK, now this is the hardcore idle scan function which actually does

the testing (most of the other cruft in this file is just

coordination, preparation, etc).  This function simply uses the

idle scan technique to try and count the number of open ports in the

given port array.  The sent_time and rcv_time are filled in with

the times that the probe packet & response were sent/received.

They can be NULL if you don't want to use them.  The purpose is for

timing adjustments if the numbers turn out to be accurate. */

static int idlescan_countopen2(struct idle_proxy_info *proxy,

Target *target, u16 *ports, int numports,

struct timeval *sent_time, struct timeval *rcv_time)

{

#if 0 /* Testing code */

int i;

for(i=0; i < numports; i++)     if (ports[i] == 22)       return 1;   return 0; #endif   int openports;   int tries;   int proxyprobes_sent = 0; /* diff. from tries 'cause sometimes we         skip tries */   int proxyprobes_rcvd = 0; /* To determine if packets were dr0pped */   int sent, rcvd;   int ipid_dist;   struct timeval start, end, latestchange, now;   struct timeval probe_times[4];   int pr0be;   static u32 seq = 0;   int newipid = 0;   int sleeptime;   int lasttry = 0;   int dotry3 = 0;   struct eth_nfo eth;   if (seq == 0) seq = get_random_u32();   memset(&end, 0, sizeof(end));   memset(&latestchange, 0, sizeof(latestchange));   gettimeofday(&start, NULL);   if (sent_time) memset(sent_time, 0, sizeof(*sent_time));   if (rcv_time) memset(rcv_time, 0, sizeof(*rcv_time));   if (proxy->rawsd < 0) {     if (!setTargetNextHopMAC(target))       fatal("%s: Failed to determine dst MAC address for Idle proxy",      __func__);     memcpy(eth.srcmac, target->SrcMACAddress(), 6);

memcpy(eth.dstmac, target->NextHopMACAddress(), 6);

eth.ethsd = eth_open_cached(target->deviceName());

if (eth.ethsd == NULL)

fatal("%s: Failed to open ethernet device (%s)", __func__, target->deviceName());

} else eth.ethsd = NULL;

/* I start by sending out the SYN pr0bez */

for(pr0be = 0; pr0be < numports; pr0be++) {     if (o.scan_delay) enforce_scan_delay(NULL);     else if (proxy->senddelay && pr0be > 0) usleep(proxy->senddelay);

/* Maybe I should involve decoys in the picture at some point --

but doing it the straightforward way (using the same decoys as

we use in probing the proxy box is risky.  I'll have to think

about this more. */

send_tcp_raw(proxy->rawsd, eth.ethsd? ð : NULL,

proxy->host.v4hostip(), target->v4hostip(),

o.ttl, false,

o.ipoptions, o.ipoptionslen,

proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0,

(u8 *) "\x02\x04\x05\xb4", 4,

o.extra_payload, o.extra_payload_length);

}

gettimeofday(&end, NULL);

openports = -1;

tries = 0;

TIMEVAL_MSEC_ADD(probe_times[0], start, MAX(50, (target->to.srtt * 3/4) / 1000));

TIMEVAL_MSEC_ADD(probe_times[1], start, target->to.srtt / 1000 );

TIMEVAL_MSEC_ADD(probe_times[2], end, MAX(75, (2 * target->to.srtt +

target->to.rttvar) / 1000));

TIMEVAL_MSEC_ADD(probe_times[3], end, MIN(4000, (2 * target->to.srtt +

(target->to.rttvar << 2 )) / 1000));   do {     if (tries == 2) dotry3 = (get_random_u8() > 200);

if (tries == 3 && !dotry3)

break; /* We usually want to skip the long-wait test */

if (tries == 3 || (tries == 2 && !dotry3))

lasttry = 1;

gettimeofday(&now, NULL);

sleeptime = TIMEVAL_SUBTRACT(probe_times[tries], now);

if (!lasttry && proxyprobes_sent > 0 && sleeptime < 50000)

continue; /* No point going again so soon */

if (tries == 0 && sleeptime < 500)       sleeptime = 500;     if (o.debugging > 1) error("In preparation for idle scan probe try #%d, sleeping for %d usecs", tries, sleeptime);

if (sleeptime > 0)

usleep(sleeptime);

newipid = ipid_proxy_probe(proxy, &sent, &rcvd);

proxyprobes_sent += sent;

proxyprobes_rcvd += rcvd;

if (newipid > 0) {

ipid_dist = ipid_distance(proxy->seqclass, proxy->latestid, newipid);

/* I used to only do this if ipid_sit >= proxyprobes_sent, but I'd

rather have a negative number in that case. */

if (ipid_dist < proxyprobes_sent) {  if (o.debugging)            error("%s: Must have lost a sent packet because ipid_dist is %d while proxyprobes_sent is %d.", __func__, ipid_dist, proxyprobes_sent);  /* I no longer whack timing here ... done at bottom. */       }       ipid_dist -= proxyprobes_sent;       if (ipid_dist > openports) {

openports = ipid_dist;

gettimeofday(&latestchange, NULL);

} else if (ipid_dist < openports && ipid_dist >= 0) {

/* Uh-oh.  Perhaps I dropped a packet this time */

if (o.debugging > 1) {

error("%s: Counted %d open ports in try #%d, but counted %d earlier ... probably a proxy_probe problem", __func__, ipid_dist, tries, openports);

}

/* I no longer whack timing here ... done at bottom. */

}

}

if (openports > numports || (numports <= 2 && (openports == numports)))

break;

} while(tries++ < 3);   if (proxyprobes_sent > proxyprobes_rcvd) {

/* Uh-oh.  It looks like we lost at least one proxy probe packet */

if (o.debugging) {

error("%s: Sent %d probes; only %d responses.  Slowing scan.", __func__, proxyprobes_sent, proxyprobes_rcvd);

}

proxy->senddelay += 5000;

proxy->senddelay = MIN(proxy->max_senddelay, proxy->senddelay);

/* No group size should be greater than .5s of send delays */

proxy->current_groupsz = MAX(proxy->min_groupsz, MIN(proxy->current_groupsz, 500000 / (proxy->senddelay+1)));

} else {

/* Yeah, we got as many responses as we sent probes.  This calls for a

very light timing acceleration ... */

proxy->senddelay = (int) (proxy->senddelay * 0.95);

if (proxy->senddelay < 500) proxy->senddelay = 0;

proxy->current_groupsz = MAX(proxy->min_groupsz, MIN(proxy->current_groupsz, 500000 / (proxy->senddelay+1)));

}

if ((openports > 0) && (openports <= numports)) {     /* Yeah, we found open ports... lets adjust the timing ... */     if (o.debugging > 2) error("%s:  found %d open ports (out of %d) in %lu usecs", __func__, openports, numports, (unsigned long) TIMEVAL_SUBTRACT(latestchange, start));

if (sent_time) *sent_time = start;

if (rcv_time) *rcv_time = latestchange;

}

if (newipid > 0) proxy->latestid = newipid;

if (eth.ethsd) { eth.ethsd = NULL; } /* don't need to close it due to caching */

return openports;

}

/* The job of this function is to use the idle scan technique to count

the number of open ports in the given list.  Under the covers, this

function just farms out the hard work to another function. */

static int idlescan_countopen(struct idle_proxy_info *proxy,

Target *target, u16 *ports, int numports,

struct timeval *sent_time, struct timeval *rcv_time) {

int tries = 0;

int openports;

do {

openports = idlescan_countopen2(proxy, target, ports, numports, sent_time,

rcv_time);

tries++;

if (tries == 6 || (openports >= 0 && openports <= numports))       break;     if (o.debugging) {       error("%s: In try #%d, counted %d open ports out of %d.  Retrying", __func__, tries, openports, numports);     }     /* Sleep for a little while -- maybe proxy host had brief birst of        traffic or similar problem */     sleep(tries * tries);     if (tries == 5)       sleep(45); /* We're gonna give up if this fails, so we will be a bit      patient */     /* Since the host may have received packets while we were sleeping,        lets update our proxy IP ID counter */     proxy->latestid = ipid_proxy_probe(proxy, NULL, NULL);

} while(1);

if (openports < 0 || openports > numports ) {

/* Oh f*ck!!!! */

fatal("Idle scan is unable to obtain meaningful results from proxy %s (%s).  I'm sorry it didn't work out.", proxy->host.HostName(),

proxy->host.targetipstr());

}

if (o.debugging > 2) error("%s: %d ports found open out of %d, starting with %hu", __func__, openports, numports, ports[0]);

return openports;

}

/* Recursively idle scans scans a group of ports using a depth-first

divide-and-conquer strategy to find the open one(s). */

static int idle_treescan(struct idle_proxy_info *proxy, Target *target,

u16 *ports, int numports, int expectedopen) {

int firstHalfSz = (numports + 1)/2;

int secondHalfSz = numports - firstHalfSz;

int flatcount1, flatcount2;

int deepcount1 = -1, deepcount2 = -1;

struct timeval sentTime1, rcvTime1, sentTime2, rcvTime2;

int retrycount = -1, retry2 = -1;

int totalfound = 0;

/* Scan the first half of the range */

if (o.debugging > 1) {

error("%s: Called against %s with %d ports, starting with %hu. expectedopen: %d", __func__, target->targetipstr(), numports, ports[0], expectedopen);

error("IDLE SCAN TIMING: grpsz: %.3f delay: %d srtt: %d rttvar: %d",

proxy->current_groupsz, proxy->senddelay, target->to.srtt,

target->to.rttvar);

}

flatcount1 = idlescan_countopen(proxy, target, ports, firstHalfSz,

&sentTime1, &rcvTime1);

if (firstHalfSz > 1 && flatcount1 > 0) {

/* A port appears open!  We dig down deeper to find it ... */

deepcount1 = idle_treescan(proxy, target, ports, firstHalfSz, flatcount1);

/* Now we assume deepcount1 is right, and adjust timing if flatcount1 was

wrong. */

adjust_idle_timing(proxy, target, flatcount1, deepcount1);

}

/* I guess we had better do the second half too ... */

flatcount2 = idlescan_countopen(proxy, target, ports + firstHalfSz,

secondHalfSz, &sentTime2, &rcvTime2);

if ((secondHalfSz) > 1 && flatcount2 > 0) {

/* A port appears open!  We dig down deeper to find it ... */

deepcount2 = idle_treescan(proxy, target, ports + firstHalfSz,

secondHalfSz, flatcount2);

/* Now we assume deepcount1 is right, and adjust timing if flatcount1 was

wrong */

adjust_idle_timing(proxy, target, flatcount2, deepcount2);

}

totalfound = (deepcount1 == -1)? flatcount1 : deepcount1;

totalfound += (deepcount2 == -1)? flatcount2 : deepcount2;

if ((flatcount1 + flatcount2 == totalfound) &&

(expectedopen == totalfound || expectedopen == -1)) {

if (flatcount1 > 0) {

if (o.debugging > 1) {

error("Adjusting timing -- idlescan_countopen correctly found %d open ports (out of %d, starting with %hu)", flatcount1, firstHalfSz, ports[0]);

}

adjust_timeouts2(&sentTime1, &rcvTime1, &(target->to));

}

if (flatcount2 > 0) {

if (o.debugging > 2) {

error("Adjusting timing -- idlescan_countopen correctly found %d open ports (out of %d, starting with %hu)", flatcount2, secondHalfSz,

ports[firstHalfSz]);

}

adjust_timeouts2(&sentTime2, &rcvTime2, &(target->to));

}

}

if (totalfound != expectedopen) {

if (deepcount1 == -1) {

retrycount = idlescan_countopen(proxy, target, ports, firstHalfSz, NULL,

NULL);

if (retrycount != flatcount1) {

/* We have to do a deep count if new ports were found and

there are more than 1 total */

if (firstHalfSz > 1 && retrycount > 0) {

retry2 = retrycount;

retrycount = idle_treescan(proxy, target, ports, firstHalfSz,

retrycount);

adjust_idle_timing(proxy, target, retry2, retrycount);

} else {

if (o.debugging)

error("Adjusting timing because my first scan of %d ports, starting with %hu found %d open, while second scan yielded %d", firstHalfSz, ports[0], flatcount1, retrycount);

adjust_idle_timing(proxy, target, flatcount1, retrycount);

}

totalfound += retrycount - flatcount1;

flatcount1 = retrycount;

/* If our first count erroneously found and added an open port,

we must delete it */

if (firstHalfSz == 1 && flatcount1 == 1 && retrycount == 0)

target->ports.forgetPort(ports[0], IPPROTO_TCP);

}

}

if (deepcount2 == -1) {

retrycount = idlescan_countopen(proxy, target, ports + firstHalfSz,

secondHalfSz, NULL, NULL);

if (retrycount != flatcount2) {

if (secondHalfSz > 1 && retrycount > 0) {

retry2 = retrycount;

retrycount = idle_treescan(proxy, target, ports + firstHalfSz,

secondHalfSz, retrycount);

adjust_idle_timing(proxy, target, retry2, retrycount);

} else {

if (o.debugging)

error("Adjusting timing because my first scan of %d ports, starting with %hu found %d open, while second scan yeilded %d", secondHalfSz, ports[firstHalfSz], flatcount2, retrycount);

adjust_idle_timing(proxy, target, flatcount2, retrycount);

}

totalfound += retrycount - flatcount2;

flatcount2 = retrycount;

/* If our first count erroneously found and added an open port,

we must delete it. */

if (secondHalfSz == 1 && flatcount2 == 1 && retrycount == 0)

target->ports.forgetPort(ports[firstHalfSz], IPPROTO_TCP);

}

}

}

if (firstHalfSz == 1 && flatcount1 == 1)

target->ports.setPortState(ports[0], IPPROTO_TCP, PORT_OPEN);

if ((secondHalfSz == 1) && flatcount2 == 1)

target->ports.setPortState(ports[firstHalfSz], IPPROTO_TCP, PORT_OPEN);

return totalfound;

}

/* The very top-level idle scan function -- scans the given target

host using the given proxy -- the proxy is cached so that you can keep

calling this function with different targets. */

void idle_scan(Target *target, u16 *portarray, int numports,

char *proxyName, const struct scan_lists * ports) {

static char lastproxy[MAXHOSTNAMELEN + 1] = ""; /* The proxy used in any previous call */

static struct idle_proxy_info proxy;

int groupsz;

int portidx = 0; /* Used for splitting the port array into chunks */

int portsleft;

char scanname[128];

Snprintf(scanname, sizeof(scanname), "idle scan against %s", target->NameIP());

ScanProgressMeter SPM(scanname);

if (numports == 0) return; /* nothing to scan for */

if (!proxyName) fatal("idle scan requires a proxy host");

if (*lastproxy && strcmp(proxyName, lastproxy))

fatal("%s: You are not allowed to change proxies midstream.  Sorry", __func__);

assert(target);

if (target->timedOut(NULL))

return;

if (target->ifType() == devt_loopback) {

log_write(LOG_STDOUT, "Skipping Idle Scan against %s -- you can't idle scan your own machine (localhost).\n", target->NameIP());

return;

}

target->startTimeOutClock(NULL);

/* If this is the first call,  */

if (!*lastproxy) {

initialize_idleproxy(&proxy, proxyName, target->v4hostip(), ports);

strncpy(lastproxy, proxyName, sizeof(lastproxy));

}

/* If we don't have timing infoz for the new target, we'll use values

derived from the proxy */

if (target->to.srtt == -1 && target->to.rttvar == -1) {

target->to.srtt = MAX(200000,2 * proxy.host.to.srtt);

target->to.rttvar = MAX(10000, MIN(proxy.host.to.rttvar, 2000000));

target->to.timeout = target->to.srtt + (target->to.rttvar << 2);   } else {     target->to.srtt = MAX(target->to.srtt, proxy.host.to.srtt);

target->to.rttvar = MAX(target->to.rttvar, proxy.host.to.rttvar);

target->to.timeout = target->to.srtt + (target->to.rttvar << 2);

}

/* Now I guess it is time to let the scanning begin!  Since idle

scan is sort of tree structured (we scan a group and then divide

it up and drill down in subscans of the group), we split the port

space into smaller groups and then call a recursive

divide-and-counquer function to find the open ports */

while(portidx < numports) {

portsleft = numports - portidx;

/* current_groupsz is doubled below because idle_subscan cuts in half */

groupsz = MIN(portsleft, (int) (proxy.current_groupsz * 2));

idle_treescan(&proxy, target, portarray + portidx, groupsz, -1);

portidx += groupsz;

}

char additional_info[14];

Snprintf(additional_info, sizeof(additional_info), "%d ports", numports);

SPM.endTask(NULL, additional_info);

/* Now we go through the ports which were scanned but not determined

to be open, and add them in the "closed|filtered" state */

for(portidx = 0; portidx < numports; portidx++) {     if (target->ports.portIsDefault(portarray[portidx], IPPROTO_TCP)) {

target->ports.setPortState(portarray[portidx], IPPROTO_TCP, PORT_CLOSEDFILTERED);

target->ports.setStateReason(portarray[portidx], IPPROTO_TCP, ER_NOIPIDCHANGE, 0, NULL);

} else

target->ports.setStateReason(portarray[portidx], IPPROTO_TCP, ER_IPIDCHANGE, 0, NULL);

}

target->stopTimeOutClock(NULL);

return;

}

IP协议扫描

IP协议扫描可以让您确定哪些IP协议(TCP,ICMP,IGMP等)是目标机器的支持。这不是技术上的端口扫描,因为只是IP协议号的循环而不是TCP或UDP端口号。

命令:NMAP -sO 目标

FTP弹跳扫描

这允许用户连接到一个FTP服务器,然后文件被发送到目标主机。NMAP会发送文件到你指定的目标主机上的端口,通过错误消息判断该端口的状态。这是绕过防火墙的好方法,因为相对于Internet主机,组织的FTP服务器经常被放置在可被内网访问的范围中。它的格式为<username>:<password>@<server>:<port>。 <server>是一个脆弱的FTP服务器的名称或IP地址。

命令:NMAP –b ftp rely host

NMAP -T0-b username:password@ftpserver.tld:21 victim.tld

这将使用用户名“username”,密码为“password”,FTP服务器“FTP server.tld”,ftp端口则是21,用于扫描的文件是服务器上的victim.tld。

如果FTP服务器支持匿名登录,就不用填写“username:password@”部分。如果FTP端口是默认的21,也可以省略不写,但如果FTP端口是21之外的必须得指明。

端口规范和扫描顺序

除了所有的前面讨论的扫描方法,NMAP提供选项用于指定被扫描的端口和扫描顺序是随机的或顺序的。默认情况下NMAP扫描最常见的1000个端口。

-p<端口范围>(只扫描指定的端口)

此选项指定要扫描的端口范围,并覆盖默认。单个端口号都行,因为是用连字符(例如1-1023)分割范围。范围的起始或结束可以被省略,NMAP会分别使用1和65535。所以你可以指定-p-,相当于从1到65535进行扫描。

NMAP -p1-1023 目标

你可以指定用于端口扫描的协议类型,比如T代表TCP,U代表UDP,S代表SCTP,P代表IP。

NMAP -p U:53,111,137,T:21-25,80,139,8080 目标

-F(快速(有限的端口)扫描)

指定比默认情况下更少的端口数。通常情况下的NMAP扫描每个扫描协议中最常见的1000个端口。用-F将会减少到100个。

NMAP -F 目标

-r(不要随机端口)

默认情况下NMAP会随机扫描端口,但您可以指定-r为顺序(从最低到最高排序)端口扫描来代替。

NMAP -r 目标

在接下来的部分,我将使用NMAP绕过防火墙,创建自定义利用程序。

引用内容:

http://www.kyuzz.org/antirez/papers/dumbscan.html

http://www.kyuzz.org/antirez/papers/moreipid.html

http://en.wikipedia.org/wiki/Idle_scan

*参考来源:infosecinstitute,FB小编东二门陈冠希编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

Nmap备忘单:从探索到漏洞利用(Part 2)的更多相关文章

  1. Nmap备忘单:从探索到漏洞利用(Part 4)

    这是我们的Nmap备忘单的第四部分(Part 1. Part 2. Part 3).本文中我们将讨论更多东西关于扫描防火墙,IDS / IPS 逃逸,Web服务器渗透测试等.在此之前,我们应该了解一下 ...

  2. Nmap备忘单:从探索到漏洞利用(Part 5)

    这是备忘单的最后一部分,在这里主要讲述漏洞评估和渗透测试. 数据库审计 列出数据库名称 nmap -sV --script=mysql-databases 192.168.195.130 上图并没有显 ...

  3. Nmap备忘单:从探索到漏洞利用 Part1

    在侦查过程中,信息收集的初始阶段是扫描. 侦查是什么? 侦查是尽可能多的收集目标网络的信息.从黑客的角度来看,信息收集对攻击非常有帮助,一般来说可以收集到以下信息: 电子邮件.端口号.操作系统.运行的 ...

  4. Nmap备忘单:从探索到漏洞利用(Part3)

    众所周知NMAP是经常用来进行端口发现.端口识别.除此之外我们还可以通过NMAP的NSE脚本做很多事情,比如邮件指纹识别,检索WHOIS记录,使用UDP服务等. 发现地理位置 Gorjan Petro ...

  5. Nmap备忘单

    #在推特上看到,感觉做的相当不错就转一波. 目标规格 开关 例 描述   nmap 192.168.1.1 扫描一个IP   nmap 192.168.1.1 192.168.2.1 扫描特定的IP地 ...

  6. Cheat (tldr, bropages) - Unix命令用法备忘单

    cheat 是一个Unix命令行小工具,用来查询一些常用命令的惯用法(我们都知道,man page阅读起来太累了,常常是跳到最后去看 examples,但并不是所有man pages里面都有examp ...

  7. Objective-C教程备忘单

    终极版本的Objective-C教程备忘单帮助你进行iOS开发. 想开始创建你的第一个iOS应用程序么?那么看一下这篇很棒的教程吧:Create your first iOS 7 Hello Worl ...

  8. HTML5属性备忘单

    在网上闲逛的时候看到了文章,感觉总结的这个html5文章,决定转载过来,在排版的时候也帮助自己重新梳理复习一遍.毕竟学习基础最重要. by zhangxinxu from http://www.zha ...

  9. 跨站脚本(XSS)备忘单-2019版

    这是一份跨站脚本(XSS)备忘录,收集了大量的XSS攻击向量,包含了各种事件处理.通讯协议.特殊属性.限制字符.编码方式.沙箱逃逸等技巧,可以帮助渗透测试人员绕过WAF和过滤机制. 译者注:原文由Po ...

随机推荐

  1. Linq之Expression初见

    目录 写在前面 系列文章 Expression 表达式树创建方式 一个例子 总结 写在前面 上篇文章介绍了扩展方法,这篇文章开始将陆续介绍在linq中使用最多的表达式树的相关概念,以概念及例子一一列出 ...

  2. ubuntu chmod 无法更改 文件夹权限 系统提示“不允许的操作 2、linux 如何修改只读文件 3、ubuntu安装

    1.ubuntu chmod 无法更改 文件夹权限 系统提示“不允许的操作 答案:需要超级用户权限 sudo 2.linux 如何修改只读文件 答案:可以使用chmod命令,为改文件提供其他的权限.u ...

  3. reboot-css

    dd, label { margin-bottom: .5rem; }abbr[title] { text-decoration: none; }abbr[title] { border-bottom ...

  4. 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树

    sunshine的A题我竟然调了一周!!! 把循环dfs改成一个dfs就可以,,,我也不知道为什么这样就不会RE,但它却是A了,,, 这周我一直在调这个题,总结一下智障错误: 1.倍增的范围设成了n而 ...

  5. 扩展KMP

    刘雅琼论文 http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 论文讲的非常详细. 给定母串S,子串T,n=strlen(S),m=st ...

  6. hdu 1576 求逆元

    题意:给出n=A mod 9973和B,求(A/B) mod 9973 昨天用扩展欧几里得做过这题,其实用逆元也可以做. 逆元的定义:例如a*b≡1 (mod m),则b就是a关于m的逆元. 求逆元方 ...

  7. POJ1737 Connected Graph

    Connected Graph Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3156   Accepted: 1533 D ...

  8. linux内核数据结构学习总结

    目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...

  9. Selenium2+python自动化13-Alert

    不是所有的弹出框都叫alert,在使用alert方法前,先要识别出它到底是不是alert.先认清楚alert长什么样子,下次碰到了,就可以用对应方法解决.alert\confirm\prompt弹出框 ...

  10. HD1561The more, The Better(树形DP+有依赖背包)

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...