Ngrok v2 بروتوكول الهندسة العكسية

Ngrok v2 بروتوكول الهندسة العكسية


ngrok هي خدمة تتيح لك إنشاء أنفاق على الكمبيوتر المحلي للمستخدم. بمعنى آخر ، يتم حجز عنوان عام ، حيث يتم إعادة توجيه جميع المكالمات إلى المنفذ المحلي.

لسوء الحظ ، منذ عام 2016 ، تم إيقاف دعم الإصدار المفتوح المصدر للعميل (ngrok v1) ، ولاستخدام الخدمة ، فأنت بحاجة إلى تشغيل الإصدار المغلق (ngrok v2) ، وهو أمر غير مقبول في كثير من الحالات. توضح هذه المقالة عملية تعلم البروتوكول الذي يستخدمه عميل رسمي وإنشاء عميل مفتوح بديل.


ولكن هل هو ضروري؟ بدائل نجروك


الغريب ، هذه الخدمة لديها عدد قليل جدا من البدائل. على وجه التحديد ، ثلاثة:


  • serveo.net . يوفر وظائف مماثلة ، ولكن يستخدم إعادة توجيه منفذ SSH العكسي ، وليس عميل مخصص. لسوء الحظ ، المشروع مغلق حاليًا.

    تم تعطيل Serveo مؤقتًا بسبب الخداع.

    سيعود Serveo في غضون بضعة أيام مع بعض القيود الجديدة للمساعدة في ثني الإساءة. شكرا لصبرك!

  • localtunnel.me . يوفر فقط نفق HTTP مع توزيع يستند إلى رأس المضيف ، وفي حالة HTTPS ، يتم فك تشفير البيانات على الخادم وإرسالها إلى تطبيق العميل بنص واضح. موقع المشروع غير متاح حاليًا.
  • pagekite.net . يوفر أنفاق HTTP و TLS. بعد فترة تجريبية مدتها 30 يومًا ، سيتعين عليك الدفع مقابل الاستخدام الإضافي.

(ملاحظة: اقترحت التعليقات أن هناك localhost.run يوفر أنفاق HTTP عبر إعادة توجيه منفذ SSH ، على غرار servo.net. ومع ذلك ، فإن الخدمة توفر فقط أنفاق HTTP ، على عكس ngrok)


محاولة ساذجة رقم 1: mitmproxy


دعونا نحاول الاستماع إلى حركة المرور الرسمية للتطبيق باستخدام mitmproxy:


$ mitmproxy $ http_proxy=http://127.0.0.1:8080 https_proxy=http://127.0.0.1:8080 ngrok http 8080 #     

التطبيق ، بطبيعة الحال ، يبدأ أقسم على شهادة غير صالحة. ومع ذلك ، يُظهر نص الخطأ أن ngrok يحاول حل عنوان خادم tunnel.us.ngrok.com من خلال DNS-over-HTTPS:


 Get https://dns.google.com/resolve?cd=true&name=tunnel.us.ngrok.com&type=AAAA: x509: certificate signed by unknown authority 

دعونا نحاول سحب tunnel.us.ngrok.com نفسه:


 $ curl https://tunnel.us.ngrok.com/ curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.haxx.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above. 

على ما يبدو ، يستخدم العميل تثبيت شهادة مع شهادة موقعة ذاتياً. دعنا نحاول تجاهل الخطأ:


 $ curl -k https://tunnel.us.ngrok.com Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file. $ curl -k --output - https://tunnel.us.ngrok.com     -illegal WNDINC frame length: 0x474554 

توفر Google بناءً على طلب "طول إطار WNDINC غير القانوني" مكتبة لذهاب إلى اتصالات TCP المتعددة. تم ذكر المكتبة نفسها في مشكلة مع استدعاء لفتح رموز مصدر ngrok v2.


مكتبة Muxado


تحقق مما إذا كان ngrok يستخدم مكتبة muxado فعلاً:


 $ nm ./ngrok | grep muxado 00000000008ae2c0 T github.com/inconshreveable/muxado.(*addr).Network 00000000008ae2e0 T github.com/inconshreveable/muxado.(*addr).String 0000000000e31b40 B github.com/inconshreveable/muxado.bufferClosed 0000000000e31b50 B github.com/inconshreveable/muxado.bufferFull 00000000008ad430 T github.com/inconshreveable/muxado.Client 0000000000e31b60 B github.com/inconshreveable/muxado.closeError 00000000008b4c00 T github.com/inconshreveable/muxado.(*condWindow).Broadcast 00000000008b2ed0 T github.com/inconshreveable/muxado.(*condWindow).Decrement 00000000008b2da0 T github.com/inconshreveable/muxado.(*condWindow).Increment 00000000008b2d30 T github.com/inconshreveable/muxado.(*condWindow).Init ... 

