Subprocess real time response

hello i want to execute this command

command = ['hashcat.exe', '-m', code, '-d', '1', hash_list, WORDLIST, '-r', year_rule] 

and get real time values like time left which word is being crracked all these are shown when running a normal hashcat command but it needs each time to click on ‘s’ in the keyboard to update the output also i didnt find an efficient way to parse the output and then use it in an api, please help im really stuck for a moment here

Please share the code you have written so far.

Also have you considered building a modified version of hascat that better meets your needs?

Really depends on how hashcat outputs data. Check out the pexect package: Pexpect version 4.8 — Pexpect 4.8 documentation

I’m guessing you want a piped subprocess: popen_spawn - use pexpect with a piped subprocess — Pexpect 4.8 documentation

They have some great examples at: Examples — Pexpect 4.8 documentation

idk if that would help since i’m hosting on a windows server, is it that reliable ?

yes sure here it is

app.task
def load_regex_patterns(f):
    with open(f, 'r', encoding='utf-8') as f:
        regex_patterns = json.load(f)
    return regex_patterns

@app.task
def parse_hashcat_output(process, regex_patterns):
    try:
        for line in process.stdout:
            output = {}
            for pattern_name, pattern in regex_patterns.items():
                match = re.search(pattern, line)
                if match:
                    output[pattern_name] = match.group(1)
            yield json.dumps(output)
            time.sleep(1)
    except KeyboardInterrupt:
        process.terminate()
        process.wait()
        raise
    finally:
        process.wait()
        process.stdout.close()

@app.task
def run_hashcat(hash_file, hashtype, wordlist, rule_year):
    patterns_dir = r'..\backend\data\hashcat_patterns.json'
    os.chdir(r'C:\Program Files (x86)\hashcat-6.2.5')
    command = ['hashcat.exe', '-m', hashtype, '-d', '1', hash_file, wordlist, '-r', rule_year]
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
    
    regex_patterns = load_regex_patterns.delay(patterns_dir).get()

    yield from parse_hashcat_output.delay(process, regex_patterns)```

and this is the patterns.json 

```{
    "session": "Session\\.*: (.+)",
    "status": "Status\\.*: (.+)",
    "hash_mode": "Hash\\.Mode\\.*: (.+)",
    "hash_target": "Hash\\.Target\\.*: (.+)",
    "time_started": "Time\\.Started\\.*: (.+)",
    "time_estimated": "Time\\.Estimated\\.*: (.+)",
    "kernel_feature": "Kernel\\.Feature\\.*: (.+)",
    "guess_base": "Guess\\.Base\\.*: (.+)",
    "guess_mod": "Guess\\.Mod\\.*: (.+)",
    "guess_queue": "Guess\\.Queue\\.*: (.+)",
    "speed": "Speed\\.#1\\.*: (.+)"}

i tried this options too

command = ['hashcat.exe', '-m', '1000', '-d', '1', hash_list, WORDLIST ,'-r', rule_year]

def send_status(proc):
    proc.stdin.write("s\n")
    proc.stdin.flush() 

with open(output_file, "w") as f:
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, universal_newlines=True)
    for line in process.stdout:
        print(line, end='', flush=True)
        f.write(line)
        if "[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit =>" in line:
            send_status(process)

print("Output saved to:", output_file)

hello ? i want to send data to the front in real time also hashcat needs an s button push each time to show updates of the values at the CLI

When you read the output of the process with for line in process.stdout do you get the prompt line?
I suspect not. You could add a print into the loop to see what you get back in line.

You may need to change the mode of the process.stdout to allow reading char-by-char and not line-by-line.

yes i actually get the prompt line the problem like i said in the process.stdin i cant communicate with it

That may e down to the way that the hashcat.exe is written.
If it uses an API call to read the keyboard and not read from stdin then what you are doing will not work.

You would need to check the code of the hashcat program to know what its doing. And also consider building a modified version with the prompt removed.

Typically applications that process standard I/O will default to full buffering for a pipe or disk file. Full buffering physically reads and writes to a file in buffered blocks, which are typically 4 KiB. On Windows, there’s nothing you can easily do about that if the application doesn’t have a command-line option to force the use of line-buffering or no buffering. You’d have to modify and rebuild the application, which often isn’t possible.

That could actually be a good thing. Since it isn’t possible to open the keyboard device to read it directly, this is implemented by reading console input using a native handle, via WinAPI ReadConsoleW() or ReadConsoleInputW(). Windows supports writing text to a console session’s input buffer via WriteConsoleInputW(). It’s a bit tedious since text has to converted into an INPUT_RECORD array, with a KEY_EVENT_RECORD for each key up and key down event. But it’s at least possible.

is it weird that this works ?

def parse_hashcat_output(process, regex_patterns):
    output = {}

    try:
        for line in process.stdout:
            print(line, end='')
            for pattern_name, pattern in regex_patterns.items():
                match = re.search(pattern, line)
                if match:
                    output[pattern_name] = match.group(1)
                    print(f"{pattern_name}: {match.group(1)}")

            print()
            
            keyboard.press_and_release('s')
            time.sleep(1)
    except KeyboardInterrupt:
        process.terminate()
        process.wait()
        raise
    finally:
        process.wait()
        process.stdout.close()

    return output


the status shows but the s is getting clicked everywhere in my computer like its a cron script, i don’t think that’s ideal

Just clone the git source of the hashcat source and edit out the need for input, then you can run it without the need to provide input.

Generating WM_KEYUP and WM_KEYDOWN messages in the current Windows session is not what I had in mind. Those messages will be delivered to whichever window happens to have the input focus at the time. You need to write the key events directly to the console’s input buffer via WriteConsoleInputW().