duckencoder.py icon indicating copy to clipboard operation
duckencoder.py copied to clipboard

duckencoder.py is unable to work on piped stream by design

Open doublehp opened this issue 7 years ago • 2 comments

I am piping live stream from keyboard into duckencoder.py; this is PITA because duckencoder.py is designed to work on closed stream, and not live pipe. Issue lays in both methods -r and -p, due to the use of

                        for line in sys.stdin:
                                source += line

This means the code is waiting for EOF before starting further work. Same issue happens further in the code:

        if rawpassthru:
                # parse raw ascii data
                result = ""
                keyboard = DuckEncoder.readResource(script_dir + "/resources/keyboard.properties")
                language = DuckEncoder.readResource(script_dir + "/resources/" + lang + ".properties")
                for line in source:
                        for c in line:
                                keydata = DuckEncoder.ASCIIChar2USBBytes(c, keyboard, language)
                                if len(keydata) > 0:
                                        result += keydata
        else:
                # parse source as DuckyScript
                result = DuckEncoder.generatePayload(source, lang)

        if ofile is None:
                # print to stdout
                # print(result)
                sys.stdout.write(result)
        else:
                # write to ofile
                with open(ofile, "w") as f:
                        f.write(result)

This whole section does things in two seperate steps: 1, it converts data, and when convertion is done, it tries to output it.

The way to fix for line in sys.stdin: is given in man python, in section for option -u. Fixing the rest needs a complete rewrite of the end of the source.

My workaround is to parse input data, and process it byte after byte, and call duckencoder.py once for each byte; this is overkilling, since it requires to reparse and recompile the python script for every single byte sent; the host can usually stand it because the initial input is a human typing on a keyboard, so it can hardly exceed 10 bytes per second for longer than 10mn ...

doublehp avatar Jan 21 '18 13:01 doublehp

This is inteded behavior. I've done per char encoding in P4wnP1's HID backdoor, if I remember correctly, for the commans sending key (uses duckencoder.py module).

In an early phase of development, I recognized that an USB keyboard is able to send non-ASCII chars, like German 'ü'.

One of the ideas was to provide Input as UTF8, which would conflict with bytewise conversion. Implementing this woild need some kind of look-ahead, as a single UTF8 char could consume multiple bytes.

Anyway, I never implemented this and trued to stay DuckyScript compatible for P4wnP1, which wasn't one of my best decissions (it is fairly limited, if you try to use loops , branches are impossible).

mame82 avatar Jan 21 '18 14:01 mame82

The work around I am looking for since a few hours would to convert my raw input into duck-script, before sending it over the network; then, I would be able to feed duckencoder with a script, and not raw bytes; but I don't find the script generator in the documentations ...

doublehp avatar Jan 21 '18 14:01 doublehp