نگاره‌هایی پیرامون امنیت، شبکه و رمزنگاری

02 فوریه 2023

بازی CSGO از سال 2012 که منتشر شد تا همین لحظه جزو معروف ترین بازی های جهان بوده و هست. این نسخه جدید بازی کانتر استریک هست که هممون باهاش خاطره داریم. برای هانت کردن از بازی های ویدیویی ما باید علم کافی از حوزه باینری اfracominaabiti giga-sport andcamiciesaldi loevenichhutkaufen scarpeovye negozitata negozigeox gigasport-online donkeywinkekatze mandarinaduckoutlet daysrelax von-dutch ovyeshop saldibenetton akutrekkingshop کسپلویتشن داشته باشیم. بازی آنلاین هست؟ پس باید به نتوورک و شبکه هم مسلط باشیم.

با یه سرچ کوچیک تو گوگل میتونیم بفهمیم که این بازی mandarinaduckoutlet kleankanteentrinkflasche cainsmooredonna negozigeox benettonoutlet mandarinaduckoutlet akutrekkingshop ovyescarpe donkeyluckycat fracominaabiti andcamiciesaldi akuscarpe yeezy grigie 350 benettonoutlet chilloutshutبا زبان ++C نوشته شده که این پروسه ی مهندسی معکوس ما رو یکم آسونتر میکنه.

این رایتاپ از secret club هست. به عوامل اصلی این باگ آخر رایتاپ اشاره کردم. **این باگ مال من نیست و من صرفا فقط کار ترجمه و آنالیز بعضی کد ها رو انجام دادم.

رایتاپ اصلی : https://secret.club/2021/05/13/source-engine-rce-join.html

ما چه اختیاراتی داریم و ویژگی این بازی چیا هست؟

تقریبا توی تمام نسخه های بازی کانتر استریک از قدیم تا جدید ما میتونیم به صورت رایگان یه اتاق بازی بسازیم که با بقیه بازی کنیم اما با یه تفاوت, ما این سرور بازی رو روی کامپیوتر خودمون میسازیم پس اختیارات خیلی بیشتری داریم.

دومین چیزی که خیلی چشممو به خودش گرفت این بود که ما میتونیم توی یه پوشه مخصوص فایل هایی رو بذاریم و بقیه عین همون فایل ها رو دانلود میکنن اما… نه هر فایلی. فقط فایل هایی مثل نقشه بازی, مدل پلیر ها, یه سری قوانین خاص که با Lua نوشته شده و… پس دستمون توی این یه جا بستست اما قطع امید نمیکنیم و همین که میدونیم سرور روی سیستم خودمون اجرا میشه یعنی اجازه ی کنترل و ارسال پکت ها و ریکوئست های بازی مستقیما به خود پلیر رو داریم.

سازندگان بازی همه ی تلاششون رو میکنن که چیزی برای سواستفاده نباشه توی هیچ بخشی از بازیشون ولی کنترل کردن 3 میلیون فانکشن و تابع داخل بازی اونم کد ++C واقعا کار سختیه. کد هایی که قبلا سرسری نوشته شده و هی فقط روی اونا کد نوشتن و اومدن جلو تا بازی اولیه ساخته بشه هنوز توی بازی هست. آپدیت هایی هم که میدن فقط یه جاهای خاصی رو یا فیکس میکنن یا کم و زیاد میکنن.

چطور بدونیم توی پکت هایی که از سمت سرور به کلاینت ارسال میشه و بالعکس چی توشه؟؟

قبل از شروع, پکت چی هست؟ packet ها برای جابه جایی اطلاعات بین کلاینت و سرور استفاده میشه. درست مثل یه بسته اطلاعاتی که از فرستنده به گیرنده میرسه. اگر با ریکوئست های وب آشنایی داشته باشید درک این آسونتره.

ما قبل از هر کار دیگه ای میایم از یه برنامه ای که بتونیم باهاش sniffing انجام بدیم کمک میگیریم (برای دریافت و ثبت پکت های بازی). چی بهتر از wireshark؟

ما با یکم آنالیز داده ها میبینیم که پکت هایی که برای اتصال به سرور استفاده میشه با متود UDP هست و پکت های داخل بازی مثل پیام دویدن – تیر زدن – پریدن و… همشون با TCP

اما یه ضدحال پیشبینی شده; تمامی پکت ها انکود شده و رمزنگاری شده هستن که الگوی رمزنگاریش دست هیچکسی نیست. خب اینکه بده ولی بازم ناامید نمیشیم.

آره میدونم, وحشتناک به نظر میاد

**ما میبینیم که پکت هایی که از سمت کامپیوتر ما به سرور ارسال میشه هم انکود شده هست. بدون اینکه واسطه ای بین کلاینت ما و سرور باشه**

