Introduction

This details reverse engineering activities and answers for labs contained in the book ‘Practical Malware Analysis’ by Michael Sikorski, and Andrew Honig, which is published by No Starch Press. This is a very informative book to learn about malware analysis and comes with a number of binaries to test your reverse engineering skills. I would thoroughly recommend purchasing this book.

Special thanks to No Starch Press for the shout-out of this post, and to both Michael Sikorski and Andrew Honig for their permission to create this blog post based on the material and exercises contained within ‘Practical Malware Analysis’.

Notes:

• If your addresses don’t match those outlined here it’s because a program is running that is using the desired base address of the binary in question. This is most common with DLLs, and if it occurs your address will have been rebased.
• The term IDA and IDA Pro have been used interchangeably here and are used to reference IDA Pro Freeware Version v5.0, in addition variants of ‘xrefs’ have also been used to mean ‘cross-references’. In some instances Ghidra has been used where scripting or extensions were required and only available in a paid version of IDA Pro.
• This has been completed using 3 windows VMs (Windows XP 32-bit, Windows 7 32-bit, Windows 10 64-bit), a pfSense box, and an instance of SIFT Workstation; however, you really only need a couple of VMs (32-bit and 64-bit) so long as they have Python installed and the tools used (including Snort).
• The Windows 10 and Windows 7 VMs were setup with FLARE VM, with the Windows XP machine loaded just with the tools required, and the SIFT Workstation being used solely for generating Yara rules as extra bonus content.
• Virtualbox has been used for virtualisation, except in cases where Vmware was required to complete the questions (Chapter 17). In this instance a single Windows XP VM was used through Vmware Workstation instead.

Chapter 1. Basic Static Techniques

This details analysis undertaken and answers to the lab questions in Chapter 1.

Lab 1-1

This lab uses the files Lab01-01.exe and Lab01-01.dll. Use the tools and techniques described in the chapter to gain information about the files and answer the questions below.

Question 1

Upload the files to http://www.VirusTotal.com/ and view the reports. Does either file match any existing antivirus signatures?

Using the Malcode Analyst Pack we are able to perform this by simply right clicking the files and selecting VirusTotal. At the time of writing both matched existing antivirus signatures:

lab01-01.exe

• 35/65 detection rate

lab01-01.dll

• 28/64 detection rate

Question 2

When were these files compiled?

Using PEview we are able to view this information. The information is found under: IMAGE_NT_HEADERS > IMAGE_FILE_HEADER > Time Date Stamp

lab01-01.exe compile time - 2010-12-19 Sunday 16:16:19 UTC

lab01-01.dll compile time - 2010-12-19 Sunday 16:16:38 UTC

Question 3

Are there any indications that either of these files is packed or obfuscated? If so, what are these indicators?

No, there’s no indicators these files are packed or obfuscated due to the following:

Using PEiD we can identify them as being compiled with Microsoft Visual C++ 6.0.

lab01-01.dll

lab01-01.exe

Using PEview we can see the virtual size is close to the raw size of the files.

lab01-01.exe

Using the Malcode Analyst Pack we can view “strings” and see there’s plenty of them.

lab01-01.dll and lab01-01.exe

Question 4

Do any imports hint at what this malware does? If so, which imports are they?

Analysing Lab01-01.exe through Dependency Walker highlighted a number of interesting functions imported from KERNEL32.DLL, these were:

• CopyFile
• FindFirstFile
• FindNextFile

Based on this we can infer that files would likely be searched for on the file system and files would be copied.

Analysing Lab01-01.dll through Dependency Walker highlighted functions imported from KERNEL32.DLL, these were:

• CreateProcess
• Sleep

Based on this we can infer that the dll would likely spawn a new process and sleep (pause execution) at some stage.

The DLL also had some interesting imports from WS2_32.DLL through the use of the ‘Ordinal Number’.

Matching the Ordinal Number to the associated name, these functions were:

• closesocket
• connect
• htons
• recv
• send
• shutdown
• socket
• WSAStartup
• WSACleanup

Based on this we can infer that the program has connects to a network or IP of some kind and opens up a socket to send and receive packets.

Question 5

Are there any other files or host-based indicators that you could look for on infected systems?

Examining the strings contained within Lab01-01.exe more closely reveals that it is referencing a file called C:\windows\system32\kerne132.dll. This is a very subtle misspelling of the legitimate Kernel32.dll file (notice the use of 1 instead of l) because of this it is likely malicious and we are able to use this to search for infected systems.

Question 6

What network-based indicators could be used to find this malware on infected machines?

Examining the strings contained within Lab01-01.dll more closely reveals that there is what appears to be an IP address. Because of this and the network imports, it is highly likely that this DLL contacts this IP address, and as such we are able to use this to find infected systems which have contacted 127.26.152.13.

Question 7

What would you guess is the purpose of these files?

Based on everything we’ve enumerated above, we would guess that the executable is used to run the DLL which acts as a backdoor or remote access trojan (RAT). Based on the imports it’s possible the executable searches to see if C:\windows\system32\kerne132.dll exists, and if it doesn’t it may attempt to copy the malicious DLL to C:\windows\system32\kerne132.dll which is used for persistence. Upon executing the DLL, it likely contacts a C2 server at 127.26.152.13.

Lab 1-2

This lab uses the file Lab01-02.exe. Analyze the file Lab01-02.exe.

Question 1

Upload the Lab01-02.exe file to http://www.VirusTotal.com/. Does it match any existing antivirus definitions?

Using the Malcode Analyst Pack we are able to perform this by simply right clicking the files and selecting VirusTotal. At the time of writing the file matched existing antivirus signatures:

lab01-02.exe

• 45/70 detection rate

Question 2

Are there any indications that this file is packed or obfuscated? If so, what are these indicators? If the file is packed, unpack it if possible.

Diving in with a different tool called Exeinfo PE, we are able to determine that this file is packed using the Ultimate Packer for eXecutables (UPX). This also gives me some information on how to unpack the executable using UPX.

In addition, we can use VirusTotal to view Section names, properties, a small number of imports, and a section with a raw size significantly smaller than the virtual size which all indicate that this file is packed with UPX.

Following the unpacking guidance, we can unpack this executable giving to a new file.

upx -d Lab01-02.exe -o Lab01-02-Unpacked.exe


Question 3

Do any imports hint at this program’s functionality? If so, which imports are they and what do they tell you?

Analysing Lab01-02.exe through Dependency Walker highlighted the below interesting functions:

WININET.DLL

• InternetOpenUrl
• InternetOpen

• CreateService
• StartServiceCtrlDispatcher
• OpenSCManager

Based on this we can infer that the executable creates and triggers a service, and that it connects to the internet.

Question 4

What host- or network-based indicators could be used to identify this malware on infected machines?

Looking at the strings of this file shows 2 interesting elements, ‘malservice’ and ‘http://www.malwareanalysisbook.com’.

Based on this we can assume that searching hosts for the scheduled service called ‘malservice’ and looking at any hosts connectiong to ‘http://www.malwareanalysisbook.com’ would serve as reliable host and network indicators.

Lab 1-3

This lab uses the file Lab01-03.exe. Analyze the file Lab01-03.exe.

Question 1

Upload the Lab01-03.exe file to http://www.VirusTotal.com/. Does it match any existing antivirus definitions?

At the time of writing this had an overwhelming number of AV detections.

Lab01-03.exe

55/65 detection

Question 2

Are there any indications that this file is packed or obfuscated? If so, what are these indicators? If the file is packed, unpack it if possible.

Once again, trying a different tool to keep things fresh, PE Detective revealed that this file was packed this time using FSG.

Using PEiD reveals that there are no import tables for the section like previously seen, which seems extremely strange. The raw hex almost looks like it is supposed to be importing something similar to loadlibrary and getprocaddress.

Looking at this through dependency walker revealed that these were indeed being imported. With only these libraries it is a very good indication that this binary is packed.

Question 3

Do any imports hint at this program’s functionality? If so, which imports are they and what do they tell you?

At present the file is packed with FSG, and we are unable to unpack this with the techniques learnt so far.

Question 4

What host- or network-based indicators could be used to identify this malware on infected machines?

At present the file is packed with FSG, and we are unable to unpack this with the techniques learnt so far.

Lab 1-4

This lab uses the file Lab01-04.exe. Analyze the file Lab01-04.exe.

Question 1

Upload the Lab01-04.exe file to http://www.VirusTotal.com/. Does it match any existing antivirus definitions?

Getting creative with our VirusTotal submissions, we can check the file hash by using the VirusTotal API and some basic PowerShell. At the time of writing this had 53 detections.

Question 2

Are there any indications that this file is packed or obfuscated? If so, what are these indicators? If the file is packed, unpack it if possible.

There are no indications this file is packed or obfuscated, PEiD identifies it was created with Microsoft Visual C++ 6.0, PEview shows similar virtual and raw data size, and dependency walker shows a number of imports.

Question 3

Using PEview we can see this program says it was compiled on the 30th of August 2019, and even as I type this years after the book was published that date is still a week away so this has obviously been faked or ‘timestomped’.

Question 4

Do any imports hint at this program’s functionality? If so, which imports are they and what do they tell you?

Based on the imports from Kernel32 we can see that this will load resources from the file’s resource section and write files to disk. Based on the GetWindowsDirectory function we can assume this will write files to the system directory, and will then execute them due to the WinExec function.

The imports from Advapi32 indicate that this is attempting to modify or change the token assigned to the execution of this process, presumably to elevate privileges or give extended access rights.

Question 5

What host-based or network-based indicators could be used to identify this malware on infected machines?

Looking into the strings of this file, we can see an entry for the following host indicators:

• winup.exe
• system32\wupdmgrd.exe

The strings also indicate the below network-based url which may be where a malware updater or second stage payload is pulled from.

• http://practicalmalwareanalysis.com/updater.exe

Question 6

This file has one resource in the resource section. Use Resource Hacker to examine that resource, and then use it to extract the resource. What can you learn from the resource?

Looking at this resource through Resource Hacker, we can see that it has a header which indicates it is an embedded executable.

By saving this as a binary (executable) file, we can then open it in dependency walker and see this is the file which not only contains the winexec imported function of kernel32, but also the URLDownloadToFile function of URLMON.DLL which indicates it will likely download and execute a file.

This concludes chapter 1.

Chapter 2. Malware Analysis in Virtual Machines

This chapter had no questions, but rather documented setting up a VM for malware analysis. Broadly speaking the process to follow is below:

• Create a clean snapshot without any malware.
• Transfer malware to the VM.
• Perform analysis from within the VM.
• Take notes, screenshots, and data from the VM, and move these back to your Host OS.
• Revert the VM back to the clean snapshot.

This concludes chapter 2.

Chapter 3. Basic Dynamic Analysis

This details analysis undertaken and answers to the lab questions in Chapter 3.

Lab 3-1

This lab uses the file Lab03-01.exe. Analyse this using basic dynamic analysis tools.

Question 1

What are this malware’s imports and strings?

Looking at a new tool, we’re able to open this up in PE Studio to gain a lot of insight into the file, and determine both its imports and strings.

Based on the low number of imports we can assume this file is packed.

If we take a look at the strings though we see a number of interesting entries which we typically wouldn’t expect to see on a packed file.

Question 2

What are the malware’s host-based indicators?

Attempting to run this file within a Windows 7 and Windows 10 VM causes it to crash and fail.

In todays day and age this piece of malware is detected by almost every AV available but also fails to run properly. This is because like a lot of malware it was created with a certain OS in mind (in this case Windows XP).

By running the malware in a Windows XP environment we are able to see what the original functionality of this file was:

The host based indicators are as follows:

• A Mutex - AKA Mutual Exclusion (this is essentially a lock on a resource), is created for “WinVMX32”.
• The malware is copied to a file called “vmx32to64.exe” which is dropped within C:\Windows\System32.
• A registry key is created at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\VideoDriver for persistence indicating whenever the system starts it should run the copied malware.

Question 3

Are there any useful network-based signatures for this malware? If so, what are they?

By directing our Windows XP traffic through another host we can use a utility such as Fakenet-NG or ApateDNS to intercept the requests.

Through doing this we can see the below:

• www[.]practicalmalwareanalysis[.]com is resolved

Had we allowed the malware to establish a connection we would see it sending random beacons of 256 bytes out of random data over port 443.

Lab 3-2

This lab uses the file Lab03-02.dll. Analyse this using basic dynamic analysis tools.

Question 1

How can you get this malware to install itself?

Using PE-bear we are able to easily see the exports of this DLL file. When comparing this with the imports shown in PEview it becomes quite clear that this DLL needs to be installed as a service.

To further validate our assumptions we can run strings over the DLL. Some key elements of interest are shown below:

Something to note is the reference to Windows XP 6.11, which means it’s once again likely this was created for, and will only work on, Windows XP.

Back in our Windows XP VM, we’re able to use rundll32.exe and the install exported function to execute this DLL and install it as a service.

rundll32.exe Lab03-02.dll,install


By using regshot we’re easily able to see the registry keys which have been modified by running the DLL.

Question 2

How would you get this malware to run after installation?

Given this has installed as a service and we know the name is IPRIP we can run it through either the net utility, or SC Tool.

sc start IPRIP
net start IPRIP


Question 3

How can you find the process under which this malware is running?

By searching for the specified DLL, or looking at the DLLs loaded by a process in Process Explorer, we’re able to get the process ID of the svchost process which is running this malware.

• 1068

Question 4

Which filters could you set in order to use procmon to glean information?

Because there’s likely to be multiple svchost processes, we can filter by the Process ID to glean information only on the svchost process responsible for running this malware.

Question 5

What are the malware’s host-based indicators?

By examining the service which is created we can get a number of host-based indicators.

• IPRIP
• Intranet Network Awareness (INA+)
• Depends INA+, Collects and stores network configuration and location information, and notifies applications when this information changes.
• HKLM\SYSTEM\CurrentControlSet\Services\IPRIP\Parameters\ /v servicedll

Question 6

Are there any useful network-based signatures for this malware?

By running Fakenet on the host we’re able to intercept the malware’s request and determine what it is sending to a remote server. In this case it uses a specified domain name, uses port 80, always fetches a specific file, and uses a custom but unique User-Agent.

• practicalmalwareanalysis[.]com
• port 80
• serve.html
• User-Agent %ComputerName% Windows XP 6.11

It’s at this point that the string previously discovered as ‘Windows XP’ has context.

Lab 3-3

Question 1

What do you notice when monitoring this malware with Process Explorer?

If we monitor this malware with Process Explorer we can see it briefly spawns svchost before both processes vanish.

At this point if we look closer into the memory strings of running svchost processes, we can see that this malware has used process replacement (more commonly known as process hollowing nowadays) to execute under the guise of a svchost process.

Question 2

Can you identify any live memory modifications?

As mentioned by looking into the live memory of svchost we can see the strings differ significantly on disk to what is in memory.

Question 3

What are the malware’s host-based indicators?

We can see both in memory, and on disk that the malware creates a file called practicalmalwareanalysis.log

• practicalmalwareanalysis.log

Question 4

What is the purpose of this program?

By opening wordpad and typing out some content, we can then open up practicalmalwareanalysis.log and see that it has logged all of our keystrokes.

From this we can conclude that this uses process hollowing to run a keylogger on the infected machine through svchost.exe

Lab 3-4

Question 1

What happens when you run this file?

When we run this file it immediately deletes itself. We can see this event coming from the program spawning a del (delete) command from a command prompt.

Question 2

What is causing the roadblock in dynamic analysis?

This could be caused by command line parameters needing to be passed to the program, it needing to fetch a particular file from a remote location, it detecting it is in a sandbox, it only targeting a particular timezone, or it only running on a specific domain. Some clues can be found by looking at the program strings.

Question 3

Are there other ways to run this program?

Attempting to run with the below enumerated through strings still results in the file being deleted, so at this stage we cannot do much more; however, this will be revisited in lab 9.

• cc
• re
• in

This concludes chapter 3.

Chapter 4. A Crash Course in x86 Disassembly

There are no questions in this chapter, but instead covers the following:

Levels of abstraction

• Hardware
• Microcode (firmware)
• Machine Code
• Low-level languages
• High-level languages
• Interpreted languages

Main Memory

• Data (DS - Data Segment
• Code (CS - Code Segment)
• Heap (dynamic memory)
• Stack (SS - Stack Segment)
• Extra (ES - Extra Segment)

Instructions

• made of a mneumonic and 0 or more operands
 Mnemonic Destination Operand Source Operand mov ecx 0x42

Opcodes and Endianness

• x86 uses little-endian format
• network data uses big-endian format

Operands

• Immediate operands (fixed values e.g. 0x42)
• Register operands (e.g. ecx)
• Memory address operands (e.g. eax)

Registers

x86 processors:

• General registers used by the CPU at execution
• Segment registers used to track sections of memory
• Status flags used to make decisions
• Instruction pointers used for process flow

x86 EAX Register Breakdown:

• EAX contains the value 0xA9DC81F5 (32bits)
• AX contains 81F5 (16bits)
• AH contains 81 (8 bits)
• AL contains F5 (8 bits)

EFLAGS Register:

• ZF: Zero flag, set to 1 when the output of an operation is equal to zero.
• CF: Carry flag, set to 1 when the output of an operation is too large or too small for the destination operand.
• SF: Sign flag, set to 1 when the output of an operation is negative, or when the most significant bit is set after an arithmetic operation.
• TF: Trap flag, when set to one the x86 processor will only execute 1 instruction at a time.

EIP Instruction Pointer:

• Contains memory address of next instruction to be executed

Note: The following sections have been added to support PMA material and understanding of 8-bit / 16-bit / 32-bit / 64-bit general-purpose registers and other common registers.

8-bit Register Usage

Register Common Name Purpose
AH Accumulator ‘High’ Register Used for arithmetic, operational, or result temporary storage.
AL Accumulator ‘Low’ Register Used for arithmetic, operational, or result temporary storage.
BH Base ‘High’ Register Used for pointing to a base (index) address within the data segment.
BL Base ‘Low’ Register Used for pointing to a base (index) address within the data segment.
CH Counter ‘High’ Register Used for operations that require looping, rotation/shifting, or string operations.
CL Counter ‘Low’ Register Used for operations that require looping, rotation/shifting, or string operations.
DH Data ‘High’ Register Used for Input/Output pointers and operations, similarly to AH.
DL Data ‘Low’ Register Used for Input/Output pointers and operations, similarly to AL.

16-bit Register Usage

Register Common Name Purpose
AX Accumulator Register Used for arithmetic, operational, or result temporary storage.
BX Base Register Used for pointing to a base (index) address within the data segment.
CX Counter Register Used for operations that require looping, rotation/shifting, or string operations.
DX Data Register Used for Input/Output pointers and operations, similarly to EAX.
SI Source Index Register Used for storing pointer to a location in Data Segment Register, or source of string or stream operations.
DI Destination Index Register Used for storing pointer to a location in Extra Segment Register, or destination of string or stream operations.
IP Instruction Pointer Register Used for keeping track of instructions within the Code Segment. Stores offset address of next instruction.
SP Stack Pointer Register Used for accessing values on the program Stack Segment. Stores offset of value on top of stack.
BP Base Pointer Register Used for accessing the base of the Stack Segment. Usually used in conjunction with an offset to get location of variables on stack.

32-bit Register Usage

Register Common Name Purpose
EAX Accumulator Register Used for arithmetic, operational, or result temporary storage.
EBX Base Register Used for pointing to a base (index) address within the data segment.
ECX Counter Register Used for operations that require looping, rotation/shifting, or string operations.
EDX Data Register Used for Input/Output pointers and operations, similarly to EAX.
ESI Source Index Register Used for storing pointer to a location in Data Segment Register, or source of string or stream operations.
EDI Destination Index Register Used for storing pointer to a location in Extra Segment Register, or destination of string or stream operations.
EIP Instruction Pointer Register Used for keeping track of instructions within the Code Segment. Stores offset address of next instruction.
ESP Stack Pointer Register Used for accessing values on the program Stack Segment. Stores offset of value on top of stack.
EBP Base Pointer Register Used for accessing the base of the Stack Segment. Usually used in conjunction with an offset to get location of variables on stack.

64-bit Register Usage

Register Common Name Purpose
RAX Accumulator Register Used for arithmetic, operational, or result temporary storage.
RBX Base Register Used for pointing to a base (index) address within the data segment.
RCX Counter Register Used for operations that require looping, rotation/shifting, or string operations.
RDX Data Register Used for Input/Output pointers and operations, similarly to EAX.
RSI Source Index Register Used for storing pointer to a location in Data Segment Register, or source of string or stream operations.
RDI Destination Index Register Used for storing pointer to a location in Extra Segment Register, or destination of string or stream operations.
RIP Instruction Pointer Register Used for keeping track of instructions within the Code Segment. Stores offset address of next instruction.
RSP Stack Pointer Register Used for accessing values on the program Stack Segment. Stores offset of value on top of stack.
RBP Base Pointer Register Used for accessing the base of the Stack Segment. Usually used in conjunction with an offset to get location of variables on stack.

Notes:

• In 64-bit mode R8 to R15 and XMM8 to XMM15 are new QWORD registers available.
• 32-bit DWORD registers can still be accessed with 32-bit variants of the above extra registers available through R8D to R15D.
• 16-bit WORD registers can still be accessed with 32-bit variants of the above extra registers available through R8W to R15W.
• 8-bit BYTE registers can still be accessed with 8-bit variants of the above extra registers available through R8L to R15L.

Simple Instructions

• Mov (move data around, e.g. into registers or RAM)
• mov destination, source
• Operands surrounded by [] are memory references to data
• mov eax, ebx (copies ebx into eax)
• mov eax, [0x4037C4] (copies 4 bytes at memory location 0x4037C4 into eax)
• mov eax, [ebx+esi4] (copies 4 bytes at memory location of the result from the equation ebx+esi4 into the EAX register) -lea (load effective address, similar to mov)
• put memory address into a location
• lea eax, [ebx+8]
• lea eax, [ebx+8] = mov eax, ebx+8 (except the mov command is invalid)
• useful when calculating values

Arithmetic:

• sub (subtract value from destination)
• sub destination, value
• inc (increase register by 1)
• inc register
• dec (decrease register by 1)
• dec register
• mul (multiply EAX by a value and store result in EDX:EAX) - imul is signed version
• mul value
• div (divides EDX:EAX by a value and store result in EAX with remainder in EDX) - idiv is signed version
• div value

x86 Logical Operators:

• OR
• AND
• XOR
• shr (shift bits right)
• shr destination count
• shl (shift bits left)
• shl destination count
• ror
• Similar to sh except bits are rotated to the other end instead of falling off
• rol
• nop
• 0x90, does nothing and goes to next instruction.

Shifting often used instead of multiplication as its faster and doesn’t require registers.

Generally functions containing only xor, or, shl, shr, ror, or rol randomly is a compression or encryption/encoding function.

The Stack

• Memory for functions, local variables and flow control is stored in stack.
• Last in First Out (LIFO) Structure.
• ESP = Stack Pointer (Changes as items are pushed on and off)
• EBP = Base Pointer (Stays constant within function)
• Stack Instructions.
• Push
• Pop
• Call
• Leave
• Enter
• Ret

Function Calls:

• Code to perform a specific task.
• Stack is used the same throughout any given binary.
• Most common convention is cdecl.
• Arguments pushed to stack.
• Call memory_location used to store current instruction onto stack and run function.
• Function prologue creates space on stack for local variables, and EBP.
• Function executes.
• Function epilogue restores stack and EBP, ESP frees local variables. Leave instruction can be used for this.
• Function calls the ret instruction which pops return address off stack and onto EIP.
• Stack is adjusted to remove arguments.

Stack Layout:

• Stack grows upward.
• Higher memory addresses used first.
• A new call = A new stack frame.
• x86 provides instructions for popping and pushing.
• pusha (Pushes 16-bit registers on stack in this order: AX, CX, DX, BX, SP, BP, SI, DI)
• pushad (Pushes 32-bit registers on the stack in this order: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI)
• popa
• pusha/pushad are typically seen in shellcode and often indicate hand coded shellcode/assembly.

Conditionals

• test (identical to AND, except operands are not modified)
• cmp (identical to SUB, except operands are not modified)
• ZF and CF may be modified as a result of cmp.

Branching

• Code executed depending on flow of the program.
• Most popular way is with jump instructions.
• jmp
• unconditional jump
• More than 30 types of conditional jumps exist, but only subset commonly seen.
• jz loc (Jump if ZF. Jump to location if ZF = 1)
• jnz loc (Jump if Not ZF. Jump to location if ZF = 0)
• je loc (Jump if Equal. Generally after cmp, jumps if destination operand = source operand)
• jne loc (Jump if Not Equal. Generally after cmp, jumps if destination operand != source operand)
• jg loc (Jump if Greater. Signed jump after cmp, jumps if destination operation > source operand)
• jge loc (Jump if Greater or Equal. Signed jump after cmp, jumps if destination operand >= source operand)
• ja loc (Jump if A. Unsigned jump, same as jg)
• jae loc (Jump if A or Equal. Unsigned jump, same as jge)
• jl loc (Jump if Less. Signed jump after cmp, jumps if destination operand is < source operand)
• jle loc (Jump if Less or Equal. Signed jump after a cmp, jumps if destination operand is <= source operand)
• jb loc (Jump if B. Unsigned jump, same as jl)
• jbe loc (Jump if B or Equal. Unsigned jump, same as jle)
• jo loc (Jump if OF. Jumps if previous instruction set the Overflow Flag)
• js loc (Jump if SF. Jumps if the Sign Flag is set)
• jecxz loc (Jump if not ECX. Jumps if ECX = 0)

Rep Instructions

• Used for manipulating data buffers.
• Usually array of bytes (b) or single (w) or double (d) words.
• Most common instructions:
• movs[b-w-d]
• cmps[b-w-d]
• stos[b-w-d]
• scas[b-w-d]
• ESI/EDI used in these operations.
• ESI = Source, EDI = Destination, ECX = Counting variable.
• rep will continue until ECX = 0.
• repe/repz/repne/repnz will continue until ECX = 0 or ZF = 1 or 0.
 Instruction Description rep Repeat until ECX = 0 repe, repz Repeat until ECX = 0 or ZF = 0 repne, repnz Repeat until ECX = 0 or ZF = 1

movsb is used to move bytes from 1 location to the next. Rep movsb is equivalent of memcopy in C. Movsb takes byte at ESI and stores it at EDI and increments/decrements ESI and EDI registers based on DF (Direction Flag). DF @ 0 = incremented, else decremented.

cmpsb is used to compare 2 sequences of bytes. It subtracts value at EDI from ESI and updates the flags. Cmpsb takes byte at ESI, compares to value at EDI and increments ESI/EDI registers by 1. Bundling this with rep is equivalent to memcmp in C.

scasb is used to search for 1 value in a sequence of bytes as defined within AL register. Compares ESI to AL. If found ESI stores location of those bytes.

stosb is used to store values in EDI specified location. Same as scasb, but byte not searched instead it is placed into EDI location. When bundled with rep, this is equivalent to memset in C.

 Instruction Description repe cmpsb Compare 2 buffers. EDI and ESI must contain buffer locations, and ECX = buffer length. Will continue until ECX = 0 or buffers aren’t equal. rep stosb Initialize all bytes of a buffer to a value. EDI = buffer location, and AL = Initialization Value. Often seen with xor eax, eax. rep movsb Copy a buffer of bytes. ESI = Source, EDI = Destination, ECX = Length to copy. Byte copy with continue until ECX = 0. repne scasb Search a data buffer for a byte. EDI = Address of buffer. AL = byte looking for. ECX = Buffer length. Comparison will continue until ECX = 0 or byte is found.

C Main Methods and Offsets

Malware is often written in C. A C program often has 2 arguments for the main method with argc and argv.

argc is an integer which contains number of arguments on command line. argv is a pointer to an array that contains command line arguments.

There’s also a couple of useful images at this point which show a simple program in C and what the main method looks like in Assembly, in addition to useful further reading.

This concludes chapter 4.

Chapter 5. IDA Pro

Interactive Disassembler Professional:

Tips:

• Options > General > Line Prefixes > (Opcode Bytes as 6) = helps show memory locations and opcode values in Graph Mode.
• L Function flag = Library and can be skipped.

Useful Windows:

• Functions: Associates flags with each function.
• Names: Every address and name including functions, data, strings, named code.
• Strings: Default, shows ASCII longer than 5 characters.
• Imports: Lists all imports.
• Exports: Lists all exported functions.
• Structures: Create own data structures or list layout of all data structures.

• Loc links: Jumps to destinations

Lab 5-1

Question 1

What is the address of DllMain?

Upon loading the DLL into IDA we arrive at the DllMain function, and can see the address in the functions window, or by turning on Line Prefixes under Options > General > Line Prefixes.

0x1000D02E

Question 2

Use the Imports window to browse to gethostbyname. Where is the import located?

By viewing the imports, searching for gethostbyname, and then looking for the address location, we find where this import is located.

0x100163CC within idata

Question 3

How many functions call gethostbyname?

We are able to find that this is run 9 times, by 5 different subroutines/functions.

Question 4

Focusing on the call to gethostbyname located at 0x10001757, can you figure out which DNS request will be made?

Looking at the operand before this function call, we can see that an address offset is being moved into EAX before 0Dh is added to it

By following this we can see that EAX now points to address 0x10019194 within data which contains: [This is RDO]pics.praticalmalwareanalysis.com

If we look at the value 0Dh which will be added to EAX, if we convert this hex to decimal it gives us the value 13, and the first 13 characters are [This is RDO].

Because the pointer (EAX) is moved along 13 bytes, we now know that the DNS request will be made for:

pics.praticalmalwareanalysis.com

Question 5

How many local variables has IDA Pro recognized for the subroutine at 0x10001656?

Jumping to the address at 0x10001656 we can find 20 different variables which IDA Pro Free has identified; however, it is important to note that a paid version of this product may identify more variables.

Question 6

How many parameters has IDA Pro recognized for the subroutine at 0x10001656?

Looking at the previous screenshot we can find that arg_0 has been identified which indicates one argument would be expected from this subroutine, and as a result 1 parameter.

Question 7

Use the Strings window to locate the string \cmd.exe /c in the disassembly. Where is it located?

Using ALT + T we can search through the strings window for cmd.exe, and we can find where it is located.

0x10095B34

Question 8

What is happening in the area of code that references \cmd.exe /c?

By following the xref to the subroutine which references \cmd.exe /c

We’re able scroll through the function to see a number of interesting values being pushed to the stack, in this case the values: quit, exit, and cd catch our eyes.

Continuing on we can see entries such as: idle, uptime, mmodule, minstall, and inject all catch out eyes.

Finally if we look around this function we can find that the char array aHiMasterDDDDDD mentioning a ‘Remote Shell Session’, and ass such we can infer we’re looking at a remote shell session function.

Question 9

In the same area, at 0x100101C8, it looks like dword_1008E5C4 is a global variable that helps decide which path to take. How does the malware set dword_1008E5C4? (Hint: Use dword_1008E5C4’s cross-references.)

Starting at address 0x100101C8 we can see a comparison statement comparing ebx to dword_1008E5C4, and viewing the cross-references to this we can find one of them which actually contain the mov statement to set the value.

Following this we can see that the output of sub_10003695 will be moved directly into dword_1008E5C4.

So by looking into this routine we can find that it is comparing the dw platform ID to the value ‘2’:

By running some searches based on this we find the following documentation on PlatformID

This tells us that the field 2 indicates the operating system is Windows NT or later.

As such we now know the malware will take a different path depending on whether the operating system is Windows NT or later.

Question 10

A few hundred lines into the subroutine at 0x1000FF58, a series of comparisons use memcmp to compare strings. What happens if the string comparison to robotwork is successful (when memcmp returns 0)?

Looking into this routine we can find the entry comparing “robotwork” which uses a JNZ branch.

The JNZ branch will jump if the Zero Flag is NOT SET (in this case that means the comparison is successful). This is because when we’re talking about Zero Flags, we’re essentially asking “Is this false?”, and if it is true (1=True), the Zero Flag IS NOT set, if it is false (0=False) then the Zero Flag IS set.

Because of this, if memcmp returns 0, the answer to the question “Is this false?” will be no, thus indicating a successful comparison. Because of this the jump is NOT taken, and we end up running a call to the subroutine sub_100052A2, so let’s take a look into it.

From this we can see that it is opening a registry key at: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion. The JZ statement is once again asking “Is this false?” which in this case would check if the registry was successfully opened or not. So long as the registry is successfully opened, the answer would be “False”, “No”, or in terms of the Zero-Flag “0”. The difference here is that it is jumping if the zero flag IS set, so let’s follow loc_10005309.

Here we can see it is querying WorkTime, and WorkTime registry keys. If we look back at where this opened the registry key we can see that it is passing an argument type of “Socket” with the value ‘s’. Looking back at the start of this question we can see that this pushes ebp+s which indicates this information is sent back over the passed network socket.

Question 11

What does the export PSLIST do?

By looking into the exports within this DLL we can find PSLIST. Following this and pressing SPACE leads us to the IDA Graph view.

From here we can see that one of 2 paths will be taken depending on the result of sub_100036C3, so let’s dive a bit deeper there.

Once again we can see this is checking whether the operating system is Windows NT or later; however, even if it is, it is then checking if it’s major version is 5. So let’s look at what this represents by looking at the documentation on OSVERSIONINFOEXW structure

So we now know it is checking whether the OS is any of these versions. Depending on the output it will either run sub_10006518 or sub_1000664C.

Taking a closer look at sub_10006518 we can see based on the API call to CreateToolhelp32Snapshot, strings, and the function name that this will allow them to grab a process listing.

Looking further at sub_1000664C, we can see that this performs the same type of calls as sub_10006518; however, this also sends through reference to the socket to send the output back to.

Question 12

Use the graph mode to graph the cross-references from sub_10004E79. Which API functions could be called by entering this function? Based on the API functions alone, what could you rename this function?

By using G to go to the address of interest (in this case sub_10004E79), we can then click View > Graphs > XRefs From to see a number of API functions within this function.

Based on this we can infer that it is more than likely the System Default Language Identifier would be sent over a network socket, and as such could name this function as LanguageIdentifier_Send.

Question 13

How many Windows API functions does DllMain call directly? How many at a depth of 2?

By clicking View > Graphs > User xrefs chart, and then adjusting the settings to start and end at the function DLLMain with a depth of 1, we’re able to see 4 Windows API Functions.

If we expand this to a depth of 2, the chart blows out in size and we’re looking at 33 including duplicates.

Question 14

At 0x10001358, there is a call to Sleep (an API function that takes one parameter containing the number of milliseconds to sleep). Looking backward through the code, how long will the program sleep if this code executes?

Moving back from the call to sleep, we can see that EAX is multiplied by 1000 before being pushed to the stack and called. This matches the reference to milliseconds, in that there are 1000 milliseconds in a second.

If we follow the previous routine at offset 10019020 (off_10019020), we see it points to the data reference unk_100192AC.

At present this is a bit confusing as it is made up of individual parts to a much larger string, but if we go ahead and convert this to the string it is supposed to be.

We can now see that it has the value [This is CTI]30 which is much clearer.

Looking back at the commands it is then adding 0Dh (13) to EAX which moves the pointer past the text ‘[This is CTI]’ leaving only ‘30’.

Based on the call to atoi this is then converted to a number before being multiplied by 1000 and as such the program will sleep for 30 seconds if this executes.

Question 15

At 0x10001701 is a call to socket. What are the three parameters?

Looking at this address we can see a call to socket which takes 3 parameters (protocol, type, and af) all of which are pushed to the stack prior to the call.

Question 16

Using the MSDN page for socket and the named symbolic constants functionality in IDA Pro, can you make the parameters more meaningful? What are the parameters after you apply changes?

By looking into the MSDN Socket Function we can find what these numbers correlate to.

By right clicking and selecting Use Standard Symbolic Constant, we’re able to quickly change these to accurately reflect their assigned values.

Question 17

Search for usage of the in instruction (opcode 0xED). This instruction is used with a magic string VMXh to perform VMware detection. Is that in use in this malware? Using the cross-references to the function that executes the in instruction, is there further evidence of VMware detection?

By searching for ‘ED’ as a sequence of bytes (ALT+B) we can find only one occurrence of the instruction ‘in’.

Diving into this function we can see it is checking for the value VMXh which indicates this malware is implementing a known anti VM technique.

Looking at the Xrefs to this function we can see a reference to locating a VM in use and cancelling installation.

Question 18

Jump your cursor to 0x1001D988. What do you find?

If we jump here using ‘G’ we find a bunch of seemingly random data.

Question 19

If you have the IDA Python plug-in installed (included with the commercial version of IDA Pro), run Lab05-01.py, an IDA Pro Python script provided with the malware for this book. (Make sure the cursor is at 0x1001D988.) What happens after you run the script?

At present we’re running this through the free version of IDA Pro, so we’ll be unable to do this; however let’s open up the script and see if we can see what it is doing.

From this we can see it will loop through from our current position (0x1001D988) up to 50 bytes and run an XOR command over all of them by 0x55. From this we can infer that the script will de-obfuscate the seemingly random data.

Question 20

With the cursor in the same location, how do you turn this data into a single ASCII string?

This can be done by pressing A on the string or doing so like we did earlier with CTI30. By converting all strings to ascii we wind up with gibberish still because each element still requires the XOR function.

We can also see there’s been some overlap of hex indicated by the ,27h,’ elements. By removing these and running the XOR command over all of the strings concatenated using CyberChef(https://gchq.github.io/CyberChef/) we get a hidden message.

Question 21

Open the script with a text editor. How does it work?

In this instance we can see that there’s been some issues bringing back any capitalisation somewhere along the line and this should read “xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234”. This is yet another benefit of us running this through the python script; however, the purpose still stands based on how the python script works. It will loop through from our position (0x1001D988) up to 50 bytes and run an XOR command over all of the values individually by 0x55

This concludes chapter 5.

Chapter 6. Recognizing C Code Constructs in Assembly

Global vs. Local Variables

• Global Variables referenced by memory addresses (e.g. dword_40CF60)
• Local Variables referenced by stack addresses (e.g. ebp-4)

Disassembling Arithmetic Operations

The below outline basic arithmetic operations and ways of remembering them within assembly.

Assigning variables (int a = 0; int b = 1;):

• mov [ebp+var_4], 0 (int a = 0)
• mov [ebp+var_8], 1 (int b = 1)

Addition of variables (a = a + 11;):

• mov eax, [ebp+var_4] (a =)
• add eax, 0Bh (a + 11)

Subtraction of variables (a = a - b;):

• mov ecx, [ebp+var_4] (a =)
• sub ecx, [ebp+var_8] (a - b)

Decrementing variables (a–;):

• mov [ebp+var_4], ecx (null)
• mov edx, [ebp+var_4] (a =)
• sub edx, 1 (a - 1)

Incrementing variables (B++;):

• mov [ebp+var_4], edx (null)
• mov eax, [ebp+var_8] (b =)
• add eax, 1 (b + 1)

Modulo variables (b = a % 3):

• mov [ebp+var_8], eax (null)
• mov eax, [ebp+var_4] (a =)
• cdq (convert value)
• mov ecx, 3 (3)
• idiv ecx (a / 3)
• mov [ebp+var_8], edx (b = remainder)

Recognizing if statements

Must be a conditional jump (e.g. jnz) for an if statement, but not all conditional jumps are if statements.

Recognizing nested if statements

Every if statement corresponds to a jump of some kind, so in this case there’s 3 close compare (cmp) and then jump (jnz) statements.

Finding for loops

Must have 4 components; initialise, compare, execute, and increment/decrement.

Finding while loops

This looks similar to a for loop, except without incrementation.

Function call conventions

Calling convention differs based on compiler and other factors.

3 most common calling conventions are:

• cdecl
• stdcall
• fastcall

cdecl convention

One of the most popular. Params pushed onto stack from right to left, and caller cleans up the stack at end.

stdcall convention

Similar to cdecl, except callee needs to clean up stack. This is the standard convention for the Windows API, and as such when calling them you don’t need to clean up the stack as the DLLs which implement the API will clean up the stack.

fastcall convention

Varies most across compilers. First couple of arguments are passed in registers (e.g. EDX or ECX). Any other arguments are loaded right to left. Calling function responsible for cleaning up stack. Generally faster.

Push vs Move

The differences are generally based on the compiler or compiler settings, sometimes parameters are pushed onto the stack, other times they are moved onto the stack. In cases of push, there’ll be an additional instruction to restore the stack pointer which won’t be present in the move.

Switch statements

Compiled either using an ‘if’ or using ‘jump tables’. Will have multiple compare and jump statements close to one another, and any ‘false’ result leads the next compare to happen.

Jump Table

Has a large amount of switch statements and avoids the need for so many compares. In this case a ‘false’ result leads to the jump statement which dynamically points to a location.

Disassembling Arrays

Globally and locally defined arrays appear different. Globally defined may have a base address within ‘dword_XXXXXX’, and locally may have a base address within var_XX. In both cases accessing these arrays has ecx multiplied by the element size (in the case of integers this is 4).

Identifying Structures aka Structs

Similar to arrays but can contain different element types. Generally used to group information. Nearby data types may or may not be part of the struct. ‘fld’ or ‘fstp’ are floating point instructions which indicate this type is a double. ‘T’ key in pro can be used to create a structure.

Linked List is data structure with data records which contain a reference (link) to the next record in the sequence. Recursive object assignments help to identify this, for example a recursive loop where a variable is assigned eax, which then becomes eax+4 may be indicative of the variable having a pointer 4bytes in.

Lab 6-1

Analyse Lab06-01.exe

Question 1

What is the major code construct found in the only subroutine called by main?

By starting at the main function we can see that a subroutine 401000 is called.

Moving into this routine we see that there is a compare statement before a JZ jump statement, and by using the graph view we can verify that this is indicative of an ‘if’ code construct.

Question 2

What is the subroutine located at 0x40105F?

By looking at the values being pushed to the stack prior to calling this function we can begin to make some assumptions that this subroutine relates to printing some sort of message which is delimited by a line feed (\n).

If we dig slightly into this function we can see reference to ‘__stbuf’ and ‘__ftbuf’ which in the context of things leads us to believe this is ‘string buffer’ and ‘format buffer’. A quick search leads us to these being declared inside of the resource internal.h within the .NET Core.

.NET Core Runtime - internal.h

From this we can see it provides support for input/output of files, and if we compare this to the function references in this context we can make an informed decision that this is in fact the ‘printf’ (print formatted) subroutine, which writes the string to stdout.

Question 3

What is the purpose of this program?

Based on what we can see in the success or error messages that were pushed to the stack, this program checks if you are connected to the internet, and responds with a corresponding message in addition to returning the number ‘1’, if you are connected.

Lab 6-2

Analyse Lab06-02.exe

Question 1

What operation does the first subroutine called by main perform?

Taking a look at the main function, we can see that it calls ‘sub_401000’.

This subroutine calls ‘InternetGetConnectedState’, and then compares if the output of it is equal to 0. Then it will jump if the internet connection is present to one of 2 messages. As such this operation is an ‘if’ statement.

Question 2

What is the subroutine located at 0x40117F?

If we look at this subroutine we notice that it is almost identical to that which we saw in Lab06-01.exe, and once again comparing a string pushed to the stack just before calling this subroutine within main leads us to believe this is once again ‘printf’. In this instance there’s also the usage of ‘%c’ to help backup this inference.

Question 3

What does the second subroutine called by main do?

We can see that the second subroutine is ‘sub401040’. By looking at this we can see that this attempts to open the URL http://www.practicalmalwareanalysis.com/cc.htm and if it is successful, it will read in the first 0x200 (512) bytes into a buffer.

Question 4

What type of code construct is used in this subroutine?

If we look under the call to ‘InternetReadFile’ we can see 2 different pathways, one where it was able to read the HTML ‘file’, and one where it failed.

If we look at the code construct under where it successfully read the HTML file, we can see that there are multiple compare statements based on 4 characters from the buffer. This indicates an array of characters is being parsed, and if we view the compare characters by using ‘R’ to convert the hex to ascii, we see some interesting characters.

We know that within HTML ‘<!–’ signals the start of a comment.

Question 5

Are there any network-based indicators for this program?

As shown in question 3, there’s 2 obvious network indicators we can use within this program, which is the URL to be opened, and the User-Agent.

• http://www.practicalmalwareanalysis.com/cc.htm
• Internet Explorer 7.5/pma

Question 6

What is the purpose of this malware?

The purpose of this malware is to check if there is an active internet connection, if there is it will proceed to try and open the URL http://www.practicalmalwareanalysis.com/cc.htm using the User-Agent ‘Internet Explorer 7.5/pma’ and if it is successful, it will read in the first 0x200 (512) bytes into a buffer, if not it will terminate. From this buffer the characters ‘<!–’ are read, and if they don’t exists the error message “Error 2.3: Fail to get command\n” is printed.

If these do exist, it will print the message “Success: Parsed command is %c\n”, where %c is the character read from the HTML comment buffer. We can also see this will wait 60000 milliseconds (1 minute) before terminating.

Lab 6-3

Analyse Lab06-03.exe

Question 1

Compare the calls in main to lab 6-2’s main method. What is the new function called from main?

Examining the calls in Lab6-2 and Lab6-3 show a number of similarities; however, 1 subroutine exists in Lab6-3 which is new and is called “sub_40113”.

Question 2

What parameters does this new function take?

Looking at the function, we can see that it takes 2 parameters, a ‘char’ value, and a ‘lpcstr’ value (long pointer constant string).

If we examine how this is being invoked, we can see 2 items are pushed to the stack before calling this subroutine; argv, and var_8.

In this instance argv represents argv[0] which points to the name of the program. We can also see that var_8 is set to AL in 0x401228. This means that the lower 8 bits (byte, or character in this case) from sub_401040 becomes var_8, and given we know sub_401040 allocates bytes to a buffer, and then checks for ‘<!–’, we can then see that the next byte after ‘<!–’ is the char being passed to this function.

Question 3

What major code construct does this function contain?

Looking at this function we can see that it contains a switch statement with a Jump Table, this is indicated by a lack of repeated compare and jump statements, which is evident in an ‘if-else’ scenario, and instead contains one compare and jump statement with multiple locations it could end up jumping to.

Question 4

What can this function do?

If we break down this function, we can see that it subtracts ‘a’ from whatever is passed to it, therefore if it is ‘a’, it will have a value of ‘0’ and be the first jump case, b will equal 1 and be the second case and so forth.

In the case of this function, depending on the letter you send it (after ‘<!–’ in the HTML), between ‘a’ and ‘e’, it will run a different set of commands.

• a = The program create’s a directory at C:\Temp if it doesn’t exist
• b = The program will copy a file to C:\Temp\cc.exe, the file passed is lpExistingFileName which we know would be the program name
• c = The program will delete the file located at C:\Temp\cc.exe if it exists
• d = The program creates persistence using the subkey Software\Microsoft\Windows\CurrentVersion\Run with the value ‘Malware’ pointing to C:\Temp\cc.exe
• e = The program sleeps for 100,000 milliseconds (100 seconds)

If the program fails to get these instructions or it fails, it will display an error message.

• Error 3.2: Not a valid command provided

Question 5

Are there any host-based indicators for this malware?

The host based indicators from this are the file the malware will copy itself to, and the registry key used for persistence.

Note: A quick search reveals that 80000002h which is pushed to the stack in the registry key is linked to HKEY_LOCAL_MACHINE, so we can assume it will be here rather than the users registry hive.

• C:\Temp\cc.exe
• HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v Malware

Question 6

What is the purpose of this malware?

The purpose of this malware is to check if there is an active internet connection, if there is it will proceed to try and open the URL http://www.practicalmalwareanalysis.com/cc.htm using the User-Agent ‘Internet Explorer 7.5/pma’ and if it is successful, it will read in the first 0x200 (512) bytes into a buffer, if not it will terminate. From this buffer the characters ‘<!–’ are read, and if they don’t exists the error message “Error 2.3: Fail to get command\n” is printed. If these do exist, it will print the message “Success: Parsed command is %c\n”, where %c is the first character read from the HTML comment buffer.

Based on the parsed command between the letters a and e, the program will either:

• Create a directory at C:\Temp if it doesn’t exist
• Copy a file to C:\Temp\cc.exe, the file passed is lpExistingFileName which we know would be the program name
• Delete the file located at C:\Temp\cc.exe if it exists
• Create persistence using the subkey HKLM\Software\Microsoft\Windows\CurrentVersion\Run with the value ‘Malware’ pointing to C:\Temp\cc.exe
• Sleep for 100,000 milliseconds (100 seconds)
• Display the error message “Error 3.2: Not a valid command provided”

Lab 6-4

Analyse Lab06-04.exe

Question 1

What is the difference between the calls made from the main method in Labs 6-3 and 6-4?

In Lab 6-3 the calls directly from the main method consist of:

• sub_401000
• sub_401040
• sub_401271
• sub_401130
• Sleep

In Lab 6-4 the calls directly from the main method consist of:

• sub_401000
• sub_401040
• sub_401150 (differs)
• sub_4012B5 (differs)
• Sleep

Looking into these methods we find that:

• sub_401000 = Check for internet connection
• sub_401040 = HTML C2 parsing function. Note: in 06-04 the User-Agent has changed.

• sub_401150 (differs) = Jump Table switch statement as previously identified in Lab 06-03 sub_401130 to control actions.

• sub_4012B5 (differs) = printf as previously identified in Lab 06-03 sub_401271.

Question 2

What new code construct has been added to main?

Looking into the main method we can see one clear change, and that’s the addition of a loop, which in this case is a for loop indicative by the flow returning and and incrementing variable which will be compared against the value 5A0h in hex (1440).

Question 3

What is the difference between this lab’s parse HTML function and those of the previous labs?

Looking at this lab’s parse HTML function, the first difference we can see is that it now takes in an argument as apparent with the reference to arg_0, and a new variable szAgent.

Looking further we can see that this is actually used now in the User-Agent which we previously identified had changed and that szAgent is being populated with the formatted user agent value.

This differs from the previous which didn’t take any argument and never changed.

Question 4

How long will this program run? (Assume that it is connected to the internet.)

The for loop in this case is comparing against the value 1440. Because computers are so fast the time it takes to run this amount of checks is negligible; however, we can also see that the program sleeps for 0EA60h (60,000) milliseconds in between each check.

Due to this we can assume the program will run for 1440 * 60,000 milliseconds = 86,400,000 milliseconds.

This number doesn’t make a lot of sense so let’s convert, 60,000 milliseconds is 1 minute. So for 1440 minutes, if we divide by 60 we find that this will run for 24 hours.

Question 5

Are there any new network-based indicators for this malware?

As mentioned in question 3, this has a new User-Agent, so the User-Agent:

Internet Explorer 7.50/pma%d

will be a new indicator, where %d is equivalent to var_C or in this case the number of minutes that have passed since the program started. This can be used to monitor how long it has been running for in each request.

Question 6

What is the purpose of this malware?

The purpose of this malware is to check if there is an active internet connection, if there is it will proceed to try and open the URL http://www.practicalmalwareanalysis.com/cc.htm using the User-Agent ‘Internet Explorer 7.5/pma%d’ which is passed in from a looping incremental user variable (this is used to track how long the program has been running.

If it is successful, it will read in the first 0x200 (512) bytes into a buffer, if not it will terminate. From this buffer the characters ‘<!–’ are read, and if they don’t exists the error message “Error 2.3: Fail to get command\n” is printed.

If these do exist, it will print the message “Success: Parsed command is %c\n”, where %c is the first character read from the HTML comment buffer.

Based on the parsed command between the letters a and e, the program will either:

• Create a directory at C:\Temp if it doesn’t exist
• Copy a file to C:\Temp\cc.exe, the file passed is lpExistingFileName which we know would be the program name
• Delete the file located at C:\Temp\cc.exe if it exists
• Create persistence using the subkey HKLM\Software\Microsoft\Windows\CurrentVersion\Run with the value ‘Malware’ pointing to C:\Temp\cc.exe
• Sleep for 100,000 milliseconds (100 seconds)
• Display the error message “Error 3.2: Not a valid command provided”

Based on the incrementing variable this program will run for 24hours before terminating. By renaming these functions and viewing the main method flow chart, we can easily see the flow of this malware.

This concludes chapter 6.

Chapter 7. Analyzing Malicious Windows Programs

Lab 7-1

Analyze the malware found in the file Lab07-01.exe.

Question 1

How does this program ensure that it continues running (achieves persistence) when the computer is restarted?

By examining the main function of this program, we can see reference to a service name ‘MalService’, a call to start the Service Control Dispatcher with the service control function sub_401040, and an associated call to a subroutine.

Within this subroutine we can see references to opening the Service Control Manager (SC Manager) and evidence of a service creation which will be used for persistence.

Question 2

Why does this program use a mutex?

The program uses a mutex to enmsure that only one instance of the program is running at any one time. The program attempts to get a handle on the mutex ‘HGL345’, and if it succeeds the program will terminate. If not, it will create a Mutex with this name.

Question 3

What is a good host-based signature to use for detecting this program?

Detection of this program can be done by checking any host for the hardcoded mutex ‘HGL345’ or by checking them for any service with the hardcoded name ‘MalService’.

Question 4

What is a good network-based signature for detecting this malware?

By examining the looping function of this program, we can see that it uses the User Agent “Internet Explorer 8.0” and communicates with the URL “http://www.malwareanalysisbook.com” which are network-based indicators which can be used to identify execution of this program.

Question 5

What is the purpose of this program?

By examining the program’s execution after creating a service for persistence, we can see that it sets up a timer checking for when the year is 2100 (834h), or midnight on January 1st 2100. At this time it will create 20 (14h) threads and with them execute the subroutine pointed to by ‘StartAddress’.

This routine attempts to open the URL http://www.malwareanalysisbook.com which leads us to believe that this is some sort of Denial of Service (DoS) program, which when multiple machines have this setup will cause a DDoS against http://www.malwareanalysisbook.com

Question 6

When will this program finish executing?

Looking back at the looping function mentioned previously, this function has no compare statement, and is an unconditional jump statement which runs the routine again. Based on this the program will never finish executing.

Lab 7-2

Analyze the malware found in the file Lab07-02.exe.

Question 1

How does this program achieve persistence?

When examining the program, we can’t see any evidence of persistence being created. The program shows no evidence or strings relating to creation of common persistence mechanisms such as run keys, scheduled tasks, services, or startup files.

Question 2

What is the purpose of this program?

Based on the program executing OleInitialize, we can infer that this has execution of a COM Object, as this initialises the COM Library.

By viewing further we can see this indeed creates an object which is then passed execution of the string: http://www.malwareanalysisbook.com/ad.html

Based on this we can begin to assume this initialises a COM object (likely Internet Explorer) and uses this to open a URL with ad.html, which may infer this is associated with an advertisement. By running the executable we can confirm our assumptions are correct.

Question 3

When will this program finish executing?

The program finishes executing after it is run and the webpage is opened. It’s likely this is part of adware which has been dropped on a users machine, potentially as part of further bundled software or malware.

Lab 7-3

Analyze the malware found in the files Lab07-03.exe and Lab07-03.dll

Question 1

How does this program achieve persistence to ensure that it continues running when the computer is restarted?

When examining the program and associated DLL we once again cannot see any obvious evidence of persistence; however there’s some elements which raise suspicions. First off the program shows reference to the DLL supplied with it (Lab07-03.dll), in addition to a well-known Windows DLL of kernel32.dll.

By examining the rest of the application, we can see reference to a similar, yet different DLL name of kerne132.dll, and reference to the supplied Lab07-03.dll DLL being copied into a file with this name at C:\Windows\System32 before we see a reference to subdirectories within C:\.

By looking inside the function call to sub_4011E0, within this we can see a statement that indicates files are being checked within C:\* which was passed to the program.

At this point a lot of comparisons and jump statements occur; however, this is of no interest to our analysis. By searching further within this function, we can see that a comparison occurs that checks if a file is a .exe, and if not a jump occurs.

Based on this we can infer that something the file system located at C:\ is being recursively checked for .exe files, and if one is found something occurs. By checking the function sub_4010A0 which runs if the jump is not performed, we can gather what occurs when an executable file is found. 3 key calls we find are CreateFile, CreateFileMapping, and MapViewOfFile.

Based on this we can infer that if an executable file is located, it is is mapped into memory and can then be modified by this program. Looking further at the program we can see that it compares kernel32.dll to a location within the executable, and if it isnt found, it will jump and repeat the process. Where it is found it proceeds to copy a value referenced by dword_403010 over the top of it.

Looking into this IDA believes it is a DWORD value specified as ‘6E72656Bh’.

By converting this to an ASCII string using ‘A’ or Edit > Strings > ASCII, we can see that it translates to something more legible.

With this we can infer that the program searches for executables recursively within C:\, and when they’re found it will open them, and directly in memory modify the file to replace any instances of kernel32.dll with kerne132.dll for persistence. Based on this we can infer the program is a type of file infector and uses the copied kerne132.dll (Lab07-03.dll) for its main payload. A brief look into Lab07-03.dll confirms that this has some form of C2 function and is likely a malicious implant used in tandem with this executable.

Question 2

What are two good host-based signatures for this malware?

Two good host-based signatures for this malware include the presence of kerne132.dll on disk, and the presence of Mutex ‘SADFHUHF’ which can be found within Lab07-03.dll.

Question 3

What is the purpose of this program?

From what we’ve gathered in question 1, we can conclude that this program is a file infector that infects executables on the system to load a malicious remote access trojan that connects back to the IP 127.26.152[.]13. By examining Lab07-03.dll, we can conclude that this trojan takes either the command sleep, or exec, which is used to start a process of interest.

Question 4

How could you remove this malware once it is installed?

Due to the malware infecting every executable on disk it is very difficult to remove. You could remove the malicious kerne132.dll from disk; however, it’s likely this will be in use by every process and be unable to be removed. Further if it is removed during deadbox analysis, it is likely the system will crash when booting due to no variant of kernel32.dll being present. To remediate you’ll be able to modify kerne132.dll to be the legitimate kernel32.dll, or even change the malware actions and recompile to instead modify all executables to point to the legitimate kernel32.dll instead of kerne132.dll. As another resort it may be easier to rebuild the system or restore from backup.

This concludes chapter 7.

Chapter 8. Debugging

Source-Level vs. Assembly-Level Debuggers

• Source-Level = Used within an Integrated Development Environment (IDE) during development
• Assembly-Level = Used to operate on compiled binaries and their associated assembly code

Kernel vs. User-Mode Debugging

• Kernel debugging is performed on 2 systems, as a breakpoint in kernel debugging would cause system to crash. WindDbg is a popular tool that supports kernel debugging.
• OllyDbg is a popular debugger. This is useful for user mode debugging on single compiled binaries.
• A newer popular debugger is x64dbg. Once again this is useful for user mode debugging on single compiled binaries.

Using a Debugger

Single-Stepping

This is what is used for running a single assembly instruction.

Stepping-Over vs. Stepping-Into

• Step-Over = Bypass every instruction of sub-function and move to next instruction after sub-function returns.
• Step-Into = Step into a sub-function/call and see the first instruction of called function.

Pausing Execution with Breakpoints

• Breakpoints = Pause execution of program at instruction.

Software Execution Breakpoints

Most common, the debugger performs this by overwriting the first byte of an instruction with 0xCC (Int 3) which is a breakpoint used by debuggers. If this is modified during code execution then the breakpoint will be overwritten and removed.

Hardware Execution Breakpoints

x86 (32-bit) programs support hardware registers and hardware breakpoints. Hardware breakpoints work by checking addresses in the register and breaking where specified. Only 4 hardware addresses store hardware breakpoints.

Conditional Breakpoints

Created as software breakpoints based on comparing data on the stack. This is based on an instruction and whenever the instruction occurs it is checked. If this is accessed often will slow down a program from running.

Exceptions

First and Second Chance Exceptions

• First Chance Exception = If an exception handler is registered it first catches an error and can choose to handle it a certain way (e.g. by ignoring or passing to an output the user can see). This occurs when no debugger is attached.
• Second Chance Exception = If an exception occurs and it is passed as a second chance exception, it means a debugger will catch it and the program would have crashed if this wasn’t the case.

Common Exceptions

• Most common is Int 3 exceptions (When debugger attached this gets first exception chance, e.g. a breakpoint).
• Single stepping also generates an exception based on instructions with “trap flag” set.
• Memory-access violation may occur based on incorrect memory address, or because of Access protections.

Modifying Execution with a Debugger

Common is implementing breakpoints and modifying instruction pointers (EIP Registers) to ignore functions.

Modifying Program Execution in Practice

Can add a breakpoint before a compare statement and modify the value of a register (e.g. EAX) being compared.

This concludes chapter 8.

Chapter 9. OllyDbg

Analyze the malware found in the file Lab09-01.exe using OllyDbg and IDA Pro to answer the following questions. This malware was initially analyzed in the Chapter 3 labs using basic static and dynamic analysis techniques.

Lab 9-1

Question 1

How can you get this malware to install itself?

Opening up the malware in OllyDbg we can see that it immediately pauses as soon as it hits the specified executable entry point.

By examining the function at address 0x403945 we can see that 3 arguments are available to be passed to the program and what looks to be the start of the main function.

Using F8 we can step over instructions of the program, and once we reach the instruction past ‘GetCommandLine’, we can see that EAX has been updated to reflect the program command line, which in this case was running the application without any arguments.

Once we reach the main function, if we press F8 the program runs through it which isn’t what we want. By pressing F7 we can step into the function to continue analysis with F8.

Upon hitting 0x402AFD we can see a comparison takes place to see if the number of arguments passed to the program is equal to one.

As no arguments were passed the comparison fails. As such a jump is not taken and the program continues to call 0x401000.

Once again by stepping into this with F7 we can examine some more. Inside this function stands out a particular check for what looks to be a typo’d registry key ‘HKLM\SOFTWARE\Microsoft \XPS’. As this doesn’t exist the jump statement after is never taken and we instead jump to 0x401066 (once again we can step into this with F7).

After this a return occurs and after a few more comparisons we wind up at 0x402410. By stepping through this once more, using F8 to skip Windows API calls as required, we find that the malware begins to build an instruction designed to delete the malware as it was run without any kind of parameters. This is a common anti-analysis technique.

Because we’re running the program in OllyDbg an open handle exists on the program and deletion fails.

At this point we know that running the program is not enough to install it, so we re-examine the comparisons undertaken when the program runs, first up is ‘-in’.

By using Debug > Arguments, we can add in -in as a command line argument and restart using CTRL+F2. Once again we move through analysis, except this time a Jump is taken, and we can see a comparison will be run on our provided argument ‘-in’.

Looking inside of 0x402510 which is called we can see that a number of arithmetic operations occur but no functions are called. In this instance it looks to be a check for certain characters, so we can assume that ‘-in’ may be for installing the malware, and this may be checking for some sort of password. What we’re aiming to achieve from this function is to return EAX with a value of 1 (signifying a success in relation to the calling conditions). Highlighted in red are conditions that if evaluated will jump past the statement that sets EAX to 1. Highlighted in blue is our end goal, but as we can see straight away the first comparison fails and we jump straight to the end of the function without setting EAX to 1.

One way to completely bypass the check is to patch it so that it returns with EAX = 1, or by modifying the value of EAX to return one after the checks fail.

This time by stepping through we can see that a jump does occur and we move past 0x402410 that executes binary deletion.

Stepping through we hit another function at 0x40380F. If we continue to step through this we will see more comparisons taking place to ensure that the parameters provided match expected parameters of the program. This passes; however, at one point we will find ourself falling back into 0x402410 again due to a comparison that checks if more than 3 elements have been passed to the program (noting that the application name is passed as an argument). Due to the comparison failing we wind up again in a state of deletion.

Repeating the process once more except with any random given parameter for the password we can meet this requirement and continue with application installation.

With this we now see that a jump doesn’t occur and the program continues as expected.

Once we hit 0x40268F and step into it we can see reference to ‘.exe’ and ‘%SYSTEMROOT%\system32\Lab09-01’ which has been taken from the file name passed to the malware.

As we progress we can see that this opens the Service Control Manager and looks at creating a service with the name Lab09-01 if it doesnt exist already.

This service is created with a number of parameters. Which can be seen within OllyDbg.

After stepping over this function we can see that a service has been created pointing to %SYSTEMROOT%\system32\Lab09-01.exe and that the malware has indeed copied itself to this directory indicating it has been successfully installed.

Question 2

What are the command-line options for this program? What is the password requirement?

In addition to the mentioned ‘-in’ argument check, we can see 3 other command-line options in this malware. “-re” “-c” and “-cc”

The password requirement mentioned previously can be uncovered by carefully examining how many checks occur in this function and breaking down what each comparison is used for knowing that we want their comparisons to be true. As such we need to also look at activity occurring before the comparison, and if required examine the current stack content as we move through it.

First off we can see that the password is 4 characters long, then we look for it containing (61) ‘a’ as the first letter, then we compare the result of letter 2 (62) take letter 1 (61) and see if it equals 1, then we compare whether the next character is c (63), before finally adding 1 to this and checking if the next character is d (64).

If we break down how the value ‘b’ is obtained, we can see that it is derived directly from what we’ve pushed to the stack.

By using the ‘-re abcd’ argument (or any of the others, we can see this still performs the same password check, so this indicates abcd needs to be passed to the malware to run unless you want it to simply remove itself.

By stepping through and stepping over this execution as required, we reach a point where the Service Control Manager is instructed to delete a service.

Continuing through this results in the malware removing itself by deleting the service and associated binary.

By using the ‘-c’ argument we wind up once again with the malware attempting to remove itself. This is due again to a check on the number of arguments passed to the program. Looking at the hex dump of the malware while it is running leads us to believe a default configuration is setup to communicate to a URL with 2 associated parameters ‘80’ and ‘60’.

Given these parameters look to be related to post-compromise activity, we need to first ensure the malware is installed using -in.

By using the ‘-cc abcd’ argument we see that the application looks for its current configuration that’s been stored at: ‘HKLM\SOFTWARE\Microsoft \XPS’ and dumps it to the programs output.

Question 3

How can you use OllyDbg to permanently patch this malware, so that it doesn’t require the special command-line password?

As mentioned in answer 1, this malware can be patched under 0x402510 to always return with EAX = 1. To do this we right click the start of the function call, click edit, and use the assocviated HEX values to make it assign EAX as 1.

After this we edit the next HEX values to immediately make it return from the function signalling a successful outcome.

To patch the binary we can right click and select copy to executable > all modifications, before right clicking and selecting save file. At this point if we open the modified binary and run as normal, we can now run commands without the need for a password.

Question 4

What are the host-based indicators of this malware?

Host-based indicators of this malware include the registry key used to store the malware configuration:

• ‘HKLM\SOFTWARE\Microsoft \XPS’

The service created for persistence with the name:

• Manager Service"

or

• Manager Service"

and finally the presence of a binary at:

• %SYSTEMROOT%\Windows\System32

With the name of the service name argument passed, or the binary name.

Question 5

What are the different actions this malware can be instructed to take via the network?

By opening this using IDA we can find sub_402020 which contains a number of instructions that help determine what different actions this malware can be instructed to take. This is also seen at 0x402020 in OllyDbg.

In this instance functions have been renamed to “Command_*” for readability.

• SLEEP: Do nothing for a certain amount of seconds. Note: This is registered in milliseconds so the value passed is multiplied by 1000.

• CMD: Execute a command and send back the output to a web resource.

• NOTHING: Do nothing

Question 6

Are there any useful network-based signatures for this malware?

We know from previous analysis of this malware that configuration is stored in the registry so by default it communicates with:

• http://www.practicalmalwareanalysis.com

To analyse how this communication occurs and whether there’s any other network-based indicators we look back to sub_402020 and the function it calls prior to comparing the response received to one of the mentioned commands. This function is sub_401E60.

This contains a number of unusual string comparisons and operations based on backticks and apostraphes.

Moving back to Ollydbg we can move back to debugging the application in an attempt to understand this. Starting out we add a breakpoint at 0x401E60 by using CTRL + G to jump to this address and using F2 to toggle a breakpoint.

We need to confirm the application isn’t running with any command line parameters and move through with F8 until the breakpoint we set is hit. From here we can begin to analyse specific register or stack values before and after a number of subroutines are run by setting breakpoints similar to the below.

After running through the first function by using F9 twice, we see reference to WinINet API and the previously mentioned domain which leads us to believe this is likely using FTP or HTTP for communication.

Repeating the process with F9 twice reveals our ECX register with the value ‘80’.

Based on what we know and it being stored in a value ‘p’, we can infer that this is the port that the malware communicates via. Repeating the process once more reveals what looks like it may be part of a URL.

By repeating the process once more we see that it fails to run through to our later break points in our isolated environment. Subsequent analysis shows that the URL elements mentioned above change. If we step through to 0x401EF9 we can see that this is indeed being passed as an argument to a function at 0x401AF0.

Stepping into this function we can see evidence this is making a HTTP/1.0 Get request to the server for C2 without any headers.

After the request is made there are some comparisons based on returned backtick and apostraphes as we found earlier, and this looks to be determining exactly how the C2 process will execute the command passed to it (how the C2 protocol works).

Based on all of this we can conclude that Get requests using HTTP/1.0 beaconing to http://www.practicalmalwareanalysis.com/xxxx/xxxx.xxx without any headers or user agent is a network indicator of this malware.

Lab 9-2

Analyze the malware found in the file Lab09-02.exe using OllyDbg to answer the following questions.

Question 1

What strings do you see statically in the binary?

Running Strings over the binary reveals a number of entries for what look like imports or function names, and ‘cmd’, but other than that not a lot else.

Question 2

What happens when you run this binary?

Attempting to run the binary results in it terminating almost instantly without showing any other visible actions.

Question 3

How can you get this sample to run its malicious payload?

By stepping through the program with a debugger and a few break points, we can see that after the call at 0x401626, EDX is filled with the value “ocl.exe”, and this remains throughout the program until a comparison check to it fails and the program terminates.

Based on this we can assume that the program checks if it is named ocl.exe, and if it isn’t then it terminates. If we rename it and continue to debug, we realise that termination doesn’t occur here anymore.

Question 4

What is happening at 0x00401133?

If we examine 0x00401133 we can see that a number of Hex values are being moved onto a relevant area of the stack segment.

This is a common string obfuscation technique to make analysis more challenging.

If we take the hex values accounting for the null values present and convert this to ascii we get the following:

• 31 71 61 7a 32 77 73 78 33 65 64 63 = 1qaz2wsx3edc
• 6F 63 6C 2E 65 78 65 = ocl.exe

Question 5

What arguments are being passed to subroutine 0x00401089?

Adding breakpoints and running through the application later reveals the presence of 1qaz2wsx3edc which is being passed to subroutine 0x00401089 and a pointer to 0x12FD58 (Incl ESI).

Question 6

What domain name does this malware use?

By running through this program to our next breakpoint we can see that it flows through the decoding routine at 0x00401089 and reveals the domain used by this malware in EAX ready to be passed to the ‘gethostname’ imported function: www.practicalmalwareanalysis.com

Question 7

What encoding routine is being used to obfuscate the domain name?

To figure this out we need to move into the encoding routine at 0x00401089. Here we can see a routine that loops and contains reference to an XOR command against EDX (which we know contains the random string we discovered earlier).

By adding a breakpoint at this command and running the program we can see that it performs this XOR against a letter one by one, and in the first instance it XORs 46 and 31 (first letter of our key).

Running the program again reveals it XORs 6 and 71 (second letter of our key)

By creating a break point at the comparison statement that occurs, and following the associated memory dump, we’re able to see the string being decoded in real time as we run through the program and hit our breakpoints.

Question 8

What is the significance of the CreateProcessA call at 0x0040106E?

This function isn’t called when we run through the program as there’s no successful beacon to the C2 we uncovered previously. Having said this we can see from this function that CreateProcessA looks to be run with cmd.exe as the process before waiting indefinitely in a loop.

By examining this in IDA for more context, we can see that it is making the cmd.exe window hidden, in addition to specifying the standard input, output, and error streams be sent to an argument that’s passed into this function.

Looking at the only calling function to this, we can see that the argument passed to this is the established socket to the C2. We now know that this process acts as the reverse shell allowing access to this host.

Lab 9-3

Analyze the malware found in the file Lab09-03.exe using OllyDbg and IDA. This malware loads three included DLLs (DLL1.dll, DLL2.dll, and DLL3.dll) that are all built to request the same memory load location.

Question 1

What DLLs are imported by Lab09-03.exe?

By opening the program in IDA we can see that the imported DLLs of this program are:

• DLL1.dll
• DLL2.dll
• KERNEL32.dll
• NETAPI32.dll

In addition to these, if we examine calls to the WinAPI ‘LoadLibraryA’, we can find another 2 DLLs that are dynamically loaded into memory from the running program.

• DLL3.dll
• user32.dll

Question 2

What is the base address requested by DLL1.dll, DLL2.dll, and DLL3.dll?

By opening these up in PE-bear, we’re able to see that they all have an image base set to 0x10000000.

Question 3

When you use OllyDbg to debug Lab09-03.exe, what is the assigned based address for: DLL1.dll, DLL2.dll, and DLL3.dll?

Because we know that DLL3.dll is dynamically loaded in we’ll need to add a breakpoint after this loadlibrary call to check when all 3 are loaded into memory.

To view where these are in memory we can use ALT+M to view the programs memory. Note: These values will likely differ per run through or system.

In this instance the results are:

• DLL1: 0x10000000
• DLL2: 0x00150000
• DLL3: 0x00160000

Question 4

When Lab09-03.exe calls an import function from DLL1.dll, what does this import function do?

Because this occurs prior to the breakpoint we previously set, we can get our first glimpse on what has happened by viewing the program output while it is at our breakpoint.

This appears to display an output of “DLL 1 mystery data”, and then a number. By disassembling this in IDA we can get more information on what is happening.

Based on this we conclude that this is printing out the current processID of the process in which the DLL has been loaded into.

Question 5

When Lab09-03.exe calls WriteFile, what is the filename it writes to?

To get this answer we need to look at both DLL2.dll, and Lab09-03.exe. In Lab09-03.exe we can see that this calls and moves the output into ebp+hObject before passing it a buffer of the characters “malwareanalysisbook.com” to write.

By examining DLL2.dll, and looking at the exported DLL2ReturnJ function, we can see that this returns a value stored under dword_1000B078. When we examine this we can see it is being assigned based on the DLLs Main method as a handle to a file with the name “temp.txt”.

Based on this we know that this writes “malwareanalysisbook.com” into a file called “temp.txt”.

Question 6

When Lab09-03.exe creates a job using NetScheduleJobAdd, where does it get the data for the second parameter?

If we look at this execution we can see that it passes 3 parameter items: JobID, Buffer, and Servername.

Buffer is called from the output of Dll3GetStructure which once again is determined by the DLLs main function.

If we examine the NetScheduleJobAdd function documentation we can see that buffer needs to be a pointer to an AT_INFO structure defining the job to submit.

By using IDA we can add in the AT_INFO structure and then apply this to dword_1000B0A0. After first adding it to the structures window:

By viewing dword_1000B0A0 in memory and clicking Edit > Struct Var to AT_INFO we can change this directly and make more sense of the data at hand.

Based on this we can see that it will ping www.malwareanalysis every day at 3600000 milliseconds (60mins) past midnight (1am).

Question 7

While running or debugging the program, you will see that it prints out three pieces of mystery data. What are the following: DLL 1 mystery data 1, DLL 2 mystery data 2, and DLL 3 mystery data 3?

We already know what these are by the analysis conducted in previous questions. These are outputted from the values found in our relevant DLL files.

• DLL 1 mystery data 1: Process ID DLL is running under. (This was found in Question 4)
• DLL 2 mystery data 2: Handle ID for the Handle on file temp.txt. (This was found in Question 5).
• DLL 3 mystery data 3: Memory location of “ping www.malwareanalysisbook.com”. (This was found in Question 6).

Question 8

How can you load DLL2.dll into IDA Pro so that it matches the load address used by OllyDbg?

In this instance we want it to match the load address of 0x00150000. We can do this by clicking the ‘Manual Load’ checkbox in IDA when analysing the DLL and specifying the load address wanted.

This concludes chapter 9.

Chapter 10. Kernel Debugging with WinDbg

Before getting into this chapter, we’ll need to setup a suitable environment for debugging Kernel Driver activity. In this instance we’ll use the below:

• VMware Player or Virtualbox
• Windows XP VM (Guest OS)
• WinDbg Preview (Host OS)

First we fire up our VM and modify boot.ini to have another entry with a COM serial port enabled (take the last line, change the name and add in the below).

/noexecute=optin /fastdetect /noexecute=optin /fastdetect /debug /debugport=COM1 /baudrate=115200


Save the file and shutdown the OS. Next create a COM serial port that uses a named pipe which our debugger will communicate with.

• Under Virtualbox this should look similar to the below:

• Under Vmware Player you will need to add a Serial Port.

• Before setting this up as a server with the other end specified as an application.

Once this is done your guest OS is ready to roll, all you need to do is open Windbg Preview and start debugging the kernel via the named pipe we created.

So long as our VM is booted using the COM serial port option we specified, it’ll create the named pipe that our debugger will connect to, and we’re good to go.

Useful Windbg Commands

• da = Reads from memory and displays as ascii
• du = Reads from memory and displays as unicode
• dd = Reads from memory and displays as 32-bit double values
• ex = Writes data to a memory location
• dwo = Dereference a pointer and show the value it points to e.g. ‘du dwo (esp+4)’
• bp = Create breakpoint
• g = (Go) Run an action at a breakpoint
• moduleName!symbolName = Search for symbol
• bu = Create breakpoint based on condition such as module load
• $iment = Determine entry point • x = Search functions for value • ln = list nearest function to memory address • dt = Driver Type information based on symbols • !drvobj Common Examples: • bu newModule!exportedFunction • bu$iment(driverName)
• x nt!CreateProcess
• ln

Lab 10-1

This lab includes both a driver and an executable. You can run the executable from anywhere, but in order for the program to work properly, the driver must be placed in the C:\Windows\System32 directory where it was originally found on the victim computer. The executable is Lab10-01.exe, and the driver is Lab10-01.sys

Question 1

Does this program make any direct changes to the registry? (Use procmon to check.)

By running procmon and filtering on reg set events related to the executable lab10-01, we can see that only one direct change to the registry has been recorded: HKLM\SOFTWARE\Microsoft\Cryptography\RNG\Seed.

Question 2

The user-space program calls the ControlService function. Can you set a breakpoint with WinDbg to see what is executed in the kernel as a result of the call to ControlService?

To do this we will need to setup a breakpoint using WindDbg in our VM and be analysing kernel operations using WinDbg on our host. First we need to determine where the breakpoint in our VM will be that calls the ControlService function. This can be done by examining the memory locations this occurs at in IDA.

bp 0x00401080


Next, while running our VM with debugging enabled and connected to our host instance of WinDbg, we open this executable in WinDbg (in our VM) and set a breakpoint at this address. This will be used to get a baseline of what has occurred prior to the call to ControlService. It’s possible you may receive an error message around verifying checksums, but attempting to run the breakpoint again ensures it is set.

By running ‘g’ the application runs and hits our new breakpoint.

Next in our host, initiate a ‘break’. This will cause the VM to stop responding as we’ve now hit a break on the kernel running. Next we run ‘!drvobj lab10-01’ to locate the driver lab10-01.sys and see if there’s any device objects that can be interacted with from user applications.

Because we want to know what has changhed before the kernel driver is unloaded, we can now set a breakpoint at this location ‘bp 0xf7ed8486’ and resume the kernel with ‘go’. At this point the OS is usable again. By clicking ‘go’ or running ‘g’ on the debugged application in our VM once again, the OS freezes and we’re notified that the kernel breakpoint has now been hit.

By stepping through operations, we can see that this then executes some commands to create a registry key.

At this point it’s worth analysing the driver using IDA to gather more information on what has occurred. By looking at this location within IDA, we can easily see that it is creating 5 different registry keys which goes completely undetected by Procmon.

Looking closer at these values we can see that it is setting keys to disable the Windows Firewall by changing these values to 0.

Question 3

What does this program do?

By taking a look at what we know, we can examine the binary in question within IDA and see it creates a kernel service which is then used to stealthily update the registry to disable the Windows Firewall before being unloaded.

Lab 10-2

The file for this lab is Lab10-02.exe.

Question 1

Does this program create any files? If so, what are they?

By running this program and examining it with Procmon we can see that it creates a kernel driver and writes it to disk.

• C:\Windows\System32\Mlwx486.sys

Attempting to view the file on disk causes it to not be shown; however, using process hacker we’re able to find this file loaded into the kernel and gather from its description that it’s likely an Input and Output Control driver, so we may be looking at a rootkit here.

This same information could have been found by using our previously setup kernel debugger.

By examining the imported functions of this binary using peview, we can see that it is likely going to examine the contents of its resource section and write a file to disk. This helps to confirm what we saw with Procmon.

Question 2

Does this program have a kernel component?

By examining the resource section of lab10-02.exe using resource hacker we’re able to see it is indeed hiding an executable of some kind, and in this instance the Program Database (pdb) we can see (which holds debugging references), leads us once again to thinking this contains a kernel component/rootkit.

With resource hacker we can save this directly to a .sys file and have the filtering kernel component extracted with the following SHA256 hash.

42B66F4DCB1380AB6330CFB638CE97C7BEA6D772EDDD1D34C1031B0D16DEA19C


This has the same file information as the kernel driver currently loaded from: C:\Windows\System32\Mlwx486.sys.

Examining the binary through IDA (The driver we extracted with resource hacker) reveals that it is indeed creating the file and creating a service for it called ‘486 WS Driver’ before starting it.

We can see this through the use of the Service Control (SC) binary.

Question 3

What does this program do?

Currently we know that this creates a service with an unknown driver that can’t be seen on disk and looks like a rootkit. To get some more information we can debug the driver in memory. Upon restarting the host it’s likely that the driver won’t have started and will need to be started with the Service Control binary.

• sc start “486 WS Driver”

From here we can break into our debugger and see whether this is loaded by using ‘lm’ and clicking on our identified driver.

This gives us enough information to begin probing the System Service Descriptor Table (SSDT), or in layman terms, a table of pointers to addresses in memory where kernel functions are located. This is identified by ntoskrnl.exe (NT OS Kernel, this dates back to Windows NT days) as ‘KiServiceTable’.

Given we are looking for pointers and know that Debugging Symbols makes our life easier, we can use the ‘dps’ command to dump pointer symbols of the KiServiceTable, list out 100 entries and view what has been loaded into the kernel. We would expect all the memory addresses to point to a similar location in memory and be from the same module e.g. ntoskrnl.exe (NT); however, when we analyse this we can see an anomaly.

dps KiServiceTable L100


Based on this output we can see that the driver (module) has hooked an entry in KiServiceTable and pointed it to our identified malicious driver. Note: In later 64-bit versions of Windows this technique would cause a blue screen due to a security feature known as ‘patch guard’.

To determine what it has hooked, we can locate what was at this address prior to infection, or we can examine this more thoroughly using IDA. When looking at this through IDA we can see it seems to be hooking NtQueryDirectoryFile.

By jumping to the file offset we identified through debugging ‘0x486’, we see some information that looks like it’s part of a function.

By right clicking the location and selecting ‘create function’ we can get a clearer picture of what is occurring.

Of most interest is that after the driver calls the legitimate NtQueryDirectoryFile function, it then adds an entry to compare a value to a block of memory. If we convert this to ascii and view the entry for word_1051A, we can see it is comparing to the value ‘Mlwx’.

This makes it far more clear that the hook functions like normal; however, if a file exists with a name starting with ‘Mlwx’, it won’t be shown (as a jump occurs). We can test this by creating a folder or file beginning with this and watching it vanish before our very eyes.

At this point we have a clear understanding that this is designed to install a kernel rootkit that uses SSDT hooking to hide any files or folders beginning with (case-sensitive) ‘Mlwx’.

Lab 10-3

This lab includes a driver and an executable. You can run the executable from anywhere, but in order for the program to work properly, the driver must be placed in the C:\Windows\System32 directory where it was originally found on the victim computer. The executable is Lab10-03.exe, and the driver is Lab10-03.sys.

Question 1

What does this program do?

By running the program in a sandbox we can see that after a brief period of time it opens a web browser to an advertisement located at: http://malwareanalysisbook.com/ad.html. This continues to open a new web browser pointing at this webpage at regular intervals.

By analysing the accompanying windows driver with peview (Lab10-03.sys) we can see that it has a number of imports including ‘IoGetCurrentProcess’.

The other imports are common among drivers; however, this particular import gives us the impression that the driver will be getting a pointer to the current process it is running from, and in essence will be either getting information about it or modifying it.

To get more information on what is occurring we can look at the executable Lab10-03.exe through IDA. At a glance we can see that this is creating a service called “Process Helper” which points to the aforementioned driver, before starting it and getting a handle to \.\ProcHelper through CreateFileA.

Based on this we can make an informed decision that a device will be created by the kernel driver at \.\ProcHelper which will allow communication between the user component Lab10-03.exe, and the kernel driver component ‘Lab10-03.sys’.

To understand what is being sent to the kernel driver prior to digging into that further we can take a look at what is being passed to “DeviceIoControl’. We can also see some calls to OleInitialise and CoCreateInstance which lead us into believing that a COM object will be created and used by this executable which in this instance we can see is what’s being used to open IE in a loop to show the advertisement webpage.

Of interest is that null (0) values are being sent through lpOutBuffer and lpInBuffer which indicates no input or output values are expected, and that only ‘0ABCDEF01h’ needs to be sent as the control code to the kernel driver which we will dive into further in the following questions. More information on this operation can be found under the DeviceIoControl function.

Question 2

Once this program is running, how do you stop it?

By opening Process Explorer or Task Manager prior to running lab10-03.exe, we can see that there is an instance of internet explorer running which is spawning advertisements through the initialised COM object; however, there’s no mention of lab10-03.exe

If we kill internet explorer the advertisement popups will stop. This is because the looping component that appears to be spawning these windows comes from the iexplore instantiated COM object rather than lab10-03.exe itself and there’s no redundancy to reinstantiate the COM object.

Having said this we still see no evidence of lab10-03.exe which may be still running. To understand why we begin to dig further into the kernel driver.

Question 3

What does the kernel component do?

Opening up lab10-03.sys in IDA we can see that it does create a device and a symbolic link (DosDevices\ProcHelper) to (\Device\ProcHelper) which allows the user application to communicate with the kernel driver.

From here if we move back to debugging the kernel driver, we can search directly for the device object ‘ProcHelper’ so long as the service “process helper” is running, and then use the address of the driver object to gather more information about the object.

!devobj ProcHelper
dt nt!_DRIVER_OBJECT 86576500


Of most relevance to us is the DriverInit and Major function address locations. To get more information about major functions this implements we can use ‘dd’ and specify the address + the offset identified.

dd 86576500+0x38


Looking at the above we can see that there’s 3 unique functions implemented, and what looks to be noise data that doesn’t fit right at the bottom (this is because we’ve retrieved more than the max amount of major functions shown when we identified this offset).

To fix this we can specify the max amount of results to retrieve in hex ‘L1C’ (1C is hex for 28 in decimal which we saw previously), the new command would be as follows:

dd 86576500+0x38 L1C


Moving back to our results we can see the following valid Major functions implemented:

• f7f30606
• 804fa87e
• f7f30666

To get an idea of what these are you can use the ‘ln’ command if you have debugging symbols installed to get the names nearest to these locations:

ln f7f30606
ln 804fa87e
ln f7f30666


If this doesn’t return results we can also go browsing with ‘dps’ similar to our previous query with ‘dd’.

dps 86576500+0x38 L1C


From here we can see that the most common major function implemented is ‘nt!IopInvalidDeviceRequest’ which is basically a catch all for any function that this driver doesn’t implement. The others now specify their offset of ‘Lab10_03+0x606’ and ‘Lab10_03+0x666’.

Moving back to IDA, if we decompile this and from the start function jump to these offsets, we can find out what these functions are performing.

• Lab10_03+0x606

• Lab10_03+0x666

From the above we can see that offset 0x606 doesn’t do much besides call a function to indicate that processing of this I/O request is complete. The offset 0x666 on the other hand is calling IoGetCurrentProcess which we identified earlier, before accessing data at 0x88, and 0x8C (0x88 + 4).

If we look at what is returned from a call to IoGetCurrentProcess we find out that it is a pointer to the current process, ref:IoGetCurrentProcess function. To understand how this looks from a kernel point of view, we need to understand that the opaque structure for a process object is ‘EPROCESS’, ref:Windows kernel opaque structures.

Knowing that an EPROCESS structure will be returned for the process that made the call to this function, we can move back to our debugger and find out what resides at 0x88 and 0x8C of this structure.

dt nt!_EPROCESS


As nothing falls at 0x8C, but this falls before 0x90, we can conclude that both relate to a LIST_ENTRY structure of ActiveProcessLinks. Once again we now need to look into what constitutes a LIST_ENTRY structure, Ref:LIST_ENTRY structure

From the above documentation we can see that there’s 2 main members we need to be aware of:

Revisiting the function at Lab10_03+0x666 with this knowledge we can begin to piece together what this does.

We know that adding 4 now is to move to the next EPROCESS structure based on the number of members in the LIST_ENTRY structure. The main function of this driver now begins to look like the below.

add eax, 88h - Access data at offset 0x88 (LIST_ENTRY structure).

mov edx, [eax] - Point to an entry at an offset of 0x88 (previous entry in list).

mov [ecx], edx - Overwrite Blink to point to the previous entry in the list (This effectively skips the calling process).

mov ecx, [eax] - Point to an entry at an offset of 0x88 (previous entry in list).

mov eax, [eax+4] - Overwrite Flink to point to the previous entry in list (This effectively skips the calling process).

mov [ecx+4], eax - Point to next entry.

Put more simply the kernel component performs the following after a call is made by a process to ‘Lab10_03+0x666’ (f7f30666 - DeviceIoControl).

• The next Active Process from a list containing EPROCESS structures is retrieved.
• This is modified to set the previous linked process to skip over the process that made this call when looking forward.
• This is modified to set the next linked process to skip over the process that made this call when looking backward.
• The end result is that the calling process is unlinked and becomes invisible when viewed by a user.

This concludes chapter 10.

Chapter 11. Malware Behavior

Types of malware behaviors:

• Backdoors
• Credential Stealers
• Persistence Mechanisms
• Privilege Escalation
• User-Mode Rootkits

Lab 11-01

Analyze the malware found in Lab11-01.exe

Question 1

What does the malware drop to disk?

By examining the binary using PEview, we can see that it contains imports to do with reading from its resource sections, writing a file to disk, and also contains an unusual import which is tagged as a binary.

Based on this we can assume it will drop a file to disk. By examining strings of the binary, we can see reference to ‘MSGina.dll’ and a registry key location that leads us to believe this may drop a credential stealer designed for Windows 2000, XP, or Server 2003. This conclusion is drawn as ‘GINA” stands for ‘graphical identification and authentication’ which is a component of these older operating systems. GINA Interception is a known technique for harvesting credentials.

By using Procmon, we can see that this drops msgina32.dll to disk before setting up a registry key to specify the custom GINA DLL be used during logon.

Question 2

How does the malware achieve persistence?

As shown above persistence is achieved by registering msgina32.dll, which is pulled from its resource section, as a custom GINA DLL in the Windows Registry at the below location:

By examining the documentation on GINA, we can see that this is loaded into winlogon, and can have credentials passed through it that can be captured.

One of the methods of doing this is to implement the WlxLoggedOutSAS which will be passed user credentials whenever someone tries to logon at the logon screen.

Question 3

How does the malware steal user credentials?

By using CFF Explorer VIII we can see that msgina32.dll exports a number of functions that correlate to known functions that need to be exported by a legitimate GINA DLL as it is prepended with Wlx.

By looking at the strings on this DLL we can see that it contains a couple of interesting strings that look to be formatting related, and reference to msutil32.sys which we haven’t seen used.

Opening this up in IDA, we can use msutil32.sys as a pivot point by looking for it in the code. Upon finding it we can use CTRL + X to find cross references to the function using this string which may give us more context into what it’s used for.

Immediately we can see that this calls _wfopen which indicates there’s a file by the name msutil32.sys which will be opened. Examining the reference to this function gives us the impression that the below formatted string will be written to the file msutil32.sys

• UN %s DM %s PW %s OLD %s

It should be noted that %s will be replaced with the appropriate dynamic strings pushed to the stack. Of interest is that this has come from the function ‘WlxLoggedOutSAS’. Looking at what arguments are passed to this function leads us to an interesting discovery.

Looking at documentation of this function, ‘pNprNotifyInfo’ which is passed to WlxLoggedOutSAS points to a structure that contains Domain, Username, and Password information for a user. This leads us to believe that this malware steals user credentials by using a custom GINA DLL which intercepts user passwords when no user is logged on.

Question 4

What does the malware do with stolen credentials?

Looking back at sub_10001570 it appears that this is getting the date, time, and another value which it is being place inside of msutil32.sys in addition to a new line character.

Based on what we see of this function the final value being written to this file is the contents passed by the calling function: UN %s DM %s PW %s OLD %s.

Placing all of this together we can make the informed decision that the malware will create a file called msutil32.sys which will contain the date, time, Domain, Username, and Password of a particular user every time a call is made to the exported function WlxLoggedOutSAS of msgina32.dll. Because this will be run by winlogon.exe we can expect this to fall within the directory C:\Windows\System32.

Question 5

How can you use this malware to get user credentials from your test environment?

Because GINA DLLs are ignored in Windows Vista and later, this will only work in Windows XP or prior. Once the GINA DLL has been installed the system needs to be restarted. This is to ensure the new GINA DLL will be loaded into Winlogon.

Upon restarting and logging in we can see a new file is created.

At this point we can confirm it has logged some relevant information as expected, and because no password was present it hasn’t logged an entry for ‘PWD’. If we log out and back in we can see a new entry has been added. By changing our password to ‘password’, logging out, and logging in we can see that the new credentials have been logged by this stealthy credential stealer.

At this point we know how the GINA DLL functions and where it stores credentials.

Lab 11-02

Analyze the malware found in Lab11-02.dll. Assume that a suspicious file named Lab11-02.ini was also found with this malware.

Question 1

What are the exports for this DLL malware?

Instead of using the same tools we’ve looked at, we examine another tool called PPEE (puppy) to get this information.

Based on the above we can see that this only has one export ‘installer’.

Question 2

What happens after you attempt to install this malware using rundll32.exe?

Given that this is a DLL which exports the function ‘installer’, we can use rundlle32.exe to run this exported function with the below.

rundll32.exe Lab11-02.dll,installer


By running procmon with a filter looking for only events from rundll32, we can then run this and see 311 events have been generated in our Windows 7 VM.

Naturally there’s a lot of requests that we won’t be interested in. One way to reduce the number of irrelevant entries is to add a filter that only shows operations that contain the words ‘set’ or ‘create’. Although this may seem like we miss out on interesting file reads, the ‘CreateFile’ API call is used both in file or I/O creation, or reading. This gives us coverage of these interesting events. By making this change we’re reduced to 99 entries.

From the above we can see 3 main entries of interest. The first is that it issues a CreateFile API call to the below:

• C:\Windows\System32\Lab11-02.ini

Because we know that the CreateFile can be used for either creating or reading a file, we can look a little bit deeper at the properties of this event. By doing this we see that it is only looking to open the file with read privileges, rather than write to it.

If you compare this to the event for CreateFile on the below, we can see that

• C:\Windows\System32\spoolvxx32.dll

In addition to this the malware attempts to add an entry to add the above DLL into ‘AppInit_DLLs’ within the registry. If we take a look into this and the security implementations added to Windows 7, we can gather that this is used to load the specified DLL into every user mode process on the system; however, because this is designed for Windows XP, there’s no modification to ‘RequireSignedAppInit_DLLs’ which is required to allow unsigned modules from being loaded in this manner.

Question 3

Where must Lab11-02.ini reside in order for the malware to install properly?

Based on the above analysis we can conclude that Lab11-02.ini must reside at C:\Windows\System32\Lab11-02.ini for the malware to install itself. Given this is on a Windows 7 system which introduces code signing requirements (without a registry modification) then this installation won’t be truly successful, even if you are running it as an administrator. From this we know that this was likely created with a target of Windows XP or older in mind.

Question 4

How is this malware installed for persistence?

Based on the analysis in question 2, the malware installs itself as an AppInit_DLL for persistence which then means it will be loaded into any user mode process (anything that loads a user interface e.g. using User32.dll) on a system making it difficult to fully remove if every user process is running the malware. This has publicly been reported as a tactic used (even in 2020) by nation state and cyber criminals. If we open this up in IDA and view the exported installer function we can see evidence that backs up what we’ve seen.

Question 5

What user-space rootkit technique does this malware employ?

To understand this we first need to take a look at this in IDA to get an idea of its functions. Using CTRL + F12 to view the call flow of this DLL is an excellent way to get an idea of its functions.

From this we can see that installer doesn’t seem to perform many more calls than what we’ve already identified. Of interest is that DllMain seems to have a number of extra calls, so we’ll look further into that. In particular the subroutine sub_100014B6 seems to make the most calls and is worth investigating.

If we examine this subroutine we can see that it contains a number of checks which appear to be looking for a specific process name.

Where the DLL is running inside of a process with any of the below names:

• MSIMN.exe
• THEBAT.exe
• OUTLOOK.exe

The DLL will proceed to call the below subroutines.

• sub_100013BD
• sub_100012A3
• sub_10001499

Of interest is that we can see reference to ‘send’ and ‘wsock32.dll’. Examining sub_100012A3 more closely, we can begin to see evidence that this gets a handle on wsock32.dll before GetProcAddress is used to get the send function of this DLL before passing them to sub_10001203.

Based on this it looks like the program is using inline hooking via this DLL as a form of user-space rootkit. The hooking code looks to primarily be installed from within ‘sub_10001203’.

Question 6

What does the hooking code do?

Examining ‘sub_10001203’ there’s a number of operations which occur due to the complexities of adding an inline hook.

Essentially this installation will calculate the correct jump address before modifying memory protections so that the ‘send’ function can be changed. This then creates a trampoline which will preserve the first 5 bytes of the send instruction, prior to overwriting these 5 bytes with the JMP instruction to what is now located in var_4. To understand what’s in var_4 we need to look back at what is being passed to this hook installation, as this is what is performing the hook function.

Based on this we can infer that ‘sub_1000113D’ and ‘dword_10003484’ are being sent as part of the hooking function and should be analysed. A quick look at sub_1000113D reveals similarities with the ‘send’ function. Because this needs to implement the same arguments as the send function it can be defined by setting the function type.

int __stdcall sub_1000113D(SOCKET s, char * buf, int len, int flags)


This makes it a little bit clearer. Looking at it we can see that it seems to be modifying in memory specified recipients by adding an entry involving ‘RCPT TO:’ and an unknown value specified by ‘byte_100034A0’.

To get more context on what this will contain we need to look for the operation which reads bytes into this offset.

Examining the main function which adds elements to this we can see that the data is pulled from Lab11-02.ini before calling the subroutine ‘sub_100010B3’.

Looking at the contents of Lab11-02.ini, we see that it looks to be ‘gibberish’ or more likely that some type of encoding is being used, which leads us to believe that ‘sub_100010B3’ may be a decoding routine.

We will examine this further in question 8.

Question 7

Which process(es) does this malware attack and why?

Based on our analysis in Question 5 and 6, this malware only attacks the below processes.

• MSIMN.exe
• THEBAT.exe
• OUTLOOK.exe

This is because they are specific email clients and this malware is designed to hook a specific API call only for the specified email clients.

Question 8

What is the significance of the .ini file?

Revisiting sub_100010B3 we’re under the impression it performs some decoding. Given this is quite challenging to work through manually in IDA, we move back to OllyDbg to perform some dynamic analysis of this subroutine. We’re able to do this by using the ‘loaddll’ binary.

By jumping to ‘0x100016CA’ which is what calls this suspected decoding routine and creating a breakpoint at the function, and directly after the function, we can then copy ‘Lab11-02.ini’ to C:\Windows\System32 where we know it is attempted to be loaded from. Running the program we hit our breakpoint.

By stepping over this routine ensuring that the second breakpoint has been added, we can now see the below value appear on the stack.

This leads us to believe that the .ini file is encoded and once decoded is used to specify an email which based on our analysis in question 6 will be added to any email sent as a secondary recipient based on the hooked send function.

Question 9

How can you dynamically capture this malware’s activity with Wireshark?

To do this we setup a host-only (networking) adapter in our VM, and then begin capturing packets on this adapter in Wireshark.

After this we run the installation function of the malware with the below.

rundll32.exe Lab11-02.dll,installer


From here we open up Outlook Express in our VM and set an appropriate account up to send emails from. We’re going to need to set this up with the IP address of our host OS.

Tools > Accounts > Mail


From here on our host OS we can setup a fake smtp daemon debugging server to receive emails with the below (substituting the IP as required).

sudo python -m smtpd -n -c DebuggingServer 192.168.0.17:25


From here if we run Wireshark on this adapter and send an email we can see it is received by our server.

If we take a look at Wireshark we can see the modification of recipients has occurred and it is now also sending an email to [email protected].

Lab 11-03

Analyze the malware found in Lab11-03.exe and Lab11-03.dll. Make sure that both files are in the same directory during analysis.

Question 1

What interesting analysis leads can you discover using basic static analysis?

If we run strings over Lab11-03.exe we can see a number of strings which relate to loading a library (DLL), manipulating (starting) a service called ‘cisvc’ (a quick search reveals this is the content index service), and reference to a non-existant DLL ‘inet_epar32.dll’.

In addition this contains references to ‘VirtualAlloc’, ‘HeapAlloc’, and ‘VirtualFree’ which seems to indicate this will manipulate memory in some fashion. It should be noted that memory manipulation using API’s such as ‘VirtualAlloc’ or ‘VirtualAllocEx’ is often used when injecting shellcode into a process.

If we run strings over Lab11-03.dll we can once again see a number of strings of interest. We can see there’s once again an entry for a non-existant DLL, and an entry for ‘GetAyncKeyState’ which is commonly used in keyloggers.

What leads us to believe this may be a keylogger even more is that it has a specific string for ‘' in addition to writing output to a file. The explicit '' declaration is common amongst keyloggers as they need a way of determining if a key pressed is capitalised or not. The same applies for a number of supporting keys such as ''.

Question 2

What happens when you run this malware?

If we run Procmon to analyse what happens with this malware is run, we can see that it looks to query Lab11-03.dll prior to creating (and then writing) a file to: C:\WINDOWS\sytem32\inet_epar32.dll, this leads us to believe it’s copied Lab11-03.dll to this location. In addition this gets Generic Read/Write access to C:\WINDOWS\sytem32\cisvc.exe, but doesn’t perform any type of file write operations.

Because we suspect this may have keylogging functionality, we begin typing some text in any application. In addition we expand our procmon search to include any process with the name cisvc.exe, given this seems to be accessed so may hold more information. What immediately is shown is that cisvc seems to look at files from our previous lab11-02, in addition to loading the copied ‘inet_epar32.dll’ file, and creating a file at ‘C:\WINDOWS\sytem32\kernel64x.dll’.

By cross examining the file written by this with the legitimate ‘kernel32.dll’, we can see a number of glaring differences that would indicate this isn’t likely a legitimate DLL. Opening this in notepad confirms that it is indeed logging applications as they shift focus, and appears to be logging keystrokes.

Question 3

How does Lab11-03.exe persistently install Lab11-03.dll?

First we take a look at Lab11-03.exe using IDA. Examining the main method it appears as there’s only a couple of custom function calls which leads us to believe the program may be basic.

When we graph the call flow of this application we can see that it’s far more complicated then we initially thought with many functions being nested.

Drilling into this we first look at the cross references to ‘sub_401070’ which is called prior to starting ‘cisvc’.

Based on the windows API calls we can assume that a file is being mapped into memory (C:\WINDOWS\sytem32\cisvc.exe) with functions occurring on the file prior to UnmapViewOfFile is called which writes the file changes ‘lazily’ to disk.

By examining ‘sub_401070’ more in depth we can see that a number of checks occur based on getting a handle on the file in question, memory, and the binary itself; however if these checks are passed an operation occurs in the bottom right of this flow at ‘loc_40127C’ which is of interest.

This function is of interest because it uses ‘lpBaseAddress’ to get the base address of the mapped file C:\WINDOWS\sytem32\cisvc.exe and has clear modifications occurring prior to ‘UnmapViewOfFile’ being called.

The function uses an unknown variable of ‘var_28’ as an offset from this base before the counter register (ECX) is set to 4Eh (78 in Hex). As the action occurring is ‘MOVSD’ (Move String, Double Word) using this counter register, we know that this is moving 78 DWORDs starting at ‘byte_409030’. At this point it’s important to note that a DWORD is a 32-bit (4-byte) unsigned integer. Due to this the total number of bytes that will be copied is 78 * 4 = 312 bytes. Examining ‘byte_409030’ we see some entries that don’t make a lot of sense.

This is shellcode that will be copied directly as assembly to the binary in question and is stored in Hex. Using ‘c’ we can convert this directly to code to see what it is performing. First we look through to see if there’s any obvious strings. At ‘00409139’ and ‘0040915D’ we find some strings of interest if we convert them to ASCII using ‘A’.

Based on this and the activity we saw running the program we begin to infer that the shellcode will likely dynamically load ‘C:\WINDOWS\System32\inet_epar32.dll’ and run the export ‘zzz69806582’. Looking at the exports of ‘Lab11-03.dll’ which we know is copied to this location, we can see this is a valid export.

Given ‘zzz69806582’ is an obvious unique string we can use this as a pivot point to open the executable in a program such as ‘HxD’ and find the appropriate shellcode for exporting. We also do this by looking for the expected Hex.

After saving the shellcode to a new file (Lab11-3Shellcode.dat) by copying it to a new file using HxD, we can now use a shellcode debugging tool (scdbg) to confirm what actions were taken by the shellcode we’ve found.

scdbg -findsc -f Lab11-3Shellcode.dat


Although an error occurs as we wind up looking into invalud memory, we’re successfully able to step over enough of the shellcode to reveal that it is using ‘LoadLibraryExA’ to load in C:\WINDOWS\System32\inet_epar32.dll, before using ‘GetProcAddress’ to get the exported function ‘zzz69806582’.

Based on this we conclude that Lab11-03.exe will persistently install Lab11-03.dll by infecting the indexing service binary C:\WINDOWS\sytem32\cisvc.exe to run shellcode that uses ‘LoadLibraryExA’ and ‘GetProcAddress’ to load ‘C:\WINDOWS\System32\inet_epar32.dll’ and run the export ‘zzz69806582’ from this DLL.

Question 4

Which Windows system file does the malware infect?

Based on the above analysis we can conclude that this malware infects the indexing service binary C:\WINDOWS\sytem32\cisvc.exe

Question 5

What does Lab11-03.dll do?

Examining Lab11-03.dll in IDA, we start with the export we identified from our previous shellcode analysis (zzz69806582)/

This doesn’t perform much except creating a thread to run actions specified in ‘StartAddress’, so we examine this subroutine for more information. By graphing the user defined cross references to this subroutine we can get an idea of what this may be trying to accomplish.

Based on the Windows API calls we begin to get the feeling that this acts as a keylogger that will create a file if it doesn’t exist, open a mutex to ensure only one instance of it is running, calls ‘GetAsyncKeyState’ to log keystrokes, and writes these to a file before sleeping for a period of time and repeating (this would simulate a poll that occurs on a schedule). To confirm this we look closer at what is occurring at ‘0x10001410’.

Based on this we can determine that the malware creates a Mutex ‘MZ’ and file at ‘C:\WINDOWS\sytem32\kernel64x.dll’. Drilling into the subroutine at ‘sub_10001380’,

Here we can see evidence of information being written to this file before a timeout of ‘0A’ (10) milliseconds occur and it repeats. We can also see evidence of another subroutine being called at ‘sub_10001030’ and if we look into this we can see lots of evidence it is being used as a keylogger. Based on GetAsyncKeyState being used, we can look into Virtual-Key Codes to get an idea of what this is checking for before logging the character “".

From this context we can infer that Lab11-03.dll is a keylogger which polls frequently and writes keys pushed to C:\WINDOWS\sytem32\kernel64x.dll.

This concludes chapter 11.

Question 5

Where does the malware store the data it collects?

Based on the above analysis we can confirm that this malware stores keystrokes and window information it collects at ‘C:\WINDOWS\sytem32\kernel64x.dll’.

Chapter 12. Covert Malware Launching

Lab 12-01

Analyze the malware found in the file Lab12-01.exe and Lab12-01.dll. Make sure that these files are in the same directory when performing the analysis.

Question 1

What happens when you run the malware executable?

Before running the malware we can take a quick look at the imports it has to give us some more context.

From the imports of Lab12-01.exe we can begin to assume it may perform some type of process injection due to the API calls involving multiple of the below which are commonly used for process injection.

• WriteProcessMemory
• VirtualAllocEx
• VirtualFree

Looking at the import from USER32.dll of Lab12-01.dll we can begin do get some context on what this may perform.

Based on this we are under the assumption that this may inject into a process and cause a message box to pop-up. By running the executable we can confirm our findings with a pop-up occurring.

Question 2

What process is being injected?

To get clues on what process is being injected into without reverse engineering the binary, we take a look at the strings of Lab12-01.exe.

Based on the strings and the order they occur, we can begin to infer that explorer.exe may be what is being injected into. Further analysis of the binary in IDA reveals that the main method contains a number of checks and operations, before calling sub_401000 with a relevant processID.

This is part of a looped function which looks to be checking through all processes based on their processID, and is comparing the output of ‘GetModuleBaseNameA’ (translating processID to process name from dword_40870C), to the string ‘explorer.exe’.

If this comparison matches, the process function will return ‘1’ (true), open a handle to the process, and then as the next loop occurs begin to allocate memory that will be used by LoadLibrary to load the DLL specified earlier in this method into memory.

From this we can tell that an existing instance of explorer.exe is being injected into. We can confirm this by simply using process explorer to look for any process that has loaded Lab12-01.dll.

Question 3

How can you make the malware stop the pop-ups?

The easiest way to make the malware stop the pop-ups is to use PowerShell to stop explorer.exe. By using this explorer.exe will stop, killing the thread which has been injected into. It will then startup again automatically and only seem like Windows has briefly refreshed.

Stop-Process -ProcessName explorer


If you’d prefer to not stop explorer, process explorer can also be used to kill individual threads, so by killing the malicious thread you don’t need to kill the entire process.

Question 4

How does this malware operate?

Given we now understand how the injection works from analysis in previous questions, we need to now take a look at ‘sub_10001030’ of Lab12-01.dll which is the code that will be running as a thread within the explorer.exe process.

Analysing this is pretty straight forward. In this instance we can see that a looping function occurs. Within this var_18 is used as a variable that will be incremented by 1 every time it loops, and prior to executing there is a 60,000 millisecond timeout.

Based on this we can see that every 60 seconds a new thread will be created to display a message box from within the explorer.exe process. This will contain the message “Practical Malware Analysis %d” where %d is replaced by the variable var_18, and so this is used to tell you how many minutes have passed since this was injected into explorer.exe.

Lab 12-02

Analyze the malware found in the file Lab12-02.exe.

Question 1

What is the purpose of this program?

Taking a look at the imports of this program leads us to believe it is performing memory manipulation on a ran process or some form of injection. Of interest is that this is creating a process, manipulating threads, looking for a file within its own resources, and getting a handle on a file based on the Windows APIs imported.

From this we can begin to assume that this may be used to run code embedded within one of its resources. Examining the resources of this executable reveals an unusual resource of interest called ‘name_0’ using PE-bear. If we examine using Resource Hacker, we can see this is instead called ‘LOCALIZATION’.

By saving this resource, taking the hash of both the resource, and the sample, and checking them against a public malware repository such as VirusTotal, we can see that this is being flagged as a KeyLogger, and more so that this is the same sample we looked at in Lab 3-3.

Given this is the same as we analysed in Lab 3-3, we know that this uses some form of process hollowing / process replacement, and this backs up what we’ve inferred in these API calls. Based on this we can make the determination the purpose of this program is likely to launch another process, which will be hollowed into / replaced with malicious code stored within its resource section called ‘LOCALIZATION’.

Question 2

How does the launcher program hide execution?

Although we know this hides execution by hollowing into svchost, we can look at this program in IDA to get more context on how this occurs. Based on the main method we can see a few API and subroutine calls which we can elaborate on. Simplified descriptions of each function is shown below.

The application subroutines can be viewed and expanded on to understand how they work.

• sub_40149D

This routine is fairly straight forward, it’s calling ‘GetSystemDirectoryA’ and using the passed in buffer containing the string svchost.exe to concatenate them to make C:\Windows\System32\svchost.exe in this case.

• sub_40132C

This routine is responsible for extracting our malicious resource.

It also goes a step further to copy the elements of it into a buffer in memory for use and calls another routine at ‘sub_401000’. This is a decoding routine that’s elaborated further in Question 4.

• sub_4010EA

This routine performs a lot of the heavy lifting when it comes to replacing the code within svchost.exe to our malicious code. Shown below is where this routine creates the svchost process with creation flags of ‘4’ which indicate it’ll be created in a suspended state.

Looking further we can see the API calls that show us the necessary process headers are being written into this process.

Shortly after we see a loop occurring to write the malicious resource code into the memory of this thread before using ‘SetThreadContext’ to get the start of the thread, and resuming it, starting the malicious code in the context of this process.

Question 3

Where is the malicious payload stored?

Based on our analysis above and in question 1, we know this is stored in the program’s resource section under the resource ‘LOCALIZATION’ which is stored as ‘UNICODE’.

Question 4

How is the malicious payload protected?

As discovered in question 2, there’s a decoding routine which resides at ‘sub_401000’. If we examine this we can see evidence that this uses the 3rd passed argument as a key for XOR decoding.

By stepping back to what is calling this we can see that 41h (or 0x41 in hex) is being pushed to the stack first, so will be the third argument popped off the stack, and in this case indicates our key for decoding.

Question 5

How are strings protected?

As discovered in the question above, strings within the program’s resource section ‘LOCALIZATION’ is XOR encoded using the hex key ‘0x41’.

By using a hex editor capable of XOR operations such as 010 Editor, or using a tool such as CyberChef, you can easily make the necessary modifications to this resource to reveal a familiar ‘MZ’ executable file format indicating your decoding was successful.

By hashing this file and checking it against a public malware repository such as VirusTotal we see it has almost double the rate of detections now that it is decoded.

Lab 12-03

Analyze the malware extracted during the analysis of Lab 12-2, or use the file Lab12-03.exe.

Question 1

What is the purpose of this malicious payload?

Given we already have a good idea that this functions as a keylogger, we can still use some other tools to help back this theory up. For example by looking at this binary using pestudio we can immediately see this picks up on some imports and strings that help lead us to believe it acts as a keylogger.

Exactly how it does this can be determined by using IDA to examine how the malicious payload injects itself into applications.

Question 2

How does the malicious payload inject itself?

By examining the main method of this binary we can see that it installs an application-defined hook procedure using .

In this instance the idHook argument of ‘0D’ in hex translates to 13, and this defines the type of hook to be installed. Referring to Microsoft documentation we find that this relates to a ‘WH_KEYBOARD_LL’ hook.

By examining ‘fn’ which is a pointer to a defined hook procedure, we can see that this is called with a ‘dwThreadId’ of 0 indicating that the hook procedure is associated with all existing threads running in the same desktop as the calling thread, which in this case allows all of this user’s applications to be hooked. We can also see it calls a subroutine at ‘sub_4010C7’ which defines the actions to be taken by this hook. Initially the program will check if a keylog file is present, and if it isn’t it’ll look to first create it.

Of note is that the graph view of this is quite long, and almost looks like a keyboard. Examining this is hooked function is fairly straight forward, first of all we can see that this attempts to pass in and log the window title of whatever application is in focus.

After this further checks and calculations occur to determine what special key is being pushed, and in the event one is a specific value is outputted to the keylog file.

Based on this we know the malicious payload injects itself by using an application-defined hook procedure using SetWindowsHookExA.

Question 3

What filesystem residue does this program create?

As shown in the above analysis this program creates a keylog file called ‘practicalmalwareanalysis.log’ to store stolen key presses.

Lab 12-04

Analyze the malware found in the file Lab12-04.exe.

Question 1

What does the code at 0x401000 accomplish?

Looking at the code at 0x401000 we can see pointers that reference to a number of unknown values indicated by dword, byte, and word values.

By examining these values and converting them to an ascii string using the letter ‘a’, we can better see what’s going on here.

In the above the string ‘winlogon.exe’ is being assigned to the variable at var_14, and “" is being assigned to the variable at var_118 prior to a call to open a process with a process ID which is being passed to this function. If we take a look at the other elements of this function we can see that a couple of subroutines are being called prior to a string comparison taking place that checks if var_14 is equal to var_118.

Naturally if the values that were previously assigned didn’t change this will always fail, so we need to take a closer look at ‘dword_40312C’ and ‘dword_403128’ to see what they’re doing. If we examine them we can see that they don’t have any values assigned. This leads us to believe that they’re being dynamically resolved from somewhere else, likely through the use of a Windows API call to ‘LoadLibraryA’ to load a previously unspecified DLL. To get an idea of what is resolving this, we use ‘x’ to get cross references to ‘dword_40312C’, and look for any references where a value is being moved into this global variable.

If we examine the main function we can see that 3 pointers are being assigned to 3 different global variables, all of which call a different export of the dynamically loaded dll ‘psapi.dll’.

Now that we have some idea of what is occurring we can rename these variables and move back to our code at 0x401000.

At this stage it’s clear that the code at 0x401000 is designed to open a process, search the process modules, for each module get the associated base name (remembering that an executable has its own name as one of its modules), and then where the name is equivalent to ‘winlogon.exe’ return ‘true’ (1).

Question 2

Which process has code injected?

Based on our above analysis we assume that this will be injecting into winlogon.exe, but at this stage we haven’t seen any evidence of injection. If we examine cross references to 0x401000 we can see it is run in the main function of this executable which is confined to a loop. This loop looks to be enumerating processes as it calls our previously renamed ‘EnumProcs’.

From the above we can see that when our subroutine at 0x401000 successfully finds winlogon.exe, it will call another at ‘sub_401174’. Looking into this we see a familiar call that confirms that winlogon.exe is what is being injected into.

Of interest is that there’s no calls to ‘WriteProcessMemory’ or ‘VirtualAllocEx’, so we should examine exactly what this is trying to do.

Question 3

By examining ‘sub_401174’ more in depth, we can easily piece together what DLL is loaded using LoadLibraryA, and what this code is attempting to accomplish.

• Grant self Debug Privileges
• Load system file checker DLL (sfc_os.dll)
• Locate module at ordinal 2
• Open winlogon.exe process with full rights
• Create a remote thread in winlogon.exe with code from ordinal 2 of system file checker DLL

The question still remains on what code is contained within ordinal 2 of the system file checker DLL. A quick search reveals this is an export known as ‘SfcTerminateWatcherThread’ that is used to disable windows file protection allowing modification of files which are otherwise protected by the system file checker.

Question 4

What is the fourth argument passed to the CreateRemoteThread call?

From the above analysis we can determine that the fourth argument passed to the CreateRemoteThread call is the exported module with ordinal number ‘2’ from ‘sfc_os.dll’ which is ‘SfcTerminateWatcherThread’ exposed by the System File Checker DLL used for Windows File Protection on older operating systems such as Windows 2000 and XP. This allows modification of otherwise protected windows files.

Question 5

What malware is dropped by the main executable?

Moving back to our main function we find 4 actions are taken with the access gained from the above injection.

These actions are as follows:

• Locate the windows update manager binary (wupdmgr.exe)
• Assign this to a local variable called ExistingFileName
• Assign a local variable called NewFileName to the \winup.exe
• Move ExistingFileName to NewFileName and call the subroutine ‘sub_4011FC’.

From here we can examine ‘sub_4011FC’ to get an idea of how malware is dropped by the main executable.

This performs 4 distinct actions as follows:

• Locate the location of the original windows update manager binary (wupdmgr.exe)
• Get a handle on the running and search its ‘BIN’ resources for ‘#101’
• Load the specified resource from this resource section
• Write this resource to the original windows update manager binary location

After this the binary calls winexec on this binary with an argument of ‘0’ (SW_HIDE) to ensure it is hidden.

Question 6

What is the purpose of this and the dropped malware?

To understand the dropped malware, we can examine this resource in Resource Hacker, and like in previous analysis conducted, we can save it to a file for opening in IDA.

The main purpose of this is as follows:

• Locate the legitimate backed up windows update binary and run
• Locate a file location at C:\Windows\system32\wupdmgrd (notice the trailing ‘d’)

Based on all of this we can conclude that the overall purpose of this malware is to disable Windows File Protection, trojanize the legitimate wupdmgr.exe with a malicious executable which is designed to run the legitimate wupdmgr.exe executable. This acts as a dropper for another unknown executable which is downloaded and run from http://www.practicalmalwareanalysis.com/updater.exe.

This concludes chapter 12.

Chapter 13. Data Encoding

Lab 13-01

Analyze the malware found in the file Lab13-01.exe.

Question 1

Compare the strings in the malware (from the output of the strings command) with the information available via dynamic analysis. Based on this comparison, which elements might be encoded?

By running strings over Lab13-01.exe we can see reference to Mozilla/4.0 and http://%s/%s/ which looks to be a User Agent combined with a string that would build a URL. By running Fakenet and the executable, we can see that it beacons to a URL not shown when using strings in addition to making a GET request to a resource that looks to be Base64 encoded.

Based on this we can assume that the URL and GET request resource this reaches out to is encoded.

Question 2

Use IDA Pro to look for potential encoding by searching for the string xor. What type of encoding do you find?

By searching in IDA Pro for the string ‘xor’ we find a number of entries. Entries that are performing an xor of a register with itself such as ecx, eax, edx, al etc is indicative of a ‘zeroing’ command that will always result in 0 and is of no interest to us. This leaves 3 possible entries to examine, of which only one has an inbuilt function with code to examine as part of it.

By examining this entry we find it is located within what appears to be a looping function at ‘sub_401190’. As this doesn’t perform any additional checks to see if the buffer passed is the hex key it is using or ‘00’, this looks to be using single-byte XOR encoding with the key 0x3B.

Question 3

What is the key used for encoding and what content does it encode?

From the above we know that the key used for encoding is 0x3B. By examining cross-references to the function ‘sub_401190’, we can see that one exists. Viewing this reveals that it is part of a function ‘sub_401300’ which looks to be loading the value of resource index ‘101’ into a buffer before it is passed to this encoding routine.

By extracting this using Resource Hacker and then leveraging 010 Editor to perform an XOR operation using the key 0x3B, we can see that this neatly decodes to ‘www.practicalmalwareanalysis.com’.

Based on this we know the key is used for decoding the resource at index 101 which has been encoding using XOR. This decodes to ‘www.practicalmalwareanalysis.com’.

Question 4

Use the static tools FindCrypt2, Krypto ANALyzer (KANAL), and the IDA Entropy Plugin to identify any other encoding mechanisms. What do you find?

Using the Krypto ANALyzer (KANAL) plugin for PEiD, we can find Base64 encoding being used at ‘0x004050E8’.

At the time of writing the IDA Entropy Plugin and FindCrypt plugins are quite dated and are maintained poorly if at all. Both experience some compatibility issues with IDA Pro Free 5.0 which makes using these challenging. 3rd party developed newer versions of findcrypt exist, but these generally utilise IDAPython which is not supported in IDA Pro Free 5.0.

As a substitute for the IDA Entropy Plugin we can use the standalone ida-ent.exe binary.

SHA256: 453bbbf34b88468f8e6aa5dfa57628439a0f74742ff093db6d3c0913d1c9325e


developed by the same creator as the original IDA Entropy plugin ‘smoked chicken’. Note: The original download for this binary and plugin has broken over time and become abandoned. As a result a copy of this can be found here. This was originally sourced from a compiled repository by Blue Soul.

It’s important to note that entropy analysis by itself like this provides little context, and many pieces of compressed file formats will have high entropy.

There’s a level of dependency between chunk size and Max Entropy when trying to find sections of interest within a binary. In the below example we use a chunk size of ‘64’ and max entropy of ‘5.95’ to find areas of interest.

By using this we immediately find high entropy between 0x004050E4 and 0x004050EB which aligns perfectly with the Base64 encoding discovered using PEiD. Some useful tests for finding many types of cryptography constants are shown below:

• Chunk Size: 64 - Max Entropy: 5.95 (Used for locating Base64-encoding strings)
• Chunk Size: 256 - Max Entropy: 7.9 (Used for locating very random data)

Some key aspects of (Shannon) entropy often used in digital information analysis (and as a result malware analysis) are as follows:

• The max entropy possible is 8.
• The closer to 8, the more random (non-uniform) the data is.
• The closer to 0, the less random (uniform) the data is.
• English text is generally between 3.5 and 5.
• Properly encrypted or compressed data is generally over 7.5.

As a substitute for Findcrypt we can use free IDA alternative Ghidra which was developed by the National Security Agency (NSA), and a ported plugin FindCrypt-Ghidra; however, for this question we’ll skip this check as it’s not required given KANAL and ida-ent have already located what we’re looking for.

From our use of crypto analysing tools we have found Base64 encoding which appears to be used at ‘0x004050E8’. Looking at this reveals the below index string being used for Base64 encoding.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/


Question 5

What type of encoding is used for a portion of the network traffic sent by the malware?

To find out whether this is related to the Base64 encoding we just found we’ll need to look for cross references to this to determine how it is being used.

Looking at the cross-references we can see that they’re all within the sub-routine ‘sub_401000’, so we’ll take a look at this closer to see if we can find any obvious constructs.

From this routine we can see that there’s 2 branches which look to be moving the value ‘=’ into the variable passed to this sub-routine which leads us to believe this may be the Base64 encoding routine given the strings present and that ‘=’ is used for Base64 padding. To determine where this Base64 encoding function is used we can look at cross-references to ‘sub_401000’ which reveals one within ‘sub_4010B1’, so we examine this further.

This contains a number of loops and conditional jumps; however, there’s 2 key constructs that help us determine this is the actual routine performing the Base64 encoding which is the following:

• comparison of passed string length to 3 bytes
• sub_401000 routine with Base64 encoding index string
• comparison of passed string length to 4 bytes

This is key to identifying Base64 functions as for every 3 bytes of input chunks given you wind up with 4 bytes of encoded ASCII. From this we know sub_4010B1 is the Base64 encoding routine with sub_401000 being the Base64 index routine. To locate where the Base64 encoding routine is being used we once again look for cross references to sub_4010B1 and find one at ‘sub_4011C9’.

Looking into this function we can confirm our suspicions and infer that the encoding used for a portion of the network traffic sent by the malware is Base64.

Question 6

Where is the Base64 function in the disassembly?

From the above analysis we know the Base64 function begins at ‘0x004010B1’.

Question 7

What is the maximum length of the Base64-encoded data that is sent? What is encoded?

To determine the maximum length of Base64-encoded data that will be sent we need to look a bit closer at ‘sub_4011C9’ which is calling the encoding function.

From this we can see that a call is being made to ‘gethostname’ which retrieves the hostname of the local computer. This then takes the first 12 bytes of the hostname and copies it using ‘strcopy’ before this is base64 encoded and formatted as the resource being retrieved in our previously discovered GET request.

Because we know that only 12 bytes will be sent to this encoding function, we can calculate the maximum length of Base64-encoded data that will be sent. To do this we need to remember from question 5 that for every 3 bytes of input chunks you get 4 bytes of encoded ASCII. Because we know that we have 12 bytes of input, we can perform the below calculation:

• Length = (12/3)*4 = 16 bytes.

At this point we know that the maximum length of Base64-encoded data that is sent is 16, and that this comes from the hostname of the system running this executable.

Question 8

In this malware, would you ever see the padding characters (= or ==) in the Base64-encoded data?

Padding occurs to make up the required values if our hostname isn’t divisible by 3. Based on this we may see padding characters in the Base64-encoded data if we run this on a host with less than 12 bytes in its hostname which is not evenly divisible by 3.

Question 9

What does this malware do?

By looking at cross-references to ‘sub_4011C9’ we find that it is called from the malware’s main method.

This helps us identify that the malware will send the hostname running it Base64-encoded in a GET request to www.practicalmalwareanalysis.com and repeat this approcimately every 30 seconds.

As a sidenote, the code inside of our beacon function will check the first character of the beacon response and check if it equals ‘6Fh’ (o).

If so it will return ‘1’ from the function indicating it was successful which will break the loop which is checking every 30 seconds.

Lab 13-02

Analyze the malware found in the file Lab13-02.exe.

Question 1

Using dynamic analysis, determine what this malware creates.

Running this malware while running procmon we can see that a number of file operations occur which creates files with the naming convention ‘temp’ followed by what looks like random characters.

These files are 10mb each in size, and contain a small amount of seemingly random data which we wouldn’t expect to take up 10mb in file size.

Question 2

Use static techniques such as an xor search, FindCrypt2, KANAL, and the IDA Entropy Plugin to look for potential encoding. What do you find?

Leveraging KANAL and IDA-Ent we don’t find anything of interest in this binary. By using a XOR search we find 6 primary entries of interest to look into further (entries not used to clear a register).

Delving into these further we find that they’re located in the following subroutines:

• sub_40128D
• 0040171F (Undefined function)
• sub_401739

Of note is that a number of these operations occur within sub_401739. Based on this there’s the potential for encoding functions to be used within sub_40128D, sub_401739 and code likely residing at 0040171F.

To clean this up and for ease of navigation, we create a function at 00401570 (given 0040171F is inside of this undefined function as shown below), rename sub_40128D to SingleXOR, and rename sub_401739 to MultiXOR.

By plotting out the XRefs to SingleXOR, we can see that this is called from a subroutine inside of MultiXOR.

If we plot XRefs from our newly created function at ‘00401570’ we see this makes similar calls to MultiXOR.

Question 3

Based on your answer to question 1, which imported function would be a good prospect for finding the encoding functions?

Based on question 1, it’s likely that the imported function ‘WriteFile’ would be a good prospect for finding the encoding functions given the data we found inside of the written files looks to be encoded. By looking for calls to this we find it located at sub_401000.

Question 4

Where is the encoding function in the disassembly?

If we pivot from xrefs to WriteFile, we find only one which is from the executable we’re examining rather than an imported library, and this is located at sub_401000. Looking at xrefs to sub_401000 we find there is only one call from sub_401851.

This makes a number of calls, and has a string reference which appears to be related to the creation of files we’ve seen; however, there’s no XOR operations or calls which would indicate this is an encoding function.

By examining sub_401070 which is called by the above function, we find this may be performing some type of screenshot involving an open window based on its imported APIs.

Although this is interesting, it doesn’t appear to be performing any kind of encoding, so we instead move to look into sub_40181F.

This function is what kicks off MultiXOR we defined earlier, and based on this being the only user-defined function, we begin to believe that the encoding function is found here, within sub_40181F of the assembly.

Question 5

Trace from the encoding function to the source of the encoded content. What is the content?

Working our way back to sub_401070 which we discovered before the encoding function took place, we can see that in addition to calling GetDesktopWindow to get a handle to the current screen, there’s calls to BitBlt and GetDIBits which is associated with getting pixel colour and layout of the desktop, which helps us to infer this is taking a screenshot.

Based on this we can assume that the content of files we’ve found are screenshots which have been encoded.

Question 6

Can you find the algorithm used for encoding? If not, how can you decode the content?

Based on results of Ida-Ent, KANAL, and by looking at this in IDA, we can begin to assume that the algorithm used for encoding is custom, and not something easily fingerprintable. Looking into the flow of this program, we can’t see any obvious decoding function in place; however, if we examine the subroutine sub_4012DD, which is located in our encoding function, we get the feeling that this may be able to be used for both encoding and decoding.

To determine if this can be leveraged to decode the content, we can look at this more closely in a debugger such as OllyDbg. After opening this in OllyDbg, we can place a breakpoint right before the call to our identified encoding routine (sub_40181F) at address 00401880 , and directly after the call to writing a file (sub_401851) at address 0040190A.

• Breakpoint at 00401880 (call to sub_40181F)
• Breakpoint at 0040190A (call to sub_401851)

After running the program for a brief period of time we hit our breakpoint. At this point we can right click the value stored in ESP, and click FOLLOW IN DUMP to view the data that will be encoded.

By opening one of the encoded files from this malware and opening it in a hex editor such as HxD, we can copy the hex contents and paste it in place of the data that was going to be encoded.

From this we see the data change.

After resuming the malware again, if we allow it to complete a new file will be created. If we give this new file a .bmp extension, we’re able to view it and see it is a recovered screenshot as expected. From this we know we can use the power of a debugger and the encoding function, to also decode encoded data.

Question 7

Using instrumentation, can you recover the original source of one of the encoded files?

Leveraging Immunity Debugger’s extended python scripting functions, we’re able to develop a python script used to decode the encoded file. Note: This is largely covered and taken from the PMA material.

Opening the program in Immunity Debugger, we can now run our script with the specified file we want to be decoded using the provided terminal inside Immunity.

!bmpdecode


By continuing to resume the program after it hits our breakpoint, we get a newly created file with the decoded content.

From here we’ve successfully used instrumentation to automate the recovery of the original source of an encoded file.

Lab 13-03

Analyze the malware found in the file Lab13-03.exe.

Question 1

Compare the output of strings with the information available via dynamic analysis. Based on this comparison, which elements might be encoded?

By running strings over this malware we see reference to what looks to be a custom Base64 index string, an error associated with an API, references to listing directory contents and spawning cmd.exe, a possible C2 of www.practicalmalwareanalysis.com, and reference to key and block length which seems to indicate that Base64-encoding and possible encryption is used in this binary.

By executing this when procmon and fakenet is running, we can see a connection occurs back to www.practicalmalwareanalysis.com via encrypted traffic on port 8910 which is then followed by cmd.exe running without any further actions. This is a classic sign of a potential reverse shell where commands sent through this connection are sent to cmd.exe for executing on the host.

At this point we still don’t know what elements may be encoded, but we have enough evidence to assume that this does use encoding of some kind. To get a bit more information, we can setup a netcat listener on port 8910 and leverage ApateDNS to notify the malware that www.practicalmalwareanalysis.com can be found at 127.0.0.1. By doing this we’re able to catch the malware connection which we suspect to be a reverse shell, and attempt to run a command such as ‘dir’.

Based on the response received, we can begin to assume that the response to commands run from the C2 of this malware is encoded.

Question 2

Use static analysis to look for potential encoding by searching for the string xor. What type of encoding do you find?

By looking for the string ‘xor’ in IDA we find that there are 194 entries. To reduce the amount of noise generated by this search (given we want to exclude any register clearing functions as a start) we can search using regex to look for only operations which contain items inside of ‘[]’ given that register clearing will never contain this.

xor .*,.*$*$


This drops us down to 68 entries instead of 194. By viewing the first entry at ‘00401F56’ we find this is located within a subroutine ‘sub_401AC2’.

By looking at when this subroutine finishes we find that it finishes at ‘00402237’. We now know that any entries for XOR between 00401AC2 and 00402237 fall under this subroutine, so we give it a name of XOR_OP_1.

If we then run the same search and look for the first xor operation that falls after 00402237 (004022DD), we find another subroutine (sub_40223A) which begins at 0040223A and ends at 004027EA, so we give it a name of XOR_OP_1. By repeating this process we find the following six functions perform xor operations that look like they may be encoding, of which the type of encoding is not yet clear.

• sub_401AC2: XOR_OP_1 (00401AC2 to 00402237)
• sub_40223A: XOR_OP_2 (0040223A to 004027EA)
• sub_4027ED: XOR_OP_3 (004027ED to 00402DA5)
• sub_402DA8: XOR_OP_4 (00402DA8 to 00403163)
• sub_403166: XOR_OP_5 (00403166 to 0040352A)
• sub_403990: XOR_OP_6 (00403990 to 00403A06)

There is one other XOR reference we haven’t accounted for; however, this falls within a OS library function so we’re not concerned about it.

Question 3

Use static tools like FindCrypt2, KANAL, and the IDA Entropy Plugin to identify any other encoding mechanisms. How do these findings compare with the XOR findings?

Leveraging KANAL, we’re able to see references to indicate this is likely using Rijndael (AES) encryption at address 0040C908, and 0040CA08.

If we examine the .rdata section using IDA-Ent and look for random data (Chunk Size: 256 - Max Entropy: 7.9), we find a number of results appear between 0040C8EC and 0040CA1A which aligns with what we found using KANAL.

Changing this to look for Base64-encoded strings (Chunk Size: 64 - Max Entropy: 5.95) reveals an area within the .data section that appears to be Base64-encoded between 0041209E and 004120A7.

As mentioned in Lab13-01, as a substitute for Findcrypt we can use Ghidra and a ported plugin FindCrypt-Ghidra to find evidence, once again of AES encryption being used.

• Td0: 0040db08
• Td1: 0040df08
• Td2: 0040e308
• Td3: 0040e708
• Te0: 0040cb08
• Te1: 0040cf08
• Te2: 0040d308
• Te3: 0040d708

Based on the above we can see that these findings help us infer AES is likely being used when compared to performing a simple XOR check.

Question 4

Which two encoding techniques are used in this malware?

From the analysis above we can make an informed assumption that the two techniques used in this malware are Base64-encoding using a custom index string and AES Encryption.

Question 5

For each encoding technique, what is the key?

To determine the AES encryption key we go back to the earliest known address which appeared to be associated with encryption, and in this case it’s address 00401AC2 under XOR_OP_1 as we identified it looking for XOR operations. In this we can quickly see reference to a key being provided.

By examining cross-references to this function we find one reference within the main function. Slightly before the call we find a string being pushed to the stack which appears to be our key ‘ijklmnopqrstuvwx’.

At this point we can infer that the AES encryption key is likely ‘ijklmnopqrstuvwx’.

By looking at the start of the identified Base64-encoded data (0041209E) we can see reference to the Base64-encoding index string in use which we previously found using strings in question 1.

At this point we can infer that the custom idex string used for this Base64-encoding is

CDEFGHIJKLMNOPQRSTUVWXYZABcdefghijklmnopqrstuvwxyzab0123456789+/


Question 6

For the cryptographic encryption algorithm, is the key sufficient? What else must be known?

When it comes to AES encryption a key in itself isn’t always sufficient to decrypt the content encrypted using it. If we take a look at the AES decryption routines built into CyberChef, we can see that based on the AES standard implemented you will also likely need to know the key size and algorithm, any Initialisation Vector, and the mode used to encrypt the content.

Question 7

What does this malware do?

Based on the dynamic and static analysis above we can begin to feel confident that this acts as a reverse command shell which beacons responses to commands run as encrypted output to the IP resolved from www.practicalmalwareanalysis.com. Exactly how this relates to the identified AES encryption and Base64-encoding is unknown so we explore the binary further.

Starting with the custom Base64-encoded index string, we find it is referenced in a subroutine at ‘sub_40103F’.

If we look at cross-references to this subroutine, we find is is called in another large routine at ‘sub_401082’.

Of note is that this appears to have 2 large loops which at a high level may indicate a decoding or encoding function is implemented here, or that it is checking for user input. We’re not looking to examine every operation, but rather looking to identify the key aspects of this malware based on observed characteristics. As such if we examine cross-references to ‘sub_401082’ we find it is called inside a windows API call to ‘StartAddress’ used to start its own thread, which if we once again examine cross-references find it is called within ‘sub_4015B7’.

What we can gleam from this is that the Base64 decoding function looks to occur after cmd.exe is run, and if we continue looking through these cross-references we can see evidence that a socket connection to www.practicalmalwareanalysis.com occurs slightly before a pipe is created to pass the input and output from this socket directly to cmd.exe.

Based on this and our dynamic analysis, we begin to suspect that any input, or commands sent from the C2 to cmd.exe will need to come in as a Base64-encoded string using the previously identified custom index string. To identify if this is related to the AES encryption we identified, we first need to know where AES operations are hiding. Based on our Findcrypt results in Ghidra, we know that anything labeled Td0 to Td3 is related to a decryption AES operation, and anything labeled Te0 to Te3 are related to an encryption AES operation.

In this instance, due to the addresses falling within XOR_OP_3 and XOR_OP_2 functions it means that:

• XOR_OP_3 is related to decryption
• XOR_OP_2 is related to encryption

By graphing the user defined cross-references to both XOR_OP_3 and XOR_OP_2, we find in addition to the above that XOR_OP_5 is related to decryption, and XOR_OP_4 is related to encryption.

From here we want to understand XOR_OP_1 and XOR_OP_6 and how they fit into this piece of malware. By graphing user defined cross-references to the main function of the malware, we can see that the AES operations aren’t related to the base64-encoded functions we identified previously in addition to how XOR_OP_1 and XOR_OP_6 fit into the picture.

Of interest is that this flow doesn’t show either of the routines XOR_OP_3 or XOR_OP_5, indicating that the decryption routine may never be used in this binary. Looking at cross-references to XOR_OP_5 we find that it looks to be called by part of the program that is marked as code but has no clearly defined function. By moving to the start of this section (00403745) and creating a function, we see what looks to be an uincovered decryption routine.

At this point we can rename this ‘Decrypt_AES’, and take a very similar looking function we previously identified (0040352D) which calls XOR_OP_4, and rename this ‘Encrypt_AES’. After graphing user defined xrefs, we can see the relation between these 2 functions.

Finally we take a look at how this encryption function relates to the rest of the malware.

In this case we find that it is called within ‘sub_40132B’ which is started in a thread after cmd.exe has been run and our previous StartAddress call has run. It performs the AES encryption, and then writes the output back to the console (which in this case is redirecting the output back through the established socket).

Through all of this analysis we can conclude that this malware creates a reverse shell back to its C2 at www.practicalmalwareanalysis.com. Any incoming commands to the reverse shell are decoded using Base64 and a custom index string of

CDEFGHIJKLMNOPQRSTUVWXYZABcdefghijklmnopqrstuvwxyzab0123456789+/


and any responses to those commands are encrypted using AES with a key of ijklmnopqrstuvwx before being sent back to the C2.

Question 8

Create code to decrypt some of the content produced during dynamic analysis. What is this content?

To do this we first need to get some content. First off we fire up ApateDNS and netcat like we did back in question 1 of this lab exercise; however, this time we’re going to setup the netcat listener on a remote system and run Wireshark to capture traffic on one of the systems.

• nc.exe -nlvp 8910

After running the malware we quickly see a connection, and if we kill malware with CTRL + C we then see what it was sending back to the server, which in this case looks like gibberish as it’s encrypted.

Examining the related TCP stream in Wireshark as a hex dump reveals different data which has been sent, in this case it is the below hex.

37 f3 1f 04 51 20 e0 b5 86 ac b6 0f 65 20 89 92
4f af 98 a4 c8 76 98 a6 4d d5 51 8f a5 cb 51 c5
cf 86 11 0d c5 35 38 5c 9c c5 ab 66 78 40 1d df


By using CyberChef, we can confirm our analysis about encryption by checking the decoded output of this hex using the key we identified and ‘0’ padding as required given no IV is used. From this output we can see it is the starting header shown when cmd.exe is run.

If we were to know the exact response format of what is sent from the C2 server, we could encode our commands using the custom Base64 index string we’ve identified such as the below; however, during testing this failed to get a response when sent from netcat, likely due to extra headers typically being sent from the legitimate C2 and the malware being unstable.

To manually decode the Base64-encoded data, we can use the following python2 script which is heavily taken from the PMA material.

import string
import base64
s = ""
index_string = 'CDEFGHIJKLMNOPQRSTUVWXYZABcdefghijklmnopqrstuvwxyzab0123456789+/'
b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
b64_command = 'f2jxAY1r'
for ch in b64_command:
if (ch in index_string):
s += b64[string.find(index_string,str(ch))]
elif (ch == '='):
s += '='
print base64.decodestring(s)


This will take a command which has been encoded using our custom index string and decode it.

To manually decrypt the AES encrypted data, for a change we can use the following python3 script created for this purpose.

from Crypto.Cipher import AES
from binascii import unhexlify
raw = '37 f3 1f 04 51 20 e0 b5 86 ac b6 0f 65 20 89 92 ' + \
' 4f af 98 a4 c8 76 98 a6 4d d5 51 8f a5 cb 51 c5 ' + \
' cf 86 11 0d c5 35 38 5c 9c c5 ab 66 78 40 1d df '
ciphertext = unhexlify(raw.replace(' ',''))
IV = unhexlify('00000000000000000000000000000000')
key = 'ijklmnopqrstuvwx'
obj = AES.new(key, AES.MODE_CBC, IV)
print(obj.decrypt(ciphertext).decode('UTF-8'))


The end result is 2 custom python scripts, one using Python2, and one using Python3, designed to decode bothe the Base64-encoded string, and the AES encrypted data.

python2 ./B64Decode.py
whoami

python3 ./AESDecrypt.py
Microsoft Windows XP [Version 5.1.2600]


This concludes chapter 13.

Chapter 14. Malware-Focussed Network Signatures

Operations Security (OPSEC) Considerations:

• Safest option is to not be connected to the internet when analysing malware.
• If you must, use passive information gathering or indirection tactics.

Indirection Tactics:

• Utilise TOR, an open proxy, or a web-based anonymiser when investigating.
• Utilise a dedicated machine for research and hide location via cellular connection, tunnelling via SSH or VPN to remote infrastructure, and/or use a cloud service such as Amazon EC2.
• Note: Cloud services may have specific conditions on running malware/research. Check this to avoid getting your service suspended.
• Utilise a cloud-based sandbox which allows interaction for analysis.
• Note: Many free cloud-based sandboxes are public which immediately poses a risk of notifying an adversary you’re performing analysis.
• Utilise a cloud-based search/scanning service.
• Note: Many free cloud-based search/scanning services are public which immediately poses a risk of notifying an adversary you’re performing analysis.

Commonly used cloud-based tools (As of writing):

Note: This lab uses Snort rules, and in many instances $HOME_NET and$EXTERNAL_NET have been used and changed around. As we are simulating an external C2 using local systems, $HOME_NET has been used to test our rules in many cases where$EXTERNAL_NET would be appropriate (to indicate the connection is coming from an external source).

Lab 14-01

Analyze the malware found in file Lab14-01.exe. This program is not harmful to your system.

Question 1

Which networking libraries does the malware use, and what are their advantages?

Opening the malware using PE-bear, we find that it is importing the Windows DLL urlmon.dll (OLE32 Extensions for Win32) used for Object Linking and Embedding based API calls. Of this it calls the ‘URLDownloadToCacheFile’ API call which leverages COM objects.

By using Fakenet-NG and running this malware, we can see that it beacons to www.practicalmalwareanalysis.com with the below GET request.

GET /ODA6NmU6NmY6NmU6Njk6NjMtSUVVc2Vy/y.png HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0;
SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Host: www.practicalmalwareanalysis.com
Connection: Keep-Alive


If we now utilise a cloud-based tool to parse User Agents called WhatIsMyBrowser, we’re able to ascertain whether this is likely to be a valid, known User Agent or not.

In this instance it is, and it correctly identifies the OS the malware was run from. This is one of the advantages to using COM Interfaces as the request API automatically takes the appropriate User Agent from the operating system.

Question 2

What source elements are used to construct the networking beacon, and what conditions would cause the beacon to change?

In the above example we can see that the networking beacon came out as ‘ODA6NmU6NmY6NmU6Njk6NjMtSUVVc2Vy’. Running the malware again on the same host reveals the same output. By Base64 decoding this we get the below.

• 80:6e:6f:6e:69:63-IEUser

In this instance we believe that the first element is a MAC address of some kind appended with ‘-‘ and the current logged on user. If we run ‘getmac’ to check if this is taken from the network adapters on this system, we find that it doesn’t match.

To further investigate what this is made up from we can open Lab14-01.exe in IDA.

Immediately we can see that a call to GetCurrentHwProfileA is run prior to a call to GetUserNameA which helps to back up what we’ve found so far.

Another way of retrieving the GUID referenced by this API is to check the registry.

reg query "HKLM\System\CurrentControlSet\Control\IDConfigDB\Hardware Profiles" /s


From here we can see that the networking beacon leverages this API which gets the last section (12 characters) from this registry key.

If we run this again in a different machine, we find that it has a different User Agent for the new OS.

GET /ODA6NmQ6NjE6NzI6Njk6NmYtYm9i/i.png HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E)
Host: www.practicalmalwareanalysis.com
Connection: Keep-Alive


In addition to seeing new Base64-encoded data based on this system GUID and user account.

• 80:6d:61:72:69:6f-bob

Question 3

Why might the information embedded in the networking beacon be of interest to the attacker?

As the information uncovered above is meant to be used for uniquely identifying systems and users, this may be of interest to an attacker who wants to keep track of infected clients and specifically target certain users or systems.

Question 4

Does the malware use standard Base64 encoding? If not, how is the encoding unusual?

If we look at the Strings window of this malware we can see what appears to be a Base64-encoding index string.

By looking at cross-references to this we can find it is used inside of ‘sub_401000’ which appears to be our encoding routine. Of interest is that this has a modified ‘padding’ character used as ‘61h’ (a) meaning that any padding required in the Base64-encoded data will appear as the letter ‘a’ rather than the standard ‘=’.

We recognise this construct as it is similar to what we saw in Lab 13-1, question 5 except with the change of padding character.

Question 5

What is the overall purpose of this malware?

To determine this we need to move back to the main method of this malware and examine the call it makes to ‘sub_4011A3’ after the base64-encoding routine occurs. Within this routine we find that a call is made to ‘URLDownloadToCacheFileA’ which is used to download a file to the internet cache directory and return the file name/location.

Of interest is that this is also passed directly to CreateProcessA and as such the file downloaded would be immediately run. Examining the calling process reveals this would wait ‘0EA60h’ (60000) milliseconds if this fails and try to download it again.

Question 6

What elements of the malware’s communication may be effectively detected using a network signature?

Examining the beacon which is sent we know that it will always send the base64-encoded values followed by a single character png resource which is one element which remains consistent. It should be noted that this character is taken from the final letter in the Base64-encoded content.

In addition to this we know that it sends base64-encoded data via the %s variable passed to sprintf which contains a MAC reference followed by ‘-‘ and a username. Although the username and specific MAC will likely change, the colons and dash which separate this will remain consistent making it another element that can be used.

Finally the beacon makes a request to www.practicalmalwareanalysis.com which is a consistent C2 in this case, making it once again a useful element to use.

Question 7

What mistakes might analysts make in trying to develop a signature for this malware?

Analysts may make a signature too broad or too lax. In this instance if analysis wasn’t done on what is creating the beacon and its use of abnormal padding analysis may make it seem like ‘a.png’ is always being retrieved (for example in the case where padding needed to be used and made the end of the base64-encoded string ‘a’). Another mistake would be to target the User-Agent, username, MAC, or another field which is dynamically set based on the system the malware is run on. If this was setup to alert on any traffic to this domain then in the case of a compromised domain or a domain which is reused it would be very easy to make the rule too broad.

Question 8

What set of signatures would detect this malware (and future variants)?

To detect this malware we’re going to want to create at least 2 Snort rules, one to identify Base64-encoded data sent when fetching the single character png resource, and one to identify any base64-encoded data which has a pattern involving colons and finally a ‘-‘ character.

Creating colon and dash signature:

Because we know that this data is Base64-encoded, we need to first look again at how this translated to the Base64-encoded data we will see. In this case we know that for every 4 bytes of Base64-encoded data it will translate to 3 bytes of plaintext. Examining this decoded data reveals a pattern whereby the presence of a colon after 2 characters (to ensure no padding) is signified ending with the number ‘6’, and the presence of a dash after 2 characters (to ensure no padding) is signified by the letter ‘t’.

From this we need to create some regex which will be used to identify the above pattern signified in words below.

• 3 characters followed by the number ‘6’, 5 times.
• 3 characters followed by the letter ‘t’, 1 time.
• 4 or more characters.

An easy way to start piecing this together is to use an online validation tool such as regex101.

Starting with some base64 detection logic, we want to look for any possible base64 character. Note in this instance we’ve modified the regex to be from “[A-Za-z0-9+\/=]” to be “[A-Za-z0-9+\/a]” due to the custom encoding method used and we’re using quantifiers to match 3 instances followed by the number ‘6’.

[A-Za-z0-9+\/a]{3}6


This makes up the first part of our pattern mentioned above. By changing the number ‘6’ to the letter ‘t’, we get the second part of our detection pattern.

[A-Za-z0-9+\/a]{3}t


To get the third part of our detection pattern we can simply match on 4 or more characters.

[A-Za-z0-9+\/a]{4,}


Finally, we can piece this all together by using a capture group and by specifying the number of hits required.

([A-Za-z0-9+\/a]{3}6){5}[A-Za-z0-9+\/a]{3}t[A-Za-z0-9+\/a]{4,}


Piecing this into a Snort rule we need to ensure this is for the following conditions:

• Only HTTP ports
• Only content which is 32 bytes or above in length (we know this as the smallest MAC address + a username with 1 letter would be 19/3*4 characters long) which is appended by ‘GET’ and prepended by the fetched file name.
• Only GET requests
• Only within the first 10 bytes of the connection
• Uses perl compatible regex (same as what we used for validation with regex101)
• Uses a SID > 1,000,000 (as SID values 1-999,999 are reserved for Snort rule usage)

 alert tcp $HOME_NET any ->$EXTERNAL_NET $HTTP_PORTS (msg:”PMA Lab14-01 colon and dash”; urilen:>31; content:”GET 20 /”; depth:10; pcre:”/GET\x20\/([A-Za-z0-9+\/a]{3}6){5}[A-Za-z0-9+\/a]{3}t[A-Za-z0-9+\/a]{4,}\//”; sid:1337347; rev:1;) Using Snort which we’ve setup and configured on a pfSense firewall, we can add in our custom Snort rule. At this point by running the malware we find that our new Snort rule works and we’ve created our colon and dash signature. Creating Base64 and png signature: To move into our second rule, we can do something similar to what we’ve done above, only modify this to instead only look for .png files being requested after a base64-encoded string where the file being requested has the name of the last character from our previously matched base64-encoded string. [A-Z0-9a-z+\/a]{24,}([A-Z0-9a-z+\/a])\/\1\.png  The end result is the below Snort rule. alert tcp$HOME_NET any -> $EXTERNAL_NET$HTTP_PORTS (msg:"PMA Lab14-01 Base64 and png"; urilen:>31; uricontent:".png"; pcre:"/\/[A-Z0-9a-z+\/a]{24,}([A-Z0-9a-z+\/a])\/\1\.png/"; sid:1337348; rev:1;)


By adding this Snort rule into our pfSense box and running the malware again, we see that both of our Snort rules have been hit.

At this point we’ve now developed some network signatures to detect this malware now and in the future. By combining these with any network traffic to www.practicalmalwareanalysis.com we should have a robust way of detecting this dropper over the wire.

Lab 14-02

Analyze the malware found in file Lab14-02.exe. This malware has been configured to beacon to a hard-coded loopback address in order to prevent it from harming your system, but imagine that it is a hard-coded external address.

Question 1

If we consider malware that uses direct IP addresses there are a number of advantages and disadvantages for both the malware author, and the defender. If we take this from the malware author’s perspective the following applies.

• IP addresses may host numerous legitimate websites or services, and as such it may be difficult for a defender to just block this at a firewall.
• A static IP address isn’t suceptible to DNS Sinkholing whereby a malicious domain could be sinkholed.
• A domain doesn’t need to be registered, and so there’s no risk of the domain registration being seized, or leaking information that could be used to identify or track the malware author and their actions.

• Web requests to a public IP are often suspicious as most people only browse websites through their associated DNS entry.
• Using a static IP ensures that technniques such as Domain Fronting cannot be used.
• Static IP addresses are more difficult to maintain as the infrastructure malware points to is hard-coded, whereas a Domain allows it to be redirected by only updating a DNS Server if infrastructure was to be taken down.

Question 2

Which networking libraries does this malware use? What are the advantages or disadvantages of using these libraries?

Using CFF Explorer VIII we can see that this makes use of WinInet.dll and its associated API calls.

• InternetCloseHandle
• InternetOpenUrlA
• InternetOpenA

An advantage of these API calls is that they are more granular and as such has access to work with caching and cookies. In addition they don’t rely on a COM object which if corrupted could cause issues.

A disadvantage of these API calls is that they require many elements such as a User Agent to be manually entered. A comparison between WinInet and WinHTTP can be found here

Question 3

What is the source of the URL that the malware uses for beaconing? What advantages does this source offer?

If we leverage Fakenet-NG and run the malware we can see that it makes a request to the local system loopback IP of 127.0.0.1 (in this case we pretend this is a C2 IP). This occurs with an unusual user agent which is then followed by another request with an unusual user agent ‘Internet Surf’.

Lab14-02.exe (2140) requested TCP 127.0.0.1:80
GET /tenfour.html HTTP/1.1
Host: 127.0.0.1
Cache-Control: no-cache

GET /tenfour.html HTTP/1.1
User-Agent: Internet Surf
Host: 127.0.0.1
Cache-Control: no-cache


To determine the source of this IP we can work back from the networking calls we found inside of WinInet.dll using IDA. The subroutine which call these can be found at ‘sub_4015C0’ or ‘sub_401800’ which is also called by ‘sub_4015C0’.

If we look at how this is launched by examining cross-references, we find that these network connections are being launched in their own threads one after another from within WinMain which reflects what we’ve seen during the dynamic analysis above.

In both of these calls the source of the URL is being passed to them, so we need to continue looking back to see how this is fetched. Of note is that directly before these network calls we can see evidence of pipes being created and cmd.exe starting which leads us to believe this malware may be a reverse TCP command shell.

Of interest is that at the start of this program we find a call to ‘LoadStringA’ which is used to load in a string resource which is then stored within a buffer of EAX which currently holds a reference to ‘[esp+1A8h+Buffer]’. This is then loaded into ebx which becomes the read handle, or ‘input’ stream into this anonymous pipe. Due to an Event Object creation used to prevent thread conflicts and multiple anonymous pipe operations this can be difficult to explain; however, a simplified overview of how this works is below.

If we take a look at the resource section of this malware using PE-bear we can see that the C2 in question is what we saw in our dynamic analysis.

http://127.0.0.1/tenfour.html


From this we know that the source of the URL that the malware uses for beaconing is a string contained within the resource section of this malware. As embedded resources can be easily modified this provides an advantage of allowing the C2 to change, or for this to function as a backdoor to multiple different C2 servers without having to modify and recompile the binary.

Question 4

Which aspect of the HTTP protocol does the malware leverage to achieve its objectives?

From our dynamic analysis there looks to be some strange data contained within the User-Agent field so we investigate that further. First we look at the thread creation which uses the anonymous pipe we saw created in the previous section.

Within StartAddress at ‘0x004014C0’ we can see this calls ‘PeekNamedPipe’ with the read end of the anonymous pipe being referenced in ECX, and the output being sent to ESI (the source for an upcoming string operation).

In this instance if content exists on the named pipe (for example the output from cmd.exe starting or output of commands being run into this terminal) the malware proceeds to run sub_401000 passing in ESI to its buffer prior to running loc_401750.

Looking at sub_401000 which is passed the output from our anonymous pipe we find that this construct is familiar and looks to be a Base64-encoding routine which is leveraging a value defined by ‘byte_403010’.

Examining byte_403010 we find that this looks to be referencing an unknown value followed by looks to be our Base64 index string.

To fix this we can convert all of it to be the string we’d expect as follows.

WXYZlabcd3fghijko12e456789ABCDEFGHIJKL+/MNOPQRSTUVmn0pqrstuvwxyz


In this instance the base pointer contains our base64 encoded content and is then used within loc_401750 to concatenate our encoded content with the value ‘(!<’.

From this we know that the malware leverages the User-Agent to achieve its objectives.

Question 5

What kind of information is communicated in the malware’s initial beacon?

Taking our output from running the malware and our knowledge from the above analysis on custom Base64 index string used, we can decode the output and confirm this is the standard output of cmd.exe being run.

From this we know the initial beacon is an encoded command prompt.

Question 6

What are some disadvantages in the design of this malware’s communication channels?

To identify some disadvantages in the design of this malware’s communication channels we can look within ‘sub_4015C0’ which is what is run within the second thread of this malware. Inside of this we immediately see this uses ‘sub_401800’ to make the outgoing internet connection, so we examine this further.

inside sub_401800 we can see what appears to be very basic operations with a hardcoded User-Agent of “Internet Surf” being sent with the output being passed directly into our anonymous pipe of cmd.exe which is then read and the internet connection closed.

At this point we know the communication channels both to and from the anonymous pipe to cmd.exe. What’s apparent is that outgoing connections use a hardcoded User-Agent which can be used to fingerprint this malware. In addition no encoding is done on commands being sent from the server.

To detect this malware we can create and test some Snort rules; however, given this is set to beacon to the local system’s loopback address it will never traverse through our gateway, and as such our pfSense system running Snort will never see the traffic. In addition if there’s no resource receiving the connection on the end then the initial internet connection fails prior to any User-Agent being sent and we are left without any Snort rules being triggered.

For us to get around this we first need to modify the resource section of this malware (e.g. by using Resource Hacker) to instead beacon to a private IP we have control over and can run a couple of netcat listeners on. One issue we encounter here is that the malware is set to read a certain amount of characters from this resource section, so whatever IP address we choose to beacon to needs to be the same number of characters (9) as 127.0.0.1.

To get around this we can use a hardcoded DNS entry (in this case CYBERAIJU) consisting of 9 characters, and then modify our hosts file to point this to a private IP we control.

Creating Suspicious Resource signature:

Note - Depending on how the malware was run, whether there was a successful network connection, and how the malware threads are ended, we may find that the malware has deleted itself. It’s recommended a backup of the malware be created.

In this instance we can now setup a basic Snort rule for the malware and see if this works. One consistent element in this malware is that it always fetches a resource at ‘/tenfour.html’ which although in itself may only be a low to medium fidelity indicator, is a good starting point.

alert tcp $HOME_NET any -> any$HTTP_PORTS (msg:"PMA Lab14-02 Suspicious Resource"; uricontent:"/tenfour.html"; sid:1337349; rev:1;)


If we now setup netcat listeners on our receiving machine (in this case 10.13.13.107) and add in the created Snort rule we can see if it worked.

Upon running the malware we see 2 successful connections to our Netcat listeners for both threads as expected.

Checking our snort alerts we find 2 successful alerts based on connections to this C2 resource.

Creating Suspicious User Agent signatures:

In this instance we’re going to leverage the unique User-Agent elements used by this malware and also classify this classtype as ‘trojan-activity’ to give the alert a little more weighting and severity.

In this instance we’ll use the ‘Internet Surf’ User-Agent.

alert tcp $HOME_NET any -> any$HTTP_PORTS (msg:"PMA Lab14-02 Suspicious User-Agent - Internet Surf"; flow:to_server; content:"User-Agent|3A 20|Internet|20|Surf"; http_header; classtype:trojan-activity; sid:1337350; rev:1;)


In addition to any User-Agent beginning with “(!<”.

alert tcp $HOME_NET any -> any$HTTP_PORTS (msg:"PMA Lab14-02 Suspicious User-Agent - Starts with (!<"; flow:to_server; content:"User-Agent|3A 20|(!<"; http_header; classtype:trojan-activity; sid:1337351; rev:1;)


If we repeat the process used to test our suspicious resource signature, we can see there’s new alert hits this time categorising the activity as a network trojan and assigning a severity level of 1.

The combination of these alerts is enough for any responder to have a strong indication of malicious activity occurring on this system.

Question 7

Is the malware’s encoding scheme standard?

From our analysis in question 4 we know that the malware’s encoding scheme is Base64 but not using the standard index string.

Question 8

How is communication terminated?

Looking back into this malware within IDA, after establishing a connection through ‘sub_401800’ contained within ‘sub_4015C0’, a comparison is then made looking for the term ‘exit’.

If this is found then the thread will exit and communication will be terminated. Inside of the main method we find that upon this program finishing or threads being killed this runs a sub-routine at ‘sub_401880’.

Taking a look into this sub-routine it appears to be used simply to issue a file delete on the malware once it is finished running, failed to run/connect back to its C2, or if it had its threads terminated.

Question 9

What is the purpose of this malware, and what role might it play in the attacker’s arsenal?

From our analysis above we know the purpose of this malware is to establish a reverse TCP command shell which passes data through a user-agent to try and evade network analysis techniques. Given the malware attempts to delete itself it’s likely this is only used during initial access to a system prior to further malware or persistence being setup and is simply a disposable means to an end.

Lab 14-03

This lab builds on Lab 14-1. Imagine that this malware is an attempt by the attacker to improve his techniques. Analyze the malware found in file Lab14-03.exe.

Question 1

What hard-coded elements are used in the initial beacon? What elements, if any, would make a good signature?

By running the malware and using Fakenet-NG, we can get a glimpse of the beacon this sends.

If we compare this beacon to elements seen in Lab14-1 we find the below.

Lab 14-1:

GET /ODA6NmU6NmY6NmU6Njk6NjMtSUVVc2Vy/y.png HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E)
Host: www.practicalmalwareanalysis.com
Connection: Keep-Alive


Lab 14-3:

GET /start.htm HTTP/1.1
Accept: */*
Accept-Language: en-US
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Host: www.practicalmalwareanalysis.com


Of interest is that this beacon has sent some new or modified elements in its HTTP Header including the below:

• Accept-Language
• UA-CPU
• User-Agent

Based on this we begin to assume these may be hard-coded elements. Looking closely at the User-Agent it looks as if the malware author may have a bug in their code because it’s sent “User-Agent: “ as part of the User Agent. This would make a good signature.

If we open up IDA and look for reference to this beacon based on the User-Agent, we find that in addition to the above 3 elemets, the header fields of ‘Accept’ and ‘Accept-Encoding’ are also hard-coded, as is the beacon URL.

http://www.practicalmalwareanalysis.com/start.htm


Question 2

What elements of the initial beacon may not be conducive to a longlasting signature?

If we examine the hard-coded URL above and where it is referenced, we find that it is located in a function ‘sub_401457’.

Of interest is that this attempts to get a handle on a file C:\autobat.exe with read access. Where this fails it will call ‘sub_401372’ which is used to create the file and write into it the contents of this hard-coded URL C2 before running itself again. Where this succeeds it will get a handle on the file and read it into a buffer which is then later used in ‘sub_4011F3’ within the main method.

If we take a look at cross-references which call ‘sub_401372’, we find that there’s one other function which calls it within ‘sub_401651’. If we continue to examine cross-references it looks like this may be taking input from the C2 indicating that there’s another way for this C2 URL to be written to ‘C:\autobat.exe’. From this we can assume a couple of things:

• The domain and URL found in this are hard-coded but only if an existing file C:\autobat.exe with a configured C2 isn’t present.
• The Domain, URL, Host, or GET parameters wouldn’t be conductive to a longlasting signature.
• By creating a 0-byte inoculation file at C:\autobat.exe we can effectively prevent this malware from beaconing to its C2.

Question 3

How does the malware obtain commands? What example from the chapter used a similar methodology? What are the advantages of this technique?

Taking a closer look at sub_4011F3 we found earlier, we can see that after attempting to initiate the C2 beacon connection, we can see that after reading the .htm file hosted in the C2, it begins searching for elements which start with “<no” in addition to performing a subroutine at sub_401000 before comparing other elements.

To properly unravel this we can take a closer look into sub_401000 which looks to be involved in constructing a comparison string. What is initially obvious ios that there are a number of comparisons looking for HEX characters, so it appears this may be a string obfuscation technique to make analysis more challenging.

If we use ‘r’ on the hex characters we can convert them into their letter equivalent. In addition we need to pay attention to the movsx operations beforehand which help to guide us in the order the string comparison will take place (this takes the form of ‘register + position’).

If we expand these comparisons out and sort by the position number we get the below:

movsx   ecx, byte ptr [eax]
cmp     ecx, 'n'
movsx   edx, byte ptr [ecx+1]
cmp     edx, 'o'
movsx   eax, byte ptr [edx+2]
cmp     eax, 's'
movsx   ecx, byte ptr [eax+3]
cmp     ecx, 'c'
movsx   ecx, byte ptr [eax+4]
cmp     ecx, 'r'
movsx   eax, byte ptr [edx+5]
cmp     eax, 'i'
movsx   edx, byte ptr [ecx+6]
cmp     edx, 'p'
movsx   eax, byte ptr [edx+7]
cmp     eax, 't'
movsx   edx, byte ptr [ecx+8]
cmp     edx, '>'


This in turn allows us to see it is checking for the entry “

Based on the search being read and comparisons taking place, we can assume this filter is looking for something similar to the below where is any random string.

<noscript><DYNAMICCONTENT>http://www.practicalmalwareanalysis.com/<COMMAND>/<ARG>96'


For a final piece of analysis we take a look at sub_401684 which is run immediately preceding this response and appears to bne running one of 3 different subroutines depending on the response received.

This leads us to believe that the malware obtains commands through

Question 4

When the malware receives input, what checks are performed on the input to determine whether it is a valid command? How does the attacker hide the list of commands the malware is searching for?

Based on the above analysis we know that the malware receives input from the C2 and looks for the presence of

This comes in the form of a switch whereby case ‘0’ (loc_4016E9) is run when it finds the value ‘d’. This comparison is looking for the first byte of the first token. From this the switch uses reference to a table at byte_40173E to then look within an offset stored at ‘off_40172A’.

The calculations on specifically translating these offsets into values can be confusing as it uses an index to determine which case to jump to. An easy way to describe this is to view byte_40173E as undefined data as shown below.

Essentially if the character sent is 10 higher than ‘d’, the switch case to run is ‘1’. If the character sent is 14 higher than ‘d’ the switch case to run is 2. If the character sent is 15 higher than ‘d’ the switch case to run is 3. Otherwise the switch case to run is 4.

Adding these onto ‘d’ (4) you get ‘n’ (14), ‘r’ (18), and ‘s’ (19) respectively.

These cases take an input which is only evaluated from the first character in the command sent from the server. So in this case any word starting with ‘d’, ‘n’, ‘r’, or ‘s’ can be sent to run a command through this malware.

Question 5

What type of encoding is used for command arguments? How is it different from Base64, and what advantages or disadvantages does it offer?

Examining ‘loc_40170E’ we find that it runs ‘sub_401651’ which calls what looks to be a decoding routine at ‘sub_401147’. Within this we can see what appears to be a non-standard encoding routine. We know this because it doesn’t quite follow the basis of breaking 3 bytes into 4 bytes, and instead has a call to ‘strlen’ to break this string apart for encoding, before ‘ebp+var_4’ is increasing by 1, and ‘ebp+var_8’ is increasing by 2.

If we take a look at what we would usually presume to be an index string in the case of Base64-encoding, we can see that it isn’t made up of enough characters, nor does it have all the values required. Close analysis reveals that this takes 2 chars which are then turned into a number, and then cross references that number to an index within the identified string.

	/abcdefghijklmnopqrstuvwxyz0123456789:.


An advantage of this is that it is non-standard so isn’t easily fingerprinted and would need to be reversed. A disadvantage is that it is fairly basic, and by understanding it we will be able to create some robust signatures in later questions due to the known structure of how URLs are used.

Question 6

What commands are available to this malware?

To determine what commands are available to is malware we need to look into the subroutines inside of ‘sub_401684’. Remembering the array we identified in question 4, the possible cases and their triggers are shown below.

• Case 0 (d): loc_4016E9
• Case 1 (n): loc_4016F7
• Case 2 (r): loc_40170E
• Case 3 (s): loc_401700
• Case 4 (other): loc_401723

You’ll notice this order is slightly different to how it is shown left -> right in IDA.

In this instance 3 options cause a subroutine to be called, whereas one just updates a variable which is then used to quit the C2 loop and thus the program. The possible subroutines and their associated trigger letter are shown below.

• d: sub_401565
• n: NO SUBROUTINE (quit)
• r: sub_401651
• s: sub_401613

By examining sub_401565 (d) we get a pretty clear indication that this takes an argument before using this to download and run another application. This also uses a call to ‘sub_401147’ so we know the argument passed takes uses the previously identified decoding routine.

By examining sub_401613 (s) we can see that this looks to be a simple sleep function which sleeps for 20,000 milliseconds if no argument was given, otherwise it sleeps for however many seconds were sent as an argument.

By examining sub_401651 (r) we can see that this has a call to ‘sub_401147’ to decode any provided URL, before calling ‘sub_401372’ which we identified in question 2 as being responsible for updating the C2 configuration file.

Putting this all together we know what commands are available to this malware.

Question 7

What is the purpose of this malware?

Based on the above commands available to this malware we can presume this is a malware dropper AKA a ‘Downloaders and Launcher’. This differs from traditional throwaway malware which may exist only to drop malware before removing itself in that it sets up persistence to allow further malware and C2 to be dropped over time.

Question 8

This chapter introduced the idea of targeting different areas of code with independent signatures (where possible) in order to add resiliency to network indicators. What are some distinct areas of code or configuration data that can be targeted by network signatures?

Because the malware leveraged custom, yet simple encoding mechanisms, static, yet configurable domain names, User-Agent errors, and a few other static elements such as commands being sent via the C2, we can use all of this to create specific snort rules to identify this malware. As we are focussing on network signatures, we can target the initial beacon of the malware and subsequent commands sent down via the web-based C2.

Question 9

What set of signatures should be used for this malware?

Expanding on the above, we can split this section into identifying the initial beacon, and then the subsequent C2 commands before testing our rules.

Beacon:

We gathered up the static elements of this beacon in question 1. The specific elements are highlighted below.

• Accept-Language
• UA-CPU
• User-Agent
• Accept
• Accept-Encoding

Because we can specify the C2 with autobat.exe, we can modify this to point to our own system. Given we’ve already defined ‘CYBERAIJU’ to point to one of our controlled hosts, let’s continue to use this, and create a Snort rule based on all the hardcoded elements of this beacon.

If we wanted to limit this to one hardcoded element over another it would be trivial to do; however for the purpose of thoroughly identifying every static element of this beacon for a high confidence hit, we have added all to our Snort rule.

Side Note: Given header elements stretch over many lines the hex ‘0D 0A’ needs to be used to signal a new line feed, and many other special characters will need to be converted to hex.

alert tcp $HOME_NET any -> any$HTTP_PORTS (msg:"PMA Lab14-03 Duplicate User-Agent and known hardcoded headers"; flow:to_server; content:"Accept|3A 20|*/*|0D 0A|Accept-Language|3A 20|en-US|0D 0A|UA-CPU|3A 20|x86|0D 0A|Accept-Encoding|3A 20|gzip|2C 20|deflate|0D 0A|User-Agent|3A 20|User-Agent|3A 20|Mozilla/4.0|20|(compatible|3B 20|MSIE|20|7.0|3B 20|Windows|20|NT|20|5.1|3B 20|.NET|20|CLR|20|3.0.4506.2152|3B 20|.NET|20|CLR|20|3.5.30729)"; http_header; classtype:trojan-activity; sid:1337352; rev:1;)


The end result is a thorough Snort rule which identifies this malware beacon

Command Generic:

To test any Snort created rules we will need to simulate a command being sent from the initial beacon. To do this we can use the same netcat listeners as previous, and simply respond with content we know will be contained in a web response as a command. As a start we know the general syntax of a command being sent.

<noscript><DYNAMICCONTENT>http://www.practicalmalwareanalysis.com/<COMMAND>/<ARG>96'


The consistent elements in this response include “

alert tcp $HOME_NET any ->$HOME_NET any (msg:"PMA Lab14-03 C2 based on noscript tag and 96'"; content:"<noscript>"; content:"http|3A 2F 2F|"; distance:0; within:1024; content:"96'"; distance:0; within:1024; classtype:trojan-activity; sid:1337352; rev:1;)


Testing in the same way as before, we can respond to the netcat command by sending a test payload.

The end result is our rule being hit.

It should be noted that in the above we have used a command of ‘Security’. One would assume because this starts with ‘s’ that the malware will sleep; however, the character is case-sensitive which we will need to keep in mind for the coming rules aimed at detecting each command sent.

Command d or r:

Given our knowledge of the encoding algorithm used, we can create a robust signature which looks for any command beginning with ‘d’ or ‘r’. We know that either of these commands must be followed by an encoded URL. Because the URL encoding uses a number mapping to a string previously identified:

/abcdefghijklmnopqrstuvwxyz0123456789:.


Because every URL is expected to be specified via ‘http://’ We simply need to determine what the encoded number value of ‘http://’ would be. This used 2 bytes for each number, so starting with ‘00’ this would look like the below given each character mentioned above simply increments the number value by 1.

http://
08202016370000


An end result would look like either of the below which could be used to trigger the malware with an ‘d’ or ‘r’ command being run.

<noscript>sefgdgesgfhttp://CYBERAIJU/doctor/082020163700004123496'
<noscript>sefgdgesgfhttp://CYBERAIJU/real/082020163700004123496'


Turning this into a Snort rule we could use something like the below.

alert tcp $HOME_NET$HTTP_PORTS -> $HOME_NET any (msg:"PMA Lab14-03 C2 d or r command ran"; content:"|2F|08202016370000"; pcre:"/\/[dr][^\/]*\/08202016370000/"; classtype:trojan-activity; sid:1337353; rev:1;)  The end result is our rule being hit after testing as we did above. Command s: The final piece of our puzzle is to trigger if a command is sent to sleep. Much like the above we could use something like the below. <noscript>sefgdgesgfhttp://CYBERAIJU/security/20096'  To get this we will focus on the ‘s’ character followed by any number of numbers between 0 and 20 characters long, closed by our signature 96’ alert tcp$HOME_NET $HTTP_PORTS ->$HOME_NET any (msg:"PMA Lab14-03 C2 sleep command ran"; content:"96'"; pcre:"/\/[s][^\/]*\/[0-9]{0,20}/"; classtype:trojan-activity; sid:1337354; rev:1;)


The end result is our rule being hit after testing as we did above.

This concludes chapter 14.

Chapter 15. Anti-Disassembly

There are 2 types of disassembler algorithms.

• Linear disassembly: Widely used. Iterates over blocks of code one instruction at a time in a linear fashion. Uses size of disassembled instruction to determine next byte to disassemble. No regard for control flow instructions and unable to determine the difference between code and data.
• Flow-oriented disassembly: Used more commonly in commercial disassemblers. Examines each instruction and uses that to build a list of locations to disassemble. Generally prevents data from being interpreted as code.

Disassemblers generally process the “False” branch of a conditional jump first which can be abused much to their detriment when there’s conflicting code with the “True” branch that gets ignored. Relevant opcodes of interest include E9 (5-byte jmp) and E8 (5-byte call). If these are disassembled it can lead to 4-bytes being hidden from view. We can use ‘D’ and ‘C’ in IDA to transform components from ‘Data’ to ‘Code’ and vice versa.

Anti-Disassembly Techniques:

• Jump with same target: Most common anti-disassembly technique and is made up of multiple conditional jump instructions pointing to the same location. Cross-references in red may indicate anti-disassembly is being used.
• Jump with constant condition: Common anti-disassembly technique and is made up of a single conditional jump where the condition is always the same.
• Impossible disassembly: Occurs when a ‘rogue byte’ e.g. E9/E8 mentioned above is required and executed at runtime and can’t be ignored e.g. the byte is used by multiple instructions. An example is where ‘FF’ could be part of a jmp, but also part of the following operation e.g. inc eax, and the disassembler is unable to show this as both a jmp, and the inc operation. Only real way to resolve is to patch with ‘NOP’ operations, or convert to data.

NOP Out Instructions in IDA:

Note: This is taken directly from the PMA material. It adds a hotkey to allow converting an instruction to a ‘NOP’ at the current cursor location.

import idaapi
idaapi.CompileLine('static n_key() { RunPythonStatement("nopIt()"); }')
def nopIt():

start = ScreenEA()
for ea in range(start, end):
PatchByte(ea, 0x90)
Jump(end)
Refresh()


Obscure Flow Control:

• Function Pointer Issues: By using function pointers in hand-written assembly or crafted in a nonsensical manner, it can make analysis difficult by preventing decompilers such as IDA from showing all the correct cross-references to a particular function. This can also remove function argument names which would otherwise be present.

We can manually add comments containing function arguments if required; however, to add missing cross-references, we need to leverage IDC (AddCodeXref) or IDAPython. Example executions are shown below where fl_JF is a jump instruction, and fl_CF is a call instruction as flow types.

AddCodeXref(0x004011DE, 0x004011C0, fl_CF);

• Return Pointer Issues: This is generally ret or retn. Functions like a jmp, except return pointer is pushed to stack. Generally used to return from a function call, but can be abused elsewhere to just pop a value from the top of the stack and jump to it.
• Structured Exception Handlers: Method of flow control when errors occur. Manually generated errors and custom handlers (on the top of the SEH chain, generally appears as accessing ‘large fs:0’) can fool debuggers and disassemblers. SEH chain found by examining FS segment register to gain access to Thread Environment Block (TEB). To do this the binary needs to be compiled with Software Data Execution Prevention (DEP or SafeSEH) disabled.

Defeating Stack-Frame Analysis:

• When abused by a malware author, this can prevent certain useful components such as the decompiler plugin, as this relies on having knowledge about the stack frame. Can use CTRL + K to view stack frame in IDA and ALT + K to adjust the stack pointer.

Lab 15-01

Analyze the sample found in the file Lab15-01.exe. This is a command-line program that takes an argument and prints “Good Job!” if the argument matches a secret code.

Question 1

What anti-disassembly technique is used in this binary?

By opening the binary in IDA we can immediately see some sort of anti-disassembly has been used due to all the data being marked as text, and calls to non-existant functions.

Using ‘Options -> General’ we’re able to set the number of opcode bytes we want to see, and in this case setting it to ‘4’ provides us some more information on what is going on.

In the above we can see 4 instances where an XOR operation has been run for eax and eax (the end result is the return value ‘0’), right before a jump statement occurs if the zero flag is returned (jz). Because of this the return is always true; however, the ‘false’ statement is evaluated by the disassembler first. It’s this false conditional branch use which has caused the disassembly issue.

Question 2

What rogue opcode is the disassembly tricked into disassembling?

The rogue opcode in the disassembly is 0xE8 which makes the disassembler believe the following data is made up of 5-bytes for the call instruction, thus hiding the remaining bytes proceeding this from our view.

Question 3

How many times is this technique used?

To get an idea how many times this technique is used we can take a quick glance at how many operations attempt to jump to a new location near a pointer + an offset.

This leads us to believe it has been used 5 times. To confirm this assumption, we can begin reassembling this into the code it should be. Starting out we can turn the instruction at ‘00401010’ into data, using ‘D’.

From here we can see that too many op codes have been converted to data, so we begin converting anything besides the rogue 0xE8 back into code using ‘C’. Once completed this reveals our second false conditional branch.

Repeating this process for every rogue instance of 0xE8, we can begin to gain visibility into what was previously unknown to us, and the program begins to look more like a properly disassembled program.

This confirms that the technique was used 5 times.

Question 4

What command-line argument will cause the program to print “Good Job!”?

By highlighting the above sections from ‘main’ to ‘ret’ we can have IDA turn this code into a function by pressing ‘P’. At this point we can now view this in the alternative IDA view.

This now reveals 2 possible outcomes for comparisons that take place, one where your parent “is disappoint” - sneaky 4chan meme, and one where you’ve done a good job. At this point it is trivial to convert the hex comparisons to their character constances by using ‘r’.

Taking a look at the above we have found that by passing ‘pdq’ to the program as an argument, all the checks pass and it prints “Good Job!”.

Lab 15-02

Analyze the malware found in the file Lab15-02.exe. Correct all anti-disassembly countermeasures before analyzing the binary in order to answer the questions.

Question 1

What URL is initially requested by the program?

If we open this in IDA and run the program, we can see that it immediately displays the message “not enough name” and exits.

Examining the data in IDA it hasn’t neatly disassembled, and it appears that anti-disassembly techniques have been used. To locate the URL initially requested by the program we need to ensure it is properly disassembled so we read down the code looking for any known antidisassembly techniques which have a ‘E9’ or ‘E8’ operation and look to be calling an invalid function. This initially reveals an entry at 0040115E.

This is testing if ESP = ESP, and if so it’ll have a non-zero flag set. If it has a not zero flag set it will jump, yet our disassembler has trusted the false condition of this statement. As with the previous instance we’ve found a false conditional branch used in anti-disassembly, so we convert this rogue op-code into data, and the surrounding elements into code. Continuing on we see our next instance at 004011D4 which takes a jump if a zero flag is set.

In this instance the operation proceeding it is a XOR operation which will always make EAX 0. So we repeat the process of turning this into data/code as required. Continuing on we see an interesting entry at 00401215.

What’s interesting here is that the location of the jump happens to be the second byte inside of itself indicated by the samer location it is run from +1. By converting this into data and cleaning up surrounding code we can see that this is immediately followed by something that doesn’t quite look right.

To fix this, we will first need to enable the ‘Patch’ submenu in IDA (by editing idagui.cfg under cfg), and reopen it.

Now under the rogue byte (EB), we can use Edit > Patch program to change this to 90.

If we now turn this into code we find another technique has been used at 0040126D.

In this instance we see the proceeding comparisons ‘jz’ and ‘jnz’ are jumping with the same target, and as these are 2 different conditionals one after another, we can see another anti-disassembly technique has been used. By converting this to data, and then the surrounding elements to code, we can see more of the assembly, and more evidence of anti-disassembly techniques being used at 0040126D.

What we encounter here is an instance of impossible disassembly, where the rogue op-code at 4012EC is used both in the legitimate program execution, and for the sake of performing a call which isn’t required. By converting areas around this to data and code like previous, and following the assembly logically to ensure it makes sense, we wind up with something more like the below.

At this point there are no jumps to invalid locations, and we have what looks like it may be a valid function. To make sure this works we’re going to first patch the rogue bytes we have laying around (the ones shown in between 2 lines similar to ‘db 0E8h’, ‘db 0E9h’ etc, with 0x90 (NOP) so that they’re effectively just passed over. So no mistakes are made, the entries at 004012E6 (db 66h) and 004012E7 (db 0B8h) must not be patched, and must stay as data given they are still used. After highlighting this and using ‘P’ again to convert it to a function we see something which resembles valid assembly.

If the wrong bytes have been nop’d out, you’ll wind up with some broken process flows (instructions which don’t tie directly to the main class or have cross references), and may need to work through it again to ensure it’s been done correctly. For the purpose of this question we need to take a look at sub_401386. Inside this function we find what looks to be a string building operation.

By using ‘R” to turn these characters to their ASCII equivalent, we find that this builds the string ‘http://www.practicalmalwareanalysis.com/bamboo.html’

This makes up the URL initially requested by the program. We can confirm this by examining cross-references to sub_401386 to find it is called to establish the URL parameter passed to ‘InternetOpenURLA’.

Question 2

How is the User-Agent generated?

To determine how the User-Agent is generated, we need to find out where it is defined before the call to InternetOpenA. If we look slightly above we can see that the hostname appears to be assigned as the User-Agent.

What’s interesting though is that if we examine the graph overview we can see what looks to be a loop and operations occurring on the User-Agent. To understand how the User-Agent is generated, we need to understand what is happening here. First off ‘[ebp+var_2A0]’ is set to 0 before the looping function occurs. The looping function has various elements to it.

• First it will check if it has looped more than 256 times by checking the value of [ebp+var_2A0], if it has, it will initiate opening URL.
• Next it will run a check which will cause it to always jump to ‘loc_4010B5’. This is leftover from our anti-disassembly binary reassembling.
• Next it will check if the value of the User-Agent character specified by [ebp+var_2A0] (e.g. 0 = 1st character, 1 = 2nd etc) is equivalent to ‘90’ (‘Z’ in decimal). If it is it will set the value to ‘A’.
• If the above value isn’t ‘90’ (Z), it will check to see if it is 122 (‘z’ in decimal, notice the case change). If it is it will set the value to ‘a’.
• If the above value isn’t ‘122’ (z), it will check to see if it is equivalent to the number 9. If it is it will set the value to ‘0’.
• Finally if the above value isn’t ‘9’, it will add 1 to the character value.

This then increases [ebp+var_2A0] by 1 and the loop goes again. What the above is basically doing is performing a character rotation (rot1) operation on the hostname. The checks ensure that rotations don’t lead to an invalud decimal character and ensure that once it gets to the end value it will return to the start.

Based on this we know that the User-Agent is created by taking the hostname and shifting all the characters by 1 (rot1 operation).

Question 3

What does the program look for in the page it initially requests?

If we examine the operations after the page has been read, we can see that this program searches for the first occurrence of the string “Bamboo::”.

Question 4

What does the program do with the information it extracts from the page?

Based on the string “Bamboo::” being found, the program searches for the string “::”. It then calls a subroutine at sub_40130F, before reading the bytes inbetween “Bamboo::” and “::” into a buffer.

The subroutine at sub_40130F looks to be another string building operation once we use ‘R’ to convert to associated characters once more.

This shows us that [ebp+lpFile] is being assigned to the value ‘Account Summary.xls.exe’. Looking further to where this is used, we can see that this is the name of a file which will be written by the program based on the bytes read in between “Bamboo::” and “::”.

Of interest is that we see what looks to be a broken tree whereby nothing happens after the file is written. If we examine this closely this is because of the impossible disassembly operation we encountered during analysis. What we can infer though is that this is supposed to then execute the file written to disk. Based on this we know that the program is a downloader and launcher designed to drop a file with double extensions and execute it.

Lab 15-03

Analyze the malware found in the file Lab15-03.exe. At first glance, this binary appears to be a legitimate tool, but it actually contains more functionality than advertised.

Question 1

How is the malicious code initially called?

To get an idea of what this does we can run it using Fakenet-NG to track any network connections. If we do we see some rapid text through our terminal which appears to be showing process lists; however, at the end we see an outbound connection.

For a process listing tool this looks suspicious, so we open this up in IDA for further investigation. After disassembling completes we see evidence of ‘URLDownloadToFileA’ being imported and used, which backs up what we saw with dynamic analysis; however, this doesn’t appear to be legitimately used based on how the disassembler has interpreted the data.

This raises even more suspicions, particularly that this program may be using anti-disassembly techniques. By examining the very beginning of the main function we can see modification of ebp+4 which in itself is suspicious given ebp+4 is the return address. We can use CTRL + K to view the stack frame associated with this.

The operations store 0x0040148C in ebp+4 (the return address). By examining 0x0040148C we find what looks to be code which hasn’t disassembled and uses some known anti-disassembly techniques.

By converting isolating the rogue byte into data and converting back into code, we see a suspicious element which looks to be dividing by zero.

This will cause an error and the resulting text after it to never be displayed which leads us to believe this is part of a red herring. At this stage we’re pretty confident that this is indeed code which is initially called by overwriting the return address stored on the stack to cause different process execution after the main method completes execution.

Question 2

What does the malicious code do?

Following on from where we left off in the above question, we can see a reference to 004014C0 from loc_401497, yet no call instructions. This leads us to believe that the resulting divide by 0 error will be handled by a handler here which has been mistakingly interpreted as data.

By converting this to code, we find another anti-disassembly attempt at 004014D7.

By isolation the rogue ‘EB’ byte, and converting this to code, we begin to see what looks far more promising, a call to URLDownloadToFileA before more anti-disassembly, and a call to WinExec.

By once again isolating the rogue byte and converting the surrounding text to code we can see a proper function now seems to be present.

At this point we can be pretty sure that the malicious code will download a file from a remote URL and execute it with winexec.

Question 3

What URL does the malware use?

This is easily answered through dynamic analysis (using Fakenet-NG) like we did in Question 1. To properly find out how this is built we need to examine a newly created function from our disassembled code (even if their trees are now a bit mangled).

Of interest is a couple of calls to sub_401534, prior to 2 random strings being pushed and a call to URLDownloadToFileA. By examining sub_401534 we find what looks to be a simple XOR decoding function using the value 0xFF.

Taking the gibberish data at byte_403010.

If we decoding the hex values specified and perform a XOR operation using our identified key, we find the URL we initially identified.

Question 4

What filename does the malware use?

To locate the filename used by the malware, all we need to do is repeat the above decode and XOR operation; however, in this case we are looking at the value specified in CmdLine.

From this we get the filename used by the malware as ‘spoolsrv.exe’.

This concludes chapter 15.

Chapter 16. Anti-Debugging

Windows API: Most obvious technique

• IsDebuggerPresent: Most simple, searches Process Environment Block (PEB) for the field ‘IsDebugged’.
• CheckRemoteDebuggerPresent: Almost identical to ‘IsDebuggerPresent’. Takes a handle to a process, and will check PEB for if debugger is present on local machine.
• NtQueryInformationProcess: Takes a handle to a process, and the information to be retrieved, and retrieves this from a process. Can use ‘ProcessDebugPort’ (0x7) to check if being debugged.
• OutputDebugString: Sends string to a debugger. Can use an if statement in tandem to run malware if this doesn’t return an error to check if being debugged.

Mitigations:

• Hook API calls.
• Modify code to not call APIs.
• Modify checks to jump to the intended path in all instances.

Manually Checking Structures: Most common technique

PEB of process is at fs:[30h]

• BeingDebugged Flag: Can be checked by comparing the value of fs:[30h] + Offset of 2 to determine in the PEB of a process if ‘BeingDebugged’ is set or not.
• ProcessHeap Flag: Can be checked by first comparing the value of fs:[30h] + Offset of 0x18 to get the ‘ProcessHeap’, and then comparing an offset of 0x10 within the ‘ProcessHeap’ (Windows XP) to find the ‘ForceFlags’ field. In Windows 7 (32-bit binaries) this is at 0x44. We can also check an offset of 0x0C (Windows XP) or 0x40 (Windows 7) to find the ‘Flags’ field.
• NTGlobalFlag: Can be checked by first comparing the value of fs:[30h] + Offset of 0x68 to the value 0x70 to determine if the heap combination indicates a debugger is set.
• System Residue: Can check system for artefacts a known debugger is installed, e.g. registry keys of installed software, files/directories, processes running etc.

Mitigations:

• Most popular OllyDbg plug-ins at the time of PMA publishing include ‘Hide Debugger’, ‘Hidedebug’, and ‘PhantOm’. Many seem to now be deprecated or superseded.
• The most popular free Ant-Anti-Debug library (Ring 3) at the time of this post is ScyllaHide.
• The most popular free Anti-Anti-Debug driver (Ring 0) at the time of this post is TitanHide.
• Debuggers can be started with the debug heap disabled. For example the following using windbg: windbg –hd .exe
• Modify comparison checks to jump to the intended path in all instances.

Identifying Debugger Behavior:

• INT Scanning: INT 3 (0xCC) is commonly used to set a break via a debugger, INT can also be used (0xCD). Malware can scan its own code for these (e.g. 0xCC) to find software break points.
• Code Checksums: By verifying the malware’s own code integrity (e.g. via a CRC or checksum of opcodes), malware can determine if software break points may be present or their code has been tampered with.
• Timing Checks: One of the most popular techniques. Uses delay in time between operations to infer a debugger is present.
• rdtsc Instruction: Most common. Uses opcode 0x0F31 (returns tick count) at least twice. Where the difference is > than X amount it will not run the intended code.
• QueryPerformanceCounter and GetTickCount: Similar to the above but uses Windows APIs.

Mitigations:

• Use hardware break points.
• Create break points after timing checks and step over them.
• Modify comparison checks to jump to the intended path in all instances.

Interfering with Debuggers:

• Using TLS Callbacks: TLS Callbacks (Thread Local Storage Callbacks) run before the programs first instruction so are often missed by debuggers. Programs implementing this generally have a .tls section in the header and most normal programs don’t use this. Can be mitigated by setting debuggers to break at System, break-points (e.g. Options > Debugging Options > Events) or TLS callbacks.
• Using Exceptions: By detecting if an exception is passed back to the program running, the program can infer if a debugger is being used. Can be mitigated by setting a debugger to pass exceptions back to the running process (e.g. Options > Debugging > Options > Exceptions).
• Inserting Interrupts: USed to slow down, disrupt, or annoy an analyst by inserting software breaks interpreted by debuggers.
• INT 3: Emulates a software break by inserting 0xCC or 0xCD03 (used to advance EIP by 1-byte when debugged using WinDbg).
• INT 2D: Similar to INT 3, but uses 0x2D to instead emulate a kernel debugger.
• ICE: Undocumented In-Circuit Emulator (0xF1). Generates a single-step exception. Can be mitigated by not single-stepping over an icebp (0xF1) instruction.

Debugger Vulnerabilities:

• PE Header Vulnerabilities: By modifying certain PE Headers to a number greater than the max value possible, certain debuggers will follow this and cause the program execution to crash, whereas under normal running conditions, the OS would ignore anything outside of the max values. Some fields include NumberOfRvaAndSizes (Max 0x10), SizeOfRawData (Max size is generally only that of VirtualSize given the smaller is mapped to memory, and OllyDbg only uses SizeOfRawData. If specifying more than the size available, it will crash). This can be mitigated by setting the SizeOfRawData close to that of VirtualSize.
• OutputDebugString Vulnerability: OllyDbg 1.1 has an OutputDebugString vulnerability (like many of the other vulnerabilities mentioned), where a string of “%s” as a parameter to OutputDebugString can cause it to crash. Mitigations include using version 2.0 of OllyDbg.

Lab 16-01

Analyze the malware found in Lab16-01.exe using a debugger. This is the same malware as Lab09-01.exe, with added anti-debugging techniques.

Question 1

Which anti-debugging techniques does this malware employ?

Given this incorporates anti-debugging techniques a good place to start is with a disassembler rather than a debugger. At first glance we can see a number of different jumps and conditional flows by viewing the graph overview.

Drilling into the conditions surrounding the main method we can see a number of comparisons after an moving instances of ‘fs:30h’ into EAX, in addition to calls to ‘sub_401000’ where an expected condition isn’t met.

If we examine sub_401000 closely we can see that it is designed to delete the calling binary, indicating not only that this is using some sort of anti-debugging technique, but also that when it identifies it is being debugged, it tries to delete itself.

Drilling into all of the comparisons which use reference to “fs:[30h]” (The Process Execution Block) of the process running, we can see a number of comparisons checking if the ‘BeingDebugged’, ‘ProcessHeap’ or ‘NTGlobalFlag’ have been set.

We can confirm what we’ve said by looking at the documentation around PEB structures, noting that some elements are undocumented.

Question 2

What happens when each anti-debugging technique succeeds?

As mentioned in the above analysis, if at any point the anti-debugging techniques succeed sub_401000 will be run which attempts to delete itself and terminate the program.

Question 3

How can you get around these anti-debugging techniques?

There’s a few different ways to get around these anti-debugging techniques explored below.

• OllyDbg Plugin.

By far one of the easiest ways to defeat this anti-debugging technique is to use a plugin such as ScyllaHide. By getting the latest release of this and installing it into our OllyDbg2 directory (in this case we are using version 2.01).

We can now access these components via Plugins > ScyllaHide > Options and setup a profile which will hide the identified anti-debugging components from the inspected PEB.

At this point we’re in the clear and can debug the program as normal.

• Modify comparison checks to jump to the intended path in all instances.

This method is much more tedious; however, we could manually go through and patch the binary, either in memory or by modifying it’s raw hex to change all instances of anti-debugging jump conditions to be opposite.

In the above jump conditions occur using both JZ and JNZ, to make them opposite we simply change instances of ‘74’ to ‘75’ and vice versa on appropriate anti-debugging checks.

• Patch the structures using ImmunityDebugger PyCommands.

This method can also be used if we are leveraging ImmDbg (ImmunityDebugger) as our debugger of choice. It comes with a pycommand called ‘hidedebug’ which can be called to patch the appropriate PEB structure elements.

Question 4

How do you manually change the structures checked during runtime?

To manually change the PEB structures checked during runtime we can first debug the program using Ollydbg 1.10 (this gives us access to the command line plugin).

BeingDebugged:

Using the command-line plugin we can dump the contents of PEB with the below.

dump fs:[30] + 2


From here we can change the ASCII representation of what we can only assume is a face, and fill this ‘01’ part of the binary with 00’s.

At this point we’ve manually modified this part of the PEB structure to prevent checks on the ‘BeingDebugged’ flag.

ProcessHeap:

Similar to the above, this time we’re looking for 4-bytes as this is the number of flags added on the ProcessHeap, and we’re going to check at an offset of 0x10 (given this was created for Windows XP).

dump ds:[fs:[30] + 0x18] + 0x10


We can once again fill these with 00’s.

At this point we’ve successfully modified the ProcessHeap to prevent checks on the ‘ForceFlags’ field.

NTGlobalFlag:

Once again we will follow the PEB offset of 0x68 to find out whether the NTGlobalFlag is set to 0x70 or not.

dump fs:[30] + 0x68


We can see that it is, so once again we can modify this to be filled with 00’s.

At this point we have successfully modified all these structures during runtime, and if we do this when the malware is run with an appropriate command-line as analysed in Lab09-1.exe we find that it successfully runs.

Of note is that if we’d taken the route to patch the program and bypass these checks we’d be in for difficult time. This is because if we were to examine cross-references to sub_401000 where the program attempts to delete itself, we find it has 79 entries which would need to be patched.

Question 5

Which OllyDbg plug-in will protect you from the anti-debugging techniques used by this malware?

As explored previously there are a number of anti-debugging plugins available in addition to a PyCommand that can be used through Immunity Debugger including HideDebug and ScyllaHide.

Lab 16-02

Question 1

What happens when you run Lab16-02.exe from the command line?

Running Lab16-02.exe from the command line we see that it prompts us to enter a 4 character password.

Question 2

What happens when you run Lab16-02.exe and guess the command-line parameter?

If we guess the command-line parameter (and get it wrong) Labe16-02.exe reports “Incorrect password, Try again”.

Question 3

At this point it is too early to determine the command-line password. A quick glance using IDA Pro reveals a wealth of information, the first being that this pushes data to the stack prior to a string comparison taking place, and second that this is contained within a .tls section of the binary which is pretty uncommon, and probably indicates that anti-debugging techniques have been used.

At a glance it looks like the data pushed to the stack may be performing a comparison to ‘p}’ or ‘[email protected]’; however, there’s some references to 0FFH which may indicate memory registers, and the comparison doesn’t seem to add up. We also know that this is instructing a 4-character password, which although it could be a red herring, this together is enough to warrant further investigation.

Upon trying password combinations we find they don’t appear to work, so we’ll continue to investigate the binary further and return to this question later.

Question 4

Load Lab16-02.exe into IDA Pro. Where in the main function is strncmp found?

Within IDA Pro we find that the main function has ‘strncmp’ located at 0x40123A.

Question 5

What happens when you load this malware into OllyDbg using the default settings?

Opening this in OllyDbg or OllyDbg2 we find that it doesn’t hit any breakpoint upon loading and immediately terminates. To determine why we can take a look into the PE structure using PE-bear.

Question 6

What is unique about the PE structure of Lab16-02.exe?

PE-bear reveals that a .tls (Thread Local Storage) callback section is present which is intended to run before the programs main method.

Using the in-build disassembler we can also see evidence this likely contains multiple anti-debugging techniques such as ‘OutputDebugStringA’ being used, and looking for any window called ‘OLLYDBG’.

Question 7

Where is the callback located? (Hint: Use CTRL-E in IDA Pro.)

We can find where the callback is located using PE-bear by shifting to the TLS tab.

In addition we can use CTRL + E in IDA Pro to view this information and confirm.

From this we know the callback is located at 0x401060.

Question 8

Which anti-debugging technique is the program using to terminate immediately in the debugger and how can you avoid this check?

Examining the tls callback further in IDA, we can see that this performs a check for any window called ‘OLLYDBG’.

Where there are no instances of windows open with the name ‘OllyDbg’, it will continue to run the programs main method, otherwise it will terminate.

We can avoid this check by using another debugger, modifying the window class name while running in memory with a plugin, or bypass the check by setting it to be a ‘jnz’ jump instead of a ‘jz’ jump, or even just completely bypass the check by modifying it to be filled with as many 0x90 (NOP) operations as required.

Using Another Debugger:

Using Immunity Debugger we can see that this successfully bypasses these checks and pauses at the main method entry point.

Modify Window Class Name:

Using a plugin such as ScyllaHide we can easily change the Window Class Name and have this reflected as the newly running process name. Note this in itself won’t necessarily prevent this techinque. In addition we can hook NTUserFindWindowEX which is called by NTUserFindWindowA which will nullify the API call being made.

We may also need to add a break at the start of the tls callback if we’re stepping through this for the first time to see the difference in program termination due to this debugger check.

Modify Program:

By setting the break point in tls callback as shown above, we can modify this check in memory to change the JZ check to instead perform no operation and lead into the next section.

Question 9

What is the command-line password you see in the debugger after you disable the anti-debugging technique?

Setting a break point at 0x40123A (string compare operation) we can see a check against the password ‘[email protected]’; however we can also see this is only looking to check the first 4 characters.

From this we infer that the password must be ‘bzrr’; however if we restart the program using OllyDbg2 and set this as the password command-line we still see that a jump is taken at 0x401249 which doesn’t add up to what we expect.

By running this outside of a debugger we can see that the password is in-fact correct.

From this we can infer that operations within the string compare statement have a level of anti-debugging techniques within them which are altering the expected password. In this case we’ve answered question 3 and now know bzrr is the password used when this application is not being debugged.

Question 10

Does the password found in the debugger work on the command line?

In our above analysis we have found that the password shown in the debugger does work on the command line, but only if further anti-debugging techniques don’t determine that it is currently running in a debugger. To figure out what is going on we will explore what is occurring before the string compare function in more depth.

In the above we see that StartAddress is being pushed and started in a new thread, so we examine that further and find what looks to be a decoding routine.

At a glance we also see reference to the program loading the PEB structure looking for an offset of 2, which we know is the ‘BeingDebugged’ flag in addition to us realising this is located within the .tls section of the program.

When we previously debugged the program we were using ScyllaHide which had a number of anti-debugging settings enabled, including one to remove the ‘BeingDebugged’ flag if it is set. By disabling this option and running the program again we see a different password output.

With the new comparison now looking for ‘bzqr’ we can infer that this anti-debugging technique has a direct influence on the password being checked by the application. Very tricky. Had we not set the ‘BeingDebugged’ flag to 0 we would have been presented with the wrong password which doesn’t work on the command-line.

Question 11

Which anti-debugging techniques account for the different passwords in the debugger and on the command line, and how can you protect against them?

Now that we know multiple anti-debugging techniques are involved, let’s first see if we can get the program to run through a debugger and the intended password. Back in question 6 we found reference to ‘OutputDebugStringA’ within tls, so we can begin to assume this is being used at a minimum. By enabling a hook to this we can try and debug again.

The end result is that we’ve successfully bypassed all anti-debugging components and the correct password now works with a jump not being taken using the password bzrr.

To determine how this is formed to assist in the event we cannot hook OutputDebugStringA (e.g. in Windows XP with the 32-bit variant of ScyllaHide when run inside OllyDbg 1.1) we’ll finally examine the decoding routine once more. At the start we see reference to ‘byte_40A968’ which is moved into ‘bl’ and appears to be used.

If we look into this it is created with the value ‘0’; however, if we examine cross-references to this by using ‘x’, we can see it has 4, of which 2 occur ‘UP’ (before) this operation within sub_401020 which is of interest.

By examining sub_401020 we find that it makes a call to OutputDebugStringA with the string ‘b’ and an error code 0x3039. Where this is still present the program infers it is within a debugger and sets byte_40A968 to 1.

This is later used adding to a character in the decoding routine which explains why the value was one character off in our debugger results (bzqr instead of bzrr).

As a final thought: What is interesting is that these API calls and anti-debugging checks are very volatile, and given the password is based off of these calls, if they were to give a different output across operating systems, then the associated password check would be different. For example in the above we have run checks using a Windows 7 32-bit OS; however, the same binary yields different results when run on a Windows XP 32-bit OS when not run in a debugger using anti-debugging techniques, and a totally different password is required.

We can easily NOP out the operation which performs the +1 to our byte to nullify the impact of ‘OutputDebugStringA’ anti-debugging checks when using OllyDbg on a 32-bit OS with ScyllaHide.

By doing this we find that the password check is now ‘byrr’.

Failing to do this the check is still made against bzrr, indicating that the different operating systems are likely processing the checks against ‘OutputDebugStringA’ differently. Checking natively on Windows XP we find that the intended password without the OutputDebugStringA is now ‘byrr’.

This highlights the need to thoroughly examine anti-debugging features within a program to find any red-herrings and how they may operate differently on different versions of Windows. To summarise, the intended password for this on Windows XP when not operating within a debugger is ‘byrr’, with Windows 7 checks generally requiring ‘bzrr’.

Lab 16-03

Question 1

Which strings do you see when using static analysis on the binary?

Opening the program usine pestudio we can see it contains some strings related to cmd.exe which looks like it may be trying to delete something, strings associated with getting access to the current window it is running within, and reference to GetTickCount which may be used for anti-debugging.

Looking at its imports we find more API calls which lead us to believe this is supposed to make network connections, and is performing more anti-debugging techniques.

Question 2

What happens when you run this binary?

If we try and run this binary it looks like it immediately terminates with no further actions taken.

Question 3

How must you rename the sample in order for it to run properly?

If we examine the main method of this malware using IDA Pro, we can see a familiar string being pushed to the stack ‘ocl.exe’.

This was found back in Lab09-02.exe in question 3, which leads us to believe this is a copy of Lab09-02.exe which has been modified with anti-debugging techniques implemented. What we find if we rename this to ‘ocl.exe’ and attempt to run it is that nothing happens, so we need to examine the operations before the strncmp to see if any modifications are made to ‘ocl.exe’ prior to checking the binary module name. An easy way to do this is through a debugger setting a breakpoint at strncmp (0x401518); however, upon doing this and running the program, we can see we’re presented with a division by 0 error.

Using SHIFT + F9 we can pass this error back into the application we can see our break point is now comparing the string to ‘qgr.exe’.

Even if we rename the binary to this and continue to step through or run the binary again, we will soon hit another divide by 0 error, one we can’t successfully pass back to the program, and if we run Fakenet-NG we don’t see any network connections which we’re assuming this will make based on the API calls we identified.

To determine what is going on we will look at ‘sub_4011E0’ in more depth which is being passed the value ‘[ebp+var_29C]’ (ocl.exe).

What’s immediately obvious in the above is that there’s a section of code which doesn’t look to be legitimately called anywhere given no cross-references have been inferred by IDA. This leads us to believe that only an abnormal condition will cause this code to be run, and when we compare this to a call to ‘QueryPerformanceCounter’, we can begin to infer that perhaps a timing check used for anti-debugging is in play so we will investigate how this works further.

Firstly the program gets ‘[ebp+PerformanceCount]’ which contains the first output of QueryPerformanceCounter, then it will perform another check using QueryPerformanceCounter and store this in ‘[ebp+var_110]’. Now that it has two time-interval measurements, it subtracts these from one another, and then checks whether or not the result is less than 1200, and where it is a jump will occur. The overall process looks like the below, noting that whilst this is happening a divide by 0 exception looks to be thrown.

If we examine the rest of the function we find that if a jump successfully occurs (it passes this debugging check), var_118 will remain intact and is passed to what looks like a decoding or transformation routine, otherwise the value changes to ‘2’ which in essence will change the output of our decoding routine, and as such the program name which is checked by this executable.

To ensure this check is passed, we can NOP out the instruction at ‘0x401292’ that changes var_118 to a ‘2’, or modify the JLE (7E) to instead be JG (7F).

By once again running the program and passing the error to the program when it occurs, we can see that a comparison is now made against the string ‘peo.exe’

By running Fakenet-NG, renaming this binary to ‘peo.exe’, and running it we quickly see a large amount of text sprawling in Fakenet-NG indicating that a connection has gone out.

With this we know that the sample must be called ‘peo.exe’ for it to run properly.

Question 4

Which anti-debugging techniques does this malware employ?

From the above we know that this malware uses at the bare minimum timing checks using the ‘QueryPerformanceCounter’ API. To see if any more anti-debugging techniques are present, we can follow back on the main method before this makes an outbound connection.

What we can see above is that 2 calls to sub-functions are made under ‘sub_401000’ and ‘sub_401300’ prior to API calls that lookup a domain name and make a connection indicating these may be used in anti-debugging checks, so we’ll look at ‘sub_401000’ first, particularly as this is surrounded by suspicious ‘GetTickCount’ API calls which looks to be another timing check.

What we see from the above is that this performs a similar divide by 0 to the last anti-debugging check we encountered; however, what we didn’t look into before is how both of these checks first use EIP (the current instruction pointer) with an offset of ‘2C’ to reference different code to execute. It will then push this as the location for a structured exception handler which will be called when the divide by 0 executes.

Both of these are designed to cause an exception which will cause latency during debugging execution, and as such cause a different outcome to occur from the malware. In this instance the ‘GetTickCount’ is just looking for a difference of ‘1’ (millisecond), at which point it will attempt to move ‘edx’ into a location pointing to ‘0’, leading to an access exception violation that makes the program crash.

If we now look at ‘sub_401300’ we can see what appears to be a similar comparison to what we saw in question 3, only instead of ‘QueryPerformanceCounter’ being used, it is instead using ‘rdtsc’ to get 2 timestamps of interest, and then after subtracting them comparing the difference to ‘500000’. Where this is exceeded, ‘sub_4010E0’ will be called.

Examining ‘sub_4010E0’ we find that this is a deleting routine which attempts to delete the binary in question if this check fails.

Question 5

For each technique, what does the malware do if it determines it is running in a debugger?

QueryPerformanceCounter:

In question 3 we determined that the malware would modify a variable to be ‘2’ which would throw off its filename check if it detected it was being run in a debugger based on ‘QueryPerformanceCounter’ timing API checks.

GetTickCount:

In question 4 we determined that the malware would cause an access violation and crash if it detected it was running in a debugger based on ‘GetTickCount’ timing API checks.

rdtsc:

In question 4 we determined that the malware would attempt to delete and kill itself if it detected it was running in a debugger based on the ‘rdtsc’ assembly instruction to perform a timing check.

Question 6

Why are the anti-debugging techniques successful in this malware?

The anti-debugging techniques used are successful because there’s more than one used and they rely on timing differences which would only be present if the malware wasn’t able to handle errors thrown to its own structured exception handler. These timing differences become apparent when a debugger intercepts the divide by 0 errors, whereas if they ran outside of a debugger the latency generally wouldn’t be present.

Question 7

What domain name does this malware use?

From our analysis in question 4, we can NOP out the conditional jumps or the actions taken inside of these as required to ensure the malware runs as normal. Note: We can use CTRL+G to quickly navigate there through OllyDbg.

What’s easier is to instead now use dynamic analysis given we know the checks are only looking to identify the presence of a debugger and we now know the name this binary needs.

By running ApateDNS we can intercept the DNS request made when this malware is successfully run.

From this we know the domain name used by this malware is adg.malwareanalysisbook.com

This concludes chapter 16.

Chapter 17. Anti-Virtual Machine Techniques

Note: This chapter is becoming less applicable due to the increase in legitimately virtualised hosts which may be of interest to infect.

VMware Artefacts:

Malware can check for virtual machine artefacts, for example by checking if any processes or services exist containing the word “vmware”, looking for associated files, or by checking residue in the registry. This tactic expands beyond Vmware and is generally also used to identify targets which may be using a particular AntiVirus product.

• First 3 bytes of NIC MAC generally narrow down the vendor. 00:0C:29 generally signifies VMWare.

Mitigations: Patch binary on disk or binary in memory to bypass checks or uninstall VMware Tools.

• Searching through memory often finds artefacts that are difficult or impossible to remove.

Vulnerable Instructions:

• VMWare emulates via binary translation.
• Many kernel-mode instructions are hooked and emulated so they don’t run on the host physical processor.
• User-mode instructions run directly on the processor.
• Almost all instructions which interact with hardware generates a kernel trap/interrupt or is privileged and VMware processes the interrupts to simulate a real OS.
• Some x86 instructions don’t generate interrupts but access hadware-information (e.g. sidt, sgdt, sldt, cpuid), and as such to reduce performance issues VMWare allows these to execute without virtualisation. This in turn leads to discrepencies which can be monitored to detect virtualisation.

Key structures are loaded at different offsets by a processor. These include:

• Interrupt Descriptor Table (IDT): Data structure, internal to CPU. Used by OS to determine response for each interrupt or exception. IDTR = IDT Register which contains address size and tables.
• Global Descriptor Table (GDT): On x86 OS all memory accesses go via this or the LDT. Contains segment descriptors that point to each segment, such as base address, type, length, access rights etc. GDTR = GDT Register which contains address size and tables.
• Local Descriptor Table (LDT): On x86 OS all memory accesses go via this or the GDT. Contains segment descriptors that point to each segment, such as base address, type, length, access rights etc. LDTR = LDT Register which contains address size and tables.

Windows only needs to use the GDT by default. Instructions such as sidt, sgdt, amd sldt can be used to read the location of these tables, and because they’re not privileged in x86 and run without virtualisation, they can be used to infer differences between a host and guest OS to detect virtualisation.

• Using the Red Pill Anti-VM Technique: Executes sidt to get IDTR. This is 6 bytes, with the 5th byte pointing to the start of the base memory address. In this instance 0xFF is known to be the VMwaresignature.
• Note: This won’t run reliably on multi-processor machines, and as such this is not likely to be used.
• Using the No Pill Technique: sldt and sgdt Anti-VM commonly known as “No Pill”. Windows does not normally use LDT, but VMWare has support for it, so looking for a nonzero value helps determine if you’re in a VM.
• Note: This can be mitigated by disabling acceleration (VM > Settings > Processors > Disable Acceleration). At this point smsw will be used by No Pill instead.
• Querying the I/O Communication Port: One of the most popular techniques. Depends on x86 ‘in’ instruction which copies data to an I/O port. Vmware needs to load 0x5658 (VX) into the I/O destination but only when EAX contains 0x564D5868 (VMXh) as this is the magic number Vmware uses. ECX must also be loaded with a number that corresponds to an element you wish to retrieve from the port. 0xA=”Vmware version”, 0x14=”Memory size”, with 0xA being one of the more popular values to use.
• Note: We can overcome this by changing the operation to a NOP or patching the relevant jump.
• Using the str Instruction: Retrieves the segment selector from task register. This points to the task state segment (TSS) and differences exist in this when running in Vmware over a host OS.
• Note: This won’t run on multi-processor machines, and as such is not likely to be used.
• Using ScoopyNG: Tool used to detect if it is running in a VM. Performs checks for ‘Red Pill’ and ‘No Pill’ instructions, str checks, querying the I/O COM port, and checking for a known bug in older VMWare versions.

Tweaking Settings: A number of projects exist to help harden Vmware from detection such as the VmwareHardenedLoader. Some of this involves tweaking settings assigned to .vmx files, and the most common modifications to this can be found below. It should be noted that it may be much easier to patch out the binary or use different virtualisation software given the restrictions these modifications can put on your VM.

hypervisor.cpuid.v0 = "FALSE"
board-id.reflectHost = "TRUE"
hw.model.reflectHost = "TRUE"
serialNumber.reflectHost = "TRUE"
smbios.reflectHost = "TRUE"
SMBIOS.noOEMStrings = "TRUE"
isolation.tools.getPtrLocation.disable = "TRUE"
isolation.tools.setPtrLocation.disable = "TRUE"
isolation.tools.setVersion.disable = "TRUE"
isolation.tools.getVersion.disable = "TRUE"
monitor_control.disable_directexec = "TRUE"
monitor_control.disable_chksimd = "TRUE"
monitor_control.disable_ntreloc = "TRUE"
monitor_control.disable_selfmod = "TRUE"
monitor_control.disable_reloc = "TRUE"
monitor_control.disable_btinout = "TRUE"
monitor_control.disable_btmemspace = "TRUE"
monitor_control.disable_btpriv = "TRUE"
monitor_control.disable_btseg = "TRUE"
monitor_control.restrict_backdoor = "TRUE"


Escaping the Virtual Machine: Lots of vulnerabilities have been found in VMware Tools, and VMWare’s shared folder functionality. Although these get patched once they become known, given the history of vulnerabilities present, disabling these features and finding alternatives such as temporarily mounting a USB, or using 3rd party software remote admin tools may be safer in the long run. As always if you’re running malware and you’re unsure of its capabilities, it’s safer to ensure these are being run in a virtual machine on a non-critical host OS, particularly if the host OS is running a different operating system to the VM.

Lab 17-01

Analyze the malware found in Lab17-01.exe inside VMware. This is the same malware as Lab07-01.exe, with added Anti-VMware techniques. The Anti-VM techniques found in this lab may not work in your environment.

Question 1

What Anti-VM techniques does this malware use?

As this sample comes with a file called findAntiVM.py, we can take a look into this to see what it is doing as a start.

At a glance we can see it is getting any references to any of the following 7 mneumonic assembly commands:

• sidt
• sgdt
• sldt
• smsw
• str
• in
• cpuid

If we were using the commercial version of IDA Pro we could run this using File > Script File to run this script; however, as we’re doing this freely, we’ll need to do this using multiple text searches for each mneumonic (ALT+T). This reveals 3 entries of interest.

SIDT:

STR:

SLDT:

From this we can infer that this is using vulnerable x86 instructions to detect if it is in a VM. We will examine how this works in the following questions.

Question 2

If you have the commercial version of IDA Pro, run the IDA Python script from Listing 17-4 in Chapter 17 (provided here as findAntiVM.py). What does it find?

Although we don’t have the commercial version of IDA Pro, we can create a similar script for Ghidra (we touched on this tool back in Lab13 when using FindCrypt), and use this to find the banned instructions. A script which does this has been created and included below.

#Find Anti-VM instruction addresses.
#@author: Jai Minton (@CyberRaiju)
#@category _NEW_

print "Searching for Anti-VM instructions..."
AntiVM = (["SIDT","SGDT","SLDT","SMSW","STR","IN","CPUID"])

instruction = getFirstInstruction()
while instruction is not None:
for i in AntiVM:
if instruction.getMnemonicString() == i:
print "Potential Anti-VM Instruction:%s found at %s" % (instruction.getMnemonicString(),instruction.getAddress())
instruction = getInstructionAfter(instruction)
print


By adding this to a directory of usable Ghidra scripts, we can run it across our decompiled binary and get a list of the 3 instructions we previously identified.

Question 3

What happens when each Anti-VM technique succeeds?

Examining the instructions we identified in question 2, we find the following:

SIDT - Red Pill Technique:

The SIDT instruction occurs at 0x4011B5 if no Mutex exists with the name ‘HGL345’. This takes the Interrupt Descriptor Table (6 bytes) and takes the 2 least significant bytes off of this using an offset of 0x2. To get to an offset of 0x5 (where the Vmware signature FF starts), the malware then shifts 18h (24) bits to the right, and as we know there’s 8 bits in a byte, this means it shifts another 3 bytes taking us to an offset of 0x5 prior to comparing the value 0xFF.

Where this Anti-VM check succeeds, the malware will call ‘sub_401000’ which we can see attempts to end the process and remove it from disk.

STR:

The STR instruction occurs at 0x401204 if the previous check passes. This takes the Task State Segment and loads it into var_418. This then checks if the first byte returned is ‘0’, if this is the case a second check will occur to see if the second byte is 0x40.

Where this Anti-VM check succeeds, the malware will reach ‘loc_401336’ which will inevitably call ‘sub_401000’ again.

SLDT - No Pill Technique:

The SLDT instruction occurs at 0x401121 if the previous check passes. This is stored in an earlier offset as this check occurs within sub_401100 which is called at 0x4012D1 after Malservice is created.

Examining sub_401100 we find that the value 0x0DDCCBBAA is assigned to EAX which is then stored at ‘[ebp+var_8]’ (this value is purely used fo initialisation and is never seen again). The SLDT operation then occurs with the output falling into this location of memory. This output is then stored into ‘[ebp+var_C]’, and then EAX, which is returned from this subroutine.

If we go back to what calls sub_401100 we can see that a check is made against the value ‘0x0DDCC0000’, where this is not the case a jump will occur which inevitably causes the malware to terminate, otherwise this will create a new thread of ‘StartAddress’ over and over again in a loop, which is the same as we saw in Lab07-01.exe functioning as a Denial of Service catalyst.

Question 4

Which of these Anti-VM techniques work against your virtual machine?

Firing up VMware Workstation (in this instance it will be our 32-bit Windows XP machine), we can run this in OllyDbg and place break points (F2) at the below locations we identified a check was being made, in addition to placing a breakpoint at the conditional jump which occurs directly after these checks are made.

• 0x4011B5 (SIDT - Red Pill Technique)
• 0x401204 (STR)
• 0x401121 (SLDT - No Pill Technique)

This will look similar to the following for each address.

If we then run the program with ‘F9’ until we reach our comparisons we can see the following:

• 0x4011B5 (SIDT - Red Pill Technique)

This instruction has resulted in a comparison against the decimal value 128 instead of 255.

Based on this the Anti-VM check failed, likely due to multi-processors being in use.

• 0x401204 (STR)

This instruction has resulted in the first byte being returned with a value which isn’t 0, and as such no further Anti-VM checks occur.

Based on this the Anti-VM check failed, once again because this won’t run on multi-processor machines.

• 0x401121 (SLDT - No Pill Technique)

This instruction has resulted in a comparison against the expected value 0x0DDCC0000.

Based on this the Anti-VM check failed, likely due to hardware acceleration not being enabled in this version of Vmware Workstation.

Question 5

Why does each Anti-VM technique work or fail?

From the above analysis we have adequately described why each Anti-VM technique either worked or failed.

Question 6

How could you disable these Anti-VM techniques and get the malware to run?

The easiest way to disable these Anti-VM techniques is to ‘NOP’ out the associated instructions to ensure only the required jumps are taken, or modify the jump flags via a debugger.

Lab 17-02

Analyze the malware found in the file Lab17-02.dll inside VMware. After answering the first question in this lab, try to run the installation exports using rundll32.exe and monitor them with a tool like procmon. The following is an example command line for executing the DLL:

rundll32.exe Lab17-02.dll,InstallRT (or InstallSA/InstallSB)


Question 1

What are the exports for this DLL?

Opening this up in peview we can find it has 9 exported functions.

• InstallRT
• InstallSA
• InstallSB
• PSLIST
• ServiceMain
• StartEXS
• UninstallRT
• UninstallSA
• UninstallSB

Examining the imports reveals a significant amount of imported functions.

Question 2

What happens after the attempted installation using rundll32.exe?

First we can run procmon to keep track of what is happening on the OS and add in some filters such as the below:

Next we will create a backup of the file, just in case. If we then attempt to install this in our Windows XP VM (Vmware) by using the below command line:

rundll32.exe Lab17-02.dll,InstallRT


We find that this creates 2 files of interest before deleting one of them, and deleting the DLL.

• vmselfdel.bat
• xinstall.log

Because the deletion occured from cmd.exe after a .bat file was written, we can infer that deletion was caused by the vmselfdel.bat file. By viewing the cmd.exe command-line we can validate this hypothesis.

Question 3

Which files are created and what do they contain?

Examining xinstall.log still on disk we can see that it contains what looks to be a log of the malware identifying it is being run in a VM, and cancelling the malware installation.

To view the contents of vmselfdel.bat we can first identify where this file is written to disk by examining the program in IDA. Starting at the exported function we just ran ‘InstallRT’, we can see that this looks to write xinstall.log at ‘sub_10003592’, and then calls another function at ‘sub_10005567’.

Examining ‘sub_10005567’ we can see what looks to be the creation of a file named ‘vmselfdel.bat’ in addition to the content which will be written to it before execution.

If we run this again in a debugger such as OllyDbg2 and create a breakpoint after the file creation e.g. at 0x1000563B:

We can then call the relevant export using ALT + F6 which will then hit our breakpoint.

At this point we can now examine the file vmselfdel.bat.

Taking a look at the file we can see that it first turns ‘echo’ off so that nothing will be shown in a command prompt. Next it defines a function called ‘selfkill’. This function attempts to remove all attributes from the DLL which may prevent it from being removed prior to attempting to delete the file. Finally it checks if the file exists, and if it does it attempts to run ‘selfkill’ prior to attempting to delete itself which is exactly the behaviour we saw during dynamic analysis.

Question 4

What method of Anti-VM is in use?

Looking back at this DLL using IDA we can revisit the exported function ‘InstallRT’ to examine a check within ‘sub_10006196’ which occurs just before the ‘Found Virtual Machine’ file is written to disk. If we check cross-references to this we can see it is called by all installation exports which gives us a good idea that it may be related to this Anti-VM check.

Examining this we can see 2 process flows which is due to a custom exception handler being created before some unusual checks are made.

By converting some of these to their ascii character constants (using ‘R’), we get a slightly different picture.

From the above we see that there’s an operation ‘IN’ which occurs over the data register ‘dx’ (used for I/O operations, in this case it is ‘VX’) to ‘eax’ (VMXh). The ‘IN’ x86 instruction is essentially looking for input from the I/O port ‘VX’ (this is used by Vmware), and where this is found it is ensuring the magic number for Vmware is present. This is taking an instruction of 0xA which is asking to retrieve the Vmware version from this I/O virtual port.

Based on this comparison the result is returned to ‘al’ before the function returning.

Looking back at the ‘InstallRT’ exported function we can see that a ‘TEST’ is performed against ‘al’ which will set the zero-flag (ZF) to ‘1’ if al is equivalent to 0, otherwise if it contains output it knows it is running in a VM, and the malware doesn’t take the jump.

Question 5

How could you force the malware to install during runtime?

To force the malware to install during runtime we can modify the ‘jz’ jump flag at 0x1000D86E to instead be ‘jnz’, or alternatively patch the ‘IN’ instruction at 0x100061DB with NOP instructions to bypass the check like we’ve done previously.

Question 6

How could you permanently disable the Anti-VM technique?

If we re-examine ‘InstallRT’ at 0x1000D847 we can see there’s a conditional jump prior to the Anti-VM techniques which leverages ‘off_10019034’. This is the same in all the exported functions.

If we examine the above closely we can see the string “[This is DVM]5” is stored at ‘off_10019034’ with 0xD (13) being added to this pointer. This in turn moves the pointer past “[This is DVM]” and onto ‘5’ which is then converted to a number and compared to the value ‘0’ (the test instruction will cause a jump to occur if the value is 0).

By opening this in a hex editor such as HxD we can locate the string in question and change the value ‘5’ to be ‘0’.

This will cause the check to always pass and jump, and as such permanently disable the Anti-VM check.

Question 7

How does each installation export function work?

The following installation exports are present within this malware:

• InstallRT (0x1000D847)
• InstallSA (0x1000DEC1)
• InstallSB (0x1000E892)

After passing the relevant Anti-VM checks:

InstallRT causes an installation of the malware to occur within sub_1000D3D0. The graphed overview of this function is shown below.

InstallSA causes an installation of the malware to occur within sub_1000D920. The graphed overview of this function is shown below.

InstallSB causes an installation of the malware to occur within sub_1000DF22. The graphed overview of this function is shown below.

Although these functions may seem to have a lot to them, we can break them all down to understand what is going on.

• InstallRT

This is the smallest of all the installation exported functions. Looking over the first half of the exported function, this looks to copy the malware into the System directory of windows using ‘GetSystemDirectoryA’ e.g. C:\Windows\System32.

Following on from this it should be first noted that ‘sub_10003592’ seems to be a logging routine to record data about whether or not installation has been successful into xinstall.log. Besides this we can break the function down to see that this functions by first taking an argument of a process to inject into. Where this fails (no arguiment is given) it will use iexplore.exe, before it uses VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread to create a remote thread inside the process containing our reflectively loaded DLL.

We can confirm this by running the install function from our patched binary (from question 6, used to bypass the Anti-VM check), and examine this is Process Explorer in addition to reviewing the contents of xinstall.log

From this we can conclude that ‘InstallRT’ likely means ‘Install Remote Thread’ and is used to reflectively load a DLL into a remote thread inside a process specified as an argument, or if no argument is provided, internet explorer.

• InstallSA

Looking over the start of this exported function (more specifically sub_1000D920), we can see that this looks to be taking a default string of ‘Irmon’ which appears to be searched to see if it exists as a service using the registry.

Looking further if given an argument this seems to perform a check within “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost” for a value of ‘netsvcs’ which is then checked to see if it contains the argument given.

If the argument provided exists in this key, the malware looks to install a service under “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services” with the name provided and makes sure this a part of the netsvcs group within “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost”.

As shown above the service is created with the description “ System Services". After the service is created, this attempts to set the service DLL associated with it by opening a handle to the 'parameters' registry key of the created service.

What’s interesting is that although this attempts to set the ServiceDLL to be Lab17-02.dll which is currently running;

It never actually copies the DLL to the system directory where it is attempting to run from, and as such the service never installs properly solely using InstallSA.

Finally we can confirm this by installing the malware using the ‘InstallSA’ export and taking a look at the registered services.

From this we can conclude that ‘InstallSA’ likely means ‘Install Service A’ and is used to install the malware as a Service DLL into a given service specified within netsvcs, or a new service called ‘Irmon’ if no parameter is provided.

• InstallSB

Before diving into ‘sub_1000DF22’ which performs the crux of InstallSB, we can examine ‘sub_10005A0A’ which occurs before it.

Here we can see something similar to what we saw in Lab12-04.exe question 3 where sfc_os.dll or sfc.dll are being loaded in an attempt to disable Windows File Protection through the ‘SfcTerminateWatcherThread’ export ‘2’.

Examining the start of ‘sub_1000DF22’ reveals what looks to be similar to InstallSA, only this time it is looking for the service name NtmsSvc if no parameters are passed.

This remains consistent in the way it is checking for services as part of netsvcs if an argument is specified.

If we continue analysis it appears as if this backs up the existing service to a new service called ‘ServiceMainbak’ prior to attempting to install itself. This is likely to allow removal of the implant at another date and prevent impacting the system.

Continuing through this execution we see what looks to be a fork, or crossroad where one of the paths more resembles updating to an existing installation of the malware, and the other more resembles a fresh infection taking place.

Following the fresh installation fork, we can see evidence that this will be copying the malware and setting up persistence in the form of a service.

What is interesting here is we can see another check taking place to see a call to ‘sub_1000D10D’ prior to a call to ‘sub_1000C564’.

If we examine ‘sub_1000D10D’ closer we can see that this has all the trademarks of a remote thread being used to inject into a process, the same technique as used in InstallRT.

Of interest is what process this is injecting into, in this instance the process specified is stored at [ebp-24h]. If we look back where the first fork was we can see that this is actually an instance of svchost.exe which has been located within ‘sub_1000D26B’.

‘sub_1000C564’ looks to be more around starting the malicious service we just attempted to setup to trigger the payload.

From this we can conclude that ‘InstallSB’ likely means ‘Install Service B’ and is used to install the malware as a Service DLL into a given service specified within netsvcs, or an existing service called ‘NtmsSvc’ if no parameter is provided. This also attempts to inject into svchost.exe.

Lab 17-03

Analyze the malware Lab17-03.exe inside VMware. This lab is similar to Lab12-02.exe, with added Anti-VMware techniques.

Question 1

What happens when you run this malware in a virtual machine?

Opening this in Vmware and running it we can see that it terminates upon running without any indication that process hollowing has occurred within svchost.exe (which is what we saw in Lab12-02.exe).

Question 2

How could you get this malware to run and drop its keylogger?

Opening this in PE-bear we can see that this contains a similar resource to Lab12-02.exe which was previously identified as being a keylogger.

Based on this it’s likely that some Anti-VM techniques have been implemented to prevent dropping of the keylogger. Opening this in IDA we can look at cross-references to ‘FindResourceA’ to find where this resource is likely being used.

This looks to be getting extracted and decoded through ‘sub_401670’. Working our way back by examining cross-references to ‘sub_401670’, we can see this is called within the main method, with at least 3 other checks taking place before this which have process flows that bypass the injection routine and may be Anti-VM checks. The call proceeding this (‘sub_401400’) looks to perform the actual injection, and as such there looks to be at least 2 jumps we want to take, and 2 jumps we don’t want to take highlighted in green and red respectively.

Within ‘sub_401400’ there’s one jump we want to occur (highlighted in green) in particular which may be a part of another Anti-VM check.

Enabling line-prefixes by using Options > General > Line Prefixes, we can pinpoint where we need jumps to be taken and where we need the jumps to fail.

By running this in OllyDbg and setting breakpoints at the below addresses, we can modify the jump flags as appropriate to ensure our flow is not interrupted.

• 0x4019A1 (Jump needs to be taken)
• 0x4019C0 (Jump needs to be taken)
• 0x401A2F (Jump must not be taken)
• 0x401467 (Jump needs to be taken)

Debugging the program using F9, we reach our first breakpoint (0x4019A1).

Continuing with the debugger using F9, we reach our second breakpoint (0x4019C0).

Once again the jump will not be taken, so we assemble at this location and change the jump from ‘JE’ to ‘JNZ’ to force the jump to be taken.

Pressing F9 once again we reach our third breakpoint (0x401A2F).

In this instance it looks like the jump will not be taken. As this is what we want to occur we can just continue with F9 hitting our final breakpoint (0x401467)

Here we can see we’ve made it to the section that looks to be creating a suspended process ready for hollowing out to inject the keylogger into. It’s also shown that we will be taking the jump which is what we need to occur.

If we now run procmon and filter for svchost.exe in addition to lab17-03.exe.

We can then press F9 and see what happens. At this point it’s also worthwhile to examine process execution through Process Explorer.

The above is interesting as we can clearly see that Lab17-03.exe has launched svchost with an unusual Call Stack, and if we view the memory of svchost.exe we can see reference to the keylogger file we identified back in Lab12-02.exe. This file is also now on disk to examine. Using Process Explorer we can take a full dump svchost.exe memory which can later be used to retrieve the keylogger as it exists in memory (Right Click > Create Dump > Create Full Dump).

If we want to analyse the dump file we could open it in WinDbg using File > Open Crash Dump.

From here we can use ‘LM’ to list the modules and find where svchost starts and finishes.

We can also use ‘.imgscan’ to scan and find images in this memory dump similar to ‘LM’.

.imgscan


At this point we know where the svchost.exe process resides which has been hollowed into and how big it is, and can use WinDbg to write this out to an executable file by using ‘.writemem’. The syntax is:

.writemem <outputfile> <start> <end>
.writemem C:\Users\IEUser\Desktop\keylog.exe 00400000 00407000


Although we get an error, the crux of the code is there and can now be disassembled successfully in IDA. This may initially seem small; however, the keylogger is present within the offset ‘fn’.

Looking specifically within sub_4010C7 of offset ‘fn’, we can see a familiar disassembled function involved in keylogging.

At this point we’ve well and truly got the malware to run and drop its keylogger, and have extended this analysis by dumping it from memory for disassembling.

Question 3

Which Anti-VM techniques does this malware use?

To determine what Anti-VM techniques are in use we need to examine what determines whether jumps are taken as identified in the previous question.

• 0x4019A1

This Anti-VM check is based off of a call to ‘sub_401A80’. Examining this we can see it uses the ‘IN’ Anti-VM technique to query the IO Communication Port for known Vmware values the same as we identified in a previous lab.

• 0x4019C0

This Anti-VM check is based off of a call to ‘sub_4011C0’ with an argument of ‘SYSTEM\CurrentControlSet\Control\DeviceClasses’.

Examining this we find a looping function that looks to be comparing any registry keys under the provided location to the string ‘vmware’ recursively.

Based on this we can infer it is looking for some sort of system residue that would indicate this host is running within VMware.

• 0x401A2F

This Anti-VM check appears to be based off of a call to ‘sub_401670’; however, what is interesting is that it is preceeding what looks to be enumeration of Adapter information which hasn’t been used anywhere (stored into dword_403114).

If we look at cross-references to dword_403114 we see that it is referenced twice within ‘sub_401670’ which makes this subroutine a good spot to start. Examining the operations before the first reference of dword_403114 reveals that there’s a number of mov operations on 27 different bytes.

By double clicking the variable reference and modifying the stack frame, we can set var_38 to an array size of 27 given the bytes seem to all be related.

Where any call to ‘dword_403114’ is we can assume it is making a call to the GetAdaptersInfo API based on what we discovered when dword_403114 was first defined. In this instance it needs to be passed 2 parameters.

This points to a buffer containing the a linked list of IP_ADAPTER_INFO structures.

• SizePointer

This is a ULONG variable containing a buffer size used by pAdapterInfo.

In the first call to this EAX ([ebp+dwBytes]) and ‘0’ are pushed to the stack before the call which resulted in a linked list containing nothing, and a size being specified as [ebp+dwBytes]. In turn [ebp+dwBytes] is then filled with the required buffer size to store a linked list of IP_ADAPTER_INFO structures.

In the second call [ebp+dwBytes] is once again used, this time with a proper linked list being passed. After this we see what looks to be unusual comparisons taking place.

These comparisons are contained within a loop which takes the linked list of IP adapter information from [ebp+lpMem], and if we look closely we can see that these comparisons map to elements within the IP_ADAPTER_INFO structure as a ‘Type’ at [eax+1A0h].

From this we know it is looking for an adapter which is either ethernet or WiFi with a length greater than 2 (this correlates to what is at [ecx+190h]). If we look down to where the looping function of enumerating adapters concludes, we can see more comparisons taking place, but this time against an offset 0x194 of [ebp+lpMem] (a linked list of IP Adapter information).

Given we know the offset 0x190 was the IP_ADAPTER_INFO AddressLength, we can gather based on the structure that 0x194 will contain the ‘Address’ of the Adapter, or more specifically its MAC address. Something that should be noted is we see reference to var_38 which is the array of 27 characters we defined not long ago. Based on these characters we can infer that the first 3 characters of them are being compared to the gathered VM adapter MAC address. The characters we have in this array are as follows:

0
50h
56h
0
0Ch
29h
0
5
69h
0
1Ch
14h
0
3
0FFh
0
1Ch
42h
0
16h
3Eh
0
0Fh
4Bh
8
0
27h


Putting these in order we find the following comparisons on MAC addresses is taking place:

• 00:50:56
• 00:0C:29
• 00:05:69
• 00:1C:14
• 00:03:FF
• 00:1C:42
• 00:16:3E
• 00:0F:4B
• 08:00:27

If we look these up online, for example using maclookup, we find that most resolve to Vmware in addition to Oracle and other virtualisation vendors indicating this is likely an Anti-VM check against 9 MAC addresses which would indicate it is running in a VM.

• 0x401467

This final Anti-VM check is based off of a call to ‘sub_401130’. Examining the call to this we can see it is passed ‘0x0F30D12A5’ as an argument which is interesting.

Examining inside of this we find that this takes a snapshot of running processes and there are 2 more subroutines called (sub_401060 and sub_401000) before a comparison is made against the passed argument.

Examining sub_401060 we can see a familiar construct which looks to convert the given process EXE file names to lowercase.

Examining sub_401000 we can see another familiar construct, this time what looks to be a hashing function.

It would take a bit of time to properly reverse this hashing function, but given the theme we are seeing it is likely that this is enumerating processes running which contain ‘vmware’. We can also run this in a debugger setting breakpoints at 0x401181 and 0x401186 to see the before and after hash comparisons taking place.

Question 4

What system changes could you make to permanently avoid the Anti-VM techniques used by this malware?

Permanently avoiding all of these Anti-VM techniques is a challenge; however we can fix most of the low hanging fruit by:

• Removing VMware tools.
• Removing any registry keys under SYSTEM\CurrentControlSet\Control\DeviceClasses with the string ‘vmware’.
• Changing the MAC address to one not being checked for.
• Ensuring no process is running starting with the string ‘vmware’.

Question 5

How could you patch the binary in OllyDbg to force the Anti-VM techniques to permanently fail?

If we look back at question 2 we patched the binary in memory using OllyDbg to force the Anti-VM techniques to fail; however, this was in context to our current running process and OS/VM. To make the Anti-VM checks we previously identified fail, we just need to ensure the correct jumps are taken for the above Anti-VM checks no matter how or where the malware is run.

Starting with the first jump at 0x4019A1, we can change the operation before it to ensure it is zero as the jump needs to be taken. This bypasses the first Anti-VM check indefinitely.

This same technique can be used at the operation before 0x4019C0 to ensure it is zero and the jump will be taken. The next jumps of interest are 0x40169F and 0x401467. 0x401467 is simple as it relies on a call to sub_401130 at 0x401450 to come back with a confirmed hit on the hash string, so by changing this call to a NOP we can bypass this check.

Finally the jump at 0x40169F can be modified to jump directly to 0x40184A which will bypass the MAC checks while still retaining the rest of the malware functions as required to inject shellcode.

This concludes chapter 17.

Chapter 18. Packers and Unpacking

Your goal for the labs in this chapter is simply to unpack the code for further analysis. For each lab, you should try to unpack the code so that other static analysis techniques can be used. While you may be able to find an automated unpacker that will work with some of these labs, automated unpackers won’t help you learn the skills you need when you encounter custom packers. Each lab is a packed version of a lab from a previous chapter. Your task in each case is to unpack the lab and identify the chapter in which it appeared. The files are Lab18-01.exe through Lab18-05.exe.

General Notes:

• Packers change an executable into an executable that stores the modified file (e.g. compressed, encrypted, and/or encoded etc) as data, and uses an ‘unpacking stub’ that is run by the operating system to unpack this data.
• Packers can transform all data in an exe, or only the code and data sections.
• Import information is stored in different formats after packing, and to properly RE a packed executable you generally need to reconstruct the import section.

Unpacking Stub:

• Unpacks the original executable (generally stored in extra sections of the file) into memory.
• Resolves all original imports.
• Transfers execution from the unpacking stub to the original entry point (OEP).

• Similar to unpacked in that it formats the PE header so that any loader will successfully allocate space for the executable sections in memory.
• Unpacking stub unpacks code and copies it into the sections of memory which were allocated. The method of how this is done is generally within the stub.

Resolving Imports:

• Most common approach is for packer to use ‘LoadLibrary’ and ‘GetProcAddress’ to get addresses for imported functions.
• Simplest approach is to keep import table intact; however, this defeats the purpose of obfuscating the imported functions.
• Another approach is to keep only one function of each imported library to keep table intact.
• Another approach which is useful nowadays is to remove all imports entirely; however, this makes the unpacking stub complicated as all imports

Tail Jump:

• After unpacking stub finishes, execution must gopt to the original entry point (OEP).
• Instruction that does this is called the ‘Tail Jump’.
• Packers sometimes try to obscure this jump with a ‘ret’ or ‘call’ instruction. Sometimes the instead use OS functions such as ‘NtContinue’ or ‘ZwContinue’.

Notes on unpacking:

• Unpacked program still differs from the original program as it conains the unpacking stub and other code added by the packer.
• PE header is reconstructed by unpacker/in memory so won’t be identical to the original.

Indicators of a Packed Program:

• Minimal number of imported functions.
• Only a small amount (if any) of code is recognised by disassembler ‘auto analysis’.
• OllyDbg and a number of other debuggers identify what looks to be an unpacking stub and provide a warning.
• Program contains sections with names known to be used by packers e.g. UPX0.
• Program contains unusual section sizes such as a ‘Raw Data’ size of 0, but ‘Virtual Size’ much larger.
• Programs such as PEiD are also designed to identify common packers.

Entropy:

• High entropy as identified in previous chapters (when looking at encrypted or Base64-encoded data) may indicate a binary is packed and/or encrypted if it occurs on the binary sections itself.

Automated Unpacking:

• Best method if there’s an unpacker available.
• PE Explorer comes with a number of plugins and default unpackers embedded.
• Automatic dynamic unpackers run the malicious code whereas automatic static unpackers don’t.

Manual Unpacking:

• One common approach is to figure out the packing algorithm and develop a script to run it in reverse.
• Another common approach is to run the packed program so that the unpacking stub does its job. At this point you can dump the exe from memory and fix up any PE Header required.
• OllyDump can find the OEP of a packed executable to make unpacking easier, just use the below without changing any settings to ensure everything is reconstructed correctly:

Plugins > OllyDump > Find OEP by Section Hop Plugins > OllyDump > Dump Debugged Process

Where this fails more manual steps will be required.

Rebuild Import Table with Import Reconstructor:

• Import Reconstructor (ImpRec) can be used to repair the import table for packed programs.
• Select the relative virtual address (RVA) of OEP in OEP after selecting running packed exe (Base - OEP address).
• Use IAT autosearch button and select ‘GetImports’.

Finding OEP:

• Run malicious program in debugger and use single steps + breakpoints.
• Most common tool is OllyDbg plug-in ‘OllyDump’ using ‘Find OEP by Section Hop’.
• Malware packers include call functions without a return to break debuggers and confuse analysts.
• Use both ‘Step-Into’ and ‘Step-Over’ methods.
• To find the OEP manually, you need to find the Tail Jump.
• This is often the last instruction before padding bytes which are invalid instructions in a disassembler.
• This jump generally goes to a location far away.
• Trailing 0x00 bytes after a jump are an indication it is the Tail Jump.
• Tail jumps often go to an address without valid instructions and is coloured red in IDA.
• OllyDbg attempts to debug 0x00 as ADD BYTE PTR DS:[EAX],AL.
• Most functions begin with a ‘Push’ instruction.
• Using a hardware ‘read’ breakpoint at the memory address of data which is ‘pushed’ can help to find the Tail Jump.
• Adding breakpoints after every loop can help to find the ‘Tail Jump’.
• Setting a breakpoint at ‘GetProcAddress’ if it is used by the packer helps to find the Tail Jump.
• Can set a breakpoint at a function known to be called by the program and work backwards to find Tail Jump. GetModuleHandleA is common for this. Sometimes dumping at the function which called this gets you the OEP.
• Can use ‘Run Trace’ in OllyDbg to find the OEP. This is always within the original .text section, so breaking on an instruction executing within .text can help to find OEP.

Repairing Import Table Manually:

• Import Table consists of 2 tables in memory.
• Names or Ordinals used by the loader/unpacking stub.
• List of addresses to functions that are imported.
• Need to repair imports manually by renaming calls to their corresponding imported function.
• Can be identified by looking for indirect calls to addresses outside of the loaded executable start/end ranges.
• Can use OllyDbg to jump to where IDA DWORD pointers are referencing to get the original function names.

Common Packers and their Attributes:

• UPX
• Most common packer. Can use the same UPX program with the ‘-d’ parameter to decompress the packed executable.
• Malware can also be packed with modified versions of UPX or different packers where ‘UPX -d’ fails to unpack it (yet they appear to be packed with UPX).
• PECompact
• Often contains anti-debugging exceptions and obfuscated code.
• Unpacking largely involves debugging to find the Tail Jump which is often a ‘jmp eax’ followed by many 0x00 bytes.
• ASPack
• Uses self modifying code to make unpacking difficult and often terminates prematurely if it is being debugged.
• Is so popular that many automated unpackers now exist with varying levels of success depending on the version.
• Unpacking stub contains a PUSHAD instruction. Set a hardware break on a ‘read’ for the stack addresses storing these registers to easily find OEP.
• Petite
• Similar to ASPack; however, also uses ‘single-step’ instructions to break the debugger, pass ‘single-step’ exceptions to the program to bypass.
• Use a similar method as ASPack with a hardware ‘read’ break on the relevant stack addresses.
• Keeps one import from each library in the import table.
• WinUpack
• Generally hides the Tail Jump within the unpacking stub to make it difficult to find.
• Push instructions followed by a return instruction are very common for this packer.
• Best method for finding OEP is to set a breakpoint at ‘GetProcAddress’ and then ‘single-step’ searching for loops that repair the import table.
• Another method is to break at ‘GetModuleHandleA’ or ‘GetCommandLineA’ and work backwards.
• Themida
• One of the most complicated and secure packers at the time of publication.
• Contains many Anti-VM, and Anti-Debugging components, in addition to kernel code.
• Code runs even after unpacking and the original program is running.
• One of the best approaches is to dump the program from memory if automated unpackers don’t work

Common obfuscators/packers resolved by de4dot - Note: This is .NET (e.g. malware written in C#) PE files only.

• Agile.NET (aka CliSecure)
• Babel.NET
• CodeFort
• CodeVeil
• CodeWall
• CryptoObfuscator
• DeepSea Obfuscator
• Dotfuscator
• .NET Reactor
• Eazfuscator.NET
• Goliath.NET
• ILProtector
• MaxtoCode
• MPRESS
• Rummage
• Skater.NET
• SmartAssembly
• Spices.Net
• Xenocode

Analysis Without Fully Unpacking:

• If you’re unable to fully unpack a program either due to the inability to repair the import table or PE header you can still use a disassembler such as IDA and use strings analysis.
• Some malware unpacks only part of a code as it is about to run to make analysis more difficult.
• If you can unpack part of the code, you can often create a script to unpack it all, or instead focus more on dynamic analysis.

Packed DLLs:

• More complicated than packing executables so not all packers support it.
• Packer must account for not only the imports, but also the exports.
• OEP of a DLL is the original start of the DllMain function.
• Debuggers will break at DllMain; however, this is after the unpacking stub has occurred, so to find this change the bit at ‘0x2000’ in the PE header from 1 to 0 to have it treated as an executable when unpacking.

Overview

Starting out we can do a multi-scan using PEiD to see if we can fingerprint what packer each executable is using.

From this we have determined the following which will be used as a guide for the rest of the lab:

• Lab18-01.exe: No Packer Detected
• Lab18-02.exe: FSG 1.0 Detected
• Lab18-03.exe: PECompact 1.68 - 1.84 Detected
• Lab18-04.exe: ASPack 2.12 Detected
• Lab18-05.exe: UPack 0.39 beta Detected

Lab 18-01.exe

From our search with PEiD we begin to believe no packer has been used; however, given the context of this chapter and the malware in question this surely isn’t the case. To help find out whether a packer is in use we can open this in pestudio and examine the sections of this file to see if there’s any known section names used by a packer.

From the above we see a section which is known to be used by the packer UPX, in addition to indications that the executable sections are self-modifying and are marked as both ‘writeable’ and ‘executable’. As a first attempt we can try to unpack this using UPX; however, we’re promptly displayed a message that indicates this may have used a custom version of UPX or be further modified to prevent unpacking.

Opening this up in IDA we can see that the exported functions look to exist within this UPX section, in addition to what looks to be a Base64 index string, and a looping function no doubt used to unpack the program.

Examining an instruction at 0x409F43 we can see what looks to be a jump to a faraway address which seemingly doesn’t have any valid code in it right before the end of the ‘start’ function.

As we are currently looking for the Tail Jump to our original entry point, it currently looks like this would be a good candidate. By opening this up in OllyDbg we can see that this has a number of 0x00 trailing bytes which helps us to pinpoint it as the Tail Jump.

By creating a hardware break here for whenever it attempts to execute, we will see it hit our hardware breakpoint. By pressing F7 we will single step to what is the OEP of this program. From here we can use OllyDump to dump our debugged process.

Opening the dumped program in IDA, we can immediately see a lot more imported functions and a familiar use of imports looking for ‘GetCurrentHwProfileA’.

From this we can infer that this was a packed version of Lab14-01.exe as we identified how these components were being used in Lab 14-01 question. This proves we’ve successfully found the Tail Jump and unpacked this executable.

Bonus PE Identification using ‘DIE’:

Other tools exist to determine what packer may have been used and information about a file including ‘Detect-It-Easy (DIE)’

• DIE can easily be expanded on and has support for many file formats which have been contributed by the infosec community.

In this example if we use DIE to look at the file we can see it is packed using a modified version of UPX despite it not being identified using PEiD.

Lab 18-02.exe

From our search with PEiD we begin to believe FSG 1.0 is the packer used on this executable. Opening in IDA we can see that this packer looks to be leveraging the ‘GetProcAddress’ Windows API.

First off we will attempt to unpack this using an automated unpacker. In this case we can use PEiD’s Generic Unpacker plugin to try and unpack the executable.

By attempting to automatically find the OEP we are presented with a message saying it was unable to find the OEP.

Based on this we need to look through other ways of unpacking it. By opening this using OllyDbg we can use the OllyDump plugin to find the OEP via Section Hop (Trace Over) method.

This immediately pauses execution of the program as it’s detected that EIP is outside of a specified range which may mean it is the Tail Jump.

What’s interesting here is that it looks to not have been disassembled as code. By pressing CTRL + A we can force OllyDbg to analyse and disassemble these bytes resulting in a different set of instructions.

Because we can see what looks to be valid function calls and a known string from the program, it looks like this isn’t inside of the unpacking stub, but rather is part of the unpacked program so may once again be our OEP. BY dumping this debugged process once again using OllyDump, and opening it in IDA we get what looks to be a successfully unpacked program.

At a glance we can see that this is the same as what we saw with Lab07-02.exe indicating we have successfully found the OEP and unpacked the program.

Lab 18-03.exe

Automated Unpacking:

From our search with PEiD we begin to believe ‘PECompact 1.68 - 1.84’ is the packer used on this executable. Once again we attempt to unpack this and find the OEP using plugins for PEiD.

Both of these plugins have identified the OEP as 0x401577 which is promising. Attempting to unpack this using PEiD’s Generic Unpacker plugin we are prompted to rebuilt the imports with ImpREC. By proceeding to do this we now have a new file called Lab18-03.exe.unpacked_.exe.

A quick analysis of this in IDA reveals the string ‘1qaz2wsx3edc’ which we remember from Lab09-02.exe.

In this instance it looks like the automated unpacking method worked and successfully rebuilt the imports of this program.

Manual Unpacking:

To manually identify the above OEP had automated unpacking not worked, we have to examine this in OllyDbg once again. First we will attempt to use the OllyDump plugins ‘Find OEP By Section Hop (Trace into)’.

As we can see this has taken us to ‘0x40A110’, which isn’t the OEP we found previously using automated methods. Further although 0x40A111 looks to be a null byte (0x00) there doesn’t look to be many of these indicating this may not be the Tail Jump. If we then try ‘Find OEP By Section Hop (Trace over)’, we wind up at another address which doesn’t look to be the OEP.

What is interesting about this is that it follows a number of null byte instructions. Given this plugin doesn’t seem to have worked we can scroll up to follow any leads on jumps or returns prior to a number of null byte instructions.

Although in the above we can see a jump to 0x40754E right before some null byte instructions, we can also see that there are some calls to POPAD and POPFD. Although none of this looks to be related to the necessary Tail Jump, it does lead us to another avenue we can explore, and that’s seeing if any data is pushed to the stack prior to the unpacking stub executing. Using OllyDbg we can restart the program and search for any PUSHAD instructions.

This reveals a number of entries; however, one really stands out as it isn’t showing the PUSHAD instruction and instead shows a comment of (Initial CPU Selection) indicating it may be part of modifying code.

By examining 0x405130 further we can see that straight after PUSHAD and PUSHFD execute there is a call to a routine which indicates this may be the start of the unpacking stub given how early it executes and the use of the below operators:

• PUSHAD: Push all 8 general purpose registers to the stack.
• PUSHFD: Push the EFLAGS register to the stack.

By using F8 to step over these first instructions to 0x40513A (the call to the identified routine after PUSHAD and PUSHFD has executed), we can then set a hardware breakpoint to catch whenever these registers are popped which will likely be right before the OEP. By right clicking ESP and selecting ‘Follow in Dump’.

We can then create a Hardware break on if this is accessed.

By running the program with F9, we hit a breakpoint right before a jump at 0x407551 which looks to be our Tail Jump.

We can see that this is jumping to 0x401577 which is what we previously identified as our OEP. If we step into the instruction which takes us to ‘0x401577’ we can now dump the program using OllyDump. Opening in IDA, although we can see the 2 dumped processes differ slightly in file size due to how they were dumped and import tables rebuilt, we can see that the overall content of the program is very much the same.

Lab 18-04.exe

From our search with PEiD we begin to believe ‘ASPack 2.12’ is the packer used on this executable. Using our automated methods above proves invaluable; however, examining this in IDA reveals it is performing a PUSHAD at 0x411001 similar to the previous executable.

Using this as our anchor we will repeat the same process as Lab18-02.exe to manually find the OEP. Running in OllyDbg we will step to ‘0x411002’ aftert PUSHAD has been run, then follow ESP to our Dump, before creating a hardware breakpoint again.

By running the program we hit a POPAD instruction right before a jump. This looks to be right before a RETN and as such a Tail Jump at 0x4113BF.

After taking this jump we arrive at some data at ‘0x403896’ which looks familiar to other data we’ve initially seen when arriving from a Tail Jump given OllyDbg hasn’t analysed this correctly.

By using CTRL + A to analyse this, we can see error handler installations in additon to a call to GetVersion and GetCommandLineA which helps us validate that was likely the Tail Jump.

Dumping this with OllyDump we can then open it in IDA and see some familiar command-line options present in Lab09-01.exe which helps us confirm we have successfully found the OEP and associated Tail Jump.

Lab 18-05.exe

Automated Unpacking:

From our search with PEiD we begin to believe ‘UPack 0.39 beta’ is the packer used on this executable. We can attempt to automatically unpack this by leveraging PE Explorer and its ‘Upack Unpacker Plug-In’. Upon opening this in PE Explorer we can see it has identified that it is packed and attempted to unpack it.

From the above we can also see it has identified the OEP as 0x401190 and has managed to partially restore the file and import tables. By saving this executable to a new file we have a more or less complete file which we can see is related to Lab07-01.exe due to it searching for the service ‘MalService’.

Manual Unpacking:

If we open this in IDA we get messages indicating that it has unaligned section pointers and a virtual address error.

By continuing with analysis we can see that it uses ‘GetProcAddress’ which is typical for this packer to rebuild the import table.

Opening this in OllyDbg we are presented with an error message which indicates that the PE Header of this has been tampered with.

As a starting point we will look for calls to ‘GetProcAddress’ by using CTRL + G and putting in ‘GetProcAddress’. At this point we can create a breakpoint with F2.

Running the program we hit our breakpoint and can see that the first API imported by Lab18-05.exe is ‘CreateWaitableTimerA’.

If we continue to press F9 the unpacker will continue to find the necessary API in the original executable as it repairs the import table. Eventually we find it will get the address for ‘InternetOpenUrlA’.

After this an exception handler error is hit which we can pass to the program; however, given the error it may be a good spot to examine the program at 0x408EB4 which is where the calls to ‘GetProcAddress’ occur.

At this point we find a loop occurs which may be involved with repairing the import table. This is repeated a number of times as the loop goes through every API imported by the program. As we want to analyse right before the exception occurs we will use F9 to run the program up until we hit ‘InternetOpenUrlA’ and then step through manually using F8 until we reach 0x408EA5 where a jump should be taken to 0x408E91.

At 0x408E96 we can see another jump occurring which may be the Tail Jump given we have just gone through repairing the import table aspect of unpacking; however, if we examine where this is jumping to we see 0x408EB7 is just a call to ‘RETN’ so can’t be the start of this executable.

By using F7 to step into this we find that this ‘RETN’ takes us to a sight for sore eyes.

What we can now see is that the RETN was in fact our Tail Jump and we are at what looks to be the OEP. This is the same location found through our automated unpacking (0x401190). By dumping the program we may experience some errors or even OllyDbg crashing; however, we can still open this in IDA and see it is essentially the same as we unpacked using PE Explorer.

Once again we can see this is a packed version of Lab07-01.exe.

This concludes chapter 18.

Chapter 19. Shellcode Analysis

General Notes:

Shellcode is:

• Often used within an exploit or by software performing process injection, both of which occur on a process after it has started.
• Unable to automatically perform actions traditionally done by a normal executable, such as loading external libraries, allocating or reallocating preferred memory etc.

• Code is generally a blob of data and unable to be loaded normally.
• Can use tools to load the shellcode for analysis:
• When loading in IDA the correct processor needs to be selected.
• For the purpose of this lab that processor is:
• Intel 80x86 processors: metapc
• 32-bit disassembly

Position-Independent Code (PIC):

• Shellcode must use Position-Independent Code as there’s no guarantee it will be loaded at the expected location in memory.
• Using relative offsets to registers helps to avoid addressing memory as position fixed locations e.g. ‘mov [register], [ebp-4]’
• Mneumonics such as ‘mov [register], dword_[memory_address]’ aren’t position-independent as they reference a specific memory address.

Identifying Execution Location:

• When using offsets, shellcode essentially needs to use a ‘base pointer’ and add or subtract to it to get execution locations (particularly x86 shellcode).
• Shellcode cannot load a general purpose register with EIP; however, shellcode uses call/pop operations and fnstenv to perform this.
• Call executions place the address of the following instruction on the stack.
• Once a call finishes a return instruction pops this address into EIP.
• A call to POP instead of a return causes shellcode to go to the address contained in EIP which can confuse disassemblers and debuggers.
• Hardcoded addresses can be found for functions by using OllyDbg to search for the location of the function e.g. CTRL + G > MessageBoxA.
• The debugged process can be any process which has the required DLL loaded into memory. This is because if a DLL is already in memory every process will use the same DLL instead of loading it into memory again.
• A just-in-time debugger can be registered so that if any program hits a breakpoint it is passed to an instance of the debugger.
• OllyDbg can be setup to do this by using Options > Just-in-time Debugging > Make OllyDbg Just-in-time Debugger
• There’s special purpose registers used by the x87 floating-point unit (FPU) which can be used by shellcode to find the required instruction pointer.
• These registers are used to perform arithmetic functions within the FPU, but ‘fstenv’ and ‘fnstenv’ have an entry ‘fpu_instruction_pointer’ at offset 12.
• Both of these can be used to find EIP similar to the call/pop method, with ‘fldz’ commonly being used as the FPU instruction to push nothing to the stack.

Manual Symbol Resolution:

• Shellcode generally needs to interact with the Windows API via DLLs which are already loaded into memory.
• To ensure all of these libraries are loaded and their exported functions can be used, shellcode often needs to use ‘LoadLibraryA’ and ‘GetProcAddress’ to find them in memory.
• Without using the above to get a handle on the library, hard-coded addresses are used to find these symbols which means it will only work on a specific OS and service pack given these memory locations often change.
• To do this, shellcode must first find kernel32.dll in memory and parse the PE header to find the exported functions for ‘LoadLibraryA’ and ‘GetProcAddress’.
• Windows structures generally need to be followed to get the load address of kernel32.dll which are noted in order below:
• Thread Environment Block (TEB) can be located at FS:EAX (FS segment register).
• TEB + 0x30 = pointer to Process Environment Block (PEB).
• PEB + 0x0c = pointer to PEB_LDR_Data struct (contains 3 doubly linked lists of the LDR_DATA_TABLE struct - one for each DLL).
• PEB_LDR_Data + 0x14 = InMemoryOrderLinks (LIST_ENTRY).
• PEB_LDR_Data + 0x1c = InInitializationOrderLinks (LIST_ENTRY).
• LDR_DATA_TABLE_ENTRY (ntdll.dll) = first entry in PEB_LDR_DATA.
• LDR_DATA_TABLE_ENTRY (ntdll.dll) + 0x08 = InMemoryOrderLinks (LIST_ENTRY).
• LDR_DATA_TABLE_ENTRY (ntdll.dll) + 0x10 = InInitializationOrderLinks (LIST_ENTRY).
• Prior to Windows 7 kernel32.dll is the second module initialised and can be found by the second entry in the ‘InInitializationOrderLinks’ list.
• Windows 7 and later shellcode will need to look for FullDllName (UNICODE_STRING) to ensure it is kernel32.dll
• LDR_DATA_TABLE_ENTRY (kernel32.dll)
• LDR_DATA_TABLE_ENTRY (kernel32.dll) + 0x08 = InMemoryOrderLinks (LIST_ENTRY).
• LDR_DATA_TABLE_ENTRY (kernel32.dll) + 0x10 = InInitializationOrderLinks (LIST_ENTRY).
• LDR_DATA_TABLE_ENTRY (kernel32.dll) + 0x18 = DllBase (PVOID).
• LDR_DATA_TABLE_ENTRY (kernel32.dll) + 0x24 = FullDllName (UNICODE_STRING).
• When going from one LIST_ENTRY to the next using Flink and Blink (Covered in Lab 10-3) you will wind up at the same offset in the next DLL.
• For example when using the Flink pointer inside LDR_DATA_TABLE_ENTRY (kernel32.dll) + 0x10 (InInitializationOrderLinks), it will take you to offset 0x10 inside of the next DLL.
• This means to access the DllBase of the next DLL, we will only need to add an offset of 0x08.
• After finding the base address of kernel32.dll, exported symbols can then be parsed by following structs in memory.
• PE files use Relative Virtual Addresses (RVAs), essentially offsets within the PE image in memory.
• PE image base + RVA = a valid pointer.
• Export data is stored within IMAGE_EXPORT_DIRECTORY.
• RVA to IMAGE_EXPORT_DIRECTORY is stored within IMAGE_DATA_DIRECTORY at the end of IMAGE_OPTIONAL_HEADER.
• Location of IMAGE_DATA_DIRECTORY differs between 32 and 64-bit OS. Most shellcode assumes it is operating under 32-bit OS and use the below to find IMAGE_DATA_DIRECTORY:
• Shellcode maps export names to ordinal numbers by using ‘AddressOfNames’ and ‘AddressOfNameOrdinals’ arrays.
• Export address of symbols are found by performing the following:
• Searching AddressOfNames for a char* entry with desired symbol and storing this index in a variable.
• Retrieving the AddressOfNameOrdinals entry for the index stored above and store this index in a variable.
• Retrieving the AddressOfFunctions entry for the index stored above to get the RVA of the exported symbol.
• The above is a pointer to the dllBase of the library and can be treated as a HANDLE.
• To search for API functions the full name needs to be included as ASCII in our shellcode unless it is hashed.
• Hashing has a benefit of making it smaller to fit shellcode constraints and also the API calls aren’t in plaintext.
• Hashing occurs on a string pointer.
• Hash collisions can occur between symbols in different DLLs and symbols unused by the shellcode without any issue.
• Most common hash function is a 32-bit rotate-right-additive hash (rot13).
• Comes across as ‘ror’ mneumonic for the value 0x0d.
• Precomputated tables by ‘ihack4falafel’ can be found forked here

Shellcode Encodings:

• Shellcode must be located inside of program address space to execute.
• Strcopy and strcat are examples of unsafe string functions as they do not set a maximum length of data to be written.
• Shellcode must not include any NULL-byte (0x00) characters as these are termination characters for these string copy functions.
• Shellcode often uses a stub to unpack encoded payloads so that it avoids bad characters.
• Where shellcode uses the stub to write decoded bytes back over the encoded bytes it is considered self-modifying.
• Common encoding techniques:
• Leverage alphabetic transforms to change a byte to 4-bits appended to an ASCII character.

NOP Sleds/Slides:

• NOP sleds are a number of 0x90 instructions preceding a decoding stub which is used to run shellcode in an exploit.
• These can also use characters other than 0x90 such as ones between 0x40 to 0x4f which increment or decrement general registers and don’t necessarily interrupt program flow.
• These exist because decoding stubs often blow a hole around the stub as the stack grows which can take out valid instructions.
• Decoding stubs tend to use ‘GetPC’ to get the Program Counter which causes instructions to be overwritten, this is where NOP instructions are often used so that only NOP instructions are overwritten causing the shellcode to function normally.
• Shellcode authors can also instead use code which subtracts the position of ESP (Stack Pointer) to avoid needing a NOP Sled; however, this is seldom used.

Finding Shellcode:

• Shellcode is often found in files, network traffic, or in script telemetry.
• Malicious web pages generally use JavaScript to determine if a system is running a vulnerable browser or application version.
• ‘unescape’ is generally used to convert shellcode which is encoded so it can run.
• ‘unescape’ can use ‘%u’ preceding values which will be converted, and on little-endian systems e.g. x86 these are converted in reverse order.
• e.g. ‘%u1122’ becomes ‘22 11’
• Where this isn’t using unescape it is treated as a single HEX character
• e.g. ‘%41%42%43’ becomes ‘41 42 43’
• Shellcode inside executables can be easy to identify as they look like shellcode, or an obfuscated blob which is leveraged in injection.
• This is generally found by looking for API calls mentioned in Chapter 12, e.g. VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread.
• Other methods of injection exist though so these API calls won’t always be present.
• Initial decoders can be found by searching for some common opcodes and disassembling/analysing them in IDA:
• Call (0xe8)
• Unconditional Jumps (0xeb, 0xe9)
• Loops (0xe0, 0xe1, 0xe2)
• Short Conditional Jumps (0x70 - 0x7f)

Lab 19-01

Analyze the file Lab19-01.bin using shellcode_launcher.exe.

Question 1

How is the shellcode encoded?

To be able to analyse Lab19-01.bin using shellcode_launcher.exe, we first need to understand how shellcode_launcher.exe can be used. By running it on the command-line we can get an idea of what parameters are required.

In the above we can see its basic usage is:

shellcode_launcher.exe -i <shellcode_filename>


To allow us to debug this shellcode and understand how it is encoded, we will also use the ‘-bp’ parameter to add a breakpoint before execution. For this to work we will first go in and set OllyDbg as our ‘just-in-time’ Debugger using Options > Just-in-time Debugging > Make OllyDbg Just-in-time Debugger.

By attempting to run the shellcode and adding a breakpoint we get an error and can go to the debugger. You’ll notice this also tells us where the base of our shellcode has been loaded in memory (in this case 0x001f0100).

Examining the debugged code we can see a jump statement which if we follow where it is pointing to, leads us to a large number of ‘INC ECX’ operations.

We can gloss over these as they’re essentially just padding (0x41 operations which act as an equivalent to a NOP Slide) and don’t do anything of interest. Once we arrive at an XOR instruction we see a number of other operations occurring.

What is important here is that this occurs at an offset of 0x200. If we were to open this in IDA, we could go to an offset of 0x200 and find where our code changes.

By pressing ‘C’ in IDA, we can disassemble this and view it in IDA’s graph view to get a bit of a better idea of the flow this code goes through.

What we can see is that this is some sort of decoding routine given how it loads bytes, loops and shifts bits. First it will perform a ‘push’ operation of esi and move it into edi (now may be a good time for us to revisit Chapter 4: A Crash Course in x86 Disassembly), this will set our Source Index Register to be our new Destination Index Register, and as a result when the loop completes the RETN operation will send us to the offset address of our intended next instruction. This is the equivalent of performing a ‘jump’ to a sub-routine which then returns back after it completes; however given this is shellcode and hasn’t resolved any API calls, it must be done in a way such as this.

If we step into this operation (F7) using our debugger, we can see that ESI now contains what looks to be an encoded string which will be overwritten by our decoding routine to become our payload.

Note: In the screenshot above our address base has changed due to the shellcode being re-ran, our new base address is 0x200100.

From here the decoding routine functions as follows:

• From the 4-bit low register filled with part of our byte (remember 8 bits make up a byte), 0x41 is subtracted from it.
• These bits are then shifted to the left by 4 and stored in ‘dl’.
• After loading in another byte, 0x41 is subtracted from the 4-bit low register and stored in ‘al’.
• Both ‘al’ and ‘dl’ are added together (with the output being stored in ‘al’)
• The mneumonic operator ‘stosb’ (store string byte) stores this decoded byte back to memory at EDI.

Based on this we know that the shellcode is encoded by using 0x41 (A) as a ‘base’ for a type of alphabetic encoding scheme where each payload byte is stored in the 4-bit low register of two encoded bytes added together. By holding ‘F7’ in our debugger we can see this decoding play out as the assembly appears before our very eyes overwriting what used to be various generic operations acting as a NOP slide.

By adding a breakpoint at the ‘RETN’ instruction, we can then use ‘F9’ to run through the entire routine and see we will be returning to offset 0x224.

We can go a step further and use ‘F7’ once more, before following ‘EDI’ in our ASCII dump to see some interesting strings.

From here we can save the decoded shellcode to another file which will be of value for subsequent questions. To do this we can Right Click the dump and select ‘Binary’ > ‘Binary Copy’ and paste it into a hex editor such as hxd before saving it.

Question 2

Which functions does the shellcode manually import?

Given we have dumped out the decoded shellcode, we can get a lot of information including this automatically by using ‘scdbg’ which we have previously used in Lab11-03.exe.

scdbg -f HexDumpLab19-01.bin -findsc


This extremely useful tool by David Zimmer reveals the functions this shellcode proceeds to manually import.

• GetSystemDirectoryA
• WinExec
• GetCurrentProcess
• TerminateProcess

not only that, but it also shows what network it communicates with, filesystem residue, and what it does. It effectively answers the next 3 questions. If we were to manually look into this using our debugger, we would continue to step through the shellcode to find it locating kernel32.dll’s base address in memory. From here it parses it based on symbol hashes to get the required exported function pointers which are then used.

Another way to find this information is to open the shellcode (which we saved in question 1) up in IDA and perform an autoanalysis at the start. Starting from the top of this shellcode we can see our familiar decoding routine.

After this completes the shellcode jumps to ‘loc_163’. Of interest here is that we immediately jump to ‘loc_BE’.

What’s interesting is that this follows a pattern where a hash is pushed to the stack before calling ‘sub_51’ directly after first calling ‘sub_9D’.

The hashes pushed are as follows:

• 0xEC0E4E8E
• 0xB8E579C1
• 0x78B5B983
• 0x7B8F17E6
• 0xE8AFE98
• 0x702F1A36

Examining ‘sub_9D’ we can see that this is first getting a pointer to the PEB structure in memory, walking it using InInitializationOrderLinks inside of PEB_LDR_Data, and leveraging this to find the DLLBase of DLLs loaded into memory.

We can dive into ‘sub_51’; however if we recognise these hashes, we can find the same exported function information as we did using scdbg. ‘sub_51’ is performing a hashing algorithm over DLLs in memory and then comparing them to the hash it has pushed to the stack. Luckily we know this is using ROR13 for its hashing algorithm, and we already have a number of pre-computed hashes available here. Comparing them to the above we find the below:

Kernel32:

• 0xB8E579C1 = GetSystemDirectoryA
• 0x78B5B983 = TerminateProcess
• 0x7B8F17E6 = GetCurrentProcess
• 0xE8AFE98 = WinExec

Unknown:

• 0x702F1A36

The reason ‘0x702F1A36’ is unknown is because we haven’t precalculated this hash, and it is present within Urlmon.dll. We can proceed to do so; however, given what we’ve already enumerated this with scdbg (URLDownloadToFileA) there’s no real purpose to do so.

Question 3

What network host does the shellcode communicate with?

Based on our analysis using scdbg in question 2, we know this communicates with the below URL and downloads another binary to c:\WINDOWS\system32\1.exe.

• http://www.practicalmalwareanalysis.com/shellcode/annoy_user.exe

This was also found when looking at the strings in our decoded shellcode.

Question 4

What filesystem residue does the shellcode leave?

Based on our analysis using scdbg in question 2, we know this downloads a binary to c:\WINDOWS\system32\1.exe. This is after retrieving the system directory, and indicates that filesystem residue would be found at:

• %SystemRoot%\system32\1.exe

Question 5

What does the shellcode do?

Based on our analysis in questions 1 and 2, we know this shellcode decodes itself using an alphabetic encoding scheme where each payload byte is stored in the 4-bit low register of two encoded bytes added together. After this it resolves a number of imports and uses them to download a file from a URL to disk before executing it.

Lab 19-02

The file Lab19-02.exe contains a piece of shellcode that will be injected into another process and run. Analyze this file.

Question 1

What process is injected with the shellcode?

Examining this executable in IDA, we can see there looks to be 3 main operations which initially occur. The first is adjusting the running process so that it has ‘SeDebugPrivilege’, this will allow any process to be debugged by the executable. Next it looks to be querying the registry for ‘HKEY_LOCAL_MACHINE\SOFTWARE\Classes\http\shell\open\command’ in order to find the default browser used on this system, and finally it looks to be running this process with the ShowWindow parameter set to 0, making it hidden from the user.

Based on this it looks like the default web browser installed on the OS is injected into, which in this case is Internet Explorer.

Question 2

Where is the shellcode located?

If we continue looking at the main function of this program we can see ‘unk_407030’ is stored in a buffer right before ‘sub_401230’ is called.

Looking at ‘sub_401230’ we can see that there’s 4 API calls which immediately makes us assume this is the subroutine used to injected into Internet Explorer.

The ‘CreateRemoteThread’ method is one of the most common methods of injection. Based on this we can assume that unk_407030 at 0x407030 is where our shellcode buffer is located.

Question 3

How is the shellcode encoded?

By using OllyDbg we can set 0x407030 as our new origin point upon starting the program by right clicking and selecting ‘new origin here’. We can also set a breakpoint at this location.

A message will likely be received that EIP is outside of executable code due to how the shellcode dynamically executes itself.

If we then use F9, we will be at the start of this thread initialisation.

Looking at the start of this initialisation we can see that a xor operation occurs over the shellcode with the value 0xe7 before a loop occurs.

This looks to be how the shellcode is encoded.

Question 4

Which functions does the shellcode manually import?

To answer this question we need to look at the shellcode itself. One way to do this is to create breakpoints associated with relevant API calls we discovered were being used to inject into Internet Explorer, particularly ‘WriteProcessMemory’. By Opening this in OllyDbg2, we can easily pivot to the instance of WriteProcessMemory by using CTRL + G and locating the appropriate label.

By creating a breakpoint here and beginning to step into the next assembly instructions, we can see that this is writing a buffer from 0x407030 where our shellcode resides for the next 423 bytes.

By following this in our dump we can see at a glance approximately where the shellcode starts and finishes based on the data shown.

From here we can dump this to a file to get the shellcode which will be injected into Internet Explorer.

If we open this in IDA and begin converting it to code using ‘c’ we will soon get to a section which contains the decoding routine.

This helps to prove the code will be injected into Internet Explorer, and once injected will perform decoding of the shellcode before execution; however, it doesn’t answer what imports this has. By running it through scdbg like we did previously we can see it shows the decoding stub assembly in addition to what the shellcode is essentially trying to do.

scdbg -f Lab19-02_00407000.bin -findsc


From this we know that the shellcode is at least importing the following functions.

• WSAStartup
• WSASocket
• connect
• GetCurrentProcess
• TerminateProcess

We also now know that this is designed to connect back to a host at 192.168.200.2 on TCP port 13330.

One way we can debug the shellcode after our decoding routine has executed, is to create a breakpoint at 0x407041 after the shellcode has decoded, and set our origin to the start of the shellcode 0x407030.

Once we hit our breakpoint using F9, we can once again dump the decoded shellcode into a file.

If we run scdbg over it again we can see a similar result, only this time the assembly shown is different. This will still contain the decoding routine, as only certain instructions and the contents of registers will have after the decoding routine runs.

If we return to our debugger we can step into our next jump operation and once we jump to 0x4070E3 we will see a POP ESI instruction occurring. This is essentially telling the program that that 0x4071BB is at the top of the stack.

By doing this the program can use a Call/Pop method of manually resolving imports used by the shellcode which can cause our debugger to access invalid memory locations and get confused had we not set our origin. By setting up a breakpoint at any call to 0x407076 (the subroutine used to walk through PEB and look for imports), and also adding breakpoints at 0x407095 (import hash calculating function), and 0x40709E (conditional jump used to determine if correct imported DLL is found), we can now use F9 over and over to begin to manually find the imports used by this shellcode.

Most of the time a jump will be taken; however, in circumstances where a jump is not taken, we will have one of our imported functions, in this case it is obvious the imported function is ‘TerminateProcess’.

An easy way to enumerate this is to follow the below steps:

• CTRL + G - 0x407030
• Set above as New Origin
• Set a breakpoint at 0x407041 (this is only hit once an imported function is hit)
• F9
• Review contents of ESI to get the imported function.

Enumerating imported functions in this way may cause exceptions once this begins to attempt loading in other functions from within ws2_32.dll; however, if running this on the correct OS and allowing it to connect back to the specified C2, we should find it import the below previously missed function.

• CreateProcessA

The reason for this is because it only seems to trigger once a successful connection is established to 192.168.200.2 on TCP port 13330. When this occurs cmd.exe is run indicating this is acting as a reverse TCP shell.

Another way we could have gotten relevant information is to start autoanalysis in IDA at offset 0x30 given we know this is where our shellcode starts. With this our disassembly looks a little bit different.

Following through in IDA we can begin to see some references to ws2_32 and cmd (these are stored in reverse order on the stack so much be evaluated backwards).

With all of this we’ve got a good understanding of how the shellcode works and what it imports.

Question 5

What network hosts does the shellcode communicate with?

Based on the shellcode debugging performed in question 4, we can see that this shellcode communicates with the host at 192.168.200.2 on TCP port 13330.

Question 6

What does the shellcode do?

From the analysis in question 4, we can see that this shellcode is designed to connect back to the IP 192.168.200.2 on TCP port 13330 to establish a reverse command shell.

Lab 19-03

Analyze the file Lab19-03.pdf. If you get stuck and can’t find the shellcode, just skip that part of the lab and analyze file Lab19-03_sc.bin using shellcode_launcher.exe.

Question 1

What exploit is used in this PDF?

Opening this in PDFStreamDumper, we can use load in Lab19-03.pdf and use ‘Exploits_Scan’ to look for possible exploits.

This immediately reveals that Stream 9 has what looks to be CVE-2008-2992. This is a Stack buffer overflow in Adobe Acrobat and Reader 8.1.2 which allows remote attackers to execute arbitrary code via a PDF file that calls the util.printf JavaScript function with a specially crafted format string argument.

Taking a look at Stream 9 seems to back up this assumption with JavaScript and util.printf being leveraged in what looks to be some sort of buffer overflow.

From this we have a safe assumption that CVE-2008-2992 is being exploited in this PDF.

Question 2

How is the shellcode encoded?

The shellcode is first of all using percent escape encoding in the variable ‘payload’. To unescape this properly, we need to know that the unescape operations occurring are reading in 2 hex characters specified after ‘%u’ and turning these into 2 bytes. In addition this will swap endianness when the unescape operation occurs. To easily decode this we can use CyberChef with a ‘Swap Endianness’ operation with a word length of 2. We can also replace all spaces to allow it to be read in as raw hex by scdbg.

From here we can save this and we have decoded shellcode for further analysis. Attempting to run this through scdbg reveals it performs a check to see if a file handle is opened, likely in an attempt to prevent analysis unless a handle is open on the malicious PDF file.

Question 3

Which functions does the shellcode manually import?

One way we can debug this to find imports is through shellcode_launcher so long as we specify a file to get a handle on during the launching process by using the ‘-r’ parameter.

Note: scdbg is able to read in our shellcode as a raw hex string, whereas shellcode_launcher requires the file to be stored as a hex dump to prevent it from interpreting the hex characters as content which still requires hex encoding. The easiest way to do this is to copy the content inside of a hex editor such as HxD and save it as a new file.

At this point we can launch our shellcode.

shellcode_launcher.exe -i Lab19-03_shellcode_raw.bin -r Lab19-03.pdf -bp


This leads us into our just-in-time debugger, and by using ‘F8’ twice to step over the initial breakpoint and jump past our (equivalent of) NOP sleds, we get to the start of our shellcode.

We can immediately see our stack pointer is being moved into EBP before we look at an offset of 0x17 and call a routine. If we step over both of these we’ll see that the proceeding instructions have been changed by our call at offset 8.

By instead using ‘F7’ to step into this routine, we can see that it is calling POP ESI, signalling this may be similar to the identified hashing and import functions found in Lab19-02, so this is likely going to be enumerating imports.

It’s important to note here that prior to Windows 7 kernel32.dll is the second module initialised by the OS and can be found by the second entry in the ‘InInitializationOrderLinks’ list when looking over the PEB. It may be that this shellcode assumes it is running on an OS prior to Windows 7. If you try and debug or run this on Windows 7 or later you may have some issues with memory access while debugging which looks similar to the below.

In addition if you step over (F8) the wrong call, where it runs POP ESI, you can find yourself experiencing the same error due to the debugger getting confused which leads to imports not being properly loaded or resolved by the shellcode.

For the purpose of ensuring this runs smoothly it’s best to debug in a 32-bit Windows XP machine. We’re going to restart our debugged process ensuring it is on a 32-bit Windows XP machine, and in the following scenario we have loaded this DLL in at base address 0x350100.

To debug this smoothly and determine the functions this manually imports, we will start by stepping over instructions using ‘F8’ until we get to 0x350108.

From here we will step into this function with ‘F7’, and at this point we are back at POP ESI. Because we know this is going to be searching the Thread Environment Block (TEB) at FS:EAX before moving to the Process Environment Block (PEB) at FS:EAX + 0x30, we will want to know what (call) routine this occurs in.

Looking at the first call which is made to 0x3501CA, we can see that this is responsible for getting access to the first PEB ‘InInitializationOrderLinks’ entry and DllBase of the next DLL in memory (similar to what we saw in Lab19-01).

We will want to step over this call with ‘F8’. The next call we see is at 0x350295 which is calling 0x35017E. If we look at this we can see that it is immediately referencing the ‘FullDllName’ offset which is stored at 0x24.

Based on accessing ESP+24 we can assume this function will be performing hash comparisons to find imported functions, and as such we can use F7 to step into this. When performing these comparisons, it will likely take place in a looping function, so a good place to set our breakpoints would be directly after the JNZ operation, and proceeding JMP operation.

The reason behind this is because if a comparison takes place in a loop and it fails to find the wanted imported function, it will immediately jump back before our breakpoint, meaning we can use ‘F9’ to run the program through all the failed comparison statements. By doing this we can press ‘F9’ and write down each associated import which was compared and has its value in ‘ESI’. Doing this reveals the following functions are imported by this shellcode.

• CreateProcessA

• TerminateProcess

• GetCurrentProcess

• GetTempPathA

• SetCurrentDirectoryA

• CreateFileA

• GetFileSize

• SetFilePointer

• WriteFile

• CloseHandle

• GlobalAlloc

• GlobalFree

• ShellExecuteA

If you press F9 after resolving the final import the program will run until completion.

Question 4

What filesystem residue does the shellcode leave?

If we run the program without creating anymore breakpoints after resolving ShellExecuteA, the program will complete and we’ll see what looks to be 2 files left on the system after completion.

It’s not yet known if there are any other artefacts we’ve missed, so we’ll run the program again using shellcode_launcher. This time we will step into the first call like normal; however, from there we will step over the next 2 calls which includes the one to resolve imported functions.

If we continue to use ‘F8’ to step over instructions, we will find ourself caught in a loop which is now being used to import all the resolved library functions.

By setting a breakpoint after this we can press F9 to skip this loop. Using ‘F8’ to step over instructions we quickly get to a call to ‘GetFileSize’ which is occurring in a loop each time increasing ESI by 4 (this is looping through open handles). This is then comparing the file size of the file specified by our open handle to the value at our data segment EBX+0x3c.

Stepping over this with F8 we can see that the value being searched in our data segment has to be 0xC602 bytes in size. If we examine the size of Lab19-03.pdf on disk, we can see that it is 50,690 bytes in size.

Converting the above to base 16 gives us this exact value, which leads us to believe this is looking for an open handle to the malicious PDF file hosting this shellcode.

One reason this handle search may be used is to fetch further payloads from data within the PDF itself. In this case it would reuse the current file handle instead of attempting to get a new one. Setting a breakpoint at the JNZ operation that occurs directly after this comparison allows us to use F9 to jump through this process. At this point we reach a call to GlobalAlloc which looks to be allocating bytes from the heap so that they can be used in memory. This is before parameters seem to be set prior to a function being called.

The allocation which occurs is at an offset of 0x44 within EBX, which in this case is within the PDF file we have a handle to. The function appears to be used to extract required data from this PDF, so we can step over all of this with ‘F8’. At this point we then make it to another call, this time to ‘GetTempPathA’.

This is the first sign that filesystem residue may be present as this is generally used to get a writeable temporary directory prior to dropping a file. Pressing F8 we can see EDI contains our temporary directory.

Continuing to step over this we can see that the temporary string is now concatenated with ‘foo.exe’.

Stepping over the next call we will now be able to see that this file has been written to %TEMP%\foo.exe. this is our first file system residue.

If we continue stepping over with F8 we will find that foo.exe starts; however, there’s another call to the same function which just wrote foo.exe. This means there’s likely another system artefact about to drop. Shortly before this is called we can see EDI being modified to be ‘bar.pdf’.

Moving past this we can see that bar.pdf is now dropped to disk at %TEMP%\bar.pdf.

Shortly after this our shellcode completes. This proves that only the below system residue is left by this shellcode.

• %TEMP%\foo.exe
• %TEMP%\bar.pdf

Question 5

What does the shellcode do?

From the above analysis we can conclude that the shellcode is designed to extract 2 files from within the malicious PDF and write these into the users temp directory before opening both files using the existing handler to Lab19-03.pdf.

This concludes chapter 19.

Chapter 20. C++ Analysis

Object-Oriented:

• C++ is an object-oriented programming language.
• C++ has objects which can contain both data and functions.
• Functions in C++ are similar to C programs except they can extend and be associated with an object or object class.
• Functions in C++ are often called methods.
• Classes are like structs except they can store function information and data.
• Classes are similar to a blueprint or foundation for creating an object.
• An object is an instance of a class.
• Multiple objects can be created from a class, all with unique data, except they share the same methods.
• Accessing data and functions require you to reference an object of a particular type.

The ‘this’ pointer:

• Variables and functions can be accessed using the object name + the variable name.
• e.g. CustomObject.var = 0;
• e.g. CustomObject.function();
• Variables and functions can also be accessed using just the variable name if called from within the definition of a class.
• e.g. var = 0;
• e.g. function();
• When accessed from within the definition of a class, the location in memory storing this variable will vary between objects as each object has its own memory addresses.
• The ‘this’ pointer keeps track of mapping memory addresses to variables.
• The ‘this’ pointer is implied whenever a variable is accessed within a function where an object wasn’t specified.
• ECX and sometimes ESI are used by Microsoft Assembly to pass the ‘this’ parameter.

• ‘Method overloading’ is supported in C++ and means to have multiple functions with the same name, but with a different set of parameters being passed.
• C++ uses ‘name mangling’.
• In a PE file format each function only has its name as a label.
• Because this would cause labels to clash, the names in a PE file format are modified so that the name includes parameter information.
• e.g. A function called ‘Function’ as part of a class called ‘Class’ which includes 2 integers as parameter items would look like ‘[email protected]@@[email protected]
• IDA can demangle this, but only if symbols are present, and these are often removed by malware authors.

Inheritance and Function Overriding:

• Child classes inherit functions and data from parent classes.
• Generally isn’t visible in assembly.

Virtual and Non-Virtual Functions

• You can override a Virtual Function by a subclass.
• Virtual Function execution is determined at runtime.
• A child class with the same named function overrides the parent function.
• Non-virtual functions instead determine execution at compile time.
• A child class with the same named function does not override the parent function.
• The above functionality differences is commonly known as polymorphism as they share a common interface but perform different functions.

Use of Vtables:

• When C++ compiles, data structures called Virtual Function Tables or vtables are added to support Virtual Functions.
• These are arrays to function pointers.
• Each class using a Virtual Function has its own vtable.
• Each Virtual Function in a class is included in the vtable.
• Biggest issue is that a Virtual function call doesn’t show the target for a ‘call’ instruction.
• Non-virtual Function call may look like ‘call sub_<address>’
• Virtual function call would look like ‘call eax’
• First 4 bytes of an object are a pointer to the vtable.
• First 4-byte entry of a vtable is a pointer to the code for the first Virtual Function.
• To find the location of a Virtual Function call, you must find where a vtable is accessed and its offset, and then you must find the vtable in memory.

Recognising a Vtable:

• A vtable looks like an array of function pointers.
• Only the first value in a vtable should have a cross-reference with other being accessed via their offset.
• Virtual functions are not directly called by other parts of the code, so cross-references to them should not contain a ‘call’ instruction, but rather be referenced as an offset.
• All functions within a vtable table belong to the same class and are somehow related.
• If 2 classes point to the same offset you can infer an inheritence relationship.
• If one vtable is larger than the other it is a subclass.

Creating and Destroying Objects:

• When an object is created the ‘constructor’ function is called.
• This performs initialisation.
• Objects can be stored on the heap or stack.
• When not stored on the stack, memory allocation needs to occur. This happens with the ‘new’ operator which is of interest.
• New operators can often have an unusual function name such as ‘[email protected]@Z’.
• When an object is destroyed the ‘destructor’ function is called.
• This is automatically called if objects go out of scope.
• Can complicate disassembly due to exception handlers being added.

Lab 20-01

The purpose of this first lab is to demonstrate the usage of the this pointer. Analyze the malware in Lab20-01.exe.

Question 1

Does the function at 0x401040 take any parameters?

If we examine the main function of ‘Lab20-01.exe’ (C++ executable) in IDA, we see that this doesm’t take any parameters; however, it does take a ‘this’ pointer. By doing this it knows that the function it will be running is for the created object.

One way to identify this is the lack of clear structure being passed, strange duplication of references being stored prior to it, and the result being stored in our ‘ecx’ register. This is in addition to a URL being moved into our newly created object reference.

Question 2

At a glance we can see the below URL being moved into ‘dword ptr [ecx]’.

• http://www.practicalmalwareanalysis.com/cpp.html

Based on this we know that the URL http://www.practicalmalwareanalysis.com/cpp.html is being stored at the start of our newly created object. By examining ‘sub_401040’, we can see that the object passed in our ‘this’ pointer is being stored in [ebp+var_4].

This is then being referenced, and the start of our object is being accessed as the LPCSTR entry passed to URLDownloadToFile. In this case it is the URL and FileName respectively which is pushed to the calling object stack shortly before execution.

This in turn confirms the URL and FileName used by the call to URLDownloadToFile.

Question 3

What does this program do?

The program is contained solely within what we’ve discussed in the previous 2 questions. From what we’ve seen, this program will download a file from http://www.practicalmalwareanalysis.com/cpp.html and save it on the local machine to a file called c:\tempdownload.exe.

Lab 20-02

The purpose of this second lab is to demonstrate virtual functions. Analyze the malware in Lab20-02.exe. This program is not dangerous to your computer, but it will try to upload possibly sensitive files from your machine.

Question 1

What can you learn from the interesting strings in this program?

If we run strings over this executable, we can see a number of interesting entries, including what looks to be evidence this is made using C++, possible imports associated with network connections and FTP operations, and strings that indicate the program likely functions as an FTP client which is looking for .doc and .pdf files to send back to ftp.practicalmalwareanalysis.com.

strings Lab20-02.exe


Question 2

Opening this in PE-bear, we can see that this is importing functions from WININET.dll which look to be associated with FTP operations. This leads us to believe the program will function as a FTP client, further backing up our hypothesis from question 1.

Examining the imports from KERNEL32.dll we also see what looks to be API calls associated with finding files which match a certain parameter on a system.

Based on these imports it looks like this program will search for files on a system, and at some stage send them to a remote FTP server.

Question 3

What is the purpose of the object created at 0x4011D9? Does it have any virtual functions?

If we examine 0x4011D9, we can see that this occurs directly after a comparison which looks to be searching for a .doc file. We can also see checks on one branch which may be looking for a .pdf file.

Of interest in the above is that after an object is created, for what looks to be a .doc file being found, there are 2 sets of ‘mov’ operations occurring directly after one another.

This looks to first create an object and store a reference to it into [ebp+var_15C]. This is then stored in a pointer to [edx] and [eax]. Immediately after this we see what looks to be a virtual function table ‘offset off_4060DC’ being written to the object’s first offset. If we examine cross-references to ‘off_4060DC’, we can see that this looks to be a virtual function given it is only referenced by an offset rather than a ‘call’ instruction.

Based on this it appears that the purpose of this object is to act as a reference to a ‘.doc’ file which has been found. Looking back at assembly operations performed prior to these operations shows calls to functions which help to back up this hypothesis. These back up our hypothesis given the malware would need to find a file before creating an object as a reference to the file.

Question 4

Which functions could possibly be called by the call [edx] instruction at 0x401349?

Taking a look at the call [edx] instruction at ‘0x401349’, we can see that 3 possible objects are being created. The 3 objects being created are for a PDF file, DOC file, and a file that is neither of these being found on disk. From here we see evidence of Virtual Function Tables being setup, until all the references to a created object merge into a single reference to ‘[ebp+var_148]’.

Taking a step back, what we’re really interested in is the possible virtual functions that different objects would call, which in this case is at ‘off_4060DC’, ‘off_4060D8’, and ‘off_4060E0’ (remember that these all point to the first function in the virtual function table for our created objects).

If we take a look at what these offsets point to, we can see that they point to

• sub_401380
• sub_401440
• [email protected]@@[email protected]’ (Name mangling has occurred. This tells us the original class was ‘std’ with a function name of ‘_Init_locks’. A quick search reveals this is likely an inbuilt C++ function used for creating a lock on an object when it is created)

If we examine sub_401380, we can see that this looks to be establishing a new connection to a remote FTP server and attempting to place a found PDF file into a ‘pdfs’ directory.

If we examine sub_401440, we can see that this looks to be establishing a new connection to a remote FTP server and attempting to place a found DOC file into a ‘docs’ directory.

Based on this we know what functions could be called by the call [edx] instruction at 0x401349.

Question 5

How could you easily set up the server that this malware expects in order to fully analyze the malware without connecting it to the Internet?

Given we know that this is expecting an FTP server to be present at ftp.practicalmalwareanalysis.com for exfiltration, we can setup a local ftp server using software such as XAMPP or FileZilla and then redirect any calls for that domain to our local host like we’ve done in previous labs.

Note: This was designed to run against a Windows XP OS, and as such running this on other operating systems appears to fail.

We know based on what was found in question 4 that this doesn’t look to be authenticating to the ftp server in question. Due to this we will first need to enable an ‘anonymous’ user account on our FTP server and ensure it doesn’t require a password. In addition we will need to configure the home directory where captured files will be sent.

After doing this we can fire up ApateDNS, our FTP Server, and logon to the admin interface of our FTP server to track what is being sent to it. By running the program we can see DNS requests being made which are redirected to our own host. From here the program begins to establish a FTP connection, store the file found, and then disconnects from the FTP server causing a number of connections to occur.

This also highlights that the malware is attempting to store each type of file found in a folder called ‘docs’ or ‘pdfs’ depending on the extension being exfiltrated. This backs up what we found in our previous analysis.

By performing these actions, we are able to fully analyse the malware without connecting it to the internet.

Question 6

What is the purpose of this program?

The purpose of this program is to find .pdf and .doc files on your system and exfiltrate these to a remote FTP server at ftp.practicalmalwareanalysis.com.

Question 7

What is the purpose of implementing a virtual function call in this program?

By implementing virtual functions the program is able to perform different actions depending on the object file extension found on the host. In this case the different functions were to specify what directory exfiltrated files would be stored in.

Lab 20-03

This third lab is a longer and more realistic piece of malware. This lab comes with a configuration file named config.dat that must be in the same directory as the lab in order to execute properly. Analyze the malware in Lab20-03.exe

Question 1

What can you learn from the interesting strings in this program?

By running strings against this binary we can begin to infer what it may be used for and what functionality it may have.

strings Lab20-03.exe


First off we see it is likely written in C++ and can present a message popup to the user.

Next up we see what looks to be a number of imported APIs giving this the ability to read files, create files, get access to the user context it is running under, make network connections, terminate itself, understand what process it is running under, and load further libraries.

Finally we can see that this looks to perform some Base64-encoding or decoding functions, potentially using a custom index_string, we see reference to remote URIs, a reference to original C++ clases being labelled as a ‘BackdoorClient’ in addition to ‘Polling’ and ‘Beacon’ strings. Further to this we can see this program looks to gather Host/User information, has the ability to upload and download files, the ability to create arbitrary processes, and can make GET/POST requests.

Immediately we begin to believe this is some sort of information gathering remote access tool/trojan which provides the ability to exfiltrate files and run commands on a system.

Question 2

Opening this in the latest available version of pestudio (in this case 9.09), we can see that a number of imports are already down as ‘blacklisted’, in addition to some deprecated APIs being used by the program.

Of interest is that we can see this has the ability to make network connections, execute processes, and sleep, all of which would be pretty common functions for a remote access tool/trojan which leveraged the sleep API call to allow checking into the C2 periodically.

Question 3

The function 0x4036F0 is called multiple times and each time it takes the string Config error, followed a few instructions later by a call to CxxThrowException. Does the function take any parameters other than the string? Does the function return anything? What can you tell about this function from the context in which it’s used?

If we first examing cross-references to 0x4036F0, we can see that it is called 5 times throughout this program.

Looking at where these are called we can see they all take place inside of ‘sub_403180’. An example of this is shown below.

To get a bit more of an idea what is being passed to the function, we can examine cross-references to sub_403180 to see if anything is passed to this subroutine. Immediately we see an ‘sub_401EE0’ object being created and the object’s ‘this’ pointer being stored into ecx.

Based on this we know that the function 0x4036F0 doesn’t take any parameters other than the Config error string. Taking a look we can see that this same object (which we’re beginning to believe is part of an exception object) is used as a parameter to the CxxThrowException function.

If we examine what’s contained within ‘sub_4036F0’, we find evidence that this is likely setting up an exception to be raised.

Based on all of this context, and by examining the patterns which occur right before 0x4036F0 is called, we can infer that these are all exception objects which raise an exception if the specified config.dat file doesn’t exist or is invalid.

Question 4

What do the six entries in the switch table at 0x4025C8 do?

If we jump to 0x4025C8 we find the six entries in the switch table which are referenced at 0x40252A.

If we follow this reference, we can see that this is triggered by a reference at 0x402500.

If we continue tracking back what kicks this off, we can find at ‘loc_402410’ there’s a cross-reference to an offset within ‘sub_403BE0’. This is ultimately what kicks off any one of these switches to occur.

If we were to look at what calls this, we’d find it is the only call within our _main method which is kicked off shortly after the program ‘start’ method runs. Of interest in the above is that we can see a looping function and a call to ‘sleep’. Right before this happens there’s a call to ‘sub_401F80’ which we’ll examine further.

In the above we find 5 calls to subroutines to examine further.

• sub_403D50

Based on the above User-Agent string and API calls, we can assume this plays the role of establishing a connection to the C2.

• sub_402FF0

Based on the above strings and API calls, we can assume this plays the role of gathering initial system information to send back to the C2.

• sub_404ED0

This subroutine has a number of subroutines which are called; however, at a glance we can see that this is likely playing the role of posting the gathered data back to the C2, or making a GET request to it.

• sub_404B10

Based on the above strings and errors being called, we can assume this is receving the response to our request and checking to see if it matches an expected valid HTTP response.

• sub_4015C0

Based on the above strings and what looks to be Base64 index_strings, we can assume this is Base64-encoding or decoding the response received from the C2 server.

At this point we have a good idea of what actions the Beacon will take prior to ‘loc_402410’ inevitably calling the switch table at 0x4025C8. We also know that the six entries in this switch table are likely six different actions to take based on the response received from the C2.

To find out what each of the switch entries does we can investigate them further.

• loc_402561

This is case 0x61, and from the above we can see that this looks to delete the object which called it, but nothing else.

• loc_402531

This is case 0x62, and from the above we can see that this calls ‘sub_4025E0’ before executing case 0x61. Examining sub_4025E0 we can see that this looks to call atoi used in parsing a string into a number before this is passed to a ‘sleep’ API call.

This tells us that case 0x62 is likely designed to notify the beacon to sleep for a certain amount of time before checking back in for new commands.

• loc_402559

This is case 0x63, and from the above we can see that this calls ‘sub_402F80’ before flowing into and executing case 0x61. Examining ‘sub_402F80’ we don’t find much besides another call to ‘sub_402EF0’. By looking at sub_402EF0, we can see that this looks to call CreateProcessA in order to run a command sent to it.

This tells us that case 0x63 is likely designed to start a process sent down from the C2 thus executing a command tasked to the beacon.

• loc_40253B

This is case 0x64, and from the above we can see that this calls ‘sub_402BA0’ before executing case 0x61. Examining ‘sub_402BA0’ we can see that it calls ‘sub_402A20’ with some parameters including ‘lpFileName’. If we look into what ‘sub_402A20’ is doing we see some familiar calls associated with connecting to the C2 and checking the response is valid.

This tells us that case 0x64 is likely designed to download a file from the C2.

• loc_402545

This is case 0x65, and from the above we can see that this calls ‘sub_402C70’ before executing case 0x61. Examining ‘sub_402C70’ we can see that it calls ‘sub_4027E0’. If we look into what ‘sub_4027E0’ is doing we can see a call to CreateFileA which in this instance looks to be getting a handle on a file before its bytes are read in a looping function and it is uploaded to the C2.

This tells us that case 0x65 is likely designed to upload a file to the C2.

• loc_40254F

This is case 0x66, and from the above we can see that this calls ‘sub_402D30’ before executing case 0x61. Examining ‘sub_402D30’ we find that this looks to be gathering information about the machine it is being run on which will be sent back to the C2.

This tells us that case 0x66 is likely designed to profile a system and send the information back to the C2.

Question 5

What is the purpose of this program?

If we view ‘sub_401EE0’ which is run after taking the config.dat file as a parameter.

We can see this is once again creating an exception object, in addition to specifying the resources which are present for commands to be retrieved from the C2.

We also know that this sends a beacon to the C2 and has a number of operations which could occur based on the C2 server response including:

• Notifying the beacon to sleep for a specified number of seconds.
• Notifying the beacon to start an arbitrary process.
• Notifying the beacon to upload a file to the C2.
• Notifying the beacon to profile a system and send the information back to the C2.

Combining this with the above analysis in questions 1-4, we can conclude that this is a remote access trojan/tool which uses a config file which is encoded on disk to connect to its associated C2.

This concludes chapter 20.

Chapter 21. 64-Bit Malware

Various Implementations:

• x64 or x86-64 (previously known as EM64T) is the most popular implementation of 64-bit code on Windows (Intel).
• Other implementations include AMD64 which was one of the first 64-bit code implementations on Windows (AMD).

Supported OS:

• The vast majority of currently supported Windows versions are available in 32-bit and 64-bit versions.
• 64-bit operating systems support both 64-bit and 32-bit programs.
• Not all debugging, decompiling, or disassembling tools will support 64-bit programs.

Reasons for Compiling 64-bit Malware:

• 32-bit code cannot be run inside 64-bit applications or vice versa.
• Any kernel drivers or kernel code must be compiled for the same type of OS it is running under (e.g. 32-bit OS needs to be compiled as 32-bit, 64-bit OS needs to be compiled as 64-bit).
• Any plug-ins, shared libraries, injected DLLs or other code which is running within a process needs to be the same as the process it is running within. For example an executable compiled as 64-bit will require 64-bit code to properly run within it.
• Further to the above, this extends to shellcode which may be used. The shellcode needs to be written specifically for the same process it is intended to be run within (32-bit for 32-bit, 64-bit for 64-bit).

Differences in x64 Architecture:

In x64 Architectures the following differences apply when compared to x86:

• General purpose registers have grown in size and have had the first character ‘E’ replaced with ‘R’, with the 32-bit registers still being available. For example RBX is the 64-bit version of EBX.
• All pointers and addresses are 64-bits.
• RDI, RSI, RBP, and RSP general purpose registers now have byte support by adding ‘L’ to allow the lowest 8-bits. For example if we are discussing ‘RDI’, DIL accesses the lowest 8-bits, DI accesses the lowest 16-bits, EDI accesses the lowest 32-bits, and RDI accesses the full 64-bits.
• Special purpose registers such as the Instruction Pointer have been renamed similar to general purpose registers. For example RIP is the 64-bit instruction pointer which used to be EIP on a 32-bit system.
• There’s twice as many general purpose registers. These are labeled R8 to R15 (QWORD). 32-bit versions can be accessed as R8D to R15D (DWORD). 16-bit versions can be accessed as R8W to R15W (WORD). 8-bit versions can be accessed as R8L to R15L.
• More registers can be found by revisiting Chapter 4 (A Crash Course in x86 Disassembly).
• 64-bit code supports RIP-relative addressing or Instruction pointer-relative addressing. This means data can be accessed based on an offset from the current instruction pointer, whereas in 32-bit it requires absolute addressing if it is not data at an offset to a register.
• This is most applicable to Position-Independent Code (PIC) and shellcode discussed in earlier chapters.
• This may not appear different in something such as IDA (as the disassembler has done the work of automatically resolving this) but it is shown when examining raw opcodes used. The raw opcode doesn’t contain the address specified, but rather an offset to the current instruction pointer.

Differences in the x64 Calling Convention and Stack:

Note: These general rules apply to anything a compiler has generated. There may be cases where these aren’t followed if hand-crafted assembly has been used.

• 64-bit calling process is similar to ‘fastcall’ mentioned in Chapter 6. The first 4 parameters of any given call are passed in RCX, RDX, R8, and R9 registers with additional ones stored on the stack.
• In 32-bit pop/push instructions can be used to allocate space on the stack at any time during a function. In 64-bit, functions cannot allocate space on the stack in the middle of their function. Put simply, the stack only grows at the start of the function and stays the same throughout the entire function.
• 64-bit exception handlers require this to be followed. Not following this can cause a crash if an exception occurs.
• There’s no easy way to tell if a register was populated before a function for the purpose of it being passed to the function, or for another reason.

Leaf and Nonleaf Functions:

• 64-bit stack has leaf and nonleaf functions.
• A function which calls another function is called a nonleaf function (sometimes called a frame function).
• All other functions are leaf functions.
• Nonleaf functions need to allocate 0x20 bytes of space on the stack whenever a function is called as this is used to store RCX, RDX, R8, and R9 in that space if required.
• If more than 0x20 is allocated we know there are local stack variables in play.

Prologue and Epilogue 64-bit Code:

• Windows 64-bit assembly code has a ‘prologue’ and ‘epilogue’ at the beginning and end of a function respectively.
• Any ‘mov’ instructions at the start of a ‘prologue’ are storing parameters passed to the function.

64-bit Exception Handling:

• Structured exception handlers don’t use the stack in x64 like they do in x86.
• In x86 they are often accessed via a pointer to fs:[0].
• In x64 these are coded into the PE file itself.
• The .pdata section contains a _IMAGE_RUNTIME_FUNCTION_ENTRY structure for every function which stores the start and end of that function, in addition to a pointer for their associated exception-handlers.

Windows 32-bit Run on a 64-bit OS:

• Subsystem exists on 64-bit operating systems called WOW64 which is used to allow 32-bit code to run on the 64-bit OS.
• WOW64 uses 32-bit mode of x64 processors.
• WOW64 needs extra work-arounds to support the registry and file system.
• ‘SYSTEMROOT’ is generally accessed to locate required DLLs by programs (usually \Windows\System32 on your drive). A separate location is required to support 32-bit DLLs (usually \Windows\SysWOW64 on your drive).
• The reason WOW64 hosts 32-bit binaries, and System32 hosts 64-bit binaries, is for compatibility reasons due to System32 being the default location throughout Windows.
• On a 64-bit OS if a 32-bit binary is run, the OS will automatically redirect all requests for the System32 directory to SysWOW64.
• On a 64-bit OS if a 32-bit binary is run, the OS will automatically redirect all requests for the registry key HKEY_LOCAL_MACHINE\Software to HKEY_LOCAL_MACHINE\Software\Wow6432Node.
• A 32-bit binary can still access \Windows\Sysnative and be redirected to \Windows\System32.
• The ‘IsWow64Process’ function can be used to determine if code is running in a 64-bit process.
• The ‘Wow64DisableWow64FsRedirection’ function can be used to disable OS redirections in the current process thread.
• API calls to registry functions such as ‘RegCreateKeyEx’, ‘RegOpenKeyEx’, and ‘RegDeleteKeyEx’ also now have a flag to specify if it should access the 32-bit or 64-bit version of the registry.

64-bit Clues on Malware Functionality:

Note: This applies to anything a compiler has generated. There may be cases where these aren’t followed if hand-crafted assembly has been used.

• When examining x64 code it’s easier to determine if something is a pointer.
• This is because all new pointers must be 64-bits, and as such must be in ‘R’ based registers.
• If something is being moved into a 32-bit register such as ECX, it is not a pointer.
• If something is being moved into a 64-bit register such as RCX, it is potentially a pointer. An exception would be if a QWORD variable has been defined, but most developers would likely not need a variable that large and would instead opt to use a DWORD (32-bit) variable.

Lab 21-01

Analyze the code in Lab21-01.exe. This lab is similar to Lab 9-2, but tweaked and compiled for a 64-bit system.

Question 1

What happens when you run this program without any parameters?

If we attempt to run this in a x86 (32-bit) OS, we’re presented with an error message that it is not compatible with this version of windows as it has been compiled for a 64-bit OS.

Attempting to run this in a 64-bit OS with a tool such as procmon running reveals that it simply exits and doesn’t do anything of interest. A number of events are still shown based on registry keys queried and files loaded, as part of normal process execution, but nothing stands out as interesting.

Question 2

Depending on your version of IDA Pro, main may not be recognized automatically. How can you identify the call to the main function?

If we open this in IDA Free 7.0 as a standard AMD64 PE file…

We find that we’re dumped into the main function located at 0x1400010C0.

If we instead open this in another disassembler which doesn’t identify the main function, in this case we’ll open it in Cutter, if we enable offset visibility in Cutter preferences, we can see we start at 0x140001750.

To identify the call to our main function we will need to look for a call, likely after any ‘GetCommandLineA’ checks which may be present. If we examine the underlying structure of this PE file using Detect-It-Easy (DIE), we can see it was created in C++.

If we examine what a main function would look like in C++ using the C++ language reference, we find that it must pass ‘argc’, ‘argv’, and ‘envp’ if it is passing environment variables.

Due to this we know that any call to the main function would need to take 3 parameters, 2 of these being envp and argv, and another which is an integer. If we continue to examine our disassembly, we only find one call to function 0x1400010C0 which takes 3 parameters.

In this instance ecx is our integer, because we know it is a 32-bit register being accessed, common amongst integer declarations, and 2 other 64-bit register declarations, RDX, and R8. If we examine this same function in IDA Free 7.0, we can see these have been identified as envp, argv, and argc, in addition to the main function being labelled.

Question 3

What is being stored on the stack in the instructions from 0x0000000140001150 to 0x0000000140001161?

If we jump to ‘0x140001150’, we can see that some large hexadecimal values are being stored on the stack.

If we press ‘R’ on these to convert them to an ASCII string, we find the following.

At first glance it looks like the string ‘.lcoexe’ is being stored on the stack; however, this is because x86 and x64 assembly is little-endian (reversed). As IDA has interpreted this as a hex value rather than a string, converting it results in backwards values. If we reverse this we find the following string stored on the stack.

ocl.exe


This is the same value we saw in Lab09-02. Given this, it’s possible the program needs to be called ocl.exe in order for it to run correctly.

Question 4

How can you get this program to run its payload without changing the filename of the executable?

If we examine 0x14000120C we can see that a string comparison looks to take place which is likely looking for very specific conditions to be met to allow the malware to run (possibly checking if it is named ocl.exe).

When this comparison fails, the program makes a jump to 0x14000120E, which then makes a jump past the primary functions of this malware at 0x140001213, to loc_1400013D7.

One way we can make this program run its payload without changing the filename is to ensure that even after it fails this check, instead of jumping to loc_1400013D7, it flows right into the primary function which triggers the payload.

If we run this in a debugger such as x64dbg (at this point we’re introducing a newer, more robust debugger which supports 64-bit debugging), we can find the jump located at 0x140001213.

From here it can be modified to instead perform no operation, effectively allowing the program to flow into its payload.

If we set a breakpoint at our new NOP values, we can use F9 to run the program and see it hits them without issue. If we then hold F8 to step over functions, we will begin to see a decoding routine runs which gives us a known C2.

At this point we can be confident that the check used to determine if the filename of the executable is correct has been bypassed.

Question 5

Which two strings are being compared by the call to strncmp at 0x0000000140001205?

Using x64dbg we can easily create a breakpoint at 0x140001205 and see the two strings being compared stored in RCX and RDX. After setting a breakpoint and pressing F9, to run the program until we hit it, we can see the values being compared are the binary name (Lab21-01.exe) and the string jzm.exe.

Based on this we know that some transformations must be occurring on the string ocl.exe before being used in this comparison.

Question 6

Does the function at 0x00000001400013C8 take any parameters?

Jumping to the function at 0x1400013C8, it isn’t immediately obvious in IDA or x64dbg how many parameters it takes, but what we do see is RBX being moved into RCX.

Because we know RCX, RDX, R8, and R9 are the first 4 parameters of any given function call in a 64-bit OS, we know that whatever is within RBX at the time of this call will be passed to the function at 0x1400013C8 (sub_140001000). By looking at what is being passed to this in IDA prior to the call, we can see that it is RAX, or more specifically a pointer to the socket returned by WSASocketA.

By viewing the start of sub_140001000 in IDA we can also see that rcx is being stored back into rbx which is then being used for the standard input, output, and error destination meaning that all output will be redirected to this socket.

Based on this we know that the function at 0x1400013C8 takes 1 parameter, the socket to our C2.

Question 7

How many arguments are passed to the call to CreateProcess at 0x0000000140001093? How do you know?

It’s not immediately clear how many arguments are passed to the call to CreateProcessA at 0x140001093.

Given IDA has identified this as CreateProcessA though, we can double click on it and see how many arguments are expected to be passed to this call.

In this case we can see there are 10 arguments which are expected to be passed to it.

• lpApplicationName
• lpCommandLine
• lpProcessAttributes
• bInheritHandles
• dwCreationFlags
• lpEnvironment
• lpCurrentDirectory
• lpStartupInfo
• lpProcessInformation

Because this is documented, we know that these 10 arguments need to be passed to CreateProcessA

Lab 21-02

Analyze the malware found in Lab21-02.exe on both x86 and x64 virtual machines. This malware is similar to Lab12-01.exe, with an added x64 component.

Question 1

What is interesting about the malware’s resource sections?

Because we know this malware is similar to Lab12-01.exe, we can compare the malware’s resource sections to that of Lab12-01.exe and see if there’s any noticable differences. By opening both of these in pestudio, we can see that Lab21-02.exe has an added section called .rsrc and a number of extra imports and strings.

The added section is a resource section, and if we examine what is contained within it, we can see three interesting binaries named x64, x64DLL, and x86.

Although this malware is similar to Lab12-01.exe, we’re not entirely sure how similar it is. To do this we should look at similarities between our sample ‘Lab12-01.exe’ and ‘Lab21-02.exe’. We can utilise a disassembler plugin such as BinDiff to get this information at a glance. This requires a disassembled binary be present from either a paid pro version of IDA, or the free alternative Ghidra.

If we want to install this plugin into Ghidra, we first must install it on our OS from the provided msi file. From here we can run Ghidra and click File > Install Extensions.

The extension we need to install is ghidra_BinExport.zip as shown below.

After installing this, we need to restart Ghidra and disassemble both Lab12-01.exe, and Lab21-02.exe. We should also set these to automatically analyze the selected binary.

Once analysis is complete we can use File > Export, and select ‘Binary BinExport for BinDiff’.

Once this is complete for both our binaries, we can compare the 2 BinExport files using BinDiff. We will need to first setup a workspace.

From here we can compare our 2 BinDiff exports.

The end result is a number of graphs and functions we can drill down into and see what has changed, and in fact a lot has changed between these 2 binaries.

Question 2

Is this malware compiled for x64 or x86?

Using our BinDiff above we have a graph which tells us what this malware is compiled for.

• x86-32 (32-bit)

We can also use a number of other tools such as peview, PE-bear, pestudio or DIE to get the same information as this is stored in the File Header.

Question 3

How does the malware determine the type of environment in which it is running?

Comparing this to Lab12-01.exe, our previous analysis revealed that the main method contains a number of checks and operations before the main functionality begins. If we go to the start of the program we may see evidence of analysis failure.

In this instance it’s not a big issue and we can safely ignore that. Scrolling down in IDA, we know that any checks to determine what type of environment it is running in is likely to occur after a call to ‘GetCommandLineA’. We soon find this call, and 5 subsequent calls to examine of interest.

One thing to note is that 3 of these look to directly lead to sub_4017D0 which seems to prematurely throw an error and terminate the malware. One of these calls looks more interesting than the others though which is ‘sub_401260’. If we examine this we can see a reference to ‘IsWow64Process’.

In the above we see the malware is attempting to resolve the location of the ‘IsWow64Process’ export within Kernel32.dll. Where this is found it will then get its own process ID and execute IsWow64Process which has dynamically been resolved (dword_40A7A8).

From this we can tell the malware attempts to resolve and call ‘IsWow64Process’ to determine if it is running on a 64-bit or 32-bit OS.

Question 4

What does this malware do differently in an x64 environment versus an x86 environment?

If we examine code flow after the check for ‘IsWow64Process’, depending on whether or not this returned true or false in [ebp+var_10], a different number of actions will be taken.

If it returns true, then the malware assumes it is running in an x64 (64-bit) environment. This is due to it being compiled for an x86 (32-bit) environment and needing to be run under WOW64 when executing on a 64-bit OS.

64-bit (x64 Actions):

If we examine the 64-bit case at a glance, we can see the following actions taken:

First we see 2 calls to ‘sub_401000’ which is associated with getting 2 different files from the binary resource section and saving them to disk, these binaries are then saved as ‘Lab21-02x.exe’ and ‘Lab21-02x.dll’ before Lab21-02x.exe is launched and the program terminates.

32-bit (x86 Actions):

If we examine the 32-bit case at a glance, we can see the following actions taken:

First we see a call to ‘sub_401000’ which is once again associated with getting a file from the binary resource section and saving it to disk (Lab21-02.dll). From here we then see the malware allocating the extracted DLL into a buffer for later use, and attempting to grant itself Debug Privileges. From here it then opens a handle to a process with the name ‘explorer.exe’.

Looking further at the malware, we can see that after getting a handle to a process with the name explorer.exe, it will attempt to open the process, allocate memory, write the dropped DLL into that process memory, and then create a remote thread to run and execute the injected DLL.

Based on this we know that the malware will attempt to run one of the dropped binaries in a x64 environment, whereas a x86 environment it will attempt to inject the dropped binary into a process called explorer.exe.

Question 5

Which files does the malware drop when running on an x86 machine? Where would you find the file or files?

From the above analysis we know that the file dropped when run on on x86 machine will be ‘Lab21-02.dll’. Using Procmon and running the binary on an x86 system we can see this attempting to be written. In this case we haven’t run the malware as an administrator so it is unable to write the file.

This shows us that the file Lab21-02.dll is dropped to C:\Windows\System32\Lab21-02.dll when run on an x86 machine.

Question 6

Which files does the malware drop when running on an x64 machine? Where would you find the file or files?

From the analysis in question 4 we know that the file dropped when run on on x64 machine will be ‘Lab21-02x.exe’ and ‘Lab21-02x.dll’. Using Procmon and running the binary on an x64 system we can see this attempting to be written. In this case we haven’t run the malware as an administrator so it is unable to write the file.

This shows us that the files Lab21-02x.exe and Lab21-02x.dll are dropped to C:\Windows\SysWOW64\Lab21-02x.exe and C:\Windows\SysWOW64\Lab21-02x.dll when run on an x64 machine.

If we take a closer look at ‘sub_401000’ which performs the file dropping on both an x64 and x86 OS, we can see how this happens.

In both cases a call is made to ‘GetSystemDirectoryA’ which should return C:\Windows\System32\; however, because this is a 32-bit binary being run on a 64-bit OS, the OS instinctively sets up a redirect to C:\Windows\SysWOW64. This is done because the SysWOW64 directory contains necessary 32-bit compiled DLLs required to allow the operating system to run 32-bit binaries seemlessly.

Question 7

What type of process does the malware launch when run on an x64 system?

Based on our analysis in question 4 we know this is dropping and launching ‘Lab21-02x.exe’ on an x64 system. If we use the 32-bit debugger version of x64dbg (x32dbg), we can set a breakpoint before the process is started (for example 0x401381) and collect the dropped binaries from C:\Windows\SysWOW64.

From here we can close our debugger, terminate the process before it executes Lab21-02x.exe, and move these to the same directory as the other binaries we’re analysing. Opening both the DLL and EXE in pestudio reveals they don’t have the 32-bit flag set, and as such have been compiled specifically for a 64-bit OS.

From this we know that the malware launches a 64-bit process when run on a x64 system, after the initial 32-bit process is run to drop our 64-bit payloads.

Question 8

What does the malware do?

To fully answer this question we still need to understand what happens after Lab21-02x.exe is executed, and what the payload of Lab21-02.dll is which is injected into explorer.exe. Starting with Lab21-02.dll, we can first extract this by repeating the process we took in the above question except we need to perform this on a 32-bit OS, and set a breakpoint at a different location (for example 0x401454) which occurs on the x86 path.

We know that this is similar to Lab12-01.exe which injected Lab12-01.dll into explorer.exe. If we compare the file hash of Lab12-01.dll and Lab21-02.dll, we can confirm that these are the exact same DLL.

In this instance the malware when run on an x86 system drops the required DLL which is identical to Lab12-01.dll and injects this into explorer.exe.

At this point we just need to confirm what the malware does once Lab21-02x.exe is executed. If we open this in IDA 7.0, we can see that it is attempting to get a handle on the dropped DLL file Lab21-02x.dll so it’s likely this is going to be used somewhere by a reference to [rsp+1168h+String1].

Shortly after this we see a call to ‘sub_140001090’ before ‘OpenProcess’ is called. Analysis of sub_140001090 reveals this is also looking for ‘explorer.exe’ as a process name to get a handle to.

Shortly after we see a familiar group of calls which indicate that Lab21-02x.dll (stored in [rsp+1168h+String1]) will be the buffer injected into explorer.exe.

At this point it’s beginning to look like this malware injects the same payload into explorer.exe on both 32-bit and 64-bit operating systems, except it sources that payload from different resources in the executable. To confirm this we need to examine Lab21-02x.dll which is being injected and see if it is similar to Lab21-02.dll (or Lab12-01.dll).

To do this we can open both of these in IDA and look at the StartAddress to see that Lab21-02.dll is identical only Lab21-02x.dll is compiled for a 64-bit OS.

From the above analysis we know that the malware first drops secondary payloads from its resource section, and that the resource section payload differs depending on if it is running in a 64-bit or 32-bit OS. On a 64-bit OS it will drop 2 binaries Lab21-02x.dll and Lab21-02x.exe, and then execute Lab21-02x.exe to inject Lab21-02x.dll into explorer.exe. On a 32-bit it will drop a Lab21-02.dll and inject this into explorer.exe. In both cases the injected DLL performs the same action as Lab12-01.dll which prompts the user to reboot with a message counting how many minutes have passed since it executed.

This concludes chapter 21.

Extra - YARA: Malware Identification

This section is independent of the PMA Labs. It contains resources to expand on malware analysis practices by creating Yara rules for detecting different variants or families of malware.

For those getting started Florian Roth has some excellent guides which is what we’ll be basing this section off of for simplicity and efficiency:

First we’ll look at using YarGen as a starting point. This is a Yara generation tool created by Florian Roth.

We download the latest release, extract it, open a terminal in this directory, and install requirements on our Linux OS of choice (in this scenario we’ve used Sift Workstation created by SANS). We’re also going to ensure we have pip (Pip Installs Packages) installed for python3.6 which as the name implies is used for managing packages used by python.

In the below example we’ve used explicitly python 3.6 to avoid some bugs present in python 3.5.

sudo python3.6 -m pip install --upgrade pip
sudo pip3.6 install -r requirements.txt


Next we’ll update the definitions of known goodware strings which is used to help avoid false positives in our created rules. This may take a bit of time.

python3.6 yarGen.py --update


Note: When attempting to run yarGen.py I experienced an issue with ‘etree’ being imported from lxml. A reinstall of the latest version of lxml at the time of wrtiting fixed the issue.

sudo pip3.6 install lxml==4.6.1


From here we’re able to start generating a Yara rule. A simple example of generating a rule for Chapter_1 binaries is shown below.

python3.6 yarGen.py -a "@CyberRaiju" -r "PMA Labs - Chapter 1" -m BinaryCollection/Chapter_1L/ -o PMA-Lab01.yar


Parameters used are below:

• a: set the author field.
• r: set the reference field.
• m: malware path (this must be a folder).
• o: output file for yara rule.

The end result is a staring Yara rule that we can then perform some ‘post-processing’ on. Some items of interest have been highlighted.

Obviously there’s some good indicators pulled from the binaries in question. What we need to do is look at defining specific strings (in this case they become ‘x’) which in themselves should be unique to this family of malware, and combined strings (in this case they become ‘s’) which may come up in other binaries, but the combination of them would be common across this malware.

• x: specific strings that can be used as an indicator by themselves.
• s: strings that may appear across multiple samples, but together would become an indicator.

Let’s see if we can get some hits with Yara. In this example we go and modify the rules for ‘Lab01-01.exe’, ‘Lab01-01.dll’, and ‘Lab01-04.exe’ while leaving the others as generated (post-processing is important, but we’re going to do this on a subset today). The aim is to remove some ‘noise’ strings that may have been included but hold no value to uniquely identifying this malware, change the conditions to suit what will cause a hit on this yara rule, and even create some more generic rules based on these strings.

After refining some of the rules they now look like the below. Areas have been highlighted where major modifications have occurred.

As you can see we’ve made some minor, but deliberate changes. From here we can place all the binaries provided as part of the PMA Labs into a folder called ‘All’ and see if we get any hits. We need to install Yara if we haven’t already.

sudo apt install yara
yara PMA-Lab01.yar BinaryCollection/All -s


This will run a standard yara scan across all binaries in the ‘BinaryCollection/All’ folder, and output the strings that matched.

Success. If you look carefully you can see that although we only had rules created for binaries in Lab01, we’ve successfully identified binaries with similar attributes at the below:

• BinaryCollection/All/Lab07-03.exe: Hit on Yara Rule - Lab01_01_2
• BinaryCollection/All/Lab18-02.exe: Hit on Yara Rule - Lab01_03
• BinaryCollection/All/Lab12-04.exe: Hit on Yara Rule - Lab01_04
• BinaryCollection/All/Lab07-03.dll: Hit on Yara Rule - Lab01_01

The results proved we didn’t mess anything up and the Yara rules worked. Of course if the binaries are the same, then of course our yara rules will match, so lets see whether this is the case.

sha256sum BinaryCollection/All/Lab01-01.exe;sha256sum BinaryCollection/All/Lab07-03.exe

sha256sum BinaryCollection/All/Lab01-03.exe;sha256sum BinaryCollection/All/Lab18-02.exe

sha256sum BinaryCollection/All/Lab01-04.exe;sha256sum BinaryCollection/All/Lab12-04.exe

sha256sum BinaryCollection/All/Lab01-01.dll;sha256sum BinaryCollection/All/Lab07-03.dll


The results of this show that 2 of the hits were for the same binary that had just been renamed, and two were from unique binaries that we’ve successfully determined have similar characteristics.

It’s entirely possible that these may be false positives which is why it’s useful to run them over a repository of clean binaries, luckily YarGen has already done a lot of this hard work for us. If we wanted to go a step further we could then use this to hunt for hits across a public malware repository such as Hybrid Analysis which is powered by MalQuery. This would help to confirm that our rule wasn’t overzealous in its detections.

Congratulations, you’ve just used the power of Yara with some assistance from yarGen to create your first Yara rule designed to detect malware used in Lab01 of PMA.

For those who are interested in the Yara rules created for closer analysis, they can be found here:

Tutorial Conclusion

This concludes my write-up of ‘Practical Malware Analysis’ by Michael Sikorski, and Andrew Honig, published by No Starch Press.

Although this has covered a lot, it really is still an introductory to reversing malware and binaries, and there’s so much that can be touched on. From unpacking modern protectors which have virtualisation included in the packer themselves, to malware which utilises direct syscalls, there’s always more tips and tricks which can be learnt.

If you’ve found this valuable or have any feedback, please feel free to let me know, share, or buy a coffee to show your gratitude.

Tags:

Categories:

Updated: