1. Introduction
In the field of computer security, the ongoing changes in challenges require us to come up with new solutions. Malware is a particularly pervasive threat, affecting a wide range of devices from servers to mobile phones [
1]. To solve this, various malware analysis methods have been devised, yet attackers continue to innovate, developing sophisticated evasion techniques [
2].
Attackers commonly deploy packers [
2,
3,
4]. These tools go beyond simple compression; they integrate sophisticated anti-analysis and obfuscation techniques into binaries. Packed malware, with its original code encrypted, presents significant detection and analysis challenges, especially in debugger or sandbox environments [
5,
6,
7].
Despite the proposal of generic unpacking methods, they are frequently undermined by obfuscation techniques, including those affecting the OEP and API. Packed malware typically has its original code encrypted and its entry point redirected to the packer’s bootstrap code. This bootstrap code, upon execution, temporarily restores the original program in memory. However, OEP obfuscation can mislead unpackers, causing them to incorrectly detect the OEP or interact with trampoline code, which results in execution inconsistencies.
Moreover, whereas standard programs rely on the operating system’s loader for runtime binding of API addresses to the Import Address Table (IAT), packed malware depends on its bootstrap code due to the packer often stripping away the import table. Recent obfuscators have made this situation more complex by inserting trampoline codes into the IAT, which hide the API calls. Unpackers attempting to identify and reconstruct the IAT may misinterpret these trampoline codes as API addresses, leading to unpacking failures [
8].
Modern packers frequently use trampoline code to disguise both the OEP and IAT, thus complicating program analysis [
9,
10,
11,
12]. Execution of such packed programs incorporates trampoline code into the original data, changing its behavior.
The difficulty of OEP obfuscation depends on whether trampoline code is present or not. Sometimes, a branch to this code is embedded at the OEP, causing potential invalid memory accesses in unpacked programs. In some cases, trampoline code execution disrupts the original control flow, rendering accurate OEP detection a challenging task.
The complexity in de-obfuscating API obfuscation hinges on the sensitivity of trampoline code to arguments [
8]. Argument-sensitive trampoline codes funnel all obfuscated APIs to a single point, with the specific API being determined by the provided argument [
12]. Conversely, argument-insensitive trampoline codes associate every obfuscated API with a unique trampoline code, requiring the identification and tracking of each one [
9,
10,
11]. This distinction is critical as previous API de-obfuscation approaches mainly focused on detecting and observing trampoline code, often neglecting the argument’s role [
8,
13,
14].
This paper explores methods for automatically uncovering the obfuscation techniques employed by modern packers, emphasizing trampoline codes in OEP and API obfuscation. We introduce Pinicorn, a dynamic approach aimed at recovering these techniques and unpacking packed programs.
Pinicorn initially utilized a Dynamic Binary Instrumentation (DBI)-based Obfuscated Program Execution Module to counteract the packer’s anti-analysis techniques, reinstating the original program in memory for runtime execution. During this phase, Pinicorn monitors the process, identifying potential OEP candidates to effectively analyze the unpacked program. The resulting memory dump includes trampoline codes critical for obfuscating OEP and API, which are then analyzed using memory static analysis. Then, an Emulator-based Trampoline Code Execution Module examines all trampoline codes, uncovering key information that was hidden by obfuscation. This process helps restore the program’s original structure and import table.
We provide an analysis of packers and their role in hindering reverse-engineering of programs.
We propose an automated dynamic analysis approach for de-obfuscating and unpacking programs.
We introduce an Emulator-based Obfuscated Code Execution method, demonstrating its efficacy in identifying and analyzing trampoline code in packed programs.
The remainder of this paper is organized as follows:
Section 1 discusses the impact of packing, OEP, and API obfuscation techniques on binaries. It also reviews related work in unpacking and de-obfuscation approaches.
Section 2 outlines the challenges associated with OEP and API obfuscation and details our proposed solutions.
Section 3 presents our de-obfuscation results.
Section 4 delves into potential challenges in analyzing obfuscated program and mitigation strategies. Finally,
Section 5 concludes the study and suggests future directions. Packers play a pivotal role in malware obfuscation, often removing the entry point and import table during the packing process. While earlier research efforts have centered on detecting the OEP and rebuilding the import table of packed malware, packers have evolved, adopting advanced obfuscation techniques to counter these measures [
5,
7]. A notable study, API-Xray, has effectively tackled the challenge of reconstructing import tables in obfuscated malware contexts, revealing that 9.5% of resistant malware samples employed both OEP and API obfuscation [
8].
1.1. The Impact of General Packers on Binaries
General packers, such as Themida, VMProtect, and ASProtect, are widely used to obfuscate malware binaries, making analysis and detection challenging. These packers employ various techniques to compress, encrypt, and manipulate the executable code, hindering static and dynamic analysis. Understanding the impact of these packers on binary structure and behavior is crucial for developing effective unpacking solutions.
Figure 1 illustrates the standard control flow of a Portable Executable (PE) file. In this process, the Windows Loader carries out essential tasks such as binding the API to the IAT and starting execution from the entry point. PE files utilize APIs from Dynamic Link Libraries (DLLs), with the Windows Loader populating the IAT with these API addresses [
15].
Once configured, the loader activates the program’s entry point, commencing the main program functions. However, as depicted in
Figure 2, packers modify the entry point to direct it to their bootstrap code. In execution, the bootstrap code unpacks the original program, manages library loading, and allocates resources before triggering the OEP to execute the
temporarily unpacked program.
1.2. Anti-Analysis Techniques
Modern packers incorporate sophisticated anti-analysis techniques to evade detection by analysts and automated tools. These techniques include anti-debugging, anti-virtual machine, and anti-emulation strategies that complicate the analysis process. Previous studies have successfully bypassed such techniques in commercial protectors and unpacked malware protected by known packers [
5,
7,
16,
17]. However, challenges persist with unknown packers, and research is ongoing to overcome these obstacles from yet unidentified packers.
1.3. OEP Finding
The Original Entry Point (OEP) is a critical component in unpacking malware, as it represents the location where the unpacked code begins execution. Identifying the OEP in heavily obfuscated binaries is challenging. Traditional unpacking methods often employ a
Written-then-Execute approach to locate the OEP by analyzing instructions restored at runtime [
18,
19,
20,
21]. However, commercial protectors like Themida [
10], as shown in
Figure 3b, implement OEP obfuscation techniques that challenge these conventional methods. These techniques may involve the use of trampoline code or not.
1.4. Import Table Reconstruction
Reconstructing the import table is essential for understanding the external dependencies of a binary. Obfuscation techniques often modify or hide import table entries to thwart analysis. Our methodology leverages dynamic analysis to accurately rebuild the import table, revealing the true dependencies and enhancing the understanding of the malware’s functionality. Some research has successfully deobfuscated by examining five argument-insensitive API obfuscation techniques [
8,
13,
14]. Nevertheless, identifying obfuscated APIs becomes particularly challenging when dealing with argument-sensitive trampoline codes, which depend on API arguments.
1.5. OEP and API Obfuscation Techniques
Obfuscation techniques targeting the OEP and API calls are designed to mislead analysts and automated tools. These techniques include code virtualization, encryption, and polymorphism. We provide a comprehensive overview of these obfuscation strategies, highlighting their impact on the analysis process and the challenges they pose.
1.6. OEP Obfuscation: A Deep Insight
OEP obfuscation involves various methods to obscure the original entry point, making it difficult to locate and analyze. Techniques such as control flow manipulation and encryption are commonly used. Our deep dive into OEP obfuscation reveals the intricacies of these techniques and how our approach effectively counters them.
In approaches employing trampoline code, packers may remove branching around the OEP, as with Themida. Execution then involves either the bootstrap or trampoline code replicating the effects of these removed instructions, complicating OEP detection and risking program termination if untreated trampoline codes lead to invalid memory access at startup. Packers like VMProtect [
9], illustrated in
Figure 3c, might have bootstrap code directly execute targets without fully restoring the OEP, presenting additional challenges for its identification.
In contrast, techniques not involving trampoline code may further conceal the OEP or access it through multiple branches. Once reached, however, the execution mirrors that of non-obfuscated programs. Packers such as ASProtect [
12] and Obsidium [
11] adopt this method, indicating that conventional unpacking can successfully detect the OEP in these cases.
1.7. API Obfuscation: A Deep Insight
API obfuscation aims to hide or alter API calls to prevent detection and analysis. Techniques include API redirection and dynamic import resolution. We delve into these methods, explaining their mechanism and how our combined use of DBI and emulators successfully deobfuscate API calls, ensuring accurate analysis of the malware’s behavior.
API obfuscation techniques, which alter API calls or IAT entries, are a prevalent strategy among packers. They reconstruct the import table exclusively during runtime, thus requiring dynamic analysis after the API has been bound. These techniques, including trampoline code, are designed to obfuscate control flow and complicate analysis by employing tactics like
Dead Code Inserting and
Constant Propagation [
7]. Trampoline codes can be invoked in two primary ways:
Indirect Calls: Packers such as Themida use the IAT to bind trampoline codes at runtime, redirecting API calls to these codes (
Figure 4a,d).
Direct Calls: Alternatively, packers like VMProtect and ASProtect modify API call instructions to point directly to trampoline codes, bypassing the IAT (
Figure 4b,c).
These trampoline codes, integral to the execution logic, serve to conceal the control flow and call API addresses in a masked manner. Packers such as Themida, VMProtect, and Obsidium typically employ
argument-insensitive trampoline code, where each obfuscated API is associated with its specific trampoline code. In contrast, packers like ASProtect use
argument-sensitive trampoline codes, where the API address depends on the provided arguments, leading all obfuscated APIs to a single trampoline code. This variation presents a significant challenge for deobfuscation efforts [
8].
Figure 4.
The control flow of API obfuscation techniques.
Figure 4.
The control flow of API obfuscation techniques.
1.8. Summary of Related Works on Malware Unpacking and Analysis Techniques
Table 1 provides a comprehensive overview of the literature on malware unpacking and analysis techniques, summarizing the research design, methodologies, contributions, and results of related works. This table serves as a foundational reference for understanding the current state of the art and positioning our contributions within this context.
4. Discussion
Analyzing malware is inherently challenging, and no method can claim to be perfect. Security researchers often select techniques that best suit their specific needs, while accepting inevitable trade-offs. Various approaches aimed at rendering malware into an analyzable state often face countermeasures implemented by sophisticated malware. This section discusses the role of DBI and emulators in malware analysis, how our proposed system overcomes the limitations of existing systems, and its integration with existing knowledge, and it examines potential attacks against Pinicorn and its inherent limitations.
4.1. Role of DBI and Emulators in Malware Analysis
Dynamic binary instrumentation and emulation technologies have evolved significantly, becoming critical tools in malware analysis. DBI frameworks, such as Intel Pin and DynamoRIO, allows for dynamic analysis of binary executables by inserting instrumentation code at runtime. This capability enables detailed monitoring and analysis of program behavior without modifying the binary code.
Early DBI systems were limited by performance overhead and compatibility issues, which restricted their application in real-time malware analysis. However, advancements in DBI technology have addressed many of these limitations. Modern DBI frameworks offer improved performance, greater flexibility, and support for a wide range of architectures and operating systems. These enhancements have made DBI an invaluable tool for analyzing obfuscated and packed malware.
Emulators, such as QEMU and Unicorn, simulate the execution of binary code in a controlled environment, allowing analysts to observe malware behavior without the risk of infection. These tools have evolved to provide high-quality simulation of various CPU architectures and system environments, expanding their applicability in malware analysis.
4.2. Overcoming Limitations of Existing Systems
Traditional malware unpacking systems often struggle with several limitations, including the following:
Detection Evasion: Advanced malware employs anti-analysis techniques to detect and evade previous analysis environments, rendering many tools ineffective.
Dynamic Analysis Limitations: Dynamic analysis tools cannot execute or monitor all behaviors of a binary code. This limitation can prevent the analysis of certain obfuscated code, making them impractical for unpacking some malware. Specifically, dynamic analysis may miss code paths that are rarely executed or require specific triggers to activate. By not capturing all possible execution paths, these tools might fail to fully unpack or understand the malware’s functionality, reducing their effectiveness in thorough malware analysis.
Our proposed solution leverages modern DBI and emulation technologies to overcome these limitations. By utilizing Intel Pin to dump the temporarily unpacked process in memory and performing static analysis on the memory dump to detect trampoline code used in obfuscation techniques, and employing Unicorn to analyze the trampoline code, we can achieve comprehensive monitoring of malware behavior. The integration of these approaches allows for the detection of anti-analysis techniques and the reconstruction of obfuscated code.
4.3. Integration with Existing Systems
Our approach builds on existing knowledge in malware analysis by integrating DBI and emulators into the broader framework of dynamic and static analysis techniques. Related works have demonstrated the effectiveness of DBI and emulators in various contexts, but few have explored their combined potential in tackling both OEP and API obfuscation simultaneously.
For instance, Park et al. [
16] utilized Intel Pin to detect and bypass anti-debugging techniques, demonstrating the framework’s robustness. Similarly, Choi et al. [
7] combined instruction emulation with direct execution to handle anti-reverse engineering techniques, showcasing the power of emulation in malware analysis. Our work extends these studies by integrating DBI and emulation to provide a more comprehensive solution that addresses multiple layers of obfuscation. Furthermore, API-Xray [
8] demonstrated the capability of reverse engineering by reconstructing the import tables of obfuscated malware. This study highlights the effectiveness of dynamic and static analysis techniques in overcoming advanced obfuscation strategies, reinforcing the potential of our integrated approach to achieve similar successes in unpacking and analyzing complex malware.
4.4. Potential Attacks and Measures
4.4.1. DBI Detection Attacks
Intel Pin, as a DBI framework, enables the execution of packed programs that use anti-analysis techniques. Despite its resilience [
7,
16,
17], some sophisticated methods can still detect Pin and similar DBI frameworks. Thus, despite protective measures, some packed malware may recognize Pinicorn’s DBI module, triggering its bootstrap code and hindering memory dumping.
4.4.2. Anti-Debugging Attacks in Trampoline Code
Our study primarily investigated commercial packers known for regular updates, focusing on OEP and API obfuscation techniques. Although our reviewed techniques did not employ anti-debug APIs during trampoline code execution, other studies have reported such instances within API obfuscation’s trampoline codes [
8]. This implies the possibility that some sophisticated packed malware might detect emulation of their trampoline codes.
4.5. Limitation
4.5.1. Context Dump Problem
Most unpackers run the packed program until it naturally concludes [
18,
32]. In virtual or sandbox environments, this can result in incomplete unpacking due to time constraints. Pinicorn captures the moment when the bootstrap code temporarily restores the original program in memory, then performs a comprehensive memory dump. However, this approach encounters several challenges:
We utilized PinDemonium’s OEP detection to recognize when the program’s original state is restored. Pinicorn identifies trampoline code from several OEP candidates. Analyzing multiple candidates and performing memory dumps for each significantly impacts performance.
Operating in a virtual machine with a 30-min runtime limit, Pinicorn faced resource allocation challenges for malware dumping across 15 virtual machines. This occasionally resulted in restoring virtual machine snapshots before executing the packed malware’s original code.
In experiments with malware, issues may arise from anti-analysis techniques in unknown versions of known packers, which cannot be completely bypassed. To improve this, there is a need to analyze as many versions of packers as possible and implement additional bypass modules.
4.5.2. Stolen Function
Some packers utilize the
Stolen Function technique, copying entire Windows API instructions directly rather than redirecting through trampoline code [
8]. This technique presents a challenge for Pinicorn in identifying these copies, as no redirection takes place. In our research, this issue was observed with only a few APIs, such as
GetCurrentThreadID.
4.5.3. Unknown Argument-Sensitive Trampoline Code for API Obfuscation
Among the examined tools, only ASProtect employs
argument-sensitive trampoline code in its API obfuscation. It switches from argument-sensitive to argument-insensitive call instructions at runtime, depending on preceding arguments. This complexity makes traditional deobfuscation methods, which primarily focus on trampoline code execution, less effective [
8]. To overcome this, Pinicorn initiates emulation from the basic block that contains the call instruction (
Figure 4c), covering necessary argument-related trampoline codes and facilitating effective tracking and precise identification of obfuscated API. However, malwares using unknown packers might employ other advanced argument-sensitive API obfuscation patterns, introducing further challenges.
4.5.4. Problems of Deobfuscation Approaches
Despite efforts to unpack malware for analysis, completely reversing certain malware to its original state proves challenging, particularly in pinpointing crucial elements such as OEP and IAT, which vary with the obfuscation tool employed [
5,
17,
21]. As a result, the reconstructed binaries might not functionally match their original counterparts, heightening the likelihood of deobfuscation failures.
4.5.5. Deobfuscation Challenges with Obfuscated Malware by ASProtect
We conducted deobfuscation experiments on malware, focusing on samples obfuscated with Themida, VMProtect, and ASProtect, sourced from the VirusShare dataset. Unfortunately, we were unable to deobfuscate any of the samples obfuscated with ASProtect. The main challenge was the difficulty in accurately identifying the ASProtect version used in the malware. Pinicorn analyzed the obfuscation techniques applied in ASProtect version 2.78, but like many obfuscation tools, older version of ASProtect could potentially use completely different obfuscation patterns.
4.5.6. Obsidium Malware Sample Were Not Found
We used malware samples from VirusShare, specifically targeting PE samples, to identify packing with PyPackerDetect. While this tool successfully detected malware packed by Themida, VMProtect, and ASProtect, we did not find any samples packed with Obsidium. Consequently, we did not conduct experiments on Juliet Test Suite samples protected by Obsidium.
4.5.7. Application to Other Operating Systems
Our study primarily focuses on Windows-based malware and obfuscation techniques. However, it is important to consider the applicability of our proposed methods to other operating systems such as Linux and macOS. Each operating system has unique characteristics and environments that can result in differences in the application process. Firstly, we used the Intel Pin DBI framework. Intel Pin operates only in Intel CPU-based environments and does not work on other architectures such as ARM. However, alternative frameworks like DynamoRIO are available for these environments. Secondly, we analyzed the anti-analysis techniques used in Windows operating system and implemented modules to bypass them. However, the anti-analysis techniques used in Linux and macOS can vary. For example, Linux malware might leverage ptrace-based anti-debugging techniques, requiring different bypass strategies compared to those used for Windows-based packers. Thirdly, we focused on analyzing the technique used by protectors that apply packing and obfuscation to PE binaries in the Windows operating systems. Packers targeting ELF and Mach-O binaries may employ different forms of obfuscation techniques. Addressing these would require additional analysis. In conclusion, while our current approach demonstrates potential for Windows-based malware, applying and extending it to other operating systems will require further work. Such efforts are expected to enhance the ability to unpack and analyze malware across diverse operating system environments.
4.6. Out-of-Scope
4.6.1. Limited Scope of Examined Commercial Protectors
Our study focuses on four prevalent packers, Themida, VMProtect, ASProtect, and Obsidium [
11], selected for their consistent updates and implementation of OEP and API obfuscation techniques. While these packers offer unique obfuscation strategies, addressing unknown packers and their techniques remains a formidable challenge. Ongoing efforts are needed to analyze and deobfuscate a wider range of packers to effectively counteract unidentified malwares.
4.6.2. Macro-Based Source Code Obfuscation
The packers in our study employ various obfuscation techniques, including source code level obfuscation prior to binary compilation, a method known as
macro-based obfuscation [
10]. This includes techniques like
code virtualization,
string obfuscation, and
resource obfuscation. However, our research primarily focuses on the trampoline code-based obfuscation of OEP and API, excluding macro-based source-level obfuscation from our purview.
5. Conclusions
Recent research on deobfuscation has primarily targeted API obfuscation techniques that complicate the reconstruction of the import table. However, these efforts have not successfully reconstructed import tables obfuscated using trampoline codes that are sensitive to the API’s arguments. Moreover, the lack of research on OEP obfuscation techniques, combined with their application in malware, has led to failures in unpacking such obfuscated malware. To address these gaps, this paper analyzes the OEP and API obfuscation techniques employed by various packers and introduces an effective deobfuscation approach.
Our proposed system leverages dynamic binary instrumentation tools and emulators to identify information obfuscated by trampoline codes sensitive to API arguments. It also discerns the presence or absence of trampoline code calls among OEP candidates and identifies deleted OEP instructions. This approach enables the deobfuscation and unpacking of malware obfuscated through trampoline codes. However, as unknown packers may employ different techniques for OEP and API obfuscation, and given the potential for obfuscating a wide range of information beyond OEP and API, challenges in malware analysis are likely to continue.
Limitations and Future Works
Firstly, Pinicorn is designed to primarily unpack malware that has been protected using prevalent packers such as Themida, VMProtect, ASProtect, and Obsidium. Should Pinicorn encounters malware packed with different tools, it may not successfully unpack it. Consequently, it is essential to identify the packing tool used on the malware to effectively utilize Pinicorn. Additionally, Pinicorn targets deobfuscation techniques primarily focused on OEP obfuscation and API obfuscation. Like other unpackers, Pinicorn may fail to unpack if it encounters obfuscation techniques beyond its designed capabilities. We note that unpacking unknown and obfuscated malware is a challenging problem, and the limitation is common in dynamic analysis-based approaches. We leave these limitations as future work.