• Cheat Engine 修改器获取内存数据心路历程, THREADSTACK0 C# .NET VB 获取基址 CE修改器


    一、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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    添加可被调用函数:

    extern "C" FUNHEAD int  GetThreadStartAddress_SSY(int Pid, int intThreadNo);
    
    • 1

    在这里插入图片描述

    修改项目为:动态库(.dll) ,点击F5生成,得到threadstack.dll。
    在这里插入图片描述

    三、VB.NET程序示范

    1.获取线程基址
    把 threadstack.dll 放入程序运行目录下。
    dll下载地址
    我会上传到CSDN,付积分下载(有钱真的可以为所欲为哦),当然也可以按照我的方法编译。

        <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
    
    • 1
    • 2
    • 3
        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)
       
       '下面还有代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    四、总结

    第一次使用CE写项目,熬了几个大夜终于搞定了。我们遇到的问题刚好在我们的能力范围内,或许再坚持一下,我们就能把问题解决了。
    瑞思拜。

  • 相关阅读:
    Proteus中如何使用Arduino实现 ST7735显示屏十六宫格拼图游戏
    活动图高阶讲解-03
    图象的感光原件、成象原理、相机的相关坐标系
    【PLC】三菱plc控件安装 component Movedata had the following error ... Error Number:-119
    2334. 元素值大于变化阈值的子数组-单调栈法和暴力求解法
    【附源码】计算机毕业设计SSM网上求职招聘系统
    聚观早报 | 极越07正式上市;宝骏云海正式上市
    【NLP】使用 BERT 和 PyTorch Lightning 进行多标签文本分类
    电子学会2022年9月青少年软件编程(图形化)等级考试试卷(一级)答案解析
    Django学习笔记
  • 原文地址:https://blog.csdn.net/u011993802/article/details/126558852