Jump to content

[Resolvido] Tempo de execução de outros programas


Muryllo
 Share

Recommended Posts

Boas pessoal, não estou conseguindo fazer com que minha aplicação pegue o tempo em que cada processo está aberto no computador em segundos.

abaixo está o código :

Public Sub GetMemoryApplicationRuntime(ByVal Service As String, ByVal Section As String)
 On Error Resume Next
 Do
	 System.Threading.Thread.Sleep(1000)
	 System.GC.Collect()
	 Dim programas As Process() = Process.GetProcesses
	 Dim arquivo As FileInfo
	 For Each x In programas
		 Dim valor As String
		 Dim segundovalor As Integer = 0
		 arquivo = New FileInfo(x.MainModule.FileName)
		 valor = Read_File(Service, Section, arquivo.FullName, "")
		 If valor = "" Then
			 segundovalor = 0
			 segundovalor += Convert.ToInt32(valor)
			 segundovalor += 1
			 Write_File(Service, Section, arquivo.FullName, segundovalor)
		 Else
			 segundovalor = 0
			 segundovalor += Convert.ToInt32(valor)
			 Dim processo As Process() = Process.GetProcessesByName(x.ProcessName)
			 If processo.Length > 1 Then
				 segundovalor += (1 / processo.Length)
				 Write_File(Service, Section, arquivo.FullName, segundovalor)
			 Else
				 segundovalor += 1
				 Write_File(Service, Section, arquivo.FullName, segundovalor)
			 End If
		 End If

	 Next
 Loop
End Sub

Meu objetivo é descobrir o tempo a que os processos estão a funcionar, eles precisam ser em segundos. O código aparenta erro na hora de contar, ele grava no arquivo INI com excesso os processos chrome etc que são executados várias vezes.

Edited by apocsantos
geshi
Link to comment
Share on other sites

Não devias usar o "On Error Resume Next", aprende a fazer as coisas em condições... o que estás a fazer não têm mt sentido, qual é objetivo?

Não vais ter acesso a todos os processos, devias pelo menos excluir os de sistema, se a tua aplicação for de 32-bit não terás acesso a processos 64-bit quando executares a propriedade MainModule.Filename.

O que é que o Read_FIle e Write_File faz? Como é que estás a obter o tempo de execução dos processos? Não vejo isso aqui.

E por favor, apaga também o Do Loop e tenta fazer ou com um timer ou de outra maneira.

Link to comment
Share on other sites

Boas He B Te My,

O objetivo é descobrir quanto tempo o processo está ativo desde a execução do meu código, o tempo deve ser dado em segundo. Quanto a Read_File e Write_File são funções de ler e escrever arquivos INI que eu inclui na biblioteca de vínculo dinâmico junto a função.

Eu utilizo o "On Error Resume Next" Pois como você mesmo disse, alguns processos não podem ser usados os métodos que foram passados no código, então ele continua com a execução dos outros, mas mesmo assim é quase que impossível isso acontecer já que a dll será usada por um Serviço com a conta do SISTEMA, eu também gosto de utilizar algumas Constantes de permissões para APIs RtlAdjustPrivilege.

O Do Loop serve para fazer o loop e contar o tempo em que eles estão sendo utilizados (o tempo dos processos). Não posso utilizar Timer porque estou colocando o código em uma dll, o objetivo de tudo isso que eu estou a fazer é uma capacidade de detecção heurística que estou a criar para o meu antivírus feito em C# e VB.NET.

No total são 5 funções básicas de heurística, 2 de análise e 1 de julgamento. Essa é uma das 5 funções de heurística, ela serve para criar um arquivo INI contendo o tempo que cada processo está sendo executado, quanto menor for o tempo, maior a heurística, ou seja, a função de julgamento irá tratar isso com cautela.

No final da análise ele deve retornar um valor de cada processo em execução, como se fosse um tipo de Nota em que a maior nota é o arquivo suspeito pelo antivírus. É quase como uma função em que retorna o nome de um processo que o antivírus julga ser nocivo.

Abraços.

Edited by Muryllo
Link to comment
Share on other sites

Threading.Sleep num antivírus?

E nesse caso, porque estás a fazer GC.Collect se é para uma dll?

Quanto a acederes aos processos, ao processo "System" com o identificador (PID) 4 (pelo menos no Vista e 7) nunca terás acesso, por isso deverias lidar melhor com erros na minha opinião.

Tás a tentar obter o tempo de execução do processo DEPOIS de a rotina que falas-te começar? Ou o tempo de execução total do processo?

