Book Review: "Reverse Engineering for Beginners" (RE4B)

"Reverse Engineering for Beginners" (RE4B) by Dennis Yurichev, is an amazing book, extremely technical, and also totally free. The book has it's own dedicated site, which is a great resource as it presents the many forms which the book has been made available in (multiple languages etc..). Possibly one of the best computer security / computer science books I have read to date, I'm going to talk a bit more about the structure of the book before I dive into the content. The github for the book is here, which is awesome because accepts pull requests meaning anyone can add to the text, keeping it open source, free, and up to date for and by the community. The main book has two version, lite and full, I read the lite version at 147 pages, although the full version has 921 pages (a felt increase in the magnitude of the text)! While I recommend the lite version for cover to cover reading and the full as a reference text, you can actually build the book in any manner you want using the LaTex documents described here. It's available for in many forms and languages, both digital and print, and while I have some selected parts in print I generally recommend the digital version so you can search it (ctrl+f). I give it 10 / 10 stars, the first book I've given a perfect rating to, as it's highly technical with many references and current weekly updates (and FREE). Overall, I recommend the text to fledgling computer scientists, reverse engineers, and even exploit developers, essentially anyone on a quest to better understand low level computing. The book also heavily references it sources, with links and subscripts at the bottoms of the pages and throughout, something I have rewarded technical books for highly in the past, which is also really nice in the digital version, as the links work for sections within the book as well. RE4B is full of code, having almost as much code and examples of disassembly as it does regular text, everything from hex, to shell scripting, to C, to IL, and assembly for all kinds of architectures. The book also includes tons of screenshots from essential tools like IDApro and OllyDebugger, where it's extra helpful to see these common patterns in the tools they would be discovered in. RE4B essentially focuses on common assembly patterns, showing readers how to recognize basic compiler conventions, encryptions routine, obfuscation techniques, strange constants and common processes. As a student of reverse engineering, the book is excellent for some quick targeted learning, where I can pick up and read a chapter on a common coding convention, and become familiar with what this looks like at a lower level. The book is excellent for highlighting those architecture specific gotchas, or easily recognizable patterns that are indicative of higher level operations (such as manipulating user input or a common networking process). This part will be long, but I want to compare the index of the lite version, to the index of the full version, so readers can tell the difference and what they are missing by reading the lite version. Essentially, the full version provides far more detail, variation, and examples within each chapter, which the indexes will illuminate.The following is the index of the lite version (the numbers sections and subsections):

Part I: Code patterns 

