sudo apt update
sudo apt install curl build-essential gdb -y
sudo apt install rustc -y
mkdir HelloWorld-App
cd HelloWorld-App
nano Hello.rs
Enter this code,
as shown below.
fn
main(){
println!("Rust says Hello!");
}
Save the file with Ctrl+X, Y, Enter.
Execute these commands to compile and run the program:
rustc Hello.rs
./Hello
The program runs,
as shown below.
cd
mkdir Int-App
cd Int-App
nano Int.rs
Enter this code:
fn main() {
let i = 1;
let j:u32 = -5;
println!("i is {}", i);
println!("j is {}", j);
}
Execute this command to compile
it:
rustc Int.rs
This program has errors.
Figure out the problem.
This tutorial should help:
R 10.1: Int (5 pts)
Change one character in the "Int.rs" program to fix it and produce this desired output:The flag is the complete fixed line.
cd
mkdir Add-App
cd Add-App
nano Add.rs
fn main() {
let a = 1;
a = a + 1;
println!("a is {}", a);
}
Save the file with Ctrl+X,
Y, Enter.
Execute this command to compile it:
rustc Add.rs
This program has errors.
Figure out the problem.
This tutorial should help:
R 10.2: Add (5 pts)
Add one three-letter keyword to a single line in the "Add.rs" program to fix it and produce this desired output:The flag is the complete fixed line.
nano ovc.c
Enter this code:
#include <stdio.h>
int main()
{
unsigned char x = 230;
int i;
for (i = 1; i < 10; i++)
{
x = x + i;
printf("x is %d\n",x);
}
}
Save the file with Ctrl+X,
Y, Enter.
Execute these commands to compile the program and run it:
gcc -o ovc ovc.c
./ovc
As shown below, the integer overflows
when it exceeds 255 and assumes incorrect
low values. It does not warn the developer,
so a bug like this can easily end up
in distributed software.
cd
mkdir Ov-App
cd Ov-App
nano Ov.rs
Enter this code:
fn main() {
let mut x:u8 = 230;
for y in 1..10{
x = x + y;
println!("x is {}",x);
}
}
Save the file with Ctrl+X,
Y, Enter.
Execute these commands to compile and run it:
rustc Ov.rs
./Ov
R 10.3: Overflow (5 pts)
Compile the file and run it.As shown below, Rust does not allow the integer to assume an incorrect value. Instead, it stops and alerts the developer with an error message.
The flag is covered by a green rectangle in the image below.
nano strovc.c
Enter this code:
#include <stdio.h>
int main()
{
char s1[5] = "AAAA";
char s2[5] = "BBBB";
printf("String 1 address: %p. String 2 address: %p.\n", s1, s2);
printf("String 1 contains %s. String 2 contains %s.\n", s1, s2);
printf("Enter new value for String 2:\n");
scanf("%s", s2);
printf("String 1 address: %p. String 2 address: %p.\n", s1, s2);
printf("String 1 contains %s. String 2 contains %s.\n", s1, s2);
}
Save the file with Ctrl+X,
Y, Enter.
Execute these commands to compile the program and run it:
gcc -o strovc strovc.c
./strovc
Note: if the address of String 1 is larger than
the address of String 2, change the program to
enter a new value for String 1.
The program asks for a new value. Enter eight "C" characters, as shown below.
The eight-letter value in String 2 overflows into String 1. As before, C just lets this awful thing happen without stopping or warning the developer.
This is the notorious "buffer overflow" vulnerability responsible for many viruses and other security problems.
cd
mkdir Str-App
cd Str-App
nano Str.rs
Enter this code:
fn main() {
let mut s1 = String::from("AAAA");
let mut s2 = String::from("BBBB");
println!("String 1 address: {:p}. String 2 address: {:p}.", &s1, &s2);
println!("String 1 contains {}. String 2 contains {}. ", s1, s2);
println!("Enter new value for String 1: ");
let num = std::io::stdin().read_line(&mut s1).unwrap();
println!("{} bytes read", num);
println!("String 1 address: {:p}. String 2 address: {:p}.", &s1, &s2);
println!("String 1 contains {}. String 2 contains {}. ", s1, s2);
}
Save the file with Ctrl+X,
Y, Enter.
Execute these commands to compile and run it. Don't omit the "-g" switch--we'll need it later for debugging.
rustc -g Str.rs
./Str
The program compiles with a warning
but no errors, as shown below.
When the program asks for a new value, enter eight "C" characters.
Notice these things:
gdb -q Str
list
The debugger starts, and shows
the Rust source code,
as shown below.
Execute these commands to set a breakpoint and start running the program:
break 7
run
The program initializes the strings
and halts at the breakpoint,
as shown below.
Execute these commands to examine memory where the strings are stored. You may have to adjust the addresses to match the addresses shown on your system:
x/2x 0x7fffffffdfc0
x/2x 0x7fffffffdfd8
The letters "A" and "B" are not stored here--they
would appear as "41" and "42" hex values.
Instead, pointers are stored here, as shown below.
Execute these commands to examine the details of how the strings are stored:
print s1
print s2
The debugger shows the two pointers,
outlined in green in the image below.
Execute these commands to see the stored strings, replacing the addresses with the correct addresses on your system:
x/4x 0x5555555a69d0
x/4x 0x5555555a69f0
The "AAAA" and "BBBB" letters are visible
as ASCII hex codes 41414141 and 42424242,
outlined in red in the image below.
break 10
continue
When the program asks for a new value, enter
eight "C" characters.
Execute these commands to examine the details of how the strings are stored, correcting the addresses as you did before:
print s1
print s2
x/4x 0x5555555a69d0
x/4x 0x5555555a69f0
Both strings are still stored in the same
locations, and even though String 1 is longer,
it hasn't overwritten String 2,
as shown below.
run
y
continue
When the program asks for a new value, enter
thirty "C" characters.
Execute these commands to examine the details of how the strings are stored, adjusting the addresses to match the new values of the pointers:
print s1
print s2
x/4x 0x5555555a8a20
x/4x 0x5555555a69f0
As shown below, String 2 is unchanged,
but String 1 is now stored at a different
address, so it can hold its longer
value without overflowing into the memory
used by String 2.
This is much safer. The developer doesn't need to remember how long the string is--it just resizes automatically as needed, and never corrupts memory used by some other variable.
R 10.4: String Storage (10 pts)
The flag is covered by a green rectangle in the image above.
cd
nano cmdi.c
Enter this code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char ip[30];
char cmd[40];
printf("IP:");
scanf("%s", ip);
strcpy(cmd, "ping -c 1 ");
strcat(cmd, ip);
system(cmd);
}
Save the file with Ctrl+X,
Y, Enter.
Execute these commands to compile the program and run it:
gcc -o cmdi cmdi.c
./cmdi
The program asks for an IP address.
Enter this IP:
8.8.8.8
The program sends a ping to that
address,
as shown below.
Run the program again, entering this address:
8.8.8.8;date
As shown below,
the program performs a ping
and then executes the "date"
command. This is another
common flaw: command injection.
Execute these commands to create a new Rust package named cmdi and edit its "Manifest":
cd
cargo new cmdinj
cd cmdinj
nano Cargo.toml
Add this line at the bottom,
as shown below.
cmd_lib = "0.6.5"
Save the file with Ctrl+X, Y, Enter.
Execute this command to edit the package's source code:
nano src/main.rs
Cargo creates a "Hello, world!"
program. Replace it with this
code:
use cmd_lib::{run_cmd};
fn main() {
let mut ip = String::new();
println!("Enter IP: ");
let _num = std::io::stdin().read_line(&mut ip).unwrap();
run_cmd!("ping -c 1 {}", ip);
}
Save the file with Ctrl+X, Y, Enter.
Execute this command to compile and run it:
cargo run
The program compiles with a warning
but no errors, as shown below,
and runs, asking for an IP address.
Enter:
8.8.8.8
The program
performs a "ping",
as shown below.
cargo run
Enter this IP:
8.8.8.8;date
The program
performs a "ping",
and then displays the date,
as shown below.
Rust does not prevent command injection vulnerabilities.
R 10.5: Lock File (10 pts)
Execute this command:The flag is covered by a green rectangle in the image below.
cat Cargo.lock
Posted 5-30-2020
R 10.3 instructions fixed 11-15-20
R 10.2 instructions fixed 4-26-2021
Rust install instructions updated 8-3-2021
Updated with different gdb commands 6-22-22
Minor updates 11-22-22
Video and note about string pointer order added 4-20-23