Jump to content

Close processes within a certain directory and list closed processes in txt file.


Go to solution Solved by TheXman,

Recommended Posts

Hello everyone:

I return to the forum to see if any crack/teacher can offer me help for a code that doesn't work for me because it doesn't seem to do anything I require.

I would like to kill any processes running in Task Manager, that are running from the location C:\Users\UserName\AppData\Temp

I have this code:

Func GetUsername()
    Local $sUserName = @UserName
    Return $sUserName
EndFunc   ;==>GetUsername

Func StopProcessesInTempFolder()
    ; Get the username of the system.
    Local $sUserName = GetUsername()

    ; Get the path of the Temp folder for the current user.
    Local $sTempFolder = "C:\Users\" & $sUserName & "\AppData\Local\Temp\"

    ; Get the list of processes running in the Task Manager.
    Local $aProcesses = ProcessList()

    ; Create an array to store the names of the stopped files.
    Local $aStoppedFiles[1]

    ; Loop through the list of processes.
    For $i = 1 To $aProcesses
        ; Get the path of the executable file for the current process.
        Local $sProcessPath = ProcessGetPath($aProcesses[$i][1])

        ; Check if the executable file is located in the Temp folder.
        If StringLeft($sProcessPath, StringLen($sTempFolder)) = $sTempFolder Then
            ; Stop the current process.
            ProcessClose($aProcesses[$i][1])

            ; Add the name of the stopped file to the array.
            Local $sStoppedFile = StringTrimLeft($sProcessPath, StringLen($sTempFolder))
            _ArrayAdd($aStoppedFiles, $sStoppedFile)
        EndIf
    Next

    ; Add a line of text to the beginning of the informe.txt file.
    Local $hFile = FileOpen("report.txt", 2)
    FileWriteLine($hFile, "CLOSED PROCESSES")

    ; Create an external report file that lists the names of the stopped files.
    ;Global Const $FO_OVERWRITE = 2
    ;$hFile = FileOpen("report.txt", $FO_OVERWRITE)
    For $i = 1 To UBound($aStoppedFiles) - 1
        FileWriteLine($hFile, $aStoppedFiles[$i])
    Next
    FileClose($hFile)

    ; Set the value of the @error macro to indicate success.
    SetError(0)
    Return True
EndFunc   ;==>StopProcessesInTempFolder

I have some lines commented out in the StopProcessInTempFolder() function, because it gave me a double constant declaration error.

Also the ProcessGetPath() function, is flagged as error, but I guess it's because when compiling is when the compiler takes :
#include <Process.au3> and #include <Array.au3>
 

But anyway, I have two problems:

- The code does not close any process that I have running in the directory C:\Users\" & $sUserName & "\AppData\Local\Temp\

- The code does not write me in the txt file, which closes any process, although it does write me the text line: CLOSED PROCESSES

If anyone can think of what could be failing, or some code to close the processes of a certain folder, I would be grateful.

Greetings and thank you.

Edited by drlynch
Add more information
Link to comment
Share on other sites

Here are a few things to take a look at.  Hopefully, after you read, understand, and resolve the ones that need resolution, you will be a little closer to your goal.  Since this isn't the full script, there are probably more issues.  The ones listed stuck out to me at first glance.

  1. Why do you have a GetUsername() function when all it does is pass back the value of the @UserName macro?  You can just replace calls to GetUsername() with @UserName.
     
  2. If you want the current profile's Temp folder, you can just use the @TempDir macro.  The temp folder is not always in %USERPROFILE%\AppData\Local\Temp.  It's only there by default.  So hard-coding it the way you have could be problematic if the user has moved their TEMP folder location.
     
  3. "Local $aStoppedFiles[1]" defines an array with 1 row in it.  Since you are using _ArrayAdd() to populate your array, using your current logic, the first row added will be row[1] and row[0] will always be empty.  If you want to start with an empty array, then define it as "Local $aStoppedFiles[0]".  Then, the first row added will be row[0] and you can process it starting at index 0 and looping to Ubound($aStoppedFiles) - 1.
     
  4. The number of processes in your $aProcesses array is in $aProcesses[0][0], like it says in the help file.  Using the array name by itself, as you did, does not return the number of rows in the array.  That's what Ubound() does.
     
  5. What in your logic/code should have prevented the output of the line "CLOSED PROCESS".  It's a rhetorical question because the answer is nothing.  So of course it was written to the file.  If it shouldn't be written to the file, then you should wrap it in some sort of conditional structure like:
     
    If There are rows to process in the array ($aStoppedFiles) Then
      Write "CLOSED PROCESSES"
      Do any other processing
    Else
      Return SetError(1, 0, False)
    ENDIF


    Or skip the logic by returning with @error set to something other than 0 right before any stopped files processing, like:
     
    If no stopped files found Then Return SetError(1, 0, False)


     
  6. You are setting @error to 0 regardless of whether your function was successful or not.  Nowhere in your function do you return with an @error other than 0, to signal an that an error has occurred.  (See item #5)
     
  7. Do you see a ProcessGetPath() function anywhere in the help file or in the Process.au3 include file?  Maybe that's why it is flagged as an error?  Maybe _WinAPI_GetProcessFileName() will return what you're looking for.

 

Edited by TheXman
Link to comment
Share on other sites

Thanks for your help Nine and TheXman. You are awesome ;)

