Description
I don't know that if your goal is covering all kind of mc-level tricks, but there's a case that breaks CFG generation due to the _determine_function_returning algorithm.
Considering this function:
a: call a + 5 ; instr.len == 5
a + 5: pop rax
a + 6: ret
(its shellcode: b"\xE8\x00\x00\x00\x00\x58\xC3")
It marks this function as 'non-returning', but indeed, it's not. It ends up that the generated CFG is not complete.
i.e (previous function stub is called A):
... beginning of block, containing irrelevant instructions ...
call A
... rest of block, containing important instructions ...
In this case the 'important instructions' are not going to be represented in control flow graph, but irrelevants.
CFGEmulated analysis also utilizes this function to obtain function's return state, I think this property can be dynamically computed by symbolic execution on CFGEmulated; by checking return address is equal to qword ptr [rsp] value and is constant.
Steps to reproduce the bug
No response
Environment
No response
Additional context
No response
Description
I don't know that if your goal is covering all kind of mc-level tricks, but there's a case that breaks CFG generation due to the _determine_function_returning algorithm.
Considering this function:
(its shellcode:
b"\xE8\x00\x00\x00\x00\x58\xC3")It marks this function as 'non-returning', but indeed, it's not. It ends up that the generated CFG is not complete.
i.e (previous function stub is called A):
In this case the 'important instructions' are not going to be represented in control flow graph, but irrelevants.
CFGEmulated analysis also utilizes this function to obtain function's return state, I think this property can be dynamically computed by symbolic execution on CFGEmulated; by checking return address is equal to qword ptr [rsp] value and is constant.
Steps to reproduce the bug
No response
Environment
No response
Additional context
No response