Daily Archives: December 1, 2020

Using Speakeasy Emulation Framework Programmatically to Unpack Malware

Andrew Davis recently announced the public release of his new Windows emulation framework named Speakeasy. While the introductory blog post focused on using Speakeasy as an automated malware sandbox of sorts, this entry will highlight another powerful use of the framework: automated malware unpacking. I will demonstrate, with code examples, how Speakeasy can be used programmatically to:

  • Bypass unsupported Windows APIs to continue emulation and unpacking
  • Save virtual addresses of dynamically allocated code using API hooks
  • Surgically direct execution to key areas of code using code hooks
  • Dump an unpacked PE from emulator memory and fix its section headers
  • Aid in reconstruction of import tables by querying Speakeasy for symbolic information

Initial Setup

One approach to interfacing with Speakeasy is to create a subclass of Speakeasy’s Speakeasy class. Figure 1 shows a Python code snippet that sets up such a class that will be expanded in upcoming examples.

import speakeasy

class MyUnpacker(speakeasy.Speakeasy):
    def __init__(self, config=None):
        super(MyUnpacker, self).__init__(config=config)

Figure 1: Creating a Speakeasy subclass

The code in Figure 1 accepts a Speakeasy configuration dictionary that may be used to override the default configuration. Speakeasy ships with several configuration files. The Speakeasy class is a wrapper class for an underlying emulator class. The emulator class is chosen automatically when a binary is loaded based on its PE headers or is specified as shellcode. Subclassing Speakeasy makes it easy to access, extend, or modify interfaces. It also facilitates reading and writing stateful data before, during, and after emulation.

Emulating a Binary

Figure 2 shows how to load a binary into the Speakeasy emulator.

self.module = self.load_module(filename)

Figure 2: Loading the binary into the emulator

The load_module function returns a PeFile object for the provided binary on disk. It is an instance of the PeFile class defined in speakeasy/windows/common.py, which is subclassed from pefile’s PE class. Alternatively, you can provide the bytes of a binary using the data parameter rather than specifying a file name. Figure 3 shows how to emulate a loaded binary.

self.run_module(self.module)

Figure 3: Starting emulation

API Hooks

The Speakeasy framework ships with support for hundreds of Windows APIs with more being added frequently. This is accomplished via Python API handlers defined in appropriate files in the speakeasy/winenv/api directory. API hooks can be installed to have your own code executed when particular APIs are called during emulation. They can be installed for any API, regardless of whether a handler exists or not. An API hook can be used to override an existing handler and that handler can optionally be invoked from your hook. The API hooking mechanism in Speakeasy provides flexibility and control over emulation. Let’s examine a few uses of API hooking within the context of emulating unpacking code to retrieve an unpacked payload.

Bypassing Unsupported APIs

When Speakeasy encounters an unsupported Windows API call, it stops emulation and provides the name of the API function that is not supported. If the API function in question is not critical for unpacking the binary, you can add an API hook that simply returns a value that allows execution to continue. For example, a recent sample’s unpacking code contained API calls that had no effect on the unpacking process. One such API call was to GetSysColor. In order to bypass this call and allow execution to continue, an API hook may be added as shown in Figure 4.

self.add_api_hook(self.getsyscolor_hook,
                  'user32',
                  'GetSysColor',
                  argc=1
                  )

Figure 4: Adding an API hook

According to MSDN, this function takes 1 parameter and returns an RGB color value represented as a DWORD. If the calling convention for the API function you are hooking is not stdcall, you can specify the calling convention in the optional call_conv parameter. The calling convention constants are defined in the speakeasy/common/arch.py file. Because the GetSysColor return value does not impact the unpacking process, we can simply return 0. Figure 5 shows the definition of the getsyscolor_hook function specified in Figure 4.

def getsyscolor_hook(self, emu, api_name, func, params):
            return 0

Figure 5: The GetSysColor hook returns 0

If an API function requires more finessed handling, you can implement a more specific and meaningful hook that suits your needs. If your hook implementation is robust enough, you might consider contributing it to the Speakeasy project as an API handler!  

Adding an API Handler

Within the speakeasy/winenv/api directory you'll find usermode and kernelmode subdirectories that contain Python files for corresponding binary modules. These files contain the API handlers for each module. In usermode/kernel32.py, we see a handler defined for SetEnvironmentVariable as shown in Figure 6.

1: @apihook('SetEnvironmentVariable', argc=2)
2: def SetEnvironmentVariable(self, emu, argv, ctx={}):
3:     '''
4:     BOOL SetEnvironmentVariable(
5:         LPCTSTR lpName,
6:         LPCTSTR lpValue
7:         );
8:     '''
9:     lpName, lpValue = argv
10:    cw = self.get_char_width(ctx)
11:    if lpName and lpValue:
12:        name = self.read_mem_string(lpName, cw)
13:        val = self.read_mem_string(lpValue, cw)
14:        argv[0] = name
15:        argv[1] = val
16:        emu.set_env(name, val)
17:    return True

Figure 6: API handler for SetEnvironmentVariable

A handler begins with a function decorator (line 1) that defines the name of the API and the number of parameters it accepts. At the start of a handler, it is good practice to include MSDN's documented prototype as a comment (lines 3-8).

The handler's code begins by storing elements of the argv parameter in variables named after their corresponding API parameters (line 9). The handler's ctx parameter is a dictionary that contains contextual information about the API call. For API functions that end in an ‘A’ or ‘W’ (e.g., CreateFileA), the character width can be retrieved by passing the ctx parameter to the get_char_width function (line 10). This width value can then be passed to calls such as read_mem_string (lines 12 and 13), which reads the emulator’s memory at a given address and returns a string.

It is good practice to overwrite string pointer values in the argv parameter with their corresponding string values (lines 14 and 15). This enables Speakeasy to display string values instead of pointer values in its API logs. To illustrate the impact of updating argv values, examine the Speakeasy output shown in Figure 7. In the VirtualAlloc entry, the symbolic constant string PAGE_EXECUTE_READWRITE replaces the value 0x40. In the GetModuleFileNameA and CreateFileA entries, pointer values are replaced with a file path.

KERNEL32.VirtualAlloc(0x0, 0x2b400, 0x3000, "PAGE_EXECUTE_READWRITE") -> 0x7c000
KERNEL32.GetModuleFileNameA(0x0, "C:\\Windows\\system32\\sample.exe", 0x104) -> 0x58
KERNEL32.CreateFileA("C:\\Windows\\system32\\sample.exe", "GENERIC_READ", 0x1, 0x0, "OPEN_EXISTING", 0x80, 0x0) -> 0x84

