此文為靜態分析ELF文件結構,遍歷其中Elf_Ehdr文件頭信息,遍歷Elf_Shdr節表頭信息,並將所有節放置在左側樹控件上,遍歷Elf_Phdr程序頭也放置在左側樹控件上,並着重分析字符串表,重定位表,符號表。遍歷表頭的使用使用map將節表信息對應字符串存入,當點擊樹控件的時候取出顯示在右側。
遍歷程序頭
Elf64_Phdr* Phdr = (Elf64_Phdr*)(m_szFileData+Elf_Ehdr->e_phoff); for(int i = 0;i<Elf_Ehdr->e_phnum;i++,Phdr++) { CString item; item.Format(L"Program Header %d",i); m_Tree.InsertItem(item,0,2); Map_Phdr64.insert(map<CString,Elf64_Phdr>::value_type(item,*(Elf64_Phdr*)Phdr)); }
遍歷節表頭
Elf64_Shdr* Shdr = (Elf64_Shdr*)(m_szFileData+Elf_Ehdr->e_shoff); for(int i = 0;i< Elf_Ehdr->e_shnum; i++,Shdr++) { WCHAR* Temp = CharToWchar(pStrTable + Shdr->sh_name); CString item; item.Format(L"%s",Temp); HTREEITEM Handle = m_Tree.InsertItem(item,0,2); if(item==L".shstrtab"||item==L".strtab"||item==L".dynstr") { m_Tree.InsertItem(L"String Table 字符串表",1,3,Handle); } else if(item==L".symtab") { m_Tree.InsertItem(L"Symtab 符號表",1,3,Handle); } else if(item==L".rel.dyn"||item==L".rel.plt") { m_Tree.InsertItem(L"REL Table 重定位表",1,3,Handle); } else if(item==L".dynsym") { m_Tree.InsertItem(L"Dynsym 符號表",1,3,Handle); } Map_Shdr64.insert(map<CString,Elf64_Shdr>::value_type(item,*(Elf64_Shdr*)Shdr)); }
其中Shdr結構中st_name存放的是字符串表(最后一個節表頭對應的節.shstrtab)中的索引,我們需要取得節表對應的名稱,需要在.shstrtab中取出
char * pStrTable; // 用以取得每個 section 的名字 Elf64_Shdr * ShdrStringTable = (Elf64_Shdr *)(m_szFileData + Elf_Ehdr->e_shoff) + Elf_Ehdr->e_shstrndx; pStrTable = (char *)(m_szFileData + ShdrStringTable->sh_offset);
取出字符串的時候只需要調用
pStrTable + Shdr->sh_name
ELF格式驗證為前4個字節為: ".ELF"
if (!( (((char*)m_szFileData)[EI_MAG0] == 0x7F) && (((char*)m_szFileData)[EI_MAG1] == 'E') && (((char*)m_szFileData)[EI_MAG2] == 'L') && (((char*)m_szFileData)[EI_MAG3] == 'F'))) { MessageBox(L"非ELF 格式文件或者文件已被損壞!",L"Error"); goto END; }
程序運行結果如下:
還有沒完善的大家可以自行學習完善,對於64和32位沒想到什么好的方法重定義結構體,只能寫兩個函數,有什么方法一定要告訴我!!
其他可以參考代碼:https://github.com/LycorisGuard/android/tree/master/ElfAnalyse
ELF格式參考:ELF格式