Chapter 1: A short introduction to the CPU
Chapter 2: The simplest Function 
2.1: x86
Chapter 3: Hello, world! 
3.1: x86
3.1.1: MSVC
3.2: x86-64
3.2.1: MSVC—x86-64
3.3: Conclusion
Chapter 4: Function prologue and epilogue 
Chapter 5: Stack 
5.1: Why does the stack grow backwards?
5.2: What is the stack used for?
5.2.1: Save the function’s return address
5.2.2: Passing function arguments
5.2.3: Local variable storage
5.2.4: x86: alloca() function
5.2.5: (Windows) SEH
5.2.6: Buffer overflow protectio
5.2.7: Automatic deallocation of data in stack
5.3: A typical stack layout
Chapter 6: printf() with several arguments
6.1: x86
6.1.1: x86: 3 arguments
6.1.2: x64: 8 arguments
6.2: Conclusion
6.3: By the way
Chapter 7: scanf()
7.1: Simple example
7.1.1: About pointers
7.1.3: x64
7.2: Global variables
7.2.1: MSVC: x86
7.2.2: MSVC: x64
7.3: scanf() result checking
7.3.1: MSVC: x86
7.3.2: MSVC: x86 + Hiew
7.3.3: MSVC: x64
7.4: Exercise
Chapter 8 :Accessing passed arguments 
8.1: x86
8.1.1: MSVC
8.2: x64
8.2.1: MSVC
Chapter 9: More about results returning 
9.1: Attempt to use the result of a function returning void
9.2: What if we do not use the function result?
Chapter 10: GOTO operator 
10.1: Dead code
Chapter 11: Conditional jumps 
11.1: Simple example
11.1.1: x86
11.2: Calculating absolute value
11.2.1: Optimizing MSVC
11.3: Ternary conditional operator
11.3.2: Let’s rewrite it in an if/else way
11.4: Getting minimal and maximal values
11.4.1: 32-bit
11.5: Conclusion
11.5.1: x86
11.5.2: Branchless
Chapter 12: switch()/case/default 
12.1: Small number of cases
12.1.1: x86
12.1.2: Conclusion
12.2: A lot of cases
12.2.1: x86
12.2.2: Conclusion
12.3: When there are several case statements in one block
12.3.1: MSVC
12.4: Fall-through
12.4.1: MSVC x86
Chapter 13: Loops
13.1: Simple example
13.1.1: x86
13.1.2: One more thing
13.2: Memory blocks copying routine
13.2.1: Straight-forward implementation
13.3: Conclusion
Chapter 14: Simple C-strings processing 
14.1: strlen()
14.1.1: x86
Chapter 15: Replacing arithmetic instructions to other ones 
15.1: Multiplication
15.1.1: Multiplication using addition
15.1.2: Multiplication using shifting
15.1.3: Multiplication using shifting, subtracting, and adding
15.2: Division
15.2.1: Division using shifts
Chapter 16: Arrays 
16.1: Simple example
16.1.1: x86
16.2: Buffer overflow
16.2.1: Reading outside array bounds
16.2.2: Writing beyond array bounds
16.3: One more word about arrays
16.4: Array of pointers to strings
16.4.1: x64
16.5: Multidimensional arrays
16.5.1: Two-dimensional array example
16.5.2: Access two-dimensional array as one-dimensional
16.5.3: Three-dimensional array example
16.6: Conclusion
Chapter 17: Manipulating specific bit(s) 
17.1: Specific bit checking
17.1.1: x86
17.2: Setting and clearing specific bits
17.2.1: x86
17.3: Shifts
17.4: Counting bits set to 1
17.4.1: x86
17.4.2: x64
17.5: Conclusion
17.5.1: Check for specific bit (known at compile stage)
17.5.2: Check for specific bit (specified at runtime)
17.5.3: Set specific bit (known at compile stage)
17.5.4: Set specific bit (specified at runtime)
17.5.5: Clear specific bit (known at compile stage)
17.5.6: Clear specific bit (specified at runtime)
Chapter 18: Linear congruential generator
18.1: x86
18.2: x64
Chapter 19: Structures
19.1: MSVC: SYSTEMTIME example
19.1.1: Replacing the structure with array
19.2: Let’s allocate space for a structure using malloc()
19.3: Fields packing in structure
19.3.1: x86
19.3.2: One more word
19.4: Nested structures
19.5: Bit fields in a structure
19.5.1: CPUID example
Chapter 20: 64-bit values in 32-bit environment 
20.1: Returning of 64-bit value
20.1.1: x86
20.2: Arguments passing, addition, subtraction
20.2.1: x86
20.3: Multiplication, division
20.3.1: x86
20.4: Shifting right
20.4.1: x86
20.5: Converting 32-bit value into 64-bit one
20.5.1: x86
Chapter 21: 64 bits 
21.1: x86-64

Part II: Important fundamentals 

Chapter 22: Signed number representations
Chapter 23: Memory 

Part III: Finding important/interesting stuff in the code 

Chapter 24: Communication with the outer world (win32) 
24.1: Often used functions in the Windows API
24.2 tracer: Intercepting all functions in specific module
Chapter 25: Strings
25.1: Text strings
25.1.1: C/C++
25.1.2 Borland Delphi
25.1.3: Unicode
25.1.4: Base64
25.2: Error/debug messages
25.3: Suspicious magic strings
Chapter 26: Calls to assert() 
Chapter 27: Constants 
27.1: Magic numbers
27.1.1: Dates
27.1.2: DHCP
27.2: Searching for constants
Chapter 28: Finding the right instructions 
Chapter 29: Suspicious code patterns 
29.1: XOR instructions
29.2: Hand-written assembly code
Chapter 30: Using magic numbers while tracing 
Chapter 31: Other things 
31.1: General idea
31.2: Some binary file patterns
31.3: Memory “snapshots” comparing
31.3.1: Windows registry
31.3.2: Blink-comparator

Part IV: Tools 

Chapter 32: Disassembler 
32.1: IDA
Chapter 33: Debugger 
33.1: tracer
Chapter 34: Decompilers 
Chapter 35: Other tools 

