scispace - formally typeset
Search or ask a question
Book ChapterDOI

A novel obfuscation: class hierarchy flattening

25 Oct 2012-Vol. 7743, pp 194-210
TL;DR: For real-life programs from the DaCapo benchmark suite, it is demonstrated that the transformation effectively hinders both human and tool analyses, and that it does so at limited overheads.
Abstract: This paper presents class hierarchy flattening, a novel obfuscation technique for programs written in object-oriented, managed programming languages. Class hierarchy flattening strives for maximally removing the inheritance relations from object-oriented programs, thus hiding the overall design of the program from reverse engineers and other attackers. We evaluate the potential of class hierarchy flattening by means of a fully automated prototype tool for Java bytecode. For real-life programs from the DaCapo benchmark suite, we demonstrate that the transformation effectively hinders both human and tool analyses, and that it does so at limited overheads.

Summary (2 min read)

1 Introduction

  • Reverse engineering and modification of managed code are well-understood and common practices, with many legitimate goals [16].
  • This symbolic information is also what makes managed code easier to understand, reverse engineer, decompile, modify, reuse and steal.
  • Others try to remove information that is useful informally, such as field and method identifiers [2, 5].
  • This paper takes application design obfuscation one step further.
  • The authors discuss the necessary analyses and transformations to automate CHF and present a proof-of-concept tool.

2 Rationale: an Example Program

  • To set the context for a detailed discussion of their obfuscating class hierarchy transformation, the authors first present an example consisting of a media player.
  • Depending on the actual run-time type of the MediaStream objects, they are either cast to AudioStream or VideoStream, such that the correct play method is invoked (lines 14 and 16).
  • The inheritance relations are meaningful and code shared between different classes is located in a common superclass.
  • All media streams are decrypted using the getRawBytes method declared in MediaStream.
  • Code analysis has also become harder, as the code in the transformed application ) contains less type information than the original application.

3.1 Basic Algorithm

  • The basic class hierarchy flattening (CHF) algorithm consists of five steps.
  • This limitation is similar to the limitations imposed to several code refactoring transformations.
  • Ti Each subtree will then be transformed into one flat set of classes that all implement a common interface and that are all direct subclasses of the direct superclass of the tree’s root.
  • As such, their treatment of casts is similar to that in other code refactoring techniques that change type hierarchies [31].
  • Each row in the lookup table initially corresponds to one of the instanceof expression oi instanceof.

3.2 Extensions

  • Several extensions to CHF can be considered.
  • By copying function bodies from unrelated classes, the authors can make unrelated classes look related and vice versa.
  • To prevent the propagation of precise type information at allocation sites, the authors can replace individual allocations by multiple ones by means of opaque predicates [24].
  • The effect of such object allocation obfuscations, when not undone by an attacker, will be that no points-to analysis, however complicated, will compute more precise results than the analysis based on class hierarchy analysis [10].
  • Coalescing MP3 File and VideoStream in Figure 1 with the algorithm proposed by Sosonkin et al. [28] would require MediaFile and MediaStream to be coalesced as well.

4 Evaluation

  • The authors implemented CHF in Soot 2.5.0 [18, 32], an analysis and transformation framework for Java bytecode.
  • As their tool rewrites the application bytecode that the developer has packaged in a collection of jar files, it does not require any changes to the application’s source code.
  • The authors implementation consists of two parts; a CHFTransformer and a refactoring toolkit.
  • To detect the set of non-transformable classes and to ensure that all Java features like reflection and dynamic class loading are handled correctly, the authors rely on TamiFlex, a tool developed specifically for facilitating the static analysis of Java programs that use such features [4].
  • As a profile-based tool, TamiFlex relies on the developer to provide program inputs that generate enough coverage.

4.1 Benchmarks

  • The authors use the DaCapo 9.12 benchmark suite [3] to evaluate the protection-wise effectiveness and the performance-wise efficiency of CHF.
  • Because of space concerns, the authors report results for the four applications listed in Table 2.
  • For eclipse, the number of transformable classes is much lower, because of restrictions imposed by dynamically generated classes.
  • The first, base version is the original bytecode that comes with the DaCapo suite, but with identifier names obfuscated [7].
  • For each merge threshold value, the tool generates ten different program versions with ten different random seeds.

