ReadProcessMemory with Chez Scheme FFI - ffi

I'm having some trouble reading from an arbitrary memory address using Chez Scheme's FFI and the kernel32/user32.dll's ReadProcessMemory function. I got the process handle and everything fine, but I'm struggling with quite a few aspects of the read function itself:
(define (read-process-memory handle address size)
((foreign-procedure "ReadProcessMemory" (iptr iptr string int iptr) iptr)
handle address byte-array size output-ptr))
(define address (make-ftype-pointer iptr #x14a24d63660))
(read-process-memory process-handle address 4)
From this I get Exception in read-process-memory: invalid foreign-procedure argument #<ftype-pointer iptr 1417957226080>, but I'm pretty sure I'm approaching a lot of things about this wrong.
Thanks in advance

This works:
(define (read-process-memory handle address size)
(let ((temp-buffer (foreign-alloc size)))
(set! success ((foreign-procedure "ReadProcessMemory" (unsigned-32 unsigned-32 uptr unsigned-32 u8*) boolean)
handle address temp-buffer size #f))
(set! result (foreign-ref 'unsigned-32 temp-buffer 0))
(foreign-free temp-buffer)))
Like other implementations, the process-handle and the address can just be unsigned-32's rather than a pointer, so I switched those types, same for the size although that wasn't necessary. The return type should be a boolean, not a pointer, I wasn't paying attention. The boolean indicates the success of the memory read.
Although passing in a string for the buffer works in some implementations, in Chez it does not mutate the string, most likely because it's not passed by reference. The proper solution is to make it accept a uptr instead, (foreign-alloc the size you need, and since that will pass in its own address, it will be mutated correctly and then you can get the answer back with (foreign-ref, which I store in result, then free the allocated memory.
Also it's worth mentioning the address in my original question is a 64-bit address, so an unsigned-64 needs to be used in order to properly access that address.

Related

Following a pointer to a pointer

sqlite3_open takes a pointer to a pointer. Id like to trace the address of the second pointer.
E.g: p1(p2(obj))
https://www.sqlite.org/c3ref/open.html
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
What is the syntax to get the address of that pointer in DTrace?
Im using the pid$target::sqlite3_open:return probe to read from the arg1 that was set from the entry probe.
Im currently using:
// Copy pointer bytes from arg1 to kernel, cast to pointer.
(uintptr_t *)copyin(arg1, sizeof(uintptr_t))
Which results in: invalid kernel access in action.
Im on MacOS with SIP enabled, is this the issue?
I may be misunderstanding your question, but what I suspect is that you've misunderstood how sqlite3_open works.
To call sqlite3_open you should have a code that looks like this:
sqlite3 * pDB = NULL;
/* ... */
int result = sqlite3_open("file:database.db", &pDB);
As you see, there's no "pointer to pointer" variable in my code. Instead, sqlite3_ope takes the address of of a pointer variable I allocated on the stack.
To copy that pointer is as simple as:
sqlite3 * pDB2 = pDB
The reason for this is simple:
The sqlite3_open function wants to return two variable, which is impossible in C.
Instead of returning two variables, sqlite3_open returns only one variable directly and returns the second variable indirectly.
In order to return the second, it takes a pointer to a variable of the same type it wants to return. Then, by dereferencing the address and filling in the value, it provides you with the second variable's value.
However, the second variable sqlite3_open returns is a pointer. This is why, in order to return a pointer as a second variable, sqlite3_open requires a pointer to a pointer variable.
Reading the address
In the example above, the pDB variable holds the address for the sqlite3 object (the one allocated by sqlite3_open).
The address, as you know, is simply a number representing a location in the memory. To read the pointer value as a number, simply cast the pointer to a uintptr_t. i.e.:
uintptr_t db_mem_addr_value = (uintptr_t)pDB;
Of course, numbers (and memory addresses) can't be printed as hex strings directly, they need a function that will convert them into hex notation.
Consider that in C you would print the memory address in Hex notation by using printf i.e.,
fprintf(stderr, "%p\n", (void *)pDB);
Using dtrace would be the same. You might want to convert the pointer address to a number, for example, using the lltostr dtrace function:
lltostr((uintptr_t)*(void**)arg1, 16)
Not a dtrace pro, but here are some observations.
uintptr_t is defined to be large enough to hold any pointer converted to an integer. Note that this does not imply that sizeof(uintptr_t) == sizeof(void*). It is perfectly valid (and on some platforms, necessary) for uintptr_t to be strictly larger than a pointer. That means your copyin call might be copying more bytes than are actually there. Try using a size of sizeof(sqlite**) instead.
Also, it's possible that some of OSX's internal protection mechanisms are causing you problems. See the answer on this related question for a good explanation.

Doubts about pointer and memory access

i am just started learning pointers in c. I have following few doubts. If i find the answers for the below questions. It Will be really useful for me to understand the concept of pointers in c. Thanks in advance.
i)
char *cptr;
int value = 2345;
cptr = (char *)value;
whats the use of (char *) and what it mean in the above code snippet.
ii)
char *cptr;
int value = 2345;
cptr = value;
This also compiles without any error .then whats the difference between i & ii code snippet
iii) &value is returning address of the variable. Is it a virtual memory address in RAM? Suppose another c program running in parallel, will that program can have same memory address as &value. Will each process can have duplicate memory address same as in other process and it is independent of each other?
iv)
#define MY_REGISTER (*(volatile unsigned char*)0x1234)
void main()
{
MY_REGISTER=12;
printf("value in the address tamil is %d",(MY_REGISTER));
}
The above snippet compiled successfully. But it outputs segmentation fault error. I don't know what's the mistake I am doing. I want to know how to access the value of random address, using pointers. Is there any way? Will program have the address 0x1234 for real?
v) printf("value at the address %d",*(236632));//consider the address 236632 available in
//stack
why does the above printf statement showing error?
That's a type cast, it tells the compiler to treat one type as some other (possibly unrelated) type. As for the result, see point 2 below.
That makes cptr point to the address 2345.
Modern operating systems isolate the processes. The address of one variable in one process is not valid in another process, even if started with the same program. In fact, the second process may have a completely different memory map due to Address Space Layout Randomisation (ASLR).
It's because you try to write to address 0x1234 which might be a valid address on some systems, but not on most, and almost never on a PC running e.g. Windows or Linux.
i)
(char *) means, that you cast the data stored in value to a pointer ptr, which points to a char. Which means, that ptr points to the memory location 2345. In your code snipet ptr is undefined though. I guess there is more in that program.
ii)
The difference is, that you now write to cptr, which is (as you defined) a pointer pointing to a char. There is not much of a difference as in i) except, that you write to a different variable, and that you use a implicit cast, which gets resolved by the compiler. Again, cptr points now to the location 2345 and expects there to be a char
iii)
Yes you can say it is a virtual address. Also segmentation plays some parts in this game, but at your stage you don't need to worry about it at all. The OS will resolve that for you and makes sure, that you only overwrite variables in the memory space dedicated to your program. So if you run a program twice at the same time, and you print a pointer, it is most likely the same value, but they won't point at the same value in memory.
iv)
Didn't see the write instruction at first. You can't just write anywhere into memory, as you could overwrite another program's value.
v)
Similar issue as above. You cannot just dereference any number you want to, you first need to cast it to a pointer, otherwise neither the compiler, your OS nor your CPU will have a clue, to what exactely it is pointing to
Hope I could help you, but I recommend, that you dive again in some books about pointers in C.
i.) Type cast, you cast the integer to a char
ii.) You point to the address of 2345.
iii.) Refer to answer from Joachim Pileborg. ^ ASLR
iv.) You can't directly write into an address without knowing if there's already something in / if it even exists.
v.) Because you're actually using a pointer to print a normal integer out, which should throw the error C2100: illegal indirection.
You may think pointers like numbers on mailboxes. When you set a value to a pointer, e.g cptr = 2345 is like you move in front of mailbox 2345. That's ok, no actual interaction with the memory, hence no crash. When you state something like *cptr, this refers to the actual "content of the mailbox". Setting a value for *cptr is like trying to put something in the mailbox in front of you (memory location). If you don't know who it belongs to (how the application uses that memory), it's probably a bad idea. You could use "malloc" to initialize a pointer / allocate memory, and "free" to cleanup after you finish the job.