Figure 7: Speakeasy API logs

Saving the Unpacked Code Address

Packed samples often use functions such as VirtualAlloc to allocate memory used to store the unpacked sample. An effective approach for capturing the location and size of the unpacked code is to first hook the memory allocation function used by the unpacking stub. Figure 8 shows an example of hooking VirtualAlloc to capture the virtual address and amount of memory being allocated by the API call.

1: def virtualalloc_hook(self, emu, api_name, func, params):
2:     '''
3:     LPVOID VirtualAlloc(
4:        LPVOID lpAddress,
5:        SIZE_T dwSize,
6:        DWORD  flAllocationType,
7:        DWORD  flProtect
8:      );
9:     '''
10:    PAGE_EXECUTE_READWRITE = 0x40
11:    lpAddress, dwSize, flAllocationType, flProtect = params
12:    rv = func(params)
13:    if lpAddress == 0 and flProtect == PAGE_EXECUTE_READWRITE:
14:        self.logger.debug("[*] unpack stub VirtualAlloc call, saving dump info")
15:        self.dump_addr = rv
16:        self.dump_size = dwSize

17:    return rv

Figure 8: VirtualAlloc hook to save memory dump information

The hook in Figure 8 calls Speakeasy’s API handler for VirtualAlloc on line 12 to allow memory to be allocated. The virtual address returned by the API handler is saved to a variable named rv. Since VirtualAlloc may be used to allocate memory not related to the unpacking process, additional checks are used on line 13 to confirm the intercepted VirtualAlloc call is the one used in the unpacking code. Based on prior analysis, we’re looking for a VirtualAlloc call that receives the lpAddress value 0 and the flProtect value PAGE_EXECUTE_READWRITE (0x40). If these arguments are present, the virtual address and specified size are stored on lines 15 and 16 so they may be used to extract the unpacked payload from memory after the unpacking code is finished. Finally, on line 17, the return value from the VirtualAlloc handler is returned by the hook.

Surgical Code Emulation Using API and Code Hooks

Speakeasy is a robust emulation framework; however, you may encounter binaries that have large sections of problematic code. For example, a sample may call many unsupported APIs or simply take far too long to emulate. An example of overcoming both challenges is described in the following scenario.

Unpacking Stubs Hiding in MFC Projects

A popular technique used to disguise malicious payloads involves hiding them inside a large, open-source MFC project. MFC is short for Microsoft Foundation Class, which is a popular library used to build Windows desktop applications. These MFC projects are often arbitrarily chosen from popular Web sites such as Code Project. While the MFC library makes it easy to create desktop applications, MFC applications are difficult to reverse engineer due to their size and complexity. They are particularly difficult to emulate due to their large initialization routine that calls many different Windows APIs. What follows is a description of my experience with writing a Python script using Speakeasy to automate unpacking of a custom packer that hides its unpacking stub within an MFC project.

Reverse engineering the packer revealed the unpacking stub is ultimately called during initialization of the CWinApp object, which occurs after initialization of the C runtime and MFC. After attempting to bypass unsupported APIs, I realized that, even if successful, emulation would take far too long to be practical. I considered skipping over the initialization code completely and jumping straight to the unpacking stub. Unfortunately, execution of the C-runtime initialization code was required in order for emulation of the unpacking stub to succeed.

My solution was to identify a location in the code that fell after the C-runtime initialization but was early in the MFC initialization routine. After examining the Speakeasy API log shown in Figure 9, such a location was easy to spot. The graphics-related API function GetDeviceCaps is invoked early in the MFC initialization routine. This was deduced based on 1) MFC is a graphics-dependent framework and 2) GetDeviceCaps is unlikely to be called during C-runtime initialization.

0x43e0a7: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e0e3: 'kernel32.DecodePointer(0x7049)' -> 0x7048
0x43b16a: 'KERNEL32.HeapSize(0x4130, 0x0, 0x7000)' -> 0x90
0x43e013: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02a: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02c: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e068: 'kernel32.EncodePointer(0x44e215)' -> 0x44e216
0x43e013: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02a: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02c: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e068: 'kernel32.EncodePointer(0x704c)' -> 0x704d
0x43c260: 'KERNEL32.LeaveCriticalSection(0x466f28)' -> None
0x422151: 'USER32.GetSystemMetrics(0xb)' -> 0x1
0x422158: 'USER32.GetSystemMetrics(0xc)' -> 0x1
0x42215f: 'USER32.GetSystemMetrics(0x2)' -> 0x1
0x422169: 'USER32.GetSystemMetrics(0x3)' -> 0x1
0x422184: 'GDI32.GetDeviceCaps(0x288, 0x58)' -> None

Figure 9: Identifying beginning of MFC code in Speakeasy API logs

To intercept execution at this stage I created an API hook for GetDeviceCaps as shown in Figure 10. The hook confirms the function is being called for the first time on line 2.

1: def mfc_init_hook(self, emu, api_name, func, params):
2:     if not self.trigger_hit:
3:         self.trigger_hit = True
4:         self.h_code_hook =   self.add_code_hook(self.start_unpack_func_hook)
5:         self.logger.debug("[*] MFC init api hit, starting unpack function")

Figure 10: API hook set for GetDeviceCaps

Line 4 shows the creation of a code hook using the add_code_hook function of the Speakeasy class. Code hooks allow you to specify a callback function that is called before each instruction that is emulated. Speakeasy also allows you to optionally specify an address range for which the code hook will be effective by specifying begin and end parameters.

After the code hook is added on line 4, the GetDeviceCaps hook completes and, prior to the execution of the sample's next instruction, the start_unpack_func_hook function is called. This function is shown in Figure 11.

1: def start_unpack_func_hook(self, emu, addr, size, ctx):
2:     self.h_code_hook.disable()
3:     unpack_func_va = self.module.get_rva_from_offset(self.unpack_offs) + self.module.get_base()
4:     self.set_pc(unpack_func_va)

Figure 11: Code hook that changes the instruction pointer

The code hook receives the emulator object, the address and size of the current instruction, and the context dictionary (line 1). On line 2, the code hook disables itself. Because code hooks are executed with each instruction, this slows emulation significantly. Therefore, they should be used sparingly and disabled as soon as possible. On line 3, the hook calculates the virtual address of the unpacking function. The offset used to perform this calculation was located using a regular expression. This part of the example was omitted for the sake of brevity.

