【问题标题】:Win API ReadProcessMemory at base address of DLL returning unexpected dataWin API ReadProcessMemory 在 DLL 的基地址返回意外数据
【发布时间】:2016-03-24 20:32:24
【问题描述】:

我正在尝试从内存中读取 DLL 的内容以进行一些学术研究。具体来说,NTDSA.DLL 库的目的是为了改变特定指令来模拟编程错误以迫使系统发生故障。然后将记录失败,以训练机器学习算法来预测未来的失败(这是对先前发表的研究seen here 的推广的尝试)。

我通过here 概述的进程获得了我认为是 lsass.exe 进程(加载目标 DLL)在虚拟内存中的基地址。然后,我使用分配的缓冲区调用 ReadProcessMemory,并通过设置“PROCESS_ALL_ACCESS”调用 OpenProcess 获得 lsass 的句柄。 ReadProcessMemory 在 80% 的时间(部分读取)中返回错误代码 299,读取的字节数为零。我的假设是,当拨打电话时,我试图访问的区域正在使用中。幸运的是,它偶尔会返回我请求的字节数。不幸的是,与 System32 目录中的静态 DLL 相比,返回的数据与磁盘上的数据不匹配。

所以问题是,ReadProcessMemory 是否对我提供的地址做了一些有趣的事情,还是我的虚拟地址有误?是否有另一种方法来确定该 DLL 加载到内存中的位置?有什么想法吗?任何帮助或建议将不胜感激。

添加代码:

// FaultInjection.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <windows.h>
#include <psapi.h>

#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <io.h>
#include <tchar.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[]) {

    // Declarations
    int pid = 0;
    __int64* start_addr;
    DWORD size_of_ntdsa;
    DWORD aProcesses[1024], cbNeeded, cProcesses;
    TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
    HMODULE hmods[1024];
    unsigned int i;

    // Get All pids
    if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)){
        cout << "Failed to get all PIDs: " << GetLastError() << endl;
        return -1;
    }

    // Find pid for lsass.exe
    cProcesses = cbNeeded / sizeof(DWORD);
    for (i = 0; i < cProcesses; i++) {
        if (aProcesses[i] != 0) {
            HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
            if (hProc != NULL) {
                HMODULE hMod;
                DWORD cbNeededMod;
                if (EnumProcessModules(hProc, &hMod, sizeof(hMod), &cbNeededMod)) {
                    GetModuleBaseName(hProc, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
                }

                if (wstring(szProcessName).find(L"lsass.exe") != string::npos) {
                    pid = aProcesses[i];
                }
                CloseHandle(hProc);
            }
        }
    }

    cout << "lsass pid: " << pid << endl;

    HANDLE h_lsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!h_lsass) {
        cout << "Failed to open process (are you root?): " << GetLastError() << endl;
        return -1;
    }

    // Get Process Image File Name
    char filename[MAX_PATH];
    if (GetProcessImageFileName(h_lsass, (LPTSTR)&filename, MAX_PATH) == 0) {
        cout << "Failed to get image file name: " << GetLastError() << endl;
        CloseHandle(h_lsass);
        return -1;
    }

    // Enumerate modules within process
    if (EnumProcessModules(h_lsass, hmods, sizeof(hmods), &cbNeeded)) {
        for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            TCHAR szModName[MAX_PATH];
            if (GetModuleFileNameEx(h_lsass, hmods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
                if (wstring(szModName).find(L"NTDSA.dll") != string::npos) {
                    _tprintf(TEXT("%s\n"), szModName);
                    MODULEINFO lModInfo = { 0 };
                    if (GetModuleInformation(h_lsass, hmods[i], &lModInfo, sizeof(lModInfo))){
                        cout << "\t Base Addr: " << lModInfo.lpBaseOfDll << endl;
                        cout << "\t Entry Point: " << lModInfo.EntryPoint << endl;
                        cout << "\t Size of image: " << lModInfo.SizeOfImage << endl;

                        start_addr = (__int64*)lModInfo.lpBaseOfDll;
                        size_of_ntdsa = lModInfo.SizeOfImage;
                    }
                    else {
                        cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
                    }
                }
            } else {
                cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
            }
        }
    }
    else {
        cout << "Failed to enum the modules: " << GetLastError() << endl;
    }

    // Ready to continue?
    string cont = "";
    cout << "Continue? [Y|n]: ";
    getline(cin, cont);
    if (cont.find("n") != string::npos || cont.find("N") != string::npos) {
        CloseHandle(h_lsass);
        return 0;
    }

    void* buf = malloc(size_of_ntdsa);
    if (!buf) {
        cout << "Failed to allocate space for memory contents: " << GetLastError() << endl;
        CloseHandle(h_lsass);
        return -1;
    }

    SIZE_T num_bytes_read = 0;
    int count = 0;

    if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
        cout << "Read success. Got " << num_bytes_read << " bytes: " << endl;
    } else {
        int error_code = GetLastError();
        if (error_code == 299) {
            cout << "Partial read. Got " << num_bytes_read << " bytes: " << endl;
        } else  {
            cout << "Failed to read memory: " << GetLastError() << endl;
            CloseHandle(h_lsass);
            free(buf);
            return -1;
        }
    }

    if (num_bytes_read > 0) {
        FILE *fp;
        fopen_s(&fp, "C:\\ntdsa_new.dll", "w");
        SIZE_T bytes_written = 0;
        while (bytes_written < num_bytes_read) {
            bytes_written += fwrite(buf, 1, num_bytes_read, fp);
        }
        fclose(fp);
        cout << "Wrote " << bytes_written << " bytes." << endl;
    }

    CloseHandle(h_lsass);
    free(buf);

    return 0;
}

【问题讨论】:

  • 不知道为什么投反对票。
  • 为什么在ReadProcessMemory()中使用(&)变量start_addr的地址?
  • 呃...因为距离我编写 C/C++ 已经太久了...这就是问题所在。无法告诉你我有多欣赏第二双眼睛。

标签: c++ winapi dll readprocessmemory


【解决方案1】:

代码的工作原理与描述的一样,减去了发送变量地址的业余错误,我使用该变量的地址来存储目标应用程序的虚拟内存中的位置地址。在上面的代码中,改变了:

if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {

if (ReadProcessMemory(h_lsass, start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {

像魅力一样工作。谢谢ssbssa指出错误,抱歉浪费大家时间。

【讨论】:

    猜你喜欢
    • 2014-03-06
    • 2012-09-08
    • 2011-11-04
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多