Character Array Pointers and Casts from Integers (Memory Address)

Okay, currently I am writing a kernel for the sake of my resume. While writing my memory management unit I have hit a brick wall.
int address = (int)malloc(sizeof(Test))
consoleWriteString("Variable Address:\n");
consoleWriteInteger(address);
char* f = (void*)address;
consoleWriteString("\nVariable Address:\n");
consoleWriteInteger((int)&f); // Should print off the same as above
Logically the output should be the same for both. Somewhere somthing has gone wrong though. as my output is the following.
Variable Address: 47167
Variable Address: 1065908
After a long period of testing and debugging I finally gave in and decided to ask stack overflow. Also if you spot any syntax errors ignore them. By the way this is all in C, and all functions are custom, including malloc, but I have determined that the error does not lie in that functon, or any other for a fact. I believe this is just me being stupid about pointers and casting but don't laugh at me when it was somthing super simple that I missed.
Thanks yall
&f is the address of f, not the address contained in it! f is on the stack. Its value (the address you first printed) is pointing to the allocated memory.
Think of it this way: You allocate room in memory for some stuff. This memory region has an address. You put the address in a pointer (f), so that it points to that region. But f itself needs to be somewhere in memory in order to hold the value of that address. In this case, f is on the stack, and &f gets the address of f (the container of the original address), not the address that f contains.
As an aside, be very careful casting addresses to int (and back!), since int might not be large enough to hold an address (e.g. on x86-64, depending on your compiler). I believe the correct type to use when you want to use an address as an integer is uintptr_t in stdint.h.
The value of f (which happens to be a pointer) is the same as address (which is also a pointer, but of a different type) - this is what you do in the line
char* f = (void*)address;
But then you print the address of f:
consoleWriteInteger((int)&f);
And that is not the same thing as the value of f... change that line to
consoleWriteInteger((int)f);
and you should be all set.
the first print out is an int, although malloc returns an address, The second is an address casted to an int. do f instead & gets you the address of a value while * dereferences a pointer getting you the value of what is being pointed to.

