Ir para conteúdo

Vacina: Vírus atalho


Aof

Posts Recomendados

 

Fiz esse script em Python, pra automatiza o processo de remoção worm que se replica em diversos hardwares HDs e PenDrives.

podem dar dicas sugestivas para haver uma melhora significativa no mesmo, afinal não e só meu script e nosso a parti de agora. heheheh

atenção: essa vacina apenas apaga o arquivo infectado dentro do windows. Ainda não  limpa pendrives.

 

abraço a todos.

import os


def Deleta_Worm():
	username = os.environ['username'] ##pega o nome do usuario logado e armazena na variavel 'username'.
	path = "C:\\Users\\"+username+"\\AppData\\Roaming\\" ## caminho onde o worm esta localizado, a variavel 'username' e utilizada pelo fato de haver diferentes nomes de usuarios.
	pasta = ""

	##seta o local do virus com variavel 'path'
	os.chdir(path)


	diretorio = []

	for p in os.listdir(): ##lista pastas
		diretorio.append(p) ## add as pasta a list diretorio
		for d in diretorio:  ## percorrer a lista diretorio
			pasta = d ##pasta recebe valor de diretorio
			os.chdir(path+pasta) ##seta novo caminho, com a cocatenaçao das varias path e pasta
			for file in os.listdir(): ## Dentro da nova pasta lista todos arquivos
				f = file.split('.') 	##divide arquivos com . ex: virus.exe = 'virus' . 'exe'
				try:
					##primeira verificaçao a preocura da extencao js																				
																									##  0 pos    1 pos
					if f[1] == "js": ## se a segunda posiçao de f e igual a js, encontrou o virus. ex: 'virus' , 'exe'
						deletefile = "del " + file ## variavel deletefile recebe a cancatenaçao, ex: "del virus.exe" 
						print(deletefile) ## mostra o arquivo a ser deletado
						os.system(deletefile) ## deleta o arquivo
						for ff in os.listdir(): 	#lista arquivos da pasta do virus
							s = ff.split('.')	## divide novamente
							try: ## tenta os argumentos abaixo
								##segunda verificaçao dentre da pasta do virus
								if s[1] == "exe": 
									deletefile = "del " + ff
									print(deletefile)
									os.system(deletefile)
							except IndexError: ## se for encontrado uma pasta, da IndexError e vai da pass nessa pasta
											   ## e continuar a localizaçao de arquivo com extençao
								pass
						print("\n\n Worm Removido com sucesso. Reinicie o pc.")
						os.system("pause > null")
						break
				except IndexError:
					pass





result = os.system('taskkill /T /F /IM wscript.exe ') ##finaliza o processo e retorna um valor inteiro
## taskkill 	  finaliza processo do windows
## /t     		  Finaliza o processo e o filhos do mesmo
## /f    		  Força a finalização 
## /IM 			  Especifica o nome do processo a ser finalizado.
## wscript.exe 	  programa padrao do windows para execuçao de script javascrip


if result != 0:##verificaçao se wscript esta rodando no windows.
	## se o wscript nao estiver rodando no windows.
	print("Nenhum processo Malicioso foi encontrado!") 
	os.system("pause > null")
	exit()
else:##se o wscript estiver rodando
	Deleta_Worm()##chama a  funcao para deleta o worm





			

 

Link para o comentário
Compartilhar em outros sites

olá @Aof tudo bem!?

Seria interessante melhorar o nome das tuas variáveis para perceber melhor !?

Outra questão e desculpa a minha ignorância( eu já não me lembro da ultima vez que usei windows não conheço os comandos), mas o que "taskkill /T /F /IM wscript.exe", faz?, a minha duvida tem a ver com estes "/T /F /IM".

Outra coisa, esse executável "wscript.exe", é um arquivo especifico? (se sim onde baixar?), preciso executar ele durante os testes?, ou é apenas para exemplo?

Abraço :) 

Link para o comentário
Compartilhar em outros sites

Tudo bem, 

 Caro @gnoo  documentei todo o script para facilita o intendimento de todos.

respondendo suas perguntas.

taskkill   Programa padrão para finaliza processo do windows

parâmetros
/t     	 Finaliza o processo e os filhos do mesmo
/f    	 Força a finalização 
/IM 	 Especifica o nome do processo a ser finalizado.


wscript.exe  Programa padrão do windows para execução de script javascript 

Obrigado pelo feedback.

abraço. 

Link para o comentário
Compartilhar em outros sites

@Aof o código fico bom,

sabes onde posso arranjar um virus, coisa básica, que faça uso do wscript.exe,  para ver como ele funciona?

