Saturday, December 16, 2017

Impacket part 1: psexec.py

As a SOC analyst we are often tasked with finding out either pentester or malicious
 activity that occurs in the monitored environment and creating signatures for
 these findings. In a recent pentesing engagement (after of course running freely in the
 network), they shared that they used the Impacket tools for much of their movement. 
This short series will be analyzing some of the various tools offered in the
Impacket set. Through this analysis we will attempt to identify elements of the tools
 that signatures can be created for. Although attackers have a seemingly limitless amount of 
tools, in your analysis you may discover a shared immutable principle between these tools 
that may lend insight to attack techniques in general.

We will begin with impacket tool psexec.py. The original psexec, written by Windows guru
 and all around savage Mark Russinovich, was created to help administrators remote
 into hosts and perform their administrative duties. It can also be an excellent tool for 
lateral movement in an environment. Psexec.py uses RemcomSVC to perform the same
 functions psexec can. As explained in the github page for RemcomSvc, it is :

“a small (10KB upx packed) remoteshell / telnet replacement that lets you execute processes on remote 
windows systems, copy files on remote systems, process their output and stream it back. It allows execution 
of remote shell commands directly with full interactive console without having to install any client software.”Source.

Below is a great succinct description provided in an article titled ‘Psexec Demystified’ on
 how PSExec works:

