binarly-io / fwhunt-scan

Tools for analyzing UEFI firmware and checking UEFI modules with FwHunt rules
GNU General Public License v3.0
210 stars 30 forks source link

UefiAnalyzer cannot find BootService and RuntimeService #58

Closed river-li closed 1 year ago

river-li commented 1 year ago

I followed the instruction in README and installed fwhunt_scan module, but the analyzer cannot find any services when calling get_summary.

Here is an example.

>>> from fwhunt_scan import UefiAnalyzer
>>> analyzer = UefiAnalyzer(image_path="EnglishDxe")
>>> analyzer.boot_services
[]
>>> analyzer.runtime_services
[]
>>> analyzer.get_summary()
{'core': {'file': 'EnglishDxe', 'fd': 3, 'size': 3136, 'humansz': '3.1K', 'iorw': False, 'mode': 'r-x', 'block': 256, 'format': 'pe64'}, 'bin': {'arch': 'x86', 'baddr': 65536, 'binsz': 3136, 'bintype': 'pe', 'bits': 64, 'retguard': False, 'class': 'PE32+', 'cmp.csum': '0x00007325', 'compiled': 'Thu Jan  1 08:00:00 1970 UTC+8', 'endian': 'LE', 'hdr.csum': '0x00000000', 'laddr': 0, 'lang': 'c', 'machine': 'AMD 64', 'maxopsz': 16, 'minopsz': 1, 'os': 'efi', 'overlay': False, 'cc': 'ms', 'pcalign': 0, 'signed': False, 'subsys': 'EFI Boot Service Driver', 'stripped': False, 'crypto': False, 'havecode': True, 'va': True, 'sanitiz': False, 'static': True, 'linenum': False, 'lsyms': False, 'canary': False, 'PIE': False, 'RELROCS': False, 'NX': False}, 'g_bs': [67568], 'g_rt': [], 'g_smst': [], 'bs_list': [], 'rt_list': [], 'protocols': [], 'nvram_vars': [], 'p_guids': [{'value': 'A4C751FC-23AE-4C3E-92E94964CF63F349', 'name': 'EFI_UNICODE_COLLATION2_PROTOCOL_GUID', 'address': 67328}, {'value': '1D85CD7F-F43D-11D2-9A0C0090273FC14D', 'name': 'EFI_UNICODE_COLLATION_PROTOCOL_GUID', 'address': 67344}]}
>>>

The rizin version is as follow:

(fwhunt) ➜  fwhunt-scan git:(master) ✗ rizin -v
rizin 0.4.1 @ linux-x86-64
commit: 9023f8b997db210cef3b9a25cf1748fbc94942ed, build: 2022-09-10__02:22:47

I tried to find out the problem, it seems like the comparison here returns not equal.

https://github.com/binarly-io/fwhunt-scan/blob/bfb3dbf8d013968ab3320b416dca0166fbcdfd4a/fwhunt_scan/uefi_analyzer.py#L336

In rizin, the call instruction has a ircall type rather than ucall.

[0x00010362]> pdb
│           0x00010349      and   qword [var_28h], 0
│           0x0001034f      lea   rax, [0x00010758]
│           0x00010356      mov   qword [var_20h], rax
│           0x0001035b      lea   r9, section..data                    ; 0x10700
│           0x00010362      mov   rax, qword [0x000107f0]              ; [0x107f0:8]=0
│           0x00010369      lea   r8, [0x00010720]
│           0x00010370      lea   rdx, [0x00010710]
│           0x00010377      lea   rcx, [0x000107e0]
│           0x0001037e      call  qword [rax + 0x148]                  ; 328
│           0x00010384      add   rsp, 0x38
└           0x00010388      ret
[0x00010362]> pdj 1 @ 0x1037e
[{"offset":66430,"ptr":328,"esil":"0x148,rax,+,[8],rip,8,rsp,-=,rsp,=[],rip,=","refptr":false,"fcn_addr":66208,"fcn_last":66435,"size":6,"opcode":"call qword [rax + 0x148]","disasm":"call qword [rax + 0x148]","bytes":"ff9048010000","family":"cpu","type":"ircall","reloc":false,"type_num":402653188,"type2_num":0}]
[0x00010362]>

The issue was fixed when changing all these comparisons to ircall.

yeggor commented 1 year ago

@river-li thank you very much. It's fixed now