Part V: Books/blogs worth reading 

Chapter 36: Books 
36.1: Windows
36.2: C/C++
36.3: x86 / x86-64
36.4: ARM
36.5: Cryptography
Chapter 37: Blogs 
37.1: Windows
Chapter 38: Other
Afterword
Chapter 39: Questions?
Acronyms used
Index
Bibliography 

The following is the index of the full version, where you can really see how much extra detail they put in, especially in regards to the various architectures:

Part I: Code patterns 

Chapter 1: A Short introduction to the CPU
1.1: A Couple of words about different ISA4s
Chapter 2: The simplest Function
2.1: x86
2.2: ARM
2.3: MIPS
2.3.1: A note about MIPS instruction/register names
Chapter 3: Hello, world!
3.1: x86
3.1.1: MSVC
3.1.2: GCC
3.1.3: GCC: AT&T syntax
3.2: x86-64
3.2.1: MSVC—x86-64
3.2.2: GCC—x86-64
3.3: GCC—one more thing
3.4: ARM
3.4.1: Non-optimizing Keil 6/2013 (ARM mode)
3.4.2: Non-optimizing Keil 6/2013 (Thumb mode)
3.4.3: Optimizing Xcode 4.6.3 (LLVM) (ARM mode)
3.4.4: Optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode)
3.4.5: ARM64
3.5: MIPS
3.5.1: A word about the “global pointer”
3.5.2: Optimizing GCC
3.5.3: Non-optimizing GCC
3.5.4: Role of the stack frame in this example
3.5.5: Optimizing GCC: load it into GDB
3.6: Conclusion
3.7: Exercises
Chapter 4: Function prologue and epilogue 
4.1: Recursion
Chapter 5: Stack
5.1: Why does the stack grow backwards?
5.2: What is the stack used for?
5.2.1: Save the function’s return address
5.2.2: Passing function arguments
5.2.3: Local variable storage
5.2.4: x86: alloca() function
5.2.5: (Windows) SEH
5.2.6: Buffer overflow protection
5.2.7: Automatic deallocation of data in stack
5.3: A typical stack layout
5.4: Noise in stack
5.4.1: MSVC 2013
5.5: Exercises
Chapter 6: printf() with several arguments
6.1: x86
6.1.1: x86: 3 arguments
6.1.2: x64: 8 arguments
6.2.1: ARM: 3 arguments
6.2.2: ARM: 8 arguments
6.3: MIPS
6.3.1: 3 arguments
6.3.2: 8 arguments
6.4: Conclusion
6.5: By the way
Chapter 7: scanf()
7.1: Simple example
7.1.1: About pointers
7.1.2: x86
7.1.3: MSVC + OllyDbg
7.1.4: x64
7.1.5: ARM
7.1.6: MIPS
7.2: Global variables
7.2.1: MSVC: x86
7.2.2: MSVC: x86 + OllyDbg
7.2.3: GCC: x86
7.2.4: MSVC: x64
7.2.5: ARM: Optimizing Keil 6/2013 (Thumb mode)
7.2.6: ARM64
7.2.7: MIPS
7.3: scanf() result checking
7.3.1: MSVC: x86
7.3.2: MSVC: x86: IDA
7.3.3: MSVC: x86 + OllyDbg
7.3.4: MSVC: x86 + Hiew
7.3.5: MSVC: x64
7.3.6: ARM
7.3.7: MIPS
7.3.8: Exercise
7.4: Exercise
Chapter 8: Accessing passed arguments
8.1: x86
8.1.1: MSVC
8.1.2: MSVC + OllyDbg
8.1.3: GCC
8.2: x64
8.2.1: MSVC
8.2.2: GCC
8.2.3: GCC: uint64_t instead of int
8.3: ARM
8.3.1: Non-optimizing Keil 6/2013 (ARM mode)
8.3.2: Optimizing Keil 6/2013 (ARM mode)
8.3.3: Optimizing Keil 6/2013 (Thumb mode)
8.3.4: ARM64
8.4: MIPS
Chapter 9: More about results returning 
9.1: Attempt to use the result of a function returning void
9.2: What if we do not use the function result?
9.3: Returning a structure
Chapter 10: Pointers 100
10.1: Global variables example
10.2: Local variables example
10.3: Conclusion
Chapter 11: GOTO operator
11.1: Dead code
11.2: Exercise
Chapter 12: Conditional jumps
12.1: Simple example
12.1.1: x86
12.1.2: ARM
12.1.3: MIPS
12.2: Calculating absolute value
12.2.1: Optimizing MSVC
12.2.2: Optimizing Keil 6/2013: Thumb mode
12.2.3: Optimizing Keil 6/2013: ARM mode
12.2.4: Non-optimizing GCC 4.9 (ARM64)
12.2.5: MIPS
12.2.6: Branchless version?
12.3: Ternary conditional operator
12.3.1: x86
12.3.2: ARM
12.3.3: ARM64
12.3.4: MIPS
12.3.5: Let’s rewrite it in an if/else way
12.3.6: Conclusion
12.4 Getting minimal and maximal values
12.4.1: 32-bit
12.4.2: 64-bit
12.4.3: MIPS
12.5: Conclusion
12.5.1: x86
12.5.2: ARM
12.5.3: MIPS
12.5.4: Branchless
12.6: Exercise
Chapter 13: switch()/case/default 
13.1: Small number of cases
13.1.1: x86
13.1.2: ARM: Optimizing Keil 6/2013 (ARM mode)
13.1.3: ARM: Optimizing Keil 6/2013 (Thumb mode)
13.1.4: ARM64: Non-optimizing GCC (Linaro) 4.9
13.1.5: ARM64: Optimizing GCC (Linaro) 4.9
13.1.6: MIPS
13.1.7: Conclusion
13.2 A: lot of cases
13.2.1: x86
13.2.2: ARM: Optimizing Keil 6/2013 (ARM mode)
13.2.3: ARM: Optimizing Keil 6/2013 (Thumb mode)
13.2.4: MIPS
13.2.5: Conclusion
13.3: When there are several case statements in one block
13.3.1: MSVC
13.3.2: GCC
13.3.3: ARM64: Optimizing GCC 4.9.1
13.4: Fall-through
13.4.1: MSVC x86
13.4.2: ARM64
13.5: Exercises
13.5.1: Exercise #1
Chapter 14: Loops
14.1 Simple example
14.1.1: x86
14.1.2: x86: OllyDbg
14.1.3: x86: tracer
14.1.4: ARM
14.1.5: MIPS
14.1.6: One more thing
14.2: Memory blocks copying routine
14.2.1: Straight-forward implementation
14.2.2: ARM in ARM mode
14.2.3: MIPS
14.2.4: Vectorization
14.3: Conclusion
14.4: Exercises
Chapter 15: Simple C-strings processing 
15.1: strlen()
15.1.1: x86
15.1.2: ARM
15.1.3: MIPS
Chapter 16: Replacing arithmetic instructions to other ones 
16.1: Multiplication
16.1.1: Multiplication using addition
16.1.2: Multiplication using shifting
16.1.3: Multiplication using shifting, subtracting, and adding
16.2: Division
16.2.1: Division using shifts
16.3: Exercise
Chapter 17: Floating-point unit
17.1: IEEE 754
17.2: x86
17.3: ARM, MIPS, x86/x64 SIMD
17.4: C/C++
17.5: Simple example
17.5.1: x86
17.5.2: ARM: Optimizing Xcode 4.6.3 (LLVM) (ARM mode)
17.5.3: ARM: Optimizing Keil 6/2013 (Thumb mode)
17.5.4: ARM64: Optimizing GCC (Linaro) 4.9
17.5.5: ARM64: Non-optimizing GCC (Linaro) 4.9
17.5.6: MIPS
17.6: Passing floating point numbers via arguments
17.6.1: x86
17.6.2: ARM + Non-optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode)
17.6.3: ARM + Non-optimizing Keil 6/2013 (ARM mode)
17.6.4: ARM64 + Optimizing GCC (Linaro) 4.9
17.6.5: MIPS
17.7: Comparison example
17.7.1: x86
17.7.2: ARM
17.7.3: ARM64
17.7.4: MIPS
17.8: Stack, calculators and reverse Polish notation
17.9: x64
17.10: Exercises
Chapter 18: Arrays
18.1: Simple example
18.1.1: x86
18.1.2: ARM
18.1.3: MIPS
18.2: Buffer overflow
18.2.1: Reading outside array bounds
18.2.2: Writing beyond array bounds
18.3: Buffer overflow protection methods
18.3.1: Optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode)
18.4: One more word about arrays
18.5: Array of pointers to strings
18.5.1: x64
18.5.2: 32-bit ARM
18.5.3: ARM64
18.5.4: MIPS
18.5.5: Array overflow
18.6: Multidimensional arrays
18.6.1: Two-dimensional array example
18.6.2: Access two-dimensional array as one-dimensional
18.6.3: Three-dimensional array example
18.6.4: More examples
18.7: Pack of strings as a two-dimensional array
18.7.1: 32-bit ARM
18.7.2: ARM64
18.7.3: MIPS
18.7.4: Conclusion
18.8: Conclusion
18.9: Exercises
Chapter 19: Manipulating specific bit(s) 
19.1: Specific bit checking
19.1.1: x86
19.1.2: ARM
19.2: Setting and clearing specific bits \
19.2.1: x86
19.2.2: ARM + Optimizing Keil 6/2013 (ARM mode)
19.2.3: ARM + Optimizing Keil 6/2013 (Thumb mode)
19.2.4: ARM + Optimizing Xcode 4.6.3 (LLVM) (ARM mode)
19.2.5: ARM: more about the BIC instruction
19.2.6: ARM64: Optimizing GCC (Linaro) 4.9
19.2.7: ARM64: Non-optimizing GCC (Linaro) 4.9
19.2.8: MIPS
19.3: Shifts
19.4: Setting and clearing specific bits: FPU5 example
19.4.1: A word about the XOR operation
19.4.2: x86
19.4.3: MIPS
19.4.4: ARM
19.5: Counting bits set to 1
19.5.1: x86
19.5.2: x64
19.5.3: ARM + Optimizing Xcode 4.6.3 (LLVM) (ARM mode)
19.5.4: ARM + Optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode)
19.5.5: ARM64 + Optimizing GCC 4.9
19.5.6: ARM64 + Non-optimizing GCC 4.9
19.5.7: MIPS
19.6: Conclusion
19.6.1: Check for specific bit (known at compile stage)
19.6.2: Check for specific bit (specified at runtime)
19.6.3: Set specific bit (known at compile stage)
19.6.4: Set specific bit (specified at runtime)
19.6.5: Clear specific bit (known at compile stage)
19.6.6: Clear specific bit (specified at runtime) \
19.7: Exercises
Chapter 20: Linear congruential generator 
20.1: x86
20.2: x64
20.3: 32-bit ARM
20.4: MIPS
20.4.1: MIPS relocations
20.5: Thread-safe version of the example
Chapter 21: Structures
21.1: MSVC: SYSTEMTIME example
21.1.1: OllyDbg
21.1.2: Replacing the structure with array
21.2: Let’s allocate space for a structure using malloc()
21.3: UNIX: struct tm
21.3.1: Linux
21.3.2: ARM
21.3.3: MIPS
21.3.4: Structure as a set of values
21.3.5: Structure as an array of 32-bit words
21.3.6: Structure as an array of bytes
21.4: Fields packing in structure
21.4.1: x86
21.4.2: ARM
21.4.3: MIPS
21.4.4: One more word
21.5: Nested structures
21.5.1: OllyDbg
21.6: Bit fields in a structure
21.6.: CPUID example
21.6.: Working with the float type as with a structure
21.7: Exercises
Chapter 22: Unions 
22.1: Pseudo-random number generator example
22.1.1: x86
22.1.2: MIPS
22.1.3: ARM (ARM mode)
22.2: Calculating machine epsilon
22.2.1: x86
22.2.2: ARM64
22.2.3: MIPS
22.2.4: Conclusion
22.3: Fast square root calculation
Chapter 23: Pointers to functions 
23.1: MSVC
23.1.1: MSVC + OllyDbg
23.1.2: MSVC + tracer
23.1.3: MSVC + tracer (code coverage)
23.2: GCC
23.2.1: GCC + GDB (with source code)
23.2.2: GCC + GDB (no source code)
Chapter 24: 64-bit values in 32-bit environment 
24.1: Returning of 64-bit value
24.1.1: x86
24.1.2: ARM
24.1.3: MIPS
24.2: Arguments passing, addition, subtraction
24.2.1: x86
24.2.2: ARM
24.2.3: MIPS
24.3: Multiplication, division
24.3.1: x86
24.3.2: ARM
24.3.3: MIPS
24.4: Shifting right
24.4.1: x86
24.4.2: ARM
24.4.3: MIPS
24.5: Converting 32-bit value into 64-bit one
24.5.1: x86
24.5.2: ARM
24.5.3: MIPS
Chapter 25: SIMD 
25.1: Vectorization
25.1.1: Addition example
25.1.2: Memory copy example
25.2: SIMD strlen() implementation
Chapter 26: 64 bits 
26.1: x86-64
26.2: ARM
26.3: Float point numbers
Chapter 27: Working with floating point numbers using SIMD 
27.1: Simple example
27.1.1: x64
27.1.2: x86
27.2: Passing floating point number via arguments
27.3: Comparison example
27.3.1: x64
27.3.2: x86
27.4: Calculating machine epsilon: x64 and SIMD
27.5: Pseudo-random number generator example revisited
27.6: Summary
Chapter 28: ARM-specific details 
28.1: Number sign (#) before number
28.2: Addressing modes
28.3: Loading a constant into a register
28.3.1: 32-bit ARM
28.3.2: ARM64
28.4: Relocs in ARM64
Chapter 29: MIPS-specific details 
29.1: Loading constants into register
29.2: Further reading about MIPS

Part II: Important fundamentals

Chapter 30: Signed number representations 
Chapter 31: Endianness 
31.1: Big-endian
31.2: Little-endian
31.3: Example
31.4: Bi-endian
31.5: Converting data
Chapter 32: Memory 
Chapter 33: CPU 
33.1: Branch predictors
33.2: Data dependencies
Chapter 34: Hash functions
34.1: How do one-way functions work?

Part III: Slightly more advanced examples

Chapter 35: Temperature converting 
35.1: Integer values
35.1.1: Optimizing MSVC 2012 x86
35.1.2: Optimizing MSVC 2012 x64
35.2: Floating-point values
Chapter 36: Fibonacci numbers
36.1: Example #1
36.2: Example #2
36.3: Summary
Chapter 37: CRC32 calculation example 
Chapter 38: Network address calculation example 
38.1: calc_network_address()
38.2: form_IP()
38.3: print_as_IP()
38.4: form_netmask() and set_bit()
38.5: Summary
Chapter 39: Loops: several iterators 
39.1: Three iterators
39.2: Two iterators
39.3: Intel C++ 2011 case
Chapter 40: Duff’s device 
Chapter 41: Division by 9
41.1: x86
41.2: ARM
41.2.1: Optimizing Xcode 4.6.3 (LLVM) (ARM mode)
41.2.2: Optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode)
41.2.3: Non-optimizing Xcode 4.6.3 (LLVM) and Keil 6/2013
41.3: MIPS
41.4: How it works
41.4.1: More theory
41.5: Getting the divisor
41.5.1: Variant #1
41.5.2: Variant #2
41.6: Exercise
Chapter 42: String to number conversion (atoi()) 
42.1: Simple example
42.1.1: Optimizing MSVC 2013 x64
42.1.2: Optimizing GCC 4.9.1 x64
42.1.3: Optimizing Keil 6/2013 (ARM mode)
42.1.4: Optimizing Keil 6/2013 (Thumb mode)
42.1.5: Optimizing GCC 4.9.1 ARM64
42.2: A slightly advanced example
42.2.1: Optimizing GCC 4.9.1 x64
42.2.2: Optimizing Keil 6/2013 (ARM mode)
42.3: Exercise
Chapter 43: Inline functions 
43.1: Strings and memory functions
43.1.1: strcmp()
43.1.2: strlen()
43.1.3: strcpy()
43.1.4: memset()
43.1.5: memcpy()
43.1.6: memcmp()
43.1.7: IDA script
Chapter 44: C99 restrict 
Chapter 45: Branchless abs() function 
45.1: Optimizing GCC 4.9.1 x64
45.2: Optimizing GCC 4.9 ARM64
Chapter 46: Variadic functions 
46.1: Computing arithmetic mean
46.1.1: cdecl calling conventions
46.1.2: Register-based calling conventions
46.2: vprintf() function case
Chapter 47: Strings trimming 
47.1: x64: Optimizing MSVC 2013
47.2: x64: Non-optimizing GCC 4.9.1
47.3: x64: Optimizing GCC 4.9.1 (Linaro) 4.9
47.5: ARM64: Optimizing GCC (Linaro) 4.9
47.6: ARM: Optimizing Keil 6/2013 (ARM mode)
47.7: ARM: Optimizing Keil 6/2013 (Thumb mode)
47.8: MIPS
Chapter 48: toupper() function 
48.1: x64
48.1.1: Two comparison operations
48.1.2: One comparison operation
48.2: ARM
48.2.1: GCC for ARM64
48.3: Summary
Chapter 49: Incorrectly disassembled code 
49.1: Disassembling from an incorrect start (x86)
49.2: How does random noise looks disassembled?
Chapter 50: Obfuscation 
50.1: Text strings
50.2: Executable code
50.2.1: Inserting garbage
50.2.2: Replacing instructions with bloated equivalents
50.2.3: Always executed/never executed code
50.2.4: Making a lot of mess
50.2.5: Using indirect pointers
50.3: Virtual machine / pseudo-code
50.4: Other things to mention
50.5: Exercise
Chapter 51: C++ 
51.1: Classes
51.1.1: A simple example
51.1.2: Class inheritance
51.1.3: Encapsulation
51.1.4: Multiple inheritance
51.1.5: Virtual methods
51.2: ostream
51.3: References
51.4: STL
51.4.1: std::string
51.4.2: std::list
51.4.3: std::vector
51.4.4: std::map and std::set
Chapter 52: Negative array indices 
Chapter 53: Windows 16-bit 
53.1: Example #1
53.2: Example #2
53.3: Example #3
53.4: Example #4
53.5: Example #5
53.6: Example #6
53.6.1: Global variables

