插件分享 | 一键统计 Windows 各版本数量的 Windows Count

GobySec  1218天前

youdu图片20210805163541.png


Goby社区第16 篇插件分享文章

全文共:4955    预计阅读时间:13 分钟


前言:Goby 是一款优秀的漏洞验证和利用的工具,功能十分强大,具有丰富的指纹识别规则,扩展性也非常好,各种丰富的插件极大地简化了日常渗透的工作,初次编写插件的我,选择了一个较为简单的统计插件作为入门之作,编写过程中也学习了很多关于 js 的知识,同时参考了插件市场中许多的插件,也感谢编写期间 @go0p 师傅的指导。


0×01 插件使用


当 Goby 扫描完成后或点击扫描历史结果,然后点击侧边的插件按钮,打开我们的 Windows Count 插件即可看到统计的结果,详情如下所示:

Image

0×02 插件开发


2.1 开发思路

作为一个 js 啥都没有接触过的小白,第一想法肯定是先去看看官方文档和模仿一下别的师傅写的插件。首先,我简单地对插件的需求进行了梳理,主要有以下几个要点:

  • 插件基本配置

  • 从扫描资产中提取信息

  • Windows 版本信息提取

  • 提取 IP 和数量

  • 展示

2.2 插件基本配置

通过对官方文档进行阅读,主要的是配置好 extension.js 中的注册函数,和 package.json 中的插件位置展示,详情如下:

function activate (content) {
    goby.registerCommand('WindowsCount', function () {#WindowsCount以带要和package中的command值对应
        let path = __dirname + "/os.html"#实现的代码文件路径
        goby.showPage(path,false);#展示以页面方式展示
    });
}

exports.activate = activate;

2.jpg

2.3 从扫描资产中提取信息

基本的配置都实现好之后,接下来我们就需要对功能的实现进行编码,首先我们需要将扫描的结果提取出来,这里需要用到的 API 是 goby.getAsset,参考官方文档说明:

3.jpg

我们首先需要编写一个简单的 debug 函数查看获取的信息:

goby.getAsset(goby.getTaskId(), getAssetData);//获取资产数据
function getAssetData(data) {
    if (data.statusCode == 200) {
        console.log(data);//打印出返回的data数据
    }
}

4.png

2.4 Windows 版本信息提取

通过将 data 数据进行输出,我们可以很清晰地看到 Windows 的版本信息存储在 dcerpc 协议中的 product 字段中,故此我们可以根据协议为 dcerpc 并且 product 中包含 Windows 关键字作为过滤条件提取 Windows 版本类型,代码如下:

let ostypes = []; //存储系统类型
goby.getAsset(goby.getTaskId(), getAssetData); //获取资产数据
 //去重函数
function unique(arr) {
  return Array.from(new Set(arr));
}
function getAssetData(data) {
    if (data.statusCode == 200) {
        let ipinfo = data.data.ips
        //获取OS类型
        ipinfo.forEach((v, k) = >{
            if (v.protocols) {
                for (var i in v.protocols) {
                    if (v.protocols[i].protocol.search("dcerpc") != -1 && v.protocols[i].product.search("Windows") != -1) {
                        console.log(v.protocols[i].product) 
                        ostypes.push(v.protocols[i].product);//将系统类型存入列表中
                    }
                }
            }
        });
        ostypes = unique(ostypes);//去重
    }
}

执行结果

5.jpg

2.5 提取 IP 和数量

将系统版本提取完成后,我们需要将对应的版本的 IP 提取出来,然后将 IP 个数进行统计,这里是一个一对多的关系,我们需要建立一个字典,将系统类型作为 key,将 IP 放入到 list 中去,然后就可以将其关系对应起来,最后对 value 的数量进行统计既可以完成我们的需求,详细代码如下:

        //根据OS类型生成dic
        for (var i in ostypes) {
          osinfo[ostypes[i]] = [];
        }

        //根据OS类型匹配对应的IP
        for (var key in osinfo) {
          ipinfo.forEach((v, k) => {
            if (v.protocols) {
              for (var i in v.protocols) {
                if (v.protocols[i].port == 135 && v.protocols[i].product == key) {
                  osinfo[key].push(v.protocols[i].hostinfo.split(":")[0]);
                }
              }
            }
          });

        }
        console.log(osinfo)

执行结果

6.png

2.6 展示

展示就直接抄了 threatbook 插件的 html 代码,直接将源码复制修改一下即可,详细的可以参考如下代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Windows系统统计表</title>
  <link rel="stylesheet" href="assets/lib/layui/css/layui.css">
</head>

