相对于nmap扫描,masscan扫描随机扫描IP和端口。多个IP地址多个端口并行扫描,加快了扫描速度。对于处理能力低的端口,可以获取更加准确的结果。Masscan是怎么做到随机化?
假设我们扫描m个ip地址,n个端口,总共需要mn次扫描。第i次扫描是对i%m个IP地址,i/m端口的扫描。扫描的随机化就变为对[1,mn]的随机排序。假设k=m*n,需要找到一个映射使得[1,k]空间映射到[1,k]空间,并且映射后的数值是随机的。Masscan是通过有限元加密来实现的,即若1<i<k,经过有限元加密之后,数值仍然在[1, k]空间内,并且一一对应。
代码中Masscan通过blackrock_shuffle函数(rand-blackrock.c)实现随机化。
uint64_t
blackrock_shuffle(const struct BlackRock *br, uint64_t m)
{
uint64_t c;
c = ENCRYPT(br->rounds, br->a, br->b, m, br->seed);
while (c >= br->range)
c = ENCRYPT(br->rounds, br->a, br->b, c, br->seed);
return c;
}
ENCRYPT通过加密实现了k个数的随机化。
static inline uint64_t ENCRYPT(unsigned r, uint64_t a, uint64_t b, uint64_t m, uint64_t seed)
{
uint64_t L, R;
unsigned j;
uint64_t tmp;
L = m % a;
R = m / a;
for (j=1; j<=r; j++) {
if (j & 1) {
tmp = (L + READ(j, R, seed)) % a;
} else {
tmp = (L + READ(j, R, seed)) % b;
}
L = R;
R = tmp;
}
if (r & 1) {
return a * L + R;
} else {
return a * R + L;
}
}
随机化代码如下:
xXx = blackrock_shuffle(&blackrock, xXx);
ip_them = rangelist_pick(&masscan->targets, xXx % count_ips);
port_them = rangelist_pick(&masscan->ports, xXx / count_ips);
上述问题实际上是随机获取k个不重复的不大于k的整数。然后通过k,计算出本次扫描的IP地址和端口号。