Part IV: Java

Chapter 54: Java 
54.1: Introduction
54.2: Returning a value
54.3: Simple calculating functions
54.4: JVM6 memory model
54.5: Simple function calling
54.6: Calling beep()
54.7: Linear congruential PRNG7
54.8: Conditional jumps
54.9: Passing arguments
54.10: Bitfields
54.11: Loops
54.12: switch()
54.13: Arrays
54.13.1: Simple example
54.13.2: Summing elements of array
54.13.3: The only argument of the main() function is an array too
54.13.4: Pre-initialized array of strings
54.13.5: Variadic functions
54.13.6: Two-dimensional arrays
54.13.7: Three-dimensional arrays
54.13.8: Summary
54.14: Strings
54.14.1: First example
54.14.2: Second example
54.15: Exceptions
54.16: Classes
54.17: Simple patching
54.17.1: First example
54.17.2: Second example
54.18: Summary

Part V: Finding important/interesting stuff in the code 

Chapter 55: Identification of executable files 
55.1: Microsoft Visual C++
55.1.1: Name mangling
55.2: GCC
55.2.1: Name mangling
55.2.2: Cygwin
55.2.3: MinGW
55.3: Intel FORTRAN
55.4: Watcom, OpenWatcom
55.4.1: Name mangling
55.5: Borland
55.5.1: Delphi
55.6: Other known DLLs
Chapter 56: Communication with the outer world (win32) 
56.1: Often used functions in the Windows API
56.2: tracer: Intercepting all functions in specific module
Chapter 57: Strings
57.1: Text strings
57.1.1: C/C++
57.1.2: Borland Delphi
57.1.3: Unicode
57.1.4: Base64
57.2: Error/debug messages
57.3: Suspicious magic strings
Chapter 58: Calls to assert() 
Chapter 59: Constants 
59.1: Magic numbers
59.1.1: Dates
59.1.2: DHCP
59.2: Searching for constants
Chapter 60: Finding the right instructions 
Chapter 61: Suspicious code patterns 
61.1: XOR instructions
61.2: Hand-written assembly code
Chapter 62: Using magic numbers while tracing 
Chapter 63: Other things 
63.1: General idea
63.2: C++
63.3: Some binary file patterns
63.4: Memory “snapshots” comparing
63.4.1: Windows registry
63.4.2: Blink-comparator

