> For the complete documentation index, see [llms.txt](https://documentation.hak5.org/packet-squirrel-mark-ii/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.hak5.org/packet-squirrel-mark-ii/advanced-payloads/flow-control.md).

# Flow control

Typically, a payload will start at the first command, and continue executing until the last command.

There are, of course, ways to change this.  Generally referred to as "flow control", these options change the course of the payload being run.

## If

The simplest flow control is the `if` statement.  Like a word problem in math, an `if` says simply:

"If this condition is true, perform this action".

What constitutes "true"-ness?  As in the majority of programming languages, a `true` statement is one where the result is `not zero`. &#x20;

```sh
if [ 1 -eq 1 ]; then
    echo "True!"
fi
```

This will, of course, print "True!" when run, because 1 is equal to 1.

```bash
if [ "true" = "not true" ]; then
    echo "True!"
fi
```

Similarly, this will print nothing, as the string `true` is not equal to the string `not true`.

### Writing if statements

The basic syntax of an `if` statement is:

```bash
if [ condition ]
then
    commands
fi
```

This is usually shortened (as we did above) to simply:

```bash
if [ condition ]; then
    commands
fi
```

You'll notice the `if` block ends with `fi` (`if` backwards).  Bash uses this convention in several places to indicate the end of a special block.

### Conditions

In the `if` statement, `[ condition ]` is a test that evaluates to true or false. You can test conditions based on file attributes, strings, numbers, or expressions using various comparison operators such as `-eq` (equal to), `-ne` (not equal to), `-lt` (less than), `-gt` (greater than), `-le` (less than or equal to), `-ge` (greater than or equal to), and `-z` (tests if a string is empty).

### Integer comparisons

<table><thead><tr><th width="149">Test</th><th>Returns true when...</th></tr></thead><tbody><tr><td>a -eq b</td><td>a is equal to b</td></tr><tr><td>a -ne b </td><td>a is not equal to b</td></tr><tr><td>a -gt b </td><td>a is greater than b</td></tr><tr><td>a -ge b </td><td>a is greater than or equal to b</td></tr><tr><td>a -lt b</td><td>a is less than b</td></tr><tr><td>a -le b </td><td>a is less than or equal to b</td></tr></tbody></table>

{% hint style="warning" %}
Notice that we use `-eq` instead of `=`, `-gt` instead of `>=`, and so on?  This is because bash treats strings and numbers differently!

When doing numerical comparisons, be sure to use the right operators!
{% endhint %}

```bash
X=10
Y=20

if [ "$X" -lt "$Y" ]; then
    echo "$X is less than $Y"
fi
```

### String comparisons

<table><thead><tr><th width="149">Test</th><th>Returns true when...</th></tr></thead><tbody><tr><td>"$a" = "$b"</td><td>a is equal to b</td></tr><tr><td>"$a" == "$b"</td><td>a is equal to b</td></tr><tr><td>"$a" != "$b"</td><td>a is not equal to b</td></tr><tr><td>-z "$a"</td><td>a is empty</td></tr></tbody></table>

For example,

```bash
OPTION="green"

if [ "$OPTION" == "green" ]; then
    echo "Green"
fi
```

Notice the spaces:  You *must* use spaces around the `=` or `==` operators!

{% hint style="info" %}
Remember to use quotes!

Whenever you're comparing strings, be sure to enclose the value in quotes.  This prevents an empty string from causing a syntax error!
{% endhint %}

### File conditions

There are many tests we can perform on files:

<table><thead><tr><th width="125">Test</th><th>Returns true when...</th></tr></thead><tbody><tr><td>-e</td><td>File exists</td></tr><tr><td>-f</td><td>File exists and is a regular file (not a directory or special file type)</td></tr><tr><td>-s</td><td>File exists and has data (has a size greater than zero)</td></tr><tr><td>-d</td><td>File is a directory</td></tr><tr><td>-b</td><td>File is a block device (a special file in Linux that represents hardware like disks and other storage systems)</td></tr><tr><td>-c</td><td>File is a character device (a special file in Linux that represents hardware like serial ports)</td></tr><tr><td>-p</td><td>File is a pipe (a special file in Linux that represents a two-way communication system between processes)</td></tr><tr><td>-h</td><td>File is a symbolic link (essentially a shortcut or pointer to another file)</td></tr><tr><td>-r</td><td>File has read permission for the user running the test</td></tr><tr><td>-w</td><td>File has write permission for the user running the test</td></tr><tr><td>-x</td><td>File has execute permission for the user running the test</td></tr><tr><td>f1 -nt f2</td><td>File f1 is newer than file f2</td></tr><tr><td>f1 -ot f2</td><td>File f1 is older than file f2</td></tr></tbody></table>

For example, to determine if a file exists:

```bash
#!/bin/bash

if [ -e /tmp/walnuts.txt ]; then
   echo "The file exists."
else
   echo "The file does not exist."
fi
```

### If-Else

We already touched on the `else` structure in the example above:  Else handles taking actions if a statement is **not** true.

```bash
if [ some-test ]; then
    action-when-test-is-true
else
    action-when-test-is-false
fi
```

To handle multiple tests, we use the `elif` option ("else if"):

```bash
if [ some-test ]; then
    action-when-test-is-true
elif [ some-other-test ]; then
    action-when-some-other-test-is-true
elif [ some-third-test ]; then
    action-when-some-third-test-is-true
else
    action-when-no-tests-are-true
fi
```

Notice how we can combine `elif` with `else` ; when no tests are true, the `else` block is executed.

For a more practical example:

```bash
if [ "$OPT" = "option1" ]; then
    echo "option 1 selected"
elif [ "$OPT" = "option2" ]; then
    echo "option 2 selected"
elif [ "$OPT" = "option3" ]; then
    echo "option 3 selected"
else
    echo "unknown option"
fi
```

### Condensed return codes

A variant of an `if` statement can be used when handling the return codes from a process.

Every process has a return code; these are numeric codes that indicate if the process succeeded or failed.  A return code of `0` is considered a success, while any other number is considered an error.

Return codes are stored in the internal variable `$?`.  For example:

```bash
root@squirrel:~# ls /i-dont-exist
root@squirrel:~# echo $?
1
root@squirrel:~# ls /tmp
root@squirrel:~# echo $?
0
```

The `ls` program will set an error code if the file does not exist.

We *could* check for this using a traditional `if` statement:

```bash
ls /i-dont-exist >/dev/null
if [ "$?" -ne 0 ]; then
    echo "I don't exist"
else
    echo "I exist"
fi
```

{% hint style="info" %}
What's the `>/dev/null` in the above example?  Check out the section about [redirecting output](/packet-squirrel-mark-ii/advanced-payloads/redirecting-output.md)!
{% endhint %}

Often, however, it is much quicker to use the bash shorthand of `&&` and `||`.  This will execute the next statement only if the previous one succeeded.  To implement the same using these shorthand options:

```bash
ls /i-dont-exist >/dev/null && echo "I dont't exist"; || echo "I exist"
```

The short methods are not always *clearer*, but are often very useful for short tests of command success.  They're covered more in the [Return codes & success](/packet-squirrel-mark-ii/advanced-payloads/return-codes-and-success.md) section!

## Case

To handle multiple options in a more elegant fashion than constant if-else blocks, the `case` statement is a conditional statement that is used to test a variable or an expression against a series of patterns or values.  It is similar to the `switch` statement in other programming languages.

The basic syntax of the `case` statement is as follows:

```bash
case expression in
  pattern1)
    do-something-for-pattern-1
    ;;
  pattern2)
    do-something-for-pattern-2
    ;;
  pattern3|pattern4|pattern5)
    do-something-for-pattern3-pattern4-or-pattern5
    ;;
  *)
    do-something-if-nothing-else-matches
    ;;
esac
```

Here, `expression` is the variable or expression to be tested, and `pattern1`, `pattern2`, `pattern3`, etc., are the patterns or values against which the expression is to be tested.

Each pattern is followed by a list of commands to execute if the expression matches that pattern. The `;;` symbol is used to indicate the end of each pattern.  In other languages, the `;;` is equivalent to a `break` statement in a `switch` block.

The `|` symbol is used to separate multiple patterns that should be treated as equivalent.

The `*` pattern matches any value, and is used as a default case if none of the other patterns match.

For example, the following script demonstrates the use of the `case` statement to test the value of a variable called `day`:

```bash
# Day is the day of the week, 1-7
day="1"

case $day in
  1)
    echo "Monday"
    ;;
  2)
    echo "Tuesday"
    ;;
  3)
    echo "Wednesday"
    ;;
  4)
    echo "Thursday"
    ;;
  5)
    echo "Friday"
    ;;
  6)
    echo "Saturday"
    ;;
  7)
    echo "Sunday"
    ;;
  *)
    echo "Invalid day"
    ;;
esac
```

You can see this in action in the `NETMODE` DuckyScript command:

```bash
root@squirrel:~# cat /usr/bin/NETMODE
#!/bin/bash

function show_usage() {
        echo "Usage: $0 [NAT|BRIDGE|JAIL|TRANSPARENT|ISOLATE]"
        echo ""
}

case $1 in
        "NAT")
                cat /usr/lib/network_config/nat /tmp/wireguard.conf 2>/dev/null > /etc/config/network
                ;;
        "BRIDGE")
                cat /usr/lib/network_config/bridge /tmp/wireguard.conf 2>/dev/null > /etc/config/network
                ;;
        "TRANSPARENT")
                cp /usr/lib/network_config/transparent /etc/config/network
                ;;
        "ISOLATE")
                cp /usr/lib/network_config/isolate /etc/config/network
                ;;
        "JAIL")
                cat /usr/lib/network_config/jail /tmp/wireguard.conf 2>/dev/null > /etc/config/network
                ;;
        "VPN")
                # VPN is now NAT + vpn configs
                cat /usr/lib/network_config/nat /tmp/wireguard.conf 2>/dev/null > /etc/config/network
                ;;
        *)
                show_usage
                exit 0
                ;;
esac
```

## For

A `for` loop is used to iterate over a set of values, such as a list of files, or a range of numbers. The general syntax for a `for` loop is as follows:

```bash
for var in list
do
   some-stuff-per-item
done
```

Or more condensed,

```bash
for var in list; do
   some-stuff-per-item
done
```

Here, `var` is a variable that is used to hold each value from the `list` as the loop iterates. `list` is a sequence of items, separated by spaces, that the loop will iterate over.

The `commands` block contains the instructions to be executed for each iteration of the loop. This block can contain any valid commands, including DuckyScript commands, other loops, conditionals, and function calls.

Here's an example of a simple `for` loop that iterates over a list of values:

```bash
for tool in squirrel pineapple ducky turtle bunny; do
   echo "Doing a thing with $tool"
done
```

This will iterate over the list of tools ("squirrel", "pineapple", "ducky", "turtle", "bunny"), and for each iteration print the line "Doing a thing with \[tool]".  This would output:

```bash
Doing a thing with squirrel
Doing a thing with pineapple
Doing a thing with ducky
Doing a thing with turtle
Doing a thing with bunny
```

You can also use a `for` loop to iterate over a range of values, using the `seq` command. Here's an example:

```sh
for i in $(seq 1 5); do
   echo "Counting: $i"
done
```

This loop will iterate over the numbers 1 to 5, and for each iteration, it will print the message "`Counting: [number]`". The output of this script will be:

```sh
Counting: 1
Counting: 2
Counting: 3
Counting: 4
Counting: 5
```

The list of items can be taken from a shell expansion, for instance to iterate over all files in a directory:

```bash
for f in /usb/captures/*; do
    C2EXFIL "$f"
done
```

Notice we place quotes around the variable `$f`:  This protects against a file with a space (or other special characters) in the name.  Without the quotes, it would appear as two arguments to the `C2EXFIL` command.

## While

A `while` loop is used to execute a block of commands repeatedly as long as a certain condition is true. The general syntax for a `while` loop is as follows:

```bash
while condition
do
   commands
done
```

or

```bash
while condition; do
   commands
done
```

Here, `condition` is a test that is evaluated at the beginning of each iteration of the loop. If the condition is true, the `commands` block will be executed; if it is false, the loop will terminate and execution will continue with the command after the `done` keyword.

Conditions are evaluated the same as `if` statement conditions, allowing for quite complex controls.

The `commands` block contains the instructions to be executed for each iteration of the loop. This block can contain any valid commands, including DuckyScript commands, other loops, conditionals, and function calls.

Here's an example of a simple `while` loop that iterates as long as a certain condition is true:

```bash
count=0
while [ $count -lt 5 ]; do
   echo "Counting: $count"
   count=$((count+1))
done
```

This loop will iterate as long as the value of `count` is less than 5. For each iteration, it will print the message "`Counting: [count]`", and then increment the value of `count` by 1. The output of this script will be:

```bash
Counting: 0
Counting: 1
Counting: 2
Counting: 3
Counting: 4
```

## Functions

A function is a block of code that can be called by name from within a script. Functions allow you to modularize your code and reuse it in different parts of your script, making it easier to write and maintain complex scripts.

The general syntax for defining a function is as follows:

```bash
function_name () {
   commands
}
```

Here, `function_name` is the name you choose for your function, and `commands` is the block of code that will be executed when the function is called.

You can call a function by simply typing its name, followed by any arguments you want to pass to it (if any):

```sh
function_name argument1 argument2 ...
```

This is a simple function which adds two numbers:

```bash
add_numbers () {
   sum=$(( $1 + $2 ))
   echo $sum
}
```

The function `add_numbers` takes two arguments, `num1` and `num2`, adds them together, and then prints the result to the console. You would call this function using:

```bash
add_numbers 5 10
```

This will output `15` to the console, which is the sum of the two arguments.

You can also use functions to encapsulate complex logic, or to perform tasks that need to be repeated multiple times in your payload. For example, you could write a function to check if a file exists:

```sh
file_exists () {
   if [ -e "$1" ]; then
      echo "File exists"
   else
      echo "File does not exist"
   fi
}
```

This function takes one argument, which is the name of the file you want to check. It then uses the `-e` operator to test if the file exists, and prints a message indicating whether the file exists or not.

To call this function from within your payload, you could use:

```bash
file_exists /path/to/file.txt
```

This will output either "`File exists`" or "`File does not exist`".


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.hak5.org/packet-squirrel-mark-ii/advanced-payloads/flow-control.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