C call from Smalltalk

I'm trying to call EnumServicesStatus from within VisualWorks. For the first call I set the parameters to the required values to know how many bytes the returned information will require (pcbBytesNeeded).
Now I need to allocate memory for the lpServices buffer using malloc:, which expects the number of instances as an argument. How can I calculate this easily? Just dividing the pcbBytesNeeded by the size of of an LPENUM_SERVICE_STATUS struct makes my code crash when freeing the memory.
/Edit
I solved the crash when freeing the memory. (I accidently manipulated the variable holding the pointer). However, my question in the comment to Karsten is still valid. Why doesn't the size of ENUM_SERVICE_STATUS divide pcbBytesNeeded? Is this because of the LPTSTR lpServiceName and LPTSTR lpDisplayName members?
you can send #sizeOf to the ENUM_SERVICE_STATUS structure, similar to the sizeof(ENUM_SERVICE_STATUS) in C.
Something like:
numItems := pcbBytesNeeded / self ENUM_SERVICE_STATUS sizeOf.
please also make sure that you call the EnumServicesStatusW function, because EnumServicesStatus is a macro that actually points to EnumServicesStatusW.

return string pointer from function in C

Here is my code:
TCHAR *sResult = (TCHAR *) calloc(16384+1, sizeof(TCHAR));
sResult = (TCHAR *) GetValueFromFile(sFilename,L"Dept",L"Names"); // #1
_tcscpy(sResult,(TCHAR *) GetValueFromFile(sFilename,L"Dept",L"Names"); // #2
Function:
TCHAR *GetValueFromFile(TCHAR *sFilename,TCHAR *sDept,TCHAR *sNames)
{
...
}
Which is correct to do? #1 or #2?
Thanks everyone.
Edit #1:
I'm using VS2008 in .cpp files, but really just C code.
I just need to open a file in GetValueFromFile and send the return string back. Should I be allocating memory in GVFF and freeing it in my program?
main()
{
TCHAR *sResult;
DWORD dwRetVal = GetValueFromFile(sFile,L"Dept",L"Name", &sResult);
...
free(sResult);sResult=NULL;
}
Like this?
DWORD GetValueFromFile(TCHAR *sFilename,TCHAR *sDept,TCHAR *sNames, TCHAR ** sValueData)
{
dwL = GetStringDataLength(…)
*sValueData = (TCHAR *) calloc(dwL+1, sizeof(TCHAR));
_tcscpy_s(sValueData,dwL,sDataFromFile);
}
Well, first off, this is unnecessary in case 1 and leads to a problem:
TCHAR *sResult = (TCHAR *) calloc(16384+1, sizeof(TCHAR));
I don't know where 16384+1 is coming from, so I'll assume that's "correct" for now, but you proceed to set the pointer to another value in the very next line. That, my friend, is a memory leak. Why are you allocating memory that you don't need?
Your question really boils down to the implementation of GetValueFromFile. If that function returns a pointer (which it does) then it should certainly be a valid pointer and you are responsible for deallocating it (probably. Again, depends on the implementation).
There is no need to create a copy unless you actually need a copy. There is no "right" or "wrong" here from the information you have given us, we need to know the details of GetValueFromFile.
Per your edit:
That function does not return anything. At all. It's signature says it returns a DWORD, not a TCHAR*. It is obviously different than your first example as it initializes the pointer as an output argument (the 4th one), but that is not how you are calling it in your original example.
I am just further confused now, but if the function initializes the pointer then you need only declare (no memory allocation outside of the function) the pointer and pas in its address.
Given
DWORD GetValueFromFile(TCHAR *sFilename,TCHAR *sDept,TCHAR *sNames, TCHAR ** sValueData)
Then the proper way to pass your pointer in is:
TCHAR *result;
GetValueFromFile(filename, dept, names, &result);
The function initializes your result variable to point to a valid location. Do not forget that you are now responsible for deallocating it!
1 clearly is not correct. You start by allocating space with calloc, but then you overwrite the point to that space with the return from GetValueFromFile. Assuming no intervening code that saves that pointer somewhere else, this means you no longer have access to the memory you allocated, so you can no longer access or free it. In short, a big memory leak.
Depending on how GetValueFromFile allocates the memory to which it returns a pointer, #2 might be just as bad, but the code you posted doesn't tell us enough to know. If it returns something like a pointer to a statically allocated buffer, then chances are it's correct (for some definition of correct). If it's allocating space with something like malloc or calloc, and expecting the client code to release that when needed, then it has a problem similar to that in #1.
Note that the "for some definition of correct" basically translates to something like: "wrong the minute you have more than one thread, or any need for reentrancy". Given the current ubiquity of multicore and multiprocessor systems, that definition is pretty narrow now, and getting narrower all the time.

Resources