Jump to content

Vacina: Vírus atalho


Aof

Recommended Posts

 

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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...