从我在C++中没有的应用程序中读取内存(vb.net中的示例)
Reading memory from an application I do not own in C++ (example in vb.net)
几个月前,在我开始学习C++之前,我在VB.net中制作了一个从外部程序读取内存的应用程序。这可以是任何东西,从记事本到windows媒体播放器等。
我一直在试图找到一种在C++中做同样事情的方法,但令我惊讶的是,我在这个主题上找不到任何直截了当的东西。谷歌只会在几个论坛上发布帖子,人们的普遍反应是"Windows不允许你从你不拥有的内存中读取"。但如果它在VB.net中工作,它也可以在C++中工作。
不要被代码的数量所欺骗,它非常简单。
声明
Imports System.Math
Imports System.Threading
Imports System.Runtime.InteropServices
//Guess what this does ;D
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer
//Allows us to read a float from the memory.
Private Declare Function ReadProcessMemory Lib "kernel32" _
Alias "ReadProcessMemory" (ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByRef lpBuffer As Single, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Integer
//Allows us to read an integer or string from the memory. String will require a loop.
Private Declare Function ReadProcessMemoryInt Lib "kernel32" _
Alias "ReadProcessMemory" (ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByRef lpBuffer As Integer, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Integer
//Allows us to find a memory address when provided with a pointer and offsets
Private Declare Function ReadProcessMemoryPointer Lib "kernel32" Alias "ReadProcessMemory" ( _
ByVal hProcess As IntPtr, _
ByVal lpBaseAddress As IntPtr, _
<Out()> ByVal lpBuffer() As Byte, _
ByVal dwSize As Integer, _
ByRef lpNumberOfBytesRead As Integer) As Boolean
//Close a handle
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
//Shortcut to get read & write access to an application
Const PROCESS_ALL_ACCESS = &H1F0FFF
使用这些声明的函数
//Function to get string from memory
Public Function memstring(ByVal address As Long, ByVal length As Int32, ByVal processHandle As IntPtr)
Dim stringinmemory As Long
Dim ret1 As Byte() = Nothing
Dim tStr(length) As Char
Dim retStr As String = ""
For i As Int32 = 0 To length - 1
ReadProcessMemoryInt(processHandle, address + i, stringinmemory, 1, 0)
ret1 = BitConverter.GetBytes(stringinmemory)
tStr(i) = System.Text.Encoding.ASCII.GetString(ret1) : retStr += tStr(i)
Next
Return retStr
End Function
//Function to get float from memory. I don't know what those comments are all about, it's been a long time since I used this code.
Public Function memfloat(ByVal address As Long, ByVal processHandle As IntPtr)
Dim floatvalueinmemory As Single
ReadProcessMemory(processHandle, address, floatvalueinmemory, 4, 0)
//Floatvalueinmemory didn't give the desired result, so going to try to TryParse
Dim letstryagain As Single
Single.TryParse(floatvalueinmemory, letstryagain)
//Unfortunately returns the same result as floatvalueinmemory did
Return CStr(letstryagain)
End Function
//Function to get int from memory
Public Function memInt(ByVal address As Long, ByVal processHandle As IntPtr)
Dim intvalueinmemory As Integer
ReadProcessMemoryInt(processHandle, address, intvalueinmemory, 4, 0)
Return CStr(intvalueinmemory)
End Function
//Function to find a memory address when provided with a pointer and offsets
Private Function FindAddress(ByVal pHandle As IntPtr, ByVal BaseAddress As IntPtr, ByVal StaticPointer As IntPtr, ByVal Offsets() As IntPtr) As IntPtr
// Create a buffer that is 4 bytes on a 32-bit system or 8 bytes on a 64-bit system.
Dim tmp(IntPtr.Size - 1) As Byte
Dim Address As IntPtr = BaseAddress
// We must check for 32-bit vs 64-bit.
If IntPtr.Size = 4 Then
Address = New IntPtr(Address.ToInt32 + StaticPointer.ToInt32)
Else
Address = New IntPtr(Address.ToInt64 + StaticPointer.ToInt64)
End If
// Loop through each offset to find the address
For i As Integer = 0 To Offsets.Length - 1
ReadProcessMemoryPointer(pHandle, Address, tmp, IntPtr.Size, 0)
If IntPtr.Size = 4 Then
Address = BitConverter.ToInt32(tmp, 0) + Offsets(i).ToInt32()
Else
Address = BitConverter.ToInt64(tmp, 0) + Offsets(i).ToInt64()
End If
Next
Return Address
End Function
示例用法
Sub somesub()
//Get process handle.
Dim myProcesses As Process() = Process.GetProcessesByName("SomeProgram")
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
//We'll need the base address when we need to find an address through pointers.
BaseAddressSet = myProcesses(0).MainModule.BaseAddress
//Get float from memory.
somefloat = memfloat(&H12980D8, processHandle)
//Get string from memory.
somestring = memstring(&H12955E0, 15, processHandle)
//Get float from memory through a pointer.
Dim sptr As IntPtr = &HF28EE4 //Static pointer for float address we want to get
Dim Offsets As IntPtr() = {&H61C, &H19C, &H2AC, &HDC, &H198} //Offsets for float address we want to get
Dim addr As IntPtr = FindAddress(processHandle, BaseAddressSet, sptr, Offsets)
somefloat = memfloat(addr, processHandle)
//All done.
CloseHandle(processHandle)
End Sub
页脚
Partial Public Class NativeMethods
<DllImport("user32.dll")> _
Public Shared Function ReadProcessMemory(ByVal hProcess As System.IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As System.IntPtr, ByVal nSize As UInteger, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
End Class
请建议如何在C++中做到这一点,或者在哪里我可以学习如何做到这一步。
下面是一个小程序,用于在指定目标进程的内存块中搜索指定字符串。
#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>
template <class outIter>
void find_locs(HANDLE process, std::string const &pattern, outIter output) {
unsigned char *p = NULL;
MEMORY_BASIC_INFORMATION info;
for ( p = NULL;
VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
std::vector<char> buffer;
std::vector<char>::iterator pos;
if (info.State == MEM_COMMIT &&
(info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
DWORD bytes_read;
buffer.resize(info.RegionSize);
ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read);
buffer.resize(bytes_read);
for ( pos = buffer.begin();
buffer.end()!=(pos=std::search(pos, buffer.end(), pattern.begin(), pattern.end()));
++pos)
{
*output++ = p+(pos-buffer.begin());
}
}
}
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <process ID> <pattern>", argv[0]);
return 1;
}
int pid;
sscanf(argv[1], "%i", &pid);
std::string pattern(argv[2]);
HANDLE process = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
false,
pid);
find_locs(process, pattern,
std::ostream_iterator<void *>(std::cout, "n"));
return 0;
}
要构建它,您需要为链接器指定正确的库:
cl search_proc.cpp kernel32.lib
相关文章:
- 如何在 64 位 vb.net Windows 应用程序中引用 32 位 dll
- 如何将 VB.Net 字符串作为字符*传递给C++dll?
- VB.NET DLL中的C++DLL函数复制
- TEA在VB.NET中的实现
- 如何使函数返回数组?用于制作在VB.NET中使用的DLL
- 反调试器技术:如何使用 VB.NET 对调试器隐藏线程?
- 如何在C 调用的VB.NET中编写回调函数
- 我可以在 vb.net Windows 窗体应用程序中使用 COLECONTROLModule 吗?
- C++ DLL 包装器 vb.net 传递字节数组的字节数组?
- 将简单的程序从C++移植到 vb.net
- 内存损坏从vb.net调用c dll
- vb.net单不等于c float
- 导入C 功能将结构的指针返回到VB.NET中
- REGDB_E_CLASSNOTREG from VB.NET to C++
- 使用来自VB.NET的参数调用C 函数
- 使用P/Invoke从MFC DLL函数中读取VB.NET中的结构化数据
- 将 C 按位语句转换为 vb.net
- C++ dll variable to vb.net exe
- 我无法读取 mft 并将 VB.net 转换为 C
- 在vb.net中调用C DLL文件