c++读取指定位置硬编码数据


如果硬编码指令 48:8B05 01FB0C00 是固定的,可以通过解析该指令中的操作数来动态获取内存地址。48:8B05 01FB0C00 这条指令的含义是 mov rax, [rip + 0xC0FB01],其中 0xC0FB01 是相对地址偏移量。

你可以解析可执行文件中的指令,计算出 rip 相对于该指令的偏移量,然后读取这个内存地址的值。下面是如何在 C++ 中实现这个过程的一个示例:

  1. 查找目标进程的模块基址。
  2. 解析指令,计算目标地址。
  3. 使用 ReadProcessMemory 读取目标地址的值。
#include <windows.h>
#include <iostream>
#include <TlHelp32.h>

DWORD GetProcessIdByName(const std::wstring& processName) {
    DWORD processId = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 pe;
        pe.dwSize = sizeof(pe);
        if (Process32First(hSnapshot, &pe)) {
            do {
                if (processName == pe.szExeFile) {
                    processId = pe.th32ProcessID;
                    break;
                }
            } while (Process32Next(hSnapshot, &pe));
        }
        CloseHandle(hSnapshot);
    }
    return processId;
}

uintptr_t GetModuleBaseAddress(DWORD processId, const std::wstring& moduleName) {
    uintptr_t baseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        MODULEENTRY32 me;
        me.dwSize = sizeof(me);
        if (Module32First(hSnapshot, &me)) {
            do {
                if (moduleName == me.szModule) {
                    baseAddress = reinterpret_cast<uintptr_t>(me.modBaseAddr);
                    break;
                }
            } while (Module32Next(hSnapshot, &me));
        }
        CloseHandle(hSnapshot);
    }
    return baseAddress;
}

int main() {
    // 目标进程的名称和模块名称
    std::wstring targetProcessName = L"v.exe";
    std::wstring moduleName = L"v.exe";

    // 获取目标进程的PID
    DWORD processId = GetProcessIdByName(targetProcessName);
    if (processId == 0) {
        std::wcerr << L"Failed to find process: " << targetProcessName << std::endl;
        return 1;
    }

    // 获取模块基址
    uintptr_t moduleBase = GetModuleBaseAddress(processId, moduleName);
    if (moduleBase == 0) {
        std::cerr << "Failed to get module base address" << std::endl;
        return 1;
    }

    // 硬编码指令的偏移量(例如假设它在模块基址的某个偏移处)
    uintptr_t instructionOffset = 0x1000; // 需要根据实际情况调整
    uintptr_t instructionAddress = moduleBase + instructionOffset;

    // 读取内存中的指令
    BYTE instruction[7];
    SIZE_T bytesRead;
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
    if (!hProcess) {
        std::cerr << "Failed to open process" << std::endl;
        return 1;
    }

    if (!ReadProcessMemory(hProcess, (LPCVOID)instructionAddress, instruction, sizeof(instruction), &bytesRead)) {
        std::cerr << "Failed to read memory at instruction address" << std::endl;
        CloseHandle(hProcess);
        return 1;
    }

    // 解析指令以获取相对偏移量
    uintptr_t relativeOffset = *reinterpret_cast<uint32_t*>(instruction + 3);
    uintptr_t targetAddress = instructionAddress + 7 + relativeOffset;

    // 读取目标地址的值
    uint64_t value = 0;
    if (ReadProcessMemory(hProcess, (LPCVOID)targetAddress, &value, sizeof(value), &bytesRead)) {
        std::cout << "Value at address " << std::hex << targetAddress << ": " << std::hex << value << std::endl;
    } else {
        std::cerr << "Failed to read memory at target address" << std::endl;
    }

    // 关闭句柄
    CloseHandle(hProcess);

    return 0;
}

这个示例代码做了以下几件事:

  1. 使用 CreateToolhelp32SnapshotProcess32First/Process32Next 获取目标进程的 PID。
  2. 使用 CreateToolhelp32SnapshotModule32First/Module32Next 获取目标模块的基址。
  3. 计算硬编码指令的实际地址。
  4. 读取指令并解析相对偏移量。
  5. 计算目标地址并读取其内存值。

请注意,instructionOffset 需要根据实际情况调整,这取决于硬编码指令在目标模块中的偏移位置。你需要确保这个偏移是正确的,以便正确解析指令和读取内存。

详细解释一下这两句代码的含义:

解析指令以获取相对偏移量

uintptr_t relativeOffset = *reinterpret_cast<uint32_t*>(instruction + 3);

