Changing/Creating Windows registry.pol using Rust - windows

I'm trying to edit registry.pol file.
, but I do not know how to save changes.
I used crate registry-pol (https://docs.rs/registry-pol/1.0.0/registry_pol/v1/fn.parse.html) to read content of the current file.
let mut f = File::open("c:\\windows\\System32\\GroupPolicy\\machine\\registry.pol").unwrap();
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).unwrap();
let mut x = registry_pol::v1::parse(&buffer).unwrap();
let value: u32 = 1;
let bytes = value.to_le_bytes();
x.push(registry_pol::v1::RegistryValue {
key: "any key".to_string(),
value: Some("any value".to_string()),
data_type: Some(registry_pol::v1::RegistryValueType::REG_DWORD),
data: Some(bytes.to_vec()),
});
But if I add anything to Vec I do not have a clue how to save it as new registry.pol file.
Thanks

Related

How to wait for the last cmd command to generate a file, and then read the binary of this file, using Rust

I am writing a program, the desired effect is to generate a lua file, then compile this lua on windows platform using luac.exe and read the binary value of the generated luac.out file.
My code is here
fn test(lua_path: PathBuf, luac_path: String) -> Result<String, Box<dyn Error>> {
let index = luac_path.rfind("/").ok_or("path fail")?;
let (path, file) = luac_path.split_at(index + 1);
let cmd_str = format!("/c cd /d {} && .\\{} {}", path, file, lua_path.display());
let child = Command::new("cmd").raw_arg(cmd_str).spawn()?;
let output = child.wait_with_output()?;
if !output.status.success() {
let output_str = String::from_utf8(output.stderr)?;
return Err(output_str.into());
}
// Without the following code, luac.out will be generated normally.
// But once the following code is added, luac.out will be generated as 0kb and receive an access denied error
let out_path = Path::new(&path).join("luac.out");
let mut out_file = File::create(&out_path)?;
let mut buf = Vec::new();
out_file.read_to_end(&mut buf)?;
let result = String::from_utf8_lossy(&buf).to_string();
Ok(result)
}
My guess is that after executing child.wait, the file is not created to completion and then the program accesses it causing an error, how do I fix this?

Trying to Read Process Memory with windows_sys::Win32::System::Diagnostics::Debug::ReadProcessMemory in rust

I'm trying to read health in rust from a game called Assault cube.
However i allways have 0 stored in buffer. can anyone explain what i´m doing wrong?
my code looks like this:
fn main(){
unsafe{
use std::ffi::c_void;
use windows_sys::Win32::Foundation::HANDLE;
let process_id:HANDLE = 13488;
let health_adress = 0x005954FC as *const c_void;
let buffer: *mut c_void = std::ptr::null_mut();
let mut number_read:usize= 0;
windows_sys::Win32::System::Diagnostics::Debug::ReadProcessMemory(process_id, health_adress, buffer,4 , &mut number_read);
println!("{:?}", buffer as i32);
}
}
the picture below shows how I got the address with Cheat Engine.

How To Convert Vec<u8> to &str or String in substrate runtime

let container_returned_data = container::Module::<T>::check_for_app_name(&app_id,&instruction_name); //container_returned_data is tuple contains (bool,Vec<(Vec<u8>,Vec<u8>)>)
if container_returned_data.0{
let d = container_returned_data.1[0].1.clone();
let data_str:&str = from_utf8(&d).unwrap();
let data_str2 = data_str.to_string();
debug::error!(target:"runner","{:?}",&data_str2);
// debug::error!(target:"norm","{:?}",&data_str2);
Self::function_executer(data_str);
//now implement the ail_v2 function inside this.
unsafe{
Self::deposit_event(Event::FunctionsReceived(FUNCTION.clone()));
}
}
I have used core::str::from_utf8 but it is not converting the bytes to array
I have to perform the following steps
let querys_ = query_.replace("\n","").trim().trim_end().to_string();
let l_data_querys:Vec<&str> = querys_.trim().trim_end().split("<<-").collect();

Rust FFI with windows CryptoUnprotectData

