Sunday, January 25, 2015

Application Call to Missing DLL can lead to Meterpreter Shell

This is a proof-of-concept to demonstrate how to gain a meterpreter shell through a call by an application to a dll that does not exist can be replaced by a Meterpreter DLL.  Granted I am using an Administrator account to copy the file to it's final location but this could be done by an exploit, through poorly set permissions, incorrect access control, or through privilege escalation.

1. I generated a Meterpreter DLL and saved it temporarily as meterpreter.dll:

2. Next I ran ProcMon.exe on a Windows 7 SP1 virtual machine.  I left it running for a while and then saved the logfile to a csv file because I was not sure what I was looking for in the output.

3. After working with the log file I found a command that would return dll files that were being called by a process that were not found:

cat Logfile.CSV | grep -i "name not found" | grep -i "createfile" | grep -v -i "procmon.exe" | grep -e "\.dll"

4. With running the command the following results came out:

5. After some trial and error I found the following dll that was run by the explorer.exe process and was not found, "C:\Windows\System32\wbem\RpcRtRemote.dll".  Again this is a proof-of-concept showing that if a path was not protected or had incorrect permissions established if a dll was called and was missing it could be substituted for the meterpreter dll.  I substituted in the meterpreter.dll with the name found.



6. Now to get explorer.exe to call the RpcRtRemote.dll file I found that all I had to do is launch procmon.exe after I had previously closed it.  Then the staged Meterpreter shell loaded.


7. This could be another way that malware will establish persistence on a system.






Saturday, January 24, 2015

Using OfficeMalScanner to look at a Macro and more...

I came across a Microsoft Word document that contained a macro.  I decided to tear it apart to understand it a little better.  The steps I took are below:

1.  I downloaded OfficeMalScanner from http://www.reconstructer.org/code.html and placed it in the same directory as the Word document.  OfficeMalScanner could be placed in a separate directory.

2. Ran OfficeMalScanner against the Macro:

3. Then used the "inflate" command to extract the contents of the file:

4. I then moved the location of the decompressed files to the location of where I am working.

5. I ran the scanner on the first binary in the word/vbaProject.bin file and it extracted the contents of the macro:

6. With the extracted macro lets take a look at the first few lines of it to find Indicators of Compromise (IOC)s:

Looking at the first part of the macro that was extracted we can see a filename that we can look for "updater.exe" in the directory "C:\Users\<Username>\AppData\Local\Temp" unless it does not exist and then place it in "C:\Users\<Username>\AppData\" as the file "ntuserssc.exe".

7. Looking at more of the macro:

We notice that the fso or the File System Object is inside of an OLE Formatted Object.  Also the size of the object is comparable to SS or 168,448 bytes.

8.  Going back to the files that were extracted let's find the file that is larger than 168k in bytes:

Found that the oleObject1.bin file is slightly larger than the 168k we are looking for.

9. I used hexdump on the file to see if I could pull out any more indicators:

Looking at this we notice the filename of "updater.exe" a second time in our analysis, but we also see other indicators of possibly information about the creation of the malware:
"C:\Art\Clients\Jag\updater.exe" and "C:\Users\Em\AppData\Local\Temp\updater.exe"

Then we see where the binary starts with the letters MZ.

10.  Let's extract the binary from the file for further analysis using foremost.

Looking at the audit.txt file that foremost creates in the output folder we see the 00000007.exe was extracted.

11.  Uploading this file to VirusTotal returned the following results at the following page if you are interested:
https://www.virustotal.com/en/file/585b38c11e98a2c5891d7f4cbee40bb919ea19ceb12705eabab21dccb10b1328/analysis/

12.  I started looking at the information provided by the anti-viruses about this malware.  The following from ESET was close to the assessment of what I am seeing so far with comparing what it found to the strings in the binary:
http://www.virusradar.com/en/Win32_TrojanDownloader.Hancitor.B/description

Symantec calls it a Remote Access Trojan of (RAT):
http://www.symantec.com/security_response/attacksignatures/detail.jsp?asid=26353

