“为什么要自己写?”


“自己写的工具有大公司写的成熟工具好用吗?”


这是当初有这想法的时候,大佬们问的最多的问题。其实对我个人而言,只是想学习一下Go语言,同时为开源社区做做贡献而已。



然而,在日常渗透测试时,时常发现有些工具用着不很顺手——参数太多记不住、想用的功能还要收费、明明存在问题的地方用工具测试居然报错、不支持跨平台......


这些不方便的地方又增强了自己写一个工具的想法。然而,在随后边学边写的过程中,发现自己写了个BUG出来。



下面给大家介绍一下这个“BUG”是如何打造的。


1

搭建高交互CLI


由于对MSF一直有种莫名的崇拜,想要做一款类似MSF的工具,于是选取了一个高交互式CLI(命令行框架),采用c-bata/go-prompt这个库,主要包含Executor和Completer。


Executor相当于执行器,用于设置CLI需执行的指令;Completer相当于解释器,用于给指令需要的参数设置自动补全。


基本代码结构如下:



首先,生成一个自定义的CLI。由于要动态修改CLI前缀,需设置OptionLivePrefix属性:



进入Executor进行设置。设置支持的指令(load、poc、help、exit、quit):



接下来,给这些指令设置自动补全,有些命令使用的参数不同,需要设置多个函数进行对应:



自动检测传入的参数有几个,随即进行设置:



2

基础扫描模块


代码结构:



端口扫描


定义端口扫描的CLI:



设置扫描用的参数,针对端口扫描,优化了set参数。考虑到大范围扫描,支持读取文件操作:



获取设置的IP,随后进行全端口扫描,之后对扫描出的端口进行服务识别:



Go语言天然的高并发性是当初选择它的原因,但问题也随之而来——在进行多线程扫描时很容易产生死锁。使用了sync.Mutex互斥锁之后,发现耗时很高,还不如单线程快。


好不容易运行结束,又由于扫描进程同时在CLI进程中,导致使用互斥锁后,不知为何将CLI进程退出了。


在处理多线程时纠结了好久。后来又想到一个办法——使用channel对goroutine进行控制。这样可以保证在同一时刻,仅有一个goroutine能向一个通道发送元素值,同时也仅有一个gorountine能从它那里接收元素值。


多线程全端口扫描:



对端口进行服务和应用版本检测,利用banner进行识别,内置指纹探针采用nmap-service-probes:



完成后的效果:



看着代码顺利的运行,我满心欢喜,沉浸在激动的心情中。然而此时大佬泼来一盆冷水。



原来大佬对自己的服务器进行了测试,发现扫描的结果不准——明明开了3389,愣是扫不到。


经过排查发现,工具默认的是对全端口进行扫描,测试时,为了达到最大性能,设置了70000的线程。


大佬测试时只要开始运行,本地网络就呈现断开的情形——原来是自己把自己的带宽消耗光了。这难道就是“发起狠来连我自己都害怕”。



随后将线程调低,使用结果还是蛮准的:



子域名扫描和敏感路径扫描


对于子域名和敏感路径扫描功能,借鉴了gobuster的实现方式(向gobuster作者致敬):



首先定义一个执行器:



利用init函数定义初始化的参数,RunE参数后面是要执行的主要函数:



敏感路径扫描模块如下图。实现代码与子域名模块类似,目前针对敏感路径和子域名,只实现了通过字典进行爆破的方式:



还可以针对性地设置一些cookie、header等http访问参数:



完成之后的效果:



3

下期预告


在下周的更新中,将带来此工具的弱口令爆破模块以及POC模块,当然,还有项目的开源地址


下周同一时间,我们不见不散。