[ Links open in: same window | new window ]

Radical Software

LCST 2234, Spring 2026 (CRN 16616)
Rory Solomon

Project 2, Tutorial 2

Table of contents

  1. Opening popups
    1. Opening alerts
    2. Incorporating this into Ducky Script
    3. Opening popups with choices
    4. Responding to different popup choices
  2. Fun with basic Ducky Script commands
  3. Running a process in the background after closing Terminal

01. Opening alert popups

Mac OS offers numerous ways that we can open various kinds of system popups.

a. Opening alerts

Here is a simple command on Mac that will open up an alert popup. In Mac OS, an alert is considered a popup window offering some information, to which the user's only option is to dismiss by clicking 'OK'.

osascript -e 'display alert "Alert" message "This is a system alert."'

That will block until the user closes the window. That means that your code will pause waiting for the user's action, doing nothing until the user responds. If you would like your code to continue running while the popup is open (so that you can continue to take other actions), you can add an ampersand & to the end, like this:

osascript -e 'display alert "Alert" message "This is a system alert."' &
(jump back up to table of contents)

b. Incorporating this into Ducky Script

Incorporating this into Ducky Script should be pretty straightforward.

Let's open the Payload Studio, and enter the following script:

ATTACKMODE STORAGE HID VID_05AC PID_021E
DELAY 1000
COMMAND SPACE
STRINGLN Terminal
DELAY 1000
STRINGLN_BASH
  osascript -e 'display alert "Alert" message "This is a system alert."' &
END_STRINGLN

Click 'Generate Payload', then download inject.bin, copy it to your USB device, eject it, and plug it back in to hopefully see this in action.

c. Opening popups with choices

If you want to give the user some different options, you can run this command:

osascript -e 'display dialog "Do you want to continue?" buttons {"Cancel", "Yes"} default button "Yes" with icon caution'

🚨Note🚨: That command line instruction has likely extended outside the black box above. Make sure to highlight the entire command to read it or to copy/paste. Sorry for the bad formatting.

You do not have to include default button "Yes", in which case no option will be marked as the default. (The default option is what gets triggered if the user presses ENTER.)

You can also use different options for the icon, including stop, note, or caution, or you can leave off the with icon ... syntax entirely.

There is probably a lot of fun we could have with this.

osascript -e 'display dialog "Your computer has been hacked. You have two options:" buttons {"Permanently shutdown computer", "Delete all files"} default button "Delete all files" with icon caution'

(Even knowing that this is a joke that I myself have created, I still reflexively find it hard to click on either button!)

(jump back up to table of contents)

d. Responding to different popup choices

You can also give the user options, and take different actions depending on which they choose. Start with this command which asks the user to make a choice:

osascript -e 'display dialog "Which do you prefer, purple or orange?" buttons {"Purple", "Orange"}'

(Note that I have removed the trailing ampersand &.)

Notice that the operating system prints out the result that the user has selected. In this case, either: button returned:Purple or button returned:Orange

Combining this with technique we saw in Tutorial 1, we can save the results of this command in a variable like so:

RESPONSE="$(osascript -e 'display dialog "Which do you prefer, purple or orange?" buttons {"Purple", "Orange"}')"

RESPONSE is not a special keyword here — I could have called it SPAGHETTI or anything else.

Now we can do something with that variable.

Open VS Code, create a new plain text file, enter the below text, and save it onto your Rubber Ducky as script.sh:

RESPONSE=$(osascript -e 'display dialog "Which do you prefer, purple or orange?" buttons {"Purple", "Orange"}')
case "$RESPONSE" in

  *"Purple"*)
    open "https://www.google.com/search?udm=2&q=purple"
    ;;

  *"Orange"*)
    open "https://www.google.com/search?udm=2&q=orange"
    ;;
esac

Now create the following simple Ducky Script:

ATTACKMODE STORAGE HID VID_05AC PID_021E
DELAY 1000
COMMAND SPACE
STRINGLN Terminal
DELAY 1000
STRINGLN bash /Volumes/DUCKY/script.sh

