Using angr in 2024

Introduction

My first article on this personal blog was about angr, and was supposed to be part of a series. As evident from the lack of additional articles, I in fact gave up, for the reasons below:

  • No good enough hardware to handle the resources required by angr
  • Unfamiliarity with the framework and unwillingness to jump into its (rather large) codebase
  • angr runs for a long time and consumes all my resources, and I don’t (didn’t) know why.
  • Few people around me shared my interest for it.
  • Other priorities in my personal life

But now, things have changed and I feel I’m ready to take another stab at it! In fact, I’ve spent the last few weeks experimenting with it:

  • I needed to track which byte in a file ended up being used at specific locations in a software. So naturally I didn’t properly scout the existing tools and made one built on top of pyvex, angrs python port of Valgrind Intermediate Representation. This was before I knew about polytracker and also before I realized I didn’t really needed that. Too bad, I wrote 2,000 lines of code for that haha.
  • Discussing with a colleague, we shared our need for an IDA extension where we could right click and ask angr to find bugs for us. So I made this extension (at least, the angr integration part).
  • This time, I decided to stop reinventing the wheel and properly investigate the state-of-the-art (SOTA) approaches. While I initially relied on Google searches, the most fruitful method turned out to be exploring GitHub repositories. Specifically, I searched for projects with specific keywords (using the code search feature). The idea is that specific angr classes would necessarily be used in projects that solved the same problems I intended to solve (angr.analyses.VariableRecovery) for instance.

I found these:

I read their papers and source code. I found this file (disabled/int_overflow.py) in Arcus that piqued my interest: could I copy-paste a ready to use integer overflow sanitizer?

So I made a basic vulnerable program in C, built it, created a basic angr skeleton, and plugged in int_overflow.py. It didn’t work.

My motivation didn’t waver for mysterious reasons; in fact, I felt even more driven to debug it. What do I do whenever I’m pushed towards solving something I seriously lack skills for? I minify it and add back some features, first copy-pasting from the examples, and repeatedly doing this until my understanding levels up.

This usually snowballs quite rapidly because, by doing this, I get ideas, I test them, this constrains the horizon of possibilities further, and then solutions become more obvious. I implement them until I become rather fluent with it.

Tout voyage tend vers une fin, mais à la fin, c’est le voyage qui compte. - Antoine de Saint-Exupéry

I’m glad to say this happened with angr (although I will probably never fully master it; angr is huge, and my love for Program Analysis stops at math-heavy papers).

This also means… I’m sharing my discoveries in this article in the hope of helping or inspiring others.

Installing angr on macOS Apple Silicon in 2024

To be honest, I had a terrible experience installing it in 2020, and hoped it would be different. It was not.

Here are my notes to successfully install it:

  • Download cmake from the official website and install, then
sudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install=/usr/local/bin
brew install pkg-config 
  • Create a virtual environment if you want
  • pip install angr

This should work. If not, good luck, if yes, then you’re ready for the really painful part. By default, the capstone dependency ships with the wrong architecture. So we’ll need to build it ourselves, and also fix bugs, because why would it be otherwise.

3130  git clone https://github.com/capstone-engine/capstone
3131  l
3132  cd capstone
3133  l
3134  make
3135  brew install llvm
3136  export LDFLAGS="-L/opt/homebrew/opt/llvm/lib"\n

3139  make
3140  cd bindings
3143  cd python
3144  sudo make install
3148  python3 setup.py install
3149  pip uninstall capstone

Above is the sequence of commands I had to execute. In short, we’re cloning capstone, installing llvm (used to build capstone), configuring the linker because otherwise capstone complains about it, then build the python bindings, and then apparently uninstalling capstone (installed as dependency while installing angr) is enough for our freshly built version to be found.

Buuuut this is not over. By doing this, we installed a too recent version of capstone. Of course, they made breaking changes: they replaced CS_ARCH_ARM64 with CS_ARCH_AARCH64 if you care.

error: module 'capstone' has no attribute "'CS_ARCH_ARM64'"

Just open .venv/lib/python3.9/site-packages/archinfo/arch_aarch64.py and fix it at line 47:

    if _capstone:
        cs_arch = _capstone.CS_ARCH_ARM64

And now:

python3
>>> import angr
>>> 

It works!

To be continued

In the next article, I’m sharing tips and tricks to make angr faster and actually understand what it’s doing. I will be sharing code snippets that actually helped me find a bug in angrs exploration (or undocument shortcoming if you want to call it like that).