So I'm trying to write a reversing tool right now and trying to make a CALL graph

the problem I'm having is some calls are like Call *eax instead Call 'address'

I can easily generate the call-graph with absolute calls, but not with these

so i have three questions :

  1. what type of functions get called using register instead of absolute? i want to only generate call graph for functions inside the main program and not libraries and etc, do i need to worry about register calls or these are only used for special functions? if so, why? ( even if these are only for library functions i dont get why can't they be converted into absolute address during relocation??)

  2. if i wanted to check what is the function that is being called aka by reading the register, is this possible using static analysis or i have to do dynamic analysis?

  3. can i make a decent call-graph using static analysis, meaning by only reading the binary? do popular tools like IDA use static to generate call graph as well? or will i face real problems if i do so?

1 Answer 1

  1. In C++, the pointer of the method associated with an object are stored in something called a vtable. In order to call a specific method, you need to get a pointer to that vtable and get to the proper function. In the end, your going to end with a "call eax", even though the function call is not from an external library.

  2. Well, it really depends on your case. You can use techniques such as symbolic execution in order to resolve the jump destination. The idea of this technique is to associate a "symbolic value" (i.e. a variable) to the registers and compute the equation generated by the assembly. Then you can solve your equation to get the final value of the register you are looking for.

    This works pretty well with simple equations, but if your code is obfuscated (meaning that the code is voluntarily complex), you might not be able to solve the equation and find the call destination without a dynamic analysis. (Which, by the way, might also not give you the call destination if, for example, you don't find an execution path execution the "call eax").

  3. In IDA, the call graph is generated by performing a static analysis. However, IDA does not resolve dynamic call if the jump are more complicated than "loc_addr + offset". It's a "safe" choice, because you might end up doing really complicated operation if your code is obfuscated. What tools usually do, is find a heuristic: it's a technique that does not work for every problem, but it works in some cases (just like the IDA solution).

  • So even IDA cannot include call *eax in their call graph therefore making it not a complete call-graph? and is this a common thing to happen inside the program and not in the initialization routines? meaning will i miss important calls if i dont include call *register inside my call graph?
    – Max
    Commented Apr 15, 2019 at 12:54
  • IDA does not resolve all of them, only some of them. It is common if you have a C++ code handling objects and calling methods on this object.
    – Caroline
    Commented Apr 15, 2019 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.