TL;DR: 234 functions of three Fuzzbunch libraries are compiled into a Stuxnet DLL that interact with structures and core functionality of tibe-1, trch-0 and trfo-0. This leads to the conclusion that the developers of the Equation Group and Stuxnet share the same code-base or at least have access to the same code.

Intro

While working on the Lost in Translation leak of Shadow Brokers I noticed a constant that was unknown to me so I googled for it and came across the repository of Laurelai containing the output of the Hex-Rays decompiler for a Stuxnet support DLL. Searching for the MD5 hash leads to a presentation by McAfee about the composition of Stuxnet.

Since I didn’t had access to that sample (335707eabbe7ff256e0650432accec9b) I was glad that J-Michael Roberts provided me access to VirusShare to retrieve the sample and continue my research.

Findings

By diffing the tibe-1.dll included in Fuzzbunch with the sample above, 192 functions matched with a ratio of 1.0 (100 %). A very unlikely score given the fact that most matched functions are custom functions that are used for staging attacks/ checks in the Fuzzbunch framework. One of the central functions of tibe-1.dll, the main focus of my Fuzzbunch research at the time, is TbInitStruct. It initializes a structure that holds all information regarding a target, the necessary signatures that are used to impersonate different Windows (or Samba) versions, signing, SMB constants, local and remote sockets, etc. The same function is also present in the Stuxnet code.

The following figure shows the diff of the pseudo-code. The differences are mostly due to the fact that the tibe-1.dll had some early structure information applied.

Diffing of TbInitStruct/sub_10007D20
Diffing of TbInitStruct/sub_10007D20 - cont.

Another very good example is TbDoSmbNtWriteAndX, responsible for writing SMB payload data to the supplied socket.

Diffing TbDoSmbNtWriteAndX/sub_10011150

After these initial findings I wanted to see how many other utility functions available in the Fuzzbunch lib-folder are present in my Stuxnet sample. To archive this without spending too much time on analyzing every file by hand Diaphora in combination with IDA’s batch-mode was used to create databases of all DLLs. These were then used to create diff-databases. In the end two other DLLs could be identified that are used in Fuzzbunch to parse parameters and provide cryptographic functionality that are also used in Stuxnet.

The following figure shows matching functions of trch-0.dll that is responsible for parameter parsing in Fuzzbunch - and apparently in this Stuxnet sample.

*Fuzzbunch* DLL `trch-0.dll`.

trfo-0.dll provides cryptographic functions that are used in Fuzzbunch e.g. in different touches.

*Fuzzbunch* DLL `trfo-0.dll`

Conclusion

Due to the fact that a large number of functions (234 functions from three DLLs) are used within the Stuxnet sample that interact with structures and core functionality of tibe-1, trch-0 and trfo-0. One can easily assume, given these circumstances, that the developers have access to the same code-base or at least share common modules to ease development of different implants.

Thanks

Thanks to J-Michael Roberts of VirusShare/@VXShare for providing me access to VirusShare and the Stuxnet sample.

Artifacts

  • 335707eabbe7ff256e0650432accec9b
    • Component of: Stuxnet
    • File Type: Win32 DLL
    • MD5: 335707eabbe7ff256e0650432accec9b
    • SHA-1: e511b76d143c525c1f52f520343d80dba992d0ea
    • SHA-256: 0b2322a002ae21a7f31d57683a39fe114df35dd45ff7c4a2e78aa84dc25df8a4
    • SSDeep: 3072:cjOhJaBJV5dLmsU/CqqtZGSSpxjznUwivJdba12d0LUI3JG:6JVD6sUq5Dde2dh
  • tibe-1.dll
    • Component of: Fuzzbunch (Source: ShadowBroker Leak - Lost In Translation)
    • File Type: Win32 DLL
    • MD5: f0881d5a7f75389deba3eff3f4df09ac
    • SHA-1: 8404f2776fa8f7f8eaffb7a1859c19b0817b147a
    • SHA-256: ca63dbb99d9da431bf23aca80dc787df67bb01104fb9358a7813ed2fce479362
    • SSDeep: 3072:GQng3MAngh6CNXfdUrYSaocn484kQL93ZnV6Bbf5+1qo3/mlch9VQ816oPYQ3:GwkQf4q481Qx3hV6Bbf5+1qbch9V91J
  • trch-0.dll
    • Component of: Fuzzbunch (Source: ShadowBroker Leak - Lost In Translation)
    • File Type: Win32 DLL
    • MD5: 8b0a4ce79f5ecdb17ad168e35db0d0f9
    • SHA-1: ea659a9385e8b208d06b052bf4eca5109b3bc423
    • SHA-256: 6775d627d99733f3f02494db7e13935b505132f43c56e7f8850c54e6627691de
    • SSDeep: 1536:dPKqcRQ5TrJWq2nuWL4ehllExwvtpXuA:dCqQQ5TrJWqcuWL4+llGwvtpXuA
  • trfo-0.dll
    • Component of: Fuzzbunch (Source: ShadowBroker Leak - Lost In Translation)
    • File Type: Win32 DLL
    • MD5: 46f7b320b13a4b618946042360215179
    • SHA-1: 5b8606d26481bbbe805e495ebee6f24ebd4d8a73
    • SHA-256: a4c460b27d03daf7828f6b6db87e0ff3ee851fdb1b8654b0a778b4c34953a3dc
    • SSDeep: 768:8oLW2YiMFWwTbUYqLuvQgog+muxf6gR8psflVv7HN+bVi:8iATbUYqLuIgr+fipUVEVi

