Skip to content

Returning a released pointer from RangeDetails::with_address #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mkravchik opened this issue Jan 3, 2024 · 6 comments
Closed

Returning a released pointer from RangeDetails::with_address #120

mkravchik opened this issue Jan 3, 2024 · 6 comments

Comments

@mkravchik
Copy link

mkravchik commented Jan 3, 2024

Hi,
I consistently encountered this in the code I'm debugging. There is a call to RangeDetails::with_address. The returned value is complete nonsense.
When I debug it, I can see that when the save_range_details_by_address is called, it is passed a pointer to a details struct with correct data. However when we get back to with_address, the pointer points to garbage. I can only assume that the native Gum has freed this object and don't see anything preventing it from doing so.

pub fn with_address(address: u64) -> Option<RangeDetails<'a>> {
    let mut context = SaveRangeDetailsByAddressContext {
        address,
        details: core::ptr::null_mut(),
    };
    unsafe {
        gum_sys::gum_process_enumerate_ranges(
            gum_sys::_GumPageProtection_GUM_PAGE_NO_ACCESS as u32,
            Some(save_range_details_by_address),
            &mut context as *mut _ as *mut c_void,
        );
    }

    if !context.details.is_null() {
        Some(RangeDetails::from_raw(context.details))
    } else {
        None
    }
}
@s1341
Copy link
Contributor

s1341 commented Jan 4, 2024

Nice catch!

The upstream code is (for linux) https://github.com/frida/frida-gum/blob/a50dae75a25cb7fe95ed09883527dbd6777f28be/gum/backend-linux/gumprocess-linux.c#L1398.

I will attempt a fix now.

@s1341
Copy link
Contributor

s1341 commented Jan 4, 2024

@mkravchik can you try this fix and confirm it is working?

@s1341
Copy link
Contributor

s1341 commented Jan 4, 2024

Oh wait. I'm dumb... This doesn't fix at all...

@s1341
Copy link
Contributor

s1341 commented Jan 4, 2024

Ok. Try now

@mkravchik
Copy link
Author

I tried it, and it looks good. In the meantime (until the version is out) I've found the following workaround useful:

/// Get the start and end of the memory region containing the given address
/// Uses RangeDetails::enumerate_with_prot as RangeDetails::with_address seems to have a bug
/// Returns (start, end)
fn range_for_address(address: usize) -> (usize, usize) {
    let mut start = 0; 
    let mut end = 0; 
    RangeDetails::enumerate_with_prot(PageProtection::NoAccess, &mut |range: &RangeDetails| {
        let range_start = range.memory_range().base_address().0 as usize;
        let range_end = range_start + range.memory_range().size();
        if range_start <= address && range_end >= address {
            start = range_start;
            end = range_end;
            // I want to stop iteration here
            return false;
        }
        true
    });

    if start == 0 {
        log::error!("range_for_address: no range found for address {:#x}", address);
    }
    (start, end)
}

@s1341
Copy link
Contributor

s1341 commented Jan 7, 2024

I'll wait till the next frida version to release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants