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.
Twitter: @lokut
This blog is for educational purposes only. The opinions expressed in this blog are my own and do not reflect the views of my employers.
Sunday, January 25, 2015
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:
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.
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()
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):
conn.send(('HELP' + '\r\n'))
print conn.recv(1024)
def setString(currentChar):
print 'Current Character or String: ' + currentChar
print 'For the following characters select the numeric value before it:'
print "100. \\n 101. \\r\\n 102. \\x90 or NOP"
print '* The above characters can not be used in a series of characters'
print ' at this time.'
newChar = raw_input('Set Character> ')
return newChar
def funcSeriesChar(currentSeries):
print 'Current Series if Characters or String: ' + currentSeries
newSeries = raw_input('Set Character(s)> ')
return newSeries
def setSize(currentSize):
print 'Current Initial Size of String: ' + str(currentSize)
newSize = raw_input('Set Size> ')
return newSize
def setMultiplier(currentMulti):
print 'Current Multiplier of String: ' + str(currentMulti)
newMulti = raw_input('Set Multiplier> ')
return newMulti
def funcCommand(currentCommand):
print 'Current Command: ' + currentCommand
newCommand = raw_input('Set Command> ')
return newCommand
def runFuzzer(conn, currentCommand, currentChar, currentSeries, currentSize, currentMulti):
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':
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()
Sunday, January 11, 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
#!/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()
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):
conn.send(('HELP' + '\r\n'))
print conn.recv(1024)
def setString(currentChar):
print 'Current Character or String: ' + currentChar
newChar = raw_input('Set Character> ')
return newChar
def setSize(currentSize):
print 'Current Initial Size of String: ' + str(currentSize)
newSize = raw_input('Set Size> ')
return newSize
def setMultiplier(currentMulti):
print 'Current Multiplier of String: ' + str(currentMulti)
newMulti = raw_input('Set Multiplier> ')
return newMulti
def funcCommand(currentCommand):
print 'Current Command: ' + currentCommand
newCommand = raw_input('Set Command> ')
return newCommand
def runFuzzer(conn, currentCommand, currentChar, currentSize, currentMulti):
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)
def main():
global s
setCommand='STATS'
setChar='A'
initialSize=50
intMultiplier=1
menuOption = '0'
while menuOption <> '9':
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()
Subscribe to:
Posts (Atom)
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...
-
Here is a quick walk through of GetBoo. The first item that I found was you can harvest the usernames of the existing users that are regist...
-
As I was glancing through the logs of my honeypots I spent some time to look at the following logs. In the past I have just overlooked them...
-
I thought I would work through a few of these web applications provided by OWASP on their broken web applications VM. The first one I th...
-
Today looking at the logs of the honeypots, I became curious based on the whois of the IP Addresses attempting to login to SSH which country...
-
Recently I was doing some scanning with a tool that is available on github called masscan. The tool allows you to configure a configuration...