Command Prompt Scripting & Security
In the final chapter of this CMD series, we’ll focus on security and writing code. We’ll learn how to protect data, write Batch Scripts, run C# apps with CMD, make CURL calls, set environment variables, and summarize what we’ve learned so far.
If you’re new to the series you may be interested in the previous chapters.
Secure Personal Data
In this module, we’ll learn how to protect our data with CMD by hiding, encrypting, and locking files and folders as well as changing a password securely.
Encrypt & Decrypt data
Encryption is used to prohibit other users to see the contents of the files.
Supposedly we have a passwords.txt file on our machine that no one is allowed to see but us, we can use a command line utility cipher to encrypt this file.
important> cipher /e passwords.txt
Encrypting files in C:\Users\Mirza\Desktop\important\
passwords.txt [OK]
Looking at the same file now a lock should pop up on the icon.
Since we set the encryption we can, of course, open the file, but any other user on this machine, or user that connects to the machine won’t be able to.
To decrypt the file we once again make use of the cipher command. Only this time instead of passing the flag e/
(encrypt), we use /d
(decrypt) flag.
important>cipher /d passwords.txt
Decrypting files in C:\Users\Mirza\Desktop\important\
passwords.txt [OK]
And just like that, the file is decrypted and the lock is gone.
We can also encrypt files from the outside. If we execute cipher against the directory, all files inside will be encrypted.
C:\Users\Mirza\Desktop>cipher /e important
Encrypting files in C:\Users\Mirza\Desktop\
important [OK]
1 file(s) [or directorie(s)] within 1 directorie(s) were encrypted.
And the lock should appear on the directory icon.
The same goes for decryption.
Hide files and folders
Even with encryption, the file we locked is still visible in explorer. To hide the directory or the file we make use of attrib
command followed by a few options and a path to the directory/file we want to hide.
> attrib +s +h passwords.txt
And the passwords.txt file that was previously here is gone.
We can’t even see it if we run the standard dir
command in the CMD.
C:\Users\Mirza\Desktop\imporant>dir
03/26/2023 8:39 PM <DIR> .
03/26/2023 8:39 PM <DIR> ..
0 File(s) 0 bytes
Even if we toggle an option to display hidden files and folders, the file won’t be there.
Let’s clarify what this command meant.
- attrib — attributes
- + — we’re adding an attribute
- s — system files
- h — hide
The only way the file will display is if we use a dir
variant that displays even the hidden files/folders. (dir /a displays all files)
C:\Users\Mirza\Desktop\imporant>dir /a
03/26/2023 8:39 PM <DIR> .
03/26/2023 8:39 PM <DIR> ..
03/26/2023 8:39 PM 0 passwords.txt
To reverse this we type the same command just this time we use minuses instead of pluses.
> attrib -s -h passwords.txt
And the file is back.
The same works for folders as well.
Create secured directories
Secure directories cannot be copied, moved, or deleted. To do that create a directory called aux\
(Auxiliary device — protected name in MS-DOS)
Desktop>mkdir aux\
We can put data in this folder but only from the outside.
Entering this directory via CMD is not possible as CMD complains that the directory is not present.
Desktop>cd aux
The system cannot find the path specified.
If we try to delete the directory, Windows will pop up a message that the directory is not found even though it’s right in from of us.
The only way to remove such a directory is through the terminal.
Make sure that the aux\ folder is empty before deleting it.
Desktop>rmdir aux\
Lock Files and Folders
Similar to encryption we can set permissions per file/folder that will prevent anyone from opening or editing them.
Desktop>cacls secrets /P everyone:n
Are you sure (Y/N)?y
processed dir: C:\Users\Mirza\Desktop\secrets
If we try to open the secrets folder we should get a warning.
The file is locked. Let’s explain what this command did:
- cacls / icacls — CMD utility for access lock control (ACL)
- secrets — path, directory, or file name we want to lock
- /P — permissions we want to set
- everyone: flag — what permissions users have
Permissions variations:
- n — None
- r — Read (read-only)
- c — Change (read and write)
- f — Full control (no locks)
So the command we ran:
> cacls secrets /P everyone:n
Prohibits anyone to access the secrets directory.
To clear this out we run the same command with :f
flag at the end.
C:\Users\Mirza\Desktop>cacls secrets /P everyone:f
Are you sure (Y/N)?y
processed dir: C:\Users\Mirza\Desktop\secrets
The folder is now fully accessible.
Inside the secrets folder, there is a file called secret keys. I’ve already run a lock on it to set it to read-only.
> cacls secret-keys.txt /P everyone:r
If we attempt to edit this file and save our edits in the existing file, Windows will complain that we do not have permission to do so.
Permissions can be reset the same way as above.
C:\Users\Mirza\Desktop\secrets>cacls secret-keys.txt /P everyone:f
Are you sure (Y/N)?y
processed file: C:\Users\Mirza\Desktop\secrets\secret-keys.txt
Change Password with CMD
Using the net
command we can change the password of our Windows user through the Command Prompt. First, let’s list all users:
Desktop>net user
User accounts for \\DESKTOP
------------------------------------------------------------------
Administrator DefaultAccount Mirza
Guest WDAGUtilityAccount
The command completed successfully.
Suppose we want to change the password for one of our users. There are two ways to do this.
The first way is to type out net user <username> <password>
:
> net user Mirza 1234
The command completed successfully.
This of course sets a password for our user that it will use to log in next time. However, this was anything but secure. To keep our input hidden we’ll use the second option.
For the second case, we’ll type almost everything the same, but when we get to the password we’ll just type an asterisk and hit enter.
> net user Mirza *
This will pop up additional questions. If we enter the password now the text we enter will not be visible on CMD.
> net user Mirza *
Type a password for the user:
Retype the password to confirm:
The command completed successfully.
The password is set again.
To remove the password, follow the same steps as above and hit enter twice when prompted (do not enter anything).
CURL
The Client for URL (CURL) is a tool for transferring data with URLs. The power of Postman in the Command Prompt. With CURL we can send HTTP requests to the servers directly from CMD.
GET Request
Let’s start by retrieving information from the server. Enter curl
followed by the URL and it should return the response.
> curl www.google.com
CURL on the Google page returns a whole bunch of HTML.
Other endpoints return other responses, like files to download, XML, or JSON. Here is another request that returns a dummy JSON object:
> curl https://jsonplaceholder.typicode.com/users/1
API response:
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
We can save the response content into a file using the output flag >
followed by the name of the file.
> curl https://jsonplaceholder.typicode.com/users/1 > response.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 509 100 509 0 0 3029 0 --:--:-- --:--:-- --:--:-- 3047
HEAD Request
The HEAD request is similar to GET, with one exception — it only returns the headers from the server. To specify this request type we use the -I
flag when performing CURL.
> curl https://jsonplaceholder.typicode.com/users/1 -I
POST Request
To create new content using CURL we can make use of a POST request.
We use -X
flag to specify the request type (GET / POST / PUT, etc.), followed by content-type -H
(in this case JSON), then --data
flag containing the data we’re sending.
curl -X 'POST' -H 'Content-Type: application/json' --data
'{"name":"mirza", "profession":"dev"}' https://some-API/
And the server will send us the response.
Read more on CURL.
Common Script Commands
Let’s take a quick peek into some of the commands we haven’t used yet.
Time and Date
We can get the current time with %TIME%
command combined with the echo
command to print it out.
> echo %TIME%
> 07:42:49.64
And for the current date:
> echo %DATE%
> Mon 03/27/2023
We can combine two in one line.
> echo %DATE% %TIME%
> Mon 03/27/2023 07:43:46.04
Environment Variables
The percentage symbols around a word indicate a variable name. We can use it to print out any environment variable, e.g. computer username:
> echo %USERNAME%
> Mirza
> echo %USERPROFILE%
> C:\Users\Mirza
We can also create our own variables using the set
keyword:
> set num=123
And print it with echo:
> echo %num%
> 123
If we once again set a value of the variable, it will override the previous value.
> set num=45
> echo number is: %num%
> number is: 45
Now let’s declare a variable that contains a string (text):
> set coming_soon=Angular article
> echo %coming_soon%
Notes:
Don’t use spaces when setting variables, e.g. :set num = 123
because that won’t work.
When declaring variables containing strings, we do not wrap words quotes.
Path
Displays the path variable (collection of environment variables).
Desktop> path
PATH=C:\Program Files (x86)\Common Files\Oracle\Java\javapath
;C:\Windows\system32;
...
Other common commands.
Batch Scripting
Rather than executing each command line by line in the Command Prompt, we can create a Batch file that can contain several. Batch Scripts are stored in simple text files containing lines with commands that get executed in sequence, one after the other.
Upon writing a script file, we can execute it at any time.
The term “batch” is from batch processing, meaning “non-interactive execution”.
First Batch Script
To create a batch script we need to create a .bat file. It can be done with a right button click or via CMD, e.g.: first-script.bat
Inside we’ll write our script:
@echo off
echo Hello World!
The @echo off
command hides script code from CMD when the script is been executed.
To run this script we can double-click on it (first-script.bat) or via CMD:
> first-script.bat
Works like a charm!
Arithmetic operations
Moving forward we can create a super simple calculator script that performs arithmetic operations, such as addition, subtraction, multiplication, and division.
This is a script that calculates the sum of two numbers.
@echo off
set var1=2
set var2=3
set /a sum= %var1% + %var2%
echo sum is: %sum%
In order for the sum to work we added /a
that stands for arithmetic.
When executed, it will always print the sum of 2 & 3;
> sum.bat
> sum is: 5
To make this truly work like a calculator we can pass the arguments when executing a script. First, we need to update our script to pick up values from the Command Prompt.
@echo off
set var1=%1
set var2=%2
set /a sum= %var1% + %var2%
echo sum is: %sum%
Where,
%1 represents the first argument passed in
%2 is the second
%2 is the second
> sum.bat 20 30
> sum is: 50
> sum.bat 8 7
> sum is: 15
Conditions
Here is another script that looks up a specific file in folder2. If the file already exists, the script removes it. Otherwise, it goes to the else case and creates a new file.
@echo off
IF EXIST folder2\file.txt (
echo File already exists!
del folder2\file.txt
echo File removed!
) ELSE (
echo File not found!
cd. > folder2\file.txt
echo New file generated.
)
Full list of conditions commands.
Goto
The GOTO command is used when we want to off-road the script execution. As an example, we can say if the script is missing an argument throw an error to the consumer. Otherwise, run as usual.
In this example, we’re reading contents from the file located on our machine. The directory path is already set, but we need to pass the name of the file we want to preview (via type command). If we leave out the file name, the Command Prompt will go to the :error case and complain that the file name is not provided.
@echo off
set folder_path="C:\Users\Mirza"
if "%1" == "" goto :error
set file_name=%1
IF EXIST %folder_path%\%file_name% (
type %folder_path%\%file_name%
) ELSE (
echo File not found!
)
goto :eof
:error
echo File name is not provided!
And if the file name is provided but does not exist in the specified directory path, it will print the message that the file was not found.
Because we set up goto for the error case, for the different path, we need to use goto :eof
command (end of file) to reroute the script. It basically tells CMD that it can exit the script.
> goto-script.bat file.extension
Loops
Loops repeat a certain action over multiple iterations. We can make use of loops to create multiple folders at once.
@echo off
FOR /L %%G IN (1,1,5) DO (
mkdir test%%G
)
Rem This is a comment
Where
- 0 represents the starting index
- 1 is the counter index (count increases by one for each iteration)
- 4 is the final iteration count
This will create 5 distinct folders in our directory where each folder will be called test followed by the iteration index (%%G).
> loop.bat
> dir
03/26/2023 05:08 PM <DIR> test0
03/26/2023 05:08 PM <DIR> test1
03/26/2023 05:08 PM <DIR> test2
03/26/2023 05:08 PM <DIR> test3
03/26/2023 05:08 PM <DIR> test4
Express.js server via Batch Scripts
This script will create and set up the Express.js API server by creating a project directory, installing all required packages, and generating an app.js file by inserting line by line into the file.
To put this in motion, you need to have Node.js installed on your PC.
echo [LOG]: Setting up project directory...
mkdir express-app & cd express-app
echo [LOG]: Setting up server file...
echo const express = require('express'); >> app.js
echo const app = express(); >> app.js
echo const notifier = require('node-notifier'); >> app.js
echo app.get('/', (req, res) =^> { res.send('Hello World!') }) >> app.js
echo app.listen(4000, () =^> console.log('server started on localhost:4000')); >> app.js
echo notifier.notify({ title: 'Server is running!', message: 'Please visit localhost:4000', wait: false }) >> app.js
echo [LOG]: Installing packages...
npm init -y & npm i express node-notifier & node app.js
Here we’re using the caret symbol (^) to escape greater than (>) characters.
When we run this script via CMD or double-click on the .bat file, it should start an Express.js server on pc.
To verify that this works, we can open up another CMD and use CURL to invoke the request on port 4000.
> curl localhost:4000
We can terminate the Express app by hitting CTRL+C in the Express CMD or closing the CMD altogether.
Running .NET applications with CMD
Using the CSC (C# Compiler) we can compile and run C# apps without using a solution file from an IDE (such as Microsoft Visual Studio or Jetbrains Rider). CSC is executed directly from Command Prompt.
Let’s create a C# Hello World program.
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello C#");
}
}
If we were to run this file directly, Windows would not be sure how to and prompt us with possible answers.
But this is not what we want. We want to compile it through CMD. For that let’s use the previously mentioned csc
command.
Desktop> csc program.cs
And voila, we have compiled a program.cs file into a program.exe file.
Watch this if you have issues with running the CSC command.
Desktop>dir
Directory of C:\Users\Mirza\Desktop
03/25/2023 10:13 AM 118 program.cs
03/25/2023 10:19 AM 3,584 program.exe
Now we run the .exe file through the CMD.
Desktop> program.exe
And it worked! How cool was that?
Summary
Let’s quickly go over some of the commands we’ve used in this series:
- mkdir — create a directory
- rmdir — remove a directory
- cd — navigate between directories and drives
- dir, tree — list out folders and files
- cls — clear Command Prompt
- esc — cancel command
- start — run executables
- /? — list of options that can be applied to a command
- & — command break. Used to execute Multiple commands in a line
- echo — print or insert text
- “ “ — wrap text within quotes whenever you have words with space in between
- ipconfig — list IP addresses
- set — create a variable
As mentioned before, we can execute commands in whichever casing we like, but we can’t have files in the same directory having the same names even if the casing is different.
Code, Commit, Deploy
When it comes to using third-party tools, such as Git, NPM, AWS-CLI, etc, the commands you type in CMD are the same as those in the Unix terminal.
- Git
git add, git commit, git pull/push
- Nginx
start nginx, nginx -s reload
- Docker
docker run hello-world, docker build .
- Node.js
node app.js, npm i, npm init -y
- .NET
dotnet new, dotnet run
- Secure Shell
ssh ip
The only difference is that we don’t type sudo.
Wrapping Up
This is where this series ends but it is not the end of the Command Prompt. We only scratched the surface of shells can do. I also recommend you try the Unix terminal as it has far greater capabilities. However, if you’re interested to learn more about CMD, be sure to check the section below.
Learn More
Other Command Prompt apps that can be used on a Windows machine:
- Chocolatey
- Commander
- Powershell
- Git Bash