I'm trying to learn FFI by starting with something simple (and with a practical use), but this doesn't seem to work:
mod bindings {
::windows::include_bindings!();
}
use std::{convert::TryFrom, ptr};
use bindings::{
windows::win32::security::CryptUnprotectData,
windows::win32::security::CRYPTOAPI_BLOB
};
// Powershell code to generate the token
// $pw = read-host "Enter Token" -AsSecureString
// ConvertFrom-SecureString $pw
fn main() -> windows::Result<()> {
// The encrypted string is 'foobar'
let encrypted_token = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000c336dca1c99b7d40ae3f797c2b5d2951000000000200000000001066000000010000200000007a87d6ac2fc8037bef45e3dbcb0b652432a22a9b48fc5fa3e4fcfd9aaf922949000000000e8000000002000020000000eeaa76a44b6cd5da837f4b0f7040de8e2795ed846f8abe2c7f2d2365d00cf89c1000000069fcaa7fa475178d623f4adab1b08ac4400000008af807014cba53ed2f1e7b8a54c6ad89ff57f0ee3d8c51ecd8c5b48e99b58d0e738c9fae9fc41b4280938865a047f2724106d34313c88a0f3852d5ba9d75abfd";
let mut et_bytes = hex::decode(encrypted_token).unwrap();
let size = u32::try_from(et_bytes.len()).unwrap();
let mut decrypted = vec![0u8; et_bytes.len()];
let dt_bytes = &mut decrypted;
let mut p_data_in = CRYPTOAPI_BLOB {
cb_data: size,
pb_data: et_bytes.as_mut_ptr(),
};
let mut p_data_out = CRYPTOAPI_BLOB {
cb_data: size,
pb_data: dt_bytes.as_mut_ptr(),
};
let pin = &mut p_data_in;
let pout = &mut p_data_out;
unsafe {
let result = CryptUnprotectData(
pin,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
0,
pout
);
println!("{:?}, {:?}", dt_bytes, result);
}
Ok(())
}
Basically it returns the all zero array, but the result of the CryptUnprotectData returns 1, which according to the docs means success: https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectdata
I've verified that by trying to mangle the hex string thus corrupting the encrypted data, which causes it to return 0. I'm not sure if it's writing to the wrong location or something, but presumably the success condition means it wrote somewhere.
The CryptUnprotectData API allocates the output buffer for you. It doesn't write into the buffer you provided. That's why you keep getting the original data, irrespective of the API call's result.
Instead, you'll want to pass in a (default-initialized) CRYPTOAPI_BLOB structure, and observe the values the API passed back, something like the following will do:
fn main() -> windows::Result<()> {
// The encrypted string is 'foobar'
let encrypted_token = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000c336dca1c99b7d40ae3f797c2b5d2951000000000200000000001066000000010000200000007a87d6ac2fc8037bef45e3dbcb0b652432a22a9b48fc5fa3e4fcfd9aaf922949000000000e8000000002000020000000eeaa76a44b6cd5da837f4b0f7040de8e2795ed846f8abe2c7f2d2365d00cf89c1000000069fcaa7fa475178d623f4adab1b08ac4400000008af807014cba53ed2f1e7b8a54c6ad89ff57f0ee3d8c51ecd8c5b48e99b58d0e738c9fae9fc41b4280938865a047f2724106d34313c88a0f3852d5ba9d75abfd";
let mut et_bytes = hex::decode(encrypted_token).unwrap();
let size = u32::try_from(et_bytes.len()).unwrap();
let mut p_data_in = CRYPTOAPI_BLOB {
cb_data: size,
pb_data: et_bytes.as_mut_ptr(),
};
// Default-initialze; don't allocate any memory
let mut p_data_out = CRYPTOAPI_BLOB::default();
let pin = &mut p_data_in;
let pout = &mut p_data_out;
unsafe {
let result = CryptUnprotectData(
pin,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
0,
pout
);
// Probably safe to ignore `result`
if !p_data_out.pb_data.is_null() {
// Construct a slice from the returned data
let output = from_raw_parts(p_data_out.pb_data, p_data_out.cb_data as _);
println!("{:?}", output);
// Cleanup
LocalFree(p_data_out.pb_data as _);
}
Ok(())
}
That produces the following output for me:
[102, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0]
which is the UTF-16LE encoding for foobar.
Note that you need have to generate and import windows::win32::system_services::LocalFree to perform the cleanup.

Insert into hashmap in a loop

I'm opening a CSV file and reading it using BufReader and splitting each line into a vector. Then I try to insert or update the count in a HashMap using a specific column as key.
let mut map: HashMap<&str, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens: Vec<&str> = s.split(&d).collect(); // <-- `s` does not live long enough
if tokens.len() > c {
println!("{}", tokens[c]);
let count = map.entry(tokens[c].to_string()).or_insert(0);
*count += 1;
}
}
The compiler kindly tells me s is shortlived. Storing from inside a loop a borrowed value to container in outer scope? suggests "owning" the string, so I tried to change
let count = map.entry(tokens[c]).or_insert(0);
to
let count = map.entry(tokens[c].to_string()).or_insert(0);
but I get the error
expected `&str`, found struct `std::string::String`
help: consider borrowing here: `&tokens[c].to_string()`
When I prepend ampersand (&) the error is
creates a temporary which is freed while still in use
note: consider using a `let` binding to create a longer lived
There is some deficiency in my Rust knowledge about borrowing. How can I make the hashmap own the string passed as key?
The easiest way for this to work is for your map to own the keys. This means that you must change its type from HasMap<&str, i32> (which borrows the keys) to HashMap<String, i32>. At which point you can call to_string to convert your tokens into owned strings:
let mut map: HashMap<String, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens:Vec<&str> = s.split(&d).collect();
if tokens.len() > c {
println!("{}", tokens[c]);
let count = map.entry(tokens[c].to_string()).or_insert(0);
*count += 1;
}
}
Note however that this means that tokens[c] will be duplicated even if it was already present in the map. You can avoid the extra duplication by trying to modify the counter with get_mut first, but this requires two lookups when the key is missing:
let mut map: HashMap<String, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens:Vec<&str> = s.split(&d).collect();
if tokens.len() > c {
println!("{}", tokens[c]);
if let Some (count) = map.get_mut (tokens[c]) {
*count += 1;
} else {
map.insert (tokens[c].to_string(), 1);
}
}
}
I don't know of a solution that would only copy the key when there was no previous entry but still do a single lookup.

Resources