E porque não podes usar um timer a 1 segundo ? Visto que estás a usar o Sleep com 1segundo também, só que o Sleep não te garante o resumo do thread, enquanto um timer poderia ser melhor na minha opinião visto que poderias apagar esse Loop.

Isto claro se o processo que estiveres a fazer não for demorado nessa rotina ao ponto de ultrapassares 1segundo, porque aí já irias tar a chamar mais que uma vez a rotina e no teu caso não sei se querias isso, mas é uma questão de testares...

Link to comment
Share on other sites

Threading.Sleep num antivírus?

E nesse caso, porque estás a fazer GC.Collect se é para uma dll?

Quanto a acederes aos processos, ao processo "System" com o identificador (PID) 4 (pelo menos no Vista e 7) nunca terás acesso, por isso deverias lidar melhor com erros na minha opinião.

Tás a tentar obter o tempo de execução do processo DEPOIS de a rotina que falas-te começar? Ou o tempo de execução total do processo?

E porque não podes usar um timer a 1 segundo ? Visto que estás a usar o Sleep com 1segundo também, só que o Sleep não te garante o resumo do thread, enquanto um timer poderia ser melhor na minha opinião visto que poderias apagar esse Loop.

Isto claro se o processo que estiveres a fazer não for demorado nessa rotina ao ponto de ultrapassares 1segundo, porque aí já irias tar a chamar mais que uma vez a rotina e no teu caso não sei se querias isso, mas é uma questão de testares...

Sim a questão é que eu sinto mais segurança em Thread.Sleep do que com timer e além disso, faz na minha opinião a mesma coisa que o timer. Vou precisar de loop do mesmo jeito, então ... O System.GC.Collect está sendo usado estaticamente pela aplicação que faz o import da dll, eu uso muito isso quando se trata de Loop.

Os Processos System (PID 4) Que é o NTOSKRNL.EXE, na verdade eles nem entram na lista dos processos, e se entrarem são ignorados. o tempo de execução que eu quis dizer é DEPOIS da rotina que começo, não da execução total do processo.

Eu pensei várias vezes nessa sua última afirmação, todos pensam assim hahaha. A Rotina não demora mais do que milionésimos de segundos, não passa de 1 segundo. Estava refazendo essa função e entrou na minha cabeça de que tem como fazer isso usando a hora do computador, por exemplo : Pega a hora agora sendo HH:MM:SS e salva no arquivo ini :

[Heuristic_Runtime]

C:\WINDOWS\System32\taskmgr.exe=HH:MM:SS

A ideia é ficar assim, então eu faço uma comparação para ler se já foi dado a hora do runtime de acordo com a rotina e então eu subtraio da hora atual para receber uma nova resposta e convertê-la em segundos, mas não faço ideia de como criar isso. Talvez com Loop, Antes do loop eu pré-defina uma hora que o módulo heurístico julga ele estar em funcionamento então ele ficará lá, depois é só ficar subtraindo isso pela hora atual e dará oque eu quero, talvez assim.

Eu também tinha esquecido, quando o módulo heurístico retornar o HWND (Handle) do processo suspeito, eu usarei isso junto com 2 Funções da mesma DLL que servem para ordenar o processador a parar totalmente todas as threads do programa suspeito. (Parar, não finalizar) Então aparecerá na tela do usuário um alerta com 3 botões (Bloquear, Permitir, Cancelar)

Edited by Muryllo
Link to comment
Share on other sites

Simples, depois que ele retornar o HWND do processo suspeito, já era. É só comparar com o HWND de todos os processos, depois ele vai retornar o nome do processo, eu pego o nome, paro todas as threads do processo, e aguardo a decisão do usuário sobre o destino do arquivo.