13.   I then uploaded it to a binary analysis service that I like to use called Anubis:
https://anubis.iseclab.org/?action=result&task_id=1691a5a5dccc212d4b192dc1fb187553e&format=html

In the assessment it showed again some of the commands found in the ESET assessment.  However throughout these assessments I still do not see any network indicators.

14.Now to run the binary on a Windows 7 SP1 computer it connects out to the following locations through a TLS connection:

The tor2web.org project let's you browse to servers that are on the Tor network.  Another way to see the URL is with a .onion instead or tor2web.org.  They are trying to anonymize the traffic.

15. The program adds persistence to the computer by adding a run key:

16. The binary starts out with the name of updater.exe or ntuserssc.exe and then goes through a random name then ending up with the name of winlogin.exe.  Notice that the program is also called winlogin.exe imitating the winlogon.exe process:

Monday, January 19, 2015

msf3 database for Metasploit not working - How to rebuild...

Today I ran into some issues with my msf3 database that I have been using with Metasploit.  I thought I would take a couple minutes and document how I rebuilt it.  This will delete all the current entries and information stored in the msf3 database.

Verify the postgresql server is running or restart the server by executing '/etc/init.d/postgresql restart'

The metasploit framework when it is installed creates the following file that contains the msf3 username and random password that is generated:

cat /opt/metasploit/apps/pro/ui/config/database.yml

Gather from the file the password for the msf3 user or change it to one you would like to use.

Then switch to the postgres user in Kali linux by executing 'su - postgres'.  You should see the prompt at that time 'postgres@machname:~$'

Execute 'psql' at the prompt to get into the postgres database.  To view the databases execute '\list'.

Let's first reset the password of the msf3 account.  Note if you reset the password update it in the database.yml file mentioned above.

Execute: ALTER USER msf3 WITH PASSWORD 'passwordindatabaseymlfile';

Remove the msf3 database by executing the 'drop database msf3;'
Recreate the database by executing: 'create database msf3 owner msf3;'

Then quit from postgres by executing \q.

Type exit to get out of the user postgres.

Then run the metasploit console and it will create the necessary tables for the database then you need to wait 2-5 minutes for it to create the cache that metasploit uses.  This worked to recreate the msf3 database so now it works.

Saturday, January 17, 2015

Updated Fuzzer for vulnserver.exe

I have updated the script to cycle through a series of characters instead of manually changing the character after each iteration of the script.  I also added the ability to include the new line, carriage return and line feed, and NOP characters.

I have built this script to introduce the concept of fuzzing in a Computer Science course that I will be teaching.

#!/usr/bin/python

import socket

def optionsMenu(currentCommand, currentChar, currentSeries, currentSize, currentMulti):
print 'Select from the Following Options: '
print '1. List Commands'
print '2. Set Command - "' + currentCommand + '"'
print '3. Set Initial Character or String ("' + currentChar + '")'
print '4. Set String Initial Size ("' + currentChar + '"*' + str(currentSize) + ')'
print '5. Set String Multiplier (("' + currentChar + '"*' + str(currentSize) + ')*' + str(currentMulti) + ')'
print '6. Set Series of Characters to go through after the Initial Character: ' + currentSeries
print '7. Run Fuzzer'
print '9. Exit'
menuOpt = raw_input('>> ')
return menuOpt

def listCommands(conn):
print
conn.send(('HELP' + '\r\n'))
print conn.recv(1024)

def setString(currentChar):
print
print 'Current Character or String: ' + currentChar
print
print 'For the following characters select the numeric value before it:'
print "100. \\n 101. \\r\\n 102. \\x90 or NOP"
print
print '* The above characters can not be used in a series of characters'
print '  at this time.'
print
newChar = raw_input('Set Character> ')
return newChar

def funcSeriesChar(currentSeries):
print
print 'Current Series if Characters or String: ' + currentSeries
newSeries = raw_input('Set Character(s)> ')
return newSeries

def setSize(currentSize):
print
print 'Current Initial Size of String: ' + str(currentSize)
newSize = raw_input('Set Size> ')
return newSize

