導出文件
訪問BMC默認開啓的Web管理界面http://$ip,開啓ssh服務,之後即可以執行ssh root@$ip,得到一個受限的管理界面,功能很少,沒有系統shell。
在服務器上執行ipmitool fru可以查找到設備型號,使用廠商提供的flash備份工具導出flash,比較慢,每秒200多KB。在BMC網頁界面的BMC System Audit Log中看到BMC的Linux系統日誌:
1 | kernel: Kernel command line: root=/dev/ramdisk ro ip=none ramdisk_blocksize=4096 console=ttyS4,38400 rootfstype=cramfs bigphysarea=6144 imagebooted=1 |
從中得到flash的分區信息,包含conf bkupconf
root www
lmedia等分區。用binwalk查看導出的flash可以看到u-boot和一個存儲內核的u-boot
legacy image。
根據Linux系統日誌中描述的conf偏移提取conf,binwalk可以確定文件系統爲[JFFS2],而報告的很多zlib壓縮塊則是JFFS2的數據。本機模擬一個mtdblock設備並掛載:
1 | modprobe mtdram total_size=32768 erase_size=64 |
發現很多文件是通常Linux系統/etc下的配置文件。如果調大conf結束偏移量,還能看到更多文件,不清楚模擬出來的mtdblock有哪些差異。
修改登錄shell
猜測conf分區會被作爲/etc使用,因此修改flash中conf分區處的passwd,把root的shell改成/bin/sh,umount /mnt後再次執行上述掛載操作,在dmesg中能看到內核輸出的JFFS2
checksum錯誤,其中包含正確的校驗和。在flash中搜索錯誤的校驗和,修改成正確的。用flash備份工具寫入修改後的flash,稍等片刻等待BMC自動重啓,再次執行ssh即看到shell換成了busybox!實際測試沒有這麼順利,修改了幾次都發現沒效果,原因是系統檢測到JFFS2文件系統checksum錯誤後自動還原分區。
查看掛載點:
1 | BusyBox v1.13.2 (2015-01-08 17:43:56 CST) built-in shell (ash) |
注意/dev/mtdblock{0..5},它們是同一塊SPI
flash,kernel中應該編碼了劃分方案,但尚不清楚這個信息是怎麼存儲的。
導出initrd
內核啓動選項爲root=/dev/ramdisk ro ip=none ramdisk_blocksize=4096 console=ttyS4,38400 rootfstype=cramfs bigphysarea=6144 imagebooted=1,/dev/ramdisk即爲u-boot提供的initrd,使用只讀文件系統[cramfs],啓動後不會通過switch_root等方式更換根文件系統。可以用ssh root@$ip cat /dev/ramdisk把initrd複製到本地,掛載後發現/etc下有很多指向/conf的軟鏈接,比如/etc/passwd -> /conf/passwd。這就解釋了爲什麼之前修改/conf/passwd可以改變系統的登錄shell。
但是以initrd的數據在flash中按圖索驥卻查不到。暫時擱置。
值得注意的是負責掛載網頁管理界面程序所用分區的啓動腳本/etc/init.d/init-sp.sh,它把flash的分區/dev/mtdblock4(www)掛載到/usr/local/www:
1 | dd if=/dev/$wwwmtdblock of=/dev/ram2 |
這裏用到了程序/usr/local/bin/dencryption,它從第二個參數中獲取長度,使用ECB模式的Tiny
Encryption
Algorithm原地解密第一個參數(此處爲/dev/ram2)。程序中編碼了密鑰,而在flash的u-boot
bootloader區域也能找到該密鑰,發現initrd也是被同樣方式解密後掛載的,而執行這一解密過程的只能是u-boot。猜測開發人員修改u-boot,使用了Tiny
Encryption Algorithm解密initrd傳遞給kernel。
提取flash中0x150000到0xf10000處內容,用dencryption解密算法得到u-boot
legacy
image,tail -c+65即可得到initrd,和/dev/ramdisk一致。
交叉編譯工具鏈
1 | # uname -a |
安裝crosstool-ng,執行ct-ng menuconfig配置交叉編譯工具鏈:
1 | Paths and misc options ---> |
gcc、glibc、binutils等有複雜的版本依賴關係,近年gcc make
sed又都升級了主版本號,如果選擇與BMC系統相近的glibc-2.11,./configure時會報錯。方便起見glibc選擇新版本,這樣某些程序會因爲依賴高版本符號而無法在舊glibc系統上執行,暫且不管。爲了調試方便把strace和ltrace也選上。
ct-ng build。失敗後可以用ct-ng list-steps和ct-ng libc+等,避免前功盡棄。我在tmpfs下編譯,完成後佔用了近7GiB。
其他
內核啓動參數bigphysarea=6144用於分配設置連續的物理內存,/proc/bigphysarea、/proc/iomem可以看到地址的使用情況。
很多服務如kvm、虛擬磁盤等都用到了service location protocol,讀取SLP配置文件,有待了解。
/usr/local/bin/IPMIMain負責處理system/LAN等interface的IPMI請求。Web管理界面和原來的shell都經過自行實現的libipmi.so,請求最終發往IPMIMain監聽的unix
socket。很多符號名和https://www.virustotal.com/en/file/e72785167675ab46c8abd7bc29e66488d78bc5c9ac494c8ca4abcfd5ae94e0e0/analysis/相同。
默認開啓snmpd,但Web管理界面不顯示。可以用snmpwalk -u $username -l authPriv -a MD5 -x DES -A $password -X $passsword $ip獲取MIB樹信息。
IPMI
SDR數據取自/dev/{adc0,gpio0,i2c2,netmon,pwmtach0}等。
調試IPMIMain時需要關閉/etc/init.d中的watchdogapp以避免服務不可用導致系統自動重啓。