如何修改下面的驱动读整数的代码,读取这种字符串并用printf打印

我会用这些代码读整数 单双浮点,这种字符串就把我整不明白了

img


NTSTATUS KReadProcessMemory(IN PEPROCESS Process, IN PVOID Address, IN UINT32 Length, IN OUT PVOID Buffer)
{
    NTSTATUS ret_status = 0;
    KAPC_STATE apc_state;
    RtlZeroMemory(&apc_state, sizeof(KAPC_STATE));
    
    PVOID tmpBuf_Kernel = ExAllocatePool(NonPagedPool, Length);


    KeStackAttachProcess((PVOID)Process, &apc_state);

    
    BOOLEAN dwRet = MmIsAddressValid(Address);

    if (dwRet)
    {
        
        KdPrint(("yjx[sys64] RtlCopyMemory(Address=%p, Buffer=%p, Length=%d);\r\n", Address, Buffer, Length));
        BOOLEAN isOk = IsOkWritePtr(Address);
        
        if (isOk)
        {
            __try
            {
                //可以访问
                RtlCopyMemory(tmpBuf_Kernel, Address, Length); // c/c++ memcpy 
                ret_status = STATUS_SUCCESS;//表示复制成功
            }
            __except (1)
            {
                ret_status = STATUS_UNSUCCESSFUL; //不可访问
                __debugbreak();
                KdPrint(("yjx:sys64:Error line=%d\n", __LINE__));
            }
        }
        else
        {
            ret_status = STATUS_UNSUCCESSFUL; //不可访问
        }

    }
    else
    {
        KdPrint(("yjx:sys64:Error line=%d\n", __LINE__));
        ret_status = STATUS_UNSUCCESSFUL;
    }
    
    KeUnstackDetachProcess(&apc_state);
    
    RtlCopyMemory(Buffer, tmpBuf_Kernel, Length);
    
    ExFreePool(tmpBuf_Kernel);
    return ret_status;
}
//dwPid为目标进程id
//lpBaseAddress 目标进程地址

//lpBuffer 当前进程地址 1
//内核内存地址 当前进程地址 2
NTSTATUS ReadProcessMemoryForPid(UINT32 dwPid, PVOID pBase, PVOID lpBuffer, UINT32 nSize)
{
    NTSTATUS retstatus = STATUS_SUCCESS;
    //根据pid获取PEPROCESS OpenProcess
    PEPROCESS Seleted_pEPROCESS = NULL;
    KdPrint(("yjx:sys64  pid=%d pBase=%p  %s 行号=%d\n", dwPid, pBase, __FUNCDNAME__, __LINE__));

    retstatus = PsLookupProcessByProcessId((PVOID)(UINT_PTR)(dwPid), &Seleted_pEPROCESS);
    if (retstatus == STATUS_SUCCESS)
    {

        retstatus = KReadProcessMemory(Seleted_pEPROCESS, (PVOID)pBase, nSize, lpBuffer);
        ObDereferenceObject(Seleted_pEPROCESS);
        //return retstatus;
    }
    else
    {
        KdPrint(("yjx sys64 PsLookupProcessByProcessId Fail...%s line=%d\n", __FUNCDNAME__, __LINE__));
        //return STATUS_UNSUCCESSFUL;
    }

    return retstatus;// STATUS_UNSUCCESSFUL;

}
void IRP_IO_通过PID读内存1(PIRP pirp)
{
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pirp); //获取应用层传来的参数
    UINT64* 缓冲区 = (UINT64*)(pirp->AssociatedIrp.SystemBuffer);
    KdPrint(("yjx:%s 行号%d\n", __FUNCDNAME__, __LINE__));
    if (缓冲区)
    {
        //
        //int*p = (int*)缓冲区;
        UINT32 PID = (UINT32)(UINT64)缓冲区[0]; //传入数据
        
        PVOID pBase = (PVOID)((UINT64)缓冲区[1] ); //传入数据
        //PVOID lpBuffer = (PVOID)(UINT64)缓冲区[2]; //传入数据
        UINT64 nSize = (UINT64)缓冲区[3]; //传入数据


        UINT32 ReadSize = ReadProcessMemoryForPid(PID, pBase, 缓冲区, nSize);

        ReadSize;
        pirp->IoStatus.Status = STATUS_SUCCESS;
        pirp->IoStatus.Information = nSize;//返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
        IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级 
    }
    irpStack;
}

这是读64位整数的代码 怎么改成读unicode字符串
UINT64 PID读内存地址x64(INT pid, UINT_PTR 地址)
{


    DWORD dwRetSize = 0;//返回字节数


    ULONG64 tmp = 0;//存放读取的数据

    UINT64 输入缓冲区[4] = { pid,地址,0,8 };


    DeviceIoControl(
        DeviceHandle,//CreateFile打开驱动设备 返回的句柄
        通过PID读整数1,//控制码 CTL_CODE

        &输入缓冲区,//输入缓冲区指针
        8 * 4,//输入缓冲区大小

        &tmp,//返回缓冲区
        sizeof(tmp),//返回缓冲区大小

        &dwRetSize, //返回字节数
        NULL);

    return tmp;

}

#include <string>
#include <vector>

