SlideShare a Scribd company logo
Read Anytime Anywhere Easy Ebook Downloads at ebookmeta.com
x86 Software Reverse-Engineering, Cracking, and
Counter-Measures 1st Edition Stephanie Domas
https://ebookmeta.com/product/x86-software-reverse-
engineering-cracking-and-counter-measures-1st-edition-
stephanie-domas/
OR CLICK HERE
DOWLOAD EBOOK
Visit and Get More Ebook Downloads Instantly at https://ebookmeta.com
Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.
x86 Software Reverse-Engineering, Cracking, and Counter-
Measures (Tech Today) 1st Edition Domas
https://ebookmeta.com/product/x86-software-reverse-engineering-
cracking-and-counter-measures-tech-today-1st-edition-domas/
ebookmeta.com
Implementing Reverse Engineering: The Real Practice of X86
Internals, Code Calling Conventions, Ransomware
Decryption, Application Cracking, Assembly Language, ...
Open Source Tools (English Edition) Jitender Narula
https://ebookmeta.com/product/implementing-reverse-engineering-the-
real-practice-of-x86-internals-code-calling-conventions-ransomware-
decryption-application-cracking-assembly-language-open-source-tools-
english-edition/
ebookmeta.com
Cambridge IGCSE and O Level History Workbook 2C - Depth
Study: the United States, 1919-41 2nd Edition Benjamin
Harrison
https://ebookmeta.com/product/cambridge-igcse-and-o-level-history-
workbook-2c-depth-study-the-united-states-1919-41-2nd-edition-
benjamin-harrison/
ebookmeta.com
Low Level Light Shooting 1st Edition Richard Franks
https://ebookmeta.com/product/low-level-light-shooting-1st-edition-
richard-franks/
ebookmeta.com
A Medication Guide to Internal Medicine Tests and
Procedures 1st Edition Gregory J. Hughes
https://ebookmeta.com/product/a-medication-guide-to-internal-medicine-
tests-and-procedures-1st-edition-gregory-j-hughes/
ebookmeta.com
Twelfth Night The Pelican Shakespeare First Edition
William Shakespeare
https://ebookmeta.com/product/twelfth-night-the-pelican-shakespeare-
first-edition-william-shakespeare/
ebookmeta.com
The Fine Art of Small Talk: How to Start a Conversation,
Keep It Going, Build Networking Skills – and Leave a
Positive Impression! Debra Fine
https://ebookmeta.com/product/the-fine-art-of-small-talk-how-to-start-
a-conversation-keep-it-going-build-networking-skills-and-leave-a-
positive-impression-debra-fine/
ebookmeta.com
Psychological Applications and Trends 2021 2021st Edition
Clara Pracana
https://ebookmeta.com/product/psychological-applications-and-
trends-2021-2021st-edition-clara-pracana/
ebookmeta.com
Spiritual Warfare Fighting the Good Fight Fr. Vivian
Boland Op
https://ebookmeta.com/product/spiritual-warfare-fighting-the-good-
fight-fr-vivian-boland-op/
ebookmeta.com
Thank You Fossil Fuels and Good Night The 21st Century s
Energy Transition 1st Edition Gregory Meehan
https://ebookmeta.com/product/thank-you-fossil-fuels-and-good-night-
the-21st-century-s-energy-transition-1st-edition-gregory-meehan/
ebookmeta.com
x86 Software Reverse-Engineering, Cracking, and Counter-Measures 1st Edition Stephanie Domas
Table of Contents
Cover
Table of Contents
Title Page
Introduction
Who Should Read This Book
What to Expect from This Book
History
Legal
Chapter 1: Decompilation and Architecture
Decompilation
Lab 1: Decompiling
Architecture
Summary
Chapter 2: x86 Assembly: Data, Modes, Registers, and Memory
Access
Introduction to x86
Assembly Syntax
Data Representation
Registers
Memory Access
Addressing Modes
Summary
Chapter 3: x86 Assembly: Instructions
x86 Instruction Format
x86 Instructions
Putting It All Together
Common x86 Instruction Mistakes
Summary
Chapter 4: Building and Running Assembly Programs
Output
System Calls
Building and Linking
objdump
Lab: Hello World
ASCII
Summary
Chapter 5: Understanding Condition Codes
Condition Codes
Summary
Chapter 6: Analyzing and Debugging Assembly Code
Binary Analysis
Breakpoints
gdb
Segmentation Faults
Lab: Shark Sim 3000
Tuning Out the Noise
Summary
Chapter 7: Functions and Control Flow
Control Flow
Logic Constructs in x86
Stack
Function Calls and Stack Frames
Summary
Chapter 8: Compilers and Optimizers
Finding Starting Code
Compilers
Summary
Chapter 9: Reverse Engineering: Tools and Strategies
Lab: RE Bingo
Basic REconnaissance
Reverse Engineering Strategy
Summary
Chapter 10: Cracking: Tools and Strategies
Key Checkers
Key Generators
Lab: Introductory Keygen
Procmon
Resource Hacker
Patching
Other Debuggers
Debugging with Immunity
Lab: Cracking with Immunity
Summary
Chapter 11: Patching and Advanced Tooling
Patching in 010 Editor
CodeFusion Patching
Cheat Engine
Lab: Cracking LaFarge
IDA Introduction
IDA Patching
Lab: IDA Logic Flows
Ghidra
Lab: Cracking with IDA
Summary
Chapter 12: Defense
Obfuscation
Lab: Obfuscation
Anti-Debugging
Lab: Anti-Debugging
Summary
Chapter 13: Advanced Defensive Techniques
Tamper-Proofing
Packing
Lab: Detecting and Unpacking
Virtualization
Cryptors/Decryptors
Summary
Chapter 14: Detection and Prevention
CRC
Code Signing
RASP
Allowlisting
Blocklisting
Remote Authentication
Lab: ProcMon
Summary
Chapter 15: Legal
U.S. Laws Affecting Reverse Engineering
Summary
Chapter 16: Advanced Techniques
Timeless Debugging
Summary
Chapter 17: Bonus Topics
Stack Smashing
Connecting C and x86
Summary
Conclusion
Index
Copyright
About the Authors
About the Technical Writer
About the Technical Editor
End User License Agreement
List of Tables
Chapter 4
Table 4.1: x86 Ports
Table 4.2: sys_write
Table 4.3: sys_exit
Chapter 7
Table 7.1: x86 conditional jump instructions
Table 7.2: Pushing a variable onto the stack
Table 7.3: Popping a variable from the stack
Table 7.4: Stack trace examples
Table 7.5: Function calls and the stack
Table 7.6: Program stack after calling a
Table 7.7: Program stack after calling b
Table 7.8: Program stack after calling c
Table 7.9: Stack in add function
Table 7.10: Effects of function prologue on stack
Table 7.11: Effects of function epilogue on stack
Table 7.12: Stack locations for common values
Table 7.13: Stack content at points 1, 2, and 3 in the
program
Table 7.14: Stack frame of one_up program
Table 7.15: Stack locations for local variables
Table 7.16: Complete function stack frame
Table 7.17: Two types of prologues
Table 7.18: Two types of epilogues
List of Illustrations
Chapter 1
Figure 1.1: JetBrains dotPeek .NET decompiler
Figure 1.2: Obfuscation in JetBrains dotPeek
Figure 1.3: Computer architecture
Figure 1.4: Intel Core 2 architecture
Chapter 2
Figure 2.1: Hexadecimal
Figure 2.2: Base conversions in the Windows calculator
Figure 2.3: Bit and byte significance labels
Figure 2.4: Endianness
Figure 2.5: x86 registers
Figure 2.6: Pieces of the eax register
Figure 2.7: Common x64 registers
Figure 2.8: Pieces of the r8 register
Figure 2.9: Comparing differently sized mov instructions
Chapter 3
Figure 3.1: mov instructions
Chapter 4
Figure 4.1: Binary wristwatch
Figure 4.2: ASCII table
Figure 4.3: Program output
Figure 4.4: ASCII uppercase and lowercase values
Chapter 5
Figure 5.1: Effects of add al,bl with various inputs
Figure 5.2: Effects of sub al, bl with various inputs
Figure 5.3: cmp truth table
Chapter 6
Figure 6.1: The gdb command
Figure 6.2: Disassembly in gdb
Figure 6.3: Setting a breakpoint in gdb
Figure 6.4: gdb info files command
Figure 6.5: gdb info register command
Figure 6.6: gdb info variable command
Figure 6.7: gdb stepi command
Figure 6.8: gdb x command
Figure 6.9: Printing 10 bytes with the gdb x command
Chapter 7
Figure 7.1: Example jump table
Figure 7.2: Stack address growth
Figure 7.3: Stack frames for hack and drink functions
Chapter 8
Figure 8.1: Application without debugging symbols in gdb
Figure 8.2: .text disassembly in gdb
Figure 8.3: Main function disassembly in gdb
Figure 8.4: Unoptimized code in a disassembler
Figure 8.5: Speed and space-optimized code in a
disassembler
Figure 8.6: Space-optimized code in a disassembler
Figure 8.7: Application debugging symbols
Figure 8.8: Linked libraries in “hello world” program
Chapter 9
Figure 9.1: objump options
Figure 9.2: Sample objdump output
Figure 9.3: strace output for echo hello!
Figure 9.4: Kitten cursor applications
Figure 9.5: Examining registry modifications in
Dependency Walker
Chapter 10
Figure 10.1: Halting Process Monitor
Figure 10.2: Filtering events in Procmon
Figure 10.3: Defining a filter in Procmon
Figure 10.4: Filtering on Registry events in Procmon
Figure 10.5: Including and excluding event categories in
Procmon
Figure 10.6: Notepad font change registry event
Figure 10.7: Event properties in Procmon
Figure 10.8: Stack view in Procmon's Properties window
Figure 10.9: Stack trace for notepad.exe
Figure 10.10: File operations in Procmon
Figure 10.11: Security Registry queries in Procmon
Figure 10.12: Sample application in Resource Hacker
Figure 10.13: Password window
Figure 10.14: String search in Resource Hacker
Figure 10.15: Identifying a dialog box in Resource Hacker
Figure 10.16: Microsoft Calculator
Figure 10.17: Searching for Calculator in ResHack
Figure 10.18: Calculator window in Resource Hacker
Figure 10.19: Compiling the modified application
Figure 10.20: Modified window in Resource Hacker
Figure 10.21: Saving the modified application in ResHack
Figure 10.22: Immunity debugger window
Figure 10.23: Assembly code in Immunity debugger
Figure 10.24: Executable modules in the Immunity
debugger
Figure 10.25: Strings in Immunity debugger
Figure 10.26: String references in Immunity debugger
Figure 10.27: Launching an executable in Immunity
debugger
Figure 10.28: Single-stepping in Immunity debugger
Figure 10.29: Stepping over instructions in Immunity
debugger
Figure 10.30: Exceptions in Immunity debugger
Figure 10.31: noping out code in Immunity debugger
Figure 10.32: noped code in Immunity debugger
Figure 10.33: Reverting modified code in Immunity
debugger
Figure 10.34: Saving a modified file in Immunity debugger
Chapter 11
Figure 11.1: Viewing a file in 010 Editor
Figure 11.2: Inspector pane in 010 Editor
Figure 11.3: Searching in 010 Editor
Figure 11.4: Jumping to an address in 010 Editor
Figure 11.5: CodeFusion start screen
Figure 11.6: Loading a file in CodeFusion
Figure 11.7: Adding patch information in CodeFusion
Figure 11.8: Launching the patched executable in
CodeFusion
Figure 11.9: Opening a process in Cheat Engine
Figure 11.10: Viewing memory in Cheat Engine
Figure 11.11: Memory Viewer pane in Cheat Engine
Figure 11.12: String references in Cheat Engine
Figure 11.13: noping out instruction...
Figure 11.14: Reverting changes in Cheat Engine
Figure 11.15: Copying bytes in Cheat Engine
Figure 11.16: Loading a file in IDA
Figure 11.17: IDA graph view
Figure 11.18: Opening strings view in IDA
Figure 11.19: Strings view in IDA
Figure 11.20: String cross-references in IDA
Figure 11.21: Strings in IDA code view
Figure 11.22: Basic blocks in IDA
Figure 11.23: Function arguments in IDA
Figure 11.24: Local variables in IDA
Figure 11.25: Local variables and function arguments in IDA
Figure 11.26: IDA comment window
Figure 11.27: Searching for comments in IDA
Figure 11.28: Search results in IDA
Figure 11.29: Code paths in IDA
Figure 11.30: Showing opcode bytes in IDA
Figure 11.31: Password-checking code in IDA
Figure 11.32: IDA Patch Bytes window
Figure 11.33: Password-checking logic in IDA after patching
Chapter 12
Figure 12.1: Control flow flattening in IDA
Figure 12.2: Opaque predicates in IDA
Chapter 13
Figure 13.1: Packed code in IDA
Figure 13.2: Identifying packers with PEiD
Chapter 14
Figure 14.1: Windows warning of unverified program
Chapter 17
Figure 17.1: Function stack frame before strcpy
Figure 17.2: Function stack after strcpy
x86 Software Reverse-
Engineering, Cracking, and
Counter-Measures
Stephanie Domas
Christopher Domas
x86 Software Reverse-Engineering, Cracking, and Counter-Measures 1st Edition Stephanie Domas
Introduction
Reverse engineering and software cracking are disciplines with a
long, rich history. For decades, software developers have attempted
to build defenses into their applications to protect intellectual
property or to prevent modifications to the program code. The art of
cracking has been around nearly as long as reverse engineers have
been examining and modifying code for fun or profit.
Before diving into the details of how reverse engineering works, it is
useful to understand the context in which these disciplines reside.
This chapter describes what to expect from this book and dives into
the history and legal considerations of software reverse engineering
and cracking.
Who Should Read This Book
From security professionals to hobbyists, this book is for anyone who
wants to learn to take apart, understand, and modify black-box
software. This book takes a curious security-minded individual
behind the curtain to how software cracking and computers work.
Learning how an x86 computer works is not only powerful from a
reverse-engineering and cracking perspective, but will make each
reader a stronger developer, with advanced knowledge they can
apply to code optimization, efficiency, debugging, compiler settings
and chip selection. Then the curtain continues to pull back as readers
learn how software cracking happens. Readers will learn about tools
and techniques that real-world software crackers use, and they will
set their newfound knowledge to the test by cracking real-world
applications of their own in numerous hands-on labs. We then circle
back to understand defensive techniques for combating software
cracking. By learning both the offensive and defensive techniques,
readers will walk away as strong software crackers or software
defenders.
What to Expect from This Book
This book is based on these three core tenets of reverse engineering:
There is no such thing as uncrackable software.
The goal in offense is to try to go faster.
The goal in defense is to try to slow down.
Based on this philosophy, any software can be reverse engineered
and have its secrets stolen and protections circumvented. It's just a
matter of time.
Like other areas of cybersecurity, both offensive and defensive
reverse engineers benefit from having a similar set of skills. This
book is designed to provide an introduction to these three
interrelated skill sets:
Reverse engineering: Reverse engineering is the process of
taking software apart and figuring out how it works.
Cracking: Cracking builds on reverse engineering by
manipulating a program's internals to get it to do something
that it was not intended to.
Defense: While all software is crackable, defenses can make a
program more difficult and time-consuming to crack.
Both offensive and defensive reverse engineers benefit from the same
set of skills. Without an understanding of reverse engineering and
cracking, a defender can't craft effective protections. On the other
hand, an attacker can more effectively bypass and overcome these
protections if they can understand and manipulate how a program
works.
Structure of the Book
This book is organized based on these three core capabilities and
skill sets. The structure is as follows:
PART TOPICS GOAL
Part 1: Background History and legal
considerations
x86 crash course
Understand x86
and learn to move
quickly.
Part 2: Software
Reverse
Engineering
Reconnaissance
Key checkers
Key generators
Process monitoring
Resource manipulation
Static analysis
Dynamic analysis
Writing key gens
Cracking software
Master the tools,
approaches, and
mindset required
to take software
apart and
understand its
inner workings.
Part 3: Software
Cracking
Manual patching
Automated patchers
Advanced dynamic analysis
Execution tracing
Advanced static analysis
Trial periods
Nag screens
More key gens
More cracks
Master the tools,
approaches, and
mindset
necessary to
isolate behavior
and modify
software.
Part 4: Defenses,
Countermeasures,
and Advanced
Topics
Obfuscation/deobfuscation
Anti-debugging/anti-anti-
debugging
Packing/unpacking
Cryptors/decryptors
Architectural defenses
Legal
Timeless debugging
Binary instrumentation
Intermediate
representations
Decompiling
Automatic structure
recovery
Visualization
Master defenses
and counter-
defenses.
Evaluate
defensive posture
and tradeoffs.
Explore advanced
topics.
Exercise reverse
engineering and
cracking tools,
techniques, and
mindset.
PART TOPICS GOAL
Theorem provers
Symbolic analysis
Cracking extravaganza
Hands-On Experience and Labs
The best way to learn reverse engineering and software cracking is by
doing it. For this reason, this book will include several hands-on labs
that demonstrate the concepts described in the text.
The goal of this book isn't to teach a particular set of tools and
techniques. While the focus is on x86 software running in Windows,
many of the approaches and techniques will translate to other
platforms. This book will attempt to demonstrate a wide range of
tools, including open-source, freeware, shareware, and commercial
solutions. With an understanding of what tools are available and
their relative strengths and weaknesses, you can more effectively
select the right tool for the job.
Hands-on labs and exercises will also focus on reverse engineering
and cracking a variety of different targets, including the following:
Real software: Some exercises will use real-world software
carefully selected to avoid copyright violations.
Manufactured examples: Software written specifically for
this book to illustrate concepts that are impractical to
demonstrate with real-world examples.
Crackmes: Manufactured software developed by crackers to
illustrate a concept or challenge others.
Companion Download Files
The book mentions some additional files, such as labs or tools. These
items are available for download from
https://github.com/DazzleCatDuo/X86-SOFTWARE-REVERSE-
ENGINEERING-CRACKING-AND-COUNTER-MEASURES.
History
Before diving into the nitty-gritty details of cracking and reverse
engineering, it is useful to understand its history. Software
protections and the tricks and techniques used to overcome them
have been evolving for decades.
The First Software Protections
The first software copy protections emerged in the 1970s. Some of
the early movers in the space were as follows:
Apple II: The Apple II incorporated proprietary disk drivers
that would allow writing at half-tracks, writing extra rings, and
staggering and overlapping sectors. The purpose of this was to
make the disks unusable by non-Apple machines and software
that wouldn't know to read and write at these odd offsets.
Atari 800: Atari 800 systems would intentionally include bad
sectors in their disks and attempt to load these sectors. If these
loads didn't return a “bad sector” error, then the software knew
it wasn't a valid disk and would halt execution.
Commodore 64: Legitimate Commodore 64 software was
distributed only on read-only disks. The software would attempt
to overwrite the disk, and, if it succeeded, it knew the disk was
counterfeit.
These protections all depended on unusual behavior by the software,
such as the use of invalid memory or attempting to overwrite the
program's own code. Defeating these protections required an
understanding of how the software worked.
The Rise of Cracking and Reverse Engineering
The rise of cracking and reverse engineering began in the 1980s.
However, these early crackers weren't in it for the money. Cracking
was a contest to determine who could figure out and bypass software
protections the quickest.
Over the next several decades, the reverse engineering and cracking
scene evolved. These are some of the key dates in the history of
reverse engineering:
1987: Fairlight's formation in 1987 by Bacchus defines one of
the first operational groups. Fairlight will later come to
prominence in FBI crackdowns of the early 2000s. For more
historic details visit www.fairlight.to and csdb.dk.
1990: Elliot J. Chikofsky and James H. Cross II defined reverse
engineering as “the process of analyzing a subject system to
identify the system's components and their interrelationships
and to create representations of the system in another form or at
a higher level of abstraction. (“Reverse Engineering and Design
Recovery: A Taxonomy.” IEEE Software, Vol. 7, Issue 1, Jan
1990).
1997: Old Red Cracker (handle +ORC) founds the Internet-
based High Cracking University (+HCU) to allow everyone to
learn about cracking. +ORC released “how to crack” lessons
online and authored academic papers. +HCU students had
handles that began with an +.
1997–2009: The “warez scene” emerges with groups
competing to be the first to release copyrighted material.
Insiders (aka “suppliers”) provided early access to their groups,
“crackers” broke the protections, and “couriers” distributed
cracked software to FTP sites. Between 2003 and 2009,
approximately 3,164 active groups were on “the scene”,
competing primarily for pride and bragging rights, not money.
2004: The FBI and other countries begin raids against “the
scene”. Operation Fastlink (2004) led to the conviction of 60
warez members, and Operation Site Down (2005) took down 25
warez groups.
The arms race between software protections and crackers continues
to rage, and reverse engineering is an invaluable skill set on both
sides. Crackers need to understand how a program works to
manipulate it and bypass defenses. On the defensive side, it's
important to understand the latest cracking techniques to develop
defenses that protect intellectual property and other sensitive data.
Legal
The best way to learn is by doing. This is why this book includes labs
and exercises with real-world software as well as manufactured
examples and crackmes. We are not lawyers, and those with
concerns should consult a lawyer. We recommend the Electronic
Frontier Foundation (www.eff.org). Chapter 15 covers legal topics
because we feel it's important for everyone to understand the US-
based laws that affect this area. There are two main laws to be aware
of: the Copyright Act and the Digital Millennium Copyright Act
(DMCA).
The Fair Use Clause of the Copyright Act (Copyright Act, 17 U.S.C. §
107) states that reverse engineering falls under “fair use” when done
for “…purposes such as criticism, comment, news reporting, teaching
(including multiple copies for classroom use), scholarship, or
research….” This exception is balanced against “the effect of the use
upon the potential market for or value of the copyrighted work.” In
essence, reverse engineering used for educational purposes is legal if
you don't share or sell the cracked software.
In October 2016, the DMCA also added an exception for good faith
security research. It states, “accessing a computer program solely for
purposes of good-faith testing, …where such activity is carried out
in a controlled environment designed to avoid any harm to
individuals or the public, …and is not used or maintained in a
manner that facilitates copyright infringement.”
The software examined in this book and used in exercises was
carefully selected to fall under the fair use and DMCA exceptions. If
you are planning to reverse engineer and crack software for anything
other than self-education, you should consult a lawyer. The legal
considerations of reverse engineering will also be explored in greater
detail in a later chapter.
Software reverse engineering and cracking have a rich history, and
this skill set has both offensive and defensive applications. However,
it is important to understand the laws around these disciplines and
ensure that your activities fall under the good-faith testing and fair
use exemptions.
This book is designed to provide a strong foundation in the skills and
tools used for software reverse engineering and cracking. Beginning
with the fundamentals, the book will move on through sections on
software reverse engineering and cracking to end with an exploration
of advanced offensive and defensive techniques.
CHAPTER 1
Decompilation and Architecture
An effective reverse engineer or cracker is one who understands the
systems they are analyzing. Software is designed to run in a
particular environment, and if you don't understand how that
environment works, you will struggle to understand the software.
This chapter explores the steps necessary to get started reverse
engineering an application. Decompilation is crucial to transforming
an application from machine code to something that can be read and
understood by humans. To actually analyze the resulting code, it is
also necessary to understand the architecture of the computers that
it is designed to run on.
Decompilation
Most programmers write using a higher-level programming language
like C/C++ or Java, which is designed to be human-readable.
However, computers are designed to run machine code, which
represents instructions in binary.
Compilation is the process of converting a programming language to
machine code. This means decompilation would be the process of
taking machine code back to the original programming language,
recovering the original source code. When available, this is the
easiest approach to reverse engineering because source code is
designed to be read and interpreted by a human. The majority of this
book will focus on the more typical case when decompilation is not
possible. But for the purposes of learning, it is important to
understand that sometimes you can decompile back to the source
code, and when that is an option, you should take it.
When Is Decompilation Useful?
For many programming languages, full decompilation is impossible.
These languages build code directly to machine code, and some
information, such as variable names, is lost in the process. While
some advanced decompilers can build pseudocode for these
languages, the process isn't perfect.
However, some programming languages use what's called just-in-
time (JIT) compilation. When programs written in JIT languages are
“built,” they are converted from the source code into an intermediate
language (IL), not machine code. JIT compilers store a copy of the
code in this IL until the program is run, at which point the code is
converted to machine code. Examples of JIT languages include Java,
Dalvik (Android), and .NET.
For example, Java is well-known for being largely platform-agnostic,
and the reason for this is its use of an IL (Java bytecode) and the
Java Virtual Machine (JVM). By distributing the program code as
bytecode and compiling it only at runtime, Java's JVM translates
from the Java IL to machine code specific to the machine it's running
on. While this approach can negatively impact file size and
performance, it pays off in portability.
JIT compilation also makes reverse engineering these applications
much easier. These intermediate languages are similar enough to the
original source code that they can be decompiled or converted back
into usable source code. Source code is designed to be human-
readable, making it far easier to understand the application's logic
and identify software protections or other embedded secrets.
Decompiling JIT Programming Languages
For JIT languages like .NET, several free decompilers are available.
One widely used .NET decompiler is JetBrains dotPeek, which is
available from www.jetbrains.com/decompiler. Figure 1.1 shows an
example of .NET code decompiled in dotPeek.
As shown in the figure, the .NET code is easily readable after
decompilation because the intermediate language encodes a wealth
of information as metadata, enabling more accurate reconstruction
of the source code. Any sensitive information or trade secrets
contained within the code are easily accessible to a reverse engineer.
Figure 1.1: JetBrains dotPeek .NET decompiler
Defending JIT Languages
Unlike true machine code programs, JIT-compiled programs can
often be converted to source code. Lowering the bar for reverse
engineering the code makes many of the x86 anti-reverse
engineering defenses discussed in later chapters unnecessary and
overkill.
For decompilable languages, a commonly used defense against
reverse engineering is obfuscation. Figure 1.2 shows an example of a
.NET application before and after obfuscation.
The top half of the figure contains code before obfuscation occurs,
where the function and variable names and strings are easily
readable. The information in these variable names makes it easier for
a reverse engineer to understand the purpose of each function and
how the application works as a whole.
In the bottom half of the image, we see the obfuscated version of the
same code. Now, function names, variable names, and strings are all
mangled, making it much harder to understand the purpose of the
function shown, let alone the application as a whole.
Another important security best practice is to avoid writing security
or privacy-critical code in JIT languages where reverse engineering is
easy. Instead, write this code in an assembled language, such as
C/C++, where reverse engineering is significantly more difficult. This
code can be included in DLLs that are linked to the executable
containing the nonsensitive code written in a JIT language.
Figure 1.2: Obfuscation in JetBrains dotPeek
Lab 1: Decompiling
This is the first hands-on lab for this book. Labs and all associated
instructions can be found in their corresponding folder here:
https://github.com/DazzleCatDuo/X86-SOFTWARE-REVERSE-
ENGINEERING-CRACKING-AND-COUNTER-MEASURES
For this lab, please locate Lab Decompiling and follow the provided
instructions.
Skills to Practice
Every lab in this book is designed to teach and provide hands-on
experience with certain skills. This lab's skills to practice include the
following:
Decompiling
Performing introductory reverse engineering
To learn these skills, you'll be using JetBrains dotPeek to reverse
engineer and modify a .NET application.
Takeaways
Decompiling is a powerful and easy approach to understanding and
modifying a program. However, it doesn't work on every program.
While programs written in languages such as C/C++ can be
decompiled using tools such as IDA's Hex-Rays Decompiler or
Ghidra, the result is often low-quality and difficult to use.
When developing applications that contain sensitive information or
that you don't want modified, it's better to use a language that isn't
easily decompiled. For example, C/C++ is a better choice for
sensitive functionality than a .NET language such as C#.
Architecture
Decompilation is the easy approach to reverse engineering because it
gets you back to higher-level languages and logic structures.
However, this easy path is not often available. For languages that
build to machine code, we need to go deeper and understand how
computer architectures and machine and assembly code work.
Computer Architecture
It's generally thought that the average programmer doesn't need an
in-depth understanding of how computers work. When writing a
program in a procedural language, the operating system handles all
of the low-level operations. A program is displayed as a process that
has access to the processor, memory, and file system whenever it
needs them. Processes appear to have their own contiguous memory
spaces, and files are just a sequence of bytes to read and write.
However, none of this is actually true, and your operating system has
been abstracting the truth from you (to make it easier to program). A
solid understanding of how computer architecture actually works is
essential for a reverse engineer. Figure 1.3 shows the main
components that make up a computer, including the central
processing unit, bridge, memory, and peripherals.
Figure 1.3: Computer architecture
The Central Processing Unit
The central processing unit (CPU) is where processing occurs on a
computer. Inside the CPU are the following components:
Arithmetic logic unit (ALU): The ALU performs
mathematical operations within the computer, such as addition
and multiplication.
Registers: Registers perform temporary data storage and are
used as the primary inputs and outputs of x86 instructions.
Registers provide extremely fast access to a single word of data
and are typically accessed by name.
Control units: Control units execute code. This includes
reading instructions and orchestrating the operations of other
elements within a computer.
Bridges and Peripherals
The CPU is connected via a bus to a bridge. The purpose of the
bridge is to connect the CPU to other components of the system,
including memory and the I/O bus, which is where peripherals such
as the keyboard, mouse, and speakers are connected to the system.
While information flows over a bus, the bridge is responsible for
controlling this traffic and ensuring that traffic flowing in over one
bus is routed out over the appropriate bus.
Peripherals, connected via the I/O bus, allow the computer to
communicate with the outside world. This includes sending and
receiving data from the graphics card, keyboard, mouse, speakers,
and other systems.
Memory and Registers
As its name suggests, memory is where data is stored on the
computer. Data is stored as a linear series of bytes that are accessed
via their address. This design allows moderately fast access to data
stored on the system.
When a program wants to access data in memory, the CPU sends a
request via a bus to the bridge, which forwards it to the memory,
where the data at the indicated address is accessed. The requested
data then needs to retrace that route and return to the CPU before it
can be used by the program. In contrast, a register is physically
located within the CPU, making it far more accessible.
Registers are storage that lives inside of the CPU and, unlike
memory, are not a linear series of bytes. Registers are specifically
named and have set sizes associated with each.
Registers and memory both serve the same purpose: they store data.
However, they have different specializations (quality versus
quantity). Registers are few in number and expensive, but they
provide extremely fast access to data. Memory is cheap and plentiful
but offers slower access speeds.
The bulk of the data associated with a program, the code itself and its
data, will be stored in memory. While the program is running, small
chunks of data will be copied to the registers for processing.
Assembly
Computers run on binary, digital logic. Everything is either on (1) or
off (0). This includes programs running on a computer. All high-level
languages are eventually converted into a series of bits called
machine code. This machine code defines the set of instructions that
the computer executes to perform a desired function.
Introduction to Machine Code
Every programmer begins learning a language with a “hello world”
program. In x86, the machine code for “hello world” is as follows:
55 89 e5 83 e4 f0 83 ec 10 b8 b0 84 04 08 89 04 24 e8 1a ff ff
ff b8 00 00 00 00 c9 c3 90
This machine code is written in hexadecimal for readability and
compactness, but its true value is a binary string of 1s and 0s. This
binary string contains instructions to flip transistors to calculate
information, fetch data from memory, send signals over the system
buses, interact with the graphics card, and, finally, print out the
“hello world” text. If this string of characters seems a bit short to
accomplish all this, it's because these instructions trigger the
operating system (in this example Linux) to help out.
Machine code controls the processor at the most detailed possible
level. Some of the functions that machine code performs include the
following:
Moving data in and out of memory
Moving data to and out of registers
Controlling the system bus
Controlling the ALU, control unit, and other components
This low-level control means that applications written in machine
code can be incredibly powerful and efficient. However, while
memorizing and inputting various series of bits to perform certain
tasks is pretty awesome, it is inefficient and prone to error.
From Machine Code to Assembly
In machine code, a series of bits represents a particular action. For
example, 0x81 or 10000001 is an instruction that adds two values
together and stores the result at a particular location.
Assembly code is designed to be a human-readable version of
machine code. Instead of memorizing a binary or hexadecimal string
like 0x81 or 10000001, a programmer can use add. The add mnemonic
is mapped to 0x81, so this shorthand makes programming easier
without losing any of the benefits of writing in machine code.
Translating machine code to assembly code makes it much easier to
understand. For example, the previous “hello world” example code
can be converted into a series of comprehensible instructions.
MACHINE CODE ASSEMBLY
55 push ebp
89 e5 mov ebp,esp
83 e4 f0 and esp, 0xfffffff0
83 ec 10 sub esp, 0x10
b8 b0 84 04 08 mov eax
89 04 24 mov [esp], eax
e8 1a ff ff ff call 80482f4
b8 00 00 00 00 mov eax, 0x0
c9 leave
MACHINE CODE ASSEMBLY
c3 ret
90 nop
If you understand machine code, writing directly in it can be fun, and
there are cases where it may make sense. However, the majority of
the time, it is inefficient and impractical. Writing in assembly
provides the same benefits as writing in machine code but is much
more practical.
After code has been written in assembly, it can be translated to
machine code by an assembler in a process called assembling. A
program already in machine code can be disassembled into assembly
code by a disassembler.
DEFINITION
Assemblers convert assembly code to machine code.
Disassemblers convert machine code to assembly.
Many programmers don't write in machine code or assembly.
Instead, they use higher-level languages that abstract away more of
the details. For example, the following pseudocode is similar to many
high-level procedural languages.
int x=1, y=2, z=x+y;
During the compiling process, these higher-level languages are
converted into assembly code similar to the following:
mov [ebp-4], 0x1
mov [ebp-8], 0x2
mov eax, [ebp-8]
mov edx, [ebp-4]
lea eax, [edx+1*eax]
mov [ebp-0xc], eax
An assembler can then be used to convert the assembly code into the
following machine code that a computer can use:
c7 45 fc 01 00 00 00 c7 45 f8 02 00 00 00 8b 45 f8 8b 55 fc 8d
04 02 89 45 f4
Instruction Set Architectures and Microarchitectures
The word computer covers a wide range of systems. A smartwatch
and a desktop computer both work in similar ways. However, their
internal components can differ significantly.
An instruction set architecture (ISA) describes the ecosystems where
programs run. Some of the factors that an ISA defines include the
following:
Registers: The ISA specifies whether a processor has a single
register or hundreds. It also defines the size of these registers,
whether they contain 8 bits or 128 bits.
Addresses and data formats: The ISA specifies the format
for addresses used to access data in memory. It also defines how
many bytes the system can grab from memory at a time.
Machine instructions: Different ISAs may support different
sets of instructions. The ISA defines whether addition,
subtraction, equality, halt, and other instructions are supported.
By defining the capabilities of the physical system, the ISA also
indirectly defines the assembly language. The ISA specifies which
low-level instructions are available and what those instructions do.
A microarchitecture describes how a particular ISA is implemented
on a processor. Figure 1.4 shows an example of the Intel Core 2
architecture.
Together, an ISA and microarchitecture define the computer
architecture. The existence of thousands of ISA and thousands of
microarchitectures means that there are thousands of computer
architectures as well.
Figure 1.4: Intel Core 2 architecture
DEFINITION
An instruction set architecture defines how registers,
addresses, data formats, and machine instructions
work. Microarchitectures implement ISAs on a
processor. Together, an ISA and microarchitecture
define a computer architecture.
RISC vs. CISC Computer Architectures
While thousands of computer architectures exist, they can be broadly
divided into two main categories. Reduced instruction set computing
(RISC) architectures define a small number of simpler instructions.
In general, RISC architectures are cheaper and easier to create, and
the hardware is physically smaller and consumes less power.
In contrast, a complex instruction set computing (CISC) architecture
defines a larger number of more powerful instructions. CISC
processors are more expensive and difficult to create and are
typically larger and consume more power.
While CISC architectures may seem objectively worse than RISC
ones, their main benefit lies in the ease and efficiency of
programming. For example, consider a hypothetical example where a
program wants to multiply a value by 5 in a RISC versus CISC
system.
CISC RISC
mul [100], 5 load r0, 100
mov r1, r0
add r1, r0
add r1, r0
add r1, r0
add r1, r0
mov [100], r1
In this example, a CISC processor can perform the calculation in a
single instruction if it has a multiplication operation that can load a
value from memory, multiply it, and store the result at the same
memory location. However, a RISC processor may lack a
multiplication operator because it is a complex operation. Instead,
the RISC loads the value from memory, adds it to itself four times,
and stores the result in the same memory location across seven steps.
RISC and CISC architectures both have their advantages,
disadvantages, and use cases. For example, a RISC operator may take
100 instructions to perform the same operation that a CISC operator
can perform in one. However, that single CISC operation may take
100× as long to run or 100× the power.
Both RISC and CISC instruction sets are in common use today. Some
examples of widely used RISC architectures include the following:
ARM (used by phones, tablets)
MIPS (used by embedded systems and networking equipment)
PowerPC (used by original Macs and Xbox360)
In this book, we focus on the x86 assembly language, which is a CISC
architecture. This architecture is in use on all modern PCs and
servers and is supported by all the main operating systems
(Windows, Mac, Linux) and even some gaming systems, such as the
Xbox One. Making it one of the most powerful to learn for software
cracking.
Summary
The machine code that actually runs on computers isn't designed for
humans to read and understand. To be usable, it needs to be
converted into a different form.
One option for this is decompilation, which produces a result that is
similar or identical to the original source code. However,
decompilation is not always possible.
For fully compiled languages, such as C/C++, and many other
languages, it is necessary to disassemble a compiled executable and
analyze it in assembly. However, this requires a much deeper
understanding of the computer's architecture and how it actually
works than writing and reading code in a higher-level language. Now
that we know the role decompilation can play and the need for
disassembly, in the next few chapters we'll look at how computers
work, so we can learn to disassemble like a pro.
CHAPTER 2
x86 Assembly: Data, Modes,
Registers, and Memory Access
Most software reverse engineering requires disassembling a
compiled executable and analyzing the result. This disassembly
results in assembly code, not a higher-level language.
While a few assembly languages exist, x86 is one of the most widely
used. This chapter introduces some of the key concepts of x86
assembly, providing a foundation for later chapters.
Introduction to x86
Thousands of computer architectures exist. While they all work
similarly, a computer is a computer—but there are minor or major
differences between each.
To study reverse engineering, we need to select an architecture to
focus on. In this book, we'll be using x86, which was selected for a
few different reasons:
Ubiquity: x86 is the most widely used assembly language,
making it widely applicable for reverse engineering.
Computer support: x86 applications can be built, run, and
reverse engineered on any desktop, laptop, or server.
Market share: x86 is the core of the major operating systems
(Windows, Linux, and macOS), so it is used in billions of
systems.
The x86 architecture has been around for decades and has evolved
significantly over the years. It was first introduced in 1974 by Intel,
and some of the main milestones in the history of x86 include the
following:
Intel 8080: 8-bit microprocessor, introduced in 1974
Intel 8086: 16-bit microprocessor, introduced in 1978
Intel 80386: 32-bit microprocessor, introduced in 1985
Intel Prescott, AMD Opteron, and Athlon 64: 64-bit
microprocessor, introduced in 2003/2004
Over its nearly 50-year history, the x86 architecture has regularly
added new features while maintaining backward compatibility. Even
if a feature was determined to be unused, it was never removed from
the system. As a result, programs written for the Intel 8086
processor released in 1978 can still run on the latest x86 chips with
no modifications.
This focus on backward compatibility has created an immense,
complex, and interesting architecture. The latest Intel Software
Developer's manual
(www.intel.com/content/www/us/en/developer/articles/technical/i
ntel-sdm.html) is more than 5,000 pages long and only begins to
scratch the surface of what this architecture can do. This book
focuses on understanding the basics of x86, which is all that is
needed to read, write, and manipulate most x86 code.
As the x86 architecture has changed, the term x86 has become an
umbrella term for all of the architectures that have evolved from the
Intel 8086 16-bit architecture. This includes the Intel 80286
architecture, which contains both 16-bit and 32-bit architectures,
and the Intel 80886 architecture, which adds a 64-bit architecture.
The term x64 specifically refers to the 64-bit version of x86.
This book will show examples in 32-bit x86 architecture. All of the
concepts from 32-bit x86 translate exactly to x64. It is substantially
easier to work on examples in 32 bits versus 64 as you're learning.
After studying 32-bit x86 throughout this book, you will be
immediately able to look at x64-bit assembly and understand it.
However, your eyeballs will be thanking you for not having to look at
64 bits all the time, as even 32 bits are a bit painful to stare at. So, do
not let the examples being in 32-bit give you pause that this is
outdated or that you should focus on 64-bit out of the gate. Both of
us learned 32-bit first, and we've taught software cracking a lot and
can confidently say that if you give yourself the solid 32-bit
foundation first, 64-bit becomes just another few register names and
longer values.
Assembly Syntax
Selecting x86 from the thousands of possible computer architectures
is important, but it isn't enough. While an instruction set
architecture (ISA) defines factors such as the registers, data format,
and machine instructions, it doesn't specify the syntax.
As long as an assembly language follows all of the rules for registers,
addressing, etc., and defines the right set of instructions, it's a valid
x86 language. For example, an x86 language must have a multiply
operation. However, its mnemonic could be mul, MUL, multiply, or
any other variation across any language.
The syntax of an assembly language is entirely defined by the
assembler. There is no standard syntax for assembly language in
general or for x86 assembly in particular. As a result, there are
hundreds of different variations.
However, there are two prevalent x86 syntax options that you will
find most x86 assembly tools use: AT&T syntax and Intel syntax.
Under each of these main branches are hundreds of assembler-
specific variations.
While Intel and AT&T assembly are both x86, they look very
different. For example, consider a statement designed to move the
memory at address ebx+4*ecx+2020 into register eax.
This instruction looks very different in the Intel and AT&T syntaxes:
INTEL SYNTAX AT&T SYNTAX
mov eax, [ebx+4*ecx+2020] mov 0x7e4(%ebx,%ecx,4),%eax
In the Intel syntax, after the instruction mov comes the location where
the result will be stored. Memory access is indicated by square
brackets, and the calculation of the memory address
[ebx+4*ecx+2020] is performed within these brackets.
AT&T syntax differs from Intel syntax in a few ways:
Exploring the Variety of Random
Documents with Different Content
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You provide a full refund of any money paid by a user who
notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.
• You provide, in accordance with paragraph 1.F.3, a full refund of
any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.E.9. If you wish to charge a fee or distribute a Project
Gutenberg™ electronic work or group of works on different
terms than are set forth in this agreement, you must obtain
permission in writing from the Project Gutenberg Literary
Archive Foundation, the manager of the Project Gutenberg™
trademark. Contact the Foundation as set forth in Section 3
below.
1.F.
1.F.1. Project Gutenberg volunteers and employees expend
considerable effort to identify, do copyright research on,
transcribe and proofread works not protected by U.S. copyright
law in creating the Project Gutenberg™ collection. Despite these
efforts, Project Gutenberg™ electronic works, and the medium
on which they may be stored, may contain “Defects,” such as,
but not limited to, incomplete, inaccurate or corrupt data,
transcription errors, a copyright or other intellectual property
infringement, a defective or damaged disk or other medium, a
computer virus, or computer codes that damage or cannot be
read by your equipment.
1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except
for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive
Foundation, the owner of the Project Gutenberg™ trademark,
and any other party distributing a Project Gutenberg™ electronic
work under this agreement, disclaim all liability to you for
damages, costs and expenses, including legal fees. YOU AGREE
THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT
EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE
THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.
1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you
discover a defect in this electronic work within 90 days of
receiving it, you can receive a refund of the money (if any) you
paid for it by sending a written explanation to the person you
received the work from. If you received the work on a physical
medium, you must return the medium with your written
explanation. The person or entity that provided you with the
defective work may elect to provide a replacement copy in lieu
of a refund. If you received the work electronically, the person
or entity providing it to you may choose to give you a second
opportunity to receive the work electronically in lieu of a refund.
If the second copy is also defective, you may demand a refund
in writing without further opportunities to fix the problem.
1.F.4. Except for the limited right of replacement or refund set
forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’,
WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
1.F.5. Some states do not allow disclaimers of certain implied
warranties or the exclusion or limitation of certain types of
damages. If any disclaimer or limitation set forth in this
agreement violates the law of the state applicable to this
agreement, the agreement shall be interpreted to make the
maximum disclaimer or limitation permitted by the applicable
state law. The invalidity or unenforceability of any provision of
this agreement shall not void the remaining provisions.
1.F.6. INDEMNITY - You agree to indemnify and hold the
Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless
from all liability, costs and expenses, including legal fees, that
arise directly or indirectly from any of the following which you
do or cause to occur: (a) distribution of this or any Project
Gutenberg™ work, (b) alteration, modification, or additions or
deletions to any Project Gutenberg™ work, and (c) any Defect
you cause.
Section 2. Information about the Mission
of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new
computers. It exists because of the efforts of hundreds of
volunteers and donations from people in all walks of life.
Volunteers and financial support to provide volunteers with the
assistance they need are critical to reaching Project
Gutenberg™’s goals and ensuring that the Project Gutenberg™
collection will remain freely available for generations to come. In
2001, the Project Gutenberg Literary Archive Foundation was
created to provide a secure and permanent future for Project
Gutenberg™ and future generations. To learn more about the
Project Gutenberg Literary Archive Foundation and how your
efforts and donations can help, see Sections 3 and 4 and the
Foundation information page at www.gutenberg.org.
Section 3. Information about the Project
Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-
profit 501(c)(3) educational corporation organized under the
laws of the state of Mississippi and granted tax exempt status
by the Internal Revenue Service. The Foundation’s EIN or
federal tax identification number is 64-6221541. Contributions
to the Project Gutenberg Literary Archive Foundation are tax
deductible to the full extent permitted by U.S. federal laws and
your state’s laws.
The Foundation’s business office is located at 809 North 1500
West, Salt Lake City, UT 84116, (801) 596-1887. Email contact
links and up to date contact information can be found at the
Foundation’s website and official page at
www.gutenberg.org/contact
Section 4. Information about Donations to
the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission
of increasing the number of public domain and licensed works
that can be freely distributed in machine-readable form
accessible by the widest array of equipment including outdated
equipment. Many small donations ($1 to $5,000) are particularly
important to maintaining tax exempt status with the IRS.
The Foundation is committed to complying with the laws
regulating charities and charitable donations in all 50 states of
the United States. Compliance requirements are not uniform
and it takes a considerable effort, much paperwork and many
fees to meet and keep up with these requirements. We do not
solicit donations in locations where we have not received written
confirmation of compliance. To SEND DONATIONS or determine
the status of compliance for any particular state visit
www.gutenberg.org/donate.
While we cannot and do not solicit contributions from states
where we have not met the solicitation requirements, we know
of no prohibition against accepting unsolicited donations from
donors in such states who approach us with offers to donate.
International donations are gratefully accepted, but we cannot
make any statements concerning tax treatment of donations
received from outside the United States. U.S. laws alone swamp
our small staff.
Please check the Project Gutenberg web pages for current
donation methods and addresses. Donations are accepted in a
number of other ways including checks, online payments and
credit card donations. To donate, please visit:
www.gutenberg.org/donate.
Section 5. General Information About
Project Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could
be freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose
network of volunteer support.
Project Gutenberg™ eBooks are often created from several
printed editions, all of which are confirmed as not protected by
copyright in the U.S. unless a copyright notice is included. Thus,
we do not necessarily keep eBooks in compliance with any
particular paper edition.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.
This website includes information about Project Gutenberg™,
including how to make donations to the Project Gutenberg
Literary Archive Foundation, how to help produce our new
eBooks, and how to subscribe to our email newsletter to hear
about new eBooks.

