一、CE 找到地址
根据字符串找到地址。
找到结果,双击此行,会加入下面列表
右键点击选择:对这个地址进行指针扫描。
此处选择10级别指针,其他程序 区别对待。
参考此教程:
CE学习资料
经过多次查找可以找到如下结果
平常程序的 基址 都是以.exe或者 .dll 结尾,这里是 THREADSTACK0,表示是 线程0基地址。
二、获取THREADSTACK0 基址
获取基址:
C++项目程序
threadstack.exe 软件
三、修改C++代码,生成dll,使用的是VS2019 。
增加一个方法,作用是传入一个程序的 PID,和线程序号,程序返回线程的基址(10进制)。
int GetThreadStartAddress_SSY(int Pid, int intThreadNo) {
std::string pid = std::to_string(Pid);
DWORD dwProcID;
std::stringstream stringstream(pid);
stringstream >> std::dec >> dwProcID;
if (!dwProcID) {
std::cerr << pid << " is not a valid process id (PID)" << std::endl;
return 0;
}
HANDLE hProcHandle = NULL;
hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
std::vector<DWORD> threadId = threadList(dwProcID);
int stackNum = 0;
for (auto it = threadId.begin(); it != threadId.end(); ++it) {
if (stackNum == intThreadNo)
{
HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, *it);
DWORD threadStartAddress = GetThreadStartAddress(hProcHandle, threadHandle);
printf("TID: 0x%04x = THREADSTACK%2d BASE ADDRESS: 0x%04x\n", *it, stackNum, threadStartAddress);
return threadStartAddress;
}
stackNum++;
}
return 0;
}
添加可被调用函数:
extern "C" FUNHEAD int GetThreadStartAddress_SSY(int Pid, int intThreadNo);
修改项目为:动态库(.dll) ,点击F5生成,得到threadstack.dll。
三、VB.NET程序示范
1.获取线程基址
把 threadstack.dll 放入程序运行目录下。
dll下载地址
我会上传到优快云,付积分下载(有钱真的可以为所欲为哦),当然也可以按照我的方法编译。
<DllImport("threadstack.dll", CharSet:=CharSet.Unicode, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function GetThreadStartAddress_SSY(ByVal hProcess As ULong, ByVal hThread As ULong) As Integer
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
m_csTargetProcess = Process.GetProcesses().FirstOrDefault(Function(k) k.ProcessName = txt_ExeName.Text)
If m_csTargetProcess Is Nothing Then
MsgBox("未检索到程序!")
Return
End If
Dim csBaseAddress As System.IntPtr = IntPtr.Zero '线程的基址
csBaseAddress = GetThreadStartAddress_SSY(m_csTargetProcess.Id, 0)
'下面还有代码
2.根据基址+偏移获取最终地址。
'此代码接上面的
'获取最终地址
csBaseAddress = csBaseAddress - &H384 '基址
Dim hProcess As IntPtr = OpenProcess(&H1F0FFF, False, m_csTargetProcess.Id) '主窗体句柄
csBaseAddress = hProcess.FindDMAAddy(csBaseAddress, New Integer() {&H28, &H4, &H8, &H120, &H10, &H14, &HC4, &H10, &H8, &H10})
Dim Size As Integer = 20 '请求多少数据
Dim array As Byte() = New Byte(Size - 1) {}
Dim num As Integer '响应多少个数据
ReadProcessMemory(hProcess, csBaseAddress, array, Size, num)
Dim strTarge As String = System.Text.UnicodeEncoding.Unicode.GetString(array)
MsgBox(strTarge)
CloseHandle(hProcess)
End Sub
<DllImportAttribute("kernel32.dll", EntryPoint:="ReadProcessMemory")>
Public Function ReadProcessMemory(hProcess As IntPtr,
lpBaseAddress As IntPtr,
<Out()> lpBuffer As Byte(),
dwSize As Integer,
<System.Runtime.InteropServices.OutAttribute()>
ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<System.Runtime.CompilerServices.Extension>
Public Function FindDMAAddy(ByVal hProc As IntPtr, ByVal ptr As IntPtr, ByVal offsets() As Integer) As IntPtr
Dim buffer = New Byte(IntPtr.Size - 1) {}
For Each i As Integer In offsets
ReadProcessMemory(hProc, ptr, buffer, buffer.Length, 0)
If IntPtr.Size = 4 Then
ptr = IntPtr.Add(New IntPtr(BitConverter.ToInt32(buffer, 0)), i)
Else
ptr = IntPtr.Add(New IntPtr(BitConverter.ToInt64(buffer, 0)), i)
End If
Next i
Return ptr
End Function
四、总结
第一次使用CE写项目,熬了几个大夜终于搞定了。我们遇到的问题刚好在我们的能力范围内,或许再坚持一下,我们就能把问题解决了。
瑞思拜。