Eu preciso ver esse processo a decorrer no sistema, à alguma coisa na tua lógica que eu não estou a perceber, tu começas a tentar terminar um processo que eventualmente está a decorrer no sistema sem antes ver se ele está ativo, há alguma razão para isso?

Mesmo depois de "finalizar o processo" e enviar uma mensagem a dizer que nada foi encontrado, continuas à procura nos directórios por um suposto arquivo .exe e .js.

Uma questão, porquê que estás a ir neste caminho em especifico?

"C:\\Users\\"+username+"\\AppData\\Roaming\\"

Se souberes de algum virus desse para eu executar numa vm e ver como os processos decorrem, deixa ai link para baixar.

abraço. :)

Link para o comentário
Compartilhar em outros sites

Obrigado pelo feedback @gnoo.

fiz alguns novos comentários e modificações no código.

respondendo sua duvida: esse caminho é o local onde o worm esta localizado no sistema, a variável username  é  utilizada para armazena o nome do usuário logado no sistema, fazendo com que este código rode em qualquer maquina, seja qual for o nome de usuário.

"C:\\Users\\"+username+"\\AppData\\Roaming\\"

 

Eu tenho sample dele, só que não sei se é permitido compartilha link de virus real aqui no forum.

abraço.

  

 

Link para o comentário
Compartilhar em outros sites

Não testei direito, mas acredito que a parte da exclusão dos arquivos possa ser feito +- desta forma

 

import subprocess
import re

malware_ext = ['.js']
malware_ext2 = ['.exe']
paths = ["%appdata%"]

for path in paths:
    for malware in malware_ext:
        result = subprocess.getoutput('del /s /f /q "{path}"\*{ext}'.format(path=path, ext=malware))
        if not "*" in result:
            malware_paths = list(set(re.findall('(C\:.*\\\)', result)))
            if malware_paths:
                for malware_path in malware_paths:
                    for malware2 in malware_ext2:
                        subprocess.getoutput('del /s /f /q "{path}"\*{ext}'.format(path=malware_path, ext=malware2))
        else:
            print("Nenhum arquivo infectado")


* A ideia principal é permitir algo mais escalável, pois basta adicionar novas extensões ou paths na lista e o código fará o processo de busca e remoção utilizando os critérios do código original. Entretanto, o processo de remoção parece um tanto quanto perigoso já que exclui arquivos com base somente na extensão, isso em um ambiente real poderia causar problemas... 

** Não postei nada sobre a parte do script, mas acredito que possa ser substituída essa parte 

result = os.system('taskkill /T /F /IM wscript.exe ') ##finaliza o processo e retorna um valor inteiro

por esta 

result =  subprocess.getoutput('taskkill /T /F /IM wscript.exe ') ##finaliza o processo e retorna um valor inteiro

ou algo parecido na lib subprocess, assim podemos evitar o carregamento de mais um módulo

No comando taskskill em si, temos um problema semelhante ao de sair excluindo dados com base na extensão. Neste caso o comando encerra processos que estejam usando o wscript, e isso pode causar danos também em um ambiente real

Link para o comentário
Compartilhar em outros sites

Saudações,

venho aqui deixar o meu contributo para o código do @Aof.

@Fernando Mercês se calhar era interessante abrir um desafio para explorar este virus, especialmente como, trabalhar a ofuscação do código.

 

@Aof  acho que devias criar um repositório para quem quer fazer a sua contribuição para a "vacina" que tu tanto procuras, e talvez ficasse este tópico para discussão.  Eu não continuei este código porque não tenho tempo para fazer isto sozinho neste caso a contribuição de todos, é bem vinda.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                requirements.txt

re
os
psutil
prettytable

vacina.py                                                                                                                                                                                                                                                                                                                                                                   

import os
import re
import psutil
from prettytable import PrettyTable




