netcat 工具小巧玲珑,被誉为 hacker 界的瑞士军刀。本文以 netcat-0.7.1版本为例,分析 其
源代码。 我们主要分析的功能是: 监听、 ⑴ 连接; 端口扫描。 ⑵ (3) 连接到远端后自动打开 shell 执行命令; 将 netcat 主要的模块分析一下。水平所限,错误再所难免,请大家指正。 第一部分我们先分析其监听过程: 以 netcat –l –p 2008为例 在执行参数分析-l 的时候,将 netcat_mode 设置为 NETCAT_LISTEN,作为监听模式。 if (netcat_mode != NETCAT_UNSPEC)ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("You can specify mode flags (`-l' and `-L') only once"));
netcat_mode = NETCAT_LISTEN; 在执行参数分析-p 的时候, 通过将-p 参数的关联选项 optarg 即: ( 端口值) 填入到 local_port 结构中,如果失败,退出。 case 'p': /* local source port */if (!netcat_getport(&;amp;local_port, optarg, 0)) ncprint(NCPRINT_ERROR optarg); break; Netcat_getport 函数分析: /* Identifies a port and fills in the netcat_port structure pointed to by `dst’. If `port_string’ is not NULL, it is used to identify the port (either by port name, listed in /etc/services, or by a string number).*/ 原型:bool netcat_getport(nc_port_t *dst, const char *port_string, unsigned short port_num) memset(dst, 0, sizeof(*dst)); 填充 nc_port 结构 if (!port_string) { //如果传入的 port_string 参数为 null,则需要给定一个特定的 port //number if (port_num == 0) return FALSE; dst-&;gt;num = port_num; dst-&;gt;netnum = htons(port_num); //如果是
常用的服务端口,则将 name 付值 //比如 port 为 22 ,则为 ssh servent = getservbyport((int)dst-&;gt;netnum, get_proto); //通过端口号,得到服务名称 | NCPRINT_EXIT, _("Invalid local port: %s"),
if (servent) { assert(dst-&;gt;netnum == servent-&;gt;s_port); strncpy(dst-&;gt;name, servent-&;gt;s_name, sizeof(dst-&;gt;name)); // 将 服 务 名 称 填 入 到 nc_port //构中 } goto end; } 代码结构1 我们的参数中给定了传入了 port_string 参数,所以进入到 else 程序分支: else {long port; char *endptr; /* empty string? refuse it */ if (!port_string[0]) return FALSE; /* try to convert the string into a valid port number. but it doesn't occur at the first char, throw an error */ //将-p 2008 这个2008字符串转换为 long 数字,赋给 //port,如果为&;gt;0&;amp;&;amp;&;lt;65536然后 return netcat_getopt(dst,NULL, //(in_port_t)port) //If `port_string' is NULL then `port_num' is used to identify the port = strtol(port_string, &;amp;endptr, 10); if (!endptr[0]) { /* pure numeric value, check it out */ port If an error occurs
if ((port &;gt; 0) &;amp;&;amp; (port &;lt; 65536)) return netcat_getport(dst, NULL, //函数,通过代码结构1进行处理 else return FALSE; } else if (endptr != port_string) return FALSE; //此时如果得到的是服务名称,那么通过 getservbyname 将 nc_port 结构进行填充。 /* this is a port name, try t
o lookup it */ servent = getservbyname(port_string, get_proto); if (servent) { strncpy(dst-&;gt;name, servent-&;gt;s_name, sizeof(dst-&;gt;name)); dst-&;gt;netnum = servent-&;gt;s_port; dst-&;gt;num = ntohs(dst-&;gt;netnum); goto end; } return FALSE; } 代码结构2 通过代码结构1和2,调用 netcat_getport 将输入的 port 参数填充了 local_port 结构。 此时,对于参数 netcat –l –p 2008处理完毕。 然后,
程序进入到 listen mode 处理: listen_sock.proto = opt_proto; //对于 listen_sock 结构进行填出 listen_sock.timeout = opt_wait; /* mixed numeric and string value */ (in_port_t)port); //将这个得到的 long 型端