[IDAPython] Generating nice callgraphs.
source link: https://yurichev.com/news/20191208_callgraphs/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
As a reverse engineer, you stumble too often in such a problem: a program open/read/close file. And you can easily find functions like CreateFileA(), ReadFile(), etc. But they are buried deep somewhere at the lowest level.
You can render a whole callgraph, but it's usually huge and bulky.
Wouldn't it be cool to see what paths can lead to CreateFileA(), ReadFile(), etc, but only for these couple of functions? Can we limit (or cut) a callgraph?
This is what I did, I wrote an IDAPython plugin that finds all paths for a given functions and renders a (partial) callgraph.
N.B.: all files used here are from Windows 7.
Notepad
Let's take Notepad. What paths can lead to file functions?
NPWndProc -> doDrop -> KERNEL32.dll!CreateFileW NPWndProc -> doDrop -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> doDrop -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> NPCommand -> KERNEL32.dll!CreateFileW NPWndProc -> NPCommand -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> NPCommand -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> NPCommand -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NPWndProc -> NPCommand -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW NpOpenDialogHookProc -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> ProcessSetupOption -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> ProcessSetupOption -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> ProcessShellOptions -> KERNEL32.dll!CreateFileW WinMainCRTStartup -> sub_100003AE4 -> WinMain -> NPInit -> ProcessShellOptions -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!CreateFileW CFileDialogEvents_OnSelectionChange -> UpdateEncoding -> KERNEL32.dll!CreateFileW NPWndProc -> doDrop -> LoadFile -> New -> CheckSave -> SaveFile -> AnsiWriteFile -> KERNEL32.dll!WriteFile NPWndProc -> doDrop -> LoadFile -> New -> CheckSave -> SaveFile -> KERNEL32.dll!WriteFile NPWndProc -> doDrop -> CheckSave -> SaveFile -> AnsiWriteFile -> KERNEL32.dll!WriteFile ...
Full list:here.
Isn't it cool? Of course, you can grep the list of all paths. Want to find a path through func1 and func2? Do: grep func1 | grep func2 .
And now let's render this (partial or sliced) callgraph using GraphViz:click here.
dhcpcore.dll
It can send and receive from network using WS2_32.DLL, but can we see top-level functions?
RpcSrvMadcapRenewAddress -> RenewAddress -> RenewMadcapAddress -> GetSpecifiedMadcapMessage -> WS2_32.dll!__imp_recvfrom RpcSrvCheckServerAvailability -> CheckV4ServerAvailability -> WaitForOfferForDiagnostics -> WS2_32.dll!__imp_recvfrom RpcSrvMadcapEnumerateScopes -> EnumerateScopes -> ObtainMScopeList -> MadcapDoInform -> GetSpecifiedMadcapMessage -> WS2_32.dll!__imp_recvfrom RpcSrvMadcapRequestAddress -> RequestAddress -> ObtainMadcapAddress -> GetSpecifiedMadcapMessage -> WS2_32.dll!__imp_recvfrom RpcSrvMadcapRequestAddress -> RequestAddress -> ObtainMadcapAddress -> RenewMadcapAddress -> GetSpecifiedMadcapMessage -> WS2_32.dll!__imp_recvfrom RpcSrvRenewIpAddressLeaseEx -> RenewIpAddressLeaseEx -> RenewLease -> GetSpecifiedDhcpMessage -> WS2_32.dll!__imp_recvfrom RpcSrvRenewIpAddressLeaseEx -> RenewIpAddressLeaseEx -> RenewLease -> GetSpecifiedDhcpMessage -> GetSpecifiedDhcpMessageEx -> ProcessRecvFromSocket -> TryReceive -> WS2_32.dll!__imp_recvfrom RpcSrvMadcapReleaseAddress -> ReleaseAddress -> ReleaseMadcapAddress -> GetSpecifiedMadcapMessage -> WS2_32.dll!__imp_recvfrom AcquireParametersByBroadcast -> ReRenewParameters -> DhcpInitRebootState -> RenewLease -> GetSpecifiedDhcpMessage -> WS2_32.dll!__imp_recvfrom AcquireParametersByBroadcast -> ReRenewParameters -> DhcpInitRebootState -> RenewLease -> GetSpecifiedDhcpMessage -> GetSpecifiedDhcpMessageEx -> ProcessRecvFromSocket -> TryReceive -> WS2_32.dll!__imp_recvfrom AcquireParametersByBroadcast -> ReRenewParameters -> DhcpRenewState -> RenewLease -> GetSpecifiedDhcpMessage -> WS2_32.dll!__imp_recvfrom AcquireParametersByBroadcast -> ReRenewParameters -> DhcpRenewState -> RenewLease -> GetSpecifiedDhcpMessage -> GetSpecifiedDhcpMessageEx -> ProcessRecvFromSocket -> TryReceive -> WS2_32.dll!__imp_recvfrom ...
Full list:here.
And now the callgraph:click here.
Wonderfully, dhcpcore.dll can call srand() and rand() functions. Let's see why:paths, callgraph .
Wordpad
How it calls file functions:paths, callgraph .
(Yeah, C++ demangler would be cool.)
FreeCell
How it calls srand/rand functions:paths, callgraph .
And now the script
The networkx library is to be installed: pip install networkx
Modify couple of variables at its beginning. All the info is dumped into IDA output window. Render a PNG file from GV using GraphViz : dot -Tpng 1.gv -o 1.png
My script is a bit raw. Feel free to soup it up.
Futher work
Run GraphViz and show the result from IDA window. Pick low-level functions in IDA window as well.
Please drop me email about any bug(s) and suggestion(s): dennis(@)yurichev.com .
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK