首页
社区
课程
招聘
[分享]如何读取其它进程地址空间的数据
发表于: 2006-3-31 09:41 7915

[分享]如何读取其它进程地址空间的数据

2006-3-31 09:41
7915

如何读取其它进程地址空间的数据

问题的提出:
          当发现某一程序执行时,在内存中存在有用的信息后,需要把这些数据从内存中读出并将其翻
译成直观的图表形式表达。跟着,需要设计哪部分呢?需要将一个地址放入一个指针中,之后读取指针值

          可是这些读取的内存数据是不存在于我的程序中,众所周知,每一个进程有它的独立的地址空
间以致它不能“意外”访问属于其它程序的内存区域,所以为了读取这些数据需要找一种读取其它进程内
存空间的方法。

问题的解决思路:
          写一个可以接收一个进程并且提供读取这个进程内存地址的功能的程序。可以将其封装在一个
简单的小类库中使用它们。设计成类库主要是因为有时由于很多的情况下你也会用到它,如:你可以利用
这个类写一个调试工具。据我所知,所有调试工具都有读取调试程序的内存的功能。

问题解决的实现过程:
          该怎么读取其它进程的地址空间?答案在一个名叫ReadProcessMemory的API函数。
          使用方法:
                   1.用一个特定的读取模式打开进程,这由OpenProcess完成。
                   2.用ReadProcessMemory读取此进程内存中的指定地址。
                   3.之后,为避免资源泄露必须关闭进程句柄。这由CloseHandle帮助完成。
          具体过程:
                   1.在MSDN中找到这些API的声明:
                         WINBASEAPI
                         HANDLE
                         WINAPI
                         OpenProcess(
                             DWORD dwDesiredAccess,
                             BOOL bInheritHandle,
                             DWORD dwProcessId
                             );
                        
                         WINBASEAPI
                         BOOL
                         WINAPI
                         ReadProcessMemory(
                             HANDLE hProcess,
                             LPCVOID lpBaseAddress,
                             LPVOID lpBuffer,
                             DWORD nSize,
                             LPDWORD lpNumberOfBytesRead
                             );

                         WINBASEAPI
                         BOOL
                         WINAPI
                         CloseHandle(
                             HANDLE hObject
                             );
                    2.分析程序,找到此程序在内存中有用信息的地址(以扫雷程序为例)。
                         设:地雷区域为n行(高度)m列(宽度)
                             存放格式:1行1列;1行2列;...;1行m列;
                                       2行1列;2行2列;...;2行m列;
                                       .
                                       .
                                       .
                                       n行1列;n行2列;...;n行m列;
                             产生地雷方式为:
                                       1.随机宽度值=
                                           “在雷区宽度数值范围内(0-m)产生一随机数”+1
                                       2.随机高度值=
                                           “在雷区高度数值范围内(0-n)产生一随机数”+1
                                       3.由基址+32*随机高度值+随机高度值确定此地雷位置,并存
                                         8F数值表示为地雷。
                   3.加载扫雷程序,在以其基址开始的地址中读取数据到分析程序中。
                   4.按内存存放格式将8F(雷)按图形方式标出显示。
                   5.在扫雷程序中标出地雷位置。
                   6.做个"扫雷英雄吧"!
总结:
     学习如何将其它进程当中的数据读出,并以直观的图形方式表达程序分析结果。
附:
读取过程实现程序
#include "stdafx.h"

LPCTSTR szClassName = TEXT( "WINCLASS" );

LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
        PAINTSTRUCT        ps;
        HDC                hdc = NULL;

        TCHAR        strSysPath[ MAX_PATH ]        = { '0' };
        TCHAR        buffer[ 512 ]                = { '0' };

        static PROCESS_INFORMATION ProcessInfo;
        static STARTUPINFO           StartupInfo;

        static HANDLE hMine = NULL;

        OSVERSIONINFO versionInfo;

        int nWidthAddress        = 0x0;
        int nHeightAddress        = 0x0;
        int nMinesAddress        = 0x0;
        int nCellBaseAddress        = 0x0;

        static BYTE* byPtrIsMine = NULL;
        static RECT* rectPtr = NULL;

        static BYTE byWidth  = 0;
        static BYTE byHeight = 0;
        static BYTE byMines  = 0;

        int index = 0;

        switch ( uMsg )
        {
        case WM_CREATE:
                GetVersionEx( & versionInfo );

                if ( versionInfo.dwMajorVersion >= 5 )
                {
                        // In WIN2K enviroment
                        if ( versionInfo.dwMinorVersion == 0 )
                        {
                                nWidthAddress         = 0x10056F8;
                                nHeightAddress         = 0x1005A68;
                                nMinesAddress         = 0x1005A6C;
                                nCellBaseAddress = 0x1005700;
                        }
                        else
                        {
                                // In WINXP enviroment
                                nWidthAddress         = 0x1005334;
                                nHeightAddress         = 0x1005338;
                                nMinesAddress         = 0x1005330;
                                nCellBaseAddress = 0x1005340;
                        }
                }
                else
                {
                        MessageBox( \
                                NULL, \
                                TEXT( "THIS PROGRAMME NEED YOUR OPERATION SYSTEM IS WIN2K OR WINXP!" ), \
                                TEXT( "INFORMATION" ),
                                MB_OK | MB_ICONINFORMATION );
                        return 0;
                }
                // Execute the winmine game.
                GetWindowsDirectory( strSysPath, MAX_PATH );
                lstrcat( strSysPath, TEXT( "\\System32\\WinMine.exe" ) );

                OutputDebugString( strSysPath );
                OutputDebugString( "\n" );

                ZeroMemory( & ProcessInfo, sizeof( PROCESS_INFORMATION ) );
                ZeroMemory( & StartupInfo, sizeof( STARTUPINFO ) );

                StartupInfo.cb = sizeof( StartupInfo );

                if ( CreateProcess( \
                                strSysPath,
                                NULL, NULL, NULL, FALSE, 0, NULL, NULL, \
                                & StartupInfo, \
                                & ProcessInfo ) )
                {
                        // Wait the CreateProcess function done
                        WaitForInputIdle( ProcessInfo.hProcess, INFINITE );

                        sprintf( buffer, "ThreadId: %d\n", ProcessInfo.dwThreadId );
                        OutputDebugString( buffer );

                        hMine = OpenProcess( PROCESS_VM_READ, TRUE, ProcessInfo.dwProcessId );
                        _ASSERT( hMine );

                        DWORD dwNumOfBytesRead = 0;

                        ReadProcessMemory( \
                                hMine, \
                                ( LPVOID ) nWidthAddress, \
                                & byWidth, \
                                1, \
                                & dwNumOfBytesRead );

                        ReadProcessMemory( \
                                hMine, \
                                ( LPVOID ) nHeightAddress, \
                                & byHeight, \
                                1, \
                                & dwNumOfBytesRead );

                        sprintf( buffer, "Mine Game's Width: %d\tMine Game's Height: %d\n", byWidth, byHeight );
                        OutputDebugString( buffer );

                        ReadProcessMemory( \
                                hMine, \
                                ( LPVOID ) nMinesAddress, \
                                & byMines, \
                                1, \
                                & dwNumOfBytesRead );

                        sprintf( buffer, "Mine Game's Mines: %d\n", byMines );
                        OutputDebugString( buffer );

                        byPtrIsMine = new BYTE[ byWidth * byHeight ];
                        rectPtr = new RECT[ byWidth * byHeight ];
                        _ASSERT( byPtrIsMine );
                        _ASSERT( rectPtr );
                        if ( ! byPtrIsMine || ! rectPtr )
                        {
                                MessageBox( \
                                        NULL, \
                                        TEXT( "NO MORE MEMORY ALLOCATE !" ), \
                                        TEXT( "INFORMATION" ), \
                                        MB_OK | MB_ICONINFORMATION );
                                PostQuitMessage( 0 );
                        }
                        ZeroMemory( byPtrIsMine, byWidth * byHeight );

                        for ( int y = 0; y < byHeight; y++ )
                        {
                                for ( int x = 0; x < byWidth; x++ )
                                {
                                        int nMineCellAddress = nCellBaseAddress + ( 32 * ( y + 1 ) ) + ( x + 1 );

                                        ReadProcessMemory( \
                                                hMine, \
                                                ( LPVOID ) nMineCellAddress, \
                                                & byPtrIsMine[ index ], \
                                                1, \
                                                & dwNumOfBytesRead );

                                        sprintf( buffer, "Value Is: 0x%x\n", byPtrIsMine[ index ] );
                                        OutputDebugString( buffer );

                                        rectPtr[ index ].left        = ( x * 16 );
                                        rectPtr[ index ].top        = ( y * 16 );
                                        rectPtr[ index ].right        = ( x * 16 + 16 );
                                        rectPtr[ index ].bottom        = ( y * 16 + 16 );
       
                                        index++;
                                }
                        }

                        index = 0;
                }
                else
                {
                        MessageBox(
                                NULL, \
                                TEXT( "CANN'T CREATE WINMINE PROCESS !" ), \
                                TEXT( "INFORMATION" ), \
                                MB_OK | MB_ICONINFORMATION );
                        PostQuitMessage( 0 );
                }

        {
                // Add the WS_EX_LAYERED attribute
                SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong( hwnd, GWL_EXSTYLE ) ^ 0x80000 );

                HINSTANCE hInst = LoadLibrary( "User32.dll ");
                _ASSERT( hInst );

                typedef BOOL ( WINAPI* SetWindowLayeredFunc )( HWND, COLORREF, BYTE, DWORD );
                SetWindowLayeredFunc Func = NULL;

                Func = ( SetWindowLayeredFunc ) GetProcAddress( hInst, "SetLayeredWindowAttributes" );
                _ASSERT( Func );

                Func( hwnd, 0, 128, 2 );
                FreeLibrary( hInst );

                RECT rect;
                GetWindowRect( hwnd, & rect );
                SetWindowPos( \
                        hwnd, \
                        HWND_TOPMOST, \
                        rect.left, rect.top, \
                        16 * byWidth + 9, 16 * byHeight + 28, \
                        SWP_NOMOVE );
        }
                return 0;

        case WM_PAINT:
                hdc = BeginPaint( hwnd, & ps );
                _ASSERT( hdc );

        {
                for ( int i = 0; i < ( byWidth * byHeight ); i++ )
                {
                        // This is a mine
                        if ( byPtrIsMine[ i ] == 0x8F )
                        {
                                HBRUSH hBrushRed = CreateSolidBrush( RGB( 255, 0, 0 ) );
                                _ASSERT( hBrushRed );
                                HGDIOBJ hOldBrush = SelectObject( hdc, hBrushRed );
                                _ASSERT( hOldBrush );

                                Rectangle( hdc, \
                                        rectPtr[ i ].left, rectPtr[ i ].top, \
                                        rectPtr[ i ].right, rectPtr[ i ].bottom );

                                SelectObject( hdc, hOldBrush );
                        }
                        else
                        {
                                Rectangle( hdc, \
                                        rectPtr[ i ].left, rectPtr[ i ].top, \
                                        rectPtr[ i ].right, rectPtr[ i ].bottom );
                        }
                }
        }

                EndPaint( hwnd, & ps );
                return 0;

        case WM_DESTROY:
                // Close the winmine game
                PostQuitMessage( 0 );
                if ( byPtrIsMine )
                {
                        delete byPtrIsMine;
                        byPtrIsMine = NULL;
                }
                _ASSERT( byPtrIsMine == NULL );

                if ( rectPtr )
                {
                        delete rectPtr;
                        rectPtr = NULL;
                }
                _ASSERT( rectPtr == NULL );

                CloseHandle( hMine );

                TerminateProcess( ProcessInfo.hProcess, 0 );
                CloseHandle( ProcessInfo.hThread );
                CloseHandle( ProcessInfo.hProcess );
                return 0;

        default:
                break;
        }

        return DefWindowProc( hwnd, uMsg, wParam, lParam );
}

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow )
{
        HWND        hwnd = NULL;        // Generic window handle
        MSG        msg;                // Generic message

        WNDCLASSEX winclass;

        winclass.cbSize                = sizeof( WNDCLASSEX );
        winclass.style                = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
        winclass.lpfnWndProc        = WndProc;
        winclass.cbClsExtra        = 0;
        winclass.cbWndExtra        = 0;
        winclass.hInstance        = hInstance;
        winclass.hIcon                = LoadIcon( NULL, IDI_APPLICATION );
        winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
        winclass.hbrBackground        = ( HBRUSH ) GetStockObject( BLACK_BRUSH );
        winclass.lpszMenuName        = NULL;
        winclass.lpszClassName        = szClassName;
        winclass.hIconSm        = LoadIcon( NULL, IDI_APPLICATION );

        // Register the window class
        if ( ! RegisterClassEx( & winclass ) )
                return 0;

        int cxScreen = GetSystemMetrics( SM_CXSCREEN );
        int cyScreen = GetSystemMetrics( SM_CYSCREEN );

        // Create the window
        hwnd = CreateWindowEx(
                        NULL,                                        // extended style
                        szClassName,                                // class
                        TEXT( "GAME" ),                                // title
                        WS_OVERLAPPEDWINDOW | WS_VISIBLE,        // window style
                        cxScreen / 4, cyScreen / 4,                // initial x,y
                        cxScreen / 2, cyScreen / 2,                // initial width, height
                        NULL,                                        // handle to parent
                        NULL,                                        // handle to menu
                        hInstance,                                // instance of this application
                        NULL );                                        // extra creation parms

        _ASSERT( hwnd );
        if ( ! hwnd )
                return 0;

        // enter main event loop
        while ( TRUE )
        {
                if ( PeekMessage( & msg, NULL, 0, 0, PM_REMOVE ) )
                {
                        if ( msg.message == WM_QUIT )
                                break;

                        // translate any accelerator keys
                        TranslateMessage( & msg );
                        // send the message to the window proc
                        DispatchMessage( & msg );
                }
        } // end while

        UnregisterClass( szClassName, hInstance );
        return ( msg.wParam );
}

[注意]APP应用上架合规检测服务,协助应用顺利上架!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 117
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
呵呵。。这个游戏修改器、外挂、辅助工具中用得比较多。
2006-3-31 10:18
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
还没转够啊?
2006-3-31 10:23
0
游客
登录 | 注册 方可回帖
返回
//