تمت كتابة أداة akheron
بلغة python وهي مصممة للمساعدة في توفير الرؤية للاتصالات بين شرائح UART والمساعدة في فهم تلك الاتصالات وعكسها ومعالجتها لتمييز وظائف الجهاز (سواء المقصودة أو غير المقصودة). يقوم بذلك من خلال دعم عدة أوضاع للتشغيل:
لا يزال الاتصال بين الرقائق عبر UART خيارًا شائعًا للتصميم موجود في العديد من الأجهزة، ويبدو كما يلي:
+------------+ +------------+
| TXD +-------------------------->+ RXD |
| CHIP A | | CHIP B |
| RXD +<--------------------------+ TXD |
+------------+ +------------+
في هذا المثال، ترسل الشريحة A البيانات إلى الشريحة B عن طريق إرسال البيانات خارج طرف الإرسال (TX) الخاص بالشريحة A وتستقبل الشريحة B تلك البيانات الواردة على طرف الاستقبال (RX) الخاص بها. ترسل الشريحة B البيانات إلى طرف الإرسال (TX) الخاص بها ليتم استقبالها بواسطة الشريحة A على دبوس الاستلام (RX) الخاص بالشريحة A.
ولكن ما الذي يرسلونه بالضبط ذهابًا وإيابًا بين بعضهم البعض؟
إذا جعلنا من أنفسنا آلة مادية في المنتصف، فيمكننا اكتشاف ذلك!
تم تصميم أداة akheron
ليتم تشغيلها على نظام مزود بمنفذين تسلسليين (المحولات من USB إلى تسلسلي جيدة، طالما أن نظام التشغيل الخاص بالنظام يدعمها)، حيث تعمل بمثابة وكيل لإرسال حركة المرور بين هذين المنفذين. شيء من هذا القبيل:
^ + ^ +
| v | v
+---------------------------------+
| |TXD1 RXD1| |TXD2 RXD2| |
| +---------+ +---------+ |
| UART 1 UART 2 |
| |
| Machine-in-the-Middle |
| (running Akheron Proxy) |
| |
+---------------------------------+
إذا قطعنا فعليًا آثار الاتصال بين الشريحة A والشريحة B ثم قمنا بتوجيهها إلى المنافذ التسلسلية لجهازنا في الوسط، فسنكون قادرين على رؤية ما ترسله هذه الرقائق لبعضها البعض عبر اتصالات UART الخاصة بها مع akheron
:
+------------+ +------------+
| TXD +--------+ +------->+ RXD |
| CHIP A | | | | CHIP B |
| RXD +<-+ | | +--+ TXD |
+------------+ | | | | +------------+
| | | |
| v | v
+---------------------------------+
| |TXD1 RXD1| |TXD2 RXD2| |
| +---------+ +---------+ |
| UART 1 UART 2 |
| |
| Machine-in-the-Middle |
| (running Akheron Proxy) |
| |
+---------------------------------+
مع الإعداد على هذا النحو، akheron
جاهز للاستخدام!
akheron
الإصدار 0.1 هو التكرار الأول لهذا الجهد وولد من كود إثبات المفهوم. إنها أداة سطر أوامر تستخدم REPL قياسي للتفاعل.
تتطلب أداة akheron
إصدار Python 3.6 أو إصدار أحدث، وتستخدم مكتبة pyserial
للتواصل مع المنافذ التسلسلية للنظام. تم اختباره على كل من نظام التشغيل macOS 10.15 وUbuntu 18.04.
pip install -r requirements.txt
يمكنك بدء akheron
من نافذة طرفية في دليل المستوى الأعلى للريبو:
./akheron.py
في العديد من الأنظمة، يتم تقييد الوصول إلى الأجهزة التسلسلية. لتجنب تشغيل akheron
بامتيازات مرتفعة، تأكد من أن حساب المستخدم الخاص بك ينتمي إلى نفس المجموعة التي ينتمي إليها الجهاز الذي ترغب في استخدامه. في Linux، من المحتمل أن يكون الجهاز التسلسلي عضوًا في مجموعة dialout
. إن إضافة حساب المستخدم الخاص بك إلى تلك المجموعة (على سبيل المثال sudo usermod -a -G dialout $USER
) من شأنه أن يسمح لك بالوصول إلى الجهاز. لكي تتمكن من رؤية التغييرات، قد تحتاج إلى تسجيل الخروج وتسجيل الدخول مرة أخرى إلى حسابك، أو ربما إعادة تشغيل النظام.
بمجرد التشغيل، سترى لافتة ومطالبة >
:
$ ./akheron.py
######################################################
Akheron Proxy, UART proxy tool for inter-chip analysis
version 0.1
######################################################
>
يتوفر عدد من الأوامر في هذه المطالبة، والتي يمكنك الوصول إليها عن طريق كتابة help
:
> help
Documented commands (type help <topic>):
========================================
capturedump checksumget delimset portget replaceset stop
capturestart checksumset help portset replay watch
capturestop delimget list replaceget start
Undocumented commands:
======================
exit quit version
يمكنك الحصول على مزيد من المساعدة حول أمر معين عن طريق كتابة help <command>
.
> list
/dev/ttyS0
/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyUSB2
/dev/ttyUSB3
يمكنك أيضًا الحصول على قائمة مطولة:
> list -v
/dev/ttyS0
desc: ttyS0
hwid: PNP0501
/dev/ttyUSB0
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.0
/dev/ttyUSB1
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.1
/dev/ttyUSB2
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.2
/dev/ttyUSB3
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.3
ستعمل الخطوات التالية على إعادة توجيه حركة المرور بين المنافذ و"مراقبتها" ثم إيقاف إعادة توجيه حركة المرور:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x61 0x61 0x73 0x73 0x64 0x64
B -> A: 0x31 0x32 0x33 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
هذا هو نفس التدفق، ولكن مع محدد بداية الرسالة 0x37
المحدد:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> delimset start 0x37
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x37 0x71 0x77 0x65 0x65 0x72
0x37 0x64 0x66 0x61 0x64
0x37 0x73
0x37 0x68 0x68
B -> A: 0x37 0x6e 0x6d 0x62
0x37 0x69 0x69
A -> B: 0x37 0x61 0x73 0x64 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
ستقوم الخطوات التالية بإعادة توجيه حركة المرور بين المنافذ، والتقاطها إلى ملف، ومشاهدتها، ثم إيقاف محتويات الالتقاط وتفريغها، ثم إيقاف إعادة توجيه حركة المرور:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> capturestart mycap.out
Saving captured traffic to "mycap.out"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x31 0x32 0x33
B -> A: 0x33 0x32 0x31
A -> B: 0x20 0x20 0x20
B -> A: 0x36 0x36 0x37 0x38 0x39 ^C
Watch mode exited.
> capturestop
Capture stopped
> capturedump mycap.out
1: A -> B: 0x31 0x32 0x33
2: B -> A: 0x33 0x32 0x31
3: A -> B: 0x20 0x20 0x20
4: B -> A: 0x36 0x36 0x37 0x38 0x39
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
توضح الخطوات التالية إعادة توجيه حركة المرور بين المنافذ مع إعادة تشغيل البيانات (في هذا المثال، ملف التقاط يحتوي على سطر واحد) في هذا التسلسل:
0x64 0x61
مع 0x99 0x91
وإعادة التشغيل (لاحظ البيانات المستبدلة في الإخراج)Checksum8Modulo256Plus1
للبايتات السابقة وإعادة التشغيل > portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x64 0x61 0x73 0x64 ^C
Watch mode exited.
> replaceset A 0x64 0x61 -> 0x99 0x91
> replaceget
Replace port A pattern X -> pattern Y:
0x64 0x61 -> 0x99 0x91
Replace port B pattern X -> pattern Y:
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x99 0x91 0x73 0x64 ^C
Watch mode exited.
> checksumset A 3
> checksumget
Replace on port A using checksum 'Checksum8Modulo256Plus1'
No replace checksum specified on port B
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x99 0x91 0x73 0x72 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>