پس الگوی رمزنگاریش یه جایی توی سیستم ما هست ولی نمیدونیم کجا

ما چندین روش داریم برای انجام این کار. یکی مستقیما از ICE Key استفاده کنیم. یه راه دیگه اینه که پروتوکل نتوورک برنامه رو معکوس کنیم (یعنی ببینیم پکت ها چطور ساخته / رمزنگاری میشه و به دست سرور میرسه و بالعکس)

و راه آخر هم اینه که بیایم open handle بزنیم و ReadProcessMemory رو بخونیم که این فقط کلاینت سایده و کمک زیادی نمیکنه اگر بخوایم ارتباط جفت سرور و کلاینت رو با هم ببینیم (راه خوبیه منتها فقط نصف چیزی که میخوایم رو بهمون میده)

ما ICE Key رو نداریم ;( روش آخر هم که خوب نیست پس مجبوریم که پروتوکل نتوورک بازی رو معکوس کنیم. زمان میبره و کار طاقت فرساییه ولی تنها راهیه که داریم

اگر کتابهای attacking network protocols رو درست خونده باشم میدونم که انکود و ارسال و هندل کردن داده ها و پکت ها توی کامپیوتر خودمون با فانکشن های recv و send انجام میشه

خب ما باید اینا رو پیدا کنیم اما کجا میتونن باشن؟ این رو هم در نظر بگیریم که این دو فانکشن توی یه فایل DLL هستن که مال خود ویندوز هست و توسط برنامه ها فراخوانی میشه و کار میکنه. (WS2_32.dll)

اول از همه میرم سراغ خود فایل exe بازی و توی IDA Pro بازش میکنم و تب imports رو نگاه میکنم اما چیزی نمیبینم

پس به DLL های بازی شک میکنم و میرم سراغ اونها. بیشتر از صد تا DLL هست پس خنگ بازی در نمیارم و یه دیباگر باز میکنم و Loaded modules رو سرچ میکنم و میبینم 2 فایل به نام های server.dll و engine.dll وجود داره که اونجا از recv استفاده شده

سرچ میکنیم و فایل رو پیدا میکنیم و سریعا اون رو توی IDA باز میکنیم. دوباره میریم تب imports و بعله ایندفعه تمام فانکشن هایی که میخواستیم رو میبینیم.

recv برای گرفتن پکت ها و دیکود کردنشون و send دقیقا برعکسش. انکود کردن و فرستادن. جفتشون رو برای معکوس کردن این پروتوکل احتیاج داریم.

این مرحله اش به علم مهندسی معکوس و آنالیز کد ++C احتیاج داره ولی فعلا باید روی xref ها تمرکز کنیم تا شکل اولیه کد رو بسازیم. از یه دیکامپایلر هم برای برگردوندن کد اسمبلی به یه ساختار مبتدی کد ++C برسیم تا کارمون آسون تر بشه.

فقط براتون بگم که فهمیدیم از تکنولوژی protobuff توی این پروسه استفاده شده و ما تونستیم که ببینیم اون پکت ها چطوری باید دیکود بشن (خود شرکت valve هم به ما یه ICE Key داده که کار رو آسونتر میکنه اما فقط برای دیکود و انکود کردن دیتا توی سرور های دست ساز)

مرحله بعد : ساخت یه پراکسی برای واسطه بودن بین کلاینت و سرور و دیکود کردن دیتا

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

(عکس از brymko)

حالا دیگه میدونیم داره چه اتفاقی میفته و فقط دانش کافی برای ++C و Lua نیازه که کد رو آنالیز کنیم.

برای مثال 90c00c609a505e90e0000ab188f136c وقتی دیکود میشد به این شکل در میومد

این پکت ارسال یه پیغام صوت هست یا همون وویس چت خودمون

برای مثال میبینیم که فانکشن CSVCMsg چندین شاخه و آرایه داره مثلا quality و codec و version

بقیه پکت ها رو هم چک میکنیم و به چیزای جالبتری میرسیم. با این حال، ما هنوز نمیدونستیم که پیامها به چه ترتیبی ارسال میشن و چه نوع مقادیری انتظار میره
مثلا میدونستیم که برای مقداردهی یه پیام صوتی یه کدک استفاده میشه اما نمیدونستیم که اون کدک ها رو آیا
بازی ساپورت میکنه یا نه


خوشبختانه بعد از یک ساعت چک کردن زیرشاخه های فانکشن های مختلف به فانکشنی به نام : “CSVCMsg_SplitScreen” میرسیم

زیرشاخه هاش رو چک میکنیم

ما این رو فهمیده بودیم که این فانکشن مقدار یه پوینتر رو داخل VFTable سیستم همه پلیرهایی که این پیغام صوتی رو دریافت میکنن عوض میکنه یا کم و زیاد میکنه

ما دقیقا دنبال همین میگشتیم پس میریم که ببینیم کدومشون هست. میتونیم ببینیم که Player_index
از سمت سرور کنترل میشه اما به Arreyها کاری نداره و چیز جالب تر اینه که توی فایل DLL اصلی Engine.dll توی بخش .Data هست
(با یکم مهندسی معکوس و پیدا کردن آدرس این فانکشن از طریق دیباگر ها اینو میفهمیم)
اما باگ اصلی این نیست. چیزی که بهش شک داریم این هست : مقداری که برای Player_index میتونیم بذاریم اصلا حد و مرز نداره و این برای یه هکر به این معناست که ممکنه از توش یه بافر اورفلو در بیاد.
پس ما مقدارش رو یه عدد با ارقام زیادی میذاریم و خوشبختانه بازی کرش میکنه.

ما از این کرش شدن اطلاعات زیادی میتونیم بگیریم. اول کد مربوط به player_index رو پیدا و دیکامپایل میکنیم :

توی اسکرین شات بالا یه تیکه از کد دیکامپایل شده از پلیر_ایندکس نشون داده شده که میتونیم ببینیم اگر مقدار آبجکتمون 1 نباشه یه سری دستور العمل ها از شاخه باید اجرا بشن.
این ما رو نسبت به وجود یه باگ امیدوار تر کرد و فهمیدیم که مشکل میتونه دقیقا از همینجا باشه

میتونیم ببینیم که بعد از فراخوانی چند فانکشن از ویرچوال تیبل (لیست پوینتر ها و فانکشن های مجازی) یه پوینتر میاد و به آدرس اون آبجکت + 180تا هکس بایت بالاتر اشاره میکنه.
ما یه پوینتر از player_index و زیرشاخه هاش پیدا کردیم که توی یک آرایه engine.dll استفاده شده و واقعا مطمعن شدیم که میتونیم این پوینتر رو توی سیستم قربانیمون کنترل کنیم که عواقب خطرناکی داره
اشاره کردن دیتایی که ما کنترل میکنیم و پوینتر به آبجکتی که ذکر شده یه آسیب پذیری اجرای کد به صورت ریموت RCE رو روی سیستم قربانی به ما میده

نتیجه گیری:

سازنده سرور میتونه با ساخت یه اسکریپت که به سمت کامپیوتر بازیکن های توی سرور از پکت های درخواست دسترسی Split screen دیتایی بفرسته که حد و مرزی برای اون تایین نشده (مثلا میتونیم 9999 تا حرف A رو مستقیما به کامپیوتر تمام پلیرهای بازی بفرستیم و بازیشونو کرش بدیم ولی ما قصدمون کرش نیست, گرفتن دسترسی اجرای کد هست)

بافر مثل یه لیوان میمونه و آب هم مثل دیتا و داده ها. اگر بیشتر از اندازه لیوان داخلش آب بریزیم سرریز میکنه و آب به جاهای مختلفی میریزه.

وقتی اندازه بافر کمتر از خود اطلاعات هست بافر سرریز میکنه و اون داده ها تمام پوینتر ها و استک رو اشغال میکنن و پوینتر EIP که معلوم میکنه چی روی سیستم اجرا بشه رو در دست میگیره. ما اگر بدونیم کجای پیلودمون باید کد رو بذاریم که مستقیما بره توی eip اجرا بشه میتونیم دسترسی اجرای کد بگیریم 🙂

متاسفانه توی شبکه های اجتماعی بعضی از افراد درباره این رایتاپ شایعه سازی کردن و من برای رفع تردید و شفاف‌سازی یه رشته توییت زدم و اکثر سوالات رو جواب دادم

ریپورت و گرفتن بانتی:

به Valve Software توی پلتفورم بانتی Hackerone در تاریخ 04.01.2021 این باگ گزارش داده شد، جایزه ۷۵۰۰ دلاری داده شد.

  • Brymko
  • Dezk
  • Scannel
  • Ghasemi (ترجمه)

.رایت‌آپ اصلی رو می‌تونید اینجا ببینید، متشکرم که وقت گذاشتید و این رایتاپ رو خوندید

1 پست نوشته شده
-Reverse engineering
-Binary Exploitation
-Web Exploitation
  • به اشتراک بگذارید:
  1. حسین گفت:

    عالی بود دمت گرم 🔥

  2. Yoosof گفت:

    عالی بود لذت بردم 💯🔥

  3. صفا گفت:

    نخوندم

  4. S گفت:

    جالب بود

  5. ak3nt گفت:

    پرفکت…

  6. B. Menace گفت:

    عالب