The self.module attribute was previously set in the example code shown in Figure 2. It being subclassed from the PE class of pefile allows us to access useful functions such as get_rva_from_offset() on line 3. This line also includes an example of using self.module.get_base() to retrieve the module's base virtual address.

Finally, on line 4, the instruction pointer is changed using the set_pc function and emulation continues at the unpacking code. The code snippets in Figure 10 and Figure 11 allowed us to redirect execution to the unpacking code after the C-runtime initialization completed and avoid MFC initialization code.

Dumping and Fixing Unpacked PEs

Once emulation has reached the original entry point of the unpacked sample, it is time to dump the PE and fix it up. Typically, a hook would save the base address of the unpacked PE in an attribute of the class as illustrated on line 15 of Figure 8. If the unpacked PE does not contain the correct entry point in its PE headers, the true entry point may also need to be captured during emulation. Figure 12 shows an example of how to dump emulator memory to a file.

with open(self.output_path, "wb") as up:
    mm = self.get_address_map(self.dump_addr)
    up.write(self.mem_read(mm.get_base(), mm.get_size()))

Figure 12: Dumping the unpacked PE

If you are dumping a PE that has already been loaded in memory, it will not have the same layout as it does on disk due to differences in section alignment. As a result, the dumped PE's headers may need to be modified. One approach is to modify each section's PointerToRawData value to match its VirtualAddress field. Each section's SizeOfRawData value may need to be padded in order conform with the FileAlignment value specified in the PE’s optional headers. Keep in mind the resulting PE is unlikely to execute successfully. However, these efforts will allow most static analysis tools to function correctly.

The final step for repairing the dumped PE is to fix its import table. This is a complex task deserving of its own blog post and will not be discussed in detail here. However, the first step involves collecting a list of library function names and their addresses in emulator memory. If you know the GetProcAddress API is used by the unpacker stub to resolve imports for the unpacked PE, you can call the get_dyn_imports function as shown in Figure 13.

api_addresses = self.get_dyn_imports()

Figure 13: Retrieving dynamic imports

Otherwise, you can query the emulator class to retrieve its symbol information by calling the get_symbols function as shown in Figure 14.

symbols = self.get_symbols()

Figure 14: Retrieve symbol information from emulator class

This data can be used to discover the IAT of the unpacked PE and fix or reconstruct its import related tables.

Putting It All Together

Writing a Speakeasy script to unpack a malware sample can be broken down into the following steps:

  1. Reverse engineer the unpacking stub to identify: 1) where the unpacked code will reside or where its memory is allocated, 2) where execution is transferred to the unpacked code, and 3) any problematic code that may introduce issues such as unsupported APIs, slow emulation, or anti-analysis checks.
  2. If necessary, set hooks to bypass problematic code.
  3. Set a hook to identify the virtual address and, optionally, the size of the unpacked binary.
  4. Set a hook to stop emulation at, or after, execution of the original entry point of the unpacked code.
  5. Collect virtual addresses of Windows APIs and reconstruct the PE’s import table.
  6. Fix the PE’s headers (if applicable) and write the bytes to a file for further analysis.

For an example of a script that unpacks UPX samples, check out the UPX unpacking script in the Speakeasy repository.

Conclusion

The Speakeasy framework provides an easy-to-use, flexible, and powerful programming interface that enables analysts to solve complex problems such as unpacking malware. Using Speakeasy to automate these solutions allows them to be performed at scale. I hope you enjoyed this introduction to automating the Speakeasy framework and are inspired to begin using it to implement your own malware analysis solutions!

Using Speakeasy Emulation Framework Programmatically to Unpack Malware

Andrew Davis recently announced the public release of his new Windows emulation framework named Speakeasy. While the introductory blog post focused on using Speakeasy as an automated malware sandbox of sorts, this entry will highlight another powerful use of the framework: automated malware unpacking. I will demonstrate, with code examples, how Speakeasy can be used programmatically to:

  • Bypass unsupported Windows APIs to continue emulation and unpacking
  • Save virtual addresses of dynamically allocated code using API hooks
  • Surgically direct execution to key areas of code using code hooks
  • Dump an unpacked PE from emulator memory and fix its section headers
  • Aid in reconstruction of import tables by querying Speakeasy for symbolic information

Initial Setup

One approach to interfacing with Speakeasy is to create a subclass of Speakeasy’s Speakeasy class. Figure 1 shows a Python code snippet that sets up such a class that will be expanded in upcoming examples.

import speakeasy

class MyUnpacker(speakeasy.Speakeasy):
    def __init__(self, config=None):
        super(MyUnpacker, self).__init__(config=config)

Figure 1: Creating a Speakeasy subclass

The code in Figure 1 accepts a Speakeasy configuration dictionary that may be used to override the default configuration. Speakeasy ships with several configuration files. The Speakeasy class is a wrapper class for an underlying emulator class. The emulator class is chosen automatically when a binary is loaded based on its PE headers or is specified as shellcode. Subclassing Speakeasy makes it easy to access, extend, or modify interfaces. It also facilitates reading and writing stateful data before, during, and after emulation.

Emulating a Binary

Figure 2 shows how to load a binary into the Speakeasy emulator.

self.module = self.load_module(filename)

Figure 2: Loading the binary into the emulator

The load_module function returns a PeFile object for the provided binary on disk. It is an instance of the PeFile class defined in speakeasy/windows/common.py, which is subclassed from pefile’s PE class. Alternatively, you can provide the bytes of a binary using the data parameter rather than specifying a file name. Figure 3 shows how to emulate a loaded binary.

self.run_module(self.module)

Figure 3: Starting emulation

API Hooks

The Speakeasy framework ships with support for hundreds of Windows APIs with more being added frequently. This is accomplished via Python API handlers defined in appropriate files in the speakeasy/winenv/api directory. API hooks can be installed to have your own code executed when particular APIs are called during emulation. They can be installed for any API, regardless of whether a handler exists or not. An API hook can be used to override an existing handler and that handler can optionally be invoked from your hook. The API hooking mechanism in Speakeasy provides flexibility and control over emulation. Let’s examine a few uses of API hooking within the context of emulating unpacking code to retrieve an unpacked payload.

Bypassing Unsupported APIs

When Speakeasy encounters an unsupported Windows API call, it stops emulation and provides the name of the API function that is not supported. If the API function in question is not critical for unpacking the binary, you can add an API hook that simply returns a value that allows execution to continue. For example, a recent sample’s unpacking code contained API calls that had no effect on the unpacking process. One such API call was to GetSysColor. In order to bypass this call and allow execution to continue, an API hook may be added as shown in Figure 4.

self.add_api_hook(self.getsyscolor_hook,
                  'user32',
                  'GetSysColor',
                  argc=1
                  )

Figure 4: Adding an API hook

According to MSDN, this function takes 1 parameter and returns an RGB color value represented as a DWORD. If the calling convention for the API function you are hooking is not stdcall, you can specify the calling convention in the optional call_conv parameter. The calling convention constants are defined in the speakeasy/common/arch.py file. Because the GetSysColor return value does not impact the unpacking process, we can simply return 0. Figure 5 shows the definition of the getsyscolor_hook function specified in Figure 4.

def getsyscolor_hook(self, emu, api_name, func, params):
            return 0

Figure 5: The GetSysColor hook returns 0

If an API function requires more finessed handling, you can implement a more specific and meaningful hook that suits your needs. If your hook implementation is robust enough, you might consider contributing it to the Speakeasy project as an API handler!  

Adding an API Handler

Within the speakeasy/winenv/api directory you'll find usermode and kernelmode subdirectories that contain Python files for corresponding binary modules. These files contain the API handlers for each module. In usermode/kernel32.py, we see a handler defined for SetEnvironmentVariable as shown in Figure 6.

1: @apihook('SetEnvironmentVariable', argc=2)
2: def SetEnvironmentVariable(self, emu, argv, ctx={}):
3:     '''
4:     BOOL SetEnvironmentVariable(
5:         LPCTSTR lpName,
6:         LPCTSTR lpValue
7:         );
8:     '''
9:     lpName, lpValue = argv
10:    cw = self.get_char_width(ctx)
11:    if lpName and lpValue:
12:        name = self.read_mem_string(lpName, cw)
13:        val = self.read_mem_string(lpValue, cw)
14:        argv[0] = name
15:        argv[1] = val
16:        emu.set_env(name, val)
17:    return True

Figure 6: API handler for SetEnvironmentVariable

A handler begins with a function decorator (line 1) that defines the name of the API and the number of parameters it accepts. At the start of a handler, it is good practice to include MSDN's documented prototype as a comment (lines 3-8).

The handler's code begins by storing elements of the argv parameter in variables named after their corresponding API parameters (line 9). The handler's ctx parameter is a dictionary that contains contextual information about the API call. For API functions that end in an ‘A’ or ‘W’ (e.g., CreateFileA), the character width can be retrieved by passing the ctx parameter to the get_char_width function (line 10). This width value can then be passed to calls such as read_mem_string (lines 12 and 13), which reads the emulator’s memory at a given address and returns a string.

It is good practice to overwrite string pointer values in the argv parameter with their corresponding string values (lines 14 and 15). This enables Speakeasy to display string values instead of pointer values in its API logs. To illustrate the impact of updating argv values, examine the Speakeasy output shown in Figure 7. In the VirtualAlloc entry, the symbolic constant string PAGE_EXECUTE_READWRITE replaces the value 0x40. In the GetModuleFileNameA and CreateFileA entries, pointer values are replaced with a file path.

KERNEL32.VirtualAlloc(0x0, 0x2b400, 0x3000, "PAGE_EXECUTE_READWRITE") -> 0x7c000
KERNEL32.GetModuleFileNameA(0x0, "C:\\Windows\\system32\\sample.exe", 0x104) -> 0x58
KERNEL32.CreateFileA("C:\\Windows\\system32\\sample.exe", "GENERIC_READ", 0x1, 0x0, "OPEN_EXISTING", 0x80, 0x0) -> 0x84

Figure 7: Speakeasy API logs

Saving the Unpacked Code Address

Packed samples often use functions such as VirtualAlloc to allocate memory used to store the unpacked sample. An effective approach for capturing the location and size of the unpacked code is to first hook the memory allocation function used by the unpacking stub. Figure 8 shows an example of hooking VirtualAlloc to capture the virtual address and amount of memory being allocated by the API call.

1: def virtualalloc_hook(self, emu, api_name, func, params):
2:     '''
3:     LPVOID VirtualAlloc(
4:        LPVOID lpAddress,
5:        SIZE_T dwSize,
6:        DWORD  flAllocationType,
7:        DWORD  flProtect
8:      );
9:     '''
10:    PAGE_EXECUTE_READWRITE = 0x40
11:    lpAddress, dwSize, flAllocationType, flProtect = params
12:    rv = func(params)
13:    if lpAddress == 0 and flProtect == PAGE_EXECUTE_READWRITE:
14:        self.logger.debug("[*] unpack stub VirtualAlloc call, saving dump info")
15:        self.dump_addr = rv
16:        self.dump_size = dwSize

17:    return rv

Figure 8: VirtualAlloc hook to save memory dump information

The hook in Figure 8 calls Speakeasy’s API handler for VirtualAlloc on line 12 to allow memory to be allocated. The virtual address returned by the API handler is saved to a variable named rv. Since VirtualAlloc may be used to allocate memory not related to the unpacking process, additional checks are used on line 13 to confirm the intercepted VirtualAlloc call is the one used in the unpacking code. Based on prior analysis, we’re looking for a VirtualAlloc call that receives the lpAddress value 0 and the flProtect value PAGE_EXECUTE_READWRITE (0x40). If these arguments are present, the virtual address and specified size are stored on lines 15 and 16 so they may be used to extract the unpacked payload from memory after the unpacking code is finished. Finally, on line 17, the return value from the VirtualAlloc handler is returned by the hook.

Surgical Code Emulation Using API and Code Hooks

Speakeasy is a robust emulation framework; however, you may encounter binaries that have large sections of problematic code. For example, a sample may call many unsupported APIs or simply take far too long to emulate. An example of overcoming both challenges is described in the following scenario.

Unpacking Stubs Hiding in MFC Projects

A popular technique used to disguise malicious payloads involves hiding them inside a large, open-source MFC project. MFC is short for Microsoft Foundation Class, which is a popular library used to build Windows desktop applications. These MFC projects are often arbitrarily chosen from popular Web sites such as Code Project. While the MFC library makes it easy to create desktop applications, MFC applications are difficult to reverse engineer due to their size and complexity. They are particularly difficult to emulate due to their large initialization routine that calls many different Windows APIs. What follows is a description of my experience with writing a Python script using Speakeasy to automate unpacking of a custom packer that hides its unpacking stub within an MFC project.