这行代码从读取的指令字节中提取相对偏移量。具体步骤如下:

  1. 读取的指令: 我们读取了硬编码指令 48 8B 05 01 FB 0C 00,这是7字节的指令。

  2. 指令结构:

    • 48 8B 05 是指令的操作码部分(opcode),表示 mov rax, [rip + offset]
    • 01 FB 0C 00 是32位(4字节)的相对偏移量部分(offset)。
  3. 指令偏移量: 我们需要从指令字节数组中提取偏移量部分。偏移量从第4个字节(instruction[3])开始,占用4个字节。

  4. 解释代码:

    • instruction + 3 指向指令字节数组的第4个字节,即偏移量部分的起始位置。
    • *reinterpret_cast<uint32_t*>(instruction + 3) 将这4个字节解释为一个32位无符号整数(uint32_t),并将其值存储在 relativeOffset 中。

计算目标地址

uintptr_t targetAddress = instructionAddress + 7 + relativeOffset;

这行代码计算目标地址。具体步骤如下:

  1. 指令地址: instructionAddress 是硬编码指令在目标进程中的地址。

  2. 指令长度: 这条指令的总长度是7字节(48 8B 05 01 FB 0C 00),所以我们需要加上7。

  3. 相对偏移量: relativeOffset 是我们从指令中提取出来的偏移量。这个偏移量是相对于下一条指令的地址的。

  4. 解释代码:

    • instructionAddress + 7 计算下一条指令的地址(即当前指令结束的位置)。
    • instructionAddress + 7 + relativeOffset 将相对偏移量添加到下一条指令的地址上,得到最终的目标地址(targetAddress)。

总结一下,这两句代码的作用是从硬编码指令中提取相对偏移量,并将其添加到指令结束位置,以计算目标地址。在计算目标地址后,可以使用 ReadProcessMemory 函数读取该地址的值。

以下是详细示例:

假设我们读取到的指令是 48 8B 05 01 FB 0C 00,其含义为 mov rax, [rip + 0xC0FB01]。这条指令表示从当前指令位置(rip)加上 0xC0FB01 处读取数据并存储到 rax 寄存器。

假设指令的起始地址是 0x1000,则计算过程如下:

  1. 指令长度:7字节
  2. 下一条指令地址0x1000 + 7 = 0x1007
  3. 相对偏移量0xC0FB01
  4. 目标地址0x1007 + 0xC0FB01 = 0xC0FB08

因此,目标地址是 0xC0FB08

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,介绍一下C++中使用FFmpeg进行H.265编码的方法。 在C++中使用FFmpeg进行H.265编码,可以通过以下步骤实现[^1]: 1. 初始化FFmpeg库和相关的编码器。 2. 创建输入和输出的AVFormatContext。 3. 打开输入文件并读取视频流的信息。 4. 创建输出文件并设置编码器的参数。 5. 打开输出文件并写入文件头。 6. 循环读取输入文件中的视频帧。 7. 将视频帧送入编码器进行编码。 8. 将编码后的数据写入输出文件。 9. 释放资源并关闭文件。 下面是一个示例代码,演示了如何使用FFmpeg进行H.265编码: ```cpp extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/opt.h> } int main() { // 初始化FFmpeg库 av_register_all(); avcodec_register_all(); // 创建输入和输出的AVFormatContext AVFormatContext* inputFormatContext = avformat_alloc_context(); AVFormatContext* outputFormatContext = avformat_alloc_context(); // 打开输入文件并读取视频流的信息 avformat_open_input(&inputFormatContext, "input.mp4", nullptr, nullptr); avformat_find_stream_info(inputFormatContext, nullptr); // 创建输出文件并设置编码器的参数 avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, "output.mp4"); AVStream* outputStream = avformat_new_stream(outputFormatContext, nullptr); AVCodec* codec = avcodec_find_encoder_by_name("libx265"); AVCodecContext* codecContext = avcodec_alloc_context3(codec); codecContext->width = inputFormatContext->streams->codecpar->width; codecContext->height = inputFormatContext->streams->codecpar->height; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; avcodec_open2(codecContext, codec, nullptr); // 打开输出文件并写入文件头 avio_open(&outputFormatContext->pb, "output.mp4", AVIO_FLAG_WRITE); avformat_write_header(outputFormatContext, nullptr); // 循环读取输入文件中的视频帧 AVPacket packet; while (av_read_frame(inputFormatContext, &packet) >= 0) { if (packet.stream_index == 0) { // 将视频帧送入编码器进行编码 avcodec_send_packet(codecContext, &packet); while (avcodec_receive_packet(codecContext, &packet) == 0) { // 将编码后的数据写入输出文件 av_interleaved_write_frame(outputFormatContext, &packet); av_packet_unref(&packet); } } av_packet_unref(&packet); } // 释放资源并关闭文件 av_write_trailer(outputFormatContext); avcodec_free_context(&codecContext); avformat_close_input(&inputFormatContext); avformat_free_context(inputFormatContext); avio_close(outputFormatContext->pb); avformat_free_context(outputFormatContext); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值