Part VI: OS-specific

Chapter 64: Arguments passing methods (calling conventions) 
64.1: cdecl
64.2: stdcall
64.2.1: Functions with variable number of arguments
64.3: fastcall
64.3.1: GCC regparm
64.3.2: Watcom/OpenWatcom
64.4: thiscall
64.5: x86-64
64.5.1: Windows x64
64.5.2: Linux x64
64.6: Return values of float and double type
64.7: Modifying arguments
64.8: Taking a pointer to function argument
Chapter 65: Thread Local Storage 
65.1: Linear congruential generator revisited
65.1.1: Win32
65.1.2: Linux
Chapter 66: System calls (syscall-s) 
66.1: Linux
66.2: Windows
Chapter 67: Linux 
67.1: Position-independent code
67.1.1: Windows
67.2: LD_PRELOAD hack in Linux
Chapter 68: Windows NT 
68.1: CRT (win32)
68.2: Win32 PE
68.2.1: Terminology
68.2.2: Base address
68.2.3: Subsystem
68.2.4: OS version
68.2.5: Sections
68.2.6: Relocations (relocs)
68.2.7: Exports and imports
68.2.8: Resources
68.2.9: .NET
68.2.10: TLS
68.2.11: Tools
68.2.12: Further reading
68.3: Windows SEH
68.3.1: Let’s forget about MSVC
68.3.2: Now let’s get back to MSVC
68.3.3: Windows x64
68.3.4: Read more about SEH ion

