c ++内存写入字节以使用内核驱动程序进行寻址

问题描述

所以我将解释我正在尝试做什么,我想了解为什么它对我不起作用,

我从CE找到了一个地址:0x04013118,其值是字节数组:DC 04 00 00 04 02 00 00

我想做的是用内核驱动程序向该地址写入一个新值,该值也是一个字节数组:
DC 04 00 00 00 00 00 00

这里是我试图使用的大多数功能,但是大多数参数是在其他类中定义的,我无法提供所有这些参数,但是我认为部分代码(我将要放在这里)已经足够了,

这是MemoryManager.cpp和BypassMemory.cpp的一部分:

void MemoryManager::readMemory(PVOID BaseAddress,PVOID Buffer,SIZE_T BufferSize){
    if(!allIsWell)
        return;

    struct{
        HANDLE ProcessHandle;
        PVOID BaseAddress;
        PVOID Buffer;
        SIZE_T BufferSize;
        PSIZE_T NumberOfBytesRead;
    } input = { processHandle,BaseAddress,Buffer,BufferSize,NumberOfBytes };

    IO_STATUS_BLOCK ioStatusBlock;

    NtDeviceIoControlFile(m_hDriver,nullptr,&ioStatusBlock,MM_READVIRTUALMEMORY,&input,sizeof(input),0);

}

void MemoryManager::writeMemory(PVOID BaseAddress,SIZE_T BufferSize) {

    if (!allIsWell)
        return;

    struct {
        HANDLE ProcessHandle;
        PVOID BaseAddress;
        PVOID Buffer;
        SIZE_T BufferSize;
        PSIZE_T NumberOfBytesWritten;
    } input = { processHandle,NumberOfBytesWrite };

    IO_STATUS_BLOCK ioStatusBlock;

    NtDeviceIoControlFile(m_hDriver,MM_WRITEVIRTUALMEMORY,0);


}


bool MemoryManager::search(BYTE * bSearchData,int nSearchSize,DWORD_PTR dwStartAddr,DWORD_PTR dwEndAddr,BOOL bIsCurrProcess,int iSearchMode,std::vector<DWORD_PTR> &vRet){

    MEMORY_BASIC_INFORMATION    mbi;
    std::vector<MEMORY_REGION> m_vMemoryRegion;
    mbi.RegionSize = 0x400;
    DWORD dwAddress = dwStartAddr;

    MEMORY_REGION memSectorList[1000];

    int memSectorIndex = 0;
    while(VirtualQueryEx(processHandle,(LPCVOID)dwAddress,&mbi,sizeof(mbi)) && (dwAddress < dwEndAddr) && ((dwAddress + mbi.RegionSize) > dwAddress)){
        if(
            (mbi.State == MEM_COMMIT) &&
            ((mbi.Protect & PAGE_GUARD) == 0) &&
            (mbi.Protect != PAGE_NOACCESS) &&
            ((mbi.AllocationProtect & PAGE_NOCACHE) != PAGE_NOCACHE)
            ){
            MEMORY_REGION mData = { 0 };
            mData.dwBaseAddr = (DWORD_PTR)mbi.BaseAddress;
            mData.dwMemorySize = mbi.RegionSize;
            m_vMemoryRegion.push_back(mData);
            memSectorList[memSectorIndex] = mData;
            memSectorIndex++;
        }
        dwAddress = (DWORD)mbi.BaseAddress + mbi.RegionSize;
    }

    std::vector<MEMORY_REGION>::iterator it;
    int memSectorCount = memSectorIndex;
    memSectorIndex = 0;
    DWORD_PTR curAddr = dwStartAddr;
    while(curAddr < dwEndAddr){
        VirtualQueryEx(processHandle,(LPCVOID)curAddr,sizeof(mbi));
        long regionSizeOrg = mbi.RegionSize;
        long regionSize = mbi.RegionSize;
        if(regionSize > 10){
            BYTE* pCurrMemoryData = new BYTE[regionSize];
            ZeroMemory(pCurrMemoryData,regionSize);
            writeMemory((PVOID)curAddr,(PVOID*)pCurrMemoryData,regionSize);
            DWORD_PTR dwOffset = 0;
            int iOffset = find(pCurrMemoryData,regionSize,bSearchData,nSearchSize);
            while(iOffset != -1){
                dwOffset += iOffset;
                vRet.push_back(dwOffset + curAddr);
                dwOffset += nSearchSize;
                iOffset = find(pCurrMemoryData + dwOffset,regionSize - dwOffset - nSearchSize,nSearchSize);
            }
            delete[] pCurrMemoryData;
        }
        memSectorIndex++;
        curAddr = curAddr + (DWORD_PTR)regionSizeOrg;
        continue;
    }
    return TRUE;
}
int MemoryManager::find(BYTE *buffer,int dwBufferSize,BYTE *bstr,DWORD dwStrLen){
    if(dwBufferSize < 0){
        return -1;
    }
    DWORD  i,j;
    for(i = 0; i < dwBufferSize; i++){
        for(j = 0; j < dwStrLen; j++){
            if(buffer[i + j] != bstr[j] && bstr[j] != '?')
                break;
        }
        if(j == dwStrLen)
            return i;
    }
    return -1;
}


DWORD MemoryManager::dRead(DWORD base){ 
    readMemory((PVOID)base,&_d,4);
    return _d;
}

void MemoryManager::dWrite(DWORD base){
    writeMemory((PVOID)base,4);
}
/* these are in bypassmemory.cpp */
void BypassMemory::init(){
    viewWordBase = getAddr(); // = works and gets Addrs = 0x04013118

    if(viewWordBase){
        std::cout << "found addr : " << termcolor::green << std::hex << viewWordBase << std::dec << termcolor::reset << "\n";
    } else{
        std::cout << termcolor::red << "View World Not Found ! \n" << termcolor::reset;
        return;
    }
    // so basiclly my addres = 0x04013118 and value of it = DC 04 00 00 04 02 00 00
    BYTE writePattern[] = { 0xDC,0x04,0x00,0x00 }; 
    //const char* writePtr = "DC 04 00 00 00 00 00 00"; // i tried also this but didn't work

    MemoryManager->writeMemory((PVOID)bypassAddr1,&writePattern,sizeof(writePattern)); // i write to the base addres ( 0x04013118,new val = DC 04 00 00 00 00 00 00)

    //MemoryManager->writeMemory((PVOID)bypassAddr1,&writePtr,sizeof(writePtr));

}

DWORD BypassMemory::getAddr(){

    BYTE pattern[] = { 0xDC,0x02,0x00 };
    std::vector<DWORD_PTR> foundedBases;
    MemoryManager->search(pattern,sizeof(pattern),0x04000000,0x05000000,false,foundedBases);
    std::cout << "founded bases size: " << termcolor::green << std::hex << foundedBases.size() << std::dec << termcolor::reset << "\n";
    for(int i = 0; i < foundedBases.size(); i++){
        DWORD cand = dGet(foundedBases[i]); // this reads inside the address purpose to check
        std::cout << "founded bases addr: " << termcolor::green << std::hex << foundedBases[i] << std::dec << termcolor::reset << "\n";
        return foundedBases[i];
    }
    return 0;

}

int main()
{

    int Pid = ProcManager::getAowProcID();
     

    pMemoryManager->init(Pid,true);


    BypassMemory->init();

    return 0;
 }

这是MemoryManager.h :(如果有兴趣的话)

#define MM_DEVICE_TYPE 0x9999
#define MM_CTL_CODE(x) CTL_CODE(MM_DEVICE_TYPE,0x800 + x,METHOD_NEITHER,FILE_ANY_ACCESS)
#define MM_READVIRTUALMEMORY MM_CTL_CODE(56)
#define MM_WRITEVIRTUALMEMORY MM_CTL_CODE(57)

typedef struct _MEMORY_REGION{
    DWORD_PTR dwBaseAddr;
    DWORD_PTR dwMemorySize;
}MEMORY_REGION;

class MemoryManager{
public:
    MemoryManager();
    ~MemoryManager();


    HANDLE m_hDriver = nullptr;
    HANDLE processHandle;
    int processId = 0;
    bool allIsWell = false;
    PSIZE_T NumberOfBytes = nullptr;
    PSIZE_T NumberOfBytesWrite = nullptr; // created by oday

    DWORD _d;
    float _f;
    int _i;

    BYTE* _b = new BYTE[1];


    int _dw = 1245; // created by oday

    void init(int pid,bool debug);

    bool connectToDriver(std::string m_strDeviceName);

    void readMemory(PVOID BaseAddress,SIZE_T BufferSize);

    void writeMemory(PVOID BaseAddress,SIZE_T BufferSize); // created by oday

    bool search(BYTE * bSearchData,std::vector<DWORD_PTR>& vRet);

    int find(BYTE * buffer,BYTE * bstr,DWORD dwStrLen);


    void dWrite(DWORD base); // created by oday

    DWORD dRead(DWORD base);
    float fRead(DWORD base);
    int iRead(DWORD base);
    BYTE* bRead(DWORD base);

};


extern MemoryManager* pMemoryManager;

有趣的部分在于:

BYTE writePattern[] = { 0xDC,0x00 };
pMemoryManager->writeMemory((PVOID)bypassAddr1,sizeof(writePattern));

我从当前模式的搜索功能中成功读取了0x04013118的地址,并且一切都很好,但是当我尝试使用此处提到的内容写入此地址时 内存中什么都没有发生,并且值没有改变,是否有人知道为什么什么都不发生并且内存没有改变?我非常确定我的内核驱动程序与此无关,因为它的漏洞并且具有读写权限。

解决方法

对于有相同问题的其他人,我会得出一个简短的结论。

主要问题是作者无法写入进程内存中的特定内存位置。

在Windows API函数VirtualProtectEx的帮助下,作者可以更改虚拟内存页访问位,以允许写入所需内存地址的内存页。

该过程包括:

  1. 调用VirtualProtectEx以启用写入内存页面
  2. 写入该页面内的特定内存位置
  3. 通过再次调用VirtualProtectEx
  4. 重置页面访问位

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...