I am beginner in AutoIT. So I'm making serious mistakes. I'm sorry for that.
I am now reviewing the updated documentation, and not looking at older information.

I am trying to develop a tool to remove a malware, at least the processes, files and registry entries, that this malware creates in all the cases that I am collecting.

So, I reply to TheXman:
 

1) Wow!!!, Excellent. Fixed that GetUser() function, using only the @UserName instruction.
 

2) Yes indeed I could just delete all temporary files. And this would be a solution.

But now comes my doubt. The malware creates files that remain running all the time. One of those processes appears in the temporary path that I indicated above, and I want to close that process, and then remove the file.

I don't know if, when using the @TempDir macro to delete temporary files, this macro would be able to close the process that is active.

The file that the malware creates in this directory has a random name, so I can't stop it directly without knowing its name.

Logically, this would run the risk of the user having some other temporary file of their own running, so the tool should prompt the user to close all programs he is using.
I understand anyway, that if I delete the temporary files, the same problem could occur, if the macro is actually able to stop the running files.

 

3) It has all the logic, what you tell me.

Then I'm going to do some tests and see if I get any progress.
 

4) Thank you very much for the detailed explanation that you offer me.

I definitely have to practice with arrays and ubound(), to get the data I need.


5) I fully understand what you are telling me. Sure, my code is a mess, but by testing and testing and not having success with anything, I eventually end up creating totally inconsistent code.

Trying to solve this in the quickest and shortest way is a bad idea of course.


6) You are also absolutely right. Actually, now I'm reviewing information about @error in some forum posts.


7) A few hours ago, I checked that according to the documentation, I should probably use WinAPI_GetProcessFileName().

By the way, one question, is there any way to check the content of the .au3 files, which we import from the #include.?

I just don't really have that Process.au3 file. Maybe I copied the code from a post, and a user had created that file for private use.

 

Thanks a million for your help. It's not common to find people helping novice users.

I will try to advance in the code, and if I have any additional questions, I will ask you again if it is not too much trouble.

Edited by drlynch
Link to comment
Share on other sites

3 hours ago, drlynch said:

I am beginner in AutoIT. So I'm making serious mistakes. I'm sorry for that.
I am now reviewing the updated documentation, and not looking at older information.

No need to apologize, we were all beginners at some point. :)  Spending some time familiarizing yourself with the Help Files (either the .chm versions that are installed with AutoIt or the online version) is a very good idea.  The Help Files have answers to almost ALL of your basic questions and have numerous examples to learn from.

3 hours ago, drlynch said:

I am trying to develop a tool to remove a malware, at least the processes, files and registry entries, that this malware creates in all the cases that I am collecting.

Hopefully you are doing this as a learning exercise.  Otherwise, it would be an exercise in futility, especially given that there are numerous tools that already exist for detecting and removing malware.

3 hours ago, drlynch said:

2) Yes indeed I could just delete all temporary files. And this would be a solution.

I'm not sure where this reply is coming from.  My #2 did not suggest anything about deleting files.  It pointed out that is probably better to use the @TempDir macro when referencing the Temp folder's path than it would be to hard-code the path.

4 hours ago, drlynch said:

7) A few hours ago, I checked that according to the documentation, I should probably use WinAPI_GetProcessFileName().

By the way, one question, is there any way to check the content of the .au3 files, which we import from the #include.?

