The Challenge
A few months back, a co-worker introduced me to RangeForce, a security training platform that included a variety of different challenges. In May, this platform was running what it called the “Community SOC Challenge,” which was meant to test users on some Blue Team/detection skills. I eventually completed all of the challenge, and as a result I was given a prize of free access to some other modules on their site. I remember liking their YARA challenge the most. To be honest, I didn’t really know what YARA actually was or what it did, and as it turned out, my bash skills were more valuable than my YARA knowledge.
To start off, they gave me a malicious file sample on their Linux virtual machine, called “1”. They had the following question:
How many sequences of printable characters with the minimum length of 7 are there in the file sample/1? Assume printable characters to be single-7-bit-byte characters (ASCII, ISO 8859, etc.), including tab and space characters but no other whitespace characters.
So I decided to use the strings command, looking for a minimum length of 7 characters, and then I piped that to the wc command to count the number of lines for those strings:
student@desktop:~/Desktop/suspicious$ strings –n 7 1 | wc –l
The syntax is kind of confusing because the file is called “1,” but this actually worked and gave me the correct answer of 1091.
Writing my first YARA rule
The next question was:
Write a Yara rule to detect the presence of the string cmd.exe /c “%s”. Save the rule into the /home/student/Desktop/rules/offset.yar file.
Huh. So I’m pretty sure I Googled something like “detect string with YARA rule”. Here’s what I ended up coming up with:
pluma /home/student/Desktop/rules/offset.yar
Rule:
rule detect_cmd {
strings:
$cmd = "cmd.exe /c \"%s\""
condition:
$cmd
}
I had to backslash the double quotes in the $cmd variable. And before you get the pitchforks, I’m pretty sure pluma was the only text editor they had on the virtual machine, so no, I wasn’t using vim or any other editor.
The next question wanted us to run the YARA rule:
What is the offset of the string cmd.exe /c “%s” in the file sample/2? Provide an answer in the hex form prepended by 0x e.g. 0x1234.
After doing some digging about running YARA on the command line, I learned I needed to use the -s option to get that hex offset when using my YARA rule on the file “2”:
sudo yara -s /home/student/Desktop/rules/offset.yar ./2
Here was the output, with 0x45534 being the answer:
detect_cmd ./2
0x45534:$cmd: cmd.exe /c "%s"
Creating a YARA rule to detect a Windows executable (PE) file
Next question:
Write a Yara rule capable of detecting files that have a PE file format in the /home/student/Desktop/suspicious directory. Save the rule into the /home/student/Desktop/rules/pe.yar file.
After some searching, I eventually came across a wonderful Binary Defense article:
…The rule condition starts with something that may look rather odd, but it is fairly simple as well. “uint16(0)” is looking for two bytes at offset 0 in the scan target and then compares them to “0x5a4d” to see if the first two bytes of the file match. These two bytes are considered a file marker or “magic bytes” used to determine if the file is a Windows executable (PE) file.
So I crated the rule:
pluma /home/student/Desktop/rules/pe.yar
rule is_pe
{
condition:
uint16(0) == 0x5a4d
}
And when you run the command in the “suspicious directory” you get the following output:
student@desktop:~/Desktop/suspicious$ yara /home/student/Desktop/rules/malware.yar .
find_strings ./118
find_strings ./172
find_strings ./22
find_strings ./25
find_strings ./45
find_strings ./169
find_strings ./48
find_strings ./187
find_strings ./35
find_strings ./198
find_strings ./90
find_strings ./57
find_strings ./81
find_strings ./194
find_strings ./160
find_strings ./103
find_strings ./197
find_strings ./133
find_strings ./89
Writing a bash script to add strings to a YARA rule
Last question:
Write a Yara rule capable of detecting files that are actually malware in the /home/student/Desktop/suspicious directory. Create the Yara rule from the strings in /home/student/Desktop/intel/strings.txt to detect the malware. Save the rule into the /home/student/Desktop/rules/malware.yar file.
There were 298 strings in the strings.txt file, and I had to find a way to write a script to get that data and put it into variables for a YARA rule. Otherwise I had to do it all manually.
First things first. I know that in the strings I have to backslash out any double quotes (") and other backslashes (\), like I had to do in the 2nd question.
First I made a copy of the strings file:
cp strings.txt strings2.txt
Then I used sed to change " to \":
sed -i 's/\"/\\\"/g' strings2.txt
Then I used sed to change \ to \\:
sed -i 's/\\/\\\\/g' strings2.txt
Then I used a bash script to create the string rules:
#!/bin/bash
snum=0
cat strings2.txt | while read -r line
do
printf "\t\t\$s%s=\"%s\"\n" "$snum" "$line"
((snum++))
done
Some things I learned the hard way:
-
It was really important to include the –r option with while read, otherwise the work from my sed commands would be erased. The -r option prevents backslash escapes from being interpreted.
-
I originally tried to print the output of the script with the echo command, but there were just too many formatting errors due to how echo operates. printf was the better option. I also learned it was really important to quote the variables while using printf, as not doing so could also cause errors.
I ran that shell script on the strings2.txt file, got the output, and made a very long rule:
rule find_strings
{
strings:
$s0="WWWWWPj"
$s1="OpenSCManagerA"
$s2=";22dV::tN"
$s3="_local_unwind2"
$s4="2+( VPOL"
$s5="GlobalAlloc"
$s6="VirtualProtect"
$s7="@Pbmx~P"
$s8="FreeLibrary"
$s9="^Fr``+:&"
$s10="VirtualAlloc"
$s11="CreateDirectoryW"
$s12=">k_I[$"
$s13="msg/m_english.wnryF"
$s14="StartServiceA"
$s15=":*>B=Ox"
$s16="OpenMutexA"
$s17="GetFullPathNameA"
$s18="RegSetValueExA"
$s19="msg/m_french.wnry"
$s20="DeleteFileW"
$s21="QeTbF~ZiKw"
$s22="SbE\\lHtQeF"
$s23="Q~TbFwZiK"
$s24="CreateFileW"
$s25=".?AVtype_info@@"
$s26="CryptDecrypt"
$s27="=j&&LZ66lA??~"
$s28="F~TbKwZi"
$s29="incorrect data check"
$s30="tasksche.exe"
$s31="MoveFileW"
$s32="unknown compression method"
$s33="??1exception@@UAE@XZ"
$s34="realloc"
$s35="SetCurrentDirectoryA"
$s36="WriteFile"
$s37="b4(X2;ey"
$s38="__p__commode"
$s39="MultiByteToWideChar"
$s40="LoadLibraryA"
$s41="\\6tGuzF"
$s42="%%Jo..\\r"
$s43="4$8,9-6'.6$:#?*1hHpXeA~SrZlN"
$s44="PPxD<<%"
$s45="kernel32.dll"
$s46="&%^W6)."
$s47="CryptImportKey"
$s48="HeapFree"
$s49="_except_handler3"
$s50="WaitForSingleObject"
$s51="V,YYG;~"
$s52="Ud|JZ|BE"
$s53="_CxxThrowException"
$s54="data error"
$s55="??0exception@@QAE@ABQBD@Z"
$s56="_acmdln"
$s57="OLEAUT32.dll"
$s58=";u>H4q7.c"
$s59="GetModuleHandleA"
$s60="incomplete literal/length tree"
$s61="OpenServiceA"
$s62="CryptReleaseContext"
$s63="attrib +h ."
$s64="inflate 1.1.3 Copyright 1995-1998 Mark Adler"
$s65="12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw"
$s66="insufficient memory"
$s67="$`GnP+%<g"
$s68="TaskStart"
$s69="msg/m_chinese (traditional).wnry"
$s70="[_:L x86"
$s71="ReadFile"
$s72="Bb..fO3"
$s73="qDj$bIU"
$s74="k|_^][Y"
$s75="invalid distance code"
$s76="wcsrchr"
$s77="GetFileSizeEx"
$s78="L)b7=a`"
$s79="__CxxFrameHandler"
$s80="_stricmp"
$s81="[4+G[Tnr"
$s82="13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94"
$s83="msg/m_croatian.wnry"
$s84="CMnQ,OOr"
$s85="swprintf"
$s86="SetFileAttributesW"
$s87="msg/m_czech.wnryn"
$s88="O|x8+^_"
$s89="HeapAlloc"
$s90="__setusermatherr"
$s91="GetWindowsDirectoryW"
$s92="115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn"
$s93="LocalFileTimeToFileTime"
$s94="3/Vq9 ="
$s95="CryptAcquireContextA"
$s96="Jo7eQX%"
$s97="FindResourceA"
$s98="'B;1?5s"
$s99="IsBadReadPtr"
$s100="GetExitCodeProcess"
$s101="`.rdata"
$s102="#`?@/9P"
$s103="GetTempPathW"
$s104="invalid bit length repeat"
$s105="MSVCRT.dll"
$s106="o%%Jr..\\$"
$s107="Global\\MsWinZonesCacheCounterMutexA"
$s108="!`7RNkv"
$s109="__p___argc"
$s110="SetCurrentDirectoryW"
$s111="oversubscribed literal/length tree"
$s112="[l~y2U="
$s113="msg/m_greek.wnry4n"
$s114="invalid block type"
$s115="<` Xu9g"
$s116="GetNativeSystemInfo"
$s117="CloseServiceHandle"
$s118="incomplete distance tree"
$s119="S Q+c@x"
$s120="8d62ro/"
$s121="e ];F[p"
$s122="$@^ Y+kCM3"
$s123="X(N.K&9"
$s124="LeaveCriticalSection"
$s125="msg/m_bulgarian.wnry"
$s126="B~WJLuC"
$s127="invalid window size"
$s128="msg/m_dutch.wnry9"
$s129="GetCurrentDirectoryA"
$s130="Hy}V2l0e"
$s131="xxJo%%\\r..8$"
$s132="NLc>zQy"
$s133="=iF-s4\"t"
$s134="GetFileAttributesA"
$s135="_initterm"
$s136="2{0ONU T8"
$s137="M{_rKG C"
$s138="4XI\"whG"
$s139="DeleteCriticalSection"
$s140="b.wnryP8"
$s141="GetFileSize"
$s142="GetFileAttributesW"
$s143="md)(:--"
$s144="WNcry@2ol7"
$s145="empty distance tree with lengths"
$s146="SizeofResource"
$s147="CopyFileA"
$s148="uo\"usd/"
$s149="ciC [/K"
$s150="$0vJ<T9"
$s151="icacls . /grant Everyone:F /T /C /Q"
$s152="CryptDestroyKey"
$s153="oversubscribed distance tree"
$s154="MoveFileExW"
$s155="KfmZ@9q"
$s156="TerminateProcess"
$s157="stream end"
$s158="c.wnry%"
$s159="vi#<!d*S"
$s160="pfgGL`R"
$s161="_XcptFilter"
$s162="RegCreateKeyW"
$s163="[wS#C^6"
$s164="file error"
$s165=">nuGl=Cme4"
$s166="Microsoft Enhanced RSA and AES Cryptographic Provider"
$s167="msg/m_filipino.wnry"
$s168="incomplete dynamic bit lengths tree"
$s169=".?AVexception@@"
$s170="b=htZo&f"
$s171="KERNEL32.dll"
$s172="msg/m_chinese (simplified).wnryR9"
$s173="&&Lj66lZ??~A"
$s174="#E.(`MW"
$s175="cmd.exe /c \"%s\""
$s176="j_1lTo`"
$s177="stream error"
$s178="&Lj&6lZ6?~A?"
$s179="WS2_32.dll"
$s180="SystemTimeToFileTime"
$s181="- unzip 0.15 Copyright 1998 Gilles Vollant"
$s182="??0exception@@QAE@ABV0@@Z"
$s183=",4$8'9-6:.6$1#?*XhHpSeA~NrZlE"
$s184="CloseHandle"
$s185="??2@YAPAXI@Z"
$s186="SetFileTime"
$s187="|~}%.15"
$s188="GetProcessHeap"
$s189="SE{^QC4"
$s190="Df\"\"T~**;"
$s191="wsprintfA"
$s192="GetModuleFileNameA"
$s193="RegQueryValueExA"
$s194="2/O-_.X8w.+"
$s195="s<,kX5k"
$s196="4I_,eJi"
$s197="CreateServiceA"
$s198="f\"\"D~**T"
$s199="_controlfp"
$s200="incompatible version"
$s201="dV22tN::"
$s202="_-TPsPUv: V"
$s203="IyEf [%"
$s204="__set_app_type"
$s205="InitializeCriticalSection"
$s206="Hjz%3(0"
$s207=".Vy_Fdk"
$s208="'Oh'-o]"
$s209="qr=_os*"
$s210=",MF3j;2@"
$s211="need dictionary"
$s212="CreateDirectoryA"
$s213="pq\"b\"V1"
$s214="=XnFQ-Il"
$s215="x%Jo%.\\r."
$s216="GetProcAddress"
$s217="CryptEncrypt"
$s218="MSVCP60.dll"
$s219="6P>YK^$r"
$s220="__p___argv"
$s221="sprintf"
$s222="MF2E0UG"
$s223="KPeJr}F"
$s224="CryptGenKey"
$s225="__getmainargs"
$s226="`1^9tdb"
$s227="mK~}k=P"
$s228="ADVAPI32.dll"
$s229="GetComputerNameW"
$s230="!This program cannot be run in DOS mode."
$s231="WANACRY!"
$s232="incorrect header check"
$s233="_mbsstr"
$s234="Le\"zE^f1"
$s235="msg/m_german.wnry"
$s236="\"Df\"*T~*"
$s237="SHELL32.dll"
$s238="8,4$6'9-$:.6*1#?pXhH~SeAlNrZbE"
$s239="LockResource"
$s240="#cMe&(;[Ip"
$s241="advapi32.dll"
$s242="Lj&&lZ66~A??"
$s243="L3koq_ >"
$s244="??1type_info@@UAE@XZ"
$s245="msg/m_danish.wnry"
$s246="^Md]\"lN"
$s247="EGBkV6\"rnL9"
$s248="?-3t/''"
$s249="GetStartupInfoA"
$s250="tJ9@0O("
$s251="!A$U>=+"
$s252="2dV2:tN:"
$s253="tlHt Ht"
$s254="9d|!]`["
$s255="GlobalFree"
$s256="V22dN::t"
$s257="nyMZ?%g;"
$s258="QeFbF~TiKwZ"
$s259="[d+?8d["
$s260="EnterCriticalSection"
$s261="LoadResource"
$s262="msg/m_finnish.wnry~"
$s263="\"\"Df**T~"
$s264="kEs##Q^!"
$s265="r;#r7iS|1"
$s266="s]R\",XC("
$s267="CreateFileA"
$s268="??3@YAXPAX@Z"
$s269="VirtualFree"
$s270="CreateProcessA"
$s271="invalid literal/length code"
$s272="oversubscribed dynamic bit lengths tree"
$s273="E65etRI\\v4"
$s274="SetLastError"
$s275="*4q4[`V"
$s276="+[\\_JQ}"
$s277="\"t=.|Vbq-"
$s278="invalid stored block lengths"
$s279=":95e`Il"
$s280="$8,4-6'96$:.?*1#HpXhA~SeZlNrSbE"
$s281="=1azT)8^y"
$s282="__p__fmode"
$s283="buffer error"
$s284="^Ml,L;0"
$s285="!#pHA[P"
$s286="*@~CS%1"
$s287="~|c<caKm2"
$s288="C77nYmm"
$s289="_adjust_fdiv"
$s290="7#z y,:"
$s291="e\".E~^G"
$s292="pp|B>>q"
$s293="SetFilePointer"
$s294="RegCloseKey"
$s295="strrchr"
$s296="USER32.dll"
$s297="too many length or distance symbols"
condition:
all of them
}
I ran the rule and was able to identify the files that were malware:
student@desktop:~/Desktop/suspicious$ yara /home/student/Desktop/rules/malware.yar .
find_strings ./118
find_strings ./172
find_strings ./22
find_strings ./25
find_strings ./45
find_strings ./169
find_strings ./48
find_strings ./187
find_strings ./35
find_strings ./198
find_strings ./90
find_strings ./57
find_strings ./81
find_strings ./194
find_strings ./160
find_strings ./103
find_strings ./197
find_strings ./133
find_strings ./89