{"id":1348,"date":"2025-02-03T22:36:51","date_gmt":"2025-02-03T22:36:51","guid":{"rendered":"https:\/\/trouble.org\/?p=1348"},"modified":"2025-02-03T22:37:16","modified_gmt":"2025-02-03T22:37:16","slug":"python-shim-over-qemu-to-startup-bmc","status":"publish","type":"post","link":"https:\/\/trouble.org\/?p=1348","title":{"rendered":"Python shim over QEMU to startup BMC"},"content":{"rendered":"<p>In case anyone wants to run a\/some Supermicro firmware image under QEMU&#8230; here&#8217;s a short script that sets some network features (thanks to <a href=\"https:\/\/www.binarly.io\/blog\/old-but-gold-the-underestimated-potency-of-decades-old-attacks-on-bmc-security\" rel=\"noopener\" target=\"_blank\">binarly<\/a> for figuring out the hard stuff!)<\/p>\n<p>It still crashes and burns because I didn&#8217;t use the gdb trick they mention in the URL, but you can now talk to the BMC as if it were almost a real boy (you must run as root if doing ports < 1024, blah blah.)\n\nHere how it looks like to me when starting QEMU with an unzip'd version from of the <a href=\"https:\/\/www.supermicro.com\/support\/resources\/getfile.php?SoftwareItemID=3416\" rel=\"noopener\" target=\"_blank\">firmware<\/a> &#8211;<\/p>\n<div class=\"codecolorer-container bash blackboard\" style=\"overflow:auto;white-space:nowrap;height:800px;\"><div class=\"bash codecolorer\">python3 qemu-bmc.py REDFISH_X10_323.bin<br \/>\n<br \/>\nExecuting QEMU... <span class=\"kw1\">while<\/span> starting, control-C should stop it.<br \/>\nAfter it<span class=\"st_h\">'s booted, QEMU'<\/span>s control-a followed by an <span class=\"st_h\">'x'<\/span> should <span class=\"kw2\">kill<\/span> it.<br \/>\n<br \/>\nqemu-system-arm<br \/>\n&nbsp; &nbsp; <span class=\"re5\">-m<\/span> <span class=\"nu0\">128<\/span><br \/>\n&nbsp; &nbsp; <span class=\"re5\">-M<\/span> supermicrox11-bmc<br \/>\n&nbsp; &nbsp; <span class=\"re5\">-nographic<\/span><br \/>\n&nbsp; &nbsp; <span class=\"re5\">-drive<\/span> <span class=\"re2\">file<\/span>=REDFISH_X10_323.bin,<span class=\"re2\">format<\/span>=raw,<span class=\"re2\">if<\/span>=mtd<br \/>\n&nbsp; &nbsp; <span class=\"re5\">-net<\/span> nic<br \/>\n&nbsp; &nbsp; <span class=\"re5\">-net<\/span> user,<span class=\"re2\">hostfwd<\/span>=:127.0.0.1:<span class=\"nu0\">22<\/span>-:<span class=\"nu0\">22<\/span>,<span class=\"re2\">hostfwd<\/span>=:127.0.0.1:<span class=\"nu0\">443<\/span>-:<span class=\"nu0\">443<\/span>,<span class=\"re2\">hostfwd<\/span>=udp::<span class=\"nu0\">623<\/span>-:<span class=\"nu0\">623<\/span>,<span class=\"re2\">hostfwd<\/span>=:127.0.0.1:<span class=\"nu0\">23<\/span>-:<span class=\"nu0\">23<\/span>,<span class=\"re2\">hostname<\/span>=qemu<br \/>\n<br \/>\nqemu-system-arm: warning: nic ftgmac100.1 has no peer<br \/>\n<br \/>\n<br \/>\nU-Boot <span class=\"nu0\">2009.01<\/span> <span class=\"br0\">&#40;<\/span>Nov <span class=\"nu0\">12<\/span> <span class=\"nu0\">2014<\/span> - <span class=\"nu0\">11<\/span>:<span class=\"nu0\">37<\/span>:<span class=\"nu0\">48<\/span><span class=\"br0\">&#41;<\/span> ASPEED <span class=\"br0\">&#40;<\/span>v.0.21<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\nI2C: &nbsp; ready<br \/>\nDRAM: &nbsp;<span class=\"nu0\">128<\/span> MB<br \/>\nFlash: <span class=\"nu0\">32<\/span> MB<br \/>\n<span class=\"sy0\">***<\/span> Warning - bad CRC, using default environment<br \/>\n<br \/>\nIn: &nbsp; &nbsp;serial<br \/>\nOut: &nbsp; serial<br \/>\nErr: &nbsp; serial<br \/>\nH<span class=\"sy0\">\/<\/span>W: &nbsp; AST2400 series chip<br \/>\nCOM: &nbsp; port1 and port2<br \/>\nPWM: &nbsp; port<span class=\"br0\">&#91;<\/span>ABCDH<span class=\"br0\">&#93;<\/span><br \/>\nHit any key to stop autoboot: &nbsp;<span class=\"nu0\">0<\/span><br \/>\n<span class=\"co0\">## Booting kernel from Legacy Image at 21400000 ...<\/span><br \/>\n<br \/>\n<span class=\"br0\">&#91;<\/span>....<span class=\"br0\">&#93;<\/span><\/div><\/div>\n<p>Here&#8217;s the program &#8211;<\/p>\n<div class=\"codecolorer-container python blackboard\" style=\"overflow:auto;white-space:nowrap;height:800px;\"><div class=\"python codecolorer\"><span class=\"co1\">#!\/usr\/bin\/env python3<\/span><br \/>\n<br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># start qemu with BMC firmware under python's expect<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># &nbsp; Usage: $0 firmware.img<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># Requires root because it forwards 3 ports to localhost -<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># &nbsp; TCP - 22 and 443<\/span><br \/>\n<span class=\"co1\"># &nbsp; UDP - 623<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># (This could be changed by using ports &gt; 1024, presumably, but I wanted standard<\/span><br \/>\n<span class=\"co1\"># tools - e.g. ipmitool and the like - to work w\/o muss, simply by pointing to<\/span><br \/>\n<span class=\"co1\"># localhost)<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<br \/>\n<span class=\"kw1\">import<\/span> <span class=\"kw3\">os<\/span><br \/>\n<span class=\"kw1\">import<\/span> pexpect<br \/>\n<span class=\"kw1\">import<\/span> <span class=\"kw3\">sys<\/span><br \/>\n<br \/>\n<span class=\"kw1\">if<\/span> <span class=\"kw2\">len<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw3\">sys<\/span>.<span class=\"me1\">argv<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">!=<\/span> <span class=\"nu0\">2<\/span>:<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Usage: %s firmware.img&quot;<\/span> % <span class=\"kw3\">sys<\/span>.<span class=\"me1\">argv<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">sys<\/span>.<span class=\"me1\">exit<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">else<\/span>:<br \/>\n&nbsp; &nbsp; <span class=\"co1\"># FW &nbsp; = &quot;BMC_X11AST2400-3101MS_20230214_1.66_STDsp.bin&quot;<\/span><br \/>\n&nbsp; &nbsp; FW <span class=\"sy0\">=<\/span> <span class=\"kw3\">sys<\/span>.<span class=\"me1\">argv<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><br \/>\n<br \/>\n<span class=\"co1\"># what's the uid - well, effective uid<\/span><br \/>\neid <span class=\"sy0\">=<\/span> <span class=\"kw3\">os<\/span>.<span class=\"me1\">geteuid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">if<\/span> eid:<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">sys<\/span>.<span class=\"me1\">stdout<\/span>.<span class=\"me1\">write<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Error - must be run as root, not UID %d&quot;<\/span> % eid<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">sys<\/span>.<span class=\"me1\">exit<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># emulate a supermicro BMC with QEMU<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<span class=\"co1\"># Ports forwarded:<\/span><br \/>\n<span class=\"co1\"># &nbsp; TCP: 443 =&gt; localhost:443<\/span><br \/>\n<span class=\"co1\"># &nbsp; TCP: &nbsp;22 =&gt; localhost:22<\/span><br \/>\n<span class=\"co1\"># &nbsp; UDP: 623 =&gt; (udp) localhost:623<\/span><br \/>\n<span class=\"co1\">#<\/span><br \/>\n<br \/>\nQEMU<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;&quot;&quot;qemu-system-arm <br \/>\n&nbsp; &nbsp; -m 128<br \/>\n&nbsp; &nbsp; -M supermicrox11-bmc <br \/>\n&nbsp; &nbsp; -nographic<br \/>\n&nbsp; &nbsp; -drive file=%s,format=raw,if=mtd<br \/>\n&nbsp; &nbsp; -net nic<br \/>\n&nbsp; &nbsp; -net user,hostfwd=:127.0.0.1:22-:22,hostfwd=:127.0.0.1:443-:443,hostfwd=udp::623-:623,hostfwd=:127.0.0.1:23-:23,hostname=qemu<br \/>\n&quot;&quot;&quot;<\/span> % FW<br \/>\n<br \/>\n<span class=\"kw1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;&quot;&quot;<br \/>\nExecuting QEMU... while starting, control-C should stop it. <br \/>\nAfter it's booted, QEMU's control-a followed by an 'x' should kill it.<br \/>\n&quot;&quot;&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">print<\/span><span class=\"br0\">&#40;<\/span>QEMU<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\nqemu <span class=\"sy0\">=<\/span> pexpect.<span class=\"me1\">spawn<\/span><span class=\"br0\">&#40;<\/span>QEMU<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"co1\"># don't<\/span><br \/>\nqemu.<span class=\"me1\">timeout<\/span> <span class=\"sy0\">=<\/span> <span class=\"nu0\">999999<\/span><br \/>\n<span class=\"co1\"># echo output<\/span><br \/>\nqemu.<span class=\"me1\">logfile<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw3\">sys<\/span>.<span class=\"me1\">stdout<\/span>.<span class=\"me1\">buffer<\/span><br \/>\n<br \/>\n<span class=\"co1\"># start the fireworks<\/span><br \/>\n<br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Please press Enter to activate this console.&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;id&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"co1\"># make networking a bit more sane<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ip link set eth0 addr 4A:0A:AB:7C:96:2F&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ifconfig eth0 10.0.2.15&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ifconfig eth0 netmask 255.255.255.0&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ifconfig eth0 broadcast 10.0.2.255&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ifconfig eth0 up&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">sendline<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;ip route add 0.0.0.0\/0.0.0.0 via 10.0.2.2&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">expect<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/ #&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Ok... ready to rumble?&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\nqemu.<span class=\"me1\">logfile<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">None<\/span><br \/>\nqemu.<span class=\"me1\">interact<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nqemu.<span class=\"me1\">kill<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In case anyone wants to run a\/some Supermicro firmware image under QEMU&#8230; here&#8217;s a short script that sets some network features (thanks to binarly for figuring out the hard stuff!) It still crashes and burns because I didn&#8217;t use the gdb trick they mention in the URL, but you can now talk to the BMC [&hellip;]<\/p>\n","protected":false},"author":44,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1348","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/posts\/1348","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/users\/44"}],"replies":[{"embeddable":true,"href":"https:\/\/trouble.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1348"}],"version-history":[{"count":8,"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/posts\/1348\/revisions"}],"predecessor-version":[{"id":1358,"href":"https:\/\/trouble.org\/index.php?rest_route=\/wp\/v2\/posts\/1348\/revisions\/1358"}],"wp:attachment":[{"href":"https:\/\/trouble.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trouble.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trouble.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}