I just don't really have that Process.au3 file. Maybe I copied the code from a post, and a user had created that file for private use.

This is where spending more time with the Help Files, and learning how to effectively search for answers in the Help Files would greatly benefit you.  If you look at the "Installation Directory" topic in the AutoIt Help File, you will see that there is a folder named "Include" in the AutoIt installation folder.  That folder contains all of the standard include files.  In that folder you will find process.au3. 

4 hours ago, drlynch said:

if I have any additional questions, I will ask you again if it is not too much trouble

Unless you actually only want an answer from a specific person, it is better to post your questions, issues, and concerns to the forum and not at any one person.  That way, you may get a reply sooner than waiting for that specific person to answer.  Personally, I try never to answer or reply to a post when someone has @tagged a specific person for a response.   With that said, I don't have a problem with you @tagging me if that's what you want to do. 

4 hours ago, drlynch said:

Thanks a million for your help.

You're welcome.  :)

Link to comment
Share on other sites

Hello, TheXman

You are very kind to me. Thank you for your words, because this makes me feel at home.

Helping beginners is somewhat difficult, because we want to do things too fast, without even knowing the documentation. Serious mistake.

I will briefly respond to some of your comments.

Quote

Hopefully you are doing this as a learning exercise.  Otherwise, it would be an exercise in futility, especially given that there are numerous tools that already exist for detecting and removing malware.

I use tools like Farbar to help users remove all kinds of malware, as well as anti-malware like MalwareBytes, AdwCleaner, etc.

The problem is that the malware that I am trying to eradicate is only affecting a certain country or countries (I understand that there is some illegal software download website that is distributing this malware). I have reported to Google (VirusTotal) and sent a sample of the file to Microsoft. But it doesn't appear that they have taken action against the malware.
I have yet to report MalwareBytes for example, but in any case there are already
reversing technical docs of some of the variants of this malware. I guess some reversing experts will have already done it.

Of course, my intention is not to create a definitive removal tool, because I would have to use later a more effective study with Farbar for example, but to at least try to eliminate the most vital processes of the malware.

The best thing would be to check the signature of the files, the hashes, etc.; but I would do this in a later step if I got a breakthrough in this first phase of development.

The first option that occurred to me was to use C# or Python, but AutoIT seemed like a quick option. This is more of a way of learning. If the tool, once tested on various own computers, works, it could help some users.

 

Quote

My #2 did not suggest anything about deleting files.  It pointed out that is probably better to use the @TempDir macro when referencing the Temp folder's path than it would be to hard-code the path.

Sorry, I thought @TempDir would remove temporary files, but of course, it makes sense that @TempDir simply contains the value of the TEMP environment variable.

 

Quote

This is where spending more time with the Help Files, and learning how to effectively search for answers in the Help Files would greatly benefit you.  If you look at the "Installation Directory" topic in the AutoIt Help File, you will see that there is a folder named "Include" in the AutoIt installation folder.  That folder contains all of the standard include files.  In that folder you will find process.au3. 

Honestly, I didn't even check the folder that AutoIT creates when it installs. I directly went to the code editor.

From now on, I'm going to go much slower with all of this, because I don't want to make any more mistakes.

 

Quote

Unless you actually only want an answer from a specific person, it is better to post your questions, issues, and concerns to the forum and not at any one person.  That way, you may get a reply sooner than waiting for that specific person to answer.  Personally, I try never to answer or reply to a post when someone has @tagged a specific person for a response.   With that said, I don't have a problem with you @tagging me if that's what you want to do. 

I don't want to bother you ;)

We all have many things to do on a daily basis, and your answers have helped me understand that the answers I am looking for, I will not find directly in a search in the forum. At least, code that may be out of date.

Thank you for your answers so elaborate, and with so much good information. You have been very helpful. I will try to test and test, before I ask again.

All the best.

Edited by drlynch
Link to comment
Share on other sites

  • Solution

Here is a small example of how I might go about getting a list of currently running processes, looping through those processes, and terminating the ones of interest. 

My example looks for any instances of Notepad.exe that are running and, if found, writes a message to the console showing the PID of the process that would be terminated if I didn't have the ".Terminate" line below it commented out.  I strongly suggest that you leave that line commented out until you are absolutely sure that your condition(s) for identifying target processes to terminate is working EXACTLY as you expect it should.  In other words, the console message are showing you just the processes that you are expecting to terminate.  If you leave the ".Terminate" uncommented, and your condition or conditions for identifying processes to terminate is just a little off, you could end up terminating one or more unintended processes that might put your system in a very bad state.  The script also displays an array of the process info so you can verify that the console messages match the processes that you expected to terminate.