class Monitor_de_Processos(object):
    def __init__(self):

        self.padrao_regex = re.compile(r'wscript.exe')


    def procura_info_processo_decorrer_sistema(self):
        for processo in psutil.process_iter():
            try:
                codigo_execucao = 0
                atributos_processo = processo.as_dict(attrs=['pid','name','username']) #Devolve dicionario com info do processo wscript.exe(pid , name, username)
                if self.padrao_regex.match(atributos_processo['name']): #Expressão regular para encontrar processo wscript.exe no resultado da linha anterior
                    return atributos_processo['pid'], atributos_processo['name'], atributos_processo['username'], codigo_execucao  # retorna info do dicionário
            except:
                # Se o processo wscript.exe não estiver ativo o programa sai no ultimo ( except ) no fim do código
                pass
            
    def info_processo_descendente(self, processo_id):
        numero_key = 0
        lista_processos_child = {}
        for x in psutil.Process(processo_id).children():# Verifica processos child
            """
             A variável (numero_key) com valor zero aparece porque o dicionário (lista_processos_child)
             recebe o valor de X também enquanto dicionário, uma vez que as keys do dicionário (pid,name)
             são constantes, e em python os dicionários quando recebem Keys iguais às que já lá se encontram,
             a cada update são subscritas as keys anteriores com o mesmo nome, ficando apenas a ùltima key e o seu valor, a entrar.
             Usei a variável (numero_key) a incrementar a cada iteração para criar um dicionário aninhado, assim
             é criado uma key com número 1 que recebe como valor o dicionario de x... esse valor é incrementado a cada itereção
             dependendo do número de processos filho encontrados, assim sendo todos os processos são adicionados ao dicionário e nenhum
             é subscrito.
            """
            numero_key += 1
            lista_processos_child[numero_key] = (x.as_dict(attrs=['pid','name']))# Dicionário lista_processos_child, recebe valor de x como dicionário
                                                                                 # ficando dicionários aninhados
        return lista_processos_child, numero_key 

    # Esta função testa se os processos child do prcesso wscript.exe, têm processos descendentes
    def descendente_processo_descendente(self, descendente_processo_id):
        numero_key = 0
        child_processos_child = {}
        for x in psutil.Process(descendente_processo_id).children():
            numero_key += 1
            child_processos_child[numero_key] = (x.as_dict(attrs=['pid','name']))
            
        return child_processos_child, numero_key    
        
    def termina_processos(self, atributos_processo_id):   
        wscript_id = psutil.Process(atributos_processo_id) #Identifica processo wscript.exe
        for child in wscript_id.children(recursive=True):
            child.kill() # Termina processos filho antes de terminar processos wscript.exe
        wscript_id.kill() # Termina processo wscript.exe




class Gestor_de_Ficheiros(object):

    #def __init__(self):

    #    self.extencao_exe = '.exe'
    #    self.extencao_js = '.js'
    #    self.extencao_txt = '.txt'

    def localiza_ficheiros_diretorios_childs(self, processo_child):
        """
        ESTA FUNÇÃO NECESSITA SER TRABALHADA MEDIANTE CONCLUSÕES FUTURAS SOBRE O COMPORTAMENTO DOS PROCESSOS DETETADOS...
        Os agurmento que esta função recebe estão armazenados na lista ( lista_ficheiros_localizar),
        são os childs do processo wscript.exe...
        
        ATENÇÃO: (Aparentemente) O mesmo ficheiro dá origem a dois processos diferentes a trabalhar em simultâneo,
        essa é a razão pela qual a lista contém dois processos com o mesmo nome.

        O RESULTADO DESTA FUNÇÃO DUPLICA O MESMO RESULTADO, DEVE SER CONSIDERADA UMA SOLUÇÃO PARA ESSE EFEITO.
        
        """
        
        for root,diretorios,ficheiros in os.walk("c:\\"):
            for ficheiros in ficheiros:
                if ficheiros == processo_child:
                    print("Caminho para ficheiro\n-> ",os.path.join(root,ficheiros)) # Devolve a localização do ficheiro child de wscript.exe
                    """
                    A linha que segue deve ser tida em conta na altura de fazer a função que elemina a pasta que contém
                    os ficheiros que devem ser eleminados.
                    """
                    # Devove o nome do diretório onde se encontra o ficheiro child anterior
                    print("Diretório onde se situa o ficheiro\n-> ",os.path.basename(os.path.dirname(os.path.join(root,ficheiros))))                       
        
        

        
        
    def elemina_ficheiros_e_diretorios(self, nome_ficheiro, nome_diretorio):
        """
        Esta função deve ser feita depois de perceber que ficheiros são gerados
        e onde estão localizados no sistema.

        ATENÇÃO: Os parâmetros desta função não devem ser considerados, são apenas considerações
        para alterações futuras.
        """
        pass
        

def obter_resposta_utilizador(pergunta):
    while True:
        resposta = input(pergunta).strip().lower()
        # Se a resposta for "s" termina processos filho e processo pai
        if resposta  == 's':
            Monitora_processo.termina_processos(atributos_processo_id)
            print("Processos Terminados!")
            break
        # Se resposta for "n" termina o programa, processos continuam ativos
        elif resposta == 'n':
            print("Programa terminado pelo utilizador, processos continuam ativos...")
            break
        else:
            print("Resposta de ser s/n...")
    
   