def setMultiplier(currentMulti):
print
print 'Current Multiplier of String: ' + str(currentMulti)
newMulti = raw_input('Set Multiplier> ')
return newMulti

def funcCommand(currentCommand):
print
print 'Current Command: ' + currentCommand
newCommand = raw_input('Set Command> ')
return newCommand

def runFuzzer(conn, currentCommand, currentChar, currentSeries, currentSize, currentMulti):
print
print currentSeries
if currentSeries == '':
for i in range(0, int(currentMulti)):
buffer = currentCommand + ' '
if currentChar == '100': currentChar = '\x0a'
elif currentChar == '101': currentChar = '\x0d\x0a'
elif currentChar == '102': currentChar = '\x90'
buffer += currentChar * (int(currentSize) * (i+1))
buffer += '\r\n'
#print buffer
conn.send((buffer))
print 'Sent: ' + currentCommand + ' .("' + currentChar + '"*' + str(currentSize) + ')*' + str(i+1) + ' Size of buffer: ' + str(len(buffer))
print conn.recv(1024)
else:
currentSeries = currentChar + currentSeries
for currentSeriesChar in currentSeries:
print currentSeriesChar
for i in range(0, int(currentMulti)):
buffer = currentCommand + ' '
buffer += currentSeriesChar * (int(currentSize) * (i+1))
buffer += '\r\n'
#print buffer
conn.send((buffer))
print 'Sent: ' + currentCommand + ' .("' + currentSeriesChar + '"*' + str(currentSize) + ')*' + str(i+1) + ' Size of buffer: ' + str(len(buffer))
print conn.recv(1024)

def main():
global s
setCommand='STATS'
setChar='A'
setSeriesChar=''
initialSize=50
intMultiplier=1
menuOption = '0'
while menuOption <> '9':
print
menuOption = optionsMenu(setCommand, setChar, setSeriesChar, initialSize, intMultiplier)
if menuOption == '1':
listCommands(s)
elif menuOption == '2':
listCommands(s)
setCommand = funcCommand(setCommand)
elif menuOption == '3':
setChar = setString(setChar)
elif menuOption == '4':
initialSize = setSize(initialSize)
elif menuOption == '5':
intMultiplier = setMultiplier(intMultiplier)
elif menuOption == '6':
setSeriesChar = funcSeriesChar(setSeriesChar)
elif menuOption == '7':
runFuzzer(s, setCommand, setChar, setSeriesChar, initialSize, intMultiplier)
elif menuOption == '9':
break
else:
listCommands(s)


server = '172.16.102.132'
sourcePort = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sourcePort))
# The following line can be uncommented if you need to send first
print s.recv(1024)

main()

s.close()

Saturday, January 10, 2015

Volatility Bash Script v0.5

I have been using the volatility script that I wrote back in September and made some revisions to it.  Below is the source code:

 #!/bin/bash
# Script to collect information by utilizing volatility

# v0.5 - Added a registry key to pull out of the SOFTWARE registry file the Run keys
#      - Changed the home directory to the present working directory
#      - To get yarascan's to work successfully you may have to 'apt-get install libyara-dev python-yara' on Debian based systems
#      - Note on conducting a Yara scan on the memory image 'vol.py -f memimage.img yarascan -Y "3.5.7.3" # To search for a string or IP Address in memory or add a -p to only have it search in the memory of a particluar process.
#      - Create from psscan an output file that can be viewed by graphviz.org for the relationships of processes
#      - Added the output of the strings program with word sizes larger than 8 characters
#      - Added the output of privs envars and procdump
#      - Output to envars-list this organizes and sorts the environment variables looking for anomolies
#      - Output to privs-interesting privileges that may need to be looked at closer for a particular process
#      - Output of privs-list organizes and sorts them looking for unique privileges assigned
#      - Output to ldrmodules-UnlinkedDlls a list of dll's or files that are not in the triple linked dll list
# v0.4 - Added a loop to iterate through the plugins
#      - Added svcscan, sockets, sockscan, driverscan, cachedump, timeliner, evtlogs
#      - In hivelist the system file is upper or lower case depending on the profile
#      - Added dlllist for each process
#      - Added getsids for each process
#      - Added handles for each process
#      - Added ldrmodules for each process
#      - Extracting the contents of the registry at Software\Microsoft\Windows\CurrentVersion\Run
# v0.3 - Updated to include mftparser
#      - Added a temp directory
# v0.2 - Updated the DKOM section to include the 3 columns and not just the 1st.

