virtualqueryex()大多返回无用的数据

发布于 2025-01-29 10:54:20 字数 3479 浏览 2 评论 0原文

我已经写了一个小程序来查询一个过程的页面图:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <stdexcept>

using namespace std;

int main( int argc, char **argv )
{
    if( argc < 2 )
        return EXIT_FAILURE;
    try
    {
        DWORD dwProcessId = [&]() -> DWORD
            {
                DWORD dwRet;
                from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
                if( fcr.ec != errc() || *fcr.ptr )
                    throw invalid_argument( "process-id unparseable" );
                return dwRet;
            }();
        HANDLE hProcess = [&]() -> HANDLE
            {
                HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
                if( !hRet )
                    throw system_error( (int)GetLastError(), system_category(), "can't open process" );
                return hRet;
            }();
        size_t pageSize = []() -> size_t
            {
                SYSTEM_INFO si;
                GetSystemInfo( &si );
                return si.dwPageSize;
            }();
        using mbi_t = MEMORY_BASIC_INFORMATION;
        vector<mbi_t> mbis( 0x100 );
        size_t nRegions;
        while( !(nRegions = VirtualQueryEx( hProcess, nullptr, to_address( mbis.begin() ), mbis.size() * sizeof(mbi_t) )) )
            if( GetLastError() == ERROR_BAD_LENGTH )
                mbis.resize( mbis.size() * 2 );
            else
                throw system_error( (int)GetLastError(), system_category(), "can't query process pages" );
        mbis.resize( nRegions );
        for( mbi_t const &mbi : mbis )
        {
            cout << "base address: " << hex << mbi.BaseAddress << endl;
            cout << "allocation base: " << hex << mbi.AllocationBase << endl;
            cout << dec << mbi.RegionSize / pageSize << " pages" << endl;
            static struct
            {
                DWORD dwProtect;
                char const *str;
            } const protectMaps[] =
            {
                { PAGE_EXECUTE, "PAGE_EXECUTE" },
                { PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
                { PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
                { PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
                { PAGE_NOACCESS, "PAGE_NOACCESS" },
                { PAGE_READONLY, "PAGE_READONLY" },
                { PAGE_READWRITE, "PAGE_READWRITE" },
                { PAGE_WRITECOPY, "PAGE_WRITECOPY" }
            };
            for( auto const &pm : protectMaps )
                if( pm.dwProtect == mbi.AllocationProtect )
                {
                    cout << "state: " << pm.str << endl;
                    break;
                }
            if( mbi.Type == MEM_IMAGE )
                cout << "image";
            else if( mbi.Type == MEM_MAPPED )
                cout << "mapped";
            else if( mbi.Type == MEM_PRIVATE )
                cout << "private";
            cout << endl << endl;
        }
    }
    catch( exception const &exc )
    {
        cout << exc.what() << endl;
    }
}

不幸的是,该程序返回了null-data,除了第一个条目的页面数,这是逻辑页的数量该过程减去32.
我在这里做错了什么?
我尝试查询在同一令牌下运行的过程,因此Coudl没有任何特权问题。

I've written a little program to query the page-map of a process:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <stdexcept>

using namespace std;

int main( int argc, char **argv )
{
    if( argc < 2 )
        return EXIT_FAILURE;
    try
    {
        DWORD dwProcessId = [&]() -> DWORD
            {
                DWORD dwRet;
                from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
                if( fcr.ec != errc() || *fcr.ptr )
                    throw invalid_argument( "process-id unparseable" );
                return dwRet;
            }();
        HANDLE hProcess = [&]() -> HANDLE
            {
                HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
                if( !hRet )
                    throw system_error( (int)GetLastError(), system_category(), "can't open process" );
                return hRet;
            }();
        size_t pageSize = []() -> size_t
            {
                SYSTEM_INFO si;
                GetSystemInfo( &si );
                return si.dwPageSize;
            }();
        using mbi_t = MEMORY_BASIC_INFORMATION;
        vector<mbi_t> mbis( 0x100 );
        size_t nRegions;
        while( !(nRegions = VirtualQueryEx( hProcess, nullptr, to_address( mbis.begin() ), mbis.size() * sizeof(mbi_t) )) )
            if( GetLastError() == ERROR_BAD_LENGTH )
                mbis.resize( mbis.size() * 2 );
            else
                throw system_error( (int)GetLastError(), system_category(), "can't query process pages" );
        mbis.resize( nRegions );
        for( mbi_t const &mbi : mbis )
        {
            cout << "base address: " << hex << mbi.BaseAddress << endl;
            cout << "allocation base: " << hex << mbi.AllocationBase << endl;
            cout << dec << mbi.RegionSize / pageSize << " pages" << endl;
            static struct
            {
                DWORD dwProtect;
                char const *str;
            } const protectMaps[] =
            {
                { PAGE_EXECUTE, "PAGE_EXECUTE" },
                { PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
                { PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
                { PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
                { PAGE_NOACCESS, "PAGE_NOACCESS" },
                { PAGE_READONLY, "PAGE_READONLY" },
                { PAGE_READWRITE, "PAGE_READWRITE" },
                { PAGE_WRITECOPY, "PAGE_WRITECOPY" }
            };
            for( auto const &pm : protectMaps )
                if( pm.dwProtect == mbi.AllocationProtect )
                {
                    cout << "state: " << pm.str << endl;
                    break;
                }
            if( mbi.Type == MEM_IMAGE )
                cout << "image";
            else if( mbi.Type == MEM_MAPPED )
                cout << "mapped";
            else if( mbi.Type == MEM_PRIVATE )
                cout << "private";
            cout << endl << endl;
        }
    }
    catch( exception const &exc )
    {
        cout << exc.what() << endl;
    }
}

Unfortunately the program returns mostly null-data except from the number of pages with the first entry, which is the number of logical pages of the process minus 32.
What am I doing wrong here ?
The process I tried to query runs under the same token, so there coudln't be any privilege issues.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最笨的告白 2025-02-05 10:54:20

谢谢汉斯!你是对的。虽然virtualqueryex()仅填充许多内存_basic_information。如果您看不到在德国说的明显的话,那就是您的眼睛上有西红柿,是的,我的眼睛上有西红柿(不是因为我的风格;-))。

这是工作代码:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>

using namespace std;

vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess );

int main( int argc, char **argv )
{
    if( argc < 2 )
        return EXIT_FAILURE;
    try
    {
        DWORD dwProcessId = [&]() -> DWORD
            {
                DWORD dwRet;
                from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
                if( fcr.ec != errc() || *fcr.ptr )
                    throw invalid_argument( "process-id unparseable" );
                return dwRet;
            }();
        HANDLE hProcess = [&]() -> HANDLE
            {
                HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
                if( !hRet )
                    throw system_error( (int)GetLastError(), system_category(), "can't open process" );
                return hRet;
            }();
        size_t pageSize = []() -> size_t
            {
                SYSTEM_INFO si;
                GetSystemInfo( &si );
                return si.dwPageSize;
            }();
        vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( hProcess );
        for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
        {
            cout << "allocation base: " << hex << vmbi.front().AllocationBase << endl;
            for( MEMORY_BASIC_INFORMATION const &mbi : vmbi )
            {
                cout << "\tbase address: " << hex << mbi.BaseAddress << endl;
                cout << "\t" << dec << mbi.RegionSize / pageSize << " pages" << endl;
                static struct
                {
                    DWORD dwProtect;
                    char const *str;
                } const protectMaps[] =
                {
                    { PAGE_EXECUTE, "PAGE_EXECUTE" },
                    { PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
                    { PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
                    { PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
                    { PAGE_NOACCESS, "PAGE_NOACCESS" },
                    { PAGE_READONLY, "PAGE_READONLY" },
                    { PAGE_READWRITE, "PAGE_READWRITE" },
                    { PAGE_WRITECOPY, "PAGE_WRITECOPY" }
                };
                for( auto const &pm : protectMaps )
                    if( pm.dwProtect == mbi.AllocationProtect )
                    {
                        cout << "\tstate: " << pm.str << endl;
                        break;
                    }
                if( mbi.Type == MEM_IMAGE )
                    cout << "\timage" << endl;
                else if( mbi.Type == MEM_MAPPED )
                    cout << "\tmapped" << endl;
                else if( mbi.Type == MEM_PRIVATE )
                    cout << "\tprivate" << endl;
                cout << endl;
            }
        }
    }
    catch( exception const &exc )
    {
        cout << exc.what() << endl;
    }
}

template<typename Fn>
    requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );

vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess )
{
    vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
    enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
        {
            
            if( !vvmbis.size() || vvmbis.back().back().BaseAddress != mbi.BaseAddress )
                vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
            vvmbis.back().emplace_back( mbi );
            return true;
        } );
    return vvmbis;
}

template<typename Fn>
    requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
        MEMORY_BASIC_INFORMATION mbi;
        for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + mbi.RegionSize )
        {
            size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
            if( nBytes != sizeof mbi )
                if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
                    break;
                else
                    throw system_error( (int)dwErr, system_category(), "can't query process pages" );
            if( !fn( mbi ) )
                break;
        }
}

现在的代码分组分配基础。它的分散是可以在不更改框架的情况下扩展零件。

Thank you Hans ! You were right. I thoughth VirtualQueryEx() fills just a number of MEMORY_BASIC_INFORMATION. If you don't see something obvious you say in Germany that you've got tomatoes on your eyes, and yes, I had tomatoes on my eyes (not because of my style ;-)).

Here's the working code:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>

using namespace std;

vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess );

int main( int argc, char **argv )
{
    if( argc < 2 )
        return EXIT_FAILURE;
    try
    {
        DWORD dwProcessId = [&]() -> DWORD
            {
                DWORD dwRet;
                from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
                if( fcr.ec != errc() || *fcr.ptr )
                    throw invalid_argument( "process-id unparseable" );
                return dwRet;
            }();
        HANDLE hProcess = [&]() -> HANDLE
            {
                HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
                if( !hRet )
                    throw system_error( (int)GetLastError(), system_category(), "can't open process" );
                return hRet;
            }();
        size_t pageSize = []() -> size_t
            {
                SYSTEM_INFO si;
                GetSystemInfo( &si );
                return si.dwPageSize;
            }();
        vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( hProcess );
        for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
        {
            cout << "allocation base: " << hex << vmbi.front().AllocationBase << endl;
            for( MEMORY_BASIC_INFORMATION const &mbi : vmbi )
            {
                cout << "\tbase address: " << hex << mbi.BaseAddress << endl;
                cout << "\t" << dec << mbi.RegionSize / pageSize << " pages" << endl;
                static struct
                {
                    DWORD dwProtect;
                    char const *str;
                } const protectMaps[] =
                {
                    { PAGE_EXECUTE, "PAGE_EXECUTE" },
                    { PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
                    { PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
                    { PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
                    { PAGE_NOACCESS, "PAGE_NOACCESS" },
                    { PAGE_READONLY, "PAGE_READONLY" },
                    { PAGE_READWRITE, "PAGE_READWRITE" },
                    { PAGE_WRITECOPY, "PAGE_WRITECOPY" }
                };
                for( auto const &pm : protectMaps )
                    if( pm.dwProtect == mbi.AllocationProtect )
                    {
                        cout << "\tstate: " << pm.str << endl;
                        break;
                    }
                if( mbi.Type == MEM_IMAGE )
                    cout << "\timage" << endl;
                else if( mbi.Type == MEM_MAPPED )
                    cout << "\tmapped" << endl;
                else if( mbi.Type == MEM_PRIVATE )
                    cout << "\tprivate" << endl;
                cout << endl;
            }
        }
    }
    catch( exception const &exc )
    {
        cout << exc.what() << endl;
    }
}

template<typename Fn>
    requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );

vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess )
{
    vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
    enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
        {
            
            if( !vvmbis.size() || vvmbis.back().back().BaseAddress != mbi.BaseAddress )
                vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
            vvmbis.back().emplace_back( mbi );
            return true;
        } );
    return vvmbis;
}

template<typename Fn>
    requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
        MEMORY_BASIC_INFORMATION mbi;
        for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + mbi.RegionSize )
        {
            size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
            if( nBytes != sizeof mbi )
                if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
                    break;
                else
                    throw system_error( (int)dwErr, system_category(), "can't query process pages" );
            if( !fn( mbi ) )
                break;
        }
}

The code now groups the allocation bases. Its segemented that parts can be extended without changing the framework.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文