Because of the ability of modern LLMs to produce code, there are many tools that help integrate their use in the development process. For example, Github Copilot is often utilized within VSCode in order to provide in-line code generation within a developer's coding environment. One such tool for producing code is Aider: a software engineering assistant that provides a pair programming experience with an LLM. Developers interact with Aider via a command line interface. Two of Aider's features that make it useful are its modification of local git repositories for better control over code modifications as well as the use of Tree Sitter, a program that parses code and builds concrete syntax trees. In this exercise, we will create a guestbook web application on our course VM using Python Flask.

Cloud Shell

The web application we'll be using will run on Python Flask's default port of 5000. In order to access this port on our course's Linux VM, we will need to create a firewall rule that allows traffic to the port, then apply it to the VM. Bring up a session on Cloud Shell and create the rule, specifying a tag name of flask-server.

gcloud compute firewall-rules create default-allow-flask \
  --allow=tcp:5000 --target-tags=flask-server

Then, apply the tag to the course VM.

gcloud compute instances add-tags course-vm --tags=flask-server

Course Linux VM

The application has a home page that allows ‘guests' to post comments that are then rendered on the page with the guests name, email, message, and a timestamp. The first step will be to create a folder for our new Aider project.

mkdir -p ~/Aider/guestbook
cd ~/Aider/guestbook

python3 -m venv env
source env/bin/activate
pip install aider-chat 

Set up an environment variable named GEMINI_API_KEY that contains the same value as the GOOGLE_API_KEY you have set previously. Note that Aider offers usage with OpenAI and Anthropic, as well as other providers.

export GEMINI_API_KEY=$GOOGLE_API_KEY

Visit the AiderLLMLeaderBoard to see what models perform the best: https://aider.chat/docs/leaderboards/. Aider can be used with any of the models listed and you can launch Aider with a particular model using the command below

aider --model <MODEL_NAME>

Launch Aider with a given model:

aider --model gemini/gemini-1.5-pro-002

Agree to make a git repository when the program starts. Note that, If you want to change the model you are using from within Aider, the tool provides a convenient interface. The /models command shows the available models and can also be used to search for models not present on the leaderboard by name.

/models <QUERY>

The /model command allows you to switch to a different model.

/model <MODEL_NAME>

Aider has a 'help' mode that we can invoke using the /help. Run the command.

/help

We'll be using a subset of these commands in our initial labs. Using /help, we can then ask a question about Aider's different chat modes:

/help What are Aider's different chat modes?

This command will ask to install added dependencies which will load a vector database of all Aider's docs and then use RAG to provide context for specific Aider documentation when the user uses the /help command. We now have a personal Aider assistant!

Next we will explore how other chat modes can be used. This Guestbook application will use the model-view-controller (MVC) architecture. Instead of describing to you what the MVC architecture is, use the Aider's 'ask' mode via /ask to get an explanation.

/ask What is the Model-View-Controller design architecture?

Now that we have a rough overview of what the design architecture we will be using, we can begin to implement the application. For this exercise, we will define the structure of the code in one large step and try to debug the code if any issues arise.

Here are the steps:

  1. Define a high level overview of the application and have Aider create the project structure
  2. Ask Aider to install the necessary dependencies
  3. Use the /help command along with /architect and /ask to fix any issues there might be
  4. Try running the application (if it is not clear how to do so ask Aider)

First let's ask Aider the best chat mode to use for the first step:

/help What chat mode should be used to create the file structure of a web application?

Now let's test out the power of Aider and current chat models using the 'architect' mode (it is recommended to use one of the models on the top of the AiderLLM leaderboard for this step). Consider the prompt below:

The prompt is intentionally detailed and explicit in order to give the LLM exactly what it needs to produce the expected code. Within Aider, use architect mode to handle this prompt.

/architect I want to ...

Aider should show you the file structure and ask you if you would like to implement it. Select Yes. Then agree to add the files to the chat and to create the files. Note that Aider may attempt to reimplement the application using a persistent backend such as SQLite3. If so, decline the request. If it has been added, you can 'undo' the commit via:

/undo

In the next step, we will ask Aider to install the dependencies that are needed. First, check that the files that were just created are in the chat:

/ls

This will display the files in chat. If your applications files are not in the chat add them using the command

/add <APPLICATION FILES>

Now that the files are added to the chat we will use the architect chat-mode to ask for Aider to create a requirements.txt file that installs the necessary dependencies.

/architect Please create a requirements.txt file in the application folder that includes all of the necessary dependencies.

Now ask Aider how to install the dependencies if it has not already done so. It will prompt you to run the commands within the shell to set the environment up.

Please install the dependencies in the requirements.txt file in the repository

See troubleshooting tips if it gets caught in a loop or cannot find the file. Now ask Aider to run the application:

