jjzjj

c++ - 从 32 位进程获取 64 位进程内存的入口点

coder 2024-06-12 原文

我想获取我从 32 位进程编写的 64 位进程的入口点,就像您使用 EnumProcessModule 并获取主模块的内存地址一样。 我的最终目标是从我的 64 位进程中的内存中读取一个字节,从它的偏移量 (entry+Offset)。

但是我的 NtWow64ReadVirtualMemory64 函数一直失败。 我认为这与我的入口内存地址有关。

    #define PROC_BASIC_INFO 0
    #define NT_WOW64_QUERY_INFORMATION_PROCESS_64_NAME  "NtWow64QueryInformationProcess64"
    #define NT_WOW64_READ_VIRTUAL_MEMORY_64_NAME  "NtWow64ReadVirtualMemory64"

    typedef UINT64 SYM;
    typedef SIZE_T SIZE_T64;

    HWND   WINDOW_HANDLE;
    HANDLE PROC_HANDLE;
    DWORD PROC_ID;
    UINT address;
    UINT64 address64;
    SIZE_T bytesRead;
    SIZE_T64 bytesRead64;

    using namespace std;


    //initialize variables for importing of essential 64 bit reading functions
    //from ntdll
    typedef NTSTATUS(NTAPI *FUNC_NtReadVirtualMemory64)
    ( 
        IN  HANDLE  ProcessHandle,
        IN  PVOID64 BaseAddress,
        OUT PVOID   Buffer,
        IN  ULONGLONG BufferLength,
        OUT PULONGLONG ReturnLength OPTIONAL
    );
    typedef NTSTATUS (NTAPI *FUNC_NtWow64QueryInformationProcess64) 
    (
        IN  HANDLE ProcessHandle,
        IN  ULONG  ProcessInformationClass,
        OUT PVOID  ProcessInformation64,
        IN  ULONG  Length,
        OUT PULONG ReturnLength OPTIONAL
    );

    struct PROCESS_BASIC_INFORMATION64 {

        SYM Reserved1;
        SYM PebBaseAddress;
        SYM Reserved2[2];
        SYM UniqueProcessId;
        SYM Reserved3;
        /*
        NTSTATUS ExitStatus;
        ULONG64 PebBaseAddress;
        ULONG64 AffinityMask;
        LONG    BasePriority;
        UINT64  Reserved1;
        ULONG64 UniqueProcessId;
        ULONG64 InheritedFromUniqueProcessId;
        */
    };



    HINSTANCE ntdll = LoadLibrary("ntdll.dll");
    FUNC_NtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (FUNC_NtWow64QueryInformationProcess64)GetProcAddress(ntdll, NT_WOW64_QUERY_INFORMATION_PROCESS_64_NAME);
    FUNC_NtReadVirtualMemory64 NtReadVirtualMemory64 = (FUNC_NtReadVirtualMemory64)GetProcAddress(ntdll, NT_WOW64_READ_VIRTUAL_MEMORY_64_NAME);

    int Init32To64MemoryRead(const char* windowClass, const char* caption, SYM addressOffset)
    {

        DWORD cbNeeded;
        DWORD dwdResult;
        HMODULE mainModule;
        BOOL enumResult;
        ULONG read_length=0;
        HINSTANCE ntdll; 
        PROCESS_BASIC_INFORMATION64 procInfo;
        ZeroMemory(&procInfo, sizeof(procInfo));



        //Get the window handle
        WINDOW_HANDLE = FindWindow(windowClass, NULL);
        if (WINDOW_HANDLE == NULL)
        {
            //Window was not foud
            return 10;
        }

        //Get the process ID
        dwdResult = GetWindowThreadProcessId(WINDOW_HANDLE, &PROC_ID);

        if (dwdResult == 0)
        {
            //Getting Process ID failed
            return 20;
        }

        //Open the process
        PROC_HANDLE = OpenProcess(PROCESS_ALL_ACCESS, false, PROC_ID);

        if (PROC_HANDLE == NULL)
        {
            //Process failed to open
            return 30;
        }
        DWORD result;

        //Query Proc Information to get .exe entry point
        result = NtWow64QueryInformationProcess64( PROC_HANDLE, 0, &procInfo, sizeof(procInfo), &read_length);
        if (result != 0)
        {
            cerr << "Query Information Process has failed" << endl;

            return 40;
        }

        address64 =  (procInfo.PebBaseAddress + addressOffset);
        cerr << address64 << endl;

        string number;
        stringstream stristream;

        stristream << address64;
        stristream >> number;

        byte testByte = 0;
        (byte)ReadMemory64<byte>(testByte);

        system("PAUSE");
        return 1;
    }


template <typename _ret_t> _ret_t ReadMemory64(_ret_t& ret)
{

    NTSTATUS result = NtReadVirtualMemory64(PROC_HANDLE, (void*)address64, &ret, 8, NULL);
    ///* Debug # when too lazy for breakpoints
    cerr <<"value: " << ret << endl;
    cerr << "Error Code: " << GetLastError() << endl;
    if (result != 0)
    {
        cerr << "ReadMemory Failed.\r\nAddress: " << address64 << "\r\nSize: " << sizeof(_ret_t) << "\r\nResult: " << result << endl;
        cerr << "NtReadVirtualMemory64 has failed" << endl;
        system("PAUSE");

    } //*/
    return ret;
 };

我想知道我做错了什么。

编辑: 经过进一步检查,我注意到 NtWow64ReadVirtualMemory 没有将值存储在用作缓冲区的变量“ret”中。

最佳答案

我运行了一个简单的测试,发现我的 buffer-"ret"的值在插入函数 "NtWow64ReadVirtualMemory64" 时没有改变。
代码编译和运行没有错误(编译和运行时),除了 NtReadMemory64 返回一个奇怪的数字(没有可用于 ntdll NtWow64 函数的文档,所以 goolgling 它没有产生任何有用的东西)。
所以我想我要么提供了错误的缓冲区,要么没有从有效的内存地址读取数据。

因为我确实在函数之外显式地初始化了缓冲区,所以我想 我的问题是后者(没有提供有效的内存地址)。

我在调用 NtReadVirtualMemory 时使用了以下内容

NTSTATUS result = NtReadVirtualMemory64(PROC_HANDLE, (void*)address64, &ret, 8, NULL);

显然,当调用 NtWow64ReadVirtualMemory64 时,我将 addr 转换为 32 位空指针 (void*)address64 ,并且由于 address64 是 UINT64 类型,转换截断了地址,我是试图读取我无法读取的内存段 我通过将类型转换更改为 (PVOID64)address64 解决了这个问题 将其转换为 native 64 位指针。

比我想象的要简单,但经过几天的谷歌搜索和审查代码后发现它简直就是 hell 。

编辑: 这并没有成功,因为我的地址是错误的。 我需要通过进程主模块在内存中的位置来获取“.exe”的入口点。
看看现在如何。
任何帮助表示赞赏!

关于c++ - 从 32 位进程获取 64 位进程内存的入口点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40209833/

有关c++ - 从 32 位进程获取 64 位进程内存的入口点的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  6. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  7. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  8. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  9. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  10. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

随机推荐