C++ insert function pointer into memory - c++

I am trying to overwrite a char and a function pointer on the stack. Based on what I found on this question (How can I store a value at a specific location in the memory?) I was able to figure out how to overwrite the character. My problem now is that I get a compile error saying I am casting it wrong.
void foo(char letter);
void bar(char letter);
void function1()
{
void (*pointer)(char);
pointer = foo;
letter = 'B';
function2();
(*pointer)(letter);
}
void function2()
{
int number; // Used in omitted code
*(char *)(&number + 75) = 'A';
*(void (*)(char)) (&number + 42) = &bar; // This is the line with the error
}
The first injection works but the second one gives me a compile error.
I am running Redhat Linux using a g++ compiler. The error I get from the compiler is:
"cannot convert ‘void (*)(char)’ to ‘void(char)’ in assignment"
If I change that line to *(void(char)) then the compiler says:
"invalid cast to function type ‘void(char)’"
What is the proper syntax for this?
(This is modified code from a school security assignment, I'm not writing malware)

Your goal is to write the address of pass to memory, so why are you casting (&number + 13) to a function pointer? Just do what you did before:
*(long *)(&number + 13) = (long)&pass;
And you won't get a compiler error. As to what will happen when this undefined behavior is invoked, you'll just have to see.
Edit: As #DavidGrayson pointed out, if we deference the right side of the equation, we'd get the contents of the function, not its pointer. So we have to cast it to a POD type, not a pointer.

Related

c++ give no warning or error when a integer is passed to a function that has char arguments

Why does c++ give no warning or error when a integer is passed to a function that takes char arguments.
void test(char a) {
std::cout << a;
}
test(1);
I would get unexpected behaviour doing so(ie a ? is getting printed). But I was expecting this to be an error or atleast a compilation warning as some sort of cast was happening. Why is this not happening?
I'm not really sure why c++ allow implicit conversion here, maybe because it's good for dealing with raw memory.
For why you get unexpected behavior
1 is a valid control code like '\0' or '\n'
while you should use '1' (or 49, assume ASCII or compatible format)
Compiler would warn if it does not fit in.
void test(char c);
void F(){test(1);} // OK
void G(){test(10000);} // warning
void H(int v){test(v);} // need -Wconversion
Compiler Explorer

address returned is not what's stored in the value

I'm trying to debug a small C++ program using gdb, but may be getting hung up on some pointer arithmetic:
A* get(int) returns a pointer to an instance of a class A I've defined. Internally, get(int) references an array of A, returning:
class A_list {
private:
A* A_array;
int count;
public:
A_list(int c): count(c) { A = new A[c]; }
void insertAt(A a, int idx) {
A_array[idx] = a;
}
A* get(int);
};
A* A_list::get(int idx) {
...
A* result = A_array + idx;
return result;
}
presumably, when dealing with an array of A, I can simply add the index (times the size of a single A) to get the address of the idx'th.
This seems to work as expected. However, when calling get(int) from within another member function of A_list, I watch the value assignment in gdb and see two different values:
void A_list::foo() {
A* a = nullptr; // I declare my pointer, and initialize to 0x0
...
a = get(0); // I store the address of `A_array[0]`
The gdb watchpoint outputs:
Old value = (Number *) 0x0
New value = (Number *) 0x55555556b2c0
However, when I print the address stored in a, I get a completely different value, with an unrecognized message attached.
(gdb) p a
(Number *) 0x7ffff7b4e5c0 <_IO_file_overflow+256>
attempting to dereference any of the member values gives unexpected results
I can't find <_IO_file_overflow+256> defined anywhere in the gdb sources. What does it mean?
Why might the value stored in a appear to be different from the value returned when get() is called from inside a member function of A_list? From outside (eg - in main()) I get the expected value.
Edit 9-08:
Changed assignment in get() based on feedback. Still getting the same arbitrary address when I return from the get() function.
When doing pointer arithmetic, it's done in elements and not in units of bytes.
Therefore the multiplication with sizeof(A) is invalid and wrong: The expression A_array + (idx * sizeof(A)) should be plain A_array + idx.
Or you could be explicit and return &A_array[idx].
All this means that for any pointer or array a and (valid) index i, the expression *(a + i) is exactly the same as a[i]. And from that follows that &a[i] will be exactly the same as a + i.
To answer your last question -- <_IO_file_overflow+256> is telling you gdb's best guess as to what that address (0x7ffff7b4e5c0) refers to -- in this case, the address is pointing into some shared libaray, and the symbol _IO_file_overflow is the closest symbol defined in that library (and specifically, this address is 256 bytes past that symbol). This looks to be part of libc.
You can get more detail about what addresses correspond to what in your program by examining the file /proc/<pid>/maps -- you just need to know the pid of the process you are debugging and you can look at that file in another window.
As to why you're getting this odd value when it looks like you've just assigned a different value, it may be that gdb is getting confused and you have another a defined somewhere and gdb is printing that. Or you may have incomplete/incorrect debugging info in your program -- make sure that you compile with -O0 -g if you want accurate debug info.

Correct casting to function pointer that points to a function that returns a function

i was reversing a source code and i've found a function it wich looks like:
consider this:
int examplefn(int x) { return x * 4; }
int (*rtx())(int)
{
return examplefn;
}
well, Then i needed make a pointer function to rtx() to do a hook, then
i've done something like this:
int (*fncptr())(int) = (int(*())(int))0xC0FFEE;
/* 0xC0FFEE it's a sample of the memory address of the function...*/
But my compiler did not compile it, then i've tried do:
typedef int(*fnc_t())(int);
// Clearer example pointing to rtx
fnc_t* TRY_2 = (fnc_t*)&rtx;
// then has successfully compiled, ex test...
int main()
{
std::cout << TRY_2()(4) << std::endl; // output: 16 ok.
}
well, i'm going to the point, ¿How i can do the correct casting without use a typedef?
I searched all over the internet and I have not found anything...
Why do you want to avoid using a typedef? It makes code so much easier to understand:
using F = int(*)(int); // pointer to function taking int and returning int
using G = F(*)(); // pointer to function taking nothing and returning
// a pointer to function taking int and returning int
This took me no time to write and everybody else no time to read and understand. I'd call that a win.
(int(*())(int)) is a function type (the same type as the function rtx has). Your code attempts to declare a function, and cast an integer to function. However you actually want to deal with a pointer to such a function.
After: typedef int(*fnc_t())(int);, the equivalent of fnc_t *x; can be found by replacing fnc_t with (*x) in the typedef: int (*(*x)())(int). So your code could be:
int (*(*fncptr)())(int) = (int(*(*)())(int))0xC0FFEE;
Using a series of typedefs (or equivalent usings) is certainly preferable in real code.

In C++, I'm getting a message "error: 'void*' is not a pointer-to-object type"

Here's my code:
#include <iostream>
using namespace std;
int main()
{
void *x;
int arr[10];
x = arr;
*x = 23; //This is where I get the error
}
As you can see, the code is very simple. It just creates a void pointer x which points to the memory address of the array 'arr' and puts the integer 23 into that memory address. But when I compile it, I get the error message "'void*' is not a pointer-to-object type". When I use an 'int' pointer instead of a void pointer and then compile it, I don't get any errors or warnings. I wanna know why I get this error.
Thank you.
As the compiler message says, void* is not a pointer to object type. What this means is that you cannot do anything with void*, besides explicitly converting it back to another pointer type. A void* represents an address, but it doesn’t specify the type of things it points to, and at a consequence you cannot operate on it.
The compiler needs the type of the variable to to dereference the pointer.
only example no malloc:
*int myPtnr = 0x12345;
When you write
*myPtr = NUMBER:
The compiler looks at the type and say .. okay here we have a int ... the Information i need are in the next 4 bytes starting with the adress of the pointer.
Thats the reason why you have to tell the compiler the type. When you use void the compiler dont know how much bytes he has to use for dereference.
you cant derefrence void*, and that is what the coder is doing.
*x = 23; // this cant be done with void*
instead :
x = &arr[index] ; // this is correct

Why strange behavior with casting back pointer to the original class?

Assume that in my code I have to store a void* as data member and typecast it back to the original class pointer when needed. To test its reliability, I wrote a test program (linux ubuntu 4.4.1 g++ -04 -Wall) and I was shocked to see the behavior.
struct A
{
int i;
static int c;
A () : i(c++) { cout<<"A() : i("<<i<<")\n"; }
};
int A::c;
int main ()
{
void *p = new A[3]; // good behavior for A* p = new A[3];
cout<<"p->i = "<<((A*)p)->i<<endl;
((A*&)p)++;
cout<<"p->i = "<<((A*)p)->i<<endl;
((A*&)p)++;
cout<<"p->i = "<<((A*)p)->i<<endl;
}
This is just a test program; in actual for my case, it's mandatory to store any pointer as void* and then cast it back to the actual pointer (with help of template). So let's not worry about that part. The output of the above code is,
p->i = 0
p->i = 0 // ?? why not 1
p->i = 1
However if you change the void* p; to A* p; it gives expected behavior. WHY ?
Another question, I cannot get away with (A*&) otherwise I cannot use operator ++; but it also gives warning as, dereferencing type-punned pointer will break strict-aliasing rules. Is there any decent way to overcome warning ?
Well, as the compiler warns you, you are violating the strict aliasing rule, which formally means that the results are undefined.
You can eliminate the strict aliasing violation by using a function template for the increment:
template<typename T>
void advance_pointer_as(void*& p, int n = 1) {
T* p_a(static_cast<T*>(p));
p_a += n;
p = p_a;
}
With this function template, the following definition of main() yields the expected results on the Ideone compiler (and emits no warnings):
int main()
{
void* p = new A[3];
std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
advance_pointer_as<A>(p);
std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
advance_pointer_as<A>(p);
std::cout << "p->i = " << static_cast<A*>(p)->i << std::endl;
}
You have already received the correct answer and it is indeed the violation of the strict aliasing rule that leads to the unpredictable behavior of the code. I'd just note that the title of your question makes reference to "casting back pointer to the original class". In reality your code does not have anything to do with casting anything "back". Your code performs reinterpretation of raw memory content occupied by a void * pointer as a A * pointer. This is not "casting back". This is reinterpretation. Not even remotely the same thing.
A good way to illustrate the difference would be to use and int and float example. A float value declared and initialized as
float f = 2.0;
cab be cast (explicitly or implicitly converted) to int type
int i = (int) f;
with the expected result
assert(i == 2);
This is indeed a cast (a conversion).
Alternatively, the same float value can be also reinterpreted as an int value
int i = (int &) f;
However, in this case the value of i will be totally meaningless and generally unpredictable. I hope it is easy to see the difference between a conversion and a memory reinterpretation from these examples.
Reinterpretation is exactly what you are doing in your code. The (A *&) p expression is nothing else than a reinterpretation of raw memory occupied by pointer void *p as pointer of type A *. The language does not guarantee that these two pointer types have the same representation and even the same size. So, expecting the predictable behavior from your code is like expecting the above (int &) f expression to evaluate to 2.
The proper way to really "cast back" your void * pointer would be to do (A *) p, not (A *&) p. The result of (A *) p would indeed be the original pointer value, that can be safely manipulated by pointer arithmetic. The only proper way to obtain the original value as an lvalue would be to use an additional variable
A *pa = (A *) p;
...
pa++;
...
And there's no legal way to create an lvalue "in place", as you attempted to by your (A *&) p cast. The behavior of your code is an illustration of that.
As others have commented, your code appears like it should work. Only once (in 17+ years of coding in C++) I ran across something where I was looking straight at the code and the behavior, like in your case, just didn't make sense. I ended up running the code through debugger and opening a disassembly window. I found what could only be explained as a bug in VS2003 compiler because it was missing exactly one instruction. Simply rearranging local variables at the top of the function (30 lines or so from the error) made the compiler put the correct instruction back in. So try debugger with disassembly and follow memory/registers to see what it's actually doing?
As far as advancing the pointer, you should be able to advance it by doing:
p = (char*)p + sizeof( A );
VS2003 through VS2010 never give you complaints about that, not sure about g++