#To come...
#Analyze specific registry keys that aide in an investigation

####  Configurable Settings #############
homeDir=`pwd`
memImage="$homeDir/myImage.img"
locVolPy='/usr/share/vol2-4/volatility-2.4/vol.py'
volProfile=''
#########################################
date
outputDir="$homeDir/output"
dumpDir="$homeDir/dumpdir"
tempDir="$homeDir/temp"

if [ ! -d $outputDir ]; then
    mkdir $outputDir
    mkdir $outputDir/dlllist
    mkdir $outputDir/getsids
    mkdir $outputDir/handles
    mkdir $outputDir/ldrmodules
    mkdir $outputDir/procdump
    mkdir $dumpDir
    mkdir $tempDir
fi

# Find the profile for the image that is being analyzed and store it in volProfile
python $locVolPy -f $memImage imageinfo > $outputDir/imageinfo
cat $outputDir/imageinfo | grep "Suggested Profile(s)" | awk '{print "Identified Profile: " $4}' | sed 's/,//'
volProfile=`cat $outputDir/imageinfo | grep "Suggested Profile(s)" | awk '{print $4}' | sed 's/,//'`

# Run a variety of volatility plugins and save the output
for pluginCommand in pslist pstree psscan psxview connections connscan filescan iehistory svcscan cmdscan consoles hivelist sockets sockscan driverscan ssdt cachedump timeliner privs envars
do
    echo "Running $pluginCommand and saving results to $outputDir/$pluginCommand"
    python $locVolPy -f $memImage --profile=$volProfile $pluginCommand > $outputDir/$pluginCommand
done

# Run a dot graph for graphviz.org for the relationships of processes
echo "Running dot graph and saving results to $outputDir/processes.dot"
python $locVolPy -f $memImage --profile=$volProfile psscan --output=dot --output-file=$outputDir/processes.dot

# Create a list of environment variables that are in memory looking for anomolies
cat $outputDir/envars | awk '{print $5}' | sort | uniq -c | sort -n > $outputDir/envars-list

echo "Running evtlogs and saving results to $outputDir/evtlogs"
python $locVolPy -f $memImage --profile=$volProfile evtlogs --dump-dir $outputDir

echo "Find processes in psxview that is using Direct Kernel Object Manipulation (DKOM)"
echo "Display from psxview any processes with "False" in the psscan, pslist, thrdproc"
echo "Find processes in psxview that is using Direct Kernel Object Manipulation (DKOM)" > $outputDir/possibleDKOM
echo "Display from psxview any processes with "False" in the psscan, pslist, thrdproc" >> $outputDir/possibleDKOM
while read line
do
    pslistColumn=`echo $line | awk '{print $4}'`
    psscanColumn=`echo $line | awk '{print $5}'`
    thrdprocColumn=`echo $line | awk '{print $6}'`
    if [ $pslistColumn == 'False' ]; then
        echo "$line" >> $outputDir/possibleDKOM
    fi
    if [ $psscanColumn == 'False' ]; then
        echo "Found: $line" >> $outputDir/possibleDKOM
    fi
    if [ $thrdprocColumn == 'False' ]; then
        echo "Found: $line" >> $outputDir/possibleDKOM
    fi
done < $outputDir/psxview
echo

echo "Running mftparser and saving results to $outputDir/mftpparser"
python $locVolPy -f $memImage --profile=$volProfile mftparser --output=body --output-file=$outputDir/mftparser.csv
mactime -b $outputDir/mftparser.csv -d -z UTC-6 > $outputDir/mftparserMactime.csv