Reverse engineering the packer revealed the unpacking stub is ultimately called during initialization of the CWinApp object, which occurs after initialization of the C runtime and MFC. After attempting to bypass unsupported APIs, I realized that, even if successful, emulation would take far too long to be practical. I considered skipping over the initialization code completely and jumping straight to the unpacking stub. Unfortunately, execution of the C-runtime initialization code was required in order for emulation of the unpacking stub to succeed.

My solution was to identify a location in the code that fell after the C-runtime initialization but was early in the MFC initialization routine. After examining the Speakeasy API log shown in Figure 9, such a location was easy to spot. The graphics-related API function GetDeviceCaps is invoked early in the MFC initialization routine. This was deduced based on 1) MFC is a graphics-dependent framework and 2) GetDeviceCaps is unlikely to be called during C-runtime initialization.

0x43e0a7: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e0e3: 'kernel32.DecodePointer(0x7049)' -> 0x7048
0x43b16a: 'KERNEL32.HeapSize(0x4130, 0x0, 0x7000)' -> 0x90
0x43e013: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02a: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02c: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e068: 'kernel32.EncodePointer(0x44e215)' -> 0x44e216
0x43e013: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02a: 'KERNEL32.TlsGetValue(0x0)' -> 0xfeee0001
0x43e02c: 'kernel32.FlsGetValue(0x0)' -> 0x4150
0x43e068: 'kernel32.EncodePointer(0x704c)' -> 0x704d
0x43c260: 'KERNEL32.LeaveCriticalSection(0x466f28)' -> None
0x422151: 'USER32.GetSystemMetrics(0xb)' -> 0x1
0x422158: 'USER32.GetSystemMetrics(0xc)' -> 0x1
0x42215f: 'USER32.GetSystemMetrics(0x2)' -> 0x1
0x422169: 'USER32.GetSystemMetrics(0x3)' -> 0x1
0x422184: 'GDI32.GetDeviceCaps(0x288, 0x58)' -> None

Figure 9: Identifying beginning of MFC code in Speakeasy API logs

To intercept execution at this stage I created an API hook for GetDeviceCaps as shown in Figure 10. The hook confirms the function is being called for the first time on line 2.

1: def mfc_init_hook(self, emu, api_name, func, params):
2:     if not self.trigger_hit:
3:         self.trigger_hit = True
4:         self.h_code_hook =   self.add_code_hook(self.start_unpack_func_hook)
5:         self.logger.debug("[*] MFC init api hit, starting unpack function")

Figure 10: API hook set for GetDeviceCaps

Line 4 shows the creation of a code hook using the add_code_hook function of the Speakeasy class. Code hooks allow you to specify a callback function that is called before each instruction that is emulated. Speakeasy also allows you to optionally specify an address range for which the code hook will be effective by specifying begin and end parameters.

After the code hook is added on line 4, the GetDeviceCaps hook completes and, prior to the execution of the sample's next instruction, the start_unpack_func_hook function is called. This function is shown in Figure 11.

1: def start_unpack_func_hook(self, emu, addr, size, ctx):
2:     self.h_code_hook.disable()
3:     unpack_func_va = self.module.get_rva_from_offset(self.unpack_offs) + self.module.get_base()
4:     self.set_pc(unpack_func_va)

Figure 11: Code hook that changes the instruction pointer

The code hook receives the emulator object, the address and size of the current instruction, and the context dictionary (line 1). On line 2, the code hook disables itself. Because code hooks are executed with each instruction, this slows emulation significantly. Therefore, they should be used sparingly and disabled as soon as possible. On line 3, the hook calculates the virtual address of the unpacking function. The offset used to perform this calculation was located using a regular expression. This part of the example was omitted for the sake of brevity.

The self.module attribute was previously set in the example code shown in Figure 2. It being subclassed from the PE class of pefile allows us to access useful functions such as get_rva_from_offset() on line 3. This line also includes an example of using self.module.get_base() to retrieve the module's base virtual address.

Finally, on line 4, the instruction pointer is changed using the set_pc function and emulation continues at the unpacking code. The code snippets in Figure 10 and Figure 11 allowed us to redirect execution to the unpacking code after the C-runtime initialization completed and avoid MFC initialization code.

Dumping and Fixing Unpacked PEs

Once emulation has reached the original entry point of the unpacked sample, it is time to dump the PE and fix it up. Typically, a hook would save the base address of the unpacked PE in an attribute of the class as illustrated on line 15 of Figure 8. If the unpacked PE does not contain the correct entry point in its PE headers, the true entry point may also need to be captured during emulation. Figure 12 shows an example of how to dump emulator memory to a file.

with open(self.output_path, "wb") as up:
    mm = self.get_address_map(self.dump_addr)
    up.write(self.mem_read(mm.get_base(), mm.get_size()))

Figure 12: Dumping the unpacked PE

If you are dumping a PE that has already been loaded in memory, it will not have the same layout as it does on disk due to differences in section alignment. As a result, the dumped PE's headers may need to be modified. One approach is to modify each section's PointerToRawData value to match its VirtualAddress field. Each section's SizeOfRawData value may need to be padded in order conform with the FileAlignment value specified in the PE’s optional headers. Keep in mind the resulting PE is unlikely to execute successfully. However, these efforts will allow most static analysis tools to function correctly.

The final step for repairing the dumped PE is to fix its import table. This is a complex task deserving of its own blog post and will not be discussed in detail here. However, the first step involves collecting a list of library function names and their addresses in emulator memory. If you know the GetProcAddress API is used by the unpacker stub to resolve imports for the unpacked PE, you can call the get_dyn_imports function as shown in Figure 13.

api_addresses = self.get_dyn_imports()

Figure 13: Retrieving dynamic imports

Otherwise, you can query the emulator class to retrieve its symbol information by calling the get_symbols function as shown in Figure 14.

symbols = self.get_symbols()

Figure 14: Retrieve symbol information from emulator class

This data can be used to discover the IAT of the unpacked PE and fix or reconstruct its import related tables.

Putting It All Together

