سلام بر همه
ما، ویکتور آنتیپوف و ایلیا آلشین، امروز در مورد تجربه کار با دستگاههای USB از طریق Python PyUSB و کمی در مورد مهندسی معکوس صحبت خواهیم کرد.
ماقبل تاریخ
در سال 2019، فرمان شماره 224 دولت فدراسیون روسیه "در مورد تصویب قوانین برچسب گذاری محصولات تنباکو با ابزار شناسایی و ویژگی های اجرای یک سیستم اطلاعات دولتی برای نظارت بر گردش کالاهای مشمول برچسب گذاری اجباری با وسایل شناسایی در رابطه با محصولات تنباکو» لازم الاجرا شد.
در این سند توضیح داده شده است که از اول جولای 1، تولیدکنندگان موظفند هر بسته تنباکو را برچسب گذاری کنند. و توزیع کنندگان مستقیم باید این محصولات را با اجرای سند انتقال جهانی (UDD) دریافت کنند. فروشگاه ها نیز به نوبه خود نیاز به ثبت فروش محصولات دارای برچسب از طریق صندوق دارند.
همچنین از اول جولای 1، گردش محصولات دخانی بدون برچسب ممنوع است. این بدان معنی است که تمام پاکت های سیگار باید با یک بارکد ویژه Datamatrix علامت گذاری شوند. علاوه بر این - یک نکته مهم - معلوم شد که Datamatrix معمولی نیست، بلکه معکوس خواهد بود. یعنی نه کد سیاه روی سفید، بلکه برعکس.
ما اسکنرهای خود را آزمایش کردیم، و معلوم شد که بیشتر آنها نیاز به reflash / آموزش مجدد دارند، در غیر این صورت آنها به سادگی قادر به کار عادی با این بارکد نیستند. این چرخش وقایع برای ما یک سردرد شدید را تضمین کرد، زیرا شرکت ما فروشگاه های زیادی دارد که در یک قلمرو وسیع پراکنده شده اند. چند ده هزار صندوق - و زمان بسیار کمی.
چه باید کرد؟ دو گزینه وجود دارد. اول: مهندسان در محل به صورت دستی اسکنرها را بازخوانی و تنظیم می کنند. دوم: ما از راه دور کار می کنیم و ترجیحاً بسیاری از اسکنرها را به طور همزمان در یک تکرار پوشش می دهیم.
بدیهی است که گزینه اول برای ما مناسب نبود: ما باید برای بازدید از مهندسان پول خرج کنیم و در این مورد کنترل و هماهنگی روند دشوار خواهد بود. اما مهمترین چیز این است که مردم کار کنند، یعنی به طور بالقوه خطاهای زیادی دریافت می کنیم و به احتمال زیاد ضرب الاجل را رعایت نمی کنیم.
گزینه دوم برای همه خوب است، اگر نه برای یک چیز. برخی از فروشندگان ابزارهای چشمک زن از راه دور مورد نیاز ما برای همه سیستم عامل های مورد نیاز را نداشتند. و از آنجایی که مهلتها تمام میشد، باید با سر خودم فکر میکردم.
در مرحله بعد، به شما خواهیم گفت که چگونه ابزارهایی را برای اسکنرهای دستی برای سیستم عامل Debian 9.x توسعه دادیم (همه صندوقهای نقدی ما در دبیان هستند).
حل معما: چگونه یک اسکنر را فلش کنیم
ویکتور آنتیپوف گزارش می دهد.
ابزار رسمی ارائه شده توسط فروشنده تحت ویندوز و فقط با IE کار می کند. ابزار می تواند فلش کند و اسکنر را پیکربندی کند.
از آنجایی که سیستم هدف ما دبیان است، یک سرور usb-redirector در دبیان و یک سرویس گیرنده usb-redirector در ویندوز نصب کردیم. با استفاده از ابزارهای usb-redirector، ما اسکنر را از یک ماشین لینوکس به یک ماشین ویندوز ارسال کردیم.
ابزاری از یک فروشنده ویندوز اسکنر را دید و حتی آن را به طور معمول فلش کرد. بنابراین، ما اولین نتیجه را گرفتیم: هیچ چیز به سیستم عامل بستگی ندارد، این موضوع مربوط به پروتکل فلش است.
خوب. ما فلش را روی دستگاه ویندوز اجرا کردیم و dump را در دستگاه لینوکس حذف کردیم.
ما زباله را در WireShark گذاشتیم و ... غمگین شدیم (من برخی از جزئیات زباله را حذف می کنم، آنها هیچ علاقه ای ندارند).
آنچه زباله دان به ما نشان داد:
آدرسهای 0000-0030، با قضاوت بر اساس Wireshark، اطلاعات سرویس USB هستند.
ما به قسمت 0040-0070 علاقه مند بودیم.
هیچ چیز از یک فریم انتقال مشخص نبود به جز کاراکترهای MOCFT. معلوم شد که این کاراکترها کاراکترهایی از فایل سیستم عامل و همچنین کاراکترهای باقی مانده تا انتهای قاب هستند (فایل سیستم عامل برجسته شده است):
نمادهای fd 3e 02 01 fe به چه معنی بودند، من شخصاً مانند ایلیا هیچ ایده ای نداشتم.
من به فریم زیر نگاه کردم (اطلاعات سرویس در اینجا حذف شده است، فایل سیستم عامل برجسته شده است):
چه چیزی مشخص شد؟ که دو بایت اول نوعی ثابت هستند. همه بلوک های بعدی این را تایید کردند، اما قبل از پایان بلوک انتقال:
این فریم نیز گیجکننده بود، زیرا ثابت تغییر کرده بود (هایلایت شده) و به طرز عجیبی، بخشی از فایل وجود داشت. اندازه بایت های انتقال یافته فایل نشان می دهد که 1024 بایت منتقل شده است. من دوباره نمی دانستم بایت های باقی مانده چه معنایی دارند.
اول از همه، به عنوان یک نام مستعار قدیمی BBS، پروتکل های انتقال استاندارد را بررسی کردم. هیچ پروتکلی 1024 بایت ارسال نکرده است. من شروع به مطالعه سخت افزار کردم و با پروتکل 1K Xmodem مواجه شدم. این اجازه ارسال 1024 را می داد، اما با یک هشدار: در ابتدا فقط 128، و فقط در صورت عدم وجود خطا، پروتکل تعداد بایت های ارسال شده را افزایش داد. من بلافاصله انتقال 1024 بایت داشتم. تصمیم گرفتم پروتکل های انتقال و به طور خاص مودم X را مطالعه کنم.
دو نوع مودم وجود داشت.
ابتدا قالب بسته XMODEM با پشتیبانی از CRC8 (XMODEM اصلی):
دوم، قالب بسته XMODEM با پشتیبانی از CRC16 (XmodemCRC):
به نظر مشابه است، به جز SOH، شماره بسته و CRC و طول بسته.
من به ابتدای بلوک انتقال دوم نگاه کردم (و دوباره فایل سیستم عامل را دیدم، اما قبلاً با 1024 بایت فرورفته شده بود):
من هدر آشنا fd 3e 02 را دیدم، اما دو بایت بعدی قبلاً تغییر کرده بود: 01 fe بود و 02 fd شد. سپس متوجه شدم که بلوک دوم اکنون شماره 02 است و به این ترتیب فهمیدم: جلوی من شماره گذاری بلوک انتقال بود. دنده 1024 اول 01، دومی 02، سومی 03 و غیره (البته به صورت هگز). اما تغییر از fe به fd به چه معناست؟ چشم ها کاهش 1 را مشاهده کردند، مغز یادآور شد که برنامه نویسان از 0 می شمارند نه 1. اما پس چرا بلوک اول 1 است و 0 نیست؟ من هنوز جواب این سوال را پیدا نکردم. اما فهمیدم که بلوک دوم چگونه حساب می شود. بلوک دوم چیزی بیش از FF نیست - (منهای) تعداد بلوک اول. بنابراین، بلوک دوم به عنوان = 02 (FF-02) = 02 FD تعیین شد. خواندن بعدی روگرفت حدس من را تأیید کرد.
سپس تصویر زیر از انتقال شروع به نمایان شدن کرد:
شروع انتقال
fd 3e 02 - شروع
01 FE – شمارنده انتقال
انتقال (34 بلوک، 1024 بایت منتقل شده)
fd 3e 1024 بایت داده (تقسیم شده به بلوک های 30 بایتی).
پایان انتقال
fd 25
داده های باقیمانده باید به 1024 بایت تراز شوند.
قاب انتهایی انتقال بلوک چگونه است:
fd 25 - انتقال سیگنال به بلوک پایانی. 2f 52 بعدی – بقیه فایل تا 1024 بایت حجم دارد. 2f 52، با قضاوت بر اساس پروتکل، یک CRC 16 بیتی است.
به خاطر قدیم، برنامه ای به زبان C ساختم که 1024 بایت را از یک فایل بیرون می آورد و یک CRC 16 بیتی را محاسبه می کرد. راه اندازی برنامه نشان داد که این یک CRC 16 بیتی نیست. دوباره بی حوصلگی - برای حدود سه روز. تمام این مدت سعی می کردم بفهمم که چه چیزی می تواند باشد، اگر نه یک چک سام. در حین مطالعه سایت های انگلیسی زبان، متوجه شدم که X-modem از محاسبات کنترلی خود استفاده می کند - CRC-CCITT (XModem). من هیچ پیاده سازی C از این محاسبه را پیدا نکردم، اما سایتی را پیدا کردم که این چک جمع را به صورت آنلاین محاسبه می کرد. پس از انتقال 1024 بایت از فایل من به صفحه وب، سایت یک چکسوم را به من نشان داد که کاملاً با چکسوم فایل مطابقت داشت.
هورا! آخرین معما حل شد، حالا باید فریمور خودم را بسازم. سپس، دانش خود را (و فقط در ذهنم ماند) به ایلیا، که با ابزار قدرتمند پایتون آشناست، منتقل کردم.
ایجاد یک برنامه
ایلیا آلشین گزارش می دهد.
با دریافت دستورالعمل های مناسب، بسیار "خوشحال" بودم.
از کجا شروع کنیم؟ درست است، از ابتدا. از برداشتن dump از درگاه USB.
USB-pcap را اجرا کنید
پورتی که دستگاه به آن متصل است و فایلی که در آن dump را ذخیره خواهیم کرد را انتخاب کنید.
ما اسکنر را به دستگاهی متصل می کنیم که در آن نرم افزار بومی EZConfigScanning برای ویندوز نصب شده است.
در آن موردی را برای ارسال دستورات به دستگاه پیدا می کنیم. اما تیم ها چطور؟ از کجا می توانم آنها را تهیه کنم؟
هنگامی که برنامه شروع می شود، تجهیزات به طور خودکار مورد بررسی قرار می گیرند (این را کمی بعد خواهیم دید). و بارکدهای آموزشی از اسناد رسمی تجهیزات وجود داشت. DEFALT. این تیم ماست.
داده های لازم دریافت شده است. dump.pcap را از طریق wireshark باز کنید.
هنگام شروع EZConfigScanning مسدود کنید. مکان هایی که باید به آنها توجه کنید با رنگ قرمز مشخص شده اند.
با دیدن همه اینها برای اولین بار، دلم از دست رفت. معلوم نیست بعد کجا باید حفاری کرد.
کمی طوفان فکری و-و-و... آها! در زباله دان خارج - آیا inو in این خارج.
من در گوگل سرچ کردم URB_INTERRUPT چیست. من متوجه شدم که این یک روش انتقال داده است. و 4 روش وجود دارد: کنترل، وقفه، هم زمان، فله. شما می توانید در مورد آنها به طور جداگانه مطالعه کنید.
و آدرس های نقطه پایانی در رابط دستگاه USB را می توان از طریق دستور "lsusb –v" یا با استفاده از pyusb به دست آورد.
اکنون باید همه دستگاه های دارای این VID را پیدا کنیم. شما می توانید به طور خاص با VID:PID جستجو کنید.
این به نظر می رسد:
بنابراین، ما اطلاعات لازم را داریم: دستورات P_INFO. یا DEFALT، محل نوشتن دستورات endpoint=03 و محل دریافت پاسخ endpoint=86 را نشان می دهد. تنها چیزی که باقی می ماند تبدیل دستورات به هگز است.
از آنجایی که قبلاً دستگاه را پیدا کرده ایم، بیایید آن را از هسته جدا کنیم...
... و در نقطه پایانی با آدرس 0x03 بنویسید،
... و سپس پاسخ را از نقطه پایانی با آدرس 0x86 بخوانید.
پاسخ ساختاریافته:
P_INFOfmt: 1
mode: app
app-present: 1
boot-present: 1
hw-sn: 18072B44CA
hw-rev: 0x20
cbl: 4
app-sw-rev: CP000116BBA
boot-sw-rev: CP000014BAD
flash: 3
app-m_name: Voyager 1450g
boot-m_name: Voyager 1450g
app-p_name: 1450g
boot-p_name: 1450g
boot-time: 16:56:02
boot-date: Oct 16 2014
app-time: 08:49:30
app-date: Mar 25 2019
app-compat: 289
boot-compat: 288
csum: 0x6986
ما این داده ها را در dump.pcap می بینیم.
عالی! بارکد سیستم را به هگز تبدیل کنید. تمام است، عملکرد آموزشی آماده است.
فریمور چطور؟ به نظر می رسد همه چیز یکسان است، اما یک تفاوت ظریف وجود دارد.
پس از بررسی کامل فرآیند چشمک زدن، تقریباً متوجه شدیم که با چه چیزی سر و کار داریم. در اینجا مقاله ای در مورد XMODEM وجود دارد که برای درک چگونگی این ارتباط بسیار مفید بود، البته به صورت کلی:
با نگاه کردن به dump، می توانید ببینید که اندازه فریم 1024 است و اندازه URB-data 64 است.
بنابراین - 1024/64 – 16 خط در یک بلوک می گیریم، فایل سیستم عامل را هر بار 1 کاراکتر می خوانیم و یک بلوک تشکیل می دهیم. تکمیل 1 خط در یک بلوک با کاراکترهای خاص fd3e02 + شماره بلوک.
14 خط بعدی با fd25 + تکمیل میشوند، با استفاده از XMODEM.calc_crc() جمع چک کل بلوک را محاسبه میکنیم (زمان زیادی طول کشید تا بفهمیم "FF – 1" CSUM است) و آخرین خط شانزدهم تکمیل میشود. با fd16e.
به نظر می رسد همین است، فایل سیستم عامل را بخوانید، بلوک ها را بزنید، اسکنر را از هسته جدا کنید و آن را به دستگاه ارسال کنید. اما به این سادگی نیست. اسکنر باید به حالت سیستم عامل تغییر کند،
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
این تیم اهل کجاست؟؟ از زباله دان.
اما به دلیل محدودیت 64 نمی توانیم یک بلوک کامل را به اسکنر ارسال کنیم:
خوب، اسکنر در حالت چشمک زن NEWAPP هگز را نمی پذیرد. بنابراین، شما باید هر خط bytes_array را ترجمه کنید
[253, 10, 22, 78, 44, 78, 69, 87, 65, 80, 80, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
و سپس این داده ها را به اسکنر ارسال کنید.
جواب میگیریم:
[2, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
اگر مقاله XMODEM را بررسی کنید، مشخص می شود: داده ها پذیرفته شده اند.
بعد از اینکه همه بلوک ها منتقل شدند، انتقال را تکمیل می کنیم END_TRANSFER = 'xfdx01x04'.
خوب، از آنجایی که این بلوک ها هیچ اطلاعاتی را برای افراد عادی حمل نمی کنند، به طور پیش فرض فریمور را در حالت مخفی نصب می کنیم. و در هر صورت، نوار پیشرفت را از طریق tqdm سازماندهی خواهیم کرد.
در واقع، پس موضوع چیزهای کوچکی است. تنها چیزی که باقی می ماند این است که راه حل را در اسکریپت هایی برای تکرار انبوه در زمان مشخصی بپیچید تا روند کار در صندوق ها کند نشود و ورود به سیستم اضافه شود.
مجموع
با صرف زمان و تلاش زیاد و مو بر روی سرمان، توانستیم راه حل های مورد نیاز خود را توسعه دهیم و همچنین ضرب الاجل را رعایت کنیم. در همان زمان، اسکنرها اکنون مجدداً فلش می شوند و به طور مرکزی آموزش می بینند، ما به وضوح کل فرآیند را کنترل می کنیم. این شرکت در زمان و هزینه صرفه جویی کرد و ما تجربه بسیار ارزشمندی در تجهیزات مهندسی معکوس از این نوع به دست آوردیم.
منبع: www.habr.com