4.2 Results

  • Protection against Human Program Understanding Given an original program with a normalized understandability score of -0.99 (as defined in [1]), less understandable versions will have lower scores.
  • In all benchmarks, a considerable number of points-to sets does not grow even when more interfaces are merged.
  • Overhead Figure 9 depicts the relative code size increase as a result of the basic flattening and interface merging.
  • The overheads reported in Figure 11(a) include all 10 runs of the benchmarks in their harness.

Did you find this useful? Give us your feedback

Content maybe subject to copyright    Report

A Novel Obfuscation: Class Hierarchy Flattening
Christophe Foket
?
, Bjorn De Sutter, Bart Coppens, and Koen De Bosschere
Computer Systems Lab
Electronics and Information Systems Department
Ghent University
Sint-Pietersnieuwstraat 41, 9000 Ghent, Belgium
{cfoket,bcoppens,kdb,brdsutte}@elis.ugent.be
Abstract. This paper presents class hierarchy flattening, a novel ob-
fuscation technique for programs written in object-oriented, managed
programming languages. Class hierarchy flattening strives for maximally
removing the inheritance relations from object-oriented programs, thus
hiding the overall design of the program from reverse engineers and
other attackers. We evaluate the potential of class hierarchy flattening by
means of a fully automated prototype tool for Java bytecode. For real-life
programs from the DaCapo benchmark suite, we demonstrate that the
transformation effectively hinders both human and tool analyses, and
that it does so at limited overheads.
Key words: Java bytecode, obfuscation, class hierarchy, program design
1 Introduction
Reverse engineering and modification of managed code are well-understood and
common practices, with many legitimate goals [16]. Malicious developers can
abuse them, however, to attack Java and .NET applications with the goals of
software piracy, software IP theft, and data theft. Their attacks are facilitated by
the fact that managed code is executed at a high abstraction level. To combine
run-time efficiency with programmer productivity, a large amount of symbolic
information needs to be presented to the virtual machines that execute the code.
This is needed, e.g., to enable effective and efficient just-in-time (JIT) compila-
tion, to support efficient garbage collection, and to support reflection and byte-
code verification. This symbolic information is also what makes managed code
easier to understand, reverse engineer, decompile, modify, reuse and steal.
With respect to reverse engineering (and all practices for which reverse en-
gineering is a prerequisite), many different obfuscation techniques have been
proposed. Some try to prevent automatic decompilation [5, 17], some try to hide
?
The authors want to thank the Agency for Innovation by Science and Technology in
Flanders (IWT) for their support and Ghent University, the Hercules Foundation and
the Flemish Government - department EWI who funded the STEVIN Supercomputer
Infrastructure at Ghent University on which we carried out part of this work.

2 Christophe Foket, Bjorn De Sutter, Bart Coppens, and Koen De Bosschere
data (flow) properties [8, 34] or control flow properties [8, 9, 17, 19, 20, 22, 24, 33]
from both tools and humans. Others try to remove information that is useful in-
formally, such as field and method identifiers [2, 5]. Finally, a few have proposed
obfuscating the overall application design by altering the class and interface hi-
erarchy to make it harder to understand for software engineers [28]. The latter
techniques aim for the opposite of classic code refactoring [27, 31].
This paper takes application design obfuscation one step further. Instead of
merely modifying an application’s type hierarchy, we propose a technique called
class hierarchy flattening (CHF) to get rid of it altogether. Given a number of
constraints because of, e.g., compatibility with external libraries, CHF strives for
a class hierarchy that is as flat as possible, i.e., in which application classes are
siblings rather than subtypes and supertypes. We discuss the necessary analyses
and transformations to automate CHF and present a proof-of-concept tool. We
evaluate the level of software protection provided by CHF and its overhead.
The remainder of this paper is structured as follows. First, Section 2 discusses
the conceptual goals of CHF by means of an example program. The transforma-
tion itself is discussed in some detail in Section 3, and evaluated in Section 4. We
compare CHF to related work in Section 5. Finally, Section 6 draws conclusions
and discusses some future extensions.
2 Rationale: an Example Program
To set the context for a detailed discussion of our obfuscating class hierarchy
transformation, we first present an example consisting of a media player. It
consists of three main parts: (1) the player initializer (2) support for media files
and (3) support for media streams contained in the media files. Different subtrees
of the class hierarchy implement those parts, as shown in Figure 1. The code in
Figure 2(a) illustrates their interaction.
The main method of class Player creates an array of MediaFile objects to
be played (line 10). It then queries each of the media files in this list for its media
streams (line 12), which are initialized when the media file is accessed with the
readFile method. Figure 2(a) shows how this is done for the MP3File class,
which represents MP3 files containing MPEG audio streams.
During playback, the player checks the run-time type of the MediaStream
object associated with the stream (lines 13 and 15) to decide where it needs to
be output. Depending on the actual run-time type of the MediaStream objects,
they are either cast to AudioStream or VideoStream, such that the correct
play method is invoked (lines 14 and 16). The play methods essentially output
the raw bytes of the media streams’ analog signals for a specific output device.
Those bytes are obtained, decrypted (lines 35–36) and decoded (line 37) with the
getRawBytes method declared in MediaStream. Note that because the decoding
process is different for each type of media stream, the decode method is declared
as abstract, such that it can be implemented by subclasses of MediaStream. The
decryption process, on the other hand, is the same for each type of media stream
and is therefore handled by the MediaStream class.

