🚩
Practical CTF
BlogContact
  • 🚩Home - Practical CTF
  • 🌐Web
    • Enumeration
      • Finding Hosts & Domains
      • Masscan
      • Nmap
      • OSINT
    • Client-Side
      • Cross-Site Scripting (XSS)
        • HTML Injection
        • Content-Security-Policy (CSP)
      • CSS Injection
      • Cross-Site Request Forgery (CSRF)
      • XS-Leaks
      • Window Popup Tricks
      • Header / CRLF Injection
      • WebSockets
      • Caching
    • Server-Side
      • SQL Injection
      • NoSQL Injection
      • GraphQL
      • XML External Entities (XXE)
      • HTTP Request Smuggling
      • Local File Disclosure
      • Arbitrary File Write
      • Reverse Proxies
    • Frameworks
      • Flask
      • Ruby on Rails
      • NodeJS
      • Bun
      • WordPress
      • Angular
    • Chrome Remote DevTools
    • ImageMagick
  • 🔣Cryptography
    • Encodings
    • Ciphers
    • Custom Ciphers
      • Z3 Solver
    • XOR
    • Asymmetric Encryption
      • RSA
      • Diffie-Hellman
      • PGP / GPG
    • AES
    • Hashing
      • Cracking Hashes
      • Cracking Signatures
    • Pseudo-Random Number Generators (PRNG)
    • Timing Attacks
    • Blockchain
      • Smart Contracts
      • Bitcoin addresses
  • 🔎Forensics
    • Wireshark
    • File Formats
    • Archives
    • Memory Dumps (Volatility)
    • VBA Macros
    • Grep
    • Git
    • File Recovery
  • ⚙️Reverse Engineering
    • Ghidra
    • Angr Solver
    • Reversing C# - .NET / Unity
    • PowerShell
  • 📟Binary Exploitation
    • ir0nstone's Binary Exploitation Notes
    • Reverse Engineering for Pwn
    • PwnTools
    • ret2win
    • ret2libc
    • Shellcode
    • Stack Canaries
    • Return-Oriented Programming (ROP)
      • SigReturn-Oriented Programming (SROP)
      • ret2dlresolve
    • Sandboxes (chroot, seccomp & namespaces)
    • Race Conditions
  • 📲Mobile
    • Setup
    • Reversing APKs
    • Patching APKs
    • HTTP(S) Proxy for Android
    • Android Backup
    • Compiling C for Android
    • iOS
  • 🌎Languages
    • PHP
    • Python
    • JavaScript
      • Prototype Pollution
      • postMessage Exploitation
    • Java
    • C#
    • Assembly
    • Markdown
    • LaTeX
    • JSON
    • YAML
    • CodeQL
    • NASL (Nessus Plugins)
    • Regular Expressions (RegEx)
  • 🤖Networking
    • Modbus - TCP/502
    • Redis/Valkey - TCP/6379
  • 🐧Linux
    • Shells
    • Bash
    • Linux Privilege Escalation
      • Enumeration
      • Networking
      • Command Triggers
      • Command Exploitation
      • Outdated Versions
      • Network File Sharing (NFS)
      • Docker
      • Filesystem Permissions
    • Analyzing Processes
  • 🪟Windows
    • The Hacker Recipes - AD
    • Scanning/Spraying
    • Exploitation
    • Local Enumeration
    • Local Privilege Escalation
    • Windows Authentication
      • Kerberos
      • NTLM
    • Lateral Movement
    • Active Directory Privilege Escalation
    • Persistence
    • Antivirus Evasion
    • Metasploit
    • Alternate Data Streams (ADS)
  • ☁️Cloud
    • Kubernetes
    • Microsoft Azure
  • ❔Other
    • Business Logic Errors
    • Password Managers
    • ANSI Escape Codes
    • WSL Tips
Powered by GitBook
On this page
  • Template
  • Examples
  1. Reverse Engineering

Angr Solver

A binary analysis tool in Python to automatically find paths to code

PreviousGhidraNextReversing C# - .NET / Unity

Last updated 1 year ago

is really useful for quickly solving some Reverse Engineering challenges. The most useful function allows you to define an address in a Linux binary, and it will run the binary with different inputs to slowly make progress toward that goal.

For a CTF challenge, you could point the goal to be after some if statements that you would otherwise have to reverse engineer. Then Angr will find a valid input that gets to the code after the if statements, solving the challenge for you.

Template

import angr

# Change this binary
project = angr.Project("./binary", auto_load_libs=False)

@project.hook(0x401337)  # Change this address to your target
def print_flag(state):
    print("Valid input:", state.posix.dumps(0))
    project.terminate_execution()

project.execute()

Examples

When you can and can't use Angr is something you just need to get a feel for, by trying it sometimes and seeing if it works. In most cases, you're looking for some check on an input you're giving, and finding how to get past that if statement is a tedious process. Here are some examples of decompiled code where Angr could be used:

