digging into the core of boot · • ro firmware boots signed image on a usb • security or...
TRANSCRIPT
![Page 1: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/1.jpg)
Digging Into The Core of Boot
Yuriy Bulygin @c7zero
Oleksandr Bazhaniuk @ABazhaniuk
![Page 2: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/2.jpg)
Agenda
Intro
Recap of MMIO BAR Issues in Coreboot & UEFI
Coreboot ACPI GNVS Pointer Issue
SMI Handler Issues in Coreboot
Write Protections
Conclusions
![Page 3: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/3.jpg)
Intro to Coreboot
![Page 4: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/4.jpg)
Coreboot
• Coreboot is GPLv2 firmware implementation
• Started as LinuxBIOS in 1999 and renamed to Coreboot at 2008
• Supports x86, ARM, MIPS, POWER8, RISC-V
• Mostly in C, with some ASM. ASL for ACPI tables
• Support multiple payloads (“bootloaders”) to boot Chrome OS, Linux…
• Depthcharge, SeaBIOS, TianoCore, FILO
• Modular arch to support many CPUs, SoCs, chipsets, devices
• Supports verified boot rooted in hardware write protected firmware
![Page 5: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/5.jpg)
Coreboot Stages
Boot Block
Cache-as-RAM
(NEM)
CPU Reset
Verstage
ROMStage
RAMStage
Payload
TPM, SPI Init
Vboot MemInit, SPD,
Ucode update
PCIe enum,
SMM, Option
ROMs, ACPI
Vboot kernel,
EC FW
Read-Only Read-Write
![Page 6: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/6.jpg)
Chrome OS Boot
SoC / CPU
Coreboot RAM stage
Chrome OS
Coreboot Boot Block and Verstage (ROM stage before SKL)
VB_Kernel-A
Recovery Mode
Kernel -A
Applications
Kernel -B
Payload
Read-Only
Read-Write
Recover System from Verified USB
VB_Kernel -B
![Page 7: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/7.jpg)
Verified Boot
• Verified Boot established signature validation mechanism for Chrome OS
• Root of trust is in read-only initial part of Coreboot firmware protected by /WP
pin on SPI devices
• Verstage starting Skylake to reduce amount of read-only ROM stage firmware
(as vulnerabilities in RO firmware cannot be patched w/o voiding warranty)
• Read-only firmware verifies RW firmware (new ROM stage & RAM stage)
• Read-write firmware verifies Chrome OS kernel
• Root public key in read-only flash verifies signature of RW firmware keyblock
• Can be disabled in developer mode (requires physically present user)
![Page 8: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/8.jpg)
Recovery and Developer Modes
Recovery Mode
• RO firmware boots signed image on a USB
• Security or hardware failures trigger entering into recovery mode
Developer Mode
• Prior to entering Dev mode, the system erases local state in TPM and on a hard drive
• Root shell is available in Dev mode
• crossystem dev_boot_usb=1 (boot from USB device)
• crossystem dev_boot_signed_only=0 (load unsigned binaries)
• crossystem dev_boot_legacy=1 (allow boot any payloads including MBR systems)
![Page 9: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/9.jpg)
Read-Only Firmware
Chromebook firmware uses Write Protect pin (/WP) on SPI device to protect RO FW
# flashrom –wp-status
WP: status: 0x0094
WP: status.srp0: 1
WP: status.srp1: 0
WP: write protect is enabled.
WP: write protect range: start=0x00600000, len=0x00200000
Winbond W25Q64BV spec
![Page 10: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/10.jpg)
SPI Chip Layout in Acer C720 Chromebook
# futility dump_fmap –h /tmp/c720_spi_dump.bin
Read-Only
![Page 11: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/11.jpg)
Read-Write
SPI Chip Layout in Acer C720 Chromebook
![Page 12: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/12.jpg)
Recap of MMIO BAR Issues
in Coreboot & UEFI
![Page 13: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/13.jpg)
Recap: “MMIO BAR” Issues
Phys Memory
SMI Handlers in SMRAM
OS Memory
Base Address (BAR)
MMIO range
(registers)
Device PCI CFG
Firmware configures chipset and devices
through MMIO
SMI handlers communicate
with devices via MMIO registers
![Page 14: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/14.jpg)
Recap: “MMIO BAR” Issues
Phys Memory
SMI Handlers in SMRAM
OS Memory
Base Address (BAR)
MMIO range
(registers)
Device PCI CFG
SMI
Exploit with PCI access can modify BAR
register and relocate MMIO range
On SMI interrupt, SMI handler firmware
attempts to communicate with device(s)
It may read or write “registers” within
relocated MMIO
![Page 15: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/15.jpg)
Recap: “MMIO BAR” Issues in Coreboot bar pointer points to
MMIO range of device
B1:D0.F0 which can be
modified by an attacker
SMI handler then uses bar
pointer to write to LVTMA_BL_MOD_LEVEL
offset (when adjusting
brightness level)
SMI handler can be invoked by
properly configuring I/O Trap
hardware with BRIGHTNESS_UP/DOWN function
![Page 16: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/16.jpg)
Coreboot ACPI GNVS Pointer Issue
![Page 17: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/17.jpg)
Coreboot x86 SMI Handlers
smm_handler_start
cpu_smi_handler
northbridge_smi_handler
southbridge_smi_handler
SLEEP SMI
APMC SMI
PM1 SMI
GPE0 SMI
GPI SMI
MC SMI
TCO SMI
PERIODIC SMI
MONITOR SMI
GFX MBI
smi_obtain_lock
smi_release_lock
smi_set_EOS
![Page 18: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/18.jpg)
ACPI Global NVS (GNVS) Area
Stores data used to communicate with ACPI and SMM including across S3 sleep:
• SMM interface buffer
• EC Lock function
• Thermal thresholds
• Fan speed
• USB power controls
• ChromeOS Vboot data
• …
typedef struct {
/* Miscellaneous */
u16 osys; /* 0x00 - Operating System */
u8 smif; /* 0x02 - SMI function call ("TRAP") */
u8 prm0; /* 0x03 - SMI function call parameter */
...
u32 cmem; /* 0x18 - 0x1b - CBMEM TOC */
...
/* ChromeOS specific (0x100 - 0xfff) */
chromeos_acpi_t chromeos;
...
} __attribute__((packed)) global_nvs_t;
![Page 19: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/19.jpg)
ACPI DSDT
• GNVS area is also defined
in DSDT ACPI table
• GNVS layout is platform
(SoC/southbridge) specific
• BDW/SKL: CBMEM TOC address at offset 0x18
![Page 20: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/20.jpg)
How do we find CBMEM and ACPI tables?
![Page 21: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/21.jpg)
Coreboot is allocating GNVS area…
Allocate GNVS area in
CBMEM
Create GNVS structure
Save pointer to GNVS in GNVS_PTR CBMEM area
Add GNVS area to DSDT
ACPI table
![Page 22: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/22.jpg)
Searching for GNVS in ACPI tables…
• GNVS area is allocated in CBMEM backed by in-memory database (IMD) with CBMEM_ID_ACPI_GNVS
• Pointer to GNVS area is stored in DSDT ACPI table in NVSA field
• The table can be found with chipsec_util acpi list or manually in “Tables” area of
Coreboot memory map
• After decompiling DSDT, NVSA field contains GNVS address (0xBFF2D000)
![Page 23: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/23.jpg)
Searching for GNVS in CBMEM…
IMD Root Signature
IMD Entry ID “GNVS”
Data start offset IMD Entry Signature
CBMEM_ID_ACPI_GNVS entry in in-memory database (IMD)
![Page 24: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/24.jpg)
So why are we interested in GNVS area?
• GNVS area is allocated during “Write ACPI Tables” boot stage (bs_write_tables)
• A pointer to GNVS area (GNVP) is also stored in CBMEM_ID_ACPI_GNVS_PTR area allocated in CBMEM (on Broadwell
based systems and above?)
src\arch\x86\acpi.c
![Page 25: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/25.jpg)
When resuming from S3 Sleep…
Find GNVS_PTR in CBMEM
& read GNVP pointer
Update GNVP pointer
restored from CBMEM in
SMM (if SMI handler exists)
Jump to OS Waking Vector in
FACS table
![Page 26: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/26.jpg)
Updating SMM copy of GNVP pointer…
APM_CNT_GNVS_UPDATE SMI
updates SMM copy of GNVP from
EBX restored from CBMEM
![Page 27: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/27.jpg)
SMI handlers never check GNVS pointer
• GNVS pointer is stored in CBMEM area of DRAM which is preserved across S3
• During S3 resume, the pointer is restored from CBMEM in SMM
• SMI handlers use GNVS as a communication buffer with OS (read settings, write results)
• E.g. IOTRAP SMI handler writes byte 0x0 to gnvssmif (if SMIF value is already 0x32)
Limited write primitive in SMM (with controlled address but not the value)
![Page 28: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/28.jpg)
That leads to potential vulnerability on S3 resume
• Attacker could modify GNVS pointer in ACPI_GNVS_PTR area in
memory (to e.g. overlap with SMRAM) & cause system to enter S3
• Firmware would restore modified GNVS pointer in SMM upon
resuming from S3 state
• Attacker then could trigger SMI (e.g. IOTRAP) forcing SMI handler
to write/modify memory at controlled GNVS address
• So far only 0x320 and 0x990 write primitives found
• Only some systems have this issue: • Not all systems with Coreboot store GNVS_PTR (some just store GNVS pointer in SMM
once at normal boot like our IVB based Lenovo x230)
• Not all systems support S3 state
![Page 29: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/29.jpg)
Mitigation Options
• One option is to always store GNVS pointer (GNVP) in SMRAM
and not restore from CBMEM as SMRAM is also preserved in S3
• In general, SMI handlers have to check all pointers/addresses for
overlap with SMRAM just like EDKII does
![Page 30: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/30.jpg)
SMI Handler Issues in Coreboot
![Page 31: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/31.jpg)
SMM/GPU MBI Interface in i82830 SMI Handler
Read SWSMI code
from CPU MMIO register 0xE0
![Page 32: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/32.jpg)
GPU-SMM MBI Interface in i82830 SMI Handler
Read base address
of GPU MMIO range
![Page 33: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/33.jpg)
GPU-SMM MBI Interface in i82830 SMI Handler
Read base address
of GPU MMIO range
Write “CTNI” magic to offset 0x71428 in GFx MMIO
(address controlled by exploit)
![Page 34: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/34.jpg)
Calling MBI functions…
Read the value from offset 0x71428 in GFx MMIO and
pass it as an argument to MBI
function call
![Page 35: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/35.jpg)
Calling MBI functions…
• SMI handler reads argument for MBI from SWF16 (SW Flags) register at offset 0x71428 in Graphics MMIO (VGA Display)
• That GPU register is not locked so attacker can control its contents
• The value of the register is an address to banner_id_t structure
![Page 36: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/36.jpg)
Unchecked banner_id pointer… 1/3
• Writes at the controlled address pointed to by version
![Page 37: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/37.jpg)
Unchecked banner_id pointer… 2/3
![Page 38: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/38.jpg)
Unchecked banner_id pointer… 3/3
![Page 39: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/39.jpg)
Write Protections
![Page 40: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/40.jpg)
What about write protections?
• Read-Only part of Coreboot firmware in SPI flash devices is
hardware write protected in Chromebooks Yes, with a screw
asserting /WP in SPI!
• What if you manually flash Coreboot on a random system?
![Page 41: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/41.jpg)
After flashing Coreboot on Lenovo x230…
![Page 42: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/42.jpg)
To summarize
• SMM based firmware write protection is off
• SPI protected range registers are disabled
• TCO and Global SMI are not locked down
• SPI config is not locked
• SMRAM can be DMA’d into
• And the system doesn’t use /WP pin on SPI device like in
Chromebooks
Super Crazy Developer Mode
![Page 43: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/43.jpg)
That’s the protection…
![Page 44: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/44.jpg)
What about Libreboot?
From https://libreboot.org/faq.html#how-do-i-program-an-spi-flash-chip
![Page 45: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/45.jpg)
Conclusion
• Coreboot contains significant amount of platform dependent code
• Platform dependent SMI handlers don’t check pointers
• ACPI NVS is an attack vector as it stored data across S3 sleep state
• Not a lot of public research into Coreboot vulnerabilities
• In Chromebooks, Coreboot uses SPI device’s /WP mechanism and Verified
Boot. In other systems, Coreboot is not write protected
• If you want to build and flash Coreboot on x86 non-Chromebooks, enable
write protection manually (set BC.SMM_BWP)
![Page 46: Digging Into The Core of Boot · • RO firmware boots signed image on a USB • Security or hardware failures trigger entering into recovery mode Developer Mode • Prior to entering](https://reader033.vdocument.in/reader033/viewer/2022051901/5ff02c6817d2953fe654ae5f/html5/thumbnails/46.jpg)
Thank You!