Most efficient replacement for IsBadReadPtr?

前端 未结 10 1241
你的背包
你的背包 2020-12-06 06:45

I have some Visual C++ code that receives a pointer to a buffer with data that needs to be processed by my code and the length of that buffer. Due to a bug outside my contro

相关标签:
10条回答
  • 2020-12-06 07:14

    if you are using VC++ then I suggest to use microsoft specific keywords __try __except to and catch HW exceptions

    0 讨论(0)
  • 2020-12-06 07:18

    The fastest solution I can think of is to consult the virtual memory manager using VirtualQuery to see if there is a readable page at the given address, and cache the results (however any caching will reduce the accuracy of the check).

    Example (without caching):

    BOOL CanRead(LPVOID p)
    {
      MEMORY_BASIC_INFORMATION mbi;
      mbi.Protect = 0;
      ::VirtualQuery(((LPCSTR)p) + len - 1, &mbi, sizeof(mbi));
      return ((mbi.Protect & 0xE6) != 0 && (mbi.Protect & PAGE_GUARD) == 0);
    }
    
    0 讨论(0)
  • 2020-12-06 07:20

    If you have to resort to checking patterns in data, here are a few tips:

    • If you mention using IsBadReadPtr, you are probably developing for Windows x86 or x64.

    • You may be able to range check the pointer. Pointers to objects will be word aligned. In 32-bit windows, user-space pointers are in the range of 0x00401000-0x7FFFFFFF, or for large-address-aware applications, 0x00401000-0xBFFFFFFF instead (edit: 0x00401000-0xFFFF0000 for a 32-bit program on 64-bit windows). The upper 2GB/1GB is reserved for kernel-space pointers.

    • The object itself will live in Read/Write memory which is not executable. It may live in the heap, or it may be a global variable. If it is a global variable, you can validate that it lives in the correct module.

    • If your object has a VTable, and you are not using other classes, compare its VTable pointer with another VTable pointer from a known good object.

    • Range check the variables to see if they are possibly valid. For example, bools can only be 1 or 0, so if you see one with a value of 242, that's obviously wrong. Pointers can also be range checked and checked for alignment as well.

    • If there are objects contained within, check their VTables and data as well.

    • If there are pointers to other objects, you can check that the object lives in memory that is Read/Write and not executable, check the VTable if applicable, and range check the data as well.

    If you do not have a good object with a known VTable address, you can use these rules to check if a VTable is valid:

    • While the object lives in Read/Write memory, and the VTable pointer is part of the object, the VTable itself will live in memory that is Read Only and not executable, and will be aligned to a word boundary. It will also belong to the module.
    • The entries of the VTable are pointers to code, which will be Read Only and Executable, and not writable. There is no alignment restrictions for code addresses. Code will belong to the module.
    0 讨论(0)
  • 2020-12-06 07:20

    I am afraid you are out of luck - there is no way to reliably check the validity of a pointer. What Microsoft code is giving you bad pointers?

    0 讨论(0)
  • 2020-12-06 07:25

    The reason these functions are bad to use is that the problem can't be solved reliably.

    What if the function you're calling returns a pointer to memory that is allocated, so it looks valid, but it's pointing to other, unrelated data, and will corrupt your application if you use it.

    Most likely, the function you're calling actually behaves correctly, and you are misusing it. (Not guaranteed, but that is often the case.)

    Which function is it?

    0 讨论(0)
  • 2020-12-06 07:26
    bool IsBadReadPtr(void* p)
    {
        MEMORY_BASIC_INFORMATION mbi = {0};
        if (::VirtualQuery(p, &mbi, sizeof(mbi)))
        {
            DWORD mask = (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY);
            bool b = !(mbi.Protect & mask);
            // check the page is not a guard page
            if (mbi.Protect & (PAGE_GUARD|PAGE_NOACCESS)) b = true;
    
            return b;
        }
        return true;
    }
    
    0 讨论(0)
提交回复
热议问题