Example 1
undefined8 main(void) {
  uint uVar1;
  int local_10;
  int local_c;
  
  printf("Enter the flag: ");
  __isoc99_scanf(&DAT_00102015,buf);
  for (local_c = 0; local_c < 0x1d; local_c = local_c + 1) {
    uVar1 = (uint)(local_c >> 0x1f) >> 0x1e;
    buf[local_c] = buf[local_c] ^
                   *(byte *)((long)&magic + (long)(int)((local_c + uVar1 & 3) - uVar1));
  }
  local_10 = 0;
  while( true ) {
    if (0x1c < local_10) {  // Hard if statement (computation in the for() loop above)
      puts("Correct flag!");
      // <--- TARGET Angr right here
      // Ghidra shows 0x00101231, and starts by default at 0x00100000, meaning
      // we're only 0x1231 into the binary. When Angr runs a program with PIE enabled,
      // it starts at 0x00400000. So the final address we target is 0x00401231
      return 0;
    }
    if (buf[local_10] != flag[local_10]) break;
    local_10 = local_10 + 1;
  }
  puts("Wrong flag!");
  return 0;
}
Example 2
undefined8 validatePassword(byte *param_1) {
  size_t sVar1;
  undefined8 uVar2;
  
  sVar1 = strlen((char *)param_1);
  // Hard if statement:
  if ((((((sVar1 == 0x21) && (*param_1 == (byte)(param_1[6] * '\x02' - 0x1d))) &&
        (param_1[1] == (byte)(param_1[0x13] + 5))) &&
       (((param_1[2] == (byte)(((char)param_1[8] >> 1) + 0x13U) &&
         (param_1[3] == (byte)(param_1[0xf] + 0x35))) &&
        ((param_1[4] == (byte)(param_1[3] + 0xbc) &&
         ((param_1[5] == (byte)(param_1[0x11] + 0x28) && (param_1[6] == (char)param_1[0x16] >> 1))))
        )))) && (param_1[7] == (param_1[0xb] ^ param_1[0x15]))) &&
     (((((((param_1[8] == (param_1[5] ^ 7) && (param_1[9] == (byte)(param_1[0xe] - 0x21))) &&
          (param_1[10] == (byte)(param_1[0x1e] + 7))) &&
         ((param_1[0xb] == (byte)(param_1[0x10] * '\x02') &&
          (param_1[0xc] == (byte)(param_1[0x1d] + param_1[9]))))) && (param_1[0xd] == 0x31)) &&
       ((((param_1[0xe] == (byte)(param_1[0x1d] * '\x02' + 3) && (param_1[0xf] == (*param_1 ^ 5)))
         && (((param_1[0x10] == (byte)(((char)param_1[0x12] >> 1) * '\x02') &&
              (((param_1[0x11] == (param_1[0x14] ^ 0x40) && (param_1[0x12] == (param_1[0x17] ^ 10)))
               && (param_1[0x13] == (byte)(param_1[7] - 2))))) &&
             (((param_1[0x14] == (param_1[10] ^ param_1[0x1c]) &&
               (param_1[0x15] == (char)param_1[0x19] >> 1)) &&
              (param_1[0x16] == (byte)((param_1[0x1f] | 0x61) - 2))))))) &&
        ((param_1[0x17] == 0x39 && (param_1[0x18] == (byte)(param_1[0x12] * '\x02'))))))) &&
      (((param_1[0x19] == (byte)(param_1[0x10] + param_1[0x1a]) &&
        (((param_1[0x1a] == (byte)((char)param_1[0xb] / '\x02' + 7U) &&
          (param_1[0x1b] == (byte)((param_1[4] + 0x7b) * '\x02'))) &&
         (param_1[0x1c] == (byte)(param_1[1] - 0x13))))) &&
       (((param_1[0x1d] == (byte)(param_1[0x20] + 0xb3) &&
         (param_1[0x1e] == (byte)(param_1[0x1f] - param_1[0x10]))) &&
        ((param_1[0x1f] == (byte)(param_1[0xd] * '\x02' + 1) &&
         (param_1[0x20] == (byte)(param_1[4] + param_1[0xf]))))))))))) {
    uVar2 = 1;  // <--- TARGET Angr here, right after the if statement when
                // validatePassword() returns 1
  }
  else {
    uVar2 = 0;
  }
  return uVar2;
}

One more writeup of a reversing challenge that was easily solved using Angr:

This template lets Angr do the magic to solve it automatically without much effort, but for more advanced examples see .

⚙️
their documentation
Angr
Material :: flagbotMaterial
A presentation about Z3 and Angr that shows practical code
Cave System (Writeup) - Cyber Apocalypse 2023 | Jorian Woltjerjorianwoltjer.com
Logo
2KB
solve_with_angr.py
Another example of the challenge solved with Angr
CrackThePassword
Logo