Writing a Speakeasy script to unpack a malware sample can be broken down into the following steps:

  1. Reverse engineer the unpacking stub to identify: 1) where the unpacked code will reside or where its memory is allocated, 2) where execution is transferred to the unpacked code, and 3) any problematic code that may introduce issues such as unsupported APIs, slow emulation, or anti-analysis checks.
  2. If necessary, set hooks to bypass problematic code.
  3. Set a hook to identify the virtual address and, optionally, the size of the unpacked binary.
  4. Set a hook to stop emulation at, or after, execution of the original entry point of the unpacked code.
  5. Collect virtual addresses of Windows APIs and reconstruct the PE’s import table.
  6. Fix the PE’s headers (if applicable) and write the bytes to a file for further analysis.

For an example of a script that unpacks UPX samples, check out the UPX unpacking script in the Speakeasy repository.

Conclusion

The Speakeasy framework provides an easy-to-use, flexible, and powerful programming interface that enables analysts to solve complex problems such as unpacking malware. Using Speakeasy to automate these solutions allows them to be performed at scale. I hope you enjoyed this introduction to automating the Speakeasy framework and are inspired to begin using it to implement your own malware analysis solutions!

Cyber Security Roundup for December 2020

A roundup of UK focused Cyber and Information Security News, Blog Posts, Reports and general Threat Intelligence from the previous calendar month, November 2020.

Manchester United FC remains impacted by a seemly major cyber-attack, which I covered in a blog post titled The Multi-Million Pound Manchester United Hack. At this point, United have provided few details about their cyber-attack which has been impacting club's IT systems for well over a week. However, the UK media are widely reporting United's leaky IT defences was unable to prevent a ransomware attack and data theft.  London's Hackney Borough Council have also been tight-lipped about what they describe as "a serious cyber-attack" which has impacted its service delivery to Londoners. Like United, this attack has all the hallmarks of a mass ransomware outbreak. Both Manchester United and Hacknet Council said they are working UK's National Cyber Security Centre (NCSC).

Man.Utd hit by ransomware, who's next?

Street Fighter games maker Capcom also reported to be compromised by a ransomware attack, with up to 350,000 people said to be affected, along some of Capcom's financial information stolen. The Ragnar locker hacker group were said to be behind the attack, although indications are that Capcom hasn't given in to their ransom demands after an ominous message appeared on the Ragnar group's website, which said Capcom didn't "make a right decision and save data from leakage". 

The ransomware attacks will be going from bad to worse in 2021 according to Sophos. In its annual threat report, Sophos anticipates ransomware tactics, techniques and procedures are to become more evasive, with criminal threat actor operating more like nation-state attackers. Sophos also expects an increase in the number of entry-level, apprentice-type attackers looking for menu-driven, ransomware-for-rent, meaning the technical barrier preventing general nefarious folk orchestrating ransomware attacks is getting lower.

Its likely COVID-19 has saved Ticketmaster from a more substantial DPA/GDPR fine after the Information Commissioners Office (ICO) announced it had fined the gig ticket selling company a mere £1.25 million for failing to keep 9 million of its customer's personal data and payment cards secure.  The ICO investigation concluded a vulnerability in a third-party chatbot installed on Ticketmaster's online payments page was exploited and used to access its customer card payment details. Following the breach, 60,000 Barclays bank customers were victims of fraud, while online bank Monzo had to replace 6,000 payment cards due to fraud. Ticketmaster said it would appeal against the ICO ruling. 

An interesting new UK law is in the offing which proposes fines of 10% of turnover or more than £100,000 a day for telecoms operators that use of Huawei network equipment within their 5G networks. The bill provides the UK government new powers to force out Huawei usage with the UK telecoms giants, the threatened sum of £100,000 a day would only be used in the case of "continuing contravention" according to number 10.

Consumer group Which warned security flaws in popular smart doorbells are placing UK consumers at risk. The watchdog tested 11 smart doorbell (IoT) devices purchased from popular online marketplaces like Amazon, the dodgy products were said to have been made by Qihoo, Ctronics and Victure. The most common security flaws found by Which were weak password policies and a lack of data encryption. Two of the devices could be manipulated to steal network WiFi passwords, providing the opportunity for an attacker to then hack other smart devices within the home.

The NCSC released its annual review, confirming what we already know about the commonality of ransomware attacks on UK organisations.  The NCSC also accused Russia of trying to steal vaccine-related information through cyber-espionage, advising an "ongoing threat" of nation-states targeting the UK vaccine research-and-delivery programmes. The NCSC were not alone in pointing the finger at nation-state threat actors going after COVID-19 vaccines, Microsoft also reported state-backed hackers from Russian and North Korea were targeting organisations working on a coronavirus vaccine. The Russian group "Fancy Bear" and North Korean groups "Zinc" and "Cerium" were fingered by Microsoft as the culprits behind a spate recent cyber-attacks. Microsoft said Fancy Bear were brute-forcing accounts with millions of different passwords combinations, while North Korean groups sent spear-phishing emails posing as World Health Organisation officials, in an attempt to trick researchers into handing over their login credentials and research data. 

Stay safe and secure.

BLOG

VULNERABILITIES AND SECURITY UPDATES
AWARENESS, EDUCATION AND THREAT INTELLIGENCE

    Top Phishing Lures to Look Out for This Holiday Season

    holiday phishing scams

    Top Phishing Lures to Look Out for This Holiday Season

    And just like that, the holidays are here! That means it’s time to grab your devices and credit cards for some online holiday shopping. But while you plan to share the merry and shop for gifts, criminals are preparing some not-so-festive tricks of their own. According to Threatpost, various phishing scams are currently targeting eager consumers this holiday season.

    Let’s unwrap the top four phishing scams that users should beware of while making online purchases this week and through the rest of the year.

    Email Phishing: How Cyber-Grinches Steal Your Inbox

    It might surprise you to see that a tactic as old as email phishing is still so widely used today. Well, that’s because many people still fall for email phishing scams, as the criminals behind these attacks up the ante every year to make these threats more sophisticated.

    Scammers also tend to take advantage of current events to trick unsuspecting consumers into falling for their tricks. Take earlier this year, for example, when many users received phishing emails claiming to be from a government entity regarding financial support due to the global health emergency. Cybercriminals will likely use similar, timely tactics leading up to the holidays, posing as famous retailers and promising fake discounts in the hope that a consumer will divulge their credit card details or click on a malicious link.

    Spear Phishing Takes Advantage of the Season of Giving

    Like email phishing, spear phishing has been around for quite some time. With spear phishing attacks, hackers pretend to be an organization or individual that you’re familiar with and include a piece of content—a link, an email attachment, etc.—that they know you’ll want to interact with. For example, cybercriminals might claim to be charitable organizations asking for donations, knowing that many families like to donate during the holidays. The email might even include the recipient’s personal details to make it seem more convincing. But instead of making a generous contribution, users find that they infected their own system with malware by clicking on the fraudulent link.

    Dasher, Dancer, Prancer, Vishing?

    No, that’s not the sound of Santa coming down the chimney – it’s the sound of voice phishing! “Vishing” attacks can be highly deceiving, as hackers will call a user and trick them into giving up their credentials or sharing other personal information. For example, a scammer could call an individual telling them that they won a large amount of cash as part of a holiday contest. Overjoyed with the thought of winning this so-called contest, the user may hand over their bank information to the criminal on the other end of the phone. But instead of receiving a direct deposit, all they find is that their banking credentials were used to make a fraudulent purchase.

    Special Delivery or SMiShing?

    SMS phishing, or “SMiShing,” is another threat users should watch out for this holiday season. This tactic uses misleading text messages claiming to come from a trusted person or organization to trick recipients into taking a certain action that gives the attacker exploitable information or access to their mobile device.

    Due to the current global health emergency and the desire to do more digitally, consumers will likely rely on online shopping this holiday season. To take advantage of this trend, scammers will probably send fraudulent text messages disguised as online retailers. These messages will likely contain fake tracking links, shipping notices, and order confirmations. But if an unsuspecting user clicks on one of these links, they will be directed to a fake website prompting them to enter their credentials for the attackers to further exploit.

    Avoid Unwanted Security “Presents” This Holiday Season

     To prevent cybercriminals from messing with the festive spirit via phishing schemes, follow these tips so you can continue to make merry during the holiday shopping season:

    Be cautious of emails asking you to act 

    If you receive an email, call, or text asking you to download software or pay a certain amount of money, don’t click on anything or take any direct action from the message. Instead, go straight to the organization’s website. This will prevent you from downloading malicious content from phishing links or forking over money unnecessarily.

    Hover over links to see and verify the URL

    If someone sends you a message with a link, hover over the link without actually clicking on it. This will allow you to see a link preview. If the URL looks suspicious, don’t interact with it and delete the message altogether.

    Go directly to the source

    Instead of clicking on a link in an email or text message, it’s always best to check directly with the source to verify a holiday shopping offer or track a package’s shipment.

    Browse with caution

    Use a comprehensive security solution, like McAfee Total Protection, which can help protect devices against malware, phishing attacks, and other threats. It includes McAfee WebAdvisor, which can help identify malicious websites.

    Stay Updated

    To stay updated on all things McAfee and on top of the latest consumer and mobile security threats, follow @McAfee_Home  on Twitter, listen to our podcast Hackable?, and ‘Like’ us on Facebook.

     

     

    The post Top Phishing Lures to Look Out for This Holiday Season appeared first on McAfee Blogs.

    Putting Protection to The Test

    McAfee win

    Putting Protection to The Test

     This year has thrown a lot of challenges at us, and our digital lives were not immune. As millions of people around the world suddenly switched to working and learning online from home during the pandemic, digital threats spiked, making security and performance essential.

    At McAfee, we are hyperaware of what our users are going through this year, with changes to their work, school, and lifestyles. At the same time, we are keeping our eyes on the threats aimed at taking advantage of the situation.

    For example, we know that publicly disclosed security breaches increased by 41% in the first quarter of 2020 compared to the previous quarter. And, COVID-related threats are also on the rise. But with everything going on, it’s easy to see how technology users can become overwhelmed. That means that security not only has to protect against a wide range of threats, but also be seamless.

    Security that Stands Strong

    While you’ve been busy keeping up with all the changes this year has brought, we have been working on providing comprehensive security that protects you from existing and emerging threats so you can have peace of mind. In fact, Austria-based AV-Comparatives recently gave McAfee® Total Protection their highest three-star, “Advanced +” rating for malware protection measured against 16 competitors, and the German anti-malware test lab AV-Test awarded McAfee Total Protection with the TOP Product rating because of its 100% protection scores.

    AV-Test also gave McAfee Mobile Security for Android its highest rating in terms of protection, performance, and usability against 14 competitors.

    These labs also test for “false positives.” False positives happen when antivirus software identifies legitimate files or processes as malware by mistake.  In recent tests, our products have also scored well when it comes to avoiding false positives. AV-Test showed that McAfee Total Protection and McAfee Mobile Security flagged zero false positives during testing.

    Both of these independent antivirus testing organizations specifically look for how well security products protect their users against various threats, which is critically important given today’s threat landscape.

    Always Improving

    One of the key ways we keep on top of threats is through continuous product development. We don’t stop working on our software tools just because they are released to the public. Our products are continuously updated with new features and enhancements when they become available because security isn’t static. Regardless of if you bought your product in 2019 or early 2020, we make sure that you have the latest protection installed through automatic product updates.

    Underscoring our dedication to continual product improvement, U.K.-based SE Labs recently named McAfee the 2020 winner for “Best Product Development.”

    SE Labs’s slogan is “testing like hackers” because it evaluates a product’s effectiveness at various stages of attacks, from malicious emails and keystroke loggers, to full-on network attacks and system harm. All of these assessments are important to ensure that we can protect our users in real-world settings.

    Performance Still Matters

    I’ve written before about how security software has to be convenient, and not get in the way of our productivity. Given the climate, it’s more important than ever that we offer comprehensive security tools that are lightweight and easy to manage.

    For instance, I know how important these days are for my kids to meet with their teachers in online classes. If our security software was taking up so much of our computer’s resources that it kept them from being able to stream video while taking notes, it wouldn’t just be frustrating, but detrimental.

    McAfee has consistently received some of the best scores in performance tests, while having a minimal impact on users’ systems. Just this month, AV-Comparatives awarded McAfee Total Protection the highest possible ADVANCED+ rating yet again, for the ninth time in a row!

    This is great news for us, but even more important for our users since it shows that they do not have to sacrifice protection or performance, whether on their computers or mobile devices.

    How It Helps You

    Of course, we know the threat landscape is continuously evolving, and we need to evolve with it.

    By offering you tools that can guard against the latest risks while allowing you to be productive and connect with family and friends, we hope to be a strong ally in your digital life. It’s great to see that these three independent testing organizations recognize our accomplishments so far in protection efficacy and performance. We promise to keep it up so you can live a carefree digital life.

    Stay Updated

    To stay updated on all things McAfee and on top of the latest consumer and mobile security threats, follow @McAfee_Home  on Twitter, listen to our podcast Hackable?, and ‘Like’ us on Facebook.

    The post Putting Protection to The Test appeared first on McAfee Blogs.

    Think Beyond the Edge: Why SASE is Incomplete Without Endpoint DLP

    The move to a distributed workforce came suddenly and swiftly. In February 2020, less than 40% of companies allowed most of their employees to work from home one day a week. By April, 77% of companies had most of their employees working exclusively from home.

    Organizations have been in the midst of digital transformation projects for years, but this development represented a massive test. Most organizations were pleasantly surprised to see that their employees could remain productive while working from home thanks to successful cloud migration projects and the adoption of various mobility and remote access technologies, but companies have become more worried that they have far less visibility into data on employees’ systems when they are working remotely. Traditional Network DLP can protect data while it is traversing through the network up to the corporate edge, but it has little visibility to data once it is out of the corporate network and its effectiveness is further limited when the workforce is distributed.

    Figure 1: Data protection gaps resulting from direct-to-cloud access.

    More than three-quarters of CIOs are concerned with the impact that this increased data sprawl is having on security. Despite the fact that roughly half of all corporate data was stored in the cloud last year, only 36% of companies could enforce data protection policies there. Many organizations therefore forced home-based users to hairpin all traffic back to the corporate data center via VPN so that they could be protected by the network data loss prevention (DLP) system. This maintained security, but it came at the cost of poor performance and reduced worker productivity.

    Cloud-native security is part of the solution

    Organizations that employed cloud-based security technologies like a Cloud Access Security Broker (CASB), DLP, or Secure Web Gateway (SWG) could enable their users to perform their jobs with fast and secure direct-to-cloud access. However, this still leads to headaches: IT organizations have to manage multiple disparate solutions, while users face latency while their traffic needs to bounce between multiple siloed technologies before they can access their data.

    The Secure Access Service Edge (SASE) presents a solution to this dilemma by providing a framework for organizations to bring all of these technologies together into a single integrated cloud service. End users enjoy low-latency access to the cloud, while IT management and costs are simplified. So everyone wins, right? Not entirely.

    Many SASE proponents posit that the best way to architect a distributed Work From Home environment would be to have all security functionality in the cloud at the “service edge”, while end user devices have only a small agent to redirect traffic to that service edge. However, this model poses a data protection dilemma. While a cloud-delivered service can extend data protection to data centers, cloud applications, and web traffic, there are a number of blind spots:

    • Every remote worker’s home is now a remote office with a range of unmanaged, unsecured devices like printers, storage drives, and peripherals that can be compromised or be used to exfiltrate data.
    • Attached devices like USB keys can be used to get data off of a corporate device and beyond the reach of and data protection controls.
    • Cloud applications like Webex, Dropbox, and Zoom all have desktop companion apps that enable actions like file syncing or screen/file sharing; these websocket apps run locally on the user’s system and are not subject to cloud-based data protection policies.

    These blind spots can only be addressed by endpoint-based data loss prevention (DLP) that enforces data protection policy on the user’s device. This is not dissimilar to how SASE frameworks rely on SD-WAN customer premises equipment (CPE) that perform essential network flow functionality at branch office locations. Therefore, it’s imperative to look for SASE solutions that include endpoint DLP coverage.

    Figure 2: How endpoint DLP uniquely addresses home office security gaps.

    Bringing it all together is the key

    It’s great to say that to address the challenges of cloud transformation and the remote workforce, existing network DLP solutions – with their dedicated management interface, data classifications, and policy workflows – need to be accompanied by similar capabilities in the cloud, and then again on the endpoint. Of course, that’s completely impractical where IT organizations are already struggling to deal with the status quo due to finite budgets and skilled personnel. Not only is it impractical, but it undermines the consolidation, simplification, and cost reduction promised both by digital transformation and the SASE framework.

    The answer to this dilemma is a comprehensive data protection solution that encompasses networks, devices, and the cloud, something that is uniquely delivered by McAfee MVISION Unified Cloud Edge (UCE). MVISION UCE is a cloud-native solution that seamlessly converges core security technologies such as Data Loss Prevention (DLP), cloud access security broker (CASB) and next-gen secure web gateway (SWG) to help accelerate SASE adoption. MVISION UCE features multi-vector data protection that features unified data classification and incident management across the network, sanctioned and unsanctioned Shadow IT cloud applications, web traffic, and equally important, endpoint DLP. This provides corporate information-security teams the necessary visibility, control and management capability to secure home-based and mobile workers as they access data anywhere.

    Figure 3: Unified Multi-Vector Data Protection

    To manage data security of a distributed workforce, linking device security to corporate policy becomes extremely important. With a managed DLP agent on the device, IT security can know where sensitive data exists, block untrusted services and removable media, protect against cloud services and desktop apps, and educate employees to potential dangers.

    Historically, data protection has focused on a central point like the network or the cloud because implementing it on the device has been difficult. However, with McAfee’s Unified Computing Edge (UCE), DLP becomes an easy-to-deliver feature.

    Centrally managed by McAfee MVISION ePO, McAfee DLP can be easily deployed to endpoints. With its unique device-to-cloud DLP features, on-prem DLP policies can be easily extended to the Cloud with a single click and as fast as under one minute.  Shared data classification tags ensure consistent multi-environment protection for your most sensitive data across endpoints, network and cloud. —

    Incorporating security into the cloud and the edge, and delivering data protection at the endpoint, are the only way to really deliver on what SASE promises and unlock your remote workforce. Looking to the future, a widely distributed workforce is here to stay. Companies need to take steps to secure devices and data wherever they are.

    To find out more, please visit www.mcafee.com/unifiedcloud.

    The post Think Beyond the Edge: Why SASE is Incomplete Without Endpoint DLP appeared first on McAfee Blogs.

    Face Recognition Software Shows Improvement in Recognizing Masked Faces

    A new study of face recognition technology created after the onset of the COVID-19 pandemic shows that some software developers have made demonstrable progress at recognizing masked faces. The findings, produced by the National Institute of Standards and Technology (NIST), are detailed in a new report called Ongoing Face Recognition Vendor Test (FRVT) Part 6B: Face Recognition Accuracy with Face Masks Using Post-COVID-19 Algorithms (NISTIR 8331). It is the agency’s first study that measures the performance of face recognition algorithms developed following the arrival of the pandemic. A