保存IDA Pro中生成的函數調用關系(圖)
【未經同意禁止轉載】
鑒於本博客涉及的信息安全技術具有破壞計算機信息系統的風險,建議讀者在學習/研究/探討之前,確保已經充分了解以下內容:
本博客所討論的技術僅限於研究和學習,旨在提高計算機信息系統的安全性,嚴禁用於不良動機,任何個人/團隊/組織不得將其用於非法目的,否則后果自負,特此聲明。
“在手里拿着錘子的人眼里,全世界都是釘子。”
在研究西門子PLC CPU固件逆向的工作中[1],我非常想搞搞清楚函數之間的調用關系,以此達到按圖索驥的目的。同時fix掉看雪論壇上這個遠古的問題[2]。
舉個例子,如下代碼所示,當我明確FUN_001b8eb6_sys_send
函數僅被FUN_001ba9fc
函數調用。換言之,當一個s7comm的PDU組包完成后,接下來必然會調用FUN_001ba9fc
函數以實現發包的目的。
void FUN_001ba9fc(ushort *puParm1,int iParm2)
{
//省略無關代碼
if (*(char *)(puParm1 + 0x12) == 0x0) {
iVar4 = FUN_001b8eb6_sys_send(*puVar5,(uint)*(ushort *)(iParm2 + 10) + *(int *)(iParm2 + 0x10),local_18,1);//int t_send(long s, char *buf, int len, int flags)
那么,組包函數必然和FUN_001ba9fc
發包函數必然在某個函數內形成先后順序,該函數先調用組包函數,再調用發包函數,如以下偽代碼表示。
void FUN_xxxx(ushort *puParm1,int iParm2)
{
//...
pdu_create_funciton();//PDU組包完成后
FUN_001ba9fc();
//...
}
因此,我有必要考察某組包函數和發包函數之間的距離【在一個有向(可能)有環圖中!】。
要解決這個問題,最好將全局函數調用關系生成一個文字可搜索的PDF文件,這樣函數名是可搜索的,函數調用關系是用有向圖形象表示的。
Step1 使用IDA Pro生成函數調用關系
點擊IDA Pro->View->graphs->function calls,或者快捷鍵是Ctrl+F12,如下圖所示。
Step2 保存wingraph中生成的函數調用關系為GDL。
在Windows+IDA Pro下查看Step1中生成的由WinGraph展示的圖,點擊file->save as,將該調用關系另存為GDL(graph discription language)文本為test.gdl
,如下圖所示。
Step3 使用easy-graph將GDL描述文件轉換成DOT描述文件
在LINUX/UBUNTU下 shell下安裝easy-graph(前提是已經安裝GraphViz)
sudo cpan Graph:Easy # 安裝 Graph Easy,可能會要求更新cpan mirror的源
在LINUX/UBUNTU下輸入shell命令[3]
graph-easy --input=test.gdl --as_dot -o test.dot
Step4 在LINUX/UBUNTU下生成pdf
dot -Tpdf test.dot -o test.pdf
Step5 結束
提示:依據我的經驗,在超大規模函數的逆向工程中,不建議使用全局的函數調用圖(function calls graph)。因為這會讓你得到全局信息,而忽視掉局部信息。要知道,千里之堤,潰於蟻穴。依據灰盒的經驗,定位到一個你感興趣的函數,再以拼圖的方式聯系到其他函數,可能是安全研究的常用套路。
我手上under test的西門子PLC CPU模塊屬於早期的S7-1200系列(十分抱歉,我不能公開該設備的訂貨號、固件版本等指紋信息),它既支持s7comm協議,也支持s7comm-plus協議;因為產品硬件版本和固件版本太低,極大概率不支持s7comm-plus-plus協議。我使用IDA Pro和Ghidra等工具反匯編/反編譯了該設備的固件。 ↩︎