AMXX UnCompress - CodeHack
Esto es una mini guiá orientada a personas con alto conocimiento en pawn, solo voy a explicar lo justo y necesario.
¿ A que me refiero con CodeHack ?
A modificar instrucciones en el código de un .amxx para realizar otra acción.
¿ Como se modifican esas instrucciones ?
Utilizando AMXX UnCompress para modificar el codigo y el AMXXdump para ver las instrucciones y direcciones de memoria.
Plugin a utilizar:
Código PHP:
#include <amxmodx>
#define PLUGIN "Prueba amxx uncompress"
#define VERSION "1.0"
#define AUTHOR "Destro"
new const string[] = "Mensaje 1"
new const string2[] = "Hacked :P"
new const string3[] = "Final"
const const_value = 2
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
server_print("%s", string)
new value = 1
if(value == const_value)
{
server_print(string2)
return
}
funtion_print2()
register_srvcmd("prueba", "svcmd_prueba")
}
public svcmd_prueba()
{
funtion_print()
}
funtion_print()
{
static value
value++
server_print("string:[%s] static:[%d]", string, value)
}
funtion_print2()
{
server_print(string3)
}
AMXXdump:
Código:
No module data detected.
native: register_srvcmd
native: server_print
native: register_plugin
0x00000154 stock funtion_print()
0x000001A8 stock funtion_print2()
0x00000008 public plugin_init()
0x00000130 public svcmd_prueba()
codestart codeend address type name
0x00000074 0x00000128 0xFFFFFFFC local val value
0x00000160 0x000001A0 0x00000150 static val value
0x00000154 0x000001A8 0x00000154 stock funtion_print
0x000001A8 0x000001DC 0x000001A8 stock funtion_print2
0x00000008 0x00000130 0x00000008 public plugin_init
0x00000008 0x000001DC 0x00000000 global val string[10]
0x00000008 0x000001DC 0x00000028 global val string2[10]
0x00000008 0x000001DC 0x00000050 global val string3[6]
0x00000130 0x00000154 0x00000130 public svcmd_prueba
0x00000000 new string[10]
0x00000028 new string2[10]
0x00000050 new string3[6]
0x8 PROC ; public plugin_init()
0xC BREAK ; test_amxx_uncompress.sma:11
0x10 BREAK ; test_amxx_uncompress.sma:13
0x14 PUSH.C 0xD4 ; "Destro"
0x1C PUSH.C 0xC4 ; "1.0"
0x24 PUSH.C 0x68 ; "Prueba amxx uncompress"
0x2C PUSH.C 0xC
0x34 SYSREQ.C 0x0 ; register_plugin("Prueba amxx uncompress","1.0","Destro")
0x3C STACK 0x10 ; free 4 cells
0x44 BREAK ; test_amxx_uncompress.sma:15
0x48 PUSH.C 0x0 ; string[10] "Mensaje 1"
0x50 PUSH.C 0xF0 ; "%s"
0x58 PUSH.C 0x8
0x60 SYSREQ.C 0x1 ; server_print("%s",string[10]={"Mensaje 1"})
0x68 STACK 0xC ; free 3 cells
0x70 BREAK ; test_amxx_uncompress.sma:17
; new value
0x74 PUSH.C 0x1 ; 0x65000000
0x7C BREAK ; test_amxx_uncompress.sma:19
0x80 LOAD.S.pri 0xFFFFFFFC ; value
0x88 EQ.C.pri 0x2
0x90 JZER 0xD0 ; jump_0
0x98 BREAK ; test_amxx_uncompress.sma:21
0x9C PUSH.C 0x28 ; string2[10] "Hacked :P"
0xA4 PUSH.C 0x4
0xAC SYSREQ.C 0x1 ; server_print(string2[10]={"Hacked :P"})
0xB4 STACK 0x8 ; free 2 cells
0xBC BREAK ; test_amxx_uncompress.sma:22
0xC0 ZERO.pri
0xC4 STACK 0x4 ; free 1 cells
0xCC RETN
0xD0 BREAK ; test_amxx_uncompress.sma:25
; target:jump_0
0xD4 PUSH.C 0x0
0xDC CALL 0x1A8 ; stock funtion_print2()
0xE4 BREAK ; test_amxx_uncompress.sma:27
0xE8 PUSH.C 0x14C ; 0x0
0xF0 PUSH.C 0xFFFFFFFF ; signed=-1 float=-1.#QNAN0
0xF8 PUSH.C 0x118 ; "svcmd_prueba"
0x100 PUSH.C 0xFC ; "prueba"
0x108 PUSH.C 0x10
0x110 SYSREQ.C 0x2 ; register_srvcmd("prueba","svcmd_prueba",-1,"")
0x118 STACK 0x14 ; free 5 cells
0x120 STACK 0x4 ; free 1 cells
0x128 ZERO.pri
0x12C RETN
0x130 PROC ; public svcmd_prueba()
0x134 BREAK ; test_amxx_uncompress.sma:30
0x138 BREAK ; test_amxx_uncompress.sma:32
0x13C PUSH.C 0x0
0x144 CALL 0x154 ; stock funtion_print()
0x14C ZERO.pri
0x150 RETN
0x154 PROC ; stock funtion_print()
0x158 BREAK ; test_amxx_uncompress.sma:35
0x15C BREAK ; test_amxx_uncompress.sma:37
; static value
0x160 BREAK ; test_amxx_uncompress.sma:39
0x164 INC 0x150 ; value
0x16C BREAK ; test_amxx_uncompress.sma:41
0x170 PUSH.C 0x150 ; value 0x0
0x178 PUSH.C 0x0 ; string[10] "Mensaje 1"
0x180 PUSH.C 0x154 ; "string:[%s] static:[%d]"
0x188 PUSH.C 0xC
0x190 SYSREQ.C 0x1 ; server_print("string:[%s] static:[%d]",string[10]={"Mensaje 1"},value={""})
0x198 STACK 0x10 ; free 4 cells
0x1A0 ZERO.pri
0x1A4 RETN
0x1A8 PROC ; stock funtion_print2()
0x1AC BREAK ; test_amxx_uncompress.sma:44
0x1B0 BREAK ; test_amxx_uncompress.sma:46
0x1B4 PUSH.C 0x50 ; string3[6] "Final"
0x1BC PUSH.C 0x4
0x1C4 SYSREQ.C 0x1 ; server_print(string3[6]={"Final"})
0x1CC STACK 0x8 ; free 2 cells
0x1D4 ZERO.pri
0x1D8 RETN
file: test_amxx_uncompress.sma
Tabla valores HEX de instrucciones: (Archivo opcode.txt)
Código:
*** HEX VALUES:
- OP_NONE = 0x00
- OP_LOAD_PRI = 0x01
- OP_LOAD_ALT = 0x02
- OP_LOAD_S_PRI = 0x03
- OP_LOAD_S_ALT = 0x04
- OP_LREF_PRI = 0x05
- OP_LREF_ALT = 0x06
- OP_LREF_S_PRI = 0x07
- OP_LREF_S_ALT = 0x08
- OP_LOAD_I = 0x09
- OP_LODB_I = 0x0a
- OP_CONST_PRI = 0x0b
- OP_CONST_ALT = 0x0c
- OP_ADDR_PRI = 0x0d
- OP_ADDR_ALT = 0x0e
- OP_STOR_PRI = 0x0f
- OP_STOR_ALT = 0x10
- OP_STOR_S_PRI = 0x11
- OP_STOR_S_ALT = 0x12
- OP_SREF_PRI = 0x13
- OP_SREF_ALT = 0x14
- OP_SREF_S_PRI = 0x15
- OP_SREF_S_ALT = 0x16
- OP_STOR_I = 0x17
- OP_STRB_I = 0x18
- OP_LIDX = 0x19
- OP_LIDX_B = 0x1a
- OP_IDXADDR = 0x1b
- OP_IDXADDR_B = 0x1c
- OP_ALIGN_PRI = 0x1d
- OP_ALIGN_ALT = 0x1e
- OP_LCTRL = 0x1f
- OP_SCTRL = 0x20
- OP_MOVE_PRI = 0x21
- OP_MOVE_ALT = 0x22
- OP_XCHG = 0x23
- OP_PUSH_PRI = 0x24
- OP_PUSH_ALT = 0x25
- OP_PUSH_R = 0x26
- OP_PUSH_C = 0x27
- OP_PUSH = 0x28
- OP_PUSH_S = 0x29
- OP_POP_PRI = 0x2a
- OP_POP_ALT = 0x2b
- OP_STACK = 0x2c
- OP_HEAP = 0x2d
- OP_PROC = 0x2e
- OP_RET = 0x2f
- OP_RETN = 0x30
- OP_CALL = 0x31
- OP_CALL_PRI = 0x32
- OP_JUMP = 0x33
- OP_JREL = 0x34
- OP_JZER = 0x35
- OP_JNZ = 0x36
- OP_JEQ = 0x37
- OP_JNEQ = 0x38
- OP_JLESS = 0x39
- OP_JLEQ = 0x3a
- OP_JGRTR = 0x3b
- OP_JGEQ = 0x3c
- OP_JSLESS = 0x3d
- OP_JSLEQ = 0x3e
- OP_JSGRTR = 0x3f
- OP_JSGEQ = 0x40
- OP_SHL = 0x41
- OP_SHR = 0x42
- OP_SSHR = 0x43
- OP_SHL_C_PRI = 0x44
- OP_SHL_C_ALT = 0x45
- OP_SHR_C_PRI = 0x46
- OP_SHR_C_ALT = 0x47
- OP_SMUL = 0x48
- OP_SDIV = 0x49
- OP_SDIV_ALT = 0x4a
- OP_UMUL = 0x4b
- OP_UDIV = 0x4c
- OP_UDIV_ALT = 0x4d
- OP_ADD = 0x4e
- OP_SUB = 0x4f
- OP_SUB_ALT = 0x50
- OP_AND = 0x51
- OP_OR = 0x52
- OP_XOR = 0x53
- OP_NOT = 0x54
- OP_NEG = 0x55
- OP_INVERT = 0x56
- OP_ADD_C = 0x57
- OP_SMUL_C = 0x58
- OP_ZERO_PRI = 0x59
- OP_ZERO_ALT = 0x5a
- OP_ZERO = 0x5b
- OP_ZERO_S = 0x5c
- OP_SIGN_PRI = 0x5d
- OP_SIGN_ALT = 0x5e
- OP_EQ = 0x5f
- OP_NEQ = 0x60
- OP_LESS = 0x61
- OP_LEQ = 0x62
- OP_GRTR = 0x63
- OP_GEQ = 0x64
- OP_SLESS = 0x65
- OP_SLEQ = 0x66
- OP_SGRTR = 0x67
- OP_SGEQ = 0x68
- OP_EQ_C_PRI = 0x69
- OP_EQ_C_ALT = 0x6a
- OP_INC_PRI = 0x6b
- OP_INC_ALT = 0x6c
- OP_INC = 0x6d
- OP_INC_S = 0x6e
- OP_INC_I = 0x6f
- OP_DEC_PRI = 0x70
- OP_DEC_ALT = 0x71
- OP_DEC = 0x72
- OP_DEC_S = 0x73
- OP_DEC_I = 0x74
- OP_MOVS = 0x75
- OP_CMPS = 0x76
- OP_FILL = 0x77
- OP_HALT = 0x78
- OP_BOUNDS = 0x79
- OP_SYSREQ_PRI = 0x7a
- OP_SYSREQ_C = 0x7b
- OP_FILE = 0x7c
- OP_LINE = 0x7d
- OP_SYMBOL = 0x7e
- OP_SRANGE = 0x7f
- OP_JUMP_PRI = 0x80
- OP_SWITCH = 0x81
- OP_CASETBL = 0x82
- OP_SWAP_PRI = 0x83
- OP_SWAP_ALT = 0x84
- OP_PUSHADDR = 0x85
- OP_NOP = 0x86
- OP_SYSREQ_D = 0x87
- OP_SYMTAG = 0x88
- OP_BREAK = 0x89
- OP_FLOAT_MUL = 0x8a
- OP_FLOAT_DIV = 0x8b
- OP_FLOAT_ADD = 0x8c
- OP_FLOAT_SUB = 0x8d
- OP_FLOAT_TO = 0x8e
- OP_FLOAT_ROUND = 0x8f
- OP_FLOAT_CMP = 0x90
Objetivos:
1- Que la variable estática value de la función funtion_print2 reste 1 por cada llamada.
2- Que la variable estática value de la función funtion_print2 empiece en 10
3- Entrar dentro del IF de plugin_init para que salga el print "Hacked "
Objetivo 1:
Mirando en el resultado del AMXXdump encontramos esto:
Código:
0x154 PROC ; stock funtion_print()
0x158 BREAK ; test_amxx_uncompress.sma:35
0x15C BREAK ; test_amxx_uncompress.sma:37
; static value
0x160 BREAK ; test_amxx_uncompress.sma:39
0x164 INC 0x150 ; value
0x16C BREAK ; test_amxx_uncompress.sma:41
0x170 PUSH.C 0x150 ; value 0x0
0x178 PUSH.C 0x0 ; string[10] "Mensaje 1"
0x180 PUSH.C 0x154 ; "string:[%s] static:[%d]"
0x188 PUSH.C 0xC
0x190 SYSREQ.C 0x1 ; server_print("string:[%s] static:[%d]",string[10]={"Mensaje 1"},value={""})
0x198 STACK 0x10 ; free 4 cells
0x1A0 ZERO.pri
0x1A4 RETN
Nos encontramos con:
0x164 INC 0x150 ; value
La instrucción INC significa Increment, lo unico que tenemos que hacer es modificar la instrucción INC por DEC que es Decrement.
¿ Como lo hacemos ?
Viendo la tabla valores HEX de instrucciones encontramos que OP_DEC tiene el valor hexadecimal 0x72. Solo tenemos que ir a la dirección de memoria 0x164 e insertar el valor hexadecimal 0x72 .
Abrimos el archivo .memory y agregamos.
code:0x00000164=[72]
Comprimimos el .raw y listo.
Objetivo 2:
0x164 INC 0x150 ; value
La instrucción INC hace referencia al dato en la dirección de memoria 0x150.
Lo único que tenemos que hacer es modificar el valor en la dirección de memoria 0x150.
Abrimos el archivo .memory y agregamos.
data:0x00000150=[0A]
nota: el valor hexadecimal 0x0A es igual a 10 en decimal.
Comprimimos el .raw y listo.
Objetivo 3:
Hay muchas formas, pero dependen mucho de la condición que tenga el IF. Ahora solo voy a mostrar la mas fácil y la que podrán usar casi siempre para saltarse código.
Siempre o casi siempre que haya un IF estará la instrucción OP_JZER. Podemos modificar la dirección del salto o cambiar la instrucción por OP_JNZ.
OP_JZER y OP_JNZ son como un goto o jump.
0x90 JZER 0xD0 ; jump_0
La instrucción OP_JZER en la dirección 0x90 indica que si la condicion es false se salte a la direccion de memoria 0xD0. Solo cambiaremos OP_JZER por OP_JNZ (0x36).
Abrimos el archivo .memory y agregamos.
code:0x00000090=[36]
Comprimimos el .raw y listo.
Notas generales:
- archivo .memory:
-- data se utiliza cuando se quiere modificar alguna variable o string.
-- code se utiliza cuando se quiere modificar una instrucción.
-- la dirección de memoria siempre tiene que tener el formato 0x0000000.
-- el valor puede ser un hexadecimal de hasta 8 caracteres (4 bytes).
- si tienen el sourcecode del amxmodx pueden echarle un ojo a amx.cpp para entender mejor sobre las instrucciones.
- el AMXXdump solo funciona con .amxx que contengan informacion de depuración (debug).
- un mal uso de esta herramienta puede corromper el plugin y ocasionar caídas en el servidor.
- recomiendo leer Decompiling Plugins (.amx/x -> .sma)
Herramientas:
AMXXdump
AMXX UnCompress
Bueno, eso es todo.
Con este método seria posible crear un plugin totalmente diferente al original, siempre y cuando se ocupe menos o igual cantidad de codigo y se utilicen las mismas natives y forwards.
Tutoriales:
Aportes:
[API] Advanced Vault System - [API] sXe Injected Events - [Modulo] MySQL Threads 1.2 - [API] OldMenu 1.1
[TOOL] AMXX-Editor v2.2 (new)
MyAnimeList
Aportes:
[API] Advanced Vault System - [API] sXe Injected Events - [Modulo] MySQL Threads 1.2 - [API] OldMenu 1.1
[TOOL] AMXX-Editor v2.2 (new)
MyAnimeList