More Related Content

Similar to x86 Software Reverse-Engineering, Cracking, and Counter-Measures 1st Edition Stephanie Domas (20)

PPT
Intro dotnet
shuklagirish
 
PPT
Intro dotnet
shuklagirish
 
PPTX
Production Debugging at Code Camp Philly
Brian Lyttle
 
PDF
Programming Python 3rd ed Edition Mark Lutz
seebjqsmiq828
 
PDF
Red Gate .NET Reflector 8.2.0.7
WendyLogan6
 
PDF
Embedded systems are specialized computing systems designed to perform specif...
22bcs058
 
PDF
Larson and toubro
anoopc1998
 
PDF
Consumer centric api design v0.4.0
mustafa sarac
 
PDF
Encode Club Hackathon
Vanessa Lošić
 
PPTX
.NET Core Today and Tomorrow
Jon Galloway
 
PPT
Csharp dot net
Revanth Mca
 
PPT
.NET Debugging Tips and Techniques
Bala Subra
 
PPT
.Net Debugging Techniques
Bala Subra
 
PDF
Building a web application with ontinuation monads
Seitaro Yuuki
 
PPTX
TestUpload
ZarksaDS
 
PDF
Building frameworks: from concept to completion
Ruben Goncalves
 
PDF
Programming on Windows 8.1: The New Stream and Storage Paradigm (Raffaele Ria...
ITCamp
 
PDF
Download full ebook of Ctfctfallinone Firmianay instant download pdf
bramsdoomsc1
 
PPTX
05-machine-basics.pptx
HarinarayananRajeev1
 
Intro dotnet
shuklagirish
 
Intro dotnet
shuklagirish
 
Production Debugging at Code Camp Philly
Brian Lyttle
 
Programming Python 3rd ed Edition Mark Lutz
seebjqsmiq828
 
Red Gate .NET Reflector 8.2.0.7
WendyLogan6
 
Embedded systems are specialized computing systems designed to perform specif...
22bcs058
 
Larson and toubro
anoopc1998
 
Consumer centric api design v0.4.0
mustafa sarac
 
Encode Club Hackathon
Vanessa Lošić
 
.NET Core Today and Tomorrow
Jon Galloway
 
Csharp dot net
Revanth Mca
 
.NET Debugging Tips and Techniques
Bala Subra
 
.Net Debugging Techniques
Bala Subra
 
Building a web application with ontinuation monads
Seitaro Yuuki
 
TestUpload
ZarksaDS
 
Building frameworks: from concept to completion
Ruben Goncalves
 
Programming on Windows 8.1: The New Stream and Storage Paradigm (Raffaele Ria...
ITCamp
 
Download full ebook of Ctfctfallinone Firmianay instant download pdf
bramsdoomsc1
 
05-machine-basics.pptx
HarinarayananRajeev1
 

Recently uploaded (20)

PDF
My Thoughts On Q&A- A Novel By Vikas Swarup
Niharika
 
PPTX
Command Palatte in Odoo 18.1 Spreadsheet - Odoo Slides
Celine George
 
PPT
DRUGS USED IN THERAPY OF SHOCK, Shock Therapy, Treatment or management of shock
Rajshri Ghogare
 
DOCX
Modul Ajar Deep Learning Bahasa Inggris Kelas 11 Terbaru 2025
wahyurestu63
 
PPTX
Introduction to Probability(basic) .pptx
purohitanuj034
 
PPTX
Artificial Intelligence in Gastroentrology: Advancements and Future Presprec...
AyanHossain
 
PPTX
How to Close Subscription in Odoo 18 - Odoo Slides
Celine George
 
PPTX
Cleaning Validation Ppt Pharmaceutical validation
Ms. Ashatai Patil
 
PPTX
I INCLUDED THIS TOPIC IS INTELLIGENCE DEFINITION, MEANING, INDIVIDUAL DIFFERE...
parmarjuli1412
 
PDF
The Minister of Tourism, Culture and Creative Arts, Abla Dzifa Gomashie has e...
nservice241
 
PPTX
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 
PDF
Tips for Writing the Research Title with Examples
Thelma Villaflores
 
PPTX
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
PPTX
Electrophysiology_of_Heart. Electrophysiology studies in Cardiovascular syste...
Rajshri Ghogare
 
PPTX
Python-Application-in-Drug-Design by R D Jawarkar.pptx
Rahul Jawarkar
 
PDF
BÀI TẬP TEST BỔ TRỢ THEO TỪNG CHỦ ĐỀ CỦA TỪNG UNIT KÈM BÀI TẬP NGHE - TIẾNG A...
Nguyen Thanh Tu Collection
 
PDF
Virat Kohli- the Pride of Indian cricket
kushpar147
 
PPTX
PROTIEN ENERGY MALNUTRITION: NURSING MANAGEMENT.pptx
PRADEEP ABOTHU
 
PPTX
Top 10 AI Tools, Like ChatGPT. You Must Learn In 2025
Digilearnings
 
PPTX
Applied-Statistics-1.pptx hardiba zalaaa
hardizala899
 
My Thoughts On Q&A- A Novel By Vikas Swarup
Niharika
 
Command Palatte in Odoo 18.1 Spreadsheet - Odoo Slides
Celine George
 
DRUGS USED IN THERAPY OF SHOCK, Shock Therapy, Treatment or management of shock
Rajshri Ghogare
 
Modul Ajar Deep Learning Bahasa Inggris Kelas 11 Terbaru 2025
wahyurestu63
 
Introduction to Probability(basic) .pptx
purohitanuj034
 
Artificial Intelligence in Gastroentrology: Advancements and Future Presprec...
AyanHossain
 
How to Close Subscription in Odoo 18 - Odoo Slides
Celine George
 
Cleaning Validation Ppt Pharmaceutical validation
Ms. Ashatai Patil
 
I INCLUDED THIS TOPIC IS INTELLIGENCE DEFINITION, MEANING, INDIVIDUAL DIFFERE...
parmarjuli1412
 
The Minister of Tourism, Culture and Creative Arts, Abla Dzifa Gomashie has e...
nservice241
 
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 
Tips for Writing the Research Title with Examples
Thelma Villaflores
 
TOP 10 AI TOOLS YOU MUST LEARN TO SURVIVE IN 2025 AND ABOVE
digilearnings.com
 
Electrophysiology_of_Heart. Electrophysiology studies in Cardiovascular syste...
Rajshri Ghogare
 
Python-Application-in-Drug-Design by R D Jawarkar.pptx
Rahul Jawarkar
 
BÀI TẬP TEST BỔ TRỢ THEO TỪNG CHỦ ĐỀ CỦA TỪNG UNIT KÈM BÀI TẬP NGHE - TIẾNG A...
Nguyen Thanh Tu Collection
 
Virat Kohli- the Pride of Indian cricket
kushpar147
 
PROTIEN ENERGY MALNUTRITION: NURSING MANAGEMENT.pptx
PRADEEP ABOTHU
 
Top 10 AI Tools, Like ChatGPT. You Must Learn In 2025
Digilearnings
 
Applied-Statistics-1.pptx hardiba zalaaa
hardizala899
 
Ad

x86 Software Reverse-Engineering, Cracking, and Counter-Measures 1st Edition Stephanie Domas

  • 1. Read Anytime Anywhere Easy Ebook Downloads at ebookmeta.com x86 Software Reverse-Engineering, Cracking, and Counter-Measures 1st Edition Stephanie Domas https://ebookmeta.com/product/x86-software-reverse- engineering-cracking-and-counter-measures-1st-edition- stephanie-domas/ OR CLICK HERE DOWLOAD EBOOK Visit and Get More Ebook Downloads Instantly at https://ebookmeta.com
  • 2. Recommended digital products (PDF, EPUB, MOBI) that you can download immediately if you are interested. x86 Software Reverse-Engineering, Cracking, and Counter- Measures (Tech Today) 1st Edition Domas https://ebookmeta.com/product/x86-software-reverse-engineering- cracking-and-counter-measures-tech-today-1st-edition-domas/ ebookmeta.com Implementing Reverse Engineering: The Real Practice of X86 Internals, Code Calling Conventions, Ransomware Decryption, Application Cracking, Assembly Language, ... Open Source Tools (English Edition) Jitender Narula https://ebookmeta.com/product/implementing-reverse-engineering-the- real-practice-of-x86-internals-code-calling-conventions-ransomware- decryption-application-cracking-assembly-language-open-source-tools- english-edition/ ebookmeta.com Cambridge IGCSE and O Level History Workbook 2C - Depth Study: the United States, 1919-41 2nd Edition Benjamin Harrison https://ebookmeta.com/product/cambridge-igcse-and-o-level-history- workbook-2c-depth-study-the-united-states-1919-41-2nd-edition- benjamin-harrison/ ebookmeta.com Low Level Light Shooting 1st Edition Richard Franks https://ebookmeta.com/product/low-level-light-shooting-1st-edition- richard-franks/ ebookmeta.com
  • 3. A Medication Guide to Internal Medicine Tests and Procedures 1st Edition Gregory J. Hughes https://ebookmeta.com/product/a-medication-guide-to-internal-medicine- tests-and-procedures-1st-edition-gregory-j-hughes/ ebookmeta.com Twelfth Night The Pelican Shakespeare First Edition William Shakespeare https://ebookmeta.com/product/twelfth-night-the-pelican-shakespeare- first-edition-william-shakespeare/ ebookmeta.com The Fine Art of Small Talk: How to Start a Conversation, Keep It Going, Build Networking Skills – and Leave a Positive Impression! Debra Fine https://ebookmeta.com/product/the-fine-art-of-small-talk-how-to-start- a-conversation-keep-it-going-build-networking-skills-and-leave-a- positive-impression-debra-fine/ ebookmeta.com Psychological Applications and Trends 2021 2021st Edition Clara Pracana https://ebookmeta.com/product/psychological-applications-and- trends-2021-2021st-edition-clara-pracana/ ebookmeta.com Spiritual Warfare Fighting the Good Fight Fr. Vivian Boland Op https://ebookmeta.com/product/spiritual-warfare-fighting-the-good- fight-fr-vivian-boland-op/ ebookmeta.com
  • 4. Thank You Fossil Fuels and Good Night The 21st Century s Energy Transition 1st Edition Gregory Meehan https://ebookmeta.com/product/thank-you-fossil-fuels-and-good-night- the-21st-century-s-energy-transition-1st-edition-gregory-meehan/ ebookmeta.com
  • 6. Table of Contents Cover Table of Contents Title Page Introduction Who Should Read This Book What to Expect from This Book History Legal Chapter 1: Decompilation and Architecture Decompilation Lab 1: Decompiling Architecture Summary Chapter 2: x86 Assembly: Data, Modes, Registers, and Memory Access Introduction to x86 Assembly Syntax Data Representation Registers Memory Access Addressing Modes Summary Chapter 3: x86 Assembly: Instructions x86 Instruction Format x86 Instructions Putting It All Together Common x86 Instruction Mistakes
  • 7. Summary Chapter 4: Building and Running Assembly Programs Output System Calls Building and Linking objdump Lab: Hello World ASCII Summary Chapter 5: Understanding Condition Codes Condition Codes Summary Chapter 6: Analyzing and Debugging Assembly Code Binary Analysis Breakpoints gdb Segmentation Faults Lab: Shark Sim 3000 Tuning Out the Noise Summary Chapter 7: Functions and Control Flow Control Flow Logic Constructs in x86 Stack Function Calls and Stack Frames Summary Chapter 8: Compilers and Optimizers Finding Starting Code Compilers Summary
  • 8. Chapter 9: Reverse Engineering: Tools and Strategies Lab: RE Bingo Basic REconnaissance Reverse Engineering Strategy Summary Chapter 10: Cracking: Tools and Strategies Key Checkers Key Generators Lab: Introductory Keygen Procmon Resource Hacker Patching Other Debuggers Debugging with Immunity Lab: Cracking with Immunity Summary Chapter 11: Patching and Advanced Tooling Patching in 010 Editor CodeFusion Patching Cheat Engine Lab: Cracking LaFarge IDA Introduction IDA Patching Lab: IDA Logic Flows Ghidra Lab: Cracking with IDA Summary Chapter 12: Defense Obfuscation Lab: Obfuscation
  • 9. Anti-Debugging Lab: Anti-Debugging Summary Chapter 13: Advanced Defensive Techniques Tamper-Proofing Packing Lab: Detecting and Unpacking Virtualization Cryptors/Decryptors Summary Chapter 14: Detection and Prevention CRC Code Signing RASP Allowlisting Blocklisting Remote Authentication Lab: ProcMon Summary Chapter 15: Legal U.S. Laws Affecting Reverse Engineering Summary Chapter 16: Advanced Techniques Timeless Debugging Summary Chapter 17: Bonus Topics Stack Smashing Connecting C and x86 Summary Conclusion
  • 10. Index Copyright About the Authors About the Technical Writer About the Technical Editor End User License Agreement List of Tables Chapter 4 Table 4.1: x86 Ports Table 4.2: sys_write Table 4.3: sys_exit Chapter 7 Table 7.1: x86 conditional jump instructions Table 7.2: Pushing a variable onto the stack Table 7.3: Popping a variable from the stack Table 7.4: Stack trace examples Table 7.5: Function calls and the stack Table 7.6: Program stack after calling a Table 7.7: Program stack after calling b Table 7.8: Program stack after calling c Table 7.9: Stack in add function Table 7.10: Effects of function prologue on stack Table 7.11: Effects of function epilogue on stack Table 7.12: Stack locations for common values Table 7.13: Stack content at points 1, 2, and 3 in the program
  • 11. Table 7.14: Stack frame of one_up program Table 7.15: Stack locations for local variables Table 7.16: Complete function stack frame Table 7.17: Two types of prologues Table 7.18: Two types of epilogues List of Illustrations Chapter 1 Figure 1.1: JetBrains dotPeek .NET decompiler Figure 1.2: Obfuscation in JetBrains dotPeek Figure 1.3: Computer architecture Figure 1.4: Intel Core 2 architecture Chapter 2 Figure 2.1: Hexadecimal Figure 2.2: Base conversions in the Windows calculator Figure 2.3: Bit and byte significance labels Figure 2.4: Endianness Figure 2.5: x86 registers Figure 2.6: Pieces of the eax register Figure 2.7: Common x64 registers Figure 2.8: Pieces of the r8 register Figure 2.9: Comparing differently sized mov instructions Chapter 3 Figure 3.1: mov instructions Chapter 4 Figure 4.1: Binary wristwatch Figure 4.2: ASCII table
  • 12. Figure 4.3: Program output Figure 4.4: ASCII uppercase and lowercase values Chapter 5 Figure 5.1: Effects of add al,bl with various inputs Figure 5.2: Effects of sub al, bl with various inputs Figure 5.3: cmp truth table Chapter 6 Figure 6.1: The gdb command Figure 6.2: Disassembly in gdb Figure 6.3: Setting a breakpoint in gdb Figure 6.4: gdb info files command Figure 6.5: gdb info register command Figure 6.6: gdb info variable command Figure 6.7: gdb stepi command Figure 6.8: gdb x command Figure 6.9: Printing 10 bytes with the gdb x command Chapter 7 Figure 7.1: Example jump table Figure 7.2: Stack address growth Figure 7.3: Stack frames for hack and drink functions Chapter 8 Figure 8.1: Application without debugging symbols in gdb Figure 8.2: .text disassembly in gdb Figure 8.3: Main function disassembly in gdb Figure 8.4: Unoptimized code in a disassembler Figure 8.5: Speed and space-optimized code in a disassembler
  • 13. Figure 8.6: Space-optimized code in a disassembler Figure 8.7: Application debugging symbols Figure 8.8: Linked libraries in “hello world” program Chapter 9 Figure 9.1: objump options Figure 9.2: Sample objdump output Figure 9.3: strace output for echo hello! Figure 9.4: Kitten cursor applications Figure 9.5: Examining registry modifications in Dependency Walker Chapter 10 Figure 10.1: Halting Process Monitor Figure 10.2: Filtering events in Procmon Figure 10.3: Defining a filter in Procmon Figure 10.4: Filtering on Registry events in Procmon Figure 10.5: Including and excluding event categories in Procmon Figure 10.6: Notepad font change registry event Figure 10.7: Event properties in Procmon Figure 10.8: Stack view in Procmon's Properties window Figure 10.9: Stack trace for notepad.exe Figure 10.10: File operations in Procmon Figure 10.11: Security Registry queries in Procmon Figure 10.12: Sample application in Resource Hacker Figure 10.13: Password window Figure 10.14: String search in Resource Hacker Figure 10.15: Identifying a dialog box in Resource Hacker
  • 14. Figure 10.16: Microsoft Calculator Figure 10.17: Searching for Calculator in ResHack Figure 10.18: Calculator window in Resource Hacker Figure 10.19: Compiling the modified application Figure 10.20: Modified window in Resource Hacker Figure 10.21: Saving the modified application in ResHack Figure 10.22: Immunity debugger window Figure 10.23: Assembly code in Immunity debugger Figure 10.24: Executable modules in the Immunity debugger Figure 10.25: Strings in Immunity debugger Figure 10.26: String references in Immunity debugger Figure 10.27: Launching an executable in Immunity debugger Figure 10.28: Single-stepping in Immunity debugger Figure 10.29: Stepping over instructions in Immunity debugger Figure 10.30: Exceptions in Immunity debugger Figure 10.31: noping out code in Immunity debugger Figure 10.32: noped code in Immunity debugger Figure 10.33: Reverting modified code in Immunity debugger Figure 10.34: Saving a modified file in Immunity debugger Chapter 11 Figure 11.1: Viewing a file in 010 Editor Figure 11.2: Inspector pane in 010 Editor Figure 11.3: Searching in 010 Editor Figure 11.4: Jumping to an address in 010 Editor
  • 15. Figure 11.5: CodeFusion start screen Figure 11.6: Loading a file in CodeFusion Figure 11.7: Adding patch information in CodeFusion Figure 11.8: Launching the patched executable in CodeFusion Figure 11.9: Opening a process in Cheat Engine Figure 11.10: Viewing memory in Cheat Engine Figure 11.11: Memory Viewer pane in Cheat Engine Figure 11.12: String references in Cheat Engine Figure 11.13: noping out instruction... Figure 11.14: Reverting changes in Cheat Engine Figure 11.15: Copying bytes in Cheat Engine Figure 11.16: Loading a file in IDA Figure 11.17: IDA graph view Figure 11.18: Opening strings view in IDA Figure 11.19: Strings view in IDA Figure 11.20: String cross-references in IDA Figure 11.21: Strings in IDA code view Figure 11.22: Basic blocks in IDA Figure 11.23: Function arguments in IDA Figure 11.24: Local variables in IDA Figure 11.25: Local variables and function arguments in IDA Figure 11.26: IDA comment window Figure 11.27: Searching for comments in IDA Figure 11.28: Search results in IDA Figure 11.29: Code paths in IDA Figure 11.30: Showing opcode bytes in IDA
  • 16. Figure 11.31: Password-checking code in IDA Figure 11.32: IDA Patch Bytes window Figure 11.33: Password-checking logic in IDA after patching Chapter 12 Figure 12.1: Control flow flattening in IDA Figure 12.2: Opaque predicates in IDA Chapter 13 Figure 13.1: Packed code in IDA Figure 13.2: Identifying packers with PEiD Chapter 14 Figure 14.1: Windows warning of unverified program Chapter 17 Figure 17.1: Function stack frame before strcpy Figure 17.2: Function stack after strcpy
  • 17. x86 Software Reverse- Engineering, Cracking, and Counter-Measures Stephanie Domas Christopher Domas
  • 19. Introduction Reverse engineering and software cracking are disciplines with a long, rich history. For decades, software developers have attempted to build defenses into their applications to protect intellectual property or to prevent modifications to the program code. The art of cracking has been around nearly as long as reverse engineers have been examining and modifying code for fun or profit. Before diving into the details of how reverse engineering works, it is useful to understand the context in which these disciplines reside. This chapter describes what to expect from this book and dives into the history and legal considerations of software reverse engineering and cracking. Who Should Read This Book From security professionals to hobbyists, this book is for anyone who wants to learn to take apart, understand, and modify black-box software. This book takes a curious security-minded individual behind the curtain to how software cracking and computers work. Learning how an x86 computer works is not only powerful from a reverse-engineering and cracking perspective, but will make each reader a stronger developer, with advanced knowledge they can apply to code optimization, efficiency, debugging, compiler settings and chip selection. Then the curtain continues to pull back as readers learn how software cracking happens. Readers will learn about tools and techniques that real-world software crackers use, and they will set their newfound knowledge to the test by cracking real-world applications of their own in numerous hands-on labs. We then circle back to understand defensive techniques for combating software cracking. By learning both the offensive and defensive techniques, readers will walk away as strong software crackers or software defenders.
  • 20. What to Expect from This Book This book is based on these three core tenets of reverse engineering: There is no such thing as uncrackable software. The goal in offense is to try to go faster. The goal in defense is to try to slow down. Based on this philosophy, any software can be reverse engineered and have its secrets stolen and protections circumvented. It's just a matter of time. Like other areas of cybersecurity, both offensive and defensive reverse engineers benefit from having a similar set of skills. This book is designed to provide an introduction to these three interrelated skill sets: Reverse engineering: Reverse engineering is the process of taking software apart and figuring out how it works. Cracking: Cracking builds on reverse engineering by manipulating a program's internals to get it to do something that it was not intended to. Defense: While all software is crackable, defenses can make a program more difficult and time-consuming to crack. Both offensive and defensive reverse engineers benefit from the same set of skills. Without an understanding of reverse engineering and cracking, a defender can't craft effective protections. On the other hand, an attacker can more effectively bypass and overcome these protections if they can understand and manipulate how a program works. Structure of the Book This book is organized based on these three core capabilities and skill sets. The structure is as follows:
  • 21. PART TOPICS GOAL Part 1: Background History and legal considerations x86 crash course Understand x86 and learn to move quickly. Part 2: Software Reverse Engineering Reconnaissance Key checkers Key generators Process monitoring Resource manipulation Static analysis Dynamic analysis Writing key gens Cracking software Master the tools, approaches, and mindset required to take software apart and understand its inner workings. Part 3: Software Cracking Manual patching Automated patchers Advanced dynamic analysis Execution tracing Advanced static analysis Trial periods Nag screens More key gens More cracks Master the tools, approaches, and mindset necessary to isolate behavior and modify software. Part 4: Defenses, Countermeasures, and Advanced Topics Obfuscation/deobfuscation Anti-debugging/anti-anti- debugging Packing/unpacking Cryptors/decryptors Architectural defenses Legal Timeless debugging Binary instrumentation Intermediate representations Decompiling Automatic structure recovery Visualization Master defenses and counter- defenses. Evaluate defensive posture and tradeoffs. Explore advanced topics. Exercise reverse engineering and cracking tools, techniques, and mindset.
  • 22. PART TOPICS GOAL Theorem provers Symbolic analysis Cracking extravaganza Hands-On Experience and Labs The best way to learn reverse engineering and software cracking is by doing it. For this reason, this book will include several hands-on labs that demonstrate the concepts described in the text. The goal of this book isn't to teach a particular set of tools and techniques. While the focus is on x86 software running in Windows, many of the approaches and techniques will translate to other platforms. This book will attempt to demonstrate a wide range of tools, including open-source, freeware, shareware, and commercial solutions. With an understanding of what tools are available and their relative strengths and weaknesses, you can more effectively select the right tool for the job. Hands-on labs and exercises will also focus on reverse engineering and cracking a variety of different targets, including the following: Real software: Some exercises will use real-world software carefully selected to avoid copyright violations. Manufactured examples: Software written specifically for this book to illustrate concepts that are impractical to demonstrate with real-world examples. Crackmes: Manufactured software developed by crackers to illustrate a concept or challenge others. Companion Download Files The book mentions some additional files, such as labs or tools. These items are available for download from https://github.com/DazzleCatDuo/X86-SOFTWARE-REVERSE- ENGINEERING-CRACKING-AND-COUNTER-MEASURES.
  • 23. History Before diving into the nitty-gritty details of cracking and reverse engineering, it is useful to understand its history. Software protections and the tricks and techniques used to overcome them have been evolving for decades. The First Software Protections The first software copy protections emerged in the 1970s. Some of the early movers in the space were as follows: Apple II: The Apple II incorporated proprietary disk drivers that would allow writing at half-tracks, writing extra rings, and staggering and overlapping sectors. The purpose of this was to make the disks unusable by non-Apple machines and software that wouldn't know to read and write at these odd offsets. Atari 800: Atari 800 systems would intentionally include bad sectors in their disks and attempt to load these sectors. If these loads didn't return a “bad sector” error, then the software knew it wasn't a valid disk and would halt execution. Commodore 64: Legitimate Commodore 64 software was distributed only on read-only disks. The software would attempt to overwrite the disk, and, if it succeeded, it knew the disk was counterfeit. These protections all depended on unusual behavior by the software, such as the use of invalid memory or attempting to overwrite the program's own code. Defeating these protections required an understanding of how the software worked. The Rise of Cracking and Reverse Engineering The rise of cracking and reverse engineering began in the 1980s. However, these early crackers weren't in it for the money. Cracking was a contest to determine who could figure out and bypass software protections the quickest.
  • 24. Over the next several decades, the reverse engineering and cracking scene evolved. These are some of the key dates in the history of reverse engineering: 1987: Fairlight's formation in 1987 by Bacchus defines one of the first operational groups. Fairlight will later come to prominence in FBI crackdowns of the early 2000s. For more historic details visit www.fairlight.to and csdb.dk. 1990: Elliot J. Chikofsky and James H. Cross II defined reverse engineering as “the process of analyzing a subject system to identify the system's components and their interrelationships and to create representations of the system in another form or at a higher level of abstraction. (“Reverse Engineering and Design Recovery: A Taxonomy.” IEEE Software, Vol. 7, Issue 1, Jan 1990). 1997: Old Red Cracker (handle +ORC) founds the Internet- based High Cracking University (+HCU) to allow everyone to learn about cracking. +ORC released “how to crack” lessons online and authored academic papers. +HCU students had handles that began with an +. 1997–2009: The “warez scene” emerges with groups competing to be the first to release copyrighted material. Insiders (aka “suppliers”) provided early access to their groups, “crackers” broke the protections, and “couriers” distributed cracked software to FTP sites. Between 2003 and 2009, approximately 3,164 active groups were on “the scene”, competing primarily for pride and bragging rights, not money. 2004: The FBI and other countries begin raids against “the scene”. Operation Fastlink (2004) led to the conviction of 60 warez members, and Operation Site Down (2005) took down 25 warez groups. The arms race between software protections and crackers continues to rage, and reverse engineering is an invaluable skill set on both sides. Crackers need to understand how a program works to manipulate it and bypass defenses. On the defensive side, it's
  • 25. important to understand the latest cracking techniques to develop defenses that protect intellectual property and other sensitive data. Legal The best way to learn is by doing. This is why this book includes labs and exercises with real-world software as well as manufactured examples and crackmes. We are not lawyers, and those with concerns should consult a lawyer. We recommend the Electronic Frontier Foundation (www.eff.org). Chapter 15 covers legal topics because we feel it's important for everyone to understand the US- based laws that affect this area. There are two main laws to be aware of: the Copyright Act and the Digital Millennium Copyright Act (DMCA). The Fair Use Clause of the Copyright Act (Copyright Act, 17 U.S.C. § 107) states that reverse engineering falls under “fair use” when done for “…purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research….” This exception is balanced against “the effect of the use upon the potential market for or value of the copyrighted work.” In essence, reverse engineering used for educational purposes is legal if you don't share or sell the cracked software. In October 2016, the DMCA also added an exception for good faith security research. It states, “accessing a computer program solely for purposes of good-faith testing, …where such activity is carried out in a controlled environment designed to avoid any harm to individuals or the public, …and is not used or maintained in a manner that facilitates copyright infringement.” The software examined in this book and used in exercises was carefully selected to fall under the fair use and DMCA exceptions. If you are planning to reverse engineer and crack software for anything other than self-education, you should consult a lawyer. The legal considerations of reverse engineering will also be explored in greater detail in a later chapter. Software reverse engineering and cracking have a rich history, and this skill set has both offensive and defensive applications. However, it is important to understand the laws around these disciplines and
  • 26. ensure that your activities fall under the good-faith testing and fair use exemptions. This book is designed to provide a strong foundation in the skills and tools used for software reverse engineering and cracking. Beginning with the fundamentals, the book will move on through sections on software reverse engineering and cracking to end with an exploration of advanced offensive and defensive techniques.
  • 27. CHAPTER 1 Decompilation and Architecture An effective reverse engineer or cracker is one who understands the systems they are analyzing. Software is designed to run in a particular environment, and if you don't understand how that environment works, you will struggle to understand the software. This chapter explores the steps necessary to get started reverse engineering an application. Decompilation is crucial to transforming an application from machine code to something that can be read and understood by humans. To actually analyze the resulting code, it is also necessary to understand the architecture of the computers that it is designed to run on. Decompilation Most programmers write using a higher-level programming language like C/C++ or Java, which is designed to be human-readable. However, computers are designed to run machine code, which represents instructions in binary. Compilation is the process of converting a programming language to machine code. This means decompilation would be the process of taking machine code back to the original programming language, recovering the original source code. When available, this is the easiest approach to reverse engineering because source code is designed to be read and interpreted by a human. The majority of this book will focus on the more typical case when decompilation is not possible. But for the purposes of learning, it is important to understand that sometimes you can decompile back to the source code, and when that is an option, you should take it.
  • 28. When Is Decompilation Useful? For many programming languages, full decompilation is impossible. These languages build code directly to machine code, and some information, such as variable names, is lost in the process. While some advanced decompilers can build pseudocode for these languages, the process isn't perfect. However, some programming languages use what's called just-in- time (JIT) compilation. When programs written in JIT languages are “built,” they are converted from the source code into an intermediate language (IL), not machine code. JIT compilers store a copy of the code in this IL until the program is run, at which point the code is converted to machine code. Examples of JIT languages include Java, Dalvik (Android), and .NET. For example, Java is well-known for being largely platform-agnostic, and the reason for this is its use of an IL (Java bytecode) and the Java Virtual Machine (JVM). By distributing the program code as bytecode and compiling it only at runtime, Java's JVM translates from the Java IL to machine code specific to the machine it's running on. While this approach can negatively impact file size and performance, it pays off in portability. JIT compilation also makes reverse engineering these applications much easier. These intermediate languages are similar enough to the original source code that they can be decompiled or converted back into usable source code. Source code is designed to be human- readable, making it far easier to understand the application's logic and identify software protections or other embedded secrets. Decompiling JIT Programming Languages For JIT languages like .NET, several free decompilers are available. One widely used .NET decompiler is JetBrains dotPeek, which is available from www.jetbrains.com/decompiler. Figure 1.1 shows an example of .NET code decompiled in dotPeek. As shown in the figure, the .NET code is easily readable after decompilation because the intermediate language encodes a wealth of information as metadata, enabling more accurate reconstruction
  • 29. of the source code. Any sensitive information or trade secrets contained within the code are easily accessible to a reverse engineer. Figure 1.1: JetBrains dotPeek .NET decompiler Defending JIT Languages Unlike true machine code programs, JIT-compiled programs can often be converted to source code. Lowering the bar for reverse engineering the code makes many of the x86 anti-reverse engineering defenses discussed in later chapters unnecessary and overkill. For decompilable languages, a commonly used defense against reverse engineering is obfuscation. Figure 1.2 shows an example of a .NET application before and after obfuscation. The top half of the figure contains code before obfuscation occurs, where the function and variable names and strings are easily
  • 30. readable. The information in these variable names makes it easier for a reverse engineer to understand the purpose of each function and how the application works as a whole. In the bottom half of the image, we see the obfuscated version of the same code. Now, function names, variable names, and strings are all mangled, making it much harder to understand the purpose of the function shown, let alone the application as a whole. Another important security best practice is to avoid writing security or privacy-critical code in JIT languages where reverse engineering is easy. Instead, write this code in an assembled language, such as C/C++, where reverse engineering is significantly more difficult. This code can be included in DLLs that are linked to the executable containing the nonsensitive code written in a JIT language. Figure 1.2: Obfuscation in JetBrains dotPeek Lab 1: Decompiling This is the first hands-on lab for this book. Labs and all associated instructions can be found in their corresponding folder here:
  • 31. https://github.com/DazzleCatDuo/X86-SOFTWARE-REVERSE- ENGINEERING-CRACKING-AND-COUNTER-MEASURES For this lab, please locate Lab Decompiling and follow the provided instructions. Skills to Practice Every lab in this book is designed to teach and provide hands-on experience with certain skills. This lab's skills to practice include the following: Decompiling Performing introductory reverse engineering To learn these skills, you'll be using JetBrains dotPeek to reverse engineer and modify a .NET application. Takeaways Decompiling is a powerful and easy approach to understanding and modifying a program. However, it doesn't work on every program. While programs written in languages such as C/C++ can be decompiled using tools such as IDA's Hex-Rays Decompiler or Ghidra, the result is often low-quality and difficult to use. When developing applications that contain sensitive information or that you don't want modified, it's better to use a language that isn't easily decompiled. For example, C/C++ is a better choice for sensitive functionality than a .NET language such as C#. Architecture Decompilation is the easy approach to reverse engineering because it gets you back to higher-level languages and logic structures. However, this easy path is not often available. For languages that build to machine code, we need to go deeper and understand how computer architectures and machine and assembly code work.
  • 32. Computer Architecture It's generally thought that the average programmer doesn't need an in-depth understanding of how computers work. When writing a program in a procedural language, the operating system handles all of the low-level operations. A program is displayed as a process that has access to the processor, memory, and file system whenever it needs them. Processes appear to have their own contiguous memory spaces, and files are just a sequence of bytes to read and write. However, none of this is actually true, and your operating system has been abstracting the truth from you (to make it easier to program). A solid understanding of how computer architecture actually works is essential for a reverse engineer. Figure 1.3 shows the main components that make up a computer, including the central processing unit, bridge, memory, and peripherals. Figure 1.3: Computer architecture The Central Processing Unit The central processing unit (CPU) is where processing occurs on a computer. Inside the CPU are the following components:
  • 33. Arithmetic logic unit (ALU): The ALU performs mathematical operations within the computer, such as addition and multiplication. Registers: Registers perform temporary data storage and are used as the primary inputs and outputs of x86 instructions. Registers provide extremely fast access to a single word of data and are typically accessed by name. Control units: Control units execute code. This includes reading instructions and orchestrating the operations of other elements within a computer. Bridges and Peripherals The CPU is connected via a bus to a bridge. The purpose of the bridge is to connect the CPU to other components of the system, including memory and the I/O bus, which is where peripherals such as the keyboard, mouse, and speakers are connected to the system. While information flows over a bus, the bridge is responsible for controlling this traffic and ensuring that traffic flowing in over one bus is routed out over the appropriate bus. Peripherals, connected via the I/O bus, allow the computer to communicate with the outside world. This includes sending and receiving data from the graphics card, keyboard, mouse, speakers, and other systems. Memory and Registers As its name suggests, memory is where data is stored on the computer. Data is stored as a linear series of bytes that are accessed via their address. This design allows moderately fast access to data stored on the system. When a program wants to access data in memory, the CPU sends a request via a bus to the bridge, which forwards it to the memory, where the data at the indicated address is accessed. The requested data then needs to retrace that route and return to the CPU before it can be used by the program. In contrast, a register is physically located within the CPU, making it far more accessible.
  • 34. Registers are storage that lives inside of the CPU and, unlike memory, are not a linear series of bytes. Registers are specifically named and have set sizes associated with each. Registers and memory both serve the same purpose: they store data. However, they have different specializations (quality versus quantity). Registers are few in number and expensive, but they provide extremely fast access to data. Memory is cheap and plentiful but offers slower access speeds. The bulk of the data associated with a program, the code itself and its data, will be stored in memory. While the program is running, small chunks of data will be copied to the registers for processing. Assembly Computers run on binary, digital logic. Everything is either on (1) or off (0). This includes programs running on a computer. All high-level languages are eventually converted into a series of bits called machine code. This machine code defines the set of instructions that the computer executes to perform a desired function. Introduction to Machine Code Every programmer begins learning a language with a “hello world” program. In x86, the machine code for “hello world” is as follows: 55 89 e5 83 e4 f0 83 ec 10 b8 b0 84 04 08 89 04 24 e8 1a ff ff ff b8 00 00 00 00 c9 c3 90 This machine code is written in hexadecimal for readability and compactness, but its true value is a binary string of 1s and 0s. This binary string contains instructions to flip transistors to calculate information, fetch data from memory, send signals over the system buses, interact with the graphics card, and, finally, print out the “hello world” text. If this string of characters seems a bit short to accomplish all this, it's because these instructions trigger the operating system (in this example Linux) to help out. Machine code controls the processor at the most detailed possible level. Some of the functions that machine code performs include the following:
  • 35. Moving data in and out of memory Moving data to and out of registers Controlling the system bus Controlling the ALU, control unit, and other components This low-level control means that applications written in machine code can be incredibly powerful and efficient. However, while memorizing and inputting various series of bits to perform certain tasks is pretty awesome, it is inefficient and prone to error. From Machine Code to Assembly In machine code, a series of bits represents a particular action. For example, 0x81 or 10000001 is an instruction that adds two values together and stores the result at a particular location. Assembly code is designed to be a human-readable version of machine code. Instead of memorizing a binary or hexadecimal string like 0x81 or 10000001, a programmer can use add. The add mnemonic is mapped to 0x81, so this shorthand makes programming easier without losing any of the benefits of writing in machine code. Translating machine code to assembly code makes it much easier to understand. For example, the previous “hello world” example code can be converted into a series of comprehensible instructions. MACHINE CODE ASSEMBLY 55 push ebp 89 e5 mov ebp,esp 83 e4 f0 and esp, 0xfffffff0 83 ec 10 sub esp, 0x10 b8 b0 84 04 08 mov eax 89 04 24 mov [esp], eax e8 1a ff ff ff call 80482f4 b8 00 00 00 00 mov eax, 0x0 c9 leave
  • 36. MACHINE CODE ASSEMBLY c3 ret 90 nop If you understand machine code, writing directly in it can be fun, and there are cases where it may make sense. However, the majority of the time, it is inefficient and impractical. Writing in assembly provides the same benefits as writing in machine code but is much more practical. After code has been written in assembly, it can be translated to machine code by an assembler in a process called assembling. A program already in machine code can be disassembled into assembly code by a disassembler. DEFINITION Assemblers convert assembly code to machine code. Disassemblers convert machine code to assembly. Many programmers don't write in machine code or assembly. Instead, they use higher-level languages that abstract away more of the details. For example, the following pseudocode is similar to many high-level procedural languages. int x=1, y=2, z=x+y; During the compiling process, these higher-level languages are converted into assembly code similar to the following: mov [ebp-4], 0x1 mov [ebp-8], 0x2 mov eax, [ebp-8] mov edx, [ebp-4] lea eax, [edx+1*eax] mov [ebp-0xc], eax An assembler can then be used to convert the assembly code into the following machine code that a computer can use:
  • 37. c7 45 fc 01 00 00 00 c7 45 f8 02 00 00 00 8b 45 f8 8b 55 fc 8d 04 02 89 45 f4 Instruction Set Architectures and Microarchitectures The word computer covers a wide range of systems. A smartwatch and a desktop computer both work in similar ways. However, their internal components can differ significantly. An instruction set architecture (ISA) describes the ecosystems where programs run. Some of the factors that an ISA defines include the following: Registers: The ISA specifies whether a processor has a single register or hundreds. It also defines the size of these registers, whether they contain 8 bits or 128 bits. Addresses and data formats: The ISA specifies the format for addresses used to access data in memory. It also defines how many bytes the system can grab from memory at a time. Machine instructions: Different ISAs may support different sets of instructions. The ISA defines whether addition, subtraction, equality, halt, and other instructions are supported. By defining the capabilities of the physical system, the ISA also indirectly defines the assembly language. The ISA specifies which low-level instructions are available and what those instructions do. A microarchitecture describes how a particular ISA is implemented on a processor. Figure 1.4 shows an example of the Intel Core 2 architecture. Together, an ISA and microarchitecture define the computer architecture. The existence of thousands of ISA and thousands of microarchitectures means that there are thousands of computer architectures as well.
  • 38. Figure 1.4: Intel Core 2 architecture
  • 39. DEFINITION An instruction set architecture defines how registers, addresses, data formats, and machine instructions work. Microarchitectures implement ISAs on a processor. Together, an ISA and microarchitecture define a computer architecture. RISC vs. CISC Computer Architectures While thousands of computer architectures exist, they can be broadly divided into two main categories. Reduced instruction set computing (RISC) architectures define a small number of simpler instructions. In general, RISC architectures are cheaper and easier to create, and the hardware is physically smaller and consumes less power. In contrast, a complex instruction set computing (CISC) architecture defines a larger number of more powerful instructions. CISC processors are more expensive and difficult to create and are typically larger and consume more power. While CISC architectures may seem objectively worse than RISC ones, their main benefit lies in the ease and efficiency of programming. For example, consider a hypothetical example where a program wants to multiply a value by 5 in a RISC versus CISC system. CISC RISC mul [100], 5 load r0, 100 mov r1, r0 add r1, r0 add r1, r0 add r1, r0 add r1, r0 mov [100], r1
  • 40. In this example, a CISC processor can perform the calculation in a single instruction if it has a multiplication operation that can load a value from memory, multiply it, and store the result at the same memory location. However, a RISC processor may lack a multiplication operator because it is a complex operation. Instead, the RISC loads the value from memory, adds it to itself four times, and stores the result in the same memory location across seven steps. RISC and CISC architectures both have their advantages, disadvantages, and use cases. For example, a RISC operator may take 100 instructions to perform the same operation that a CISC operator can perform in one. However, that single CISC operation may take 100× as long to run or 100× the power. Both RISC and CISC instruction sets are in common use today. Some examples of widely used RISC architectures include the following: ARM (used by phones, tablets) MIPS (used by embedded systems and networking equipment) PowerPC (used by original Macs and Xbox360) In this book, we focus on the x86 assembly language, which is a CISC architecture. This architecture is in use on all modern PCs and servers and is supported by all the main operating systems (Windows, Mac, Linux) and even some gaming systems, such as the Xbox One. Making it one of the most powerful to learn for software cracking. Summary The machine code that actually runs on computers isn't designed for humans to read and understand. To be usable, it needs to be converted into a different form. One option for this is decompilation, which produces a result that is similar or identical to the original source code. However, decompilation is not always possible. For fully compiled languages, such as C/C++, and many other languages, it is necessary to disassemble a compiled executable and
  • 41. analyze it in assembly. However, this requires a much deeper understanding of the computer's architecture and how it actually works than writing and reading code in a higher-level language. Now that we know the role decompilation can play and the need for disassembly, in the next few chapters we'll look at how computers work, so we can learn to disassemble like a pro.
  • 42. CHAPTER 2 x86 Assembly: Data, Modes, Registers, and Memory Access Most software reverse engineering requires disassembling a compiled executable and analyzing the result. This disassembly results in assembly code, not a higher-level language. While a few assembly languages exist, x86 is one of the most widely used. This chapter introduces some of the key concepts of x86 assembly, providing a foundation for later chapters. Introduction to x86 Thousands of computer architectures exist. While they all work similarly, a computer is a computer—but there are minor or major differences between each. To study reverse engineering, we need to select an architecture to focus on. In this book, we'll be using x86, which was selected for a few different reasons: Ubiquity: x86 is the most widely used assembly language, making it widely applicable for reverse engineering. Computer support: x86 applications can be built, run, and reverse engineered on any desktop, laptop, or server. Market share: x86 is the core of the major operating systems (Windows, Linux, and macOS), so it is used in billions of systems. The x86 architecture has been around for decades and has evolved significantly over the years. It was first introduced in 1974 by Intel, and some of the main milestones in the history of x86 include the following:
  • 43. Intel 8080: 8-bit microprocessor, introduced in 1974 Intel 8086: 16-bit microprocessor, introduced in 1978 Intel 80386: 32-bit microprocessor, introduced in 1985 Intel Prescott, AMD Opteron, and Athlon 64: 64-bit microprocessor, introduced in 2003/2004 Over its nearly 50-year history, the x86 architecture has regularly added new features while maintaining backward compatibility. Even if a feature was determined to be unused, it was never removed from the system. As a result, programs written for the Intel 8086 processor released in 1978 can still run on the latest x86 chips with no modifications. This focus on backward compatibility has created an immense, complex, and interesting architecture. The latest Intel Software Developer's manual (www.intel.com/content/www/us/en/developer/articles/technical/i ntel-sdm.html) is more than 5,000 pages long and only begins to scratch the surface of what this architecture can do. This book focuses on understanding the basics of x86, which is all that is needed to read, write, and manipulate most x86 code. As the x86 architecture has changed, the term x86 has become an umbrella term for all of the architectures that have evolved from the Intel 8086 16-bit architecture. This includes the Intel 80286 architecture, which contains both 16-bit and 32-bit architectures, and the Intel 80886 architecture, which adds a 64-bit architecture. The term x64 specifically refers to the 64-bit version of x86. This book will show examples in 32-bit x86 architecture. All of the concepts from 32-bit x86 translate exactly to x64. It is substantially easier to work on examples in 32 bits versus 64 as you're learning. After studying 32-bit x86 throughout this book, you will be immediately able to look at x64-bit assembly and understand it. However, your eyeballs will be thanking you for not having to look at 64 bits all the time, as even 32 bits are a bit painful to stare at. So, do not let the examples being in 32-bit give you pause that this is outdated or that you should focus on 64-bit out of the gate. Both of us learned 32-bit first, and we've taught software cracking a lot and
  • 44. can confidently say that if you give yourself the solid 32-bit foundation first, 64-bit becomes just another few register names and longer values. Assembly Syntax Selecting x86 from the thousands of possible computer architectures is important, but it isn't enough. While an instruction set architecture (ISA) defines factors such as the registers, data format, and machine instructions, it doesn't specify the syntax. As long as an assembly language follows all of the rules for registers, addressing, etc., and defines the right set of instructions, it's a valid x86 language. For example, an x86 language must have a multiply operation. However, its mnemonic could be mul, MUL, multiply, or any other variation across any language. The syntax of an assembly language is entirely defined by the assembler. There is no standard syntax for assembly language in general or for x86 assembly in particular. As a result, there are hundreds of different variations. However, there are two prevalent x86 syntax options that you will find most x86 assembly tools use: AT&T syntax and Intel syntax. Under each of these main branches are hundreds of assembler- specific variations. While Intel and AT&T assembly are both x86, they look very different. For example, consider a statement designed to move the memory at address ebx+4*ecx+2020 into register eax. This instruction looks very different in the Intel and AT&T syntaxes: INTEL SYNTAX AT&T SYNTAX mov eax, [ebx+4*ecx+2020] mov 0x7e4(%ebx,%ecx,4),%eax In the Intel syntax, after the instruction mov comes the location where the result will be stored. Memory access is indicated by square brackets, and the calculation of the memory address [ebx+4*ecx+2020] is performed within these brackets. AT&T syntax differs from Intel syntax in a few ways:
  • 45. Exploring the Variety of Random Documents with Different Content
  • 46. payments must be paid within 60 days following each date on which you prepare (or are legally required to prepare) your periodic tax returns. Royalty payments should be clearly marked as such and sent to the Project Gutenberg Literary Archive Foundation at the address specified in Section 4, “Information about donations to the Project Gutenberg Literary Archive Foundation.” • You provide a full refund of any money paid by a user who notifies you in writing (or by e-mail) within 30 days of receipt that s/he does not agree to the terms of the full Project Gutenberg™ License. You must require such a user to return or destroy all copies of the works possessed in a physical medium and discontinue all use of and all access to other copies of Project Gutenberg™ works. • You provide, in accordance with paragraph 1.F.3, a full refund of any money paid for a work or a replacement copy, if a defect in the electronic work is discovered and reported to you within 90 days of receipt of the work. • You comply with all other terms of this agreement for free distribution of Project Gutenberg™ works. 1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™ electronic work or group of works on different terms than are set forth in this agreement, you must obtain permission in writing from the Project Gutenberg Literary Archive Foundation, the manager of the Project Gutenberg™ trademark. Contact the Foundation as set forth in Section 3 below. 1.F. 1.F.1. Project Gutenberg volunteers and employees expend considerable effort to identify, do copyright research on, transcribe and proofread works not protected by U.S. copyright
  • 47. law in creating the Project Gutenberg™ collection. Despite these efforts, Project Gutenberg™ electronic works, and the medium on which they may be stored, may contain “Defects,” such as, but not limited to, incomplete, inaccurate or corrupt data, transcription errors, a copyright or other intellectual property infringement, a defective or damaged disk or other medium, a computer virus, or computer codes that damage or cannot be read by your equipment. 1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the “Right of Replacement or Refund” described in paragraph 1.F.3, the Project Gutenberg Literary Archive Foundation, the owner of the Project Gutenberg™ trademark, and any other party distributing a Project Gutenberg™ electronic work under this agreement, disclaim all liability to you for damages, costs and expenses, including legal fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE. 1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a defect in this electronic work within 90 days of receiving it, you can receive a refund of the money (if any) you paid for it by sending a written explanation to the person you received the work from. If you received the work on a physical medium, you must return the medium with your written explanation. The person or entity that provided you with the defective work may elect to provide a replacement copy in lieu of a refund. If you received the work electronically, the person or entity providing it to you may choose to give you a second opportunity to receive the work electronically in lieu of a refund.
  • 48. If the second copy is also defective, you may demand a refund in writing without further opportunities to fix the problem. 1.F.4. Except for the limited right of replacement or refund set forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PURPOSE. 1.F.5. Some states do not allow disclaimers of certain implied warranties or the exclusion or limitation of certain types of damages. If any disclaimer or limitation set forth in this agreement violates the law of the state applicable to this agreement, the agreement shall be interpreted to make the maximum disclaimer or limitation permitted by the applicable state law. The invalidity or unenforceability of any provision of this agreement shall not void the remaining provisions. 1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the trademark owner, any agent or employee of the Foundation, anyone providing copies of Project Gutenberg™ electronic works in accordance with this agreement, and any volunteers associated with the production, promotion and distribution of Project Gutenberg™ electronic works, harmless from all liability, costs and expenses, including legal fees, that arise directly or indirectly from any of the following which you do or cause to occur: (a) distribution of this or any Project Gutenberg™ work, (b) alteration, modification, or additions or deletions to any Project Gutenberg™ work, and (c) any Defect you cause. Section 2. Information about the Mission of Project Gutenberg™
  • 49. Project Gutenberg™ is synonymous with the free distribution of electronic works in formats readable by the widest variety of computers including obsolete, old, middle-aged and new computers. It exists because of the efforts of hundreds of volunteers and donations from people in all walks of life. Volunteers and financial support to provide volunteers with the assistance they need are critical to reaching Project Gutenberg™’s goals and ensuring that the Project Gutenberg™ collection will remain freely available for generations to come. In 2001, the Project Gutenberg Literary Archive Foundation was created to provide a secure and permanent future for Project Gutenberg™ and future generations. To learn more about the Project Gutenberg Literary Archive Foundation and how your efforts and donations can help, see Sections 3 and 4 and the Foundation information page at www.gutenberg.org. Section 3. Information about the Project Gutenberg Literary Archive Foundation The Project Gutenberg Literary Archive Foundation is a non- profit 501(c)(3) educational corporation organized under the laws of the state of Mississippi and granted tax exempt status by the Internal Revenue Service. The Foundation’s EIN or federal tax identification number is 64-6221541. Contributions to the Project Gutenberg Literary Archive Foundation are tax deductible to the full extent permitted by U.S. federal laws and your state’s laws. The Foundation’s business office is located at 809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up to date contact information can be found at the Foundation’s website and official page at www.gutenberg.org/contact
  • 50. Section 4. Information about Donations to the Project Gutenberg Literary Archive Foundation Project Gutenberg™ depends upon and cannot survive without widespread public support and donations to carry out its mission of increasing the number of public domain and licensed works that can be freely distributed in machine-readable form accessible by the widest array of equipment including outdated equipment. Many small donations ($1 to $5,000) are particularly important to maintaining tax exempt status with the IRS. The Foundation is committed to complying with the laws regulating charities and charitable donations in all 50 states of the United States. Compliance requirements are not uniform and it takes a considerable effort, much paperwork and many fees to meet and keep up with these requirements. We do not solicit donations in locations where we have not received written confirmation of compliance. To SEND DONATIONS or determine the status of compliance for any particular state visit www.gutenberg.org/donate. While we cannot and do not solicit contributions from states where we have not met the solicitation requirements, we know of no prohibition against accepting unsolicited donations from donors in such states who approach us with offers to donate. International donations are gratefully accepted, but we cannot make any statements concerning tax treatment of donations received from outside the United States. U.S. laws alone swamp our small staff. Please check the Project Gutenberg web pages for current donation methods and addresses. Donations are accepted in a number of other ways including checks, online payments and
  • 51. credit card donations. To donate, please visit: www.gutenberg.org/donate. Section 5. General Information About Project Gutenberg™ electronic works Professor Michael S. Hart was the originator of the Project Gutenberg™ concept of a library of electronic works that could be freely shared with anyone. For forty years, he produced and distributed Project Gutenberg™ eBooks with only a loose network of volunteer support. Project Gutenberg™ eBooks are often created from several printed editions, all of which are confirmed as not protected by copyright in the U.S. unless a copyright notice is included. Thus, we do not necessarily keep eBooks in compliance with any particular paper edition. Most people start at our website which has the main PG search facility: www.gutenberg.org. This website includes information about Project Gutenberg™, including how to make donations to the Project Gutenberg Literary Archive Foundation, how to help produce our new eBooks, and how to subscribe to our email newsletter to hear about new eBooks.