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
angrruns 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,
angr‘s python port ofValgrind‘ Intermediate Representation. This was before I knew aboutpolytrackerand 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 clickand askangrto find bugs for us. So I made this extension (at least, theangrintegration 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
angrclasses would necessarily be used in projects that solved the same problems I intended to solve (angr.analyses.VariableRecovery) for instance.
I found these:
- ioctlance
- Arcus
- C3PO
- SEMA toolchain (malware analysis with
angr)
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
cmakefrom 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 angr‘s exploration (or undocument shortcoming if you want to call it like that).