View difference between Paste ID: Lb4bp7d6 and AL1HPFMi
SHOW: | | - or go back to the newest paste.
1
/*----------------------------------------------------------------------------*\
2
					===========================
3
					Y Sever Includes - Writemem
4
					===========================
5
Description:
6
	Write to any absolute address in the SA:MP server in pure PAWN with embedded
7
	assembly (i.e. a new native).  Calls "VirtualProtect" to make writes safe.
8
Legal:
9
	Version: MPL 1.1
10
11
	The contents of this file are subject to the Mozilla Public License Version
12
	1.1 (the "License"); you may not use this file except in compliance with
13
	the License. You may obtain a copy of the License at
14
	http://www.mozilla.org/MPL/
15
16
	Software distributed under the License is distributed on an "AS IS" basis,
17
	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18
	for the specific language governing rights and limitations under the
19
	License.
20
21
	The Original Code is the YSI ini include.
22
23
	The Initial Developer of the Original Code is Alex "Y_Less" Cole.
24
	Portions created by the Initial Developer are Copyright (C) 2011
25
	the Initial Developer. All Rights Reserved.
26
27
	Contributors:
28
		ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
29
30
	Thanks:
31
		JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
32
		ZeeX - Very productive conversations.
33
		koolk - IsPlayerinAreaEx code.
34
		TheAlpha - Danish translation.
35
		breadfish - German translation.
36
		Fireburn - Dutch translation.
37
		yom - French translation.
38
		50p - Polish translation.
39
		Zamaroht - Spanish translation.
40
		Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
41
			for me to strive to better.
42
		Pixels^ - Running XScripters where the idea was born.
43
		Matite - Pestering me to release it and using it.
44
45
	Very special thanks to:
46
		Thiadmer - PAWN, whose limits continue to amaze me!
47
		Kye/Kalcor - SA:MP.
48
		SA:MP Team past, present and future - SA:MP.
49
50
Version:
51
	1.0
52
Changelog:
53
	01/02/12:
54
		Added "VirtualProtect" calls to the code.
55
		First version.
56
Functions:
57
	Public:
58
		-
59
	Core:
60
		-
61
	Stock:
62
		-
63
	Static:
64
		-
65
	Inline:
66
		-
67
	API:
68
		WriteMem - Write data to an address.
69
Callbacks:
70
	-
71
Definitions:
72
	asm - Convert a stream of assembly to a cell.
73
Enums:
74
	-
75
Macros:
76
	-
77
Tags:
78
	-
79
Variables:
80
	Global:
81
		-
82
	Static:
83
		YSI_g_sWriteMem - The assembly.
84
Commands:
85
	-
86
Compile options:
87
	-
88
Operators:
89
	-
90
\*----------------------------------------------------------------------------*/
91
92
#include <a_samp>
93
#include <YSI\y_amx>
94
#include <YSI\y_hooks>
95
#include <YSI\y_utils>
96
97
forward WriteMem(addr, value);
98
99
#define asm(%0,%1,%2,%3) ((0x%0<<0)|(0x%1<<8)|(0x%2<<16)|(0x%3<<24))
100
101
/*
102
cell AMX_NATIVE_CALL
103
	n_WriteMem(AMX * amx, cell * params)
104
{
105
	if (params[0] == 8)
106
	{
107
		DWORD
108
			oldp;
109
		VirtualProtect((cell *)params[1], 4, PAGE_EXECUTE_READWRITE, &oldp);
110
		*((cell *)params[1]) = params[2];
111
	}
112
	return 0;
113
}
114
115
BECOMES:
116
117
	align   16
118
	push    ebp
119
	mov     ebp, esp
120
	push    esi
121
	mov     esi, [ebp+12]
122
	cmp     dword ptr [esi], 8
123
	jnz     short loc_ret
124
	mov     ecx, [esi+4]
125
	lea     eax, [ebp+12]
126
	push    eax
127
	push    40h
128
	push    4
129
	push    ecx
130
	call    ds:__imp__VirtualProtect@16
131
	mov     edx, [esi+4]
132
	mov     eax, [esi+8]
133
	mov     [edx], eax
134
loc_ret:
135
	xor     eax, eax
136
	pop     esi
137
	pop     ebp
138
	retn
139
140
BECOMES:
141
*/
142
143
static
144
	YSI_g_sWriteMem[] =
145
	{
146
		asm(CC,CC,CC,CC), asm(CC,CC,CC,CC), asm(CC,CC,CC,CC), asm(CC,CC,CC,CC),
147
		asm(55,8B,EC,56), asm(8B,75,0C,83), asm(3E,08,75,1A), asm(8B,4E,04,8D),
148
		asm(45,0C,50,6A), asm(40,6A,04,51), asm(FF,15,3C,70), asm(00,10,8B,56),
149
		asm(04,8B,46,08), asm(89,02,33,C0), asm(5E,5D,C3,CC)
150
	};
151
152
static
153
	YSI_g_sDoWriteMem[] =
154
	{
155
		135, // sysreq.d opcode
156-
		-1,   // will be set later
156+
		0,   // will be set later
157
	};
158
159
stock
160
	WriteMem(addr, value)
161
{
162-
	printf("WriteMem(%x, %x)", addr, value);
162+
163
	#emit PUSH.S value
164-
	printf("native = %x", YSI_g_sDoWriteMem[1]);
164+
165
	#emit PUSH.C 8
166
167
	// Get the jump address.
168
	#emit CONST.PRI YSI_g_sDoWriteMem
169
	#emit LOAD.ALT AMX_HEADER_DAT
170
	#emit ADD
171
	#emit LOAD.ALT AMX_HEADER_COD
172
	#emit SUB
173
174
	// Jump to the code stored in YSI_g_sDoWriteMem.
175
	// This will result in execution of the native code stored in YSI_g_sWriteMem.
176
	#emit JUMP.PRI
177
178
	// Pop native arguments.
179
	#emit STACK 12
180
}
181
182
static
183
	WM_Shift(from, to, data[], len = sizeof (data))
184
{
185
	if (FALSE)
186
	{
187
		WriteMem(0, 0);
188
	}
189
	while (from < len)
190
	{
191
		data[to++] = data[from++];
192
	}
193
}
194
195
hook OnScriptInit()
196
{
197
	new
198
		addr = AMX_GetGlobalAddress(YSI_g_sWriteMem);
199
	// Align the code to a 16-byte boundary.
200
	switch (addr & 15)
201
	{
202
		case 0:
203
		{
204
			WM_Shift(4, 0, YSI_g_sWriteMem);
205
		}
206
		case 4:
207
		{
208
			WM_Shift(4, 3, YSI_g_sWriteMem);
209
			addr += 12;
210
		}
211
		case 8:
212
		{
213
			WM_Shift(4, 2, YSI_g_sWriteMem);
214
			addr += 8;
215
		}
216
		case 12:
217
		{
218
			WM_Shift(4, 1, YSI_g_sWriteMem);
219
			addr += 4;
220
		}
221
		default:
222
		{
223
			P:E("Cannot relocate YSI_g_sWriteMem");
224
		}
225
	}
226
	YSI_g_sDoWriteMem[1] = addr;
227
	return 1;
228
}