文章目录
- 一、获取用户输入
- 1.读取单行数据
- 2.读取多行数据
- 二、一个猜数字的游戏
- 1.创建一个新项目
- 2.生成一个随机目标
- 3.进行一次猜测
- 4.多次猜测
- 三、CTF自测工具
- 1.整理资料
- 2.写一个检查函数
- 3.整合代码
- 4.增加回答次数
- 四、编译程序
一、获取用户输入
在Rust语言中,你可以使用标准库中的std::io模块来获取用户的输入。
1.读取单行数据
use std::io;
fn main() {
println!("请输入一些文本:");
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => println!("你输入了:{}", input),
Err(error) => println!("读取错误:{:?}", error),
}
}
2.读取多行数据
use std::io::BufRead;
fn main() {
println!("请输入一些文本:");
for line in std::io::stdin().lock().lines() { // 直接使用std::io::stdin()
match line {
Ok(n) if n == "quit" => break,
Ok(l) => println!("你输入了:{}", l),
Err(error) => println!("读取错误:{:?}", error),
}
}
}
二、一个猜数字的游戏
这也是官方提供的案例
1.创建一个新项目
cargo new guessing_game
- 编写cargo.toml文件
[dependencies]
rand = "0.9.0-alpha.0"
2.生成一个随机目标
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1..=100);
println!("The secret number is: {secret_number}");
}
3.进行一次猜测
use rand::Rng;
use std::cmp::Ordering;
use std::io;
fn main() {
println!("Guess the number!");
// 随机获取一个1-100之间的随机数
let secret_number = rand::thread_rng().gen_range(1..=100);
println!("The secret number is: {secret_number}");
//
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");
println!("You guessed: {guess}");
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
4.多次猜测
在单次猜测外面嵌套一个loop,注意loop是无条件循环,注意设置循环结束条件
use rand::Rng;
use std::cmp::Ordering;
use std::io;
fn main() {
println!("Guess the number!");
// 随机获取一个1-100之间的随机数
let secret_number = rand::thread_rng().gen_range(1..=100);
println!("The secret number is: {secret_number}");
//
loop {
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");
println!("You guessed: {guess}");
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
return;},
}
}
}
测试没有问题就把打印秘密数字的语句注释掉,利用cargo build
进行编译,一个简单的猜数字游戏就完成了。
三、CTF自测工具
由于英文不过关,学习CTF的时候好多单词、语句记不住,利用Rust实现一个自测工具,一方面巩固Rust基础,另一方面每天一练形成肌肉记忆。
1.整理资料
// 东西不多,用Hashmap整理题目和答案的对应。
use std::collections::HashMap;
fn main(){
let mut questions = HashMap::new();
questions.insert(String::from("SQL注入中查询数据库库名的语句"), "select group_concat(schema_name) from information_schema.schemata --+".to_string());
questions.insert(String::from("SQL注入中查询数据库表名的语句"),"select group_concat(table_name) from information_schema.tables where table_schema= 'databases' --+".to_string());
questions.insert(String::from("SQL注入中查询数据库字段名的语句"),"select group_concat(column_name) from information_schema.columns where table_name= 'tables' and table_schema= 'databases' --+".to_string());
questions.insert(String::from("利用sqlmap默认选项注入,绕过空格,读取key"),"python sqlmap.py -r a.txt --batch --file-read \"./key\" --tamper 'space2comment'".to_string());
questions.insert(String::from("利用php伪协议读取文件,base64"), "Php://filter/read-convert.base64-encode/resource=../key".to_string());
questions.insert(String::from("使用data伪协议执行命令"), "data://text/plain,<?=system('whoami');?>".to_string());
for (question,answer)in &questions{
println!("question:{},answer:{}",question,answer);
}
}
2.写一个检查函数
// 向函数传递问题和答案,获取用户输入匹配答案,返回是否正确。
fn check_answer(question: &str, answer: &str) -> bool {
println!("{} ", question);
let stdin = io::stdin();
let mut reader = stdin.lock();
let mut input = String::new();
reader.read_line(&mut input).unwrap(); // 读取一行输入
let trimmed_input = input.trim(); // 移除可能的前后空白字符,包括换行符
// 检查用户输入是否与正确答案匹配
trimmed_input == answer
}
3.整合代码
use std::collections::HashMap;
use std::io::{self, BufRead};
fn main(){
let mut questions = HashMap::new();
questions.insert(String::from("SQL注入中查询数据库库名的语句"), "select group_concat(schema_name) from information_schema.schemata --+".to_string());
questions.insert(String::from("SQL注入中查询数据库表名的语句"),"select group_concat(table_name) from information_schema.tables where table_schema= 'databases' --+".to_string());
questions.insert(String::from("SQL注入中查询数据库字段名的语句"),"select group_concat(column_name) from information_schema.columns where table_name= 'tables' and table_schema= 'databases' --+".to_string());
questions.insert(String::from("利用sqlmap默认选项注入,绕过空格,读取key"),"python sqlmap.py -r a.txt --batch --file-read \"./key\" --tamper 'space2comment'".to_string());
questions.insert(String::from("利用php伪协议读取文件,base64"), "Php://filter/read-convert.base64-encode/resource=../key".to_string());
questions.insert(String::from("使用data伪协议执行命令"), "data://text/plain,<?=system('whoami');?>".to_string());
for (question,answer)in &questions{
if check_answer(question, answer) {
println!("Correct!");
} else {
println!("Incorrect!");
println!("correct answer:{}",answer)
}
}
}
fn check_answer(question: &str, answer: &str) -> bool {
println!("{} ", question);
let stdin = io::stdin();
let mut reader = stdin.lock();
let mut input = String::new();
reader.read_line(&mut input).unwrap(); // 读取一行输入
let trimmed_input = input.trim(); // 移除可能的前后空白字符,包括换行符
// 检查用户输入是否与正确答案匹配
trimmed_input == answer
}
4.增加回答次数
// 在主函数增加次数条件
for (question,answer)in &questions{
let mut i = 0; // 回答次数计数器
loop {
if check_answer(question, answer) {
println!("Correct!");
break;
} else {
println!("Incorrect!");
}
i += 1;
// 判断是否达到次数上限
if i == 3{
println!("correct answer:{}",answer);
break;
}
}
}
四、编译程序
如果使用高版本linux编译,在低版本Linux中运行,会提示glibc不匹配,所以编译是使用使用
musl
替代glibc
错误: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33’ not found (required by ./ctf)
- 配置Cargo:
[target.x86_64-unknown-linux-musl]
linker = "rust-lld" # 或者其他适合musl的链接器
注意:这里假设你使用了lld链接器,但你也可以使用其他支持musl的链接器。
- 安装musl工具链:
rustup target add x86_64-unknown-linux-musl
- 编译程序:
cargo build --target x86_64-unknown-linux-musl --release
**然后再项目文件夹下的/target/x86_64-unknown-linux-musl/release
文件夹下,就可以找到编译好的程序了