echo "Saving the results of the hashdump to $outputDir/hashdump"
# Find the virtual address of the SYSTEM hive
while read line
do
    if [[ $line == *YSTEM* ]] || [[ $line == *ystem* ]]; then
        systemVAddr=`echo $line | awk '{print $1}'`
    fi
done < $outputDir/hivelist
# Find the virtual address of the SAM hive
while read line
do
    if [[ $line == *SAM* ]]; then
        samVAddr=`echo $line | awk '{print $1}'`
    fi
done < $outputDir/hivelist
python $locVolPy -f $memImage --profile=$volProfile -y $systemVAddr -s $samVAddr hashdump > $outputDir/hashdump

echo "Running malfind and saving results to $outputDir/malfind"
python $locVolPy -f $memImage --profile=$volProfile malfind --dump-dir $dumpDir > $outputDir/malfind

# Export to output/dlllist the PIDs found in the pslist output file
cat $outputDir/pslist | grep -v -e "Offset(V)" -e "------" | awk '{print $3}' > $tempDir/PIDlist
while read line 
do
    python $locVolPy -f $memImage --profile=$volProfile dlllist -p $line > $outputDir/dlllist/proc-$line
    python $locVolPy -f $memImage --profile=$volProfile getsids -p $line > $outputDir/getsids/proc-$line
    python $locVolPy -f $memImage --profile=$volProfile handles -p $line > $outputDir/handles/proc-$line
    python $locVolPy -f $memImage --profile=$volProfile ldrmodules -p $line > $outputDir/ldrmodules/proc-$line
    python $locVolPy -f $memImage --profile=$volProfile procdump -p $line > $outputDir/procdump/proc-$line
done < $tempDir/PIDlist