Public Declare Auto Function SuspendThread Lib "KERNEL32.DLL" (ByVal HWND_Thread As IntPtr) As UInteger
   Public Declare Auto Function ResumeThread Lib "KERNEL32.DLL" (ByVal HWND_Thread As IntPtr) As UInteger
   Public Declare Auto Function OpenThread Lib "KERNEL32.DLL" (ByVal DwDesiredAccess As ThreadAccess, ByVal BInheritHandle As Boolean, ByVal DwThreadID As UInteger) As IntPtr
   Public Declare Auto Function CloseHandle Lib "KERNEL32.DLL" (ByVal HWND_Handle As IntPtr) As Boolean
   Public Declare Auto Function GetPrivateProfileString Lib "KERNEL32.DLL" (ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpDefaut As String, ByVal lpReturnedString As System.Text.StringBuilder, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
   Public Declare Auto Function WritePrivateProfileString Lib "KERNEL32.DLL" (ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpString As String, ByVal lpFileName As String) As Integer
   Private Sub Write_File(ByVal File As String, ByVal Section As String, ByVal Key As String, ByVal Standard_Value As String)
    WritePrivateProfileString(Section, Key, Standard_Value, File)
   End Sub
   Private Function Read_File(ByVal File As String, ByVal Section As String, ByVal Key As String, ByVal Standard_Value As String) As String
    On Error Resume Next
    Dim String_Builder As New System.Text.StringBuilder(500)
    GetPrivateProfileString(Section, Key, Standard_Value, String_Builder, 500, File)
    Return String_Builder.ToString
   End Function
   Public Enum ThreadAccess As Integer
    TERMINATE = 1
    SUSPEND_RESUME = 2
    GET_CONTEXT = 8
    SET_CONTEXT = 16
    SET_INFORMATION = 32
    QUERY_INFORMATION = 64
    SET_THREAD_TOKEN = 128
    IMPERSONATE = 256
    DIRECT_IMPERSONATION = 512
   End Enum
   Public Sub ResumeProcess(ByVal Process As System.Diagnostics.Process)
    For Each T As ProcessThread In Process.Threads
	    Dim Thread As IntPtr
	    Thread = OpenThread(ThreadAccess.SUSPEND_RESUME, False, T.Id)
	    If Thread <> IntPtr.Zero Then
		    ResumeThread(Thread)
		    CloseHandle(Thread)
	    End If
    Next
   End Sub
   Public Sub SuspendProcess(ByVal Process As System.Diagnostics.Process)
    For Each T As ProcessThread In Process.Threads
	    Dim Thread As IntPtr
	    Thread = OpenThread(ThreadAccess.SUSPEND_RESUME, False, T.Id)
	    If Thread <> IntPtr.Zero Then
		    SuspendThread(Thread)
		    CloseHandle(Thread)
	    End If
    Next
   End Sub
Public Sub GetMemoryApplicationRuntime(ByVal Service As String, ByVal Section As String)
    On Error Resume Next
    Dim Kernel_Applications As Process() = Process.GetProcesses
    Dim Kernel_File_Info As FileInfo
    Dim Kernel_Runtime As Integer = 0
    For Each Application_Runtime In Kernel_Applications
	    Dim Hours As Integer = Date.Now.Hour
	    Dim Minutes As Integer = Date.Now.Minute
	    Dim Seconds As Integer = Date.Now.Second
	    Dim Memory_Primary As Integer = (Hours * 60)
	    Dim Memory_Secondary As Integer = (Memory_Primary + Minutes)
	    Dim Memory_Tertiary As Integer = (Memory_Secondary * 60)
	    Dim Memory_Result As Integer = (Memory_Tertiary + Seconds)
	    Kernel_File_Info = New FileInfo(Application_Runtime.MainModule.FileName)
	    Kernel_Runtime = Memory_Result
	    Write_File(Service, Section, Kernel_File_Info.FullName, Memory_Result)
    Next
    Do
	    System.GC.Collect()
	    System.Threading.Thread.Sleep(5000)
	    Dim Kernel_Process As Process() = Process.GetProcesses
	    For Each Application_Runtime In Kernel_Process
		    Dim Hours As Integer = Date.Now.Hour
		    Dim Minutes As Integer = Date.Now.Minute
		    Dim Seconds As Integer = Date.Now.Second
		    Dim Memory_Primary As Integer = (Hours * 60)
		    Dim Memory_Secondary As Integer = (Memory_Primary + Minutes)
		    Dim Memory_Tertiary As Integer = (Memory_Secondary * 60)
		    Dim Memory_Result As Integer = (Memory_Tertiary + Seconds)
		    Kernel_File_Info = New FileInfo(Application_Runtime.MainModule.FileName)
		    If Read_File(Service, Section, Kernel_File_Info.FullName, Nothing) = Nothing Then
			    Write_File(Service, Section, Kernel_File_Info.FullName, Memory_Result)
		    End If
	    Next
    Loop
   End Sub

Eu verifiquei aqui com um programa de teste, não entrou System na lista, aliás eu verifiquei ele com o serviço, mandei ele escrever o nome de todos os processos em um INI e nada. Acho que System não entra na lista.

Link to comment
Share on other sites

Então temos um problema, se o processo System realmente entra na lista, então isso é uma questão de privilégios do programa que faz o host da dll. Como eu disse antes, são 5 funções heurísticas (Análise do tamanho do arquivo, Tempo de execução, Tempo de Intervalo entre Erro do sistema, Período exato de algum erro no sistema, Enumeração em ordem crescente da lista de itens com maior nota heurística)

OBS : Quanto maior a nota, maior a chance do arquivo ser nocivo.

Então como um conjunto todo, cada função vai retornar um valor BOOLEANO - 1 ou 0 / True ou False, ele vai contar quantos True foram dados, sendo a nota máxima 5 ele vai enumerar, comparar as notas com as dos processos atuais, então ele vai interpretar o processo que tiver a maior nota como o nocivo. Resultado, ele vai retornar o HWND do processo, eu vou pegá-lo na função do AV, ordenar o processador a paralisar as threads e aguardar o usuário retornar uma resposta.

Posso dizer que é uma DLL a princípio, vão ter as seguintes funções :

GetMemoryApplicationRuntime - Tempo de execução dos processos

GetApplicationArrayOfBytesLength - Tamanho dos arquivos em processo (Medido em Bytes)

GetCriticalErrorPeriod - Tempo em Segundos equivalente a erro de sistema

GetApplicationRuntimeAfterCriticalError - Intervalo entre o erro do sistema e o tempo de execução do processo

GetApplicationHeuristicAnalysis - Função para retornar a nota de cada processo em execução

GetEnumerationList - Função de enumeração da lista em ordem crescente

ScanMemoryPhysical - Função de Julgamento heurístico que determina o processo nocivo

O Objetivo geral, é nada mais nada menos que bombardear as aplicações do computador com testes e verificações de comportamento, estrutura dos arquivos, heurística de disponibilidade, etc ...

Conforme o antivírus for crescendo eu vou criando mais funções heurísticas, claro que (TODO ANTIVÍRUS BASEADO EM HEURÍSTICA É PASSIVO DE ERROS).

Deixo de seguida uma print da interface do programa :

d9yFlSk.png

Estou quase, quase acabando. Falta muito pouco. Nunca achei que fosse chegar tão longe criando isso em .NET ... Mas ta aí.

Abraços

Link to comment
Share on other sites

Olá Be H Te My,

Desculpe a minha falta de atenção ao responder suas mensagens, o que eu quero é escrever o tempo em que cada processo está aberto no computador dentro de um arquivo ini, ele deverá ser formatado assim :

[secao_da_analise]

Diretorio_da_aplicacao=Tempo_De_execucao

O tempo que ele deve pegar é em relação a inicialização da rotina . Quanto ao processo system, eu por sorte descobri que mesmo que o processo esteja protegido, não dará pra pegar o diretório do aplicativo, não tem problema pois isso retornará um valor NULL e então quando for escrever o INI simplesmente ele vai dar um erro que será ignorado.

Nesse exato momento estou procurando uma API que faz com que a tela do usuário fique esmaecida, (escura) e somente o form do antivírus apareça pois será usado na hora em que o usuário tentar desativar o proteção do antivírus ele receberá uma mensagem de confirmação.

Abraços Colega.

Link to comment
Share on other sites

Então estás a programar um antivírus e não sabes escrever para um ficheiro?

IO.File deve-te ajudar... File.WriteAllText... StreamWriter...

Quanto á ultima questão... porque não fazeres com que para desactivar a tal protecção, ele precise de confirmação de admin (UAC) ? Assim aparece o popup de UAC e o utilizador escolhe sim ou não... porque o que estás a dizer parece-me que vai ser complicado e "fora-de-contexto" na minha opinião.

Link to comment
Share on other sites

Boas He B Te My,

Eu já consegui resolver a parte do tempo de execução, quanto a parte de desativar a proteção é parecido com isso que disseste, um fundo preto aparece na tela mas com o form do antivírus a interrogar o usuário. Eu não achei a API do windows para fazer isso mas criei uma função na dll de carregar o antivírus que faz isso por mim.

gO7YRQh.png

Obrigado, está funcionando bem

Link to comment
Share on other sites

Boa noite,

Podias ter feito algo "parecido" usando a powershell, para obteres dados de todos os processos em execução. Dados esses que poderiam ser comparados com pontos anteriores do sistema, para detectar por exemplo processos "estranhos".

Cordiais cumprimentos,

Apocsantos

  • Vote 1

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.