if __name__ == '__main__':

    Monitora_processo = Monitor_de_Processos() # Inicia Objecto
    Gestor_ficheiros = Gestor_de_Ficheiros()

    lista_ficheiros_localizar = [] # Recebe nome dos processos (ficheiros), para apagar

    # PrettyTable é uma biblioteca que posiciona, valores em células("Planilhas") 
    
    tabela_processo = PrettyTable() 
    tabela_processo.field_names = ["Nome Proc.", "Proc ID", "Usuário"]

    tabela_processo_child = PrettyTable()
    tabela_processo_child.field_names = ["Proc. child", "child ID", "  ", "Nome Proc.", "Proc ID"]

    tabela_child_processo_child = PrettyTable()
    tabela_child_processo_child.field_names = ["Proc. child", "child ID", "  ", "Proc. descendente de child", "descendente ID"]


    try:
        atributos_processo_id, atributos_processo_name, atributos_processo_username, codigo_execucao = Monitora_processo.procura_info_processo_decorrer_sistema()

        lista_processos_child, numero_key = Monitora_processo.info_processo_descendente(atributos_processo_id)

        

        
        if codigo_execucao == 0:
             
            tabela_processo.add_row([atributos_processo_name, atributos_processo_id, atributos_processo_username])

            for child in lista_processos_child:
                lista_ficheiros_localizar.append(lista_processos_child[child]['name'])
                tabela_processo_child.add_row([lista_processos_child[child]['name'], lista_processos_child[child]['pid'], " de ", atributos_processo_name, atributos_processo_id])
                
                
            try:
                for child_id in lista_processos_child:
                    child_processos_child, _ = Monitora_processo.descendente_processo_descendente(lista_processos_child[child_id]['pid'])
                    
                    if len(child_processos_child) == 0:
                        tabela_child_processo_child.add_row([lista_processos_child[child_id]['name'], lista_processos_child[child_id]['pid'], "  ",
                                                                                                                                 "NÃO EXISTE", "---"])
                    else:
                        
                         tabela_child_processo_child.add_row([lista_processos_child[child_id]['name'], lista_processos_child[child_id]['pid'], "  ",
                                                             child_processos_child[child_id]['name'], child_processos_child[child_id]['pid']  ])
            except:
                pass

        
              
            print(tabela_processo)
            print(tabela_processo_child)
            print(tabela_child_processo_child)
            
            for processo_child in lista_ficheiros_localizar:
                Gestor_ficheiros.localiza_ficheiros_diretorios_childs(processo_child) 

            # A ação da linha que segue, mediante a resposta do utilizador,
            # está posicionada na função (obter_resposta_utilizador)   
            obter_resposta_utilizador("Queres terminar processos e apagar os ficheiros?[s/n] ")
  
            
        
    except :
        print("Processo wscript.exe não foi encontrado")

Link para o comentário
Compartilhar em outros sites

@Aof Obrigado pelo apoio,

esse script do ponto de vista técnico, não está grande coisa, eu fiz esse código quando tinha 5 min. disponiveis do meu dia a dia e fui montando o código sem estar preocupado com a parte tecnica ma sim a informação que poderia ser manipulada através dele, afinal é apenas um script que está numa fase inicial.

Não saber programação orientada a objetos não é grave, uma vez que já tens conhecimentos de python e vontade de aprender, se gastares um mês de volta dos conceitos básicos da POO vais ter conhecimentos para começar a desenvolver as tua proprias coisas.

De inicio eu pensei em meter o objeto  Gestor_de_Ficheiros a receber como herança os atributos e métodos do Monitor_de_processos... mas depois decidi não fazer para ficar mais simples para quem vai ler, especialmente se não tem conhecimentos sobre POO.

Eu resolvi fazer o código desta forma porque a abordagem de estar a abrir processos e subprocessos nesta situação não é interessante especialmente quando tens que estar a analisar o comportamento do virus, processos gerados, ficheiros gerados, esses subprocessos são interessantes quando queremos realizar uma tarefa muito especifica em que biblioteca que estas a trabalhar não consegue chegar lá e resolver.

Eu acho que devias criar tu o repositório uma vez que o desafio foi criado por ti, e uma vez que a tua àrea de interesse é análise de malware devias tentar tratar a ofuscação do código do virus que mandas-te e perceber que àreas do sistema são afetadas entre outras coisas, era um bom contributo para a criação da tua vacina.

Abraço.

Link para o comentário
Compartilhar em outros sites

Seguindo a sugestão e dando logo meus agradecimentos ao @gnoo, criei o repositorio da nossa vacina que está em fase inicial no github. Em questão a ofuscação do código estudarei mas sobre ele.

https://github.com/thebinario/Vacina_Bondat

@Fernando Mercês fiz até uma homenagem a comunidade "mentebinaria" como vcs podem ver no link "thebinario". heheh

 

abraco.

Aof

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...