Please run the application

If there are errors anywhere in this series of steps, you can exit the application with Ctrl+c, add the error output to the chat, then ask Aider to fix the error. Other troubleshooting tips can be found in the troubleshooting section at the end of the lab.

Fix the error

Once the app is successfully created, open your application in a web browser. To do so, find the 'External IP address' of the course VM. Then, in a browser window, enter the URL

http://<External_IP_Address>:5000/

Enter a message. If the User interface is not updated with the message or there is an error please use the troubleshooting tips in the next section. Once you successfully have an application running on the local host exit by hitting Ctrl+c.

Use the ask command to inquire about the security of the application:

/ask Is this code ready for production? What security concerns are there?

Troubleshooting tips

First and foremost, always read what the model is telling you after creating code or advising you on a command. In addition, try using the model with the highest leaderboard position.

Using Aider

Ask Aider directly how to do something

/help <Your Question about Aider>

Inquire about a certain aspect of your project

/ask <Question about code>

Files don't exist or Aider enters a loop

Look at what Aider is trying to do. Look at the project structure. Use the run command to manually enter in the commands that Aider may be struggling with:

/run <Your command here>

Running the Application

Even though the default chat-mode of Aider is /code, it should still be able to respond to your question and even give you a command to run. First make sure that the files of the project are in the chat.

/ls

If the project files are not in the chat enter:

/add <Your project files>

Now simply ask the default chat-mode(code) how to run the application

How do I run the application?

It should ask you if you want to execute the presented command. If it fails use:

/ask How do I run the application?

Then run the command by entering it into Aider:

/run <Command here>

Dependency conflicts

Ask Aider to install the dependencies in the requirements.txt file. If there is an error, when Aider asks if you want to add the output to the chat select Yes. Then ask:

/architect Please update the requirements.txt file so that there are no dependency conflicts

If using a powerful model, it should be able to resolve the conflicts for you.

Starting Over

You can exit Aider via

/exit

Next remove all of the project files from the repo

rm <Your Files Here>

After this re-enter aider and type

/commit

After deleting the files and updating it via git. Now you can reset the repo map using:

/map-refresh

Next use the rest command to drop all files and clear the chat (just in case):

/reset

Now double check that the repository is empty

/map

Model Cannot Follow correct Formatting

The first step that you can try is changing the model to see if it fairs any better. Check the leaderboard and use a model with a higher score on using the correct formatting. Then switch to the model:

/model <model name>

If that doesn't work try removing unnecessary files from the chat using

/drop <file name>

You could also clear the chat history using:

/clear

The reason why these steps could be helpful is that it declutters the chat, allowing the model to better adhere to the formatting. If you want to try getting rid of everything in the chat including all the files use

/reset

In this exercise Aider will be used to assist in the incremental development of a ransomware program that performs data exfiltration. The program will carry out the following steps:

Course Linux VM

Use the web console to bring up an ssh session on your virtual machine. We'll be needing multiple ssh sessions on our VM to perform the lab. To support multiple sessions in a single terminal, we can utilize tmux: a terminal multiplexer. tmux utilizes keyboard shortcuts that are triggered after hitting Ctrl+b to navigate multiple terminals within a single window. To start a tmux session, run it in the terminal.

tmux 

To create a new terminal the command is:

As can be seen by the lower tabs on the screen, there are now two multiplexed terminals active. You can now switch between them by using the command:

Web server application tmux session

Use the web console to bring up an ssh session on your virtual machine. Change into the source directory containing the examples, create a virtual environment, activate it, and install the packages.

cd cs410g-src/08*
git pull
virtualenv -p python3 env
source env/bin/activate
pip install -r requirements.txt

Then, run the web application in the directory. This application runs a simple upload server that your generated program will upload files to.

python3 simple_http_server.py

Iconify the ssh window as you complete the rest of the exercise.

Aider tmux session

Create a new tmux window if you have not already, Ctrl+b followed by c. Switch to this window. Now, using the instructions below, create a directory for your application then create a virtual environment with Aider installed in it.

mkdir -p ~/Aider/malware
cd ~/Aider/malware

python3 -m venv env
source env/bin/activate
pip install aider-chat  

Set up an environment variable named GEMINI_API_KEY that contains the same value as the GOOGLE_API_KEY you have set previously. Note that Aider offers usage with OpenAI and Anthropic, as well as other providers.

export GEMINI_API_KEY=$GOOGLE_API_KEY

Finally, launch Aider:

aider --model <MODEL_NAME>

Stage 1: Find PDFs on the system

Now it is time to have Aider make the first git commit:

Check file that was created by running a shell command to dump its contents:

/run cat find_pdfs.py

Now that it has been verified that Aider made a local commit, it would be nice to have a way to test the function that Aider created.

