Function Ptr

BlitzMax Forums/BlitzMax Programming/Function Ptr

Pantheon(Posted 2006) [#1]
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.


Dreamora(Posted 2006) [#2]
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



Azathoth(Posted 2006) [#3]
You can modify code at runtime by allocating memory with VirtualAlloc and making it executable with VirtualProtect.


Dreamora(Posted 2006) [#4]
Doesn't that just create "new executable code"?
currently running code is protected to prevent virus etc from causing problems.


ImaginaryHuman(Posted 2006) [#5]
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.


splinux(Posted 2006) [#6]
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.


splinux(Posted 2006) [#7]
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.


Pantheon(Posted 2006) [#8]
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.


splinux(Posted 2006) [#9]
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.


Azathoth(Posted 2006) [#10]
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.


splinux(Posted 2006) [#11]
Ok, but do you have some code to test with?


Pantheon(Posted 2006) [#12]
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!


splinux(Posted 2006) [#13]
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?


Pantheon(Posted 2006) [#14]
Can you post some code? I cant think how you are calling the data as a function.


splinux(Posted 2006) [#15]

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.


splinux(Posted 2006) [#16]
It doesn't work even without the Byte Ptr() thing.


Pantheon(Posted 2006) [#17]
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.


splinux(Posted 2006) [#18]
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.


Pantheon(Posted 2006) [#19]
What about the interupt call Int 21h. In protected mode you cant call interupts, unless this is one specified by windows?


splinux(Posted 2006) [#20]
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.


Pantheon(Posted 2006) [#21]
Wow, works when only the return instruction is called.

Take indice 6 and move it into indice 0, it works!


splinux(Posted 2006) [#22]
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.


splinux(Posted 2006) [#23]
How can i get the memory cell number(real address in memory) of a variable?


splinux(Posted 2006) [#24]

Global a:Int=1150

Global b:Int=Int(Varptr(a))
Print b




splinux(Posted 2006) [#25]
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.


Fabian.(Posted 2006) [#26]
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 ( ) FuncPtr
doesn't work.
Instead you can write:
Global FuncPtr:Byte Ptr '= ...
Global Func:Int ( ) = FuncPtr



ImaginaryHuman(Posted 2006) [#27]
I think you can go from byte pointer to int pointer to function pointer and back, or used to be able to.


Pantheon(Posted 2006) [#28]
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.


Pantheon(Posted 2006) [#29]
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!


splinux(Posted 2006) [#30]
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.


Pantheon(Posted 2006) [#31]
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?


splinux(Posted 2006) [#32]
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.


splinux(Posted 2006) [#33]
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.


Pantheon(Posted 2006) [#34]
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?


splinux(Posted 2006) [#35]
http://www.programmersheaven.com/download/15526/download.aspx
For a good asm tutorial.

But what do you mean for 'custom operator definitions'?


Pantheon(Posted 2006) [#36]
Like how C++ has

class 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.


splinux(Posted 2006) [#37]
Yes, i misunderstand the sentence.


Fabian.(Posted 2006) [#38]
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 )
EndExtern
This protection isn't valid for the OS, since api functions belong to the os you can use them to access this memory.


splinux(Posted 2006) [#39]
Nice code.


Dreamora(Posted 2006) [#40]
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)