Part VII: Tools

Chapter 69: Disassembler 
69.1: IDA
Chapter 70: Debugger 
70.1: OllyDbg
70.2: GDB
70.3: tracer
Chapter 71: System calls tracing 
71.1: strace / dtruss
Chapter 72: Decompilers 
Chapter 73: Other tools 

Part VIII: Examples of real-world RE tasks

Chapter 74: Task manager practical joke (Windows Vista) 
74.1: Using LEA to load values
Chapter 75: Color Lines game practical joke 
Chapter 76: Minesweeper (Windows XP) 
76.1: Exercises
Chapter 77: Hand decompiling + Z3 SMT solver 
77.1: Hand decompiling
77.2: Now let’s use the Z3 SMT solver
Chapter 78: Dongles 
78.1: Example #1: MacOS Classic and PowerPC
78.2: Example #2: SCO OpenServer
78.2.1: Decrypting error messages
78.3: Example #3: MS-DOS
Chapter 79: “QR9”: Rubik’s cube inspired amateur crypto-algorithm 
Chapter 80: SAP 
80.1: About SAP client network traffic compression
80.2: SAP 6.0 password checking functions
Chapter 81: Oracle RDBMS 
81.1: V$VERSION table in the Oracle RDBMS
81.2: X$KSMLRU table in Oracle RDBMS
81.3: V$TIMER table in Oracle RDBMS
Chapter 82: Handwritten assembly code 
82.1: EICAR test file
Chapter 83: Demos 
83.1: 10 PRINT CHR$(205.5+RND(1)); : GOTO 10
83.1.1: Trixter’s 42 byte version
83.1.2: My attempt to reduce Trixter’s version: 27 bytes
83.1.3: Taking random memory garbage as a source of randomness
83.1.4: Conclusion
83.2: Mandelbrot set
83.2.1: Theory
83.2.2: Let’s get back to the demo
83.2.3: My “fixed” version

Part IX: Examples of reversing proprietary file formats 

Chapter 84: Primitive XOR-encryption 
84.1: Norton Guide: simplest possible 1-byte XOR encryption
84.1.1: Entropy
84.2: Simplest possible 4-byte XOR encryption
84.2.1: Exercise
Chapter 85: Millenium game save file 
Chapter 86: Oracle RDBMS: .SYM-files 
Chapter 87: Oracle RDBMS: .MSB-files 
87.1: Summary 

Part X: Other things 

Chapter 88: npad 
Chapter 89: Executable files patching 
89.1: Text strings
89.2: x86 code
Chapter 90: Compiler intrinsic 
Chapter 91: Compiler’s anomalies 
Chapter 92: OpenMP
92.1: MSVC
92.2: GCC
Chapter 93: Itanium 
Chapter 94: 8086 memory model 
Chapter 95: Basic blocks reordering 
95.1: Profile-guided optimization

Part XI: Books/blogs worth reading 

Chapter 96: Books 
96.1: Windows
96.2: C/C++
96.3: x86 / x86-64
96.4: ARM
96.5: Cryptography
Chapter 97: Blogs
97.1: Windows
Chapter 98: Other 
Chapter 99: Questions? 
Appendix 
Acronyms used