Decompilando un plugin - Dia 2: Plugin_init
Hasta ahora que tenemos la estructura del plugin, todas las forwards bien colocaditas y las natives identificadas, ha llegado el momento de decompilar una forward, y que mejor que public plugin_init =)
En la VM que utiliza el AMXX, cada function, forward, callback o como sea empieza con el siguiente codigo en ensamblador:
PHP Code:
0xAddress PROC ;Inicio del procedimiento
Y termina con
PHP Code:
0xAddress RETN ;Retorno
Segun yo pienso, el AMXXDisassembler muestra de una forma mucho mas clara y concisa esta informacion que el AMXDump. El AMXXDisassembler separa el codigo del .sma de las librerias, por lo que es mucho mas facil reconocer que pertenece a una libreria y que pertenece al codigo del plugin.
Sabiendo esto, abrimos con el AMXXDisassembler nuestro plugin y localizamos la parte del codigo maquina donde empieza el codigo del .sma, en nuestro caso:
PHP Code:
Start of C:\Documents and Settings\Rak\Desktop\chanta.sma file
De aqui en adelante, es el codigo .sma del plugin en ensamblador. Buscamos el procedimiento de plugin_init, en el que amablemente el desensamblador ha colocado un comentario indicando su nombre
.
PHP Code:
0x420 PROC ; plugin_init
0x428 BREAK
0x430 BREAK
0x438 PUSH.C 0x2F8 ; str_003
0x448 PUSH.C 0x2D8 ; str_002
0x458 PUSH.C 0x2A0 ; str_001
0x468 PUSH.C 0x18
0x478 SYSREQ.C register_plugin
0x488 STACK 0x20
0x498 BREAK
0x4A0 PUSH.C -0x1
0x4B0 PUSH.C 0x398 ; var_001
0x4C0 PUSH.C -0x1
0x4D0 PUSH.C 0x360 ; str_005
0x4E0 PUSH.C 0x328 ; str_004
0x4F0 PUSH.C 0x28
0x500 SYSREQ.C register_clcmd
0x510 STACK 0x30
0x520 BREAK
0x528 PUSH.C 0x0
0x538 PUSH.C 0x3D8 ; str_007
0x548 PUSH.C 0x3A0 ; str_006
0x558 PUSH.C 0x9
0x568 PUSH.C 0x20
0x578 SYSREQ.C RegisterHam
0x588 STACK 0x28
0x598 ZERO.pri
0x5A0 RETN
Como podemos observar, tenemos 3 native calls, register_plugin, register_clcmd y RegisterHam.
La estructura de una native call en ensamblador es un numero determinado de PUSH.S o PUSH.C o PUSHADDR, un SYSREQ.C y luego un STACK.
El orden de los parametros es de abajo arriba, por ejemplo, en una native como register_plugin de 3 params, el 3er param seria el 1er PUSH.C, el 2º param seria el 2º PUSH.C y el 1er param seria el 3er PUSH.C.
Sabiendo esto vamos a decompilar la primera de nuestras 3 native calls:
register_plugin:
PHP Code:
0x438 PUSH.C 0x2F8 ; str_003
0x448 PUSH.C 0x2D8 ; str_002
0x458 PUSH.C 0x2A0 ; str_001
0x468 PUSH.C 0x18
0x478 SYSREQ.C register_plugin
0x488 STACK 0x20
En la pantalla del AMXX Disassembler, a la derecha tenemos el form donde estan las equivalencias a las etiquetas puestas en el codigo ensamblador, buscamos los valores de str_003, str_002 y str_001 y tenemos que son:
PHP Code:
str_003 = "[R]ak"
str_002 = "1.7"
str_001 = "Chanta"
Con esto ya sabemos que es lo que metemos en el stack con los 3 primeros PUSH.C. El siguiente PUSH.C segun se es el numero de parametros de la native (Mas Info: 1ª parte del tuto de Bailopan). Seguidamente tenemos una llamada al sistema que en nuestro caso es register_plugin y luego almacenamos todo en el stack.
Asi que tenemos:
PHP Code:
PUSH "[R]ak"
PUSH "1.7"
PUSH "Chanta"
NATIVE register_plugin
Sabiendo todo esto ya solo falta reconstruir la native:
PHP Code:
register_plugin("Chanta", "1.7", "[R]ak")
Felicidades, ya decompilaste tu primera native
Pasamos al siguiente trozo de codigo donde tenemos la siguiente native call: register_clcmd
PHP Code:
0x4A0 PUSH.C -0x1
0x4B0 PUSH.C 0x398 ; var_001
0x4C0 PUSH.C -0x1
0x4D0 PUSH.C 0x360 ; str_005
0x4E0 PUSH.C 0x328 ; str_004
0x4F0 PUSH.C 0x28
0x500 SYSREQ.C register_clcmd
0x510 STACK 0x30
Por una razon que no se (ando investigando) al compilar una native como register_clcmd (no se si hay alguna mas) crea una variable que no tengo ni idea para que sirve (si alguien sabe algo es recibido con las manos abiertas ;)
A lo nuestro, register_clcmd tiene solo 2 params asique seguimos el mismo sistema que para el register_plugin:
PHP Code:
0x4D0 PUSH.C 0x360 ; str_005
0x4E0 PUSH.C 0x328 ; str_004
0x4F0 PUSH.C 0x28
0x500 SYSREQ.C register_clcmd
0x510 STACK 0x30
PHP Code:
register_clcmd("chanta", "Chanta")
Listo, segunda native decompilada, pasamos a la ultima de la forward plugin_init, RegisterHam
PHP Code:
0x528 PUSH.C 0x0
0x538 PUSH.C 0x3D8 ; str_007
0x548 PUSH.C 0x3A0 ; str_006
0x558 PUSH.C 0x9
0x568 PUSH.C 0x20
0x578 SYSREQ.C RegisterHam
0x588 STACK 0x28
Analizando el codigo sabemos que la native RegisterHam tiene 4 params: la funcion virtual a hookear, la entidad en la que hookeamos la funcion virtual, el callback y el Post.
Comenzamos pues, el primer PUSH.C corresponde al ultimo parametro de RegisterHam que en este caso es un 0, por lo que la funcion es Pre no Post. Los dos siguientes parametros ya son capaces de averiguarlos solitos (sino, pulsen Control+W) el unico problema que pueden tener es con el ultimo PUSH.C (primer parametro de la native).
El ultimo PUSH.C indica que funcion virtual estamos hookeando en hexadecimal, solo necesitamos pasar ese numero a decimal y problema solucionado. Nos vamos a la libreria ham_const.inc donde estan todas las funciones virtuales hookeables, nos ponemos a contar y llegamos a la 9, Ham_TakeDamage (tengo pensado hacer un listado para que no tengan que andar contando una a una las funciones, sean pacientes ;)
Sabiendo todo esto ya tenemos toda la informacion para recomponer el RegisterHam:
PHP Code:
RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
Listo, ya han decompilado su primera forward, no fue dificil no? ;) Nos vemos en el siguiente day-a-day
__________________