暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

DCERPC协议使用初探

我在人间读安全 2022-03-13
9062



前言

       一年前,我读到过这样一篇文章,是白帽汇赵武大佬写的,里面答题介绍的内容是关于协议识别-DCERPC(),我看后觉得深有感触,一直想好好学习下,无奈事情太多,这一拖就是一年,今天又看到了类似的文章,所以今天下定决心要搞清楚。

        赵武大佬文章里有这样一句话“识别所有应该识别的协议,收集所有世界上存在的软硬件指纹规则,录入所有能够被利用的网络类漏洞exp”,那么DCERPC协议我认为就是实现这个目标路上的基石。

        今天看到了某位研究员的两篇文章,提到了协议相关内容并做了很不错的实践,分享给大家

    https://nosec.org/home/detail/4709.html
    https://payloads.online/archivers/2020-07-16/1/
    https://payloads.online/archivers/2022-03-04/1/

    协议介绍

           首先我们理解下RPC协议,百度百科解释非常简单,大体可理解为RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

            去年爆火的漏洞,CVE-2021-1675(Windows Print Spooler 远程命令执行漏洞),也是在调用rpc函数时产生了漏洞导致。

            dcerpc协议,是非常基础的Windows系统的通信协议,它比rdp协议更普遍,默认开启。由于内容丰富,接口众多,早期的安全人员基于它写了很多蠕虫病毒,一度让微软和运营商非常头疼。dcerpc的默认端口是135,上面承载了包含wmi,有认证就有ntlmssp,还有epmapper等一系列丰富的系统信息,甚至还能获取网卡IP地址列表。(来源网络空间测绘核心技术之:协议识别(DCERPC篇))

            

    应用场景

           作为在安全行业从业人员来讲,我会对decrpc能获取到的信息感到震惊,因为就单单能获取网卡IP地址列表来讲,就有如下两种常见需求:

    1. 企业运营角度:终端/服务器都有哪些是单网卡/双网卡/多网卡,有哪些终端/服务器违规外联了?

    2. 红队攻击角度:什么?我能获取到主机网卡IP地址?听说还可以不用认证?信息收集很不错(其实部分工具已经实现了该协议的利用)em……还能探测是否连接互联网(能不能出网太关键了)

           本文以这两种角度谈谈实现方式。

    基础知识

          本文可能会用到impacket库,impacket是一个出色的Python类库,用于处理网络协议的Python类的集合,专注于提供对数据包的简单编程访问。

      https://github.com/SecureAuthCorp/impacket

      获取网卡信息

      OXIDResolver接口

      该接口是无需授权的,可以通过调用ServerAlive2,得到目标系统网卡的所有IP地址。

      代码实现最关键的是通过DCERPCTransportFactory获取transport对象,然后确定需要绑定的RPC的协议序列,关于协议序列点击。

      代码实现一(使用impacket)

        #coding=utf-8
        from impacket.dcerpc.v5 import transport
        from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_NONE as authLevel
        from impacket.dcerpc.v5.dcomrt import IObjectExporter


        def getinfo(ip):
        stringBinding = r'ncacn_ip_tcp:%s' % ip
        rpctransport = transport.DCERPCTransportFactory(stringBinding)
        dceinfo = rpctransport.get_dce_rpc()
        dceinfo.set_auth_level(authLevel)
        dceinfo.connect()


        objExporter = IObjectExporter(dceinfo)
        bindings = objExporter.ServerAlive2()


        print("[*] 正在通过dcercp探测"+ip+"信息…… ")
        for address in bindings:
        NetworkAddr = address['aNetworkAddr']
        print("info: " + NetworkAddr)


        if __name__ == '__main__':
        ip = input("请输入IP地址: ")
        getinfo(ip)

        代码实现二(不使用impacket)

          https://github.com/Rvn0xsy/OXID-Find/

          探测是否连接互联网

                连接互联网的主机一定是攻击者最关注的,同样也是企业运营者最注意防护的。

                  探测实现代码大佬已经给出了

            https://payloads.online/archivers/2022-03-04/1/

            作者给出的思路是:

            脚本执行--->被探测主机访问给定地址--->给定主机抓包查看

            那么可以仿照设计:

            脚本执行--->被探测主机访问dnslog--->产生记录--->证明主机出网。

            代码实现:

              #coding=utf-8
              import sys
              from impacket.dcerpc.v5 import rprn
              from impacket.dcerpc.v5.dtypes import NULL
              from impacket.dcerpc.v5 import transport


              TS = ('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0')
              IFACE_UUID = rprn.MSRPC_UUID_RPRN


              def findnetwork(user,passwd,dnslog,flag):
              username = user # 用户名
              password = passwd # 密码
              domain = ''
              lmhash = ''
              nthash = ''
              rpctransport = transport.DCERPCTransportFactory(r'ncacn_np:'+flag+r'[\pipe\spoolss]')
              rpctransport.set_credentials(username, password, domain, lmhash, nthash)
              dce = rpctransport.get_dce_rpc()
              dce.connect()
              dce.bind(IFACE_UUID, transfer_syntax=TS)
              request = rprn.RpcOpenPrinter()
              target_url = "http://"+flag+"."+dnslog
              request['pPrinterName'] = '%s\x00' % target_url
              request['pDatatype'] = NULL
              request['pDevModeContainer']['pDevMode'] = NULL
              request['AccessRequired'] = rprn.SERVER_READ
              try:
              dce.request(request)
              except:
              pass
              if rpctransport:
              rpctransport.disconnect()


              if __name__ == '__main__':
              ip = sys.argv[1]
              user = sys.argv[2]
              passwd = sys.argv[3]
              dnslog = sys.argv[4]
              findnetwork(user,passwd,dnslog,ip)
              print(ip+" end!")

              执行

              批量检测回头放出~


              容易出现的问题:

              如果出现impacket.dcerpc.v5报错,可以重新安装

                pip3 uninstall impacket
                git clone https://github.com/cube0x0/impacket
                cd impacket
                python3 ./setup.py install


                文章转载自我在人间读安全,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                评论