文章目录
- 一、获取用户输入
- 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
文件夹下,就可以找到编译好的程序了