[PSExec] has a Windows Service image inside of its executable.

  1. It takes this service and deploys it to the Admin$ share on the remote machine
  2. It then uses the DCE/RPC interface over SMB to access the Windows Service Control Manager API.
    It turns on the PSExec service on the remote machine.
  3. The PSExec service then creates a named pipe that can be used to send commands to the system.”Source.


    We will go through each step with the psexec.py version with network traffic and host log examples.

    1. It takes this service and deploys it to the Admin$ share on the remote machine.    
    The Admin share is typically used to deploy software on a remote machine. Source. With Psexec.py,
     This is completed by authenticating to the remote machine  with NTLM over SMB,
     though Kerberos authentication can be used as well. The first oddity that stands out after 
    authenticating, is that psexec.py sends an SMB Create Request file named “BETO “
     to the remote host. Once it receives a response, it sends a setinfo command that requests
     the file to be deleted when closed. According to Microsoft the setinfo packet is sent by a 
    client to, “ request either creation of or access to a file. In case of a named pipe or printer, 
    the server MUST create a new file.” By going through the code I can see that the author's
     name is beto with a twitter handle of @agsolino. Perhaps the author did it to ensure they
     can create files on the $ADMIN share. Following this action, psexec.py connects back to 
    the $ADMIN share and writes a randomly generated eight character executable.
    The sha1 hash for this exe is  23873bf2670cf64c2440058130548d4e4da412dd.

    2. It then uses the DCE/RPC interface over SMB to access the Windows Service Control
     Manager API. It turns on the PSExec service on the remote machine.    
    In order to complete this part, the attacker must connect to the dce-rpc svcctl interface
     which is, “used to manage Windows services via the SCM (Service Control Manager)”, Source 
    and perform the following operations illustrated in the figure below.


    These were gathered from the dce_rpc.log from bro that I would highly recommend using as it
     is not only a great logging framework but a powerful scripting language as well. 
    When psexec.py performs the OpenSCManager operation it identifies the MachineName as DUMMY.
     When I used both remcom and the original psexec, they identified the machine name with the
     ip address of the remote host. This activity could also be viewed by looking for the windows event
     code 7045, a new service being installed and other ways through the windows logs that we will go
     through in the signatures section.

    3. The PSExec service then creates a named pipe that can be used to send commands to the system.
    This last action is completed through the  IPC(Inter Process Communication) share which
     allows for this type of communication between two remote hosts. In order for named pipe
     communications to occur, two packets must be sent: the SMB IOCTL request and Create 
    Request File packets. The SMB IOCTL packet requires the following before it is sent:
    • “A handle to the TreeConnect identifying the connection to the IPC$ share
    •  The name of the named pipe, omitting any prefixes such as "\pipe\".Source.
    What matters to us, is the identification of the connection to the IPC$ share and the name of the named
     pipe. For psexec.py, the names for the named pipes are RemCom_communication, 
    RemCom_stdin[a-z0-9]{8}, RemCom_stdout[a-z0-9]{8} and RemCom_stderr[a-z0-9]{8}. 
    The Create Request File packet contains the access mask for each of these named pipes requests, 
    which is the other significant aspect to make note of. The access mask provides insight into what the
     attacker wants to do when they access the remote host. For the RemCom_communication named
     pipe pictured below, it contains the access mask of 0x0012019f. This is the same access mask many
     msrpc named pipes request when establishing a communication channel. Remcom stdin, requests 0x6, 
    which is write and append and stdout and stderr both request 0x1, which is read. By looking at these
     access masks and knowing their values, you can infer that psexec.py allows for some form of
     interactive communication over this named pipe.
    access_mask.png




    Signatures

    The signatures we will be creating, will be from Windows event logs forwarded to Splunk, since, 
    at least in my limited experience, network taps are almost never placed where you want them; 
     typically being placed at the perimeter, making every network defender cry :(. If you want to follow 
    along, I would recommend installing Splunk in your home lab. DA_667 has released a book on how 
    to  create a lab and there’s an awesome section on how to install Splunk.
    We can begin with some easy ones that generate an alert from some of the strings we pointed out
     earlier.
    iindex=wineventlog sourcetype=wineventlog:security EventCode=5145 Relative_Target_Name="BETO" | table _time Source_Address Account_Name Share_Name Share_Path Relative_Target_Name Access_Mask

    index=wineventlog sourcetype=wineventlog:security Relative_Target_Name="RemCom*" EventCode=5145 | table _time Source_Address Account_Name ComputerName Share_Name Relative_Target_Name Access_Mask

    Some others would require you to profile the activity that occurs in the network. 
    Should users/service accounts be accessing the $ADMIN share in your environment?
    If so, who does? From what IP? Is that IP always the same? Why do they usually access this share and on which hosts
    does this activity typically occur? Even looking for writes to the Admin share may yield some interesting discoveries:

    index=wineventlog sourcetype=wineventlog:security EventCode=5145
    (Access_Mask=0x120196 OR Access_Mask=0x2 OR Access_Mask=0x6 OR Access_Mask=0x130197) | table _time Source_Address Account_Name ComputerName Share_Name Relative_Target_Name Access_Mask

    Again though, there may be service accounts that  trigger these queries, so it's best to run these first as far back as you can to filter out false positives or to determine whether this is applicable in your environment.

    What about services installed on a host? How many times does this occur and by which user accounts?

    sourcetype="WinEventLog:Security" index=wineventlog EventCode=5145 AND (Access_Mask="0x2" OR Access_Mask="0x6" OR Access_Mask="0x12019f") | bucket _time span=3s | rex "(?<masks>(0x2|0x6|0x12019f))" | stats values(Relative_Target_Name) AS Relative_Target_Name values(Account_Name) AS Account_Name values(Source_Address) AS Source_Address dc(masks) AS distinct_masks by _time ComputerName | search distinct_masks=3 | table _time Source_Address Account_Name ComputerName Relative_Target_Name distinct_masks

    This signature is a bit different from the other ones. As the other ones look for identifiable
     strings, this one is more for the behavioral aspect. It looks for for a write to a share (0x2) 
    along with the write and append (0x6) and for the create file request (0x12019f)
     within a small period of time on the same host.  This signature was a revision of one created by
     jackcr in his blog findingbad.blogspot.com. Jackr is an excellent resource for developing and 
    honing your analytical process when looking for adversaries. Source

    index=wineventlog sourcetype=wineventlog:security  (EventCode=4688) OR (EventCode=5145 Access_Mask=0x120196 OR Access_Mask=0x2 OR Access_Mask=0x6 OR Access_Mask=0x130197)
    | bucket _time span=1s
    | stats values(Process_Command_Line) AS Process_Command_Line values(Relative_Target_Name) AS Relative_Target_Name values(Account_Name) AS Account_Name by _time  ComputerName
    | search Relative_Target_Name!="NULL" AND Process_Command_Line!="NULL"
    | table _time  Account_Name ComputerName Process_Command_Line Relative_Target_Name


    This signature, pictured below, looks for  writes to an smb share and command line 
    execution within a one second time span. The selection of access masks are relatively rare, 
    thus when those are used I would want to observe if there was any command line activity within 
    that time.



    index=wineventlog (sourcetype="wineventlog:security" EventCode=5145 Access_Mask=0x2
     OR Access_Mask=0x120196 OR Access_Mask=0x6) OR
     (sourcetype="wineventlog:system" EventCode=7045)
    | rex field=Service_File_Name "(?<file_name>[^\\\]*$)"
    | bucket _time span=1s
     | stats values(file_name) AS file_name values(Relative_Target_Name) 
    AS Relative_Target_Name values(EventCode) AS EventCode values(Account_Name)
     AS Account_Name by _time ComputerName
      | search file_name!="NULL" AND Relative_Target_Name!="NULL"
    | table _time Account_Name file_name Relative_Target_Name ComputerName

    This signature is very similar to the previous query however it looks for service created rather than
     process executed.






    index=wineventlog (sourcetype="wineventlog:security" EventCode=5145 Access_Mask=0x2
    OR Access_Mask=0x120196 OR Access_Mask=0x6 OR Access_Mask=0x130197)
    OR (sourcetype="wineventlog:system" EventCode=7045)
     | rex field=Service_File_Name "(?<process>[^\\\]*$)"
      | streamstats count by EventCode process Relative_Target_Name
     | bucket _time span=1s
      | stats values(process) AS process values(Relative_Target_Name) AS Relative_Target_Name values(EventCode) AS EventCode by _time ComputerName
       | eval status = if(match(process,Relative_Target_Name), "Match", "No Match")
       | search status="Match"

    This signature looks for whether process executed and the file written to the share are the same within a one second time span and if they match, return the results.








    Sources:






    http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_svcctl.html




    Tuesday, December 5, 2017

    What will follow will be intermittent protocol and log analysis. I will attempt to organize my ramblings into something coherent and worth reading. But mostly I want a place to record my thoughts so I can come back to them later.