This just runs the Bash shell script that you have just created.

Now try removing and re-inserting the Ducky device.

(jump back up to table of contents)

02. Fun with basic Ducky Script commands

Finally, let's see if we can just have some fun with some simple Ducky Script keystroke injection ...

What if we open the Stickies app, enter some text, and try to mess around with the formatting a bit ...

Here's my first shot at attempting this technique. This one types out the intro verse to a famous jazz standard.

You can copy / paste this Ducky Script directly into Payload Studio, compile, download, copy it over, and run it — no other steps are needed.

ATTACKMODE STORAGE HID VID_05AC PID_021E
DELAY 1000
COMMAND SPACE
DELAY 200
STRING Stickies.app
DELAY 500
ENTER
DELAY 1000
COMMAND n
COMMAND 6
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN Behold the way our fine-feathered friend
STRINGLN His virtue doth parade.
DELAY 1000
COMMAND n
COMMAND 5
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN Thou knowest not, my dim-witted dear,
STRINGLN The picture thou hast made.
DELAY 1000
COMMAND n
COMMAND 2
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN Thy vacant brow and thy tousled hair
STRINGLN Conceal thy good intent.
DELAY 1000
COMMAND n
COMMAND 3
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN Thou noble, upright, truthful, sincere
STRINGLN And slightly dopey gent
DELAY 1000
COMMAND n
COMMAND 1
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN You're ...
DELAY 1000
COMMAND n
COMMAND 4
COMMAND SHIFT =
COMMAND SHIFT =
COMMAND SHIFT =
STRINGLN My funny valentine ...
(jump back up to table of contents)

03. Running a process in the background after closing Terminal

We had some discussions after class today about how to allow a process to continue running in the background after closing the Terminal window. I had some ideas about how to do that, but when I got home and tested, it didn't work quite right. So I made some changes to get it to work properly.

Save the following text to a file on /Volumes/DUCKY and as above, let's call it script.sh:

osascript -e 'display dialog "Whose woods these are?" buttons {"I think I know ..."}'
osascript -e 'display dialog "His house is in the village though" buttons {"Go on"}'
osascript -e 'display dialog "He will not see me stopping here // To watch his woods fill up with" buttons {"Snow", "More snow"}'
osascript -e 'display dialog "My little horse must think it queer" buttons {"Why?"}'
osascript -e 'display dialog "To stop without a farmhouse near" buttons {"OK"}'
osascript -e 'display dialog "Between the" buttons {"woods", "frozen lake"}'
osascript -e 'display dialog "The darkest evening of the year" buttons {"hm"}'
osascript -e 'display dialog "He gives his harness bells a shake" buttons {"..."}'
osascript -e 'display dialog "To ask" buttons {"if there is some mistake?"}'
osascript -e 'display dialog "The only other sounds the sweep // Of" buttons {"easy wind", "downy flake"}'
osascript -e 'display dialog "The woods are lovely" buttons {"dark", "and deep"}'
osascript -e 'display dialog "But I have promises" buttons {"to keep"}'
osascript -e 'display dialog "And miles to go before I" buttons {"sleep"}'
osascript -e 'display dialog "And miles to go before I sleep." buttons {"*sigh*"}'

Now, copy / paste the below code into the Payload Studio, compile it, download it, and copy it to the Ducky. This similar to the script at the end of section 01.d above, but with some slight changes for the background effect to work. The changes are highlighted below.

ATTACKMODE STORAGE HID VID_05AC PID_021E
DELAY 1000
COMMAND SPACE
DELAY 200
STRING Terminal.app
DELAY 500
ENTER
DELAY 1000
STRINGLN nohup bash /Volumes/DUCKY/script.sh &
DELAY 500
COMMAND TAB
DELAY 200
COMMAND TAB
CONTROL d
DELAY 200
COMMAND w

In addition to the new syntax highlighted in blue above, I also experimented a bit with the timing of the DELAY commands to make this a bit more robust (after testing on a different target machine).