يمكن استخلاص العديد من الاستنتاجات من إخراج هذا الأمر (آسف للتعلم):


  1. ngrok حقا يستخدم هذه المكتبة.
  2. لم يحاول المؤلف تشويش الملف القابل للتنفيذ بأي شكل من الأشكال ، حيث بقيت الأحرف فيه.

لاحظ أيضًا أنه تم استلام الخطأ من الخادم عبر اتصال آمن (TLS) ، مما يعني أن بروتوكول muxado يستخدم داخل جلسة TLS. يشير هذا إلى أنه يتم إرسال بيانات muxado بنص واضح ، حيث سيكون التشفير الإضافي ضروريًا. وبالتالي ، لإزالة تفريغ حركة المرور غير المشفرة ، يكفي لاعتراض المكالمات (* دفق) .Read و (* دفق) .Write.


ABI


قبل محاولة اعتراض المكالمات ، تحتاج إلى فهم كيفية انتقال المعلمات التي تهمنا. للقيام بذلك ، سنكتب برنامجًا بسيطًا على Go باستخدام المكتبة (يعمل netcat كطرف متلقي):


قانون
 package main import "net" import "github.com/inconshreveable/muxado" func main() { var conn net.Conn conn, _ = net.Dial("tcp", "127.0.0.1:1234") sess := muxado.Client(conn, &muxado.Config{}) conn, _ = sess.Open() data := []byte("Hello, world!") conn.Write(data) } 

لذلك ، لاعتراض حركة المرور ، نحن مهتمون بما يلي:


  • معرف مؤشر ترابط فريد (مطلوب لتمييز عدة مؤشرات ترابط نشطة في وقت واحد).
  • المؤشر إلى المخزن المؤقت مع البيانات.
  • طول المخزن المؤقت للبيانات.

يُظهر إخراج objdump على github.com/inconshreveable/muxado.(*stream). وظيفة الكتابة (المضحك أن مطوري Go لا يبدو أنهم يزعجون اسم تغيير الاسم). يُظهر بوضوح تحميل الوسائط من المكدس:


  4de2d6: 48 8b 44 24 58 mov 0x58(%rsp),%rax 4de2db: 48 89 44 24 08 mov %rax,0x8(%rsp) 4de2e0: 48 8b 44 24 60 mov 0x60(%rsp),%rax 4de2e5: 48 89 44 24 10 mov %rax,0x10(%rsp) 4de2ea: 48 8b 44 24 68 mov 0x68(%rsp),%rax 4de2ef: 48 89 44 24 18 mov %rax,0x18(%rsp) 

