Separate the AMX
#21

Also, Peter's PAWN Invoke stuff does leak lots of memory.
Reply
#22

Quote:
Originally Posted by Y_Leѕѕ
Getting the addresses is quite slow, as is figuring out the parameters as it requires looking into the EXE file and figuring out how bits work (I did used to be on the team, so do have a slight advantage in that I used to have source code access so know how certain parts are done, but they do change).

Getting the addresses of PAWN natives is easy - I've got code to do that for me. Getting the addresses you actually need is harder as the PAWN natives read in the parameters, convert them to a regular format then pass them to other functions.

Also, the PAWN invoke plugin doesn't actually go through PAWN for most calls, it just needs the AMX to exist to load all the function addresses which can then be looked up dynamically. This stage can be improved somewhat to remove the AMX and speed up the lookups (either create a static list with my code or embed the code into the plugin and rebuild the list every time the server starts), which may be a compromise between the two current methods.
I found out how to get the addresses to the functions, well I found that about 2 years ago when I made my wrapper and didn't look at it anymore after it worked.
My own custom wrapper gets and stores all those addresses when it starts as I thought at that time amx_FindNative would probably use a linear search through the table with natives the AMX holds which is very slow and you don't want to be doing that each time you want to call a native.

Those addresses still point to functions with the prototype:
Код:
static cell AMX_NATIVE_CALL Func(AMX*, cell*);
int (*func)(AMX*, cell*);  //Is how my wrapper stores them
So you will still need to convert everything to cells and allocate space in the AMX for strings, arrays and stuff passed by reference.

As far as I know the only way to completely bypass the AMX is when you have the prototypes and addresses for all the native functions, not the ones with the above prototype but the ones they call internally.
Reply
#23

I don't think we understand each other correctly, I was talking about wanting to directly call the functions in SA-MP.
No cells no AMX just ints, chars and floats :P.

Back on topic.
All this hooking, wrapping and stuff we were talking about would not be necessary if the whole point of this topic was realised.
Reply
#24

I've had a little look at those functions in SA-MP.
My assembly knowledge is less than basic but I could tell that what I was discussing is not possible because all stuff they do is right there in those functions, they do not just call any underlying functions, I feel a bit stupid about thinking that was possible now.
So I really have no idea about how to bypass AMX when calling those natives.

You say you have a way of doing it.
I've had a look at some of your plugins namely YSF and that multithreaded one but I can't really figure out how you do it.
I saw something about pointer to members, I can understand why as I've read SA-MP is programmed in C++ so it will most likely use classes.
What I know about pointer to members is that if you want to call one you also need to provide a pointer to an instance of that object, so how do you know what classes SA-MP has and how do you get pointers to instances of them when it's running?
Perhaps a little example to get me in the right direction?
Reply
#25

Quote:
Originally Posted by SMX
I've had a little look at those functions in SA-MP.
My assembly knowledge is less than basic but I could tell that what I was discussing is not possible because all stuff they do is right there in those functions, they do not just call any underlying functions, I feel a bit stupid about thinking that was possible now.
So I really have no idea about how to bypass AMX when calling those natives.

You say you have a way of doing it.
I've had a look at some of your plugins namely YSF and that multithreaded one but I can't really figure out how you do it.
I saw something about pointer to members, I can understand why as I've read SA-MP is programmed in C++ so it will most likely use classes.
What I know about pointer to members is that if you want to call one you also need to provide a pointer to an instance of that object, so how do you know what classes SA-MP has and how do you get pointers to instances of them when it's running?
Perhaps a little example to get me in the right direction?
I'm trying to help you a bit, but I'm not entirely sure either:
You do have to guess how SA-MP works at parts, for example that they have to use RakNet somewhere to do SendClientMessage, or catch some log messages whenever someone connects to get the code part.
Recently I searched for the algorithm that replaces the '%' sign in client messages so I was able to hook it and replace it by a more-custom one. I already got the instruction where the
PAWN event is called so I knew the other part was not far, searched for the ascii code of '%' which is 0x25 IIRC and finally found it.
Reply
#26

Quote:
Originally Posted by SMX
I've had a little look at those functions in SA-MP.
My assembly knowledge is less than basic but I could tell that what I was discussing is not possible because all stuff they do is right there in those functions, they do not just call any underlying functions, I feel a bit stupid about thinking that was possible now.
So I really have no idea about how to bypass AMX when calling those natives.

You say you have a way of doing it.
I've had a look at some of your plugins namely YSF and that multithreaded one but I can't really figure out how you do it.
I saw something about pointer to members, I can understand why as I've read SA-MP is programmed in C++ so it will most likely use classes.
What I know about pointer to members is that if you want to call one you also need to provide a pointer to an instance of that object, so how do you know what classes SA-MP has and how do you get pointers to instances of them when it's running?
Perhaps a little example to get me in the right direction?
You are wrong. There is underlaying function for EVERY native function. Let's take for example kick, this is how it is structured:

[Kick Start]
-- Seperating params from params[] cell --
-- code for IsPlayerConnected check --
-- call to INTERNAL_Kick --
[Kick End]

That's more or less every native, just some are converting to match prototype of internal functions(such as int to long, etc.)
Reply
#27

Well that proves how poor my assembly knowledge is.

Still it's an awful lot of work to do this and that adds up to why I made this topic in the first place.

MaVe, with hook do you mean replace it's internal pointer to the function it calls at runtime so it calls your custom function instead?
If so how do you even replace that pointer? Doesn't that give trouble because you are writing memory where you're not supposed to?
Forgive me but my knowledge about this kind of stuff is also really poor, love to learn about it though.
Reply
#28

Quote:
Originally Posted by SMX
MaVe, with hook do you mean replace it's internal pointer to the function it calls at runtime so it calls your custom function instead?
If so how do you even replace that pointer? Doesn't that give trouble because you are writing memory where you're not supposed to?
Forgive me but my knowledge about this kind of stuff is also really poor, love to learn about it though.
No, with hooking I meant replacing the address at the call instruction (so it will call my function instead of the internal one)
Reply
#29

Yeah that's what I meant.
But how do you replace that address?
Reply
#30

Quote:
Originally Posted by SMX
Yeah that's what I meant.
But how do you replace that address?
There's a Call(DWORD from, DWORD to) function somewhere in ******' multithreading plugin - example:

pawn Код:
int hkFunctionToHook(int arg1, int arg2)
{
  logprintf("Received call to FunctionToHook! I block it, do nothing.");
  return 1;
}
pawn Код:
Call((DWORD)0x12345678, (DWORD)&hkFunctionToHook); // we redirect the function call to our function
if you actually want not to block the function call, you need to store the original (internal) function address into a function pointer:
pawn Код:
typedef RETTYPE (*FunctionToHook_t)(int, int);
FunctionToHook_t pfnOriginalFunction = (FunctionToHook_t)0x11234567;

int hkFunctionToHook(int arg1, int arg2)
{
  logprintf("Received call to FunctionToHook! I just append this log message.");
  // Call the original function
  return pfnOriginalFunction(arg1, arg2);
}
Reply
#31

Oh I see what he does there, he lifts the protection with VirtualProtect so he can edit the address.
When he is done he restores the protection.
What I don't get however is why he sets the first byte to 0xE8, and what he does with that "disp" variable.
Those type macros are not making it any easier for me, I always avoid using the windows.h header and all stuff in it so I don't really have them memorised, I know what BYTE and DWORD stand for but PDWORD?

Also is there a way of lifting the protection without using a platform specific function?
Reply
#32

Thanks that cleared up a lot, I think I have a very good understanding of how it works now.
It's a lot of work to figure this out for all native functions and get it to work though.

Back to what my topic is on about:
How cool would it be if SA-MP would call all it's callbacks in a plugin and allow us to call all natives in itself without all the work we discussed above.
My idea was to make SA-MP require a plugin that exports those callbacks and we could be given a lib file and a header with all natives to link against.
The AMX could then be provided as a plugin for people still using PAWN so nothing changes for them.
Reply
#33

I suppose the idea in itself is good, C++ and other bigger languages would give SA-MP much more functionality for bigger scripts, for example role play scripts could create data types for houses, businesses, etc, instead of a load of unrelated functions, therefore saving alot of time, and allowing the coders to put in new features.

The downside of course that there will be alot of people from the forums who will be confused by the C++ code and may even just quit because of it

Personally i never took a liking to java, c++, etc, i was just attracted to web app's more.
Reply
#34

Quote:
Originally Posted by iLinx
...
The downside of course that there will be alot of people from the forums who will be confused by the C++ code and may even just quit because of it
...
Quote:
Originally Posted by SMX
...
The AMX could then be provided as a plugin for people still using PAWN so nothing changes for them.
Reply
#35

I understand that, but people using PAWN may feel inferior since they dont know how to use C++, thats all im saying.
Reply
#36

Then they might aswell already feel inferior as it is already possible to create gamemodes in C++, or what is your point?
Reply
#37

Quote:
Originally Posted by SMX
Then they might aswell already feel inferior as it is already possible to create gamemodes in C++, or what is your point?
Is there an updated wrapper available for 0.3?
Reply
#38

Quote:
Originally Posted by Littlejth
Quote:
Originally Posted by SMX
Then they might aswell already feel inferior as it is already possible to create gamemodes in C++, or what is your point?
Is there an updated wrapper available for 0.3?
No, there's no specific one for 0.3 but the 0.2 by peter should "work", although it does leak lots of memory.. Just add the syntaxes for any new 0.3 natives and update the invoke FS
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)