WinAPI Access violation

Hi there! My code is:

let mut password: Vec<u8> = vec![118, 49, 48, 34, 232, 193, 1, 71, 249, 76, 132, 1, 155, 184, 92, 55, 137, 229, 130, 135, 100, 247, 164, 23, 224, 41, 49, 48, 88, 96, 74, 25, 239, 112, 99, 53, 251, 122, 173, 170, 210, 200, 88, 56, 194, 0];
    let bytes: u32 = password.len().try_into().unwrap();
    let mut blob = CRYPTOAPI_BLOB{cbData: bytes, pbData: password.as_mut_ptr()};
    let mut new_blob: *mut CRYPTOAPI_BLOB = ptr::null_mut();
    unsafe {
        let res = CryptUnprotectData(&mut blob, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), 0, new_blob);
        println!("{}", res);
        let err = GetLastError();
        println!("Err: {}", err);
        let data = *new_blob;
        println!("Deferenced!");
        let cb_data = data.cbData.try_into().unwrap();
        let vec = Vec::from_raw_parts(data.pbData, cb_data, cb_data);
    }

But there's segfault on line 10:

0
Err: 0
error: process didn't exit successfully: `target\debug\test.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
  1. res of CryptUnprotectData is a BOOL, 0 means failure.
  2. You're calling GetLastError after println! which invalidates the relevant error.

You're dereferencing a null pointer.

I think new_blob needs to be a concrete structure, the same as blob. CryptUnprotectData takes a pointer to this structure and fills out the fields.

let mut password: Vec<u8> = vec![118, 49, 48, 34, 232, 193, 1, 71, 249, 76, 132, 1, 155, 184, 92, 55, 137, 229, 130, 135, 100, 247, 164, 23, 224, 41, 49, 48, 88, 96, 74, 25, 239, 112, 99, 53, 251, 122, 173, 170, 210, 200, 88, 56, 194, 0];
let bytes: u32 = password.len().try_into().unwrap();
let mut blob = CRYPTOAPI_BLOB{cbData: bytes, pbData: password.as_mut_ptr()};
let mut new_blob = CRYPTOAPI_BLOB{cbData: 0, pbData: ptr::null_mut()};
unsafe {
    let res = CryptUnprotectData(&mut blob, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), 0, &mut new_blob);
    let err = GetLastError();
    println!("{}", res);
    if res == FALSE {
        println!("Err: {}", err);
    } else {
        let cb_data = new_blob.cbData.try_into().unwrap();
        let vec = Vec::from_raw_parts(new_blob.pbData, cb_data, cb_data);
    }
}

Thanks, now I got an error with code 87.
It's ERROR_INVALID_PARAMETER

So, I dont know which param is incorrect.

All params except first one can be null. So..are my blob wrong?

Or ppszDataDescr is wrong either.

And I don't know what is wrong.

Sorry, I'm not familiar with this API. The only thing I can guess is that blob data you're giving it is wrong in some way. As you say, all other input parameters are optional.

You might want to look at this example C program and see if you can get something working based on that. Once you have something that works it should be easier to adapt it to your needs.

In this example, pDescrOut = NULL;, just like I did in my code

Right but I think the issue is with pDataIn. I suspect the data in pbData isn't quite what it's expecting, which is why I would suggest first trying to use both CryptProtectData and CryptUnprotectData the same way they are in the example. But I'm just guessing.

Yep. It can encrypt and decrypt! But it can't decrypt other data.

So, my pet-project is chrome passwords backup-er, so I get passwords in Local Data:

let connection = sqlite::open("data.db").unwrap();
    let mut statement = connection
        .prepare("SELECT action_url, username_value, password_value FROM logins")
        .unwrap();
    while let State::Row = statement.next().unwrap() {
     let action_url: String = statement.read(0).unwrap();
     let username_value: String = statement.read(1).unwrap();
     let mut password: Vec<u8> = statement.read(2).unwrap();
}

Then I'm trying to decrypt passwords, and as you can see - it doesnt work. I found a python code, which decrypts chrome passwords. But I've the same code in Rust, but it does not work! So, what did I do wrong?

The only other thing I can suggest is that the database is returning bad values in Rust for some reason. If you get the Python script to print the raw result[2] then maybe you can compare that with the bytes you're getting in Rust. Just to confirm they're actually the same.

Huh. You're right! Can you advice any sqlite crate?

Sorry, I wouldn't have clue. You might get a more helpful answer by asking a new question about SQL.

Anyway, thanks for helping!

Hey! Now I too need to use CryptUnprotectData and I have 87 code error (ERROR_INVALID_PARAMETER), anyone can help me? :worried: