laconic¶
در این چالش با مثالی از تکنیک SROP روبهرو شده و درک میکنیم که چگونه میتوان از سیستمکال sigreturn به درستی و در جهت اکسپلویت برنامه استفاده کرد.
توجه: در این رایتاپ از بیان مفاهیم پایهای(مانند ROP) خودداری شده و تنها ارجاعاتی به منابع دیگر داده شده.
تحلیل اولیه فایل¶
در ابتدا مثل همیشه از دستور file و checksec استفاده میکنیم تا متوجه شویم که با چه فایلی و برای چه معماری و با چه اقدامات کاهشی روبهرو هستیم.
خروجی دستورات file و checksec تحلیل Static با Ghidra¶
پس از آن برنامه را با ghidra بررسی میکنیم و تحلیل static را آغاز میکنیم.
تحلیل static برنامه در Ghidra همانطور که مشاهده میکنید تنها تابع موجود در این برنامه start_ بوده که در آن از تعداد محدودی دستورالعمل اسمبلی استفاده شده است.
بررسی سیستمکال¶
اگر دقت کنید میبینید که rax مقداردهی نشده و در نتیجه احتمال میدهیم که مقدار اولیه آن صفر بوده و از آنجایی که این باینری برای معماری x64 است؛ قصد فراخوانی تابع read را دارد ولی برای اطمینان از gdb استفاده کرده و دقیقتر آن را بررسی میکنیم.
بررسی برنامه با GDB تحلیل عملکرد¶
در هنگام اجرای دستورالعمل syscall مقدار rax صفر است پس با اطمینان میتوان گفت که سیستمکال read در حال فراخوانی شدن است.
آرگومانهای تابع read¶
همانطور که میدانید آرگومانهای تابع read از طریق rdi, rsi, rdx در معماری x64 به سمت آن پاس داده خواهند شد:
- rdi = 0: ورودی (stdin)
- rdx = 0x106: تعداد بایتهای قابل خواندن
- rsi = rsp - 8: مکان ذخیرهسازی در استک
کنترل RIP¶
از آنجایی که در هنگام اجرای دستورالعمل ret مقدار بالای استک pop شده و در رجیستر rip قرار میگیرد، متوجه میشویم که بعد از ارسال 8 بایت داده به عنوان filler یا padding، میتوانیم مقدار رجیستر rip را تغییر داده و روند اجرایی برنامه را در دست بگیریم.
جستجوی ROP Gadgets¶
حال برای اینکه ROP خود را به سرانجام برسانیم نیاز داریم تا از ROPgadget کمک گرفته و gadgetهای در دسترس را برای اکسپلویت کردن برنامه بررسی کنیم.
gadgetهای ROP موجود در برنامه استفاده از SROP¶
با توجه به محدودیتهای موجود:
- gadgetهای در دسترس بسیار کم هستند
- توانایی کنترل کامل rdi را نداریم (آرگومان ابتدایی سیستمکالها)
- فضای کافی برای ساخت signal frame داریم (حداقل 200 بایت)
در نتیجه یکی از گزینههای موجود سیستمکال sigreturn است.
اگر توانایی کنترل کردن rdi را داشتیم احتمالا execve گزینه بهتری بود.
ساخت Signal Frame¶
به منظور کارکرد صحیح این سیستمکال و خودکار کردن این فرایند میتوانیم با استفاده از تابع SigreturnFrame موجود در کتابخانه pwntools، تمامی رجیسترها را به طور دلخواه مقداردهی کنیم.
مراحل اکسپلویت¶
- Pad کردن 8 بایت ابتدایی استک
- استفاده از gadgetهای pop rax و syscall
- مقداردهی rax با مقدار 15 (شماره سیستمکال sigreturn)
- ارسال مقادیر مرتبط با توجه به جایگاه هر رجیستر در signal frame
مزیت عدم فعال بودن PIE¶
خبر خوب این است که PIE این باینری فعال نبوده و در نتیجه آدرس gadgetهای موجود، پس از هر بار اجرای برنامه تغییر نخواهند کرد و در نتیجه نیازی به leak گرفتن از برنامه نیست.
لحظه قبل از اجرای syscall
لحظه بعد از اجرای syscall نتیجه نهایی¶
لحظهای قبل و پس از اجرای دستورالعمل syscall را مشاهده میکنید. اما ممکن است برایتان سوال باشد که چرا پس از اجرای دستورالعمل syscall، رجیستر rip روبه جلو حرکت نکرده و همچنان در جای قبلی خود هستیم. دلیل آن این است که در مرحله قبل و در sigframe ذکر کرده بودیم که rip روی این آدرس خاص که در آن دستورالعمل syscall وجود دارد تنظیم شود تا مجددا بتوانیم پس از کنترل rdi و سایر رجیسترهای مورد نیاز، سیستمکال مد نظرخود را(در اینجا execve) در جهت گرفتن shell فراخوانی کنیم.
رشته bin/sh/¶
یکی از مواردی که باید در این قسمت به آن دقت کنید رشته bin/sh/ است که آدرس آن را در رجیستر rdi قرار دادهایم. این رشته از قبل در برنامه وجود داشت و با استفاده از دستور strings میتوانید آن را مشاهده کنید و برای به دست آوردن آدرس دقیق آن از ghidra یا gdb کمک بگیرید.
بعد از اجرای مجدد syscall و فراخوانی تابع execve دسترسی ما به shell فراهم خواهد شد!
کد اکسپلویت¶
from pwn import *
p = process('./laconic')
#p = remote('94.237.58.78', 51484)
ret = 0x43017
pop_rax = 0x43018
syscall = 0x0000000000043015
binsh = 0x43238
frame = SigreturnFrame(arch='amd64')
frame.rax = 59 # شماره سیستمکال execve
frame.rdi = binsh # آدرس رشته /bin/sh
frame.rsi = 0 # argv
frame.rdx = 0 # envp
frame.rsp = 0xdeadbeef
frame.rip = syscall
pay = b'A' * 8 + p64(pop_rax) + p64(0xf) + p64(syscall) + bytes(frame)
p.send(pay)
p.interactive()
p.close()
دسترسی نهایی به shell FLAG 
HTB{meow_x_meow!!!!}در صورت داشتن هرگونه سوال یا انتقاد و پیشنهاد به آیدی من در تلگرام (@r0pp3r) یا دیسکورد (@nim0x2a) میتوانید پیام دهید.
نویسنده