[Include] y_writemem
#1

Introduction

This is a purely proof-of-concept include, but frankly a few people have released scripts in the last week that I had been thinking about, so I knocked this up quickly.

Basically, this embeds x86 assembly directly in to a .AMX file and invokes that code as a native function. It is a plugin embedded in a .amx file, no .dll file required. Currently there is only one function in there as it relies on redirecting a defined, but unused, existing native function ("SetDeathDropAmount"). The existence of natives is checked by the server before the AMX code is run, so the native must already exist. This puts a significant restriction on the number of native functions you can use, unless you redirect the pointer before every call and thus only really use one. Currently, all the code does is take an absolute pointer and write 4 bytes to it.

Note that once you have a working "WriteMem" function with a "VirtualProtect" call, anything else becomes simpler to do as you can safely write anywhere.

This requires the latest SVN version of YSI. It is also only tested on Windows (as it has assembly, this makes a difference), it also sometimes doesn't work, but it should do.

Example:

pawn Code:
#include <YSI\y_writemem>

stock SetModeRestartTime(Float:n)
{
    WriteMem(0x004AC45C, _:n);
}

main()
{
    // Write 4 bytes to the REAL base address of the AMX.
    WriteMem(AMX_REAL_ADDRESS, 42);
    // Read it using the relative address.
    printf("%d", AMX_Read(AMX_BASE_ADDRESS));
    // YSF function.
    SetModeRestartTime(20.0);
}
The code that generated the assembly, as well as the mnemonics, are in the comments. Download here:

http://pastebin.com/MqFxzPhe

Edit: I should say that the concept of hijacking a present, but unused, instruction to call assembly embedded in the memory segment is based on a post by a person called "CyQ" for Vice City SCM modding MANY years ago (around 10). This is an application of that idea to PAWN utilising recent advancements in #emit expoits.

I should also say that I do not believe that this is a security issue as you can already read and write memory far more conveniently from plugins, and VPSs should be sandboxed from each other anyway.

Edit: New version using a better version of "VirtualProtect" and "SYSREQ.D" not "SYSREQ.C" to avoid having to hijack an existing native. Both updates thanks to Zeex_ (it's now more his code than mine).

Download

This library is a part of YSI, which can be found here. Keep your eye on that topic and your server log for updates.

YSI Download Topic
Reply
#2

I guess this is due to the other release from zeex!
Anyways good one (:
Reply
#3

Quote:
Originally Posted by FireCat
View Post
I guess this is due to the other release from zeex!
Anyways good one (:
It's based on it, but it goes slightly further (as all good releases do - I hope to see what advancement from this people make) in that it can write to any memory without crashing, and is also a proof-of-concept for embedded ASM, not just a "WriteMem" function.
Reply
#4

I believe it's possible to invoke the assembly code easier with sysreq.d (same as sysreq.c but takes an address instead of an index).

I've made a few changes to your code to make use of sysreq.d

http://pastebin.com/Lb4bp7d6

but it crashes at the VirtualProtect call:

Code:
0203B2D8  call        dword ptr ds:[1000703Ch] // the addres looks weird
Also I found that the original code crashes for me at the same place...

Any ideas?
Reply
#5

I know why! I had my sscanf plugin loaded and didn't realise that made a difference - I added the function to sscanf (as it was the first project I found), compiled it and extracted the byte code - but the modified sscanf plugin was also loaded...

Good idea to use sysreq.d though!

Edit: I don't get a crash on your version, the JUMP.pri is invalid (I thought it was but tested it).
Reply
#6

I think I know what it does (I'm not familliar with such things), so quite good work out there!
Reply
#7

It turned out JUMP.pri worked for me because of crashdetect being loaded. I think it should be changed ot SCTRL 6.

Edit:

Got it working with this (found VirtualProtect import at 004A118C (R2 500 players) - is this correct?)

Code:
		asm(CC,CC,CC,CC), asm(CC,CC,CC,CC), asm(CC,CC,CC,CC), asm(CC,CC,CC,CC),
		asm(55,8B,EC,56), asm(8B,75,0C,83), asm(3E,08,75,1A), asm(8B,4E,04,8D),
		asm(45,0C,50,6A), asm(40,6A,04,51), asm(FF,15,8C,11), asm(4A,00,8B,56),
		asm(04,8B,46,08), asm(89,02,33,C0), asm(5E,5D,C3,CC)
but now getting a "Divide by zero" error (wtf?)

Edit2:

OK I think I know what's wrong - there's no code following the sysreq.d so it tried to execute the data! (silly me)
Reply
#8

Quote:
Originally Posted by Zeex_
View Post
It turned out JUMP.pri worked for me because of crashdetect being loaded. I think it should be changed ot SCTRL 6.
Heh, maybe we'll eventually get this "pluginless" code pluginless .

Edit: I'm not sure where that divide by zero error is coming from - the asm you posted works fine in the original code I posted so it must be coming from the sysreq.d code. I did try to port that to using SCTRL (with a return jump from the array) but I keep getting an invalid instruction and I really can't see from where.
Reply
#9

The problem was that there's no code after the SYSREQ.D so it was executing random garbage following the YSI_g_sDoWriteMem array.

So I've already fixed this: http://pastebin.com/5ip5PbBK
Reply
#10

Quote:
Originally Posted by Zeex_
View Post
The problem was that there's no code after the SYSREQ.D so it was executing random garbage following the YSI_g_sDoWriteMem array.

So I've already fixed this: http://pastebin.com/5ip5PbBK
I'd already spotted that. I'll update the first post with the new version (I've modified yours slightly to avoid doing some of the code repeatedly.

This would be what I was referring to here:

Quote:
Originally Posted by Y_Less
View Post
I hope to see what advancement from this people make
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)