A Novel Obfuscation: Class Hierarchy Flattening 3
MediaStream
- da ta :b yte[]
- KE Y :b yte[]
# decode (byte[ ]) :b yte[]
+ getRawBytes() :byte[]
AudioStream
# au di oBu ffer :int[]
# decode (byte[ ]) :b yte[]
# decode Sample() :byte []
VideoS tream
# vid eoBu ffer :int[][ ]
# decode (byte[ ]) :b yte[]
# decode Frame() :b yte[]
MediaFile
# fil ePath :String
# mediaStreams :M edia Strea m[]
# readFile () :v oi d
+ ge tStreams() :Me diaS tream []
MP3File
# readFile () :v oi d
MP4File
# rea dFile () :void
j ava.la ng.Object
XvidStr eam
# de code Fram e() :b yte[]
MPGAS tream
# de code Samp le() :byte []
DTSStream
# de code Samp le() :byte []
Player
+ ma in(St ring[] ) :vo i d
+ play (Au dioSt ream ) :vo id
+ play (Vid eoSt ream ) :vo id
Fig. 1: Class hierarchy of a simple DRM media player
From a software-engineering point of view, the media player application is
well structured. The inheritance relations are meaningful and code shared be-
tween different classes is located in a common superclass. While we could have
further improved the structure of the program by factoring out the casts and
run-time type checks, we chose not to do so for educational purposes.
From a security perspective, however, some problems arise. First, the class
hierarchy provides reverse engineers with information about the relationships
between classes and the abstraction levels of the functionalities provided by
classes (with classes higher in the hierarchy typically providing more abstract
functionality). Secondly, code sharing through inheritance enables attacks in
which compromising one class can cause all of its subclasses to be compromised.
All media streams are decrypted using the getRawBytes method declared in
MediaStream. Therefore, when an attacker reverse-engineers this method, he
will be able to decrypt all supported media stream types. Finally, we observe
that the program contains much type information, which simplifies both manual
analysis and automated analysis that rely on, a.o., point-to set computations.
These issues can be solved by rewriting the well-structured hierarchy into the
unstructured class collection of Figure 3. To determine how classes are related,
an attacker can then no longer rely on the class hierarchy. He will instead have
to analyze and compare all classes in the application. Furthermore, as all classes
are provided with a (diversified) copy of all fields and methods declared in their
former superclasses, they have become functionally more independent. Code is
no longer shared between related classes, so attackers can no longer attack many
classes at once by patching their common superclass. In short, more actual code
analysis and tampering will be needed to mount a successful attack.

