HOME> 世界杯谁是冠军> 中国蚁剑源码分析

1 前言发现很多同学对于蚁剑的基本流程还有源码结构不太熟悉,所以就有了这一篇比较基础的文章,来讲一讲自己对于蚁剑的一些认识。

通过阅读本篇文章,你可以了解蚁剑的源码结构、运行流程、以及自己动手diy时要注意的几个地方。

2 正文

2.1 目录结构

1

2

3

4

5

6

7

8

9

10

11

12

13

/antData/ 用户目录

/modules/ 蚁剑后端模块

/node_modules/ 安装的node模块

/source/ 核心模块

/base/ 自定义的功能类

/core/ payload模板

/language/ 语言模块

/modules/ 显示模块

/ui/ UI模块

/app.entry.js 渲染程序入口

/load.entry.js 前端加载模块

/static/ 静态资源文件

/views/ 前端文件

其中最核心的是modules目录跟source目录。modules里的内容为蚁剑的后端模块,属于主进程。source中存放着蚁剑运行的核心代码,属于渲染进程。

2.2 如何debug蚁剑的开发栈主要是:javascript / nodejs / electron。

Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。通过Node它提供了通常浏览器所不能提供的能力。

简单来说就是chrome里跑nodejs。

所以想要对蚁剑二次开发,要首先熟悉一下nodejs的基本语法。

electron里面又分主进程跟渲染进程,对于主进程的调试需要用到vscode等,而对于渲染进程只需要用到蚁剑中自带的dev tool就可以。具体可以看这篇文章:https://blog.csdn.net/gary_yan/article/details/78973336

一般来说,我们并不需要对modules中的后端模块进行修改,所以一般不会用到主进程调试,仅仅蚁剑中自带的dev tool就可以完成我们日常的调试工作。

打开蚁剑->调试->开发者工具即可看到调试工具。

是不是跟chrome一模一样?

其中console用于打印输出日志,蚁剑中默认的日志只会打印前100个字符,如果要查看完整日志需要输入antsword.logs[id]查看,在这里我们直接查看所有日志。

我们先连接上本地的shell,然后打印完整日志,就可以看到我们发包的很多参数,包括shell的配置, 编码器设置,字符编码,返回内容等等

那么我们在哪里下断点呢

答案是在控制台sources->no domain下面,打开后我们可以看到渲染进程中加载到的各种资源、模块

然后我们找到想下断点的文件,就拿php的base64编码器为例,在其10行处点击一下会出现蓝标,就表示下断点成功。

此时我们在shell管理界面右键->刷新目录,就可以看到程序已经断到了我们下断点的地方,在右边可以看到此时的调用栈还有各种变量信息,就可以愉快的调试了。

2.3 执行流程

主程序入口:app.js

/source/load.entry.js 前端加载模块

/source/app.entry.js 渲染程序入口

/source/modules/filemanager/index.js 监听用户操作

/source/core/php/template/ 提取组合Payload

/source/core/base.js 发送事件与配置到后端request模块

解析、回显

就按刚才php base64编码器为例,我们看一下蚁剑是如何运行到这一步的。

查看上一个调用栈,发现是进入到了编码器处理部分,编码器会接收到三个参数:shell密码、初步payload、还有ext参数。

其中ext参数即为shell的配置信息还有rsa对象的组合,这也是为什么我们在写编码器的时候可以直接获取到shell的各种配置信息。

再往上看,发现complete函数调用了encodeComplete函数,complete负责将payload套入到模板中,并且设置数据前后分割符,发送给encodeComplete进行处理。

再进入到core/base中的request函数,此函数负责将组合完成的数据包发送到后端的request模块。

那么是如何触发到这个请求功能的呢,我们直接跳到最开始的点击事件来看。

发现是当我们点击刷新目录后,会触发refreshPath函数。

然后refreshPath函数分析是否有传递的路径参数,如果没有则为刷新当前目录。

然后gotoPath调用了this.manager.getFiles函数。

getFiles函数调用this.core.request,第一个参数为this.core.filemanager.dir,即为payload模板中的dir部分。

接着组合、发送payload数据包,获取回显并解析。

其中解析跟回显部分不是我们关注的重点,我们关注的重点主要是提取组合payload到发送最终数据包的阶段。大家自己调试一下就明白其中的流程了。

2.4 修改数据包的几个重点位置其中,如果要修改发送的数据包,有三个位置可以供我们参考。

\source\core\base.js#187 模板组合(作用对象为全体)

\source\core\php\encoder\base64.js 编码器处理(作用于当前类型)

\modules\request.js 最终发包(不建议修改)

不建议修改后端最终发包是因为蚁剑中后端默认不能获取到所有的opt配置内容,除非自己加,我觉得比较麻烦。

2.5 配合opt参数实现自定义设置opt参数中有shell的所有配置,通过此项可以做到动态修改数据包的内容。比如说我在基于随机Cookie的蚁剑动态秘钥编码器中就是利用ext.opts.httpConf.headers['Cookie'] = xxx在数据包头部添加了一个cookie作为秘钥

在编码器中要用ext.opts.xxx来访问你想要访问的配置内容,在其他地方一般用this.__opts__.xxx或者opts['xxx']即可。

3 最后在实现蚁剑jsp一句话的过程中,我使用了额外传递参数的方式来决定采用什么编码器、什么字符编码等。大家可以看一下我在编码器中的写法。

这个方法是挺简单,但是特征也比较明显。那么怎么办呢?

相信你读完这篇文章后已经可以试着自己去改掉这个特征,有好的想法欢迎跟我交流。