Function Ptr
BlitzMax Forums/BlitzMax Programming/Function Ptr
| ||
In the blitzmax docs it says that you can convert a function into a byte pointer. My problem is converting from a byte pointer back to a function. I always seem to get an error message saying something like 'expression cannot be invoked'. Is it possible? If its not then im not sure why it is even included in the language. If it is possible then that opens up the possibility of writing self modifying code or a uber fast scripting language. Anyone done anything like this? It sounds like a fun area to play around in. It may be possible to pass the byte pointer to a C function and have that invoke at that address. |
| ||
If it is possible then that opens up the possibility of writing self modifying code or a uber fast scripting language Wrong. Self modifyable code is actually not possible. Execution Bit protection on actual CPUs will not allow this kind of source modification at runtime. And converting function -> byte ptr is for external usage. Within BM you have to use Typesafe Functionreferences (BM is typesafe, trying to get around that results in instability and bad code, so definitely no target to follow): SuperStrict ' The following declares the interface of the function ' you want to assign to the function reference global someFunc(val:int, text:String) someFunc = dateOut someFunc(12, "Dec 2006") end function dateOut(date:int, text:string print string(date) + " " + text end function |
| ||
You can modify code at runtime by allocating memory with VirtualAlloc and making it executable with VirtualProtect. |
| ||
Doesn't that just create "new executable code"? currently running code is protected to prevent virus etc from causing problems. |
| ||
I seem to remember there being a way to convert between byte pointer and function pointer both ways. There is another thread somewhere from some time ago where I wrote about it. Like maybe you have to convert it to an Int Point first.. MyIntPtr=IntPtr(Byte Ptr(MyOtherFunction)) MyOtherFunction=Byte Ptr(MyIntPtr) or something. There was one combination that worked both ways. |
| ||
Is it possible to create a function at runtime having an array of processor compatible binary opcodes? I know how to generate them, and it would be nice to generate them at runtime. Maybe i would need to allocate some memory, get a pointer and secure it. If you can, post code, please. |
| ||
If you would like to have some code to try with, have a look at this: ''mov ah, 0x02 ''mov dl, "J" = 74 ''Int 21h ''ret WriteByte(o, 180) WriteByte(o, 2) WriteByte(o, 178) WriteByte(o, 74) WriteByte(o, 205) WriteByte(o, 33) WriteByte(o, 195) The first part is the asm code correspondent, the second one contains the byte numbers(written as integer) to obtain that code. |
| ||
Yeah, that was what thinking about, If you can create an array of oppcodes and invoke them as a function then you could concevably create a very fast scripting language (in practice it would be way hard). It has many other abilitys as well, you could combine it with a compiler to directly inject code into your excecutable. I know it can be done in C++ because one of the examples in the 'Hacker Dissasembling Uncovered' book was on it. I was intreged as to wether it could be done in BlitzMax. It does however require that the code it excecuted from the stack (I think :S ) and im sure there are ways that the opperating system can stop this. I know that some Viruses use this method to modify and encript there payload so that some scanners cant identify them. |
| ||
I coded a compiler, which generated pure intel x86 compatible code. That is quite interesting, but it would be a lot more useful to code self modifying programs. Generate op codes is quite easy, and it can be done within 1000 lines, but execute the generated code fastly instead of generating an exacutable file would be better. |
| ||
Doesn't that just create "new executable code"? Its still in the current process though, I meant you can fill the allocated memory with opcodes and execute it; not completely the same as self-modifying code. |
| ||
Ok, but do you have some code to test with? |
| ||
When I said self modifying code I was just trying to describe that the code being excecuted can be changed dynamicly :) It would be great to compile x86 instructions directly into and from within your code. Thats realy powerfull! |
| ||
I can allocate some memory and copy the values into it, but when trying to execute i get an unhandled memory exception error. Any ideas? |
| ||
Can you post some code? I cant think how you are calling the data as a function. |
| ||
Global b:Byte Ptr=MemAlloc(7) b[0]=Byte(180) b[1]=Byte(2) b[2]=Byte(178) b[3]=Byte(74) b[4]=Byte(205) b[5]=Byte(33) b[6]=Byte(195) Global func()=Byte Ptr(b) func() I also coded a variant using banks, but it's almost the same. |
| ||
It doesn't work even without the Byte Ptr() thing. |
| ||
perhaps you have to take out the ret function because you havent created any space for the function or pushed the return address onto the stack (maby that is handled by blitz when you call func() ). I would try taking out the RET instruction but im realy rubish with assembly at the moment. It would be good to know if its running the instructions and then bombing out or finishing them. I think you would have to compile it in non-debug mode because some of the debug code could put it off. |
| ||
Without the ret function should work, because we're creating a function, which otherwise wouldn't return. The address is put on the stack when calling it, so it's not a problem. However it gives the same error as before. |
| ||
What about the interupt call Int 21h. In protected mode you cant call interupts, unless this is one specified by windows? |
| ||
It is a dos one, but it should work. Interrupt work, but not the bios' ones, the os has to redefine them. If you make a binary file with the bytes i've posted and execute it(you could do this by a dos window, because otherwise you could not see the result) you'll see a J being printed. |
| ||
Wow, works when only the return instruction is called. Take indice 6 and move it into indice 0, it works! |
| ||
I know the error. It is like you said. I've tryied with some inline asm c code and gave errors on int 21h. I'll post some new code. |
| ||
How can i get the memory cell number(real address in memory) of a variable? |
| ||
Global a:Int=1150 Global b:Int=Int(Varptr(a)) Print b |
| ||
The function has to get input vars and output something(which is not so easy in asm) or maybe it could manage some global variable, given the address. |
| ||
BlitzMax doesn't allow you to explicitly cast from Byte Ptr to function - you need to do an implicit casting:Global FuncPtr:Byte Ptr '= ... Global Func:Int ( ) = Int ( ) FuncPtrdoesn't work. Instead you can write: Global FuncPtr:Byte Ptr '= ... Global Func:Int ( ) = FuncPtr |
| ||
I think you can go from byte pointer to int pointer to function pointer and back, or used to be able to. |
| ||
Global b:Byte Ptr=MemAlloc(7) b[0]=Byte(195) Global func( a:Int )=Byte Ptr(b) func( 5 ) Can you now just pop the paramater off the stack? I cant do it because I dont know assembler so much. When I placed a debugstop before the function call and steped into the function blitzmax just passed over it. It seems like this technique could be quite well behaved. |
| ||
I guess I mite have to start dissasembling blitz max compiled programs to examine how functions are implemented so this technique can be used safely. :S thats hardcore! |
| ||
You can pop input values and push return ones, but it is quite difficult. Have a look on google. You have to calculate the address of each variable on the stack. |
| ||
Cool, when I get some free time I will, Thanks. @ splinux Is there a refrence that you could share about the conversion of opcodes -> byte values? |
| ||
Intel reference manual. It should be the third book. It contains all the specs for opcode generation having the asm code. It has a nice table to look at. |
| ||
No, it's the second one. http://developer.intel.com/design/pentium/manuals/24319101.pdf However creating functions this way has many limitation. BRL should implement inline asm. That would be cool. |
| ||
I second that, I also want custom operator defenitions. Calling functions like this could let people create custom stripting languages and have them run realy realy fast. Getting it nailed will take some time however. Thanks for the link. Anyone have any idea about how to link with some of the functions definied in the code, short of passing them to the custom function? |
| ||
http://www.programmersheaven.com/download/15526/download.aspx For a good asm tutorial. But what do you mean for 'custom operator definitions'? |
| ||
Like how C++ hasclass myClass { float Operator * ( Vec3 a, Vec3 b ) { } } Or something like that (I forget) That would make me marry BlitzMax The link doesnt work, perhaps ProgHev doesnt support Hotlinking. I'll search for it though. |
| ||
Yes, i misunderstand the sentence. |
| ||
currently running code is protected to prevent virus etc from causing problems. however you can still access it:Strict Framework brl.blitz 'here we create a new bit of code in a temporary memory area: Local PrepareArea:Byte Ptr = MemAlloc ( 7 ) PrepareArea [ 0 ] = 184 'mov eax,_RedirectFunc ( Byte Ptr Ptr ( PrepareArea + 1 ) ) [ 0 ] = RedirectFunc PrepareArea [ 5 ] = 255 'jmp eax (part 1) PrepareArea [ 6 ] = 224 'jmp eax (part 2) 'now we want to copy our new created function to the executable memory 'it should replace the String.FromWString function: 'MemCopy String.FromWString , PrepareArea , 7 'doesn't work, use this instead: WriteProcessMemory GetCurrentProcess ( ) , String.FromWString , PrepareArea , 7 , Null 'works 'now let's just try to call String.FromWString and see what happens instead: WriteStdout String.FromWString ( "Hello".ToWString ( ) ) + "~n" Function RedirectFunc$ ( Param:Short Ptr ) WriteStdout "Someone tried to call String.FromWString!~n" WriteStdout "String.FromWString was called with the following pointer as parameter:~n" WriteStdout Int Param + "~n" Return "This is the return value...." EndFunction Extern "Win32" Function GetCurrentProcess ( ) Function WriteProcessMemory ( DstProc , Dst:Byte Ptr , Src:Byte Ptr , Size , Written Ptr ) EndExternThis protection isn't valid for the OS, since api functions belong to the os you can use them to access this memory. |
| ||
Nice code. |
| ||
Will test that when I restart my system the next time. I've disabled execution bit support normally because there are some older apps that sadly dislike this security feature (Yes, I've XP SP2 installed) |