I'm suspicious of the effectiveness. Most people are doing symbolic execution to find bad pointer dereferences as bugs, whereas this tool is doing it to build the least constrained model <i>and</i> then checking the code against that same model. Wouldn't any code paths that are discovered as part of symbolic exploration and have out-of-bounds read/writes then be infered away as constraints, instead of bugs? Or being unable to detect memory corruption in the form of controlled pointer value overwrites, since you can't say that all pointer dereferences derived from your symbolic input are bugs that allow for attacked controlled memory corruption, because you don't have a concept of what inputs are under user control unlike most uses of Angr or other symbolic tainting tools. Is there a better list of the types of bug classes or heuristics that this is able to catch? Are there any numbers on the false positive/false negative rates against a dataset?
I’d built an AI agent to accomplish this using Ghidra + GDB for dynamic analysis (tested it on crackmes)<p>It worked surprisingly well<p>Applied to YC with it, sadly no interview<p>Was later told by some accepted friends/VCs that our application was good, but without pedigree we needed traction to de-risk / get accepted :(
>"How it works<p>Fundamentally, GREASE works quite similarly to UC-Crux, our tool for under-constrained symbolic execution of LLVM.<p><i>Essentially, GREASE analyzes each function in the target binary by running it on a slate of fully symbolic registers.</i><p>When errors occur (for example, if the program reads from uninitialized memory), GREASE uses heuristics to refine this initial symbolic precondition (e.g., by initializing some memory) and re-runs the target function. This process continues until GREASE finds a bug, or concludes that the function is safe under some reasonable precondition on its inputs. The blog post introducing UC-Crux [<a href="https://www.galois.com/articles/under-constrained-symbolic-execution-with-crucible" rel="nofollow">https://www.galois.com/articles/under-constrained-symbolic-e...</a>] describes this algorithm in considerable detail."<p>Fascinating!<p>It's almost like the ability to run a given function inside of its own Virtual Machine / Virtual Environment and setting parameters/constraints for execution, that is, defining pre-conditions and post-conditions which determine successful (defined) or unsuccessful (undefined) behaviors!<p>Let me speculate that future programming languages -- might have abilities like this by default, that is, implicitly baked into them...<p>In short, I like the set of ideas espoused by this tool, and future compiler/language writers would do well to consider them when they write their future compilers/languages...<p>(Phrased another way, it would be like the ability to run any function of a program inside of its own custom Bochs [<a href="https://bochs.sourceforge.io/" rel="nofollow">https://bochs.sourceforge.io/</a>] environment, set pre and post constraints, run/test as many of these as needed, and return back to main program/environment reporting any constraint violations... or something like that...)<p>Anyway, an interesting set of ideas!