4 Christophe Foket, Bjorn De Sutter, Bart Coppens, and Koen De Bosschere
public class Player{
public void play(AudioStream as) {
/* send as.getRawBytes() to audio device */
}
public void play(VideoStream vs) {
/* send vs.getRawBytes() to video device */
}
public stac void main(String[] args) {
Player player = new Player();
MediaFile[] mediaFiles = ...;
for(MediaFile mf : mediaFiles) {
for(MediaStream ms : mf.getStreams())
if(ms instanceof AudioStream)
player.play((AudioStream)ms);
else if(ms instanceo
f VideoStream)
player.play((VideoStream)ms);
}
}
}
public class MP3File extends MediaFile {
protected void readFile() {
InputStream inputStream = ...;
byte[] audioData = new byte[...];
inputStream.read(audioData);
AudioStream as = new MPGAStream(audioData);
mediaStreams = new MediaStream[]{as};
}
}
public abstract class MediaStream {
public stac nal byte[] KEY = ...;
public byte[] getRawBytes() {
byte[] decrypted = new byte[data.length];
for(int i
= 0; i < data.length; i++)
decrypted[i] = data[i] ^ KEY[i];
return decode(decrypted);
}
protected abstract byte[] decode(byte[] data);
}
public class Player implements Common {
public void play(Common as) {
/* send as.getRawBytes() to audio device */
}
public void play1(Common vs) {
/* send vs.getRawBytes() to video device */
}
public stac void main(String[] args) {
Common player = new Player();
Common [] mediaFiles = ...;
for(Common mf :
mediaFiles) {
for(Common ms : mf.getStreams())
if(myChecker.isInstance(0, ms.getClass()))
player.play(ms);
else if(myChecker.isInstance(1, ms.getClass()))
player.play1(ms);
}
}
}
public class MP3File implements Common {
public void readFile() {
InputStream inputStream = ...;
byte[] audioData = new byte[...];
inputStream.read(audioData);
Common as = new MPGAStream(audioData);
mediaStreams = new Common []{as};
}
}
public class MediaStream implements Common {
public stac nal byte[] KEY = ...;
public byte[] getRawBytes() {
byte[] decrypted = new byte[data.length];
for(int i = 0; i < data.length; i++)
decrypted[i] = data[i] ^ KEY[i];
return decode(decrypted);
}
public abstract byte[] decode(byte[] data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
(a) original code
(b) aened code
Fig. 2: Partial implementation of the Player, MediaStream and MP3File classes
Code analysis has also become harder, as the code in the transformed appli-
cation (shown in Figure 2(b)) contains less type information than the original
application. This follows from all declaration types being replaced by a new
Common type. Since this interface type serves as a common supertype for all
classes in the application and declares all their instance methods, all classes im-
plement a significantly larger number of methods. The subset of those methods
that are never called at run time can be filled in with arbitrary code, to make
the static analysis of the application even more complex.
3 Class Hierarchy Flattening
This section presents the analyses and transformations needed to automatically
transform the unprotected program into the one that is much harder to attack.

A Novel Obfuscation: Class Hierarchy Flattening 5
Me diaS tream
- da ta :b yte[]
- KE Y :b yte[]
# de code( byte[ ]) :byte[]
+ getRawBytes() :byte[]
# de codeS amp le() :byte []
# de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
AudioStream
# au di oBu ffer :i nt[]
- da ta :b yte[]
- KE Y :b yte[]
# de code( byte[ ]) :byte[]
# de codeS amp l e() : byte[ ]
+ getRawBytes() :byte[]
# de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
Vid eoStream
# vid eoBu ffer :int[][ ]
- da ta :b yte[]
- KE Y :b yte[]
# de code( byte[ ]) :byte[]
# de codeF rame () :b yte[]
+ getRawBytes() :byte[]
# de codeS amp le() :byte []
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
Me diaF ile
# file Path :Stri ng
# me diaS tream s :Comm on[]
+ de code( byte[ ]) :byte[]
# rea dFile () :void
+ getRawBytes() :byte[]
+ ge tStrea ms() :Com mon []
+ de codeS amp l e() :byte []
+ de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
MP 4File
- fi l e Path :Str i ng
- me di aS tream s :C omm on[]
+ de code( byte[ ]) :byte[]
# rea dFile () :void
+ getRawBytes() :byte[]
+ ge tStrea ms() :Com mon []
+ de codeS amp l e() :byte []
+ de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
Xv idS tr eam
- vid eoBu ffer :int[][ ]
- da ta :b yte[]
- KE Y :b yte[]
# de codeF ram e() :b yte[]
# de code( byte[ ]) :byte[]
+ getRawBytes() :byte[]
# de codeS amp le() :byte []
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
MP GAStream
- au dioBu ffer :int[]
- da ta :b yte[]
- KE Y :b yte[]
# de codeS amp le() :byte []
# de code( byte[ ]) :byte[]
+ getRawBytes() :byte[]
# de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
MP 3File
- fi l e Path :Str i ng
- me di aS tream s :C omm on[]
+ de code( byte[ ]) :byte[]
# rea dFile () :void
+ getRawBytes() :byte[]
+ ge tStrea ms() :Com mon []
+ de codeS amp l e() :byte []
+ de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
DTSStream
- au dioBu ffer :int[]
- da ta :b yte[]
- KE Y :b yte[]
# de codeS amp le() :byte []
# de code( byte[ ]) :byte[]
+ getRawBytes() :byte[]
# de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
Pla yer
+ de code( byte[ ]) :byte[]
+ ma in(String[] ) :vo id
+ getRawBytes() :byte[]
+ de codeS amp l e() :byte []
+ de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
«i n terfa ce»
Common
+ de code( byte[ ]) :byte[]
+ getRawBytes() :byte[]
+ de codeS amp l e() :byte []
+ de codeF ram e() :b yte[]
+ pla y(Commo n) :v oi d
+ pla y1(Com m on) : voi d
+ rea dFile () :void
+ ge tStrea ms() :Com mon []
Fig. 3: Flattened class hierarchy of the media player
3.1 Basic Algorithm
The basic class hierarchy flattening (CHF) algorithm consists of five steps.
Step 1: Subtree selection We assume that each application consists of a set of
application classes A that use or extend classes from a self-contained set of library
classes L that includes java.lang.Object. Classes in L are never considered for
transformation. L will usually correspond to the standard library, while A will
contain all classes that make up the actual application. In this paper, sub(x)
denotes all subclasses of class x, and super(x) its superclasses.
There is a subset X A of classes on which our CHF transformation is not
applicable because changing those classes’ position in the hierarchy can alter
the program behavior. This includes classes on which reflective operations are
performed such as getInterfaces() (which makes the program potentially de-
pendent on the number of interfaces implemented by a class), getSuperclass(),
isAssignableFrom(), getMethod(), etc.
As library classes cannot be rewritten, we cannot change their position in the
hierarchy, nor can we adapt their methods’ signatures, which typically involve
library types themselves. To maintain type correctness, this implies that in gen-
eral any application class a sub(l) with l L, needs to stay a subclass thereof.
This further implies that we cannot make all application classes direct subclasses
of java.lang.Object. This limitation is similar to the limitations imposed to
several code refactoring transformations. Those limitations have been formalized
in literature [31], so we will not repeat them here. As the classes in X cannot be
moved in the hierarchy either, similar limitations apply to them.

Citations
More filters
Journal ArticleDOI
TL;DR: The main goal of this survey is to analyze the effectiveness of different classes of software obfuscation against the continuously improving deobfuscation techniques and off-the-shelf code analysis tools.
Abstract: Software obfuscation has always been a controversially discussed research area. While theoretical results indicate that provably secure obfuscation in general is impossible, its widespread application in malware and commercial software shows that it is nevertheless popular in practice. Still, it remains largely unexplored to what extent today’s software obfuscations keep up with state-of-the-art code analysis and where we stand in the arms race between software developers and code analysts. The main goal of this survey is to analyze the effectiveness of different classes of software obfuscation against the continuously improving deobfuscation techniques and off-the-shelf code analysis tools. The answer very much depends on the goals of the analyst and the available resources. On the one hand, many forms of lightweight static analysis have difficulties with even basic obfuscation schemes, which explains the unbroken popularity of obfuscation among malware writers. On the other hand, more expensive analysis techniques, in particular when used interactively by a human analyst, can easily defeat many obfuscations. As a result, software obfuscation for the purpose of intellectual property protection remains highly challenging.

133 citations


Additional excerpts

  • ...Moreover, the idea of class hierarchy flattening to remove all inheritance relations from object-oriented programs was introduced in the literature [Foket et al. 2013, 2014]....

    [...]

Book ChapterDOI
01 Jan 2017
TL;DR: Software obfuscation as mentioned in this paper transforms a program into a functionally equivalent program which is harder for Man-At-The-End (MATE) attackers to break the confidentiality or integrity of digital assets, in detriment to digital asset creators and/or end-users.
Abstract: Protecting a digital asset once it leaves the cyber trust boundary of its creator is a challenging security problem. The creator is an entity which can range from a single person to an entire organization. The trust boundary of an entity is represented by all the (virtual or physical) machines controlled by that entity. Digital assets range from media content to code, and include items such as: music, movies, computer games and premium software features. The business model of the creator implies sending digital assets to end-users – such that they can be consumed – in exchange for some form of compensation. A security threat in this context is represented by malicious end-users, who attack the confidentiality or integrity of digital assets, in detriment to digital asset creators and/or other end-users. Software obfuscation transformations have been proposed to protect digital assets against malicious end-users, also called Man-At-The-End (MATE) attackers. Obfuscation transforms a program into a functionally equivalent program which is harder for MATE to attack. However, obfuscation can be use both for benign and malicious purposes. Malware developers rely on obfuscation techniques to circumvent detection mechanisms and to prevent malware analysts from understanding the logic implemented by the malware. This chapter presents a tutorial of the most popular existing software obfuscation transformations and mentions published attacks against each transformation. We present a snapshot of the field of software obfuscation and indicate possible directions, which require more research.

26 citations

Journal ArticleDOI
TL;DR: A systematic review of existing obfuscation techniques based on the idea of layered obfuscation and a novel taxonomy of obfuscation strategies under different branches that are orthogonal to each other are developed.
Abstract: Software obfuscation has been developed for over 30 years. A problem always confusing the communities is what security strength the technique can achieve. Nowadays, this problem becomes even harder as the software economy becomes more diversified. Inspired by the classic idea of layered security for risk management, we propose layered obfuscation as a promising way to realize reliable software obfuscation. Our concept is based on the fact that real-world software is usually complicated. Merely applying one or several obfuscation approaches in an ad-hoc way cannot achieve good obscurity. Layered obfuscation, on the other hand, aims to mitigate the risks of reverse software engineering by integrating different obfuscation techniques as a whole solution. In the paper, we conduct a systematic review of existing obfuscation techniques based on the idea of layered obfuscation and develop a novel taxonomy of obfuscation techniques. Following our taxonomy hierarchy, the obfuscation strategies under different branches are orthogonal to each other. In this way, it can assist developers in choosing obfuscation techniques and designing layered obfuscation solutions based on their specific requirements.

16 citations

Journal ArticleDOI
TL;DR: This work combines three transformations to obfuscate the type information in .Net and Java programs: class hierarchy flattening, interface merging and object factory insertion, which effectively hinders human and tool analysis with limited overhead.
Abstract: Bytecoded .Net and Java programs reveal type information through encoded type hierarchies, casts, field declarations and method signatures. This facilitates bytecode verification, but it also helps reverse engineers. To obfuscate the type information, we combine three transformations. Class hierarchy flattening removes as much of the type hierarchy from programs as possible. Interface merging and object factory insertion further remove type information from casts, method signatures, and object creation sites. We evaluate these techniques with a prototype tool for Java bytecode. On real-life programs from the DaCapo benchmark suite, we demonstrate that our approach effectively hinders human and tool analysis with limited overhead.

8 citations

Dissertation
01 Jan 2013

2 citations


Cites methods from "A novel obfuscation: class hierarch..."

  • ...• A Novel Obfuscation: Class Hierarchy Flattening Christophe Foket, Bjorn De Sutter, Bart Coppens, and Koen De Bosschere In International Symposium on Foundations & Practice of Security, 2012 [65]....

    [...]

References
More filters
Book
01 Jan 1994
TL;DR: The book is an introduction to the idea of design patterns in software engineering, and a catalog of twenty-three common patterns, which most experienced OOP designers will find out they've known about patterns all along.
Abstract: The book is an introduction to the idea of design patterns in software engineering, and a catalog of twenty-three common patterns. The nice thing is, most experienced OOP designers will find out they've known about patterns all along. It's just that they've never considered them as such, or tried to centralize the idea behind a given pattern so that it will be easily reusable.

22,762 citations


"A novel obfuscation: class hierarch..." refers background in this paper

  • ...Alternatively, we can introduce factories [12] that return all types that implement an interface....

    [...]

Book
Martin Fowler1
01 Jan 1999
TL;DR: Almost every expert in Object-Oriented Development stresses the importance of iterative development, but how do you add function to the existing code base while still preserving its design integrity?
Abstract: Almost every expert in Object-Oriented Development stresses the importance of iterative development. As you proceed with the iterative development, you need to add function to the existing code base. If you are really lucky that code base is structured just right to support the new function while still preserving its design integrity. Of course most of the time we are not lucky, the code does not quite fit what we want to do. You could just add the function on top of the code base. But soon this leads to applying patch upon patch making your system more complex than it needs to be. This complexity leads to bugs, and cripples your productivity.

5,174 citations

Book ChapterDOI
16 Aug 2001
TL;DR: A short overview of recent works on the problem of Decoding Reed Solomon Codes (aka Polynomial Reconstruction) and the novel applications that were enabled due to this development.
Abstract: Cryptography and Coding Theory are closely knitted in many respects Recently, the problem of Decoding Reed Solomon Codes (aka Polynomial Reconstruction) was suggested as an intractability assumption upon which the security of cryptographic protocols can be based This has initiated a line of research that exploited the rich algebraic structure of the problem and related subproblems of which in the cryptographic setting Here we give a short overview of recent works on the subject and the novel applications that were enabled due to this development

1,441 citations

Proceedings ArticleDOI
01 Nov 2010
TL;DR: Soot, a framework for optimizing Java* bytecode, is implemented in Java and supports three intermediate representations for representing Java bytecode: Baf, a streamlined representation of bytecode which is simple to manipulate; Jimple, a typed 3-address intermediate representation suitable for optimization; and Grimp, an aggregated version of Jimple suitable for decompilation.
Abstract: This paper presents Soot, a framework for optimizing Java* bytecode. The framework is implemented in Java and supports three intermediate representations for representing Java bytecode: Baf, a streamlined representation of bytecode which is simple to manipulate; Jimple, a typed 3-address intermediate representation suitable for optimization; and Grimp, an aggregated version of Jimple suitable for decompilation. We describe the motivation for each representation, and the salient points in translating from one representation to another. In order to demonstrate the usefulness of the framework, we have implemented intraprocedural and whole program optimizations. To show that whole program bytecode optimization can give performance improvements, we provide experimental results for 12 large benchmarks, including 8 SPECjvm98 benchmarks running on JDK 1.2 for GNU/Linuxtm. These results show up to 8% improvement when the optimized bytecode is run using the interpreter and up to 21% when run using the JIT compiler.

1,160 citations


"A novel obfuscation: class hierarch..." refers methods in this paper

  • ...0 [18, 32], an analysis and transformation framework for Java bytecode....

    [...]

01 Jul 1997
TL;DR: It is argued that automatic code obfuscation is currently the most viable method for preventing reverse engineering and the design of a code obfuscator is described, a tool which converts a program into an equivalent one that is more diicult to understand and reverse engineer.
Abstract: It has become more and more common to distribute software in forms that retain most or all of the information present in the original source code. An important example is Java bytecode. Since such codes are easy to decompile, they increase the risk of malicious reverse engineering attacks. In this paper we review several techniques for technical protection of software secrets. We will argue that automatic code obfuscation is currently the most viable method for preventing reverse engineering. We then describe the design of a code obfuscator, a tool which converts a program into an equivalent one that is more diicult to understand and reverse engineer. The obfuscator is based on the application of code transformations, in many cases similar to those used by compiler optimizers. We describe a large number of such transformations, classify them, and evaluate them with respect to their potency (To what degree is a human reader confused?), resilience (How well are automatic deobfuscation attacks resisted?), and cost (How much overhead is added to the application?). We nally discuss some possible deobfuscation techniques (such as program slicing) and possible countermeasures an obfuscator could employ against them.

1,019 citations


"A novel obfuscation: class hierarch..." refers background in this paper

  • ...[8] refactors a program in such a way that two or more unrelated classes come to share a superclass, thereby giving the impression that they are related....

    [...]

  • ...CHF can also prepare a program for false factoring [8]....

    [...]

  • ...data (flow) properties [8, 34] or control flow properties [8, 9, 17, 19, 20, 22, 24, 33] from both tools and humans....

    [...]

Frequently Asked Questions (2)
Q1. What contributions have the authors mentioned in the paper "A novel obfuscation: class hierarchy flattening" ?

This paper presents class hierarchy flattening, a novel obfuscation technique for programs written in object-oriented, managed programming languages. For real-life programs from the DaCapo benchmark suite, the authors demonstrate that the transformation effectively hinders both human and tool analyses, and that it does so at limited overheads. The authors evaluate the potential of class hierarchy flattening by means of a fully automated prototype tool for Java bytecode. 

Their future work will concentrate on more focused interface merging strategies to outperform random merging, on extending the basic protection as discussed in the paper, and on a more extensive evaluation involving more security metrics, including diffing-based metrics, and more complex points-to analyses.