C - calling a function via func_ptr, why doesnt it work? - c

i have the following code:
void print(const char* str){
system_call(4,1,str,strlen(str)); }
void foo2(void){ print("goo \n");}
void buz(void){ ...}
int main(){
char buf[256];
void (*func_ptr)(void)=(void(*)(void))buf;
memcpy(buf,foo2, ((void*)buz)-((void*)foo2));
func_ptr();
return 0;
}
the question is, why will this code fall?
the answer was, something about calling a function not via pointer is to a relative address, but i havent been able to figure out whats wrong here? which line is the problematic one?
thank you for your help

Well to begin with, there is nothing which says that foo2() and buz() must be next to each other in memory. And for another, as you guess, the code must be relative for stunts like that to work. But most of all, it is not allowed by the standard.
As Chris Luts referred to, stack (auto) variables are not executable on many operating systems, to protect from attacks.

The first two lines in your main() function are problematic.
Line 1. (void(*)(void))buf
converting buf to a function pointer is undefined
Line 2. ((void*)buz)-((void*)foo2)
subtraction of pointers is undefined unless the pointers point within the same array.
Also, Section 5.8 Functions of H&S says "Although a pointer to a function is often assumed to be the address of the function's code in memory, on some computers a function pointer actually points to a block of information needed to invoke the function."

First and foremost, C function pointers mechanism is for equal-signature function calling abstraction. This is powerful and error-prone enough without these stunts.
I can't see an advantage/sense in trying to copying code from one place to another. As some have commented, it's not easy to tell the amount of relativeness/rellocatable code within a C function.
You tried copying the code of a function onto a data memory region. Some microcontrollers would just told you "Buzz off!". On machine architectures that have data/program separated memories, given a very understanding compiler (or one that recognizes data/code modifiers/attributes), it would compile to the specific Code-Data Move instructions. It seams it would work... However, even in data/code separated memory archs, data-memory instruction execution is not possible.
On the other hand, in "normal" data/code shared memory PCs, likely it would also not work because data/code segments are declared (by the loader) on the MMU of the processor. Depending on the processor and OS, attempts to run code on data segments, is a segmentation fault.

Related

Two shellcodes in one program result in segfault, how can I pass shellcode as parameter to a function?