Scripts

diaphora-auto.cmd

Command Line: diaphora-auto.cmd [bin] [sqlite-output-file]

set DIAPHORA_AUTO=1
set DIAPHORA_EXPORT_FILE=%2
set DIAPHORA_USE_DECOMPILER=1
"C:\apps\IDA\ida.exe" -A -B -SC:\apps\diaphora-master\diaphora.py "%1"

diaphora-diff.cmd

Command Line: diaphora-diff.cmd [diff-sqlite] [primary-file] [secondary-file]

C:\Python27\python.exe C:\apps\diaphora-master\diaphora.py -o "%1" "%2" "%3"

diaphora-diff-export.py

Command Line: diaphora-diff-export.py [diff-file] ([diff-file]...)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" diaphora-diff-export.py

    Create an overview of the input Diaphora diffs 
    and export the results to csv.

    Author: marpie ([email protected])

    Last Update:  20180103
    Created:      20180103

"""
import os
import sqlite3
import csv

# Main
def main(argv):
    if len(argv) < 2:
        print("diaphora-diff-export.py [diff-file] ([diff-file]...)")
    for filename in argv[1:]:
        print("[*] File: {}".format(filename))
        csv_filename = os.path.splitext(filename)[0] + ".csv"
        conn = sqlite3.connect(filename)
        cur = conn.cursor()
        print("  [+] Overview:")
        for row in cur.execute('SELECT type, COUNT(*) AS `count` FROM results GROUP BY type;'):
            print('    ' + ': '.join([str(e) for e in row]))
        print("  [+] Exporting...")
        with open(csv_filename, "w", newline='') as f:
            writer = csv.writer(f)
            #writer.writerow(['Column 1', 'Column 2', ...])
            writer.writerows(cur.execute("SELECT * FROM results"))
        print("  [+] Done.")
    return True

if __name__ == "__main__":
    import sys
    print( __doc__ )
    sys.exit( not main( sys.argv ) )

Perfectly matched functions

Boolean_marshal
Paramchoice_addParamgroup
Paramchoice_create
Paramchoice_delete
Paramchoice_isValid
Paramchoice_setValue
Parameter_Boolean_getValue
Parameter_delete
Parameter_getType
Parameter_hasValidValue
Parameter_hasValue
Parameter_IPv4_getValue
Parameter_isValid
Parameter_LocalFile_getValue
Parameter_markInvalid
Parameter_matchFormatAndType
Parameter_matchName
Parameter_S16_getValue
Parameter_S32_getValue
Parameter_S32_setValue
Parameter_S8_getValue
Parameter_S8_setValue
Parameter_setMarshalledValue
Parameter_Socket_getValue
Parameter_String_getValue
Parameter_U16_getValue
Paramgroup_addParameter
Paramgroup_create
Paramgroup_delete
Paramgroup_isValid
Paramgroup_matchName
Params_addParamchoice
Params_addParameter
Params_create
Params_delete
Params_findParamchoice
Params_findParameter
Params_getCallbackPortValues
Params_validateCallbackPorts
S32_marshal
TbB1size
TbB2size
TbBuffCpy
TbCheckActid
TbCheckSecuritySignature
TbCleanSB
TbCloseSocket
TbCloseStructSockets
TbConvWhoAreYou2_makeresp
TbConvWhoAreYou_makeresp
TbConvWhoAreYou_parserequest
TbConvWhoAreYouAuth_makeresp
TbConvWhoAreYouAuthMore_makeresp
TbCopyBuffStrToUniBuffStr
TbCreateActid
TbDealWithDecryption
TbDealWithEncryption
TbDealWithNtlmEncryption
TbDoAuth3
TbDoBind
TbDoNbtSessionRequest
TbDoRpcBind
TbDoRpcRequest
TbDoSmbChangeShare
TbDoSmbLogoffAndX
TbDoSmbNegotiate
TbDoSmbNtCreateAndX
TbDoSmbNtReadAndX
TbDoSmbNtSessionSetupAndX
TbDoSmbNtWriteAndX
TbDoSmbPacket
TbDoSmbSendData
TbDoSmbSessionSetupAndX
TbDoSmbStartup
TbDoSmbStartupEx
TbDoSmbTransactionNamedPipe
TbDoSmbTreeConnectAndX
TbDoTcpReq
TbDoTcpSendRecv
TbDoUdpReq
TbFillUdpHdr
TbFixSmbSecuritySignature
TbFreeStructBuffers
TbGetArg
TbGetAuthTrailerTcp
TbGetAuthVSize
TbGetBindAckRpc
TbGetBuff
TbGetByte
TbGetCurrentTime
TbGetFaultRpc
TbGetNSH
TbGetNtlmAuthVerifier
TbGetProtocolLegCount
TbGetReplyRpc
TbGetRequestRpc
TbGetSmbHeader
TbGetSRpc
TbGetStringValue
TbGetSyntax
TbGetTcpStub
TbGetUdpHdr
TbGetUdpStub
TbGetUuid
TbInitNtlmCrypto
TbInitStruct
TbMakeAlterCtx
TbMakeAuth3
TbMakeAuthVerifier
TbMakeBind
TbMakeBlob1
TbMakeBlob3
TbMakeLogoffAndX
TbMakeNbtSessionRequest
TbMakeNegotiate
TbMakeNetlogonAuthVerifier
TbMakeNtCreateAndX
TbMakeNtExtSessionSetupAndX
TbMakeNtlmAuthVerifier
TbMakeNtlmBlob3
TbMakeNtReadAndX
TbMakeNtSessionSetupAndX
TbMakeNtWriteAndX
TbMakeServerSocket
TbMakeSessionSetupAndX
TbMakeSmbHeader
TbMakeSnegoBlob3
TbMakeSocket
TbMakeTcpReq
TbMakeTransactionNamedPipe
TbMakeTreeConnectAndX
TbMakeUdpFack
TbMakeUdpReq
TbMakeUdpResp
TbMakeUNDHeader
TbMalloc
TbNetlogonB1size
TbNtlmB1size
TbNtlmB3size
TbNTLMSSPOWFencrypt
TbParseBlob2
TbParseNtlmBlob2
TbPrintNetlogonBlob2Info
TbPutAlign
TbPutArg
TbPutAuth3
TbPutAuthTrailerTcp
TbPutBindRpc
TbPutBlob1
TbPutBlob3
TbPutBuff
TbPutByte
TbPutContexts
TbPutFackHdr
TbPutListHdr
TbPutLong
TbPutNetlogonAuthVerifier
TbPutNetlogonBlob1
TbPutNSH
TbPutNtCreateX
TbPutNtlmAuthVerifier
TbPutNtlmBlob1
TbPutNtlmBlob3
TbPutNtReadX
TbPutNtWriteX
TbPutOrpcThis
TbPutPadding
TbPutRequest
TbPutShort
TbPutSmbHeader
TbPutSnegoBlob1
TbPutSnegoBlob3
TbPutSRpc
TbPutStr
TbPutStrAsLEUni
TbPutSyntax
TbPutUdpHdr
TbPutUdpNetbiosHeader
TbPutUniBuff
TbPutUuid
TbReadSmbHeader
TbReadSmbNegResp
TbReadSmbNtCreateAndXResp
TbReadSmbNtExtSessionSetupAndXResp
TbReadSmbNtNegResp
TbReadSmbReadAndXResp
TbReadSmbSessionSetupAndXResp
TbReadSmbTransactionResp
TbReadSmbTreeConnectAndXResp
TbReadSmbWriteAndXResp
TbRecv
TbRecvFrom
TbRecvSmb
TbRecvTcp
TbRecvUdp
TbResetPointer2k3Base
TbResetStruct
TbSend
TbSendTo
TbSetCallbackSocketData
TbSetRemoteSocketData
TbSMBOWFencrypt
TbSnegoB1size
TbSnegoB3size
TbSnegoB4size
TbToLower
TbUniToUtf8
TbUtf8ToUni
TbUuidToStr
TbWaitServerSocket
TbWinsockCleanup
TbWinsockStartup
TbWipeInterfacePtrs
TbWstrSize
TbWstrToStr
TcpPort_type
TfCrc32
TfHmacMd5Final
TfHmacMd5Init
TfMd4
TfMd5Final
TfMd5Init
TfMd5Update
TfRandomByte
TfRandomInt
TfRandomizeBuffer
TfRc4Encrypt
TfRc4Init
TfStrcasecmp
TfXorBuffer
U32_marshal
UdpPort_type
UString_List_marshal
UString_marshal

About this site // disclaimer

This is my personal blog. The views expressed on these pages are mine alone and not those of my employer or former employers. As with time views may change and become outdated and even invalid and therefore may not represent my current views. All information is provided as-is. If not otherwise stated the content is provided under the 2-clause BSD License.

Follow me on Twitter @markus_pieton