Debugging 64-bit Malware

Why 64-Bit Malware?

  • While you can run both 32-bit and 64-bit applications on the same system, you cannot run 32-bit code within 64-bit applications
  • When a processor is running 32-bit code, it is running in 32-bit mode, and you cannot run 64-bit code.
  • Therefore, anytime malware needs to run inside the process space of a 64-bit process, it must be 64-bit

Kernel Code

  • All kernel code for an OS is within a single memory space, and all kernel code running in a 64-bit OS must be 64-bit.
  • Because rootkits often run within the kernel, rootkits that target 64-bit OSs must be compiled into 64-bit machine code

Plug-ins and injected code

  • These must be 64-bit in order to run properly in a 64-bit process.
  • If the target process is 64-bit, the injected code must also be 64-bit

Shellcode

  • Shellcode is usually run as part of an exploit within the process that it is exploiting
  • In order to exploit a vulnerability in the 64-bit version of Internet Explorer, a malware author would need to write 64-bit shellcode.

Differences in x64 Architecture

  • All addresses and pointers are 64 bits.
  • x64 also supports "instruction pointer–relative data addressing"
  • This is an important difference between x64 and x86 in relation to PIC and shellcode.
  • Specifically, in x86 assembly, anytime you want to access data at a location that is not an offset from a register, the instruction must store the entire address. This is called "absolute addressing"
  • But in x64 assembly, you can access data at a location that is an offset from the current instruction pointer. The x64 literature refers to this as "RIP-relative addressing"
  • Instruction pointer–relative addressing is a powerful addition to the x64 instruction set that significantly decreases the number of addresses that must be relocated when a DLL is loaded.
  • Instruction pointer–relative addressing also makes it much easier to write shellcode because it eliminates the need to obtain a pointer to EIP in order to access data.
  • This addition also makes it more difficult to detect shellcode, because it eliminates the need for a call/pop as discussed in “Position-Independent Code”

Leaf and Nonleaf Functions

  • Any function that calls another function is called a "nonleaf function", and all other functions are "leaf functions"
  • Nonleaf functions are sometimes called "frame functions" because they require a stack frame.

Windows 32-Bit on Windows 64-Bit

  • Microsoft developed a subsystem called Windows 32-bit on Windows 64-bit (WOW64) in order to allow 32-bit applications to execute properly on a 64-bit machine. This subsystem has several features that can be used by malicious code
  • WOW64 uses the 32-bit mode of x64 processors in order to execute instructions, but workarounds are needed for the registry and filesystem.
  • 32-bit applications are normally unaware that they are running on WOW64, but a few mechanisms allow the applications to see outside the WOW64 environment.
  • The first is the "IsWow64Process function", which can be used by 32-bit applications to determine if they are running in a WOW64 process
  • The "Wow64DisableWow64FsRedirection" function disables filesystem redirection entirely for a given thread.
  • Registry functions such as "RegCreateKeyEx, RegDeleteKeyEx, and RegOpenKeyEx" have a new flag that can be used to specify that an application wants to access the 32-bit or 64-bit view of the registry, regardless of the type of application.

64-Bit Hints at Malware Functionality

  • Certain features in 64-bit code can provide additional clues to malware functionality that are not available in 32-bit code
  • It is typically easier in 64-bit code to differentiate between pointers and data values
  • It is not easy understand type or purpose of some functions of the parameters in 32-bit
  • However, in 64-bit assembly, additional information is present which in terms helps in identifying the purpose of instructions.