1Introduction
- 1.1Handbook structure
2What we will need
- 2.1System requirements
- 2.2Software requirements
- 2.3Programming language requirements
3Binary instrumentation and Frida
- 3.1Application and code-level instrumentation
- 3.2Frida: a binary instrumentation toolkit
- Supported architectures and systems
- 3.3Instrumentation tool structure under Frida
- 3.4Frida architecture basics
- Projects using Frida
4Frida usage basics
- 4.1JavaScript vs TypeScript
- 4.2An overview of Frida API
- 4.3Main features
- 4.3.1Stalker: a code tracing engine
- 4.3.2Hooks and the Interceptor API
- 4.4frida-tools
- 4.4.1Frida command line interface
- Runtimes in Frida
- 4.4.2frida-trace
5Dealing with data types with Frida
- 5.1Dealing with strings: Reading and allocation
- 5.1.1Practical use case: Reading a WinAPI UTF16 string parameter
- 5.2Numbers
- 5.2.1Numerical arguments passed by value.
- 5.2.2Numerical values by reference
- 5.2.3Writing numbers
- 5.3Pointers
- About NativePointers
- 5.4Pointer to offsets
- Finding process’s modules
- 5.5Getting pointers to exports
- 5.5.1findExportByName vs getExportByName
- 5.6Pointer to ArrayBuffers
- Size of pointers
- 5.7Hexdump: getting a picture from a memory region
- 5.8Writing our first agent.
- 5.8.1Writing the control script
- 5.9Injecting our scripts using Frida’s command line
- 5.10Remote instrumentation
- The Frida CodeShare repository
6Intermediate usage
- 6.1Defining globals in Frida’s REPL
- 6.2Following child processes
- 6.3Creating NativeFunctions
- 6.3.1Using NativeFunction to call system APIs
- 6.4Modifying return values
- 6.5Access values after usage
- 6.6CryptDecrypt: A practical case.
- 6.7Modifying values before execution
- 6.8Undoing instrumentation
- 6.9std::string
- 6.9.1std::vector in MSVC
- 6.10Operating with ArrayBuffers
7Advanced usage
- 7.1NOP functions
- 7.1.1Using the replace API
- 7.1.2Patching memory
- 7.2Memory scanning
- 7.2.1Reacting on memory patterns
- 7.3Using custom libraries (DLL/.so)
- 7.3.1Creating a custom DLL
- 7.3.2Using our custom library
- 7.4Reading and writing registers
- 7.5Reading structs
- 7.5.1Reading from a user-controlled struct.
- 7.6SYSCALL struct
- 7.7WINAPI struct.
- 7.8Tips for calculating structure offsets
- 7.9CModule
- 7.9.1CModule: A practical use case
- 7.9.2CModule: Reading return values
- 7.9.3CModule vs JavaScript agent performance
- 7.9.4CModule: Sharing state between JS and C
- 7.10Sharing state between two CModule objects
- 7.10.1Notifying from C code
- 7.11CModule boilerplates
- 7.12Stalker
- 7.12.1Getting a thread id
- 7.12.2Stalker: Tracing from a known function call
- 7.12.3Tracing instructions
- 7.12.4Getting RET addresses
8MacOS
- 8.1ObjC
- 8.2Intercepting NSURL InitWithString
- 8.3Obj-C: Intercepting fileExistsAtPath
- 8.4ObjC: Methods with multiple arguments.
- 8.5ObjC: Reading a CFDataRef
- 8.6Getting CryptoKit’s AES.GCM.seal data before encryption
- 8.7Swift.String
9Android instrumentation
- 9.1Setting up the environment
- 9.1.1Android emulator
- 9.1.2frida-server
- 9.1.3Java API
- 9.2Java.perform() API
- 9.2.1Instrumenting Android applications
- 9.2.2Reading values
- 9.2.3Replacing return values
- 9.2.4Replacing arguments
- 9.2.5Instrumenting constructors
- 9.2.6Bytearray values
- 9.3Method overloads
- 9.3.1Stacktraces
- 9.4Frida detection mechanisms
- 9.4.1/data/local/tmp/frida-server
- 9.4.2/proc/self/maps
10r2frida
- r2frida commands
- 10.0.1Testing r2frida
- Attaching to running processes
- 10.1Tracing functions
- 10.1.1Tracing functions from imports/exports
- 10.1.2Tracing functions by using offsets
- 10.2Disassembling functions in memory
- 10.3Replace return values
- 10.4Replacing return values (hijacking)
- 10.5Allocating strings
- 10.6Calling functions
11Optimizing our Frida setup
- 11.1Building an optimized Frida agent
12A real-world use case: Building an anti-cheat with Frida
- 12.1Background
- 12.2Anti-cheat Requirements
- 12.2.1Timenudge
- 12.3Quick environment setup
- 12.4Anti-cheat architecture
- 12.5Extending the banlist
- 12.5.1Monitoring userinfo changes
- 12.5.2Predicting timenudge values
- 12.6Optimizing G_RunFrame calls
- 12.6.1Persistence across map changes
- 12.6.2Conclusions