So I though it would be a nice pet-project so I've started building a PoC tool that can generate a CFG for a given method in the .NET assembly.
The PoC uses Mono.Cecil
to inspect the binary and produces a graph in a DOT language than later can be transformed into a picture with dot
tool and works on IL level.
A bit of technical info.
First it determines leaders - instructions that will be the first instruction in the basic blocks (BB) - by going through the opcodes and checking the control flow type:
- If the instruction's control flow type is of type
Return
- the next one (if exists) will be a leader.
- If the instruction's control flow type is of type
Branch
- the destination of the branch instruction will be a leader
- If the instruction's control flow type is of type
Cond_Branch
- the destination of the branch and the next instruction will be leaders.
Also doing that we can construct edges between those BBs, there will be different outgoing edges depending on the type of flow:
- If the instruction's control flow type is of type
Return
there will be no outgoing edge
- If the instruction's control flow type is of type
Branch
there will be an outgoing edge from the current instruction's BB to the branch's destination BB
- If the instruction's control flow type is of type
Cond_Branch
there will be outgoing edges from the current BB to the destination of the Cond_Branch
BB and to the next instruction's BB
The only thing we need to do having those info, is to generate a graph definition in the DOT langage.
Calling the tool in the following way
./cfg.exe Mono.Cecil.dll Mono.Cecil.MetadataBuilder.AddCustomDebugInformations | dot -Tpng -o cfg.png
will generate for us a "nice" CFG for the method AddCustomDebugInformations
.

It might fail for some strange (or normal) edge cases and of course there's a lot to improve but overall CFG is there ;)
Link to the repo: https://github.com/pawlos/cfg