<body>
  <div>
    <script>
</script>
  </div>
  <div>
    <table id="os-table" class="layui-table" lay-even lay-skin="nob">
      <thead>
        <tr>
          <th width="40" style="font-size: medium;" data-i18n="System type"></th>
          <th width="55" style="font-size: medium;">IP</th>
          <th width="55" style="font-size: medium;" data-i18n="Count"></th>
        </tr>
      </thead>
      <tbody>
        <tr>
        </tr>
      </tbody>
    </table>
  </div>
  </div>

  <script src="assets/js/jquery-3.3.1.min.js"></script>
  <script src="assets/lib/layui/layui.all.js"></script>
  <script src="assets/js/jquery.i18next.js"></script>
  <script>
    let osinfo = new Array();
    let fs = parent.require('fs');
    let ostypes = [];
    let html = "";


    goby.getAsset(goby.getTaskId(), getAssetData);

    //去重函数
    function unique(arr) {
      return Array.from(new Set(arr));
    }

    function lang(){
      //获取当前Languzge
      let language = goby.getLang();

      //判断翻译文件是否存在
      let translateState = fs.existsSync(goby.__dirname + '/assets/translate/' + language+'/html.json');

      //翻译文件存在则使用翻译文件,否则使用默认EN翻译
      let lang = translateState?language:'EN';

      let a = $.i18n.init({
        lng: language, //指定语言
        useCookie:false,
        resGetPath: './assets/translate/'+lang+'/html.json',//语言包的路径
      }, function(err, t) {
        if(!err){
          $('[data-i18n]').i18n(); // 通过选择器集体翻译
          return;
        }
        goby.showErrorMessage(err)
      });
    }

    lang();
    
    //当lang改变时更新页面内容
    goby.bindEvent('on changeLang',()=>{
      lang();
    })

    function getAssetData(data) {
      if (data.statusCode == 200) {
        let ipinfo = data.data.ips

        //获取OS类型
        ipinfo.forEach((v, k) => {
          if (v.protocols) {
            for (var i in v.protocols) {
              if (v.protocols[i].protocol.search("dcerpc") != -1 && v.protocols[i].product.search("Windows") != -1) {
                ostypes.push(v.protocols[i].product);
              }
            }
          }
        });
        ostypes = unique(ostypes);

        //根据OS类型生成dic
        for (var i in ostypes) {
          osinfo[ostypes[i]] = [];
        }

        //根据OS类型匹配对应的IP
        for (var key in osinfo) {
          ipinfo.forEach((v, k) => {
            if (v.protocols) {
              for (var i in v.protocols) {
                if (v.protocols[i].protocol.search("dcerpc") != -1 && v.protocols[i].product == key) {
                  osinfo[key].push(v.protocols[i].hostinfo.split(":")[0]);
                }
              }
            }
          });

        }

        //输出数据

        for (var os in osinfo) {
          let ips = osinfo[os];
          let nums = osinfo[os].length;
          let tds = "";
          for (var ip in ips) {
            tds += ips[ip] + "</br>";
          }


          html += `<tr>
          <td>${os}</td>
          <td>${tds}</td>
          <td>${nums}</td>
          </tr>`;
        }
        $("#os-table tbody").html(html);

      }
    }
</script>
</body>

</html>

最后输出结果如下:

7.png

0×03 小结


此次通过编写一个简单的插件,对 Goby 的插件编写有了一定了解和认识,并且从中收获了不少 js 的知识,也感谢 @go0p 师傅的指导;在编写过程中也发现 Goby 扫描的结果需要更加完善,目标是在 FOFA 找到的,FOFA 有的能识别出系统是 Windows 2000 或者 Windows 10 等,但是 Goby 好像只能识别出 2008 和 XP,其实 Goby 部分扫描结果是有识别到 Windows 的 NT 版本号的,根据版本号的范围也可以对系统做一个初步的判断,这个只是一个小 bug,可能需要以后版本更新去对一些规则进一步完善,希望 Goby 功能越来越强大,插件越来越丰富,gogo!


插件开发文档及Goby开发版下载:

https://gobies.org/docs.html

关于插件开发在B站都有详细的教学,欢迎大家到弹幕区合影~

如果表哥/表姐也想把自己上交给Goby社区(获取红队专版),戳这里领取一份插件任务?

https://github.com/gobysec/GobyExtension/projects


文章来自Goby社区成员:socatos,转载请注明出处。

下载Goby内测版,请关注微信公众号:GobySec

下载Goby正式版,请关注网址:https://gobies.org

最新评论

昵称
邮箱
提交评论