## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'faraday' class MetasploitModule < Msf::Auxiliary def initialize super( 'Name' => 'Telegram Message Client', 'Description' => %q{ This module can be used to send a document and/or message to multiple chats on telegram. Please refer to the module documentation for info on how to retrieve the bot token and corresponding chat ID values. }, 'Author' => [ 'Ege Balcı ', # Aka @egeblc of https://pentest.blog 'Gaurav Purswani' # @pingport80 ], 'License' => MSF_LICENSE, ) register_options( [ OptString.new('BOT_TOKEN', [true, 'Telegram BOT token', '']), OptString.new('MESSAGE', [false, 'The message to be sent']), OptInt.new('CHAT_ID', [false, 'Chat ID for the BOT', '']), OptPath.new('DOCUMENT', [false, 'The path to the document(binary, video etc)']), OptPath.new('IDFILE', [false, 'File containing chat IDs, one per line']), OptEnum.new('FORMATTING', [false, 'Message formatting option (Markdown|MarkdownV2|HTML)', 'Markdown', [ 'Markdown', 'MarkdownV2', 'HTML']]) ], self.class ) end def formatting datastore['FORMATTING'] end def message datastore['MESSAGE'] end def document datastore['DOCUMENT'] end def bot_token datastore['BOT_TOKEN'] end def id_file datastore['IDFILE'] end def send_document(conn, chat_id) unless ::File.file?(document) && ::File.readable?(document) fail_with(Failure::BadConfig, 'The document to be sent does not exist or is not a readable file!') end raw_params = { 'chat_id' => chat_id, 'document' => Faraday::UploadIO.new(document, 'application/octet-stream') } params = {} raw_params.each_with_object({}) do |(key, value), _tmp_params| params[key] = value end response = conn.post("/bot#{bot_token}/sendDocument", params) if response.status == 200 print_good("Document sent successfully to #{chat_id}") elsif response.status == 403 print_bad("Error while sending document! Make sure you have access to message chat_id : #{chat_id}") else print_bad("Error while sending the document to #{chat_id} API Status : #{response.status}") end end def send_message(conn, chat_id) params = { 'chat_id' => chat_id, 'text' => message, 'parse_mode' => formatting } response = conn.post("/bot#{bot_token}/sendMessage", params) if response.status == 200 print_good("Message sent successfully to #{chat_id}") elsif response.status == 403 print_bad("Error while sending document! Make sure you have access to message chat_id : #{chat_id}") else print_bad("Error while sending the message to chat_id #{chat_id} API Status : #{response.status}") end end def run unless document || message fail_with(Failure::BadConfig, 'You must supply a message and/or document') end url = 'https://api.telegram.org' conn = Faraday.new(url: url) do |faraday| faraday.request :multipart faraday.request :url_encoded faraday.adapter Faraday.default_adapter end if id_file print_warning("Opening `#{id_file}` to fetch chat IDs...") unless ::File.file?(id_file) && ::File.readable?(id_file) fail_with(Failure::BadConfig, 'The ID file is not an existing readable file!') end File.readlines(id_file).each do |chat_id| send_document(conn, chat_id) if document send_message(conn, chat_id) if message end return end send_document(conn, datastore['CHAT_ID']) if document send_message(conn, datastore['CHAT_ID']) if message end end