يبقى أن نفهم بالضبط أين تكمن القيم التي نحتاج إليها في المجموعة. للقيام بذلك ، استخدم gdb وعرض حالة المكدس في وقت تم استدعاء الوظيفة.


 Thread 1 "test" hit Breakpoint 1, github.com/inconshreveable/muxado.(*stream).Write (buf=..., err=..., n=<optimized out>, s=<optimized out>) at /home/sergey/muxado/src/github.com/inconshreveable/muxado/stream.go:81 81 func (s *stream) Write(buf []byte) (n int, err error) { (gdb) set language c Warning: the current language does not match this frame. (gdb) p {char*[4]}$rsp $1 = { 0x4e0cbf <main.main+319> "H\213l$XH\203\304`\303\350\002A\367\377\351\255\376\377\377", '\314' <repeats 13 times>, "dH\213\f%\370\377\377\377H;a\020vKH\203\354\bH\211,$H\215,$\017\266\005k\003\025", 0xc0000b4000 "", 0xc000014300 "Hello, world!", 0xd <error: Cannot access memory at address 0xd>} 

العنصر الأول من هذه المصفوفة هو عنوان المرسل ، ولا يمكنه المشاركة في تمرير الوسائط. الأخيران ، من الواضح ، هما عنوان المصفوفة وطولها ؛ نظرًا لأن المؤشر إلى الدفق يذهب أولاً في قائمة الوسيطات ، فمن المنطقي افتراض أنه في الخلية الثانية. يمكن استخدامه (مع الحجوزات) كمعرف فريد للتيار.

لذلك ، نحن الآن نعرف كيف توجد وسيطات الدالة (* دفق) .Write في الذاكرة (من أجل (* دفق). اقرأ كل شيء كما هو بالضبط ، لأن الدوال لها نفس النموذج الأولي). يبقى أن ندرك الاعتراض نفسه.


محاولة ساذجة رقم 2: خطاطيف وظيفة وقت التشغيل


دعونا نحاول إعادة توجيه المكالمات (* الدفق). الكتابة إلى وظيفة الوكيل:


شيء مثل هذا
 unsigned long long write_hook() { volatile long long* rsp = RSP(); void* stream = (void*)rsp[1]; char* buf = (char*)rsp[2]; long long len = rsp[3]; UNSET_HOOK(); unsigned long long ans; PUSH(rsp[3]); PUSH(rsp[2]); PUSH(rsp[1]); CALL(syscall_write); POP(24, ans); SET_HOOK(); return ans; } 

عند محاولة الاتصال بـ ngrok باستخدام هذا الخطاف ، نحصل على عطل في النموذج التالي:


 unexpected fault address 0x0 fatal error: fault [signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0x4a2dc6] goroutine 1 [running]: runtime.throw(0xac7ca8, 0x5) /usr/local/Cellar/go/1.8.3/libexec/src/runtime/panic.go:596 +0x95 fp=0xc42016f9f0 sp=0xc42016f9d0 runtime.sigpanic() ... 

نحن هنا ننتظر عقبة غير متوقعة في وجه goroutines. الحقيقة هي أنه يتم تخصيص مكدس goroutine بشكل حيوي: إذا لم يكن هناك مساحة كافية في المكدس الحالي ، فسيتم تخصيصه مرة أخرى في مكان آخر ، ويتم نسخ المحتوى الحالي. لسوء الحظ ، فإن الوظائف التي تم إنشاؤها بواسطة gcc تخزن مؤشر المكدس القديم في سجل rbp (ما يسمى بمؤشر الإطار) ، وعندما ترجع من مثل هذه الوظيفة ، يبدأ مؤشر المكدس بالإشارة إلى المكدس القديم الذي تم تحريره بالفعل (الاستخدام بعد الاستخدام المجاني). لذلك C ليس مساعد هنا.


محاولة # 3: النصي gdb


سنكتب سيناريو gdb يطبع جميع البيانات المرسلة:


 set language c break github.com/inconshreveable/muxado.(*stream).Write commands set $stream={void*}($rsp+8) set $buf={char*}($rsp+16) set $len={long long}($rsp+24) p $stream p (*$buf)@$len p $len cont end run tcp 8080 -log stdout -log-format logfmt -log-level debug 

هذا يعمل ، ولكن للحصول على تفريغ كامل ، تحتاج إلى حفظ البيانات المستلمة. وهنا هناك العديد من المشاكل:


  • لقراءة البيانات المستلمة ، عليك الانتظار حتى تكمل الوظيفة التنفيذ. يتم حل هذه المشكلة عن طريق تعيين نقطة توقف على عبارة ret.
  • يمكن أن تقرأ الدالة بيانات أقل من المخطط لها ، في حين أن عدد وحدات البايت المقروءة فعليًا هو إحدى قيم الإرجاع للدالة. تحتاج إلى فهم كيفية إرسال قيم الإرجاع. (من السهل أيضًا طباعة كومة بعد تنفيذ الوظيفة. الرقم المطلوب هو $ rsp + 48).
  • المشكلة الثالثة والأكثر أهمية. إخراج gdb غير مخصص للتحليل التلقائي (على سبيل المثال ، راجع النسخة المطبوعة من قسم ABI) ، وبالتالي فإن القالب الذي تم الحصول عليه بهذه الطريقة مناسب للتحليل البصري فقط. (في الواقع ، هذه ليست مشكلة ، لأن البروتوكول بسيط للغاية ومعترف به في لمحة).

محاولة # 4: التجمع


عند فتح الملف الثنائي باستخدام ngrok objdump ، يمكنك رؤية وجود فجوة قدرها 0xc10 = 3088 بايت بين مقاطعتي .text و .rodata:


  9773eb: e9 50 ff ff ff jmpq 977340 <type..eq.[2]github.com/kevinburke/cli.Flag>   .rodata: 0000000000978000 <type.*>: 

الفجوة نفسها موجودة في الملف نفسه ، حيث يتم ملء مساحة فارغة مع صفر بايت. يتيح لك هذا تغيير حجم المقطع الذي يحتوي على قسم .text المسجل في الملف (بحث / استبدال في محرر hex) ، وإضافة رمز إلى مساحة تسجيل المكالمات.

يستغرق تعليمة الانتقال النسبي على بنية x86_64 5 بايت: شفرة التشغيل (E9) + الإزاحة إلى العنوان النهائي (موقعة int). نظرًا لأن حجم الملف القابل للتنفيذ ngrok أقل بكثير من 2 غيغا بايت ، فإن هذه الإرشادات تتيح لك نقل التحكم إلى أي مكان في قسم .text ، بما في ذلك الكود الجديد.

يستغرق التعليمة الأولى لكلا الوظيفتين 9 بايت ، لذلك يمكن استبدال أول 5 بايت من التعليمة تعليمة قفزة:


  8b0e70: 64 48 8b 0c 25 f8 ff mov %fs:0xfffffffffffffff8,%rcx 8b0e77: ff ff 

للاتصال بالوظيفة الأصلية ، ما عليك سوى اتباع التعليمات الأصلية وانتقل إلى العنوان func + 9

مع العبارة ret في الدالة (* stream) .Read ، كل شيء أكثر إثارة للاهتمام:


  8b0f6d: 7f 22 jg 8b0f91 <github.com/inconshreveable/muxado.(*stream).Read+0xa1> ... 8b0f8c: 48 83 c4 58 add $0x58,%rsp 8b0f90: c3 retq 8b0f91: 48 8b 5c 24 60 mov 0x60(%rsp),%rbx 

يشغل تعليمة ret (المكتوبة كـ retq ، بدلاً من retf) بايت واحد فقط ، في حين أن التعليمات التالية تتبع هدفًا سريعًا ، لذلك لا يمكنك تغييره. ومع ذلك ، لا يتم تنفيذ تعليمة النقل في أي مكان على تعليمة ret نفسها ، لذلك لا يوجد ما يمنعها من الاستبدال بالانتقال بالتعليم السابق (بعد الانتقال ، بالطبع ، يجب إكماله).


رمز مسجل المجمع الكامل
 section .text org 0x9773f0 use64 write_pre_hook: ;      (*stream).Write push dword 0x74697277 call log add rsp, 8 mov rcx, [fs:-8] ;   (*stream).Write    jmp 0x8b0e79 read_post_hook: ;     0x8b0f8c add rsp, 0x58 ;    ret, .  push dword 0x64616572 call log add rsp, 8 ret log: ;  ,         push rdi push rsi push rdx push rax ;; stack layout: ;; rsp+32 ret ;; rsp+40 kind ('read' or 'writ') ;; rsp+48 ret0 ;; rsp+56 &stream ;; rsp+64 buf ;; rsp+72 len ;; rsp+80 unknown ;; rsp+88 n ;; rsp+96 err ;       mmap mov rax, 9 mov rdi, 0 mov rsi, 44 add rsi, [rsp+72] mov rdx, 3 push r10 push r8 push r9 mov r10, 34 mov r8, -1 mov r9, 0 syscall test rax, rax js segfault pop r9 pop r8 pop r10 ;     mov edi, [rsp+40] mov [rax], edi lea rdi, [rax+4] lea rsi, [rsp+56] push rcx mov rcx, 40 ;up to rsp+96 rep movsb ;    mov rsi, [rsp+72] ;rsp+64 mov rcx, [rsp+80] ;rsp+72 rep movsb pop rcx ;  write mov rdi, 3 mov rsi, rax mov rdx, 44 add rdx, [rsp+72] push rax call writeall ;   pop rdi mov rsi, 44 add rsi, [rsp+72] mov rax, 11 syscall test rax, rax jnz segfault ;   pop rax pop rdx pop rsi pop rdi ret writeall: mov rax, 1 syscall test rax, rax js segfault add rsi, rax sub rdx, rax test rdx, rdx jnz writeall ret segfault: ;          mov [0], rax 
برنامج بايثون لتحليل السجلات
 import sys stream = sys.stdin.buffer while True: chunk = stream.read(44) if not chunk: break assert len(chunk) == 44 kind = chunk[:4].decode('ascii') assert kind in ('read', 'writ') str_id = hex(int.from_bytes(chunk[4:12], 'little')) l = int.from_bytes(chunk[20:28], 'little') n = int.from_bytes(chunk[36:], 'little') if kind == 'read' else l buf = stream.read(l) assert len(buf) == l if '--full-data' not in sys.argv: buf = buf[:n] print('((%r, %s, %d), (%r, %d))'%(kind, str_id, l, buf, n)) 

وبالتالي ، لدينا الآن أداة عمل لإزالة مكبات حركة المرور من ngrok. التحقق من ذلك في العمل!


نفاية
 (('writ', 0xc420326600, 4), (b'\x00\x00\x00\x00', 4)) (('writ', 0xc420148e00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420326600, 227), (b'{"Version":["2"],"ClientId":"","Extra":{"OS":"linux","Arch":"amd64","Authtoken":"3FjYRxVDd2QvNkX13h82k_6Thwfp93PUZEpsz3vYe5v","Version":"2.2.8","Hostname":"tunnel.us.ngrok.com","UserAgent":"ngrok/2","Metadata":"","Cookie":""}}\n', 227)) (('read', 0xc420326600, 512), (b'{"Version":"2","ClientId":"df05b949e58359ea6901cff60935531d","Error":"","Extra":{"Version":"prod","Cookie":"lh7YagbqJ9ixLYyE05ZDMPvaYNVm5isu$xF1Mp8fDc689269YUGlGNAV/0XRyrEH390rwGqILZqYS5+qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg+zrgnrW9cRNuO8ApSe2+OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh","AccountName":"\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9 \xd0\x9b\xd0\xb8\xd1\x81\xd0\xbe\xd0\xb2","SessionDuration":0,"PlanName":"Free"}}', 430)) (('read', 0xc420148a00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420148200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc420148200, 111), (b'{"Id":"","Proto":"https","Opts":{"Hostname":"","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 111)) (('read', 0xc420148200, 512), (b'{"Id":"39b1e32e134eff8671b02268945643f9","URL":"https://deb82e2e.ngrok.io","Proto":"https","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0$EHrXSWq/fY/mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL/3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE', 512)) (('read', 0xc420148200, 1024), (b'cOIiZ09W6pMPTHoTcih0"}}', 23)) (('writ', 0xc4200ea200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc4200ea200, 127), (b'{"Id":"","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 127)) (('read', 0xc4200ea200, 512), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","URL":"http://deb82e2e.ngrok.io","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"G4nIrca8GTvq4H62sTmqdb144FmhMgrg$U6TwkKWafv/3+bFM5AP7xIFfkWqx+HUsYWhkYXivrtMfcqan0mKZx99LHGI7mm5lOMmvI+Kdy7WF/GnwrMDXrRFwhYowczaWKRKnUimnNtndq7rdttMevFabwe5WSzwf+IZhWzQ2yvcW31+qVuS7F6uykUSw+mnBNtsdXFSNpToagqQOM66A8LT+l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ', 512)) (('read', 0xc4200ea200, 1024), (b'hhVDbeM2HP+qV6S5I="}}', 21)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('read', 0xc420148a00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148a00, 4), (b'\x00ys7', 4)) (('read', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('writ', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc4200ea200, 4), (b'\x00\x00\x00\x03', 4)) (('read', 0xc4200ea200, 8), (b'M\x00\x00\x00\x00\x00\x00\x00', 8)) (('read', 0xc4200ea200, 77), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","ClientAddr":"***.***.**.***:17815"}', 77)) (('read', 0xc4200ea200, 32768), (b'GET / HTTP/1.1\r\nHost: deb82e2e.ngrok.io\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 Midori/6\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru-RU\r\nX-Forwarded-For: ***.***.**.***\r\n\r\n', 359)) (('writ', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('writ', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc4200ea200, 32768), (b'', 0)) xF1Mp8fDc689269YUGlGNAV / 0XRyrEH390rwGqILZqYS5 + qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg + zrgnrW9cRNuO8ApSe2 + OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh"، "اسم الحساب": "\ xd0 \ xa1 \ xd0 \ xb5 \ XD1 \ X80 \ xd0 \ xb3 \ xd0 \ xb5 \ xd0 \ xb9 \ xd0 (('writ', 0xc420326600, 4), (b'\x00\x00\x00\x00', 4)) (('writ', 0xc420148e00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420326600, 227), (b'{"Version":["2"],"ClientId":"","Extra":{"OS":"linux","Arch":"amd64","Authtoken":"3FjYRxVDd2QvNkX13h82k_6Thwfp93PUZEpsz3vYe5v","Version":"2.2.8","Hostname":"tunnel.us.ngrok.com","UserAgent":"ngrok/2","Metadata":"","Cookie":""}}\n', 227)) (('read', 0xc420326600, 512), (b'{"Version":"2","ClientId":"df05b949e58359ea6901cff60935531d","Error":"","Extra":{"Version":"prod","Cookie":"lh7YagbqJ9ixLYyE05ZDMPvaYNVm5isu$xF1Mp8fDc689269YUGlGNAV/0XRyrEH390rwGqILZqYS5+qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg+zrgnrW9cRNuO8ApSe2+OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh","AccountName":"\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9 \xd0\x9b\xd0\xb8\xd1\x81\xd0\xbe\xd0\xb2","SessionDuration":0,"PlanName":"Free"}}', 430)) (('read', 0xc420148a00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420148200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc420148200, 111), (b'{"Id":"","Proto":"https","Opts":{"Hostname":"","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 111)) (('read', 0xc420148200, 512), (b'{"Id":"39b1e32e134eff8671b02268945643f9","URL":"https://deb82e2e.ngrok.io","Proto":"https","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0$EHrXSWq/fY/mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL/3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE', 512)) (('read', 0xc420148200, 1024), (b'cOIiZ09W6pMPTHoTcih0"}}', 23)) (('writ', 0xc4200ea200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc4200ea200, 127), (b'{"Id":"","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 127)) (('read', 0xc4200ea200, 512), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","URL":"http://deb82e2e.ngrok.io","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"G4nIrca8GTvq4H62sTmqdb144FmhMgrg$U6TwkKWafv/3+bFM5AP7xIFfkWqx+HUsYWhkYXivrtMfcqan0mKZx99LHGI7mm5lOMmvI+Kdy7WF/GnwrMDXrRFwhYowczaWKRKnUimnNtndq7rdttMevFabwe5WSzwf+IZhWzQ2yvcW31+qVuS7F6uykUSw+mnBNtsdXFSNpToagqQOM66A8LT+l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ', 512)) (('read', 0xc4200ea200, 1024), (b'hhVDbeM2HP+qV6S5I="}}', 21)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('read', 0xc420148a00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148a00, 4), (b'\x00ys7', 4)) (('read', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('writ', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc4200ea200, 4), (b'\x00\x00\x00\x03', 4)) (('read', 0xc4200ea200, 8), (b'M\x00\x00\x00\x00\x00\x00\x00', 8)) (('read', 0xc4200ea200, 77), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","ClientAddr":"***.***.**.***:17815"}', 77)) (('read', 0xc4200ea200, 32768), (b'GET / HTTP/1.1\r\nHost: deb82e2e.ngrok.io\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 Midori/6\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru-RU\r\nX-Forwarded-For: ***.***.**.***\r\n\r\n', 359)) (('writ', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('writ', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc4200ea200, 32768), (b'', 0)) " WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0 $ EHrXSWq / السنة المالية / mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL / 3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE، (('writ', 0xc420326600, 4), (b'\x00\x00\x00\x00', 4)) (('writ', 0xc420148e00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420326600, 227), (b'{"Version":["2"],"ClientId":"","Extra":{"OS":"linux","Arch":"amd64","Authtoken":"3FjYRxVDd2QvNkX13h82k_6Thwfp93PUZEpsz3vYe5v","Version":"2.2.8","Hostname":"tunnel.us.ngrok.com","UserAgent":"ngrok/2","Metadata":"","Cookie":""}}\n', 227)) (('read', 0xc420326600, 512), (b'{"Version":"2","ClientId":"df05b949e58359ea6901cff60935531d","Error":"","Extra":{"Version":"prod","Cookie":"lh7YagbqJ9ixLYyE05ZDMPvaYNVm5isu$xF1Mp8fDc689269YUGlGNAV/0XRyrEH390rwGqILZqYS5+qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg+zrgnrW9cRNuO8ApSe2+OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh","AccountName":"\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9 \xd0\x9b\xd0\xb8\xd1\x81\xd0\xbe\xd0\xb2","SessionDuration":0,"PlanName":"Free"}}', 430)) (('read', 0xc420148a00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420148200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc420148200, 111), (b'{"Id":"","Proto":"https","Opts":{"Hostname":"","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 111)) (('read', 0xc420148200, 512), (b'{"Id":"39b1e32e134eff8671b02268945643f9","URL":"https://deb82e2e.ngrok.io","Proto":"https","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0$EHrXSWq/fY/mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL/3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE', 512)) (('read', 0xc420148200, 1024), (b'cOIiZ09W6pMPTHoTcih0"}}', 23)) (('writ', 0xc4200ea200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc4200ea200, 127), (b'{"Id":"","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 127)) (('read', 0xc4200ea200, 512), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","URL":"http://deb82e2e.ngrok.io","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"G4nIrca8GTvq4H62sTmqdb144FmhMgrg$U6TwkKWafv/3+bFM5AP7xIFfkWqx+HUsYWhkYXivrtMfcqan0mKZx99LHGI7mm5lOMmvI+Kdy7WF/GnwrMDXrRFwhYowczaWKRKnUimnNtndq7rdttMevFabwe5WSzwf+IZhWzQ2yvcW31+qVuS7F6uykUSw+mnBNtsdXFSNpToagqQOM66A8LT+l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ', 512)) (('read', 0xc4200ea200, 1024), (b'hhVDbeM2HP+qV6S5I="}}', 21)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('read', 0xc420148a00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148a00, 4), (b'\x00ys7', 4)) (('read', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('writ', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc4200ea200, 4), (b'\x00\x00\x00\x03', 4)) (('read', 0xc4200ea200, 8), (b'M\x00\x00\x00\x00\x00\x00\x00', 8)) (('read', 0xc4200ea200, 77), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","ClientAddr":"***.***.**.***:17815"}', 77)) (('read', 0xc4200ea200, 32768), (b'GET / HTTP/1.1\r\nHost: deb82e2e.ngrok.io\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 Midori/6\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru-RU\r\nX-Forwarded-For: ***.***.**.***\r\n\r\n', 359)) (('writ', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('writ', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc4200ea200, 32768), (b'', 0)) " G4nIrca8GTvq4H62sTmqdb144FmhMgrg $ U6TwkKWafv / (('writ', 0xc420326600, 4), (b'\x00\x00\x00\x00', 4)) (('writ', 0xc420148e00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420326600, 227), (b'{"Version":["2"],"ClientId":"","Extra":{"OS":"linux","Arch":"amd64","Authtoken":"3FjYRxVDd2QvNkX13h82k_6Thwfp93PUZEpsz3vYe5v","Version":"2.2.8","Hostname":"tunnel.us.ngrok.com","UserAgent":"ngrok/2","Metadata":"","Cookie":""}}\n', 227)) (('read', 0xc420326600, 512), (b'{"Version":"2","ClientId":"df05b949e58359ea6901cff60935531d","Error":"","Extra":{"Version":"prod","Cookie":"lh7YagbqJ9ixLYyE05ZDMPvaYNVm5isu$xF1Mp8fDc689269YUGlGNAV/0XRyrEH390rwGqILZqYS5+qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg+zrgnrW9cRNuO8ApSe2+OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh","AccountName":"\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9 \xd0\x9b\xd0\xb8\xd1\x81\xd0\xbe\xd0\xb2","SessionDuration":0,"PlanName":"Free"}}', 430)) (('read', 0xc420148a00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420148200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc420148200, 111), (b'{"Id":"","Proto":"https","Opts":{"Hostname":"","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 111)) (('read', 0xc420148200, 512), (b'{"Id":"39b1e32e134eff8671b02268945643f9","URL":"https://deb82e2e.ngrok.io","Proto":"https","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0$EHrXSWq/fY/mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL/3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE', 512)) (('read', 0xc420148200, 1024), (b'cOIiZ09W6pMPTHoTcih0"}}', 23)) (('writ', 0xc4200ea200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc4200ea200, 127), (b'{"Id":"","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 127)) (('read', 0xc4200ea200, 512), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","URL":"http://deb82e2e.ngrok.io","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"G4nIrca8GTvq4H62sTmqdb144FmhMgrg$U6TwkKWafv/3+bFM5AP7xIFfkWqx+HUsYWhkYXivrtMfcqan0mKZx99LHGI7mm5lOMmvI+Kdy7WF/GnwrMDXrRFwhYowczaWKRKnUimnNtndq7rdttMevFabwe5WSzwf+IZhWzQ2yvcW31+qVuS7F6uykUSw+mnBNtsdXFSNpToagqQOM66A8LT+l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ', 512)) (('read', 0xc4200ea200, 1024), (b'hhVDbeM2HP+qV6S5I="}}', 21)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('read', 0xc420148a00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148a00, 4), (b'\x00ys7', 4)) (('read', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('writ', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc4200ea200, 4), (b'\x00\x00\x00\x03', 4)) (('read', 0xc4200ea200, 8), (b'M\x00\x00\x00\x00\x00\x00\x00', 8)) (('read', 0xc4200ea200, 77), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","ClientAddr":"***.***.**.***:17815"}', 77)) (('read', 0xc4200ea200, 32768), (b'GET / HTTP/1.1\r\nHost: deb82e2e.ngrok.io\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 Midori/6\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru-RU\r\nX-Forwarded-For: ***.***.**.***\r\n\r\n', 359)) (('writ', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('writ', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc4200ea200, 32768), (b'', 0)) + IZhWzQ2yvcW31 + qVuS7F6uykUSw + mnBNtsdXFSNpToagqQOM66A8LT + l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ، (('writ', 0xc420326600, 4), (b'\x00\x00\x00\x00', 4)) (('writ', 0xc420148e00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420326600, 227), (b'{"Version":["2"],"ClientId":"","Extra":{"OS":"linux","Arch":"amd64","Authtoken":"3FjYRxVDd2QvNkX13h82k_6Thwfp93PUZEpsz3vYe5v","Version":"2.2.8","Hostname":"tunnel.us.ngrok.com","UserAgent":"ngrok/2","Metadata":"","Cookie":""}}\n', 227)) (('read', 0xc420326600, 512), (b'{"Version":"2","ClientId":"df05b949e58359ea6901cff60935531d","Error":"","Extra":{"Version":"prod","Cookie":"lh7YagbqJ9ixLYyE05ZDMPvaYNVm5isu$xF1Mp8fDc689269YUGlGNAV/0XRyrEH390rwGqILZqYS5+qDUNbMn2l4puKD2CJHAgI83yo49aopujf0uhPBm4t997BTBvpFSg+zrgnrW9cRNuO8ApSe2+OPpUuPK0GZYZ1bpbz7Pod7cJycwVIgDFZZXLxEeNdXylQxSax9YOxgxcHeLBa79OjqrJpEUUWYtTNiMa5wxkr0AwKh","AccountName":"\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9 \xd0\x9b\xd0\xb8\xd1\x81\xd0\xbe\xd0\xb2","SessionDuration":0,"PlanName":"Free"}}', 430)) (('read', 0xc420148a00, 4), (b'\xff\xff\xff\xff', 4)) (('writ', 0xc420148200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc420148200, 111), (b'{"Id":"","Proto":"https","Opts":{"Hostname":"","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 111)) (('read', 0xc420148200, 512), (b'{"Id":"39b1e32e134eff8671b02268945643f9","URL":"https://deb82e2e.ngrok.io","Proto":"https","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"WUiWWfM9kRbpFpXoEOCydiJdEob7BKN0$EHrXSWq/fY/mRDRSTNqkVWEVCDJUyBdMSU5uSEMH5RHq5D9W1gA1BTWTUEUbltyhQIlhTJvGxezhDeOYqGe5CwNFHnIOVNidToULds48FCVdWc0zRC3Djyack74P9mQ11VHKQKAXPzXUXlUbo6TRkwMWKrpN0q93pmL3fQamRP6cREZTl2YMdnFUZtwHwyh4LGacxGAvdCP867rTKBL/3eWLdkcF2lSPdHuH8V51RzCMWMIbvmtyySzE', 512)) (('read', 0xc420148200, 1024), (b'cOIiZ09W6pMPTHoTcih0"}}', 23)) (('writ', 0xc4200ea200, 4), (b'\x00\x00\x00\x01', 4)) (('writ', 0xc4200ea200, 127), (b'{"Id":"","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":""},"Extra":{"Balance":false,"Token":""}}\n', 127)) (('read', 0xc4200ea200, 512), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","URL":"http://deb82e2e.ngrok.io","Proto":"http","Opts":{"Hostname":"deb82e2e.ngrok.io","Auth":"","Subdomain":"","HostHeaderRewrite":false,"LocalURLScheme":""},"Error":"","Extra":{"Token":"G4nIrca8GTvq4H62sTmqdb144FmhMgrg$U6TwkKWafv/3+bFM5AP7xIFfkWqx+HUsYWhkYXivrtMfcqan0mKZx99LHGI7mm5lOMmvI+Kdy7WF/GnwrMDXrRFwhYowczaWKRKnUimnNtndq7rdttMevFabwe5WSzwf+IZhWzQ2yvcW31+qVuS7F6uykUSw+mnBNtsdXFSNpToagqQOM66A8LT+l3f3OOHKrWpdq39Bz2RfoRmXaRpkDrdfT6vPUQd6S8uVUnv3t2173Ik7AgT9PlzOMJ', 512)) (('read', 0xc4200ea200, 1024), (b'hhVDbeM2HP+qV6S5I="}}', 21)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x00ys7', 4)) (('read', 0xc420148a00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148a00, 4), (b'\x00ys7', 4)) (('read', 0xc420148e00, 4), (b'\x00ys7', 4)) (('writ', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('writ', 0xc420148a00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc420148e00, 4), (b'\x11|\xb9\x99', 4)) (('read', 0xc4200ea200, 4), (b'\x00\x00\x00\x03', 4)) (('read', 0xc4200ea200, 8), (b'M\x00\x00\x00\x00\x00\x00\x00', 8)) (('read', 0xc4200ea200, 77), (b'{"Id":"9714ddd4cb111adf6599f099cec98482","ClientAddr":"***.***.**.***:17815"}', 77)) (('read', 0xc4200ea200, 32768), (b'GET / HTTP/1.1\r\nHost: deb82e2e.ngrok.io\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15 Midori/6\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru-RU\r\nX-Forwarded-For: ***.***.**.***\r\n\r\n', 359)) (('writ', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148a00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('read', 0xc420148e00, 4), (b'\x0e\xb2\xc0\x01', 4)) (('writ', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('writ', 0xc420148a00, 4), (b'X\xa3?+', 4)) (('read', 0xc420148e00, 4), (b'X\xa3?+', 4)) (('read', 0xc4200ea200, 32768), (b'', 0)) 

من هذا التفريغ يمكنك أن ترى بوضوح الهيكل الداخلي للبروتوكول:


  • من الواضح أن تدفقات إنشاء التخويل وإنشاء الأنفاق بواسطة العميل ، ويتم بدء التدفقات مع الاتصالات نفسها بواسطة الخادم. هذا ليس في السجلات ، ولكن من الواضح لأسباب المنطق السليم.
  • في بداية كل تيار ، يتم إرسال رقم 32 بت - نوع الدفق. هذا هو 0 للترخيص و 1 لإنشاء نفق و 3 للاتصالات الواردة.
  • دفق مع نوع -1 نبضات. يرسل بادئ الاتصال بشكل دوري 4 بايت عشوائي ويتوقع استلامها عند الإخراج. هناك 2 هذه التدفقات في كلا الاتجاهين.
  • عند تلقي اتصال وارد ، يتم إرسال نوع 32 بت 3 ورقم 64 بت L (endian القليل) وكائن JSON بطول L L يصف الاتصال. بعد ذلك ، يتم نقل البيانات الخام عبر الاتصال دون أي حزم الخدمة.

استنتاج


نظرًا لأن muxado مكتبة مفتوحة المصدر ، يمكن تعلم بروتوكول تعدد الإرسال من المصدر . إحضاره هنا لا معنى له.

وكانت النتيجة مكتبة Python للعمل مع بروتوكول ngrok ، وعميل بديل لوحدة التحكم باستخدام هذه المكتبة. جيثب

PS النقد البناء هو موضع ترحيب.

Source: https://habr.com/ru/post/ar485564/


All Articles