I have two questions related to C programming and shellcoding (assembly) following below.
Question 1: Can anyone provide an answer on why putting two shellcodes in one program wouldn't work? I know it's related to the memory region but I need to know the exact reason. Program is compiled using gcc with the -zexecstack and -fno-stack-protector options.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
/* if the below line is uncommmented it will result in segault */
/* unsigned char shellcode_[] = "\x01\x02<SHELLCODE>"; */
int (*ret)() = (int(*)())shellcode;
return 0;
}
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call? (I mean just STORE two shellcodes, not RUN them simultaneously, if that's possible at all).
Question 2: if the shellcode has to be passed as a parameter to a function, what would be the proper way to do it?
Pseudocode:
unsigned char shellcode[] = "\x01\x02...";
void call_shellcode(unsigned char shellcode[200]);
main()
{
call_shellcode(shellcode);
}
void call_shellcode(unsigned char shellcode[200])
{
... print/call shellcode
}
UPDATE: As there seems to be some misunderstanding to the question, this is not the ACTUAL shellcode. I do know what shellcode is and how it is generated, and how it works. I have not provided an actual shellcode within the C stub to leave it in a readable state. The value "\x01\x01" is a pseudo code to point to the idea of the question and NOT any actual contents.
Your shellcode cannot possibly work for a very simple reason: it begins with \x01\x02:
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
I'm not sure why your think your shellcode has to begin with those two bytes: it really doesn't!
Those two bytes decode to add DWORD PTR [rdx],eax (or edx if running in 32-bit mode). Since you do not have any control over the value of RDX/EDX at the time your shellcode is called, it will very likely immediately cause a segmentation fault because RDX/EDX does not contain a valid (and writable) memory address.
Changing literally anything around the shellcode, in the function or outside, could cause the compiler to choose a different register allocation that will result in RDX/EDX having a good value at runtime that doesn't result in a crash, but that'd just be a lucky coincidence. Writing and using shellcode like this is inherently undefined behavior, or at least implementation defined (fixed an operating system and compiler) so extra care must be taken.
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call?
Well, you're not really dividing anything in "different memory regions"... whether you use one array or two or ten, they are all declared on the stack and they will be close together on the stack.
If you want to jump from one to the other, that's going to be a complex task, because in general you do not know the location of a variable on the stack beforehand, so you will have to do some math calculating your current location and then the offset from one shellcode chunk to the other, ultimately performing a relative call/jump.
If shellcode has to be passed as a parameter to a function what would be the proper way to do this?
The proper way is to mmap a region of memory that is RWX, write the shellcode into it (memcpy, read from stdin, etc.) and then pass a pointer to that memory region to the function you want. You have no guarantee that a piece of global data will be put by the compiler in an executable memory region. In fact, no modern day compiler would do that, and furthermore, no modern day kernel would map such a region as executable even if the ELF is compiled with -z execstack.
In recent kernels -z execstack is only respected for the stack itself, so passing a shellcode as function argument through a variable will only work if the variable was defined on the stack.
You can't have two variables with the same name in the same scope (this part has nothing to do with what the variables are or how they are used). Simply give the second shellcode a different name.
Note I am not going to comment at all on what you are trying to do, other than that I would not think of manually created machine code as "shell code" (which I would usually think of as code intended for a command shell like bash).

What is the trick behind strcpy()/uninitialized char pointer this code?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main ()
{
char *imsi;
unsigned int i;
int val;
char *dest;
imsi = "405750111";
strncpy(dest,imsi,5);
printf("%s",dest);
/* i = 10; */
}
In the above code, with the i = 10 assignment is commented as above, the code works fine without error. When assignment is included for compilation, the error (segmentation fault) occurs at strncpy(dest,imsi,5);.
By avoiding optimization to variable i (i.e., volatile int i;), the error is cleared even with the assignment (i = 10) included.
In your code, by saying
strncpy(dest,imsi,5);
you're trying to write into an unitialized pointer dest. It can (and most possibly, it will) point to some memory which is not accessible from your program (invalid memory). It invokes undefined behavior.
There is nothing that can be guaranteed about a program having UB. It can work as expected (depends on what you're expecting, actually) or it may crash or open your bank account and transfer all money to some potential terrorist organization.
N.B - I hope by reading last line you got scared, so the bottom line is
Don't try to write into any uninitialized pointer (memory area). Period.
The behaviour of this code is unpredictable because the pointer dest is used before it is initialised. The difference in observed behaviour is only indirectly related to the root cause bug, which is the uninitialised variable. In C it is the programmers responsibility to allocate storage for the output of the strncpy() function and you haven't done that.
The simplest fix is to define an output buffer like this:
char dest[10];
Assuming you compiled this C source code into machine code for some "normal" architecture and then ran it, the possible effects of read-undefined UB basically boil down to what value floating around in registers or memory ends up getting used.
If the compiler happens to use the same value both times, and that value happened to point to a writeable memory address (and didn't overwrite anything that would break printf), it could certainly happen to work. UB doesn't guarantee a crash. It doesn't guarantee anything. Part of the point of UB is to let the compiler make assumptions and optimize based on them.
Any changes to surrounding code will affect code-gen for that function, and thus will can affect what's in the relevant register when the call happens, or which stack slot is used for dest. Reading from a different stack address will give dest a different value.
Before main, calls to dynamic-linker functions might have dirtied some memory, leaving some pointers floating around in there, maybe including apparently some to writeable memory.
Or main's caller might have a pointer to some writeable memory in a register, e.g. a stack address.
Although that's less likely; if a compiler was going to just not even set a register before making a call, strncpy would probably get main's first arg, an integer argc, unless the compiler used that register as a temporary first. But string literals normally go in read-only memory so that's an unlikely explanation in this case. (Even on an ISA / calling convention like ARM where gcc's favourite register for temporaries is R0, the return-value register but also the first arg-passing register. If optimization is disabled so statements compile separately, most expressions will use R0.)

Assigning (const char *) to function pointer executing a hex code

I found a C code that looks like this:
#include <stdio.h>
char code[] =
"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x72\x6c"
"\x64\x01\x68\x6c\x6f\x57\x6f\x68\x20\x48\x65\x6c\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7";
int main(void)
{
int (*func)();
func = (int(*)()) code;
(int)(*func)();
return 0;
}
For the given HEX CODE this program runs well and printing ("HelloWorld"). I was thinking that the HEX CODE is some machine instructions and by calling a function pointer that's pointing to that CODE we are executing that CODE.
Was my thought right? is there something to improve it?
How this HEX CODE gets generated?
Tanks for advance.
You are correct that by forcing a function pointer like this you are calling into machine instructions written as a hexadecimal string variable.
I doubt that a program like this would work on any CPU since about 2005.
On most RISC CPUs (like ARM) and on all Intel and AMD CPUs that support 64-bit, memory pages have a No Execute bit. Or in reverse an Execute bit.
On memory pages that do not have an Execute bit, the CPU will not run code. Compilers do not put variables into executable memory pages.
In order to run injected shell codes, attackers now have to use "return into libc" or function pointer overwrite attacks which set things up to call mprotect or VirtualProtect to set the execute bit on their shell code. Either that or get it injected into a executable space such as the Java, .NET, or Javascript JIT compiler uses.
Security hardened kernels will deny the ability to call mprotect. Once the program's address space is set by the dynamic library loader, it sets a security flag and no new executable pages can be created.
In order to make it always work you could assign some executable_readwrite space with malloc or the like and put the code in there and then execute it. Then there won't be any access violation faults.
void main(int argc, char** argv)
{
void* PointerToNewMemoryRegion=0;
void (*FunctionPointer) ();
PointerToNewMemoryRegion=VirtualAlloc(RandomPointer,113,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (PointerToNewMemoryRegion == NULL)
{
std::cout<<"Failed to Allocate Memory region Error code: "<<GetLastError();
return;
}
memcpy(PointerToNewMemoryRegion, code,113);
FunctionPointer = (void(*)()) PointerToNewMemoryRegion;
(void)(*FunctionPointer) ();
VirtualFree(PointerToNewMemoryRegion,113,MEM_DECOMMIT)
}
but the code never returns to my code to execute so my last line is pointless. So my code has a memory leak.
To ask this question from a "general C" point of view isn't all that meaningful.
First of all, your code has many major problems:
The literal "\xFF\xFF\xFF" equals 0xFFFFFF00, not 0x00FFFFFF as may or may not have been the intention.
What this hex code means and if it is at all meaningful, is endian-dependent and also depends on the address bus width of the given CPU.
As others have mentioned, casts between function pointers and regular pointers isn't supported or well-defined by C, the C standard lists it as a "common extension".
That being said, code like this has about one single purpose, and that is various forms of boot loaders and self-updating software used in embedded systems.
Suppose for example that you have a boot loader program that is tasked with re-programming something in the very same segment of flash memory where said program itself is executed from. That is impossible because of the way the memory hardware works. So in order to do so, you would have to execute the actual flash programming routine from RAM. Since the array of hex gibberish is stored in RAM, the program can execute from there with the function pointer trick, assuming that the C compiler has a non-standard extension that allows the cast.
As for how to generate the code, you either write it all in assembler and then translate the assembler instructions to op codes manually (very tedious). Or more likely, you write the function in C and then disassemble it and copy/paste the op codes from the disassembly.
The latter is more dangerous though, as the critical part of getting code like this to work is calling convention: you must be absolutely sure that the function stacks/unstacks things properly when it is called and when it is done, restoring the contents of any CPU registers used etc. Which may force you to write part of the function in assembler anyhow. Needless to say, the code will be completely non-portable.

24 bit const pointers on XC8 PIC18 not workings

I came across this problem twice in my project and the last time I used a kind of dirty solution.
Platform: PIC18F87J60, XC8 v1.12
I'm trying to use function pointers to point to functions that possibly reside in the upper halve of my ROM (>= 0x10000). This means that the pointer itself needs to be 17-bits or bigger (up to 20) to be able to address such a function.
This is the relevant code snippet (simplyfied):
void test(void) # 0x1C000
{
printf("function pointer called!\r\n");
}
void main(void) {
void (*testPointer) (void) = &test;
//Now testPointer contains 0x0C000
(*testPointer)(); //Doesn't call test. Instead it jumps to 0x0C000
}
What happens is that test never actually gets called. When I use the debugger (PICKIT 3) I can see that the value in testPointer is 0x0C000. It just seems that the address in the pointer is rounded down to just 16-bits max and this always happens. But when I place test() somewhere below 0x10000 everything works fine because then the pointer just needs to be max 16 bits.
When I read back the program from the device test() really is placed at 0x1C000 so that is not the problem, the code is there.
The last time I solved the situation by casting a literal long to a pointer and that worked but its dirty and now I want to avoid it.
Does anyone recognize the problem? Is this a compiler bug? If so, does Microchip already know about this? Any clean work-arounds? Does the XC8 compiler support 20-bit const pointers at all?
Edit: fixed typo in code above &testPointer(); --> (*testPointer()); (no, this was not causing my problem)
The MPLAB C18 Compiler User's Guide lists a few extra storage qualifiers that appear to be relevant to your use-case:
near/far Program Memory Objects
The far qualifier is used to denote that a variable that is located in program memory can be found anywhere in program memory, or, if a pointer, that it can access up to and beyond 64K of program memory space.
ram/rom Qualifiers
The rom qualifier denotes that the object is located in program memory, whereas the ram qualifier denotes that the object is located in data memory.
Later on, the manual shows an example of creating "a function pointer that can access up to a beyond 64K of program memory space":
far rom void (*fp) (void);
The XC8 manual is less clear about the function of the far qualifier, but still lists it, which strongly suggests that it still is recognized by the newer compilers.

Void * parameter address shift

I am using Codewarrior 8.3 (IDE version 5.9) to program a 56f8367 DSC.
I am using respected third party software, so I imagine that they know what they are doing and don't want to mess with their code too much, but they are playing around with passing void * parameters and it is something I am not totally familiar with.
So I have this function:
static void T_CALLBACK _transmit(
void *pContext,
TX_DATA *pTxDescriptor)
{
CONTEXT *pLinkContext = (CONTEXT *)pContext;
...
}
which is being called through a function pointer. When I stop the processor just before this function call, I can see the address pointed to by pContext is 0x1000, but after it is cast here, the address pointed to by pLinkContext is 0x0800. This, obviously causes problems because we start writing and reading from a different part of memory.
There is something weird going on with the byte addressing/alignment where it is getting "shifted" over 1 bit. I see what is going wrong, I just don't understand why or, more importantly, how to solve the problem.
What should I be looking for?
(Editing to add the call per comment request) - although, I'm not sure how much it will help considering everything is buried in structures and is being called through a function pointer. I can say that "pTprtContext->tmw.pChannel->pLinkContext" is of a different type than CONTEXT, pLinkContext does match up with the beginning of CONTEXT, so I think they are just trying to insert it in there.
static void T_LOCAL _transmitNextFrame(
D_CONTEXT *pTprtContext)
{
...
/* Transmit frame */
pTprtContext->t.pChannel->pLink->pLinkTransmit(
pTprtContext->t.pChannel->pLinkContext, &pTprtContext->linkTxDescriptor);
}
You say "shifted over by 1 byte," but it is actually only one bit, that is, the number is divided by 2.
This is usually the result of using a byte address in one context and a (2-byte) word address in another context. They probably refer to the same address.
Does this help you decipher it?
I use CodeWarrior compiler for an HC12 family's 16-bit microcontroller. With this compiler, I can choose a few memory models which change (among other several things) how many bytes pointers are. More specifically, +small+ memory model uses __near 16-bit pointers, whereas +large+ model makes use of __far 24-bit pointers.
If your code is compiled with a different memory model than your third party software's and the compiler does not warn you, I guess you may get wierd result.

Resources