so I will explain what im trying to do and i wanna understand why its not working for me,
I found an Address from CE : which is: 0x04013118
with value an array of bytes: DC 04 00 00 04 02 00 00
What im trying to do is write memory with kernel driver to this address a new value which is also an array of bytes :
DC 04 00 00 00 00 00 00
Here is most of the function im trying to use , but most of the parameters are defined in other classes i cannot provide all of them but i think part of the code ( just im going to put here ) is already enough,
this is part of the MemoryManager.cpp and also 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, nullptr, nullptr, &ioStatusBlock, MM_READVIRTUALMEMORY, &input, sizeof(input), nullptr, 0);
}
void MemoryManager::writeMemory(PVOID BaseAddress, PVOID Buffer, SIZE_T BufferSize) {
if (!allIsWell)
return;
struct {
HANDLE ProcessHandle;
PVOID BaseAddress;
PVOID Buffer;
SIZE_T BufferSize;
PSIZE_T NumberOfBytesWritten;
} input = { processHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesWrite };
IO_STATUS_BLOCK ioStatusBlock;
NtDeviceIoControlFile(m_hDriver, nullptr, nullptr, nullptr, &ioStatusBlock, MM_WRITEVIRTUALMEMORY, &input, sizeof(input), nullptr, 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, &mbi, 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, bSearchData, 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, &_d, 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, 0x00, 0x00, 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, 0x04, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
std::vector<DWORD_PTR> foundedBases;
MemoryManager->search(pattern, sizeof(pattern), 0x04000000, 0x05000000, false, 0, 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;
}
this is the MemoryManager.h: ( if someone interested )
#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, PVOID Buffer, SIZE_T BufferSize);
void writeMemory(PVOID BaseAddress, PVOID Buffer, SIZE_T BufferSize); // created by oday
bool search(BYTE * bSearchData, int nSearchSize, DWORD_PTR dwStartAddr, DWORD_PTR dwEndAddr, BOOL bIsCurrProcess, int iSearchMode, std::vector<DWORD_PTR>& vRet);
int find(BYTE * buffer, int dwBufferSize, 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;
The interesting part lays in this:
BYTE writePattern[] = { 0xDC, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
pMemoryManager->writeMemory((PVOID)bypassAddr1, &writePattern, sizeof(writePattern));
I successfully read the address at 0x04013118 from the search function from the current pattern, and everything is fine, but when i try to write to this address with this what i mentioned here up nothing happens in the memory, and the value doesn't change, does anybody have an idea why nothing happens and the memory doesn't change? im pretty sure my kernel driver has nothing to do with this because its vuln and it has permissions to read and write.
I will draw a short conclusion for others having the same problem.
The main problem was that the author was unable to write to a specific memory location within a processes memory.
With the help of the windows API function VirtualProtectEx
the author was able to change the virtual memory page access bits to allow writing to the memory page of the desired memory address.
The procedure includes:
VirtualProtectEx
to enable writing to the memory pageVirtualProtectEx