I've seen it around when snooping through source code and mainly used as an offset from what I can tell. but I'm a little confused as to what exactly is it?
Where exactly is it pointing too
what would be the difference between 0x8000000000000000UL and 0x80000000 other than the UL, I know that makes it an unsigned long.
If I were to go about messing with physical memory (lets say I had a system that would let me) how would I use this in my code if its needed?
For clarification the main confusion I'm having right now is understanding how such a big value is able to be used when dealing with memory locations. I normally don't see that kind of value used when referring to offsets.
I do some programming for homebrew on the xbox 360 so thats mainly where I see it. The following is code to dump a hypervisor from memory.
dprintf("Dumping HV....\n");
UINT64 dest = 0x8000010600032500ULL;
BYTE* pbPayload = (BYTE*)XPhysicalAlloc(0x100, MAXULONG_PTR, 0, PAGE_READWRITE);
memcpy(pbPayload, hvPayload, 112);
UINT64 src = 0x8000000000000000ULL + ((DWORD)MmGetPhysicalAddress(pbPayload));
BYTE* pbHypervisor = (BYTE*)XPhysicalAlloc(0x40000, MAXULONG_PTR, 0, PAGE_READWRITE);
memset(pbHypervisor, 0, 0x40000);
UINT64 xArg = 0x8000000000000000ULL + ((DWORD)MmGetPhysicalAddress(pbHypervisor));
HvxGetVersion(0x72627472, 4, dest, src, 0x40, xArg);
dprintf("HV dumped\nSaving HV....\n");
NOTE: HvxGetVersion reads memory
pastebin.com/D5vMH5CW
Another place I can think of that I've seen it is in libxenon, a library to help create homebrew from little to no pre-existing code.
void *target = (void*)(((unsigned long)0x8000000000000000UL) | shdr->sh_addr);
if (shdr->sh_type == SHT_NOBITS) {
memset (target, 0, shdr->sh_size);
} else {
memcpy ((void *) target,
(unsigned char *) addr + shdr->sh_offset,
shdr->sh_size);
}
flush_code (target, shdr->sh_size);
puts("done");
https://github.com/Free60Project/libxenon
Related
I need to read a large file in parts to a limited buffer. My code works, but always reads from the beginning. I think I need to use dwFileOffsetHigh somehow and dwFileOffsetLow, but I can't figure out how. Mapper_Winapi_Uptr is a unique_ptr with a custom deleter, if necessary I can lay out its code.
System: 64bit Win10.
const std::vector<BYTE>& ReadFile(size_t pos) {
memory = Mapper_Winapi_Uptr{ static_cast<BYTE*>(MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, bufferSize)) };
std::memcpy(&data[0], memory.get(), bufferSize);
return data;
}
You are mapping the view at file offset 0, ignoring your pos parameter which is presumably the desired file offset.
MapViewOfFile() takes a 64bit offset as input, split into 32bit low and high values. A size_t may be a 32bit or 64bit type, depending on compiler and platform. You can put your desired offset into a ULARGE_INTEGER first, that will give you the low and high values you can then give to MapViewOfFile().
Note that the file offset you give to MapViewOfFile() must be a multiple of the system allocation granularity. See Creating a View Within a File on MSDN for details on how to handle that.
Try something like this:
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
DWORD SysGran = SysInfo.dwAllocationGranularity;
...
const std::vector<BYTE>& ReadFile(size_t pos)
{
size_t MapViewStart = (pos / SysGran) * SysGran;
DWORD MapViewSize = (pos % SysGran) + bufferSize;
DWORD ViewDelta = pos - MapViewStart;
ULARGE_INTEGER ulOffset;
ulOffset.QuadPart = MapViewStart;
memory = Mapper_Winapi_Uptr{ static_cast<BYTE*>(MapViewOfFile(mapping, FILE_MAP_READ, ulOffset.HighPart, ulOffset.LowPart, bufferSize)) };
if (!memory.get()) {
// error handling ...
}
std::memcpy(&data[0], &(memory.get())[ViewDelta], bufferSize);
return data;
}
I have struggled with a very annoying problem lately with writing to Process memory in c++... I can not write to process memory with multiple offsets! Even though there are thousands of pages explaining how you fix this problem, it still seems to not work for me. I have been searching around on google all day long, and found many examples of how to fix this problem, but it still seems to not work for me.
So, let me first explain how I am writing to process memory myself, and you could possibly correct it afterwards.
Let us say I have a base address of: 0x04AF3C94
First offsets as: 0x1C
Second offsets as: 0x20
Third as: 0x568
And fourth as: 0x134
How I am doing this myself:
DWORD offset1 = 0x1C;
DWORD offset2 = 0x20;
DWORD offset3 = 0x568;
DWORD offset4 = 0x134;
DWORD base = 0x04AF3C94;
DWORD pointer;
DWORD pointer2;
DWORD pointer3;
DWORD pointer4;
DWORD pointer5;
ReadProcessMemory(handle, LPVOID(base), &pointer, sizeof(pointer), 0);
ReadProcessMemory(handle, LPVOID(pointer + offset1), &pointer2, sizeof(pointer2), 0);
ReadProcessMemory(handle, LPVOID(pointer2 + offset2), &pointer3, sizeof(pointer3), 0);
ReadProcessMemory(handle, LPVOID(pointer3 + offset3), &pointer4, sizeof(pointer4), 0);
ReadProcessMemory(handle, LPVOID(pointer4 + offset4), &pointer5, sizeof(pointer4), 0);
int value = 500;
WriteProcessMemory(handle, LPVOID(pointer5), &value, sizeof(value), 0);
As you can see, if I have 4 offsets such as in this example, I am adding every offset one at a time to the base address, until I got one value that stores every offset added to the baseaddress.
This apparently don't work, what should I do!?
I can't reply to all with your description, but in the MSDN they say that ReadProcessMemory read memory from where it is asked to the given buffer. It means when you call...
ReadProcessMemory(handle, LPVOID(base), &pointer, sizeof(pointer), 0);
...your "pointer" will be filled with what is at the "base" address. So it will contain an address that is numericaly the value of the four bytes at address "base". This is probably not what you want, because if you didn't stored something there before, it's indeterminate. And if so, it will probably crash when you use "pointer".
If you want to read the memory at adresse "base + offset1" with that function, what you have to do is:
ReadProcessMemory(handle, LPVOID(base + offset1), some_buffer, some_buffer_size, 0);
Where some_buffer is a valid buffer you have to declare somewhere.
__m128i* pData = reinterpret_cast<__m128i*>(
_aligned_malloc(
128,
16));
std::vector<byte> sectorBytes = dataSet.GetSectorBytes(index);
index &= 0xfff;
memcpy(pData, §orBytes[index], 128);
as you can see, I'm trying to copy 128 bytes from sectorBytes (which has no guarantees of 16-byte-alignment) into pData, which does. Unfortunately, after setting a breakpoint to check, I've found that while sectorBytes has exactly what I'd anticipated it to have, pData[0] through pData[7] contain only zeroes... so nothing is actually getting copied.
I don't understand why nothing's being copied... why is this happening?
Of course, the larger task I'm trying to accomplish is taking 128 bytes from a file at a specified offset, and then performing _mm_xor_si128() on them without an access violation popping up from trying to do simd operations on data that isn't 16-byte-aligned. In the interest of facilitating that discussion, here's GetSectorBytes():
std::vector<byte> GetSectorBytes(
_In_ const uint32_t index) const throw()
{
std::vector<byte> buffer(0x1000);
int indexOuter = index & 0xfffff000;
_OVERLAPPED positionalData;
positionalData.Offset = indexOuter;
positionalData.OffsetHigh = 0;
positionalData.hEvent = 0;
ReadFile(
hMappedFile,
&buffer[0],
0x1000,
NULL,
&positionalData);
return buffer;
}
hMappedFile was created with CreateFile2 with the FILE_FLAG_NO_BUFFERING flag set.
I'm working at some legacy code right now (converting some of it to C#), and I've stumbled upon a problem:
A byte array is created (length is ulcLen):
CSLAutoArray<BYTE> pMem(new BYTE[ulcLen]);
Now some stuff is put into the byte array, after which a CRC / Hash value is supposed to be written to the first four bytes (ULONG / UInt32):
__CfgCRC(pMem + sizeof(ULONG), ulcLen - sizeof(ULONG))
->
inline ULONG __CfgCRC(const void* const cpcMem, const ULONG ulcMemSize)
{
ULONG ulRes = 0;
const BYTE* const cpcUseMem = reinterpret_cast<const BYTE*>(cpcMem);
for(const BYTE* pcLook = cpcUseMem; cpcUseMem + ulcMemSize > pcLook; pcLook++)
{
ulRes ^= static_cast<ULONG>(*pcLook);
//[...]
};
return ulRes;
};
Now, is it just me, or is the static_cast reading 1/2/3 bytes over the end of the byte array, at the end of the for loop? Since pcLook (the memory pointer) is increased until it reaches the full length of the data, (ulclen + sizeof(ULONG)) ? Or am I wrong? Or does static_cast somehow not read over the end of an array ? (CSLAutoArray is some kind of managed pointer class, but as far as I see it does not interfere with this code)
*pcLook is just a BYTE so no, it's only reading 1 octet at a time. the cast just casts the BYTE and not what pcLock is pointing to.
I have a very large file and I need to read it in small pieces and then process each piece. I'm using MapViewOfFile function to map a piece in memory, but after reading first part I can't read the second. It throws when I'm trying to map it.
char *tmp_buffer = new char[bufferSize];
LPCWSTR input = L"input";
OFSTRUCT tOfStr;
tOfStr.cBytes = sizeof tOfStr;
HANDLE inputFile = (HANDLE)OpenFile(inputFileName, &tOfStr, OF_READ);
HANDLE fileMap = CreateFileMapping(inputFile, NULL, PAGE_READONLY, 0, 0, input);
while (offset < fileSize)
{
long k = 0;
bool cutted = false;
offset -= tempBufferSize;
if (fileSize - offset <= bufferSize)
{
bufferSize = fileSize - offset;
}
char *buffer = new char[bufferSize + tempBufferSize];
for(int i = 0; i < tempBufferSize; i++)
{
buffer[i] = tempBuffer[i];
}
char *tmp_buffer = new char[bufferSize];
LPCWSTR input = L"input";
HANDLE inputFile;
OFSTRUCT tOfStr;
tOfStr.cBytes = sizeof tOfStr;
long long offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
long long offsetLow = (offset & 0xFFFFFFFF);
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
memcpy(&buffer[tempBufferSize], &tmp_buffer[0], bufferSize);
UnmapViewOfFile(tmp_buffer);
offset += bufferSize;
offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
offsetLow = (offset & 0xFFFFFFFF);
if (offset < fileSize)
{
char *next;
next = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, 1);
if (next[0] >= '0' && next[0] <= '9')
{
cutted = true;
}
UnmapViewOfFile(next);
}
ostringstream path_stream;
path_stream << tempPath << splitNum;
ProcessChunk(buffer, path_stream.str(), cutted, bufferSize);
delete buffer;
cout << (splitNum + 1) << " file(s) sorted" << endl;
splitNum++;
}
One possibility is that you're not using an offset that's a multiple of the allocation granularity. From MSDN:
The combination of the high and low offsets must specify an offset within the file mapping. They must also match the memory allocation granularity of the system. That is, the offset must be a multiple of the allocation granularity. To obtain the memory allocation granularity of the system, use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure.
If you try to map at something other than a multiple of the allocation granularity, the mapping will fail and GetLastError will return ERROR_MAPPED_ALIGNMENT.
Other than that, there are many problems in the code sample that make it very difficult to see what you're trying to do and where it's going wrong. At a minimum, you need to solve the memory leaks. You seem to be allocating and then leaking completely unnecessary buffers. Giving them better names can make it clear what they are actually used for.
Then I suggest putting a breakpoint on the calls to MapViewOfFile, and then checking all of the parameter values you're passing in to make sure they look right. As a start, on the second call, you'd expect offsetHigh to be 0 and offsetLow to be bufferSize.
A few suspicious things off the bat:
HANDLE inputFile = (HANDLE)OpenFile(inputFileName, &tOfStr, OF_READ);
Every cast should make you suspicious. Sometimes they are necessary, but make sure you understand why. At this point you should ask yourself why every other file API you're using requires a HANDLE and this function returns an HFILE. If you check OpenFile documentation, you'll see, "This function has limited capabilities and is not recommended. For new application development, use the CreateFile function." I know that sounds confusing because you want to open an existing file, but CreateFile can do exactly that, and it returns the right type.
long long offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
What type is offset? You probably want to make sure it's an unsigned long long or equivalent. When bitshifting, especially to the right, you almost always want an unsigned type to avoid sign-extension. You also have to make sure that it's a type that has more bits than the amount you're shifting by--shifting a 32-bit value by 32 (or more) bits is actually undefined in C and C++, which allows the compilers to do certain types of optimizations.
long long offsetLow = (offset & 0xFFFFFFFF);
In both of these statements, you have to be careful about the 0xFFFFFFFF value. Since you didn't cast it or give it a suffix, it can be hard to predict whether the compiler will treat it as an int or unsigned int. In this case,
it'll be an unsigned int, but that won't be obvious to many people. In fact,
I got this wrong when I first wrote this answer. [This paragraph corrected 16-MAY-2017] With bitwise operations, you almost always want to make sure you're using unsigned values.
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
You're casting offsetHigh and offsetLow to ints, which are signed values. The API actually wants DWORDs, which are unsigned values. Rather than casting in the call, I would declare offsetHigh and offsetLow as DWORDs and do the casting in the initialization, like this:
DWORD offsetHigh = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD offsetLow = static_cast<DWORD>( offset & 0xFFFFFFFFul);
tmp_buffer = reinterpret_cast<const char *>(MapViewOfFile(fileMap, FILE_MAP_READ, offsetHigh, offsetLow, bufferSize));
Those fixes may or may not resolve your problem. It's hard to tell what's going on from the incomplete code sample.
Here's a working sample you can compare to:
// Calls ProcessChunk with each chunk of the file.
void ReadInChunks(const WCHAR *pszFileName) {
// Offsets must be a multiple of the system's allocation granularity. We
// guarantee this by making our view size equal to the allocation granularity.
SYSTEM_INFO sysinfo = {0};
::GetSystemInfo(&sysinfo);
DWORD cbView = sysinfo.dwAllocationGranularity;
HANDLE hfile = ::CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hfile != INVALID_HANDLE_VALUE) {
LARGE_INTEGER file_size = {0};
::GetFileSizeEx(hfile, &file_size);
const unsigned long long cbFile =
static_cast<unsigned long long>(file_size.QuadPart);
HANDLE hmap = ::CreateFileMappingW(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hmap != NULL) {
for (unsigned long long offset = 0; offset < cbFile; offset += cbView) {
DWORD high = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD low = static_cast<DWORD>( offset & 0xFFFFFFFFul);
// The last view may be shorter.
if (offset + cbView > cbFile) {
cbView = static_cast<int>(cbFile - offset);
}
const char *pView = static_cast<const char *>(
::MapViewOfFile(hmap, FILE_MAP_READ, high, low, cbView));
if (pView != NULL) {
ProcessChunk(pView, cbView);
}
}
::CloseHandle(hmap);
}
::CloseHandle(hfile);
}
}
You have a memory leak in your code:
char *tmp_buffer = new char[bufferSize];
[ ... ]
while (offset < fileSize)
{
[ ... ]
char *tmp_buffer = new char[bufferSize];
[ ... ]
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
[ ... ]
}
You're never delete what you allocate via new char[] during every iteration there. If your file is large enough / you do enough iterations of this loop, the memory allocation will eventually fail - that's then you'll see a throw() done by the allocator.
Win32 API calls like MapViewOfFile() are not C++ and never throw, they return error codes (the latter NULL on failure). Therefore, if you see exceptions, something's wrong in you C++ code. Likely the above.
I also had some troubles with memory mapped files.
Basically I just wanted to share memory (1Mo) between 2 apps on the same Pc.
- Both apps where written in Delphi
- Using Windows8 Pro
At first one application (the first one launched) could read and write the memoryMappedFile, but the second one could only read it (error 5 : AccessDenied)
Finally after a lot of testing It suddenly worked when both application where using CreateFileMapping. I even tried to create my on security descriptor, nothing helped.
Just before my applications where first calling OpenFileMapping and then CreateFileMapping if the first one failed
Another thing that misleaded me is that the handles , although visibly referencing the same MemoryMappedFile where different in both applications.
One last thing, after this correction my application seemed to work all right, but after a while I had error_NotEnough_Memory. when calling MapViewOfFile.
It was just a beginner's mistake of my part, I was not always calling UnmapViewOfFile.