Aider allows developers to run shell commands within an Aider session. This example will use this feature to test the script that was written. First find the path to your course directory, cs410g-src, using the /run command and ls. Add to your home directory path until you find the directory. Then run the script using the path to your course directory.

/run python find_pdfs.py <COURSE_DIRECTORY_PATH>

Stage 2: Create a zip file from the PDFs

To efficiently load the files off the system, it is necessary to compress them.

Now to test that the file is being created in the correct location Aider can be used to make unit tests:

Stage 3: Load file to HTTP endpoint

The next step for a data ransomware campaign might be to exfiltrate the files from the target system to a server that the adversary controls. Modify the current project using Aider to add this functionality.

(Note: Don't add the url to the chat. This is for PlayWright, an automated web browsing feature)

Now test the script that Aider wrote by using the /test command. This will add the output to the chat:

/test python find_pdfs.py <course home directory>

Stage 4: Encrypt the PDF files

A ransomware payload would want to make the exfiltrated files unusable to the target so that the target administrators are forced to pay a ransom in order to decrypt their files. This could be done using either asymmetric or symmetric encryption. This exercise will use symmetric encryption so that the encryption key and decryption key are the same.

Install the dependencies (if Aider has not prompted you to do so already), and run the script:

/run pip install -r requirements.txt
/test python find_pdfs.py <COURSE_DIRECTORY>

You have now simulated the exfiltration of sensitive pdf files and then encrypting them to ensure the owner of the files cannot regain access to the data. In an actual pentest engagement you would have exfiltrated the files to a server you own.

Stage 5: Polymorphic Code generation

To make the ransomware harder to detect it can be useful to create variants of the code that have identical functionality.

Test the code again:

/test python find_pdfs.py <COURSE_DIRECTORY>

Now exit Aider

/quit

Then to exit out of tmux type exit for each tmux window and you will be returned to the base terminal.

Cursor is an AI powered IDE that is built on a fork of VS Code. It offers the same functionality as VS Code, but is built to be seamlessly integrated with AI tools. It offers many rich features that aid in writing, understanding, and editing code.

In this exercise Cursor will be used to assist in the incremental development of a ransomware program that performs data exfiltration. The program will carry out the following steps:

Installing Cursor

Go to https://www.cursor.com/. At the homepage there will be a button to download Cursor for your system. Once downloaded, click on the installer to install Cursor. A Cursor window will pop up asking if you want to import VS Code extensions or start from scratch. Either option is fine. Then you will be asked to select "Privacy Mode" or "Help Improve Cursor" select your preference. Then you will be asked to Log In or Sign up. If you have not yet signed up, select the "Sign Up" option and you will be taken through the steps to create an account. Opt to use the 2 week free trial.

Opening Course repository

There are three primary ways to open a project, you can open a project from the file system, clone the course repo, or connect to your course VM. For this exercise, clone the course repository. Once you have the course repository open in Cursor, navigate to cs410g-src/08_CodeGeneration.

Setup environment

There are many different workflows available in Cursor. It offers tab completion similar to Github Copilot, code editing the file directly in chat mode, and using an agent in the composer tab. For this exercise we will be using Composer, which will allow us to enter and execute all of the prompts and commands we need in a single location. Hit ctrl+L to bring up a chat session. A window will pop up to the right. Select Composer on the top menu bar and then click agent:

Next start the Python server that has been provided:

We have now set up the server that will be used to receive files from the scripts we are about to create.

Stage 1: Find PDFs on the system

We are going to now get Cursor to write a program that will find all of the PDFs that exist in the repository. We could choose a couple ways to do this. To start though, we will utilize Cursor's agent feature.

Select the save all option, which will allow you to test the code without accepting it yet:

Next test that the code works.

If you want to undo accepted changes simply scroll to the top of the chat and select restore:

Stage 2: Create a zip file from the PDFs

To efficiently load the files off the system, it is necessary to compress them.

Now to test that the file is being created in the correct location Cursor can be used to make unit tests:

Select the file to see what changes were made

Stage 3: Load file to HTTP endpoint

The next step for a data ransomware campaign might be to exfiltrate the files from the target system to a server that the adversary controls. Modify the current project using Cursor to add this functionality.

Stage 4: Encrypt the PDF files

A ransomware payload would want to make the exfiltrated files unusable to the target so that the target administrators are forced to pay a ransom in order to decrypt their files. This could be done using either asymmetric or symmetric encryption. This exercise will use symmetric encryption so that the encryption key and decryption key are the same.

You have now simulated the exfiltration of sensitive pdf files and then encrypting them to ensure the owner of the files cannot regain access to the data. In an actual pentest engagement you would have exfiltrated the files to a server you own.

Stage 5: Polymorphic Code generation

To make the ransomware harder to detect it can be useful to create variants of the code that have identical functionality.