microsoft / windows-rs

Rust for Windows
https://kennykerr.ca/rust-getting-started/
Apache License 2.0
10.31k stars 484 forks source link

GetAttribute Function from IAmsiStream return ERROR_INVALID_PARAMETERS with certain AMSI_ATTRIBUTE #3219

Closed TheoTurletti closed 3 weeks ago

TheoTurletti commented 3 weeks ago

Summary

The GetAttribute function return ERROR_INVALID_PARAMETERS with these following AMSI_ATTRIBUTE :

windows crate version : 0.58

Here is my implementation of the scan function of my amsi_provider.

impl IAntimalwareProvider_Impl for MyProvider_Impl {
    fn Scan(&self, stream: Option<&IAmsiStream>)  -> Result<AMSI_RESULT>
    {
        if stream.is_none(){
            return Ok(AMSI_RESULT_NOT_DETECTED)
        }
        let stream = stream.unwrap();

        let app_name = get_string_attribute(stream, AMSI_ATTRIBUTE_APP_NAME);
        let content_name = get_string_attribute(stream, AMSI_ATTRIBUTE_CONTENT_NAME);
        let content_size = get_u64_attribute(stream, AMSI_ATTRIBUTE_CONTENT_SIZE);
        let session = get_u64_attribute(stream, AMSI_ATTRIBUTE_SESSION);

       // I know it's a LPVOID result but i am just retrieveing GetAttribute data from a Vec<u8> buffer for the moment
        let address = get_u64_attribute(stream, AMSI_ATTRIBUTE_CONTENT_ADDRESS);

...
}

And here is the result from a log file when i register my customamsi.dll COM server and launch a command on powershell that will call the Scan function :

App Name :PowerShell_C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe_10.0.22621.4163
Content Name :C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1
Content Size : ERROR :The parameter is incorrect.-0x80070057
session :  ERROR :The parameter is incorrect.-0x80070057
address :  ERROR :The parameter is incorrect.-0x80070057

The content of both get_attribute functions starts with :

pub fn get_{...}_attribute(stream: &IAmsiStream,attribute: AMSI_ATTRIBUTE) 
-> String {

    let mut alloc_size: u32 = 0;
    let mut buffer : Vec<u8> = vec![];

    // First call to GetAttribute to get the required size
    let _res = match unsafe {stream.GetAttribute(attribute, &mut buffer, &mut alloc_size) }{
        Ok(_) => {},
        Err(hr) => {

        .... Error handling logic to reallocate if ERROR_INSUFFICIENT_BUFFER or exit if invalid paremeters ...
 }
riverar commented 3 weeks ago

The IAmsiStream::GetAttribute method does not consistently use variable-sized return buffers. For example, the AMSI_ATTRIBUTE_CONTENT_SIZE attribute returns a ULONGLONG (u64) value, which requires the dataSize parameter to be set to 8. Therefore, make sure to resize the buffer to the appropriate size before making the call.

Closing this for now, but feel free to keep the discussion going.

TheoTurletti commented 3 weeks ago

Thank you very much !