UINT64 读取Unicode字符串(INT pid, UINT_PTR 地址, std::wstring& 结果) {
    DWORD dwRetSize = 0;
    UINT64 tmp = 0;

    // 输入缓冲区的第一个元素是PID,第二个元素是要读取的地址,
    // 第三个元素是要读取的字符串的长度(以字节为单位),第四个元素是0,
    // 这样驱动程序就知道要读取的是Unicode字符串。
    std::vector<UINT64> 输入缓冲区 = { pid, 地址, 0, 0 };

    // 返回缓冲区是一个用来存放字符串的缓冲区,大小为4096个字符。
    std::vector<wchar_t> 返回缓冲区(4096);

    // 调用DeviceIoControl函数来读取Unicode字符串。
    BOOL bResult = DeviceIoControl(
        DeviceHandle,
        控制码,
        输入缓冲区.data(),
        sizeof(UINT64) * 输入缓冲区.size(),
        返回缓冲区.data(),
        sizeof(wchar_t) * 返回缓冲区.size(),
        &dwRetSize,
        NULL
    );

    if (bResult && dwRetSize > 0) {
        // 如果读取成功,将结果保存到wstring对象中,并返回字符串的长度。
        结果.assign(返回缓冲区.data(), dwRetSize / sizeof(wchar_t));
        return 结果.size();
    } else {
        // 如果读取失败,返回0。
        return 0;
    }
}

Import the driver module

import driver_module

Initialize the driver

driver = driver_module.Driver()

Call a method to retrieve the memory code string

memory_code = driver.get_memory_code()

Print the memory code string

print(memory_code)

在此示例中,driver_module是包含驱动程序代码的模块的名称。类Driver是代表驱动程序的类,get_memory_code()是类的一个方法Driver,用于检索内存代码字符串。一旦为memory_code变量分配了内存代码字符串的值,该print函数就会将其打印到控制台。

要使用此驱动程序读取内存,您需要使用ReadProcessMemoryForPid以下参数调用该函数:

dwPid:要读取其内存的目标进程的进程ID。
pBase:目标进程中要从中开始读取的内存位置的地址。
lpBuffer: 指向当前进程中要存储从目标进程内存中读取的数据的缓冲区的指针。

要读取 Unicode 字符串,可以使用 ReadProcessMemory 函数。该函数可以读取一个进程中的指定内存地址中的数据,并将其复制到指定的缓冲区中。以下是一个例子,演示如何使用 ReadProcessMemory 函数从指定的进程中读取一个 Unicode 字符串:

#include <Windows.h>

// 读取 Unicode 字符串
void ReadUnicodeString(HANDLE hProcess, LPCVOID lpBaseAddress, LPWSTR lpBuffer, SIZE_T nSize)
{
    SIZE_T nBytesRead = 0;
    BOOL bSuccess = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, &nBytesRead);
    if (!bSuccess || nBytesRead == 0)
    {
        lpBuffer[0] = L'\0';
    }
    else
    {
        // 确保字符串以 null 终止
        lpBuffer[nBytesRead / sizeof(WCHAR)] = L'\0';
    }
}

// 读取进程中的 Unicode 字符串
void ReadProcessUnicodeString(DWORD dwProcessId, LPCVOID lpBaseAddress, LPWSTR lpBuffer, SIZE_T nSize)
{
    // 打开进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwProcessId);
    if (hProcess == NULL)
    {
        lpBuffer[0] = L'\0';
        return;
    }

    // 读取字符串
    ReadUnicodeString(hProcess, lpBaseAddress, lpBuffer, nSize);

    // 关闭进程句柄
    CloseHandle(hProcess);
}

要使用此函数,您需要将要读取的进程的 ID、要读取的内存地址以及要存储结果的缓冲区传递给它。如果读取成功,则缓冲区将包含读取的字符串,否则缓冲区将包含空字符串。请注意,传递给函数的缓冲区大小应该足够大,以容纳要读取的字符串。如果缓冲区太小,则只能读取部分字符串。

是unicode字符串,可以自己解析,或者使用A2W或者W2A之类的字符转换进行转换后输出,或者直接用CString,例如CString str = CString(CStringA(xxx)) xxx为文本保存地址

以下答案引用自GPT-3大模型,请合理使用:

。
要读取unicode字符串,可以修改上面的代码如下:

UINT64 ReadUnicodeStringFromProcess(INT pid, PVOID 地址, ULONG64 bufSize)
{
  DWORD dwRetSize = 0;//返回字节数


    //存放读取的数据
    WCHAR* tmpBuf = (WCHAR*) ExAllocatePool(NonPagedPool, bufSize); 

    UINT64 输入缓冲区[4] = { pid,地址,0,bufSize };


    DeviceIoControl(
        DeviceHandle,//CreateFile打开驱动设备 返回的句柄
        通过PID读整数1,//控制码 CTL_CODE

        &输入缓冲区,//输入缓冲区指针
        8 * 4,//输入缓冲区大小

        tmpBuf,//返回缓冲区
        bufSize,//返回缓冲区大小

        &dwRetSize, //返回字节数
        NULL);

    printf("Read string from process is : %ws\n", tmpBuf);

    ExFreePool(tmpBuf);

    return tmp;

}

如果我的回答解决了您的问题,请采纳我的回答

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^