Announcement

Collapse
No announcement yet.

DOS Obfuscation Part 1

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DOS Obfuscation Part 1

    Obfuscating commands is often used to make code or commands hard to read or more innocent looking for an malware analyst but it is also very useful for evading EPP sensors and antivirus software. Even the infamous AMSI is unfortunately based on string comparison and is very easy to bypass.

    We will be using two commands in the following examples. We will be using the "dir" command when ever possible because it is a short command and it is easy to have it generate output to see the techniques working. unfortunately "dir" will not work on all techniques because it is a build-in command in the Windows Command Prompt (Windows Command Shell) and not everything works if the command is not directed at an executable file directly.

    One obvious way of making case sensitive string comparisons fail is to tamper with upper and lower case letters. Windows doesn't care about that and will run the command not matter what combination you can come up with. It is very hard to block all combinations of upper and lower case letters and the longer the command the harder it gets. It is not always possible to whitelist the commands that are allowed to run, as that might consequently mean you will have to whitelist most of the windows binaries to avoid breaking things. I guess Microsoft just want an operating system that is easy to use and very forgiving but being user friendly comes at a price - as you will soon learn.

    Code:
    dir
    dIr
    dIR
    Above commands all do the same.

    Another way of obfuscating commands is to include the caret character "^" as it is generally ignored by the Command Prompt.
    Code:
    d^ir
    Oddly this works like a charm - even if several of them are inserted into the command.

    Code:
    cmd /c d^^i^^r
    cmd /c d^^i^^^r
    cmd /^c d^^i^^^r
    All above commands will give you a directory listing without complaining the slightest.

    Another weird thing is that when "cmd /c" is being used the Command Prompt seems to not care much about what comes after "cmd" and before "/c". Note that "/c" will close the window when the command is done where as "/k" will keep the window open. There is also no difference between using "/c" and "/k" in either upper or lower case.
    Code:
    cmd \C /^c d^^i^^^r
    So the "\C" that comes before the actual useful switch "/c" is being completely ignored when done with a backslash instead of a slash.

    Another more common thing is that the amount of spaces between commands, switches, arguments etc. are also ignored. Meaning you can put in an excessive amount of them in to make analysis of the commands harder.
    Code:
    cmd \C    /^c d^^i^^^r
    Lets take this a step further. It is possible and quite easy to set an environment variable and have that executed as a command.
    Code:
    set ob1=dir&&call %ob1%
    Here we have set the environment variable "ob1" to contain "dir" and if that goes well we will use the "call" command to execute that command. The "set" and the "call" commands are separated by the command separator "&&".

    Before we move on there are a few commands that may be useful. The "set" command executed with no arguments will show you all set environment variables. Using "set U" will show you all environment variables starting with the letter "U". You can be more granular if you do "set USERN" as it will show you all environment variables starting with "USERN". This will not change any variable values as long as you do not include an equal sigh, "=". Below commands will zero out the variables used in the following examples.
    Code:
    set ob1=
    set ob2=
    set ob3=
    Environment variables can contain special characters and even spaces. Used in combination could look something like this.
    Code:
    set '  =dir&&call %'  %
    set -##-=dir&&call %-##-%
    Executing the "set" and "call" commands works fine on its own and executed by "cmd.exe", the Command Prompt.
    Code:
    cmd /C "set ob1=dir && call %ob1%"
    To make it harder to conclude what commands are being run it is possible to cut the "dir" command into two or more pieces and put them together when they are executed. You can have the "di" part of "dir" in one environment variable and the remaining "r" in another one. The force of this is that it makes it hard to look for useful keywords by just taking a brief look at the obfuscated command. If you can split the command into two or more pieces you can also declare them in reverse or random order.

    Code:
    set ob1=r&&set ob2=di%ob1%&&call %ob2%
    Here the last part of the "dir" command is defined first, the "r", then the "di" part is defined and concatenated with the first part "di%ob1%" and finally the command is executed by "call".
    This also works with "cmd /R" and other variations of it. And oddly sometimes with only one command separator, "&".
    Code:
    cmd /R "set ob1=ir&&set ob2=d&cmd /R %ob2%%ob1%"
    cmd /R "set ob1=ir&set ob2=d&cmd /R %ob2%%ob1%"
    It is also possible to first set two environment variables, each with a part of the command, the concatenate them into a third environment variable, "%ob3%" and then execute it.
    Code:
    set ob1=di&& set ob2=r&&set ob3=%ob1%%ob2%&&call %ob3%
    This can be combined into some very powerful obfuscation.
    Code:
    cm^d /R "se^t ob1=i^r&s^et ob2=d&cm^d /R %ob2%%ob1%"
    For the next examples you will need to know about the "/V:ON" option that is supported by the Command Prompt. Here is how the cmd.exe help explains it.
    Enable delayed environment variable expansion using ! as the delimiter. For example, /V:ON would allow !var! to expand the variable var at execution time. The var syntax expands variables at input time, which is quite a different thing when inside of a FOR loop.
    The "/V:ON" option gives us the option to set environment variables with one value then change them later.
    Code:
    cmd.exe /V:ON/C"set ob1=dix&&set ob2=!ob1:x=r!&&call %ob2%"
    Here we set the "ob1" environment variable to "dix". Then we change the "x" in "dix" to "r" while assigning it to the variable "ob2". And finally we execute the command in "ob2".
    At this point it is getting really hard for automated tools to validate if these commands are malicious or not as it is complicated to even see what commands will be executed without actually executing them.

    Code:
    cmd.exe /V:ON/C"set ob1=dyx&&set ob2=!ob1:x=r!&&set ob3=!ob2:y=i!&&call %ob3%"
    This example is the same as the previous one except that we not only change an "x" to an "r" but also changing a "y" to an "i" so that the original command "dyx" becomes "dir". And of course we also execute it.

    It gets worse. We can actually make words up from an alphabet, random letters or made up words stored in an environment variable.
    Code:
    cmd.exe /V:ON/C"set ob1=abcdefghijklmnopqrstuvwxyz && cmd /R %ob1:~3,1%%ob1:~8,1%%ob1:~17,1%"
    Here we have set "ob1" to contain a list of letters we will use to build our command from. Note that when addressing letters in the "ob1" variable, the counting starts at 0 counting from the left. We run the "cmd /R" command with an argument build from these letters. The first letter we pull is the third letter, and we only need 1 letter. So "%ob1:~3,1%" will return a given number of letters starting at letter 3 in "ob1", remember we start counting at 0. The amount of letters is 1, as started in "%ob1:~3,1%" so this will be the letter "d". Then we pick letter number 8, and only that one letter, which equals to "i", "%ob1:~8,1%". Last but not least we find the letter "r" in position 17, "%ob1:~17,1%". That will make up the "dir" command that will be executed. Note that the "/R" is the same as "/C" even though it is not in the Command Prompt help screen.

    You do not have to settle with just one letter when cutting values stored in environment variables into pieces. You might be able to have a command look like another command or even set values as words then cut them into useful commands.

    This command have a common word in it that does not at all look like a command and of course it isn't - yet.
    Code:
    set ob1=dirty&&call %ob1:~0,3%
    Above command will take the first 3 letters in the word, it starts at letter 0 which is the first letter, then picks 3 letters from that position. in effect this will be the "dir" command.

    This command will start at position 3 from the left in "ob1" and pick the rest of the word. this again gives us the "dir" command.
    Code:
    set ob1=subdir&&call %ob1:~-3%
    When we execute commands from environment variables some of the rules that apply to commands executed directly, also apply to environment variables, such at the caret.
    Code:
    set ob1=dir^^&&call %ob1:~0,3%
    set ob1=di^r^^&&call %ob1:~0,3%
    set ob1=di^r^&1&&call %ob1:~0,3%
    Have a look at Part 2 of this write-up. I had to make it into two pieces as the post just got too long.

    Links
    https://docs.microsoft.com/en-us/win...s-commands/cmd

    Source
    https://www.fireeye.com/content/dam/...ion-report.pdf
    Last edited by Resheph; 05-18-2019, 11:38 PM. Reason: Tidy up stuff.
    Certified Security Geek
Working...
X