# With the dlllists look for unique path's
rm -f $tempDir/dlllistPaths
rm -f $tempDir/dlllistCommandline
touch $tempDir/dlllistPaths
touch $tempDir/dlllistCommandline
for file in $outputDir/dlllist/*
do 
    cat $file | grep "0x" | awk '{print $4 " " $5 " " $6 " " $7 " " $8 " " $9 " " $10}' >> $tempDir/dlllistPaths
    cat $file | grep "Command line :" >> $tempDir/dlllistCommandline
done
cat $tempDir/dlllistPaths | sort | uniq -c | sort -n | grep -v -i -e "windows.system32" > $outputDir/dlllist-OutsideSystem32
cat $tempDir/dlllistPaths | sort | uniq -c | sort -n | grep "1" > $outputDir/dlllist-SingleInstance
cat $tempDir/dlllistCommandline | sed 's/Command line :" //' > $outputDir/dlllist-Commandline 

# With the getsids look for unique sids or something out-of-the-ordinary
rm -f $tempDir/getsids-temp-list
touch $tempDir/getsids-temp-list
for file in $outputDir/getsids/*
do
    cat $file | awk -F ":" '{print $2}' >> $tempDir/getsids-temp-list
done
cat $tempDir/getsids-temp-list | sort | uniq -c | sort -n > $outputDir/getsids-list
cat $outputDir/svcscan | grep "Binary Path: " | sort | uniq -c > $outputDir/svcscan-binarypath

cat $outputDir/ldrmodules/proc-* | grep "0x" | grep "-" > $outputDir/ldrmodules-NoPathInfo
# Check the below ldrmodules-UnlinkedDlls for malware that could be unassociated from the triple linked dll's
cat $outputDir/ldrmodules/proc-* | grep "False  False  False" > $outputDir/ldrmodules-UnlinkedDlls
cat $outputDir/ssdt | egrep -v '(ntoskrnl | win32k)' > $outputDir/ssdt-modified

# Extract from the registry specific keys of interest
python $locVolPy -f $memImage --profile=$volProfile printkey -K "Software\Microsoft\Windows\CurrentVersion\Run" > $outputDir/registryRunKeys
python $locVolPy -f $memImage --profile=$volProfile printkey -K "Microsoft\Windows\CurrentVersion\Run" > $outputDir/registryRunKeys2
#http://digital-forensics.sans.org/blog/2010/10/20/digital-forensics-autorun-registry-keys/
#SysInternals autorun utility

# Added the output of the strings program with word sizes larger than 8 characters
strings -a --bytes=8 $memImage > $outputDir/strings.txt

# Look through the privs file and identify "Interesting Privileges that are given to Processes"
cat $outputDir/privs | awk '{print $4}' | sort | uniq -c | sort -n > $outputDir/privs-list
cat $outputDir/privs | grep -i -e "sebackupprivilege" -e "sedebugprivilege" -e "seloaddriverprivilege" -e "sechangenotifyprivilege" -e "seshutdownprivilege" > $outputDir/privs-interesting


date

echo

Built Fuzzer for vulnserver.exe using Python

Through searching for information about buffer overflows and exploiting them I found "vulnserver.exe" created by "The Grey Corner" @ http://www.thegreycorner.com/2010/12/introducing-vulnserver.html.

Then I began fuzzing the vulnserver.exe and built the following fuzzer using python, it can be adapted to fuzz other programs by modifying the source code that is listed below.

#!/usr/bin/python

import socket

def optionsMenu(currentCommand, currentChar, currentSize, currentMulti):
print 'Select from the Following Options: '
print '1. List Commands'
print '2. Set Command - "' + currentCommand + '"'
print '3. Set Character or String ("' + currentChar + '")'
print '4. Set String Initial Size ("' + currentChar + '"*' + str(currentSize) + ')'
print '5. Set String Multiplier (("' + currentChar + '"*' + str(currentSize) + ')*' + str(currentMulti) + ')'
print '6. Run Fuzzer'
print '9. Exit'
menuOpt = raw_input('>> ')
return menuOpt

def listCommands(conn):
print
conn.send(('HELP' + '\r\n'))
print conn.recv(1024)

def setString(currentChar):
print
print 'Current Character or String: ' + currentChar
newChar = raw_input('Set Character> ')
return newChar

def setSize(currentSize):
print
print 'Current Initial Size of String: ' + str(currentSize)
newSize = raw_input('Set Size> ')
return newSize

def setMultiplier(currentMulti):
print
print 'Current Multiplier of String: ' + str(currentMulti)
newMulti = raw_input('Set Multiplier> ')
return newMulti

def funcCommand(currentCommand):
print
print 'Current Command: ' + currentCommand
newCommand = raw_input('Set Command> ')
return newCommand

def runFuzzer(conn, currentCommand, currentChar, currentSize, currentMulti):
print
for i in range(0, int(currentMulti)):
buffer = currentCommand + ' '
#buffer = currentCommand + ' .'
buffer += currentChar * (int(currentSize) * (i+1))
buffer += '\r\n'
#print buffer
conn.send((buffer))
print 'Sent: ' + currentCommand + ' .("' + currentChar + '"*' + str(currentSize) + ')*' + str(i+1) + ' Size of buffer: ' + str(len(buffer))
print conn.recv(1024)
print

def main():
global s
setCommand='STATS'
setChar='A'
initialSize=50
intMultiplier=1
menuOption = '0'
while menuOption <> '9':
print
menuOption = optionsMenu(setCommand, setChar, initialSize, intMultiplier)
if menuOption == '1':
listCommands(s)
elif menuOption == '2':
listCommands(s)
setCommand = funcCommand(setCommand)
elif menuOption == '3':
setChar = setString(setChar)
elif menuOption == '4':
initialSize = setSize(initialSize)
elif menuOption == '5':
intMultiplier = setMultiplier(intMultiplier)
elif menuOption == '6':
runFuzzer(s, setCommand, setChar, initialSize, intMultiplier)
elif menuOption == '9':
break
else:
listCommands(s)


server = '172.16.102.132'
sourcePort = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sourcePort))
# The following line can be uncommented if you need to send first
print s.recv(1024)

main()

s.close()

Powershell - Gather Mapped Drives from a List of Computer Names

I created the following Powershell script to gather remotely the mapped drives that users had in their profiles.  I had to create the script...