As the script is currently posted, it cannot do any harm.  You can test it by opening up one or more Notepad.exe instances and running the script.  After the script executes, the console area should show a message for each instance of Notepad.exe that was found.  If you uncomment the ".Terminate" line, you will see each of the Notepad instances get terminated.  If you do uncomment the ".Terminate" line to see it in action, again, I strongly suggest commenting it out again while testing whatever conditions you are targeting until it is producing the expected console messages.

Being a beginner, there are probably some concepts in the script that are new to you, like using WMI & COM to query system info and execute object methods.  Take your time and try to research and understand what each line is doing.  If you have questions after trying to figure something out, feel free to ask.  :)

#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#include <Constants.au3>
#include <Array.au3>


terminate_processes_example()

Func terminate_processes_example()
    Enum  $PROCESS_PID, $PROCESS_NAME, $PROCESS_PATH, $PROCESS_COLS
    Local $aProcesses[0][$PROCESS_COLS]

    Local $oComError  = ObjEvent("AutoIt.Error", "com_error_handler"), _
          $oProcesses = ""

    With ObjGet("winmgmts:")
        ;Get list of currently running processes
        $oProcesses = .ExecQuery("SELECT Handle, Caption, ExecutablePath FROM Win32_Process")

        ;If no processes found, then return with message
        If $oProcesses.Count = 0 Then Return MsgBox($MB_ICONWARNING, "Warning", "No processes found.")
        If @error Then Return MsgBox($MB_ICONERROR, "WMI ExecQuery Error", $oComError.Description)

        ;For each process
        For $oProcess in $oProcesses
            With $oProcess
                ;Add process info to the array for display later, in order to verify terminated process PIDs
                _ArrayAdd($aProcesses, .Handle & "|" & .Caption & "|" & .ExecutablePath)

                ;If the process' executable path is "c:\windows\system32\notepad.exe"
                If .ExecutablePath = "c:\windows\system32\notepad.exe" Then

                    ;Display message to show what would have been terminated if
                    ;the object's .Terminate method below was not commented out.
                    ConsoleWrite(StringFormat("PID: %s (%s) terminated.", .Handle, .Caption) & @CRLF)

                    ;Terminate the process (Uncomment line below to actually terminate to the process)
;~                  .Terminate

                EndIf
            EndWith
        Next
    EndWith

    ;Display list of all processes for verification that the correct
    ;process would have have been terminated.
    _ArrayDisplay($aProcesses, "List of processes", "", 0, Default, "PID|NAME|PATH")
EndFunc

;==========================================================================
;
;==========================================================================
Func com_error_handler($oError)
    #forceref $oError
    Return ; Return so @error can be trapped by the calling function
EndFunc

Sample console output:

PID: 4348 (notepad.exe) terminated.
PID: 2340 (notepad.exe) terminated.

Sample display of the processes array

image.png.ec47399a6984219d33fc8ff52e2593a5.png

Edited by TheXman
Link to comment
Share on other sites

Hello, TheXman.

Sorry for not responding as fast as I should, but I was trying to perform some tests that finally didn't work. 

I've tried _PathSplit, along with ProcessList, ProcessExists and _WinAPI_GetProcessFileName.
I was trying to get the ID with ProcessList, and then from that ID get the path of the running processes. But in tests I've done, they didn't work.
The IDs of the Processes showed me perfectly, together with the name of the process, but some processes did not show any path, and other processes did show the path correctly. I've been looking for a reason why this might be happening, but couldn't find it.

 

xiwF0OY.jpg

kWCfgG4.jpg

In any case, your code is completely different from what I had done.

I am surprised by your code. It's great. I have to study all those lines of code, because as you tell me, there are many that I don't know.

I have no words to thank you for that code. You are a master. I wish there were more people like you in other communities, to help beginners like me.

If I can't find information about some lines of your code, and I have some doubts, I'll let you know. And don't worry, I'm not going to publish any tool without doing a lot of testing first. In the end I am taking this as a way of learning, because I am really at the base of learning AutoIT.

I'll keep you informed.

Greetings and thousands of thanks.

Edited by drlynch
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

  • Recently Browsing   0 members

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