如何读取其它进程地址空间的数据
问题的提出:
当发现某一程序执行时,在内存中存在有用的信息后,需要把这些数据从内存中读出并将其翻
译成直观的图表形式表达。跟着,需要设计哪部分呢?需要将一个地址放入一个指针中,之后读取指针值
。
可是这些读取的内存数据是不存在于我的程序中,众所周知,每一个进程有它的独立的地址空
间以致它不能“意外”访问属于其它程序的内存区域,所以为了读取这些数据需要找一种读取其它进程内
存空间的方法。
问题的解决思路:
写一个可以接收一个进程并且提供读取这个进程内存地址的功能的程序。可以将其封装在一个
简单的小类库中使用它们。设计成类库主要是因为有时由于很多的情况下你也会用到它,如:你可以利用
这个类写一个调试工具。据我所知,所有调试工具都有读取调试程序的内存的功能。
问题解决的实现过程:
该怎么读取其它进程的地址空间?答案在一个名叫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应用上架合规检测服务,协助应用顺利上架!