0
点赞
收藏
分享

微信扫一扫

【无标题】转载Melting Ice-用几个简单的步骤跟踪IcedID服务器

kmoon_b426 2022-01-26 阅读 17

[翻译]Melting Ice-用几个简单的步骤跟踪IcedID服务器 只看楼主1#梦幻的彼岸收藏2021-9-12 17:03:18备注原帖地址:https://research.checkpoint.com/2021/melting-ice-tracking-icedid-servers-with-a-few-simple-steps/原帖标题:Melting Ice – Tracking IcedID Servers with a few simple steps原帖信息:May 26, 2021 Research by: Alex Ilgayev简介追踪僵尸网络通常需要大量的努力、时间和威胁情报知识。如果是多阶段的复杂恶意软件家族,如IcedID、Emotet和QakBot,跟踪的难度就更大了。因此,作为恶意软件分析师,我们倾向于寻找尽可能多的自动化过程–收集大规模的样本,识别它们,提取它们的配置,然后让这些产生我们感兴趣的价值,如更清晰的威胁情报图片或更最新的域信誉引擎。虽然恶意软件分析的生活往往像上面描述的那样困难,但它不一定是这样。有时,如果我们很聪明,10%的工作会得到我们感兴趣的90%的结果。在这篇文章中,我们展示了这样一个巧妙的方法,并展示了如何快速跟踪IcedID C&C服务器,并且不需要跟踪或分析任何样本。IcedID背景IcedID banker恶意软件最早出现于2017年9月,此后取得了重大进展。这种威胁,也被称为BokBot,在过去的一年中不断增长,并拥有广泛的恶意功能,如浏览器拦截,凭证盗窃,MiTM代理设置和VNC模块等。Malwarebytes、Group-IB和Binary Defense过去的出版物对该僵尸程序的内部功能,包括感染链和恶意组件进行了彻底描述。根据二进制防御研究人员提出的最新感染链,最近迭代的IcedID包含三个恶意组件–包含恶意宏的进入点DOC/XLS;一个第一阶段的payload;以及最后一个第二阶段的payload,它本身由两个子部分组成–一个64位DLL加载器,以及被伪装成".dat "文件的加密的实际僵尸程序。每个第二阶段的payload通常包含2-4个独特的嵌入式域名,这些域名都可以解析到同一个IP地址。假设我们设定一个目标,跟踪这些域名/IP并阻止它们;自然,我们对最快速和无痛的方式感兴趣。受害者的通信协议是HTTPS,所以我们检查了捆绑的TLS证书。正如我们在下面观察到的,IcedID的人更关心RSA-2048提供的硬性具体保证,而不太关心遵循安全准则;该证书签发给默认名称为“ Internet Widgits Pty,Ltd”的机构,该机构位于“某个州”。IcedID C&C证书样本:如果我们把这个IcedID证书和一个默认的自签名证书进行比较,最明显的区别是通用名称字段。公共服务器的FQDN(例如)应该在这个字段中出现,而不是像本例中的Checkpoint.comlocalhost那样。你可能明白这是怎么回事;我们立即开始扫描广泛的网络,寻找其他呈现这种证书的服务器。枚举服务器我们不愿重复发明,选择使用流行的互联网扫描平台Censys来创建一份潜在的C&C候选人名单。像Shodan这样的其他网络扫描平台也可以用于此目的。Censys引擎为我们提供了大量的证书查询控制。经过一些调整和调整,我们构造了以下查询:443.https.tls.certificate.parsed.issuer_dn: “CN=localhost, C=AU, ST=Some-State, O=Internet Widgits Pty Ltd” and 443.https.tls.certificate.parsed.subject_dn: "CN=localhost, C=AU, ST=Some-State, O=Internet Widgits Pty Ltd"Censys的证书结果之一:如果您怀疑在证书中使用通用名称的唯一性,可以通过一个简短的实验轻松地证明这一点:我们搜索到的几十个服务器看起来似乎很多,但如果您在搜索查询中省略了要求,结果将在千分之一的大小和数量上爆炸式增长:localhostCN=localhost目前,我们不能假设这些服务器中的每一个都是活动的IcedID恶意C&C,所以我们需要验证它们。幸运的是,这是可能的,这要归功于我们在研究过程中发现的另一种独特的特性。验证服务器当我们对僵尸程序的功能进行逆向工程时,我们注意到僵尸程序在与C&C服务器通信之前做了一个相当有趣的测试。下面的代码是一个回调函数的一部分,在与C&C.WinHttpSendRequest联系之前被调用。证书验证代码:简单地说,这段代码在证书的公钥上运行Fowler-Noll-Vo 32位哈希函数,并将其与证书的指定序列号进行比较。只有当比较结果吻合时,通信才会继续进行(或用XOR-ed值)。0x384A2414证书序列号字段由证书颁发机构分配,并为每个生成的证书提供一个唯一的标识符。证书颁发者必须确保没有两个具有相同证书颁发者DN的不同证书包含相同的序列号,但没有人能够保证这一点。在我们的案例中,证书是自签的,恶意软件运营商根据上述逻辑唯一地分配其C&C序列号字段。自己使用这种验证算法,针对一个可疑的服务器,我们可以确保它是IcedID基础设施的一部分。我们在附录A中提供了一个简单的python脚本来验证这个逻辑,针对一个提供的远程服务器。应用该方法,我们发现之前的大多数潜在结果都与IcedID有关,并将名单缩小到52个服务器。考虑到独特的证书属性和不常见的哈希函数,我们可以安全地推断这些服务器是IcedID C&C基础设施中的组成部分。有了这个名单,我们去仔细查看了这些服务器。服务器分析通过分析他们面向互联网的标语,我们可以发现大多数部署的服务器有几个类似的属性。最常见的属性是开放端口、操作系统和网络服务器。开放的端口 - 所有的服务器都有443端口,94%的服务器还监听80端口,77%的服务器监听SSH端口(22)。操作系统 - 77%的服务器运行的是Debian操作系统。网络服务器 - 94%的服务器运行nginx网络服务器。我们还可以看到,大多数的服务器居住在罗马尼亚、美国和德国。IcedID服务器的位置:另一个分析角度是通过被动DNS服务,如RiskIQ。使用这种服务使我们能够为我们拥有的每个IP地址找到相关的域,并扩大我们的威胁情报图片。这些额外的域在逻辑上必须嵌入一些我们无法直接访问的样本中。例如,我们发现的一个地址是 ,它未解析到以下IcedID域:152[.]89.247.60formgotobig[.]topponduroviga[.]toptranmigrust[.]clubaswenedo[.]space总结一个可悲的事实是,做 "正确的事情 "可能会适得其反。IcedID活动的维护者就是这种情况;他们制作了一个自签名的证书,并让他们的恶意操作支持HTTPS,这是一个值得称赞的努力,绝大多数恶意软件都不屑一顾,甚至一些长期运行的合法网站在很长一段时间内也不屑一顾。通过这样做,他们使煽动敌意接管他们的网络变得更具挑战性–但他们也使他们所有的服务器基本上以欢快的 "嗨,我是一个恶意的C&C "来回应标准扫描服务。一旦这些服务器被暴露,我们就能持续追踪它们,分析它们的行为,而不需要运行正则表达式,更不用说启动调试器或反汇编器。对于运行恶意活动的人来说,这是一个噩梦般的场景;他们的目的是将不断更新的C&C服务器列表中的 "奖品 "放在遥不可及的地方,放在层级列表的顶端。相反,由于这种太过聪明的TLS业务,收集服务器(并获得一堆多汁的信息,这不在本文的范围之内)变得在分析师的能力范围之内,只要有一周的经验。正如一位智者曾经说过的,在使用一种技术之前要先思考,否则你的对手会用它来对付你。IOCIcedID C&C servers:83[.]97.20.24983[.]97.20.174194[.]5.249.5245[.]153.240.135194[.]5.250.104152[.]89.247.6091[.]193.19.97194[.]5.249.8183[.]97.20.73194[.]5.250.3583[.]97.20.176194[.]5.250.46212[.]114.52.18691[.]193.19.3745[.]147.231.113188[.]119.148.75185[.]38.185.9045[.]138.172.17991[.]193.19.5183[.]97.20.122194[.]5.249.103139[.]60.161.63194[.]5.249.86139[.]60.161.48185[.]33.85.35194[.]5.249.9779[.]141.164.241194[.]5.249.90193[.]109.69.52194[.]5.249.54185[.]70.184.8779[.]141.166.39146[.]0.77.9231[.]184.199.1145[.]129.99.241194[.]5.249.46185[.]123.53.202146[.]0.77.1831[.]24.228.17045[.]147.230.8883[.]97.20.25445[.]147.230.82194[.]5.249.7246[.]17.98.19145[.]153.241.115185[.]70.184.41139[.]60.161.50194[.]5.249.14379[.]141.161.1765[.]149.252.17945[.]147.228.19891[.]193.19.251附录A测试一个服务器的IcedID证书:import idnafrom socket import socketfrom OpenSSL import SSLfrom cryptography.hazmat.primitives.serialization import Encodingfrom cryptography.hazmat.primitives.serialization import PublicFormatdef fnv1a_32(data: bytes) -> int: “”“Fowler–Noll–Vo hash function variation. Args: data (bytes): Input data Returns: int: Output 32 bit hash “”” hval_init = 0x811c9dc5 fnv_prime = 0x01000193 fnv_size = 2 ** 32 hval = hval_init for byte in data: hval = hval ^ byte hval = (hval * fnv_prime) % fnv_size return hvaldef get_certificate(hostname: str, port: int): “”“Connects to the remote server, and retrieves the certificate. Args: hostname (str): Remote hostname port (int): Remote port (usually 443) Returns: Certificate object “”” hostname_idna = idna.encode(hostname) # We are building a SSL context on top of a raw socket. sock = socket() sock.connect((hostname, port)) ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.check_hostname = False # the cert is self-signed so we don’t want to verify it ctx.verify_mode = SSL.VERIFY_NONE # making SSL handshake sock_ssl = SSL.Connection(ctx, sock) sock_ssl.set_connect_state() sock_ssl.set_tlsext_host_name(hostname_idna) sock_ssl.do_handshake() # retrieving certificate and converting it to an cryptography object cert = sock_ssl.get_peer_certificate() crypto_cert = cert.to_cryptography() sock_ssl.close() sock.close() return crypto_certdef test_is_icedid_c2(hostname: str, port: int) -> bool: “”“Testing whether a remote server is part of IcedID C&C infrastructure. Args: hostname (str): Remote hostname port (int): Remote port (usually 443) Returns: bool: True if the server is IcedID verified, or False otherwise. “”” try: # We query the server and retrieve its certificate. cert = get_certificate(hostname, port) serial_number = cert.serial_number # Getting the public key, and hashing it. public_key = cert.public_key().public_bytes(Encoding.DER, PublicFormat.PKCS1) fnv_hash = fnv1a_32(public_key) & 0x7fffffff # Finally comparing the hash to the serial number. if serial_number == fnv_hash or serial_number == fnv_hash ^ 0x384A2414: return True except Exception as e: return False return False

举报

相关推荐

0 条评论