Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.

Mensajes - Yuki

Páginas: [1] 2 3 4
1
Off Topic / Escribiendo un compilador en vivo
« en: Abril 19, 2018, 04:19:03 pm »
Hoy 19/04/2018 empecé con el primer streaming donde escribo un compilador en vivo desde Twitch, para los interesados en el tema que tengan tiempo, voy a continuar con esto de lunes a viernes de 3:00 pm (hora Argentina) hasta 4:00 pm.

¡Saludos!

2
Dudas y pedidos generales / Re:El compilador de Cramel no me funciona
« en: Septiembre 14, 2017, 06:10:52 am »
Citar
Aún no funciona, ahora no me tira error, pero el archivo "App.exe"que debería crearse no se crea.
Cuando publique ese comentario, ya estaba usando la versión nueva

Como dice Randomize, es posible que no haya una buena adaptación para Windows 10. Sigo pensando que es el /ej, intenta con este:

http://www.mediafire.com/file/78ch81b23od23yn/Compilador.zip

Nota: la nueva versión es la 2.0.0.533, el compilador que te pase recién es una modificación de esa versión.

3
Dudas y pedidos generales / Re:El compilador de Cramel no me funciona
« en: Septiembre 13, 2017, 09:24:28 pm »
Aún no funciona, ahora no me tira error, pero el archivo "App.exe"que debería crearse no se crea.

Lo sé, intenta con la nueva versión que arregla ese problema y varios otros.

4
Dudas y pedidos generales / Re:El compilador de Cramel no me funciona
« en: Septiembre 13, 2017, 05:47:36 pm »
Lo que pasa es que "Cramel2.exe" también debe estar encerrado entre comillas, mi error.

Código: [Seleccionar]
"Cramel2.exe" /f "C:\Users\darling\Desktop\Cramel2\Ejemplos\Hola Mundo.cml"
Me acabo de dar cuenta de un error en el código: una vez compilado el nuevo a archivo app.exe el compilador lo elimina. al final y al cabo no lo vas a poder usar con /ej.

Podes no usar /ej e ir a la carpeta de Cramel y ejecutar App.exe directamente o descargar la nueva actualización que acabo de subir (desde la pag oficial). Te la recomiendo.

5
Dudas y pedidos generales / Re:El compilador de Cramel no funciona
« en: Septiembre 13, 2017, 01:23:26 am »
Lo que pasa es que la ruta del archivo a compilar debe ir cerrado entre comillas.

Código: [Seleccionar]
Cramel2.exe /f "C:\Users\darling\Desktop\Cramel2\Ejemplos\Hola Mundo.cml" /ej
Saludos!

6
Dudas y pedidos generales / Re:Cramel caido ayuda porfabor
« en: Septiembre 02, 2017, 07:27:08 pm »
Al ir a la pagina oficial de Cramel e ingresar a la sección de descargas aparece el siguiente mensaje:

Citar
Nota: Debido a los problemas que hemos estado teniendo con los falsos positivos de antivirus, para su correcto uso se recomienda añadir la carpeta de Cramel a la lista de excepciones de antivirus solo si este alerta sobre nuestro software.

Lamento las molestias.

Cramel esta desarrollado en VB6, un viejo compilador de Basic que es (o fue) ampliamente utilizado en el mundo del malware, los antivirus no le tuvieron piedad y hoy en dia detectan hasta ejecutables sin códigos.

El compilador de Cramel es estable, tu antivirus solo te da un falso reporte de virus. Y como dije, lamento las molestias.

Sobre el editor, los enlaces están caídos y yo ya no lo tengo en mi ordenador (tuve que formatear), pero podes escribir código de Cramel en varios otros editores muy útiles.

Podes aprender a configurar nuevos editores como Crimson Editor (mi favorito), Notepad++ o Sublime Text desde el archivo de ayuda de Cramel > Tutoriales > Como > Configurar.

Te dejo acá los complementos de los editores mencionados.


¡Saludos!

7
Dudas y pedidos generales / [SOLUCIONADO] ¿Como detectar la GPU?
« en: Septiembre 02, 2017, 01:38:41 pm »
Estoy desarrollando un código para Windows 32 bits y solo necesito saber si existe una GPU en el equipo, no necesito el nombre, versión o características, solo saber si existe.

¿Como puedo hacer esto?

8
Hacking / Minería Bitcoin - El camino difícil
« en: Septiembre 01, 2017, 05:16:31 am »

Este articulo explica la minería de Bitcoin en detalle, hasta los datos hexadecimales y el trafico de red. Si alguna vez te has preguntado que es lo que realmente pasa con la minería de Bitcoins, llegaste al lugar correcto.

El propósito de la minería

La minería de bitcoin es a menudo considerado como la forma de crear nuevos bitcoins. Pero eso realmente es sólo un propósito secundario. La principal importancia de la minería es asegurar que todos los participantes tengan una visión coherente de los datos de Bitcoin. Debido a que Bitcoin es un sistema distribuido de persona a persona ("peer to peer"), no hay una base de datos central que mantenga un registro de quién posee Bitcoins. En su lugar, el registro de todas las transacciones se distribuye a través de la red.

El principal problema con un registro de transacciones distribuidas es cómo evitar inconsistencias que podrían permitir a alguien generar el mismo Bitcoin dos veces. La solución en Bitcoin es minar las transacciones pendientes en un bloque de transacciones aproximadamente cada 10 minutos. Lo que los hace oficiales. Las transacciones conflictivas o inválidas no son permitidas en los bloques, entonces la doble minería es un problema resuelto.

Aunque las transacciones mineras en los bloques evitan el doble minado, esto representa nuevos problemas: ¿Cómo evitar que las personas minen bloques aleatorios? ¿Cómo se decide quien obtiene Bitcoins de un bloque minado? ¿Cómo acuerda la red qué bloques son válidos? Resolver estos problemas es la innovación clave de Bitcoin: La minería se hace muy, muy difícil debido a la técnica llamada "Proof Of Work". Esta hace que se necesite una enorme cantidad de esfuerzo computacional para extraer un bloque, pero que sea fácil para los compañeros de la red verificar que un bloque ha sido exitosamente extraído.

Cada bloque minado hace referencia al bloque anterior, formado por una cadena ininterrumpida de nuevo al primer bloque Bitcoin. Esta cadena de bloques asegura que todos estén de acuerdo en el registro de transacción. También asegura que nadie pueda alterar los bloques de la cadena, ya que volver a minar todos los bloques siguientes seria computacionalmente imposible. Mientras nadie controle más de la mitad de los recursos computacionales del mundo, la minería seguirá siendo competitiva y nadie podrá controlar la cadena de bloques.

Como un efecto secundario, la minería añade nuevos Bitcoins al sistema. Por cada bloque minado, los mineros obtienen actualmente 25 Bitcoins, lo que alienta a los mineros a trabajar duro para minar los bloques. Con la posibilidad de recibir dinero cada 10 minutos, hay muchas ganancias en la minería.

Como funciona la minería

La minería requiere una tarea que es muy difícil de realizar, pero fácil de verificar. La mineria Bitcoin utiliza criptografía, con un algoritmo de hashing llamado "doble SHA-256". Un algoritmo de hash (como SHA-256, MD5, CRC32 entre muchos otros) toma un fragmento de datos como entrada (cualquier dato de cualquier longitud) y lo reduce a un valor de hash mas pequeño (en este caso 256 bits). Con un hash criptográfico, no hay manera de obtener un valor de hash que desee sin intentar un montón de entradas (prueba y error). Pero una vez que encuentra la entrada que de el valor hash que desea, es fácil para cualquiera verificar el hash. Por lo tanto, el hash criptográfico se convierte en una buena manera de implementar "Proof Of Work" de Bitcoin.

Con más detalle, para extraer un bloque, primero recopila las transacciones nuevas en un bloque. A continuación, Hashea el bloque para formar un valor de hash del bloque de 256 bits (convertimos el bloque en un hash) Si el hash comienza con ceros suficientes, el bloque se ha extraído con éxito, se envía a la red Bitcoin y el hash se convierte en el identificador del bloque. La mayoría de las veces el hashing no tiene éxito (no retorna un hash que inicie con ceros) por lo que se modifica el bloque ligeramente y se vuelve a intentar una y otra vez miles de millones de veces. Aproximadamente cada 10 minutos alguien conseguirá minar un bloque, y el proceso comenzará de nuevo.

El siguiente diagrama muestra la estructura de un bloque específico, y cómo es hasheado. La parte amarilla es el encabezado del bloque, seguido de las primeras transacciones que entran en el bloque. La primera transacción es la transacción especial "coinbase" que concede la recompensa de la minería al minero. Las transacciones restantes son "transacciones Bitcoin estándar" moviéndose por ahí. Si la cabecera del hash comienza con ceros suficientes, el bloque se extrae con éxito. Para este bloque, el hash que tiene éxito es:

0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50

Citar
Nota: Estructura de un bloque Bitcoin.


La cabecera de bloque contiene un puñado de campos que describen el bloque. El primer campo del bloque es la versión del protocolo. Es seguido por el hash del bloque anterior en la cadena de bloques, lo que garantiza que todos los bloques formen una secuencia ininterrumpida en la cadena de bloques. (Inconvenientemente, el hash se invierte en la cabecera). El siguiente campo es la raíz Merkle, un hash especial de todas las transacciones en el bloque. Esta es también parte clave de la seguridad de Bitcoin, ya que garantiza que las transacciones no se puedan cambiar una vez que son parte de un bloque. A continuación se muestra una marca de tiempo (moderadamente precisa) del bloque, seguida por los bits de valor de dificultad de la minería. Finalmente, el nonce. Es un valor arbitrario que se incrementa en cada intento de hasheo para proporcionar un nuevo valor de hash. La parte difícil de la minería es encontrar un nonce que funcione.

Un pequeño programa para minar un bloque

Se escribió un programa en Python que explota el bloque anterior. El programa en sí es bastante simple - la parte más difícil del código es calcular el objetivo de dificultad a partir de bits.

Código: [Seleccionar]
import hashlib, struct
 
ver = 2
prev_block = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717"
mrkl_root = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a"
time_ = 0x53058b35 # 2014-02-20 04:57:25
bits = 0x19015f53
 
# https://en.bitcoin.it/wiki/Difficulty
exp = bits >> 24
mant = bits & 0xffffff
target_hexstr = '%064x' % (mant * (1<<(8*(exp - 3))))
target_str = target_hexstr.decode('hex')
 
nonce = 0
while nonce < 0x100000000:
    header = ( struct.pack("<L", ver) + prev_block.decode('hex')[::-1] +
          mrkl_root.decode('hex')[::-1] + struct.pack("<LLL", time_, bits, nonce))
    hash = hashlib.sha256(hashlib.sha256(header).digest()).digest()
    print nonce, hash[::-1].encode('hex')
    if hash[::-1] < target_str:
        print 'success'
        break
    nonce += 1

La siguiente tabla muestra los hash obtenidos de los valores nonce seleccionados. El punto clave es que cada nonce genera un valor hash básicamente aleatorio. De vez en cuando un nonce afortunado generará un hash que comienza con algunos ceros. Para obtener una gran cantidad de ceros, es necesario probar un número exponencialmente grande de nonces. Para este bloque, el nonce "ganador" es 856192328.

noncehash
05c56c2883435b38aeba0e69fb2e0e3db3b22448d3e17b903d774dd5650796f76
128902a23a194dee94141d1b70102accd85fc2c1ead0901ba0e41ade90d38a08e
2729577af82250aaf9e44f70a72814cf56c16d430a878bf52fdaceeb7b4bd37f4
38491452381016cf80562ff489e492e00331de3553178c73c5169574000f1ed1c
3903fd5ff1048668cd3cde4f3fb5bde1ff306d26a4630f420c78df1e504e24f3c7
9900001e3a4583f4c6d81251e8d9901dbe0df74d7144300d7c03cab15eca04bd4bb
521170000642411733cd63264d3bedc046a5364ff3c77d2b37ca298ad8f1b5a9f05ba
181315200000c94a85b5c06c9b06ace1ba7c7f759e795715f399c9c1b1b7f5d387a319f
19745650000000cdccf49f13f5c3f14a2c12a56ae60e900c5e65bfe1cc24f038f0668a6c
2439898010000000ce99e2a00633ca958a16e17f30085a54f04667a5492db49bcae15d190
8561923280000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50

Debo señalar que los engañe por comenzar con un bloque que tendría éxito al ser minado. La mayoría de los intentos de extraer un bloque fallarán por completo - ninguno de los valores de nonce tendrá éxito. En ese caso, debe modificar el bloque ligeramente y volver a intentarlo. La marca de tiempo se puede ajustar (razón por la cual la marca de tiempo en bloques minados es a menudo incorrecta) . Se pueden agregar nuevas transacciones al bloque, cambiando el hash Markle. La transacción "coinbase" puede ser modificada - esto resulta ser muy importante para las pools. Cualquiera de estos cambios dará lugar a hashes totalmente diferentes, así que los valores del nonce se pueden intentar otra vez.

El programa Python hace unos 42.000 hashes por segundo, que es un millón de veces más lento que el hardware utilizado por los mineros reales. El programa tomaría en promedio cerca de 11 millones de años para minar un bloque mediante "rasguños".

La minería es muy difícil

La dificultad de extraer un bloque es asombrosa. Con la dificultad actual, las chances de que un hash tenga éxito es un poco menos de uno en 10^19. Encontrar un hash exitoso es más difícil que encontrar un determinado grano de arena de todos los granos de arena en la Tierra. Para encontrar un hash cada diez minutos, la tasa de hashing a Bitcoin debe ser increíblemente grande. En la actualidad, los mineros de la red Bitcoin están haciendo unos 25 millones de gigahashes por segundo. Es decir, cada segundo alrededor de 25.000.000.000.000.000 bloques son hasheados. Yo estimo (muy groseramente) que el hardware total utilizado para la minería Bitcoin costó decenas de millones de dólares y utiliza tanto poder como el país de Camboya.

Tenga en cuenta que encontrar un hash exitoso es una tarea totalmente arbitraria que no logra nada útil en sí mismo. El único propósito de encontrar un pequeño hash es hacer la minería difícil, que es fundamental para la seguridad de Bitcoin. Me parece que el esfuerzo puesto en la minería de Bitcoin se ha salido de los carriles recientemente.

La minería es financiada principalmente por la recompensa de 25 bitcoin por bloque, y ligeramente por los honorarios de transacción (aproximadamente 0.1 bitcoin por bloque). Dado que la recompensa de la minería actualmente funciona a alrededor de $15.000 por bloque, que paga por un montón de hardware. Por transacción, los mineros están recibiendo alrededor de $34 en la recompensa de la minería y $0.10 en honorarios (stats).

Minando con un pool

Debido a que la minería es tan difícil, normalmente se hace en los pools de minería, donde un grupo de mineros comparte el trabajo y comparte las recompensas. Si usted mina por usted mismo, puede ser que tenga éxito en minar un bloque y conseguir 25 Bitcoins cada pocos años. Por la minería como parte de una pool, usted podría conseguir una fracción de un Bitcoin cada día, que para la mayoría de la gente es preferible.

Las piscinas mineras utilizan una técnica interesante para ver cuánto trabajo están haciendo los mineros. Ellos envían un bloque para ser minado, y obtener actualizaciones de un minero cada vez que un minero obtiene una solución parcial. Cada solución parcial demuestra que el minero está trabajando duro en el problema y le da al minero una parte de la recompensa final cuando alguien logra minar el bloque.

Por ejemplo, si la minería de Bitcoin requiere un hash comenzando con 15 ceros, el grupo de minería puede pedir hashes comenzando con 10 ceros, lo que es un millón de veces más fácil. Dependiendo de la potencia de su hardware, un minero podría encontrar tal solución cada pocos segundos o unas pocas veces por hora. Eventualmente, una de estas soluciones comenzará con no sólo 10 ceros, sino 15 ceros, minando con éxito un bloque y ganando la recompensa para el pool. La recompensa se divide en función del recuento de acciones de cada minero como una fracción del total, y el operador de la piscina toma un pequeño porcentaje por gastos generales.

La mayoría de las veces alguien fuera de la piscina mina un bloque primero. En ese caso, el operador de la piscina envía nuevos datos y los mineros comienzan a minar el nuevo bloque. Las personas en un pool pueden ponerse nerviosas si pasa un largo tiempo sin un pago debido a la "mala suerte de la mineria".

Stratum: La comunicación entre una piscina y los mineros

A continuación vamos a ver en detalle la comunicación entre un minero y la pool. La comunicación entre la piscina y los mineros es interesante. la pool debe proveer trabajo eficientemente a los mineros y recolectar sus resultados rápidamente. La piscina debe asegurarse de que los mineros no están duplicando el trabajo. Y la piscina debe asegurarse de que los mineros no pierdan el tiempo trabajando en un bloque que ya ha sido minado.

Un tema importante para las pools mineras es cómo apoyar a los mineros rápidos. El nonce en el encabezado es demasiado pequeño para los mineros rápidos ya que ellos recorrerán todos los valores posibles más rápido de lo que la piscina puede proveer nuevos bloques. La solución es permitir que los mineros actualicen la transacción "coinbase" para que puedan poner nonces adicionales ahí. Esto hace la mineria más complicada debido a que después de construir la transacción "coinbase" el minero debe recalcular el arbol de hash Merkle y luego intentar minar el bloque.

Vamos a mirar el protocolo de la pool de minería Stratum que es utilizado por muchas otras pools. (Algunos protocolos alternativos son los protocolos Getwork y Getblocktemplate). El siguiente programa de Python utiliza el protocolo Stratum para realizar una solicitud de minería en el grupo de minería GHash.IO y muestra los resultados. (Este programa es una demostración mínima, no use este código para la minería real).

Código: [Seleccionar]
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("us1.ghash.io", 3333))

sock.send("""{"id": 1, "method": "mining.subscribe", "params": []}\n""")
print sock.recv(4000)

sock.send("""{"params": ["kens_1", "password"], "id": 2, "method": "mining.authorize"}\n""")
print sock.recv(4000)

La siguiente información es lo que el grupo de minería devuelve a través de la red en respuesta al programa anterior. Dado que el protocolo Stratum utiliza JSON-RPC, los resultados son ASCII legible en lugar de los paquetes binarios utilizados por la mayoría de Bitcoin. Esto proporciona todos los datos necesarios para iniciar la minería como parte de la agrupación:

Código: [Seleccionar]
{"id":1,"result":[[["mining.set_difficulty","b4b6693b72a50c7116db18d6497cac52"],["mining.notify","ae6812eb4cd7735a302a8a9dd95cf71f"]],"4bc6af58",4],"error":null}

{"id":null,"params":[16],"method":"mining.set_difficulty"}

{"id":null,"params":["58af8d8c","975b9717f7d18ec1f2ad55e2559b5997b8da0e3317c803780000000100000000","01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4803636004062f503253482f04428b055308","2e522cfabe6d6da0bd01f57abe963d25879583eea5ea6f08f83e3327eba9806b14119718cbb1cf04000000000000000000000001fb673495000000001976a91480ad90d403581fa3bf46086a91b2d9d4125db6c188ac00000000",["ea9da84d55ebf07f47def6b9b35ab30fc18b6e980fc618f262724388f2e9c591","f8578e6b5900de614aabe563c9622a8f514e11d368caa78890ac2ed615a2300c","1632f2b53febb0a999784c4feb1655144793c4e662226aff64b71c6837430791","ad4328979dba3e30f11c2d94445731f461a25842523fcbfa53cd42b585e63fcd","a904a9a41d1c8f9e860ba2b07ba13187b41aa7246f341489a730c6dc6fb42701","dd7e026ac1fff0feac6bed6872b6964f5ea00bd8913a956e6b2eb7e22363dc5c","2c3b18d8edff29c013394c28888c6b50ed8733760a3d4d9082c3f1f5a43afa64"],"00000002","19015f53","53058b41",false],"method":"mining.notify"
{"id":2,"result":true,"error":null}
{"id":null,"params":[16],"method":"mining.set_difficulty"}

La primera línea es una respuesta del servidor del pool con los detalles de la suscripción. Los primeros valores no son demasiado importantes. El valor 4bc6af58 es el valor extranonce1 que se utiliza para construir el bloque. Cada cliente obtiene un valor único para garantizar que todos los clientes de minería generan bloques únicos y no duplicar el trabajo. El siguiente valor (4 bytes) es la longitud del valor de extranonce2_size que el minero pone en la "coinbase" durante la minería.

La segunda línea es un mensaje mining.set_difficulty a nuestro cliente. Con una dificultad de 16, puedo conseguir una parte cada hora o dos en mi PC. En comparación, la dificultad minera de Bitcoin es 3,129,573,174.52. Por lo tanto, es aproximadamente 200 millones de veces más fácil obtener una participación en esta pool que tener éxito minando un bloque de forma independiente. Es por eso que la gente se une a las pools.

La tercera línea es una notificación "mining.notify" a nuestro cliente. Este mensaje define que bloque nosotros vamos a minar. Hay una gran cantidad de datos devueltos en "params", por lo que voy a explicar campo por campo.

job_id58af8d8c
prevhash975b9717f7d18ec1f2ad55e2559b5997b8da0e3317c803780000000100000000
coinb10100000001000000000000000000000000000000000000000000000000000000
0000000000ffffffff4803636004062f503253482f04428b055308

coinb22e522cfabe6d6da0bd01f57abe963d25879583eea5ea6f08f83e3327eba9806b
14119718cbb1cf04000000000000000000000001fb673495000000001976a914
80ad90d403581fa3bf46086a91b2d9d4125db6c188ac00000000
merkle_branch["ea9da84d55ebf07f47def6b9b35ab30fc18b6e980fc618f262724388f2e9c591", ...]
version00000002
nbits19015f53
ntime53058b41
clean_jobsfalse

El job_id se utiliza para identificar esta tarea de minería si el minero reporta éxito.

La mayoría de los campos se utilizan en la cabecera del bloque. El prevhash es el hash del bloque anterior. Al parecer, la mezcla de big-ending y little-endian no son lo suficientemente confusas entonces este valor hash también tiene cada bloque de 4 bytes invertido. La versión es la versión de protocolo del bloque. El nbits indica la dificultad del bloque. El tiempo de timestamp no es necesariamente exacto.

Los campos coinb1 y coinb2 permiten al minero construir la transacción "coinbase" para el bloque. Esta transacción se forma concatenando coinb1, el valor extranonce1 obtenido al inicio, el extranonce2 que el minero ha generado, y coinb2. El resultado es una transacción en el protocolo Bitcoin. La lista de hash merkle_branch permite al minero recalcular eficientemente el hash Merkle con la nueva transacción "coinbase".

clean_jobs se utiliza si el minero necesita reiniciar los trabajos de minería.

Después de recibir estos datos, el minero puede comenzar a generar transacciones de "coinbase" y minería de bloques.

Creando un bloque para un pool

Una vez que el minero ha recibido la información de la pool, es fácil formar la transacción de coinbase combinando la coinb1, extranonce1, extranonce2 y coinb2. El siguiente diagrama muestra cómo la combinación de estos cuatro valores forman la transacción completa, con los nonces en el centro del script de coinbase. (El bloque siguiente es ligeramente diferente al descrito anteriormente).


La estructura de la transacción coinbase es similar a una transacción regular, pero hay algunas diferencias importantes. Una transacción normal transfiere Bitcoins de entradas (generalmente direcciones de origen) a salidas (normalmente direcciones de destino). Una transacción coinbase está generando nuevos Bitcoins de la nada, en lugar de hacer una transferencia, por lo que la transacción es ligeramente diferente. El hash de salida anterior y el índice son irrelevantes para la transacción coinbase. El primer script es el scriptSig que firma la transacción para probar la propiedad de los Bitcoins entrantes. En una transacción de coinbase, esto es irrelevante, por lo que en su lugar el campo se llama la "coinbase" y es en su mayoría son datos arbitrarios. (Muchos mineros ocultan mensajes allí). El campo "value" en la transacción coinbase es la recompensa de la minería de 25 bitcoin más cualquier bitcoins que sobran de las otras transacciones (los bitcoins que sobran se tratan como honorarios de minería). Finalmente, tanto las transacciones regulares como la transacción coinbase utilizan el segundo script (scriptPubKey) para especificar los destinatarios de los Bitcoins.

Una vez que se crea la transacción coinbase, el hash para esta transacción coinbase se combina con los datos merkle_branch del conjunto para generar el hash Merkle para todo el conjunto de transacciones. Debido a la estructura del hash de Merkle (explicado más adelante), esto permite que el hash para el conjunto entero de transacciones sea recalculado fácilmente.

Por último, el encabezado de bloque se construye a partir del nuevo hash Merkle y los datos proporcionados por la agrupación, y el algoritmo hash puede iterar sobre los valores nonce en el encabezado, al igual que el programa Python anterior. Una vez que todos los valores de nonce han sido probados, el minero incrementa la extranonce2, genera una nueva transacción de coinbase y continúa.


Informar al pool del éxito

La dificultad para una pool es mucho mas baja que la dificultad minera original de Bitcoin (menos ceros iniciales requeridos), por lo que es mucho más fácil obtener una parte. Cuando un bloque es hasheado a la dificultad de la pool, se le envía un simple mensaje JSON:

Código: [Seleccionar]
{"method": "mining.submit", "params": ["kens.worker1", "58af8db7", "00000000", "53058d7b", "e8832204"], "id":4}
Los parámetros son el nombre del trabajador, id de trabajo, extranonce2, tiempo y encabezado nonce. Esta información es suficiente para que el grupo construya la transacción coincidente, el encabezado y verifique el bloque. Si el hash cumple la dificultad de la pool, obtendrá una parte. Si el hash también cumple con la dificultad de Bitcoin, mucho más difícil, el bloque se ha extraído con éxito. En este caso, la agrupación envía el bloque a la red de Bitcoin y a todo el mundo con acciones (que trabajó) se les paga como consecuencia.

Minería por diversión y ganancias

Si tienes curiosidad por la minería, es sorprendentemente fácil probarla, aunque tendrás suerte de ganar incluso un centavo. Basta con crear una cuenta en un grupo de minería como BTC Guild, descargar software de minería como cpuminer (minerd.exe) y ejecutar el software para iniciar la minería. Para una piscina con dificultad baja, usted debe obtener acciones en pocos minutos; en una piscina con una dificultad mayor (como GHash.IO), puede tardar una hora o dos para obtener una parte, lo que es más frustrante.


La captura de pantalla muestra cómo se ve la minería a medida que se obtienen las acciones y los bloques son minados. Tuve suerte y sólo me tomó un minuto para exitosamente obtener una porción de lo minado. Un minuto después, alguien extrajo con éxito un bloque, por lo que la piscina le dice a todo el mundo que comience de nuevo. Otro bloque fue extraído menos de un minuto después de que - aunque los bloques son 10 minutos aparte en promedio, los tiempos pueden variar extensamente. Tomó 12 minutos para que mi próxima acción sea generada. Después de correr por un tiempo, gané 0,00000043 BTC, que es una pequeña fracción de un centavo.

La minería Bitcoin es una "carrera armamentista". Originalmente la gente podía minar con la CPU en una PC normal, pero eso no ha sido práctico por un tiempo. La siguiente minería fue descargada a GPUs. Ahora, la minería se hace con hardware ASIC de propósito especial, que está aumentando rápidamente en velocidad. La minería con fines de lucro es muy competitiva, y necesitará buscar información en otro lugar.

Si desea probar la minería sólo por diversión, es posible que prefiera minar una moneda como Dogecoin en lugar de Bitcoin. En primer lugar, Dogecoin utiliza un algoritmo de hash diferente que no funciona bien con hardware ASIC, por lo que no está tan desventajoso en comparación con los mineros profesionales. En segundo lugar, porque dogecoins valen mucho menos que bitcoins, usted terminará para arriba con un número mucho mayor de dogecoins, que parece más rewarding. Para la minería Dogecoin, he utilizado la piscina dogepool.pw algo arbitrariamente. El proceso es casi el mismo que la minería Bitcoin, excepto que se utiliza el algoritmo scrypt en lugar de sha256d. Hay muchos otros cryptocurrencies alternativos para elegir.

Citar
Nota: Este articulo fue escrito por Ken Shirriff y traducido al español por Yuki para la comunidad de Underc0de.org

9
Hacking / [Guía] Cargar DLL directamente de memoria
« en: Agosto 05, 2017, 10:52:00 am »
Información

Las funciones predeterminadas de la API de Windows para cargar bibliotecas externas en un programa (LoadLibrary, LoadLibraryEx) sólo funcionan con archivos del sistema. Por lo tanto, es imposible cargar un DLL de memoria. Pero a veces, necesitas exactamente esta funcionalidad (por ejemplo, si no quieres distribuir muchos archivos o quieres hacer el des-ensamblado más difícil). Soluciones comunes para estos problemas son escribir el DLL en un archivo temporal primero e importarlo desde ahí. Cuando el programa termina, el archivo temporal se elimina.

En este tutorial, describiré primero cómo se estructuran los archivos DLL y se presentará código que se puede utilizar para cargar una DLL completamente desde la memoria, sin tocar el disco.

Ejecutables de Windows - Formato PE

La mayoría de los binarios de Windows que pueden contener código ejecutable (.exe, .dll, .sys) comparten un formato de archivo común que consta de las siguientes partes:

Código: [Seleccionar]
DOS Header
DOS Stub
PE Header
Sección Header
Sección 1
Sección 2
. . .
Sección #

Todas las estructuras que se dan a continuación se pueden encontrar en el archivo Estructuras.cml

Cabecera DOS (DOS Header) - STUB

El encabezado DOS sólo se utiliza para la compatibilidad con versiones anteriores. Precede al stub de DOS que normalmente sólo muestra un mensaje de error acerca de que el programa no se puede ejecutar desde el modo DOS.

Microsoft define el encabezado DOS de la siguiente manera:

Código: [Seleccionar]
Estruct IMAGE_DOS_HEADER,_
        e_magic,_       ' Número mágico.
        e_cblp,_         ' Bytes en la última página del archivo.
        e_cp,_           ' Paginas en el archivo.
        e_crlc,_          ' Relocalizaciones.
        e_cparhdr,_    ' Tamaño del encabezado en el apartado.
        e_minalloc,_    ' Tamaño extra mínimo del apartado.
        e_maxalloc,_   ' Tamaño extra máximo del apartado.
        e_s,_              ' Valor SS inicial (relativo).
        e_sp,_            ' Valor inicial SP.
        e_csum,_        ' Checksum.
        e_ip,_             ' Valor inicial IP.
        e_cs,_             ' Valor CS inicial (relativo).
        e_lfarlc,_         ' Dirección en el archivo de la tabla de relocaciones.
        e_ovno,_        ' Número de superposición.
        e_res[4],_       ' Reservados.
        e_oemid,_       ' Identificador OEM (para e_oeminfo).
        e_oeminfo,_    ' Información OEM.
        e_res2[10]:Word,_ ' Reservado.
        e_lfanew:Entero ' Dirección en el archivo de la nueva cabecera.

Cabecera PE (PE Header)

La cabecera PE contiene información acerca de las diferentes secciones dentro del ejecutable que son usados para almacenar códigos y datos o también para definir importaciones de otras librerías o exportaciones que esta proporciona.

Esta se define como la siguiente estructura:

Código: [Seleccionar]
Estruct IMAGE_NT_HEADERS,_
        Signature:Entero,_
        FileHeader:IMAGE_FILE_HEADER,_
        OptionalHeader:IMAGE_OPTIONAL_HEADER

El miembro 'FileHeader' describe el formato físico del archivo. Por ejemplo: contenidos, información sobre símbolos, etc.

Código: [Seleccionar]
Estruct IMAGE_FILE_HEADER,_
        Machine,_
        NumberOfSections:Word,_
        TimeDateStamp,_
        PointerToSymbolTable,_
        NumberOfSymbols:Entero,_
        SizeOfOptionalHeader,_
        Characteristics:Word

El 'OptionalHeader' contiene información sobre el formato lógico de la librería, incluyendo la versión requerida del SO, los requisitos de memoria y los puntos de entrada.

Código: [Seleccionar]
Estruct IMAGE_OPTIONAL_HEADER,_
        Magic:Word,_ ' 0
        MajorLinkerVersion,_ ' 2
        MinorLinkerVersion:Byte,_ ' 3
        SizeOfCode,_    ' 4
        SizeOfInitializedData,_ ' 8
        SizeOfUnitializedData,_ ' 12
        AddressOfEntryPoint,_ ' 16
        BaseOfCode,_ ' 20
        BaseOfData,_ ' 24
        ImageBase,_ ' 28
        SectionAlignment,_ ' 32
        FileAlignment:Entero,_ ' 36
        MajorOperatingSystemVersion,_ ' 40
        MinorOperatingSystemVersion,_ ' 42
        MajorImageVersion,_ ' 44
        MinorImageVersion,_ ' 46
        MajorSubsystemVersion,_ ' 48
        MinorSubsystemVersion:Word,_ ' 50
        W32VersionValue,_ ' 52
        SizeOfImage,_ ' 56
        SizeOfHeaders,_ ' 60
        CheckSum:Entero,_ ' 64
        SubSystem,_ ' 68
        DllCharacteristics:Word,_ ' 70
        SizeOfStackReserve,_ ' 72
        SizeOfStackCommit,_ ' 76
        SizeOfHeapReserve,_ ' 80
        SizeOfHeapCommit,_ ' 84
        LoaderFlags,_ ' 88
        NumberOfRvaAndSizes:Entero,_ ' 92
        DataDirectory[16]:IMAGE_DATA_DIRECTORY ' 96

El 'DataDirectory' contiene 16 (IMAGE_NUMBEROF_DIRECTORY_ENTRIES) entradas que definen los componentes lógicos de la librería:

Citar
Nota: Las descripciones en rojo no pudieron ser traducidas.

Indice-Descripción
0Funciones exportadas
1Funciones importadas
2Recursos (resources)
3Información de excepciones
4Información de seguridad
5Tabla de reubicación base
6Información de depuración
7Datos de arquitectura especifica
8Puntero global
9Thread local storage
10Configuración de carga
11Importaciones vinculadas
12Tabla de direcciones de importación
13Delay load imports
14COM runtime descriptor

Para importar una DLL nosotros solo necesitamos las entradas que describen las importaciones y la tabla de reubicaciones. Para proporcionar acceso a las funciones exportadas, se requiere la entrada de las exportaciones.

Cabecera de secciones (Section Header)

La cabecera de secciones es almacenada después de la estructura 'OptionalHeader' en la cabecera PE. Si usted usa C. Microsoft le provee la macro 'IMAGE_FIRST_SECTION' para obtener la dirección de inicio basado en la cabecera PE.

Actualmente, la cabecera de secciones (Section Header) es una lista de información acerca de cada sección en el archivo.

Código: [Seleccionar]
Unión Misc,_
      PhysicalAddress,_
      VirtualSize:Entero

Estruct IMAGE_SECTION_HEADER,_
        Name[8]:Byte,_
        Misc:Misc,_
        VirtualAddress,_
        SizeOfRawData,_
        PointerToRawData,_
        PointerToRelocations,_
        PointerToLinenumbers:Entero,_
        NumberOfRelocations,_
        NumberOfLinenumbers:Word,_
        Characteristics:Entero

Una sección puede contener código, datos, información de reubicaciones, recursos, definiciones de importación/exportación, etc.

Cargando la librería

Para emular la carga PE, nosotros primero debemos entender cuales son los pasos necesarios para cargar un archivo en la memoria y preparar las estructuras para que puedan ser llamadas por otros programas.

Al invocar a la API LoadLibrary, básicamente, Windows realiza estas tareas:

  • Abre el archivo dado y analiza las cabeceras DOS y PE.
  • Trata de almacenar 'PEHeader.OptionalHeader.SizeOfImage' bytes en la posición 'PEHeader.OptionalHeader.ImageBase'.
  • Analiza las secciones de cabecera y copia cada sección a sus respectivas secciones de memoria. La dirección de destino de cada sección, relativa a la base del bloque de memoria asignado, se almacena en el miembro 'VirtualAddress' de la estructura IMAGE_SECTION_HEADER.
  • Si el bloque de memoria alojado difiere del miembro 'ImageBase', varias referencias en las secciones de código y/o datos deben ser ajustadas. Esto es llamado reubicación base (base relocation).
  • Las importaciones necesarias para la DLL deben resolverse cargando las librerías correspondientes.
  • Las regiones de memoria de cada sección deben ser protegidas dependiendo de las características de la sección. Muchas secciones son marcadas como descartables y por lo tanto se pueden liberar a partir de este punto. Estas secciones normalmente contienen información temporal que solo es requerida durante la importación. Como la información para la reubicación base.
  • Nuestra librería esta cargada completamente, Se debe notificar sobre esto llamando al punto de entrada (Entry Point) usando la bandera (flag) DLL_PROCESS_ATTACH.

En los siguientes párrafos, cada paso es descrito.

Almacenando memoria

Toda la memoria requerida por la libreria debe ser reservada/alojada usando VirtualAlloc, como Windows provee funciones para proteger estos bloques de memoria. Esto es requerido para restringir el acceso a la memoria, como bloquear el acceso a escritura del código o datos constantes.

La estructura 'OptionalHeader' define el tamaño del bloque de memoria requerido por la librería. Si es posible, esta debe ser almacenado en la dirección especificada por 'ImageBase'.

Citar
Nota: En el siguiente mini-ejemplo se asume que usted hizo apuntar 'PEHeader' a la librería en memoria.

Código: [Seleccionar]
Var Mem:Entero
Mem = VirtualAlloc(PEHeader.OptionalHeader.ImageBase,PEHeader.OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE)

Si la memoria reservada difiere de la dirección dada en 'ImageBase', se debe realizar la reubicación de base como se describe mas adelante.

Copiar secciones

Una vez que la memoria ha sido reservada, el contenido del archivo debe ser copiado al sistema. Las secciones de cabecera (Section Headers) deben ser evaluadas para determinar la posición en el archivo y el área de destino en la memoria.

Antes de copiar los datos, el bloque de memoria debe estar comprometido.

Citar
Nota: Se aloja nueva memoria con la bandera 'MEM_COMMIT'.

Código: [Seleccionar]
Var Destino:Entero
Destino = VirtualAlloc(DirecciónBase + Sección.VirtualAddress,Sección.SizeOfRawData,MEM_COMMIT,PAGE_READWRITE)

Secciones sin datos en el archivo (como secciones de datos para ser usadas como variables) tienen un 'SizeOfRawData' de 0. Entonces puedes usar la 'SizeOfInitializedData' o 'SizeOfUninitializedData' de 'OptionalHeader'. Cada uno debe ser elegido dependiendo de las banderas de bits 'IMAGE_SCN_CNT_INITIALIZED_DATA' e 'IMAGE_SCN_CNT_UNINITIALIZED_DATA' que se pueden establecer en las características de la sección (miembro 'Characteristics').

Reubicación base

Todas las direcciones de memoria en las secciones de código/datos de una libreria son almacenadas relativamente a la dirección definida por 'ImageBase' de 'OptionalHeader'.

Si la librería no puede ser importada de esta dirección de memoria, las referencias deben ser re-ajustadas (reubicadas). El formato de archivo ayuda a esto almacenando información sobre todas estas referencias en la tabla de reubicación de base, la cual puede ser encontrada en el directorio 5 de la 'DataDirectory' en la 'OptionalHeader'.

Esta tabla consta de una serie de esta estructura:

Código: [Seleccionar]
Estruct IMAGE_BASE_RELOCATION,_
        VirtualAddress,_
        SizeOfBlock:Entero

Contiene (SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2 entradas de 16 bits cada una. Los 4 bits superiores definen el tipo de reubicación, los 12 bits inferiores definen el desplazamiento en relación con el VirtualAddress.

Los únicos tipos que pueden ser usados en librerías son:

IMAGE_REL_BASED_ABSOLUTE (0)
Ninguna operación de reubicación.

IMAGE_REL_BASED_HIGHLOW (3)
Agregue el delta entre ImageBase y el bloque de memoria asignado a los 32 bits encontrados en el offset.

Resolviendo importaciones

La entrada de directorio 1 del 'DataDirectory' en 'OptionalHeader' especifica una lista de bibliotecas para importar símbolos. Cada entrada en esta lista se define de la siguiente manera:

Código: [Seleccionar]
Estruct IMAGE_IMPORT_DESCRIPTOR,_
        OriginalFirstThunk,_
        TimeDateStamp,_
        ForwarderChain,_
        Name,_
        FirstThunk:Entero

El miembro 'Name' describe el offset a una cadena terminada en nulo con el nombre de la librería (ej: KERNEL32.DLL). El miembro 'OriginalFirstThunk' apunta a una lista de referencias a los nombres de las funciones a importar de la librería externa. 'FirstThunk' apunta a una lista de direcciones que se llenó con punteros a los símbolos importados.

Cuando nosotros resolvemos las importaciones, nosotros recorremos ambas listas en paralelo, importando la función definida en la primera lista y almacenando el puntero en los símbolos de la segunda lista.

Código: [Seleccionar]
Var @NameRef,@SymbolRef:Entero
[email protected] = BaseAddress + ImportDes.OriginalFirstThunk
[email protected] = BaseAddress + ImportDes.FirstThunk

Mientras NameRef <> 0
    Var @ThunkData:IMAGE_IMPORT_BY_NAME
    [email protected] = CodeBase + NameRef
    SymbolRef = GetProcAddress(Handle,CadDePtr(ThunkData.Name))
    [email protected] = [email protected]@+4
    [email protected] = [email protected]@+4
FinMientras

Protegiendo la memoria

Cada sección especifica los indicadores de permiso en su entrada de características. Estas banderas pueden ser una o una combinación de

IMAGE_SCN_MEM_EXECUTE (&20000000)
Esta sección contiene datos que pueden ser ejecutados.

IMAGE_SCN_MEM_READ (&40000000)
Esta sección contiene datos que solo pueden ser leídos.

IMAGE_SCN_MEM_WRITE (&80000000)
Esta sección contiene datos que pueden ser escritos.

Estos indicadores deben asignarse a las banderas de protección

  • PAGE_NOACCESS (&1)
  • PAGE_WRITECOPY 8
  • PAGE_READONLY (&2)
  • PAGE_READWRITE (&4)
  • PAGE_EXECUTE (&10)
  • PAGE_EXECUTE_WRITECOPY (&80)
  • PAGE_EXECUTE_READ (&20)
  • PAGE_EXECUTE_READWRITE (&40)

Ahora, la función VirtualProtect puede ser usada para limitar el acceso a la memoria. Si el programa trata de escribir algo en un camino no autorizado, una excepción es generada por Windows.

Además de los indicadores de sección anteriores, se puede agregar los siguientes:

IMAGE_SCN_MEM_DISCARDABLE (&02000000)
Los datos en esta sección pueden ser liberados después de importar. Usualmente esta es especificada por los datos de reubicación.

IMAGE_SCN_MEM_NOT_CACHED (&04000000)
Los datos de esta sección no deben ser almacenados en caché por Windows. Agregue el indicador de bits PAGE_NOCACHE a los indicadores de protección anteriores.

Notificar librería

La ultima cosa que hacemos es llamar el punto de entrada de la DLL (definido por 'AddressOfEntryPoint') y por lo tanto notificar a la biblioteca acerca de estar conectado a un proceso.

La función de punto de entrada es definida como:

Código: [Seleccionar]
Prototipo EntryPoint(hInstance,dwReason,Reserved):Entero
Entonces el código que nosotros debemos ejecutar es:

Código: [Seleccionar]
Prototipo EntryPoint(hInstance,dwReason,Reserved):Entero

Var Entry:EntryPoint
[email protected] = BaseAddress + PEHeader.OptionalHeader.AddressOfEntryPoint
Entry(BaseAddress,DLL_PROCESS_ATTACH,0)

Después podemos utilizar las funciones exportadas como con cualquier biblioteca normal.

Funciones exportadas

Si usted quiere obtener acceso a las funciones que la librería exporta, necesita buscar el punto de entrada del simbolo, por ejemplo. El nombre de la función a llamar.

El directorio de entrada 0 de la 'DataDirectory' en la 'OptionalHeader' contiene información acerca de las funciones exportadas. Esta es definida como la siguiente estructura:

Código: [Seleccionar]
Estruct IMAGE_EXPORT_DIRECTORY,_
        Characteristics,_
        TimeDateStamp:Entero,_
        MajorVersion,_
        MinorVersion:Word,_
        Name,_
        Base,_
        NumberOfFunctions,_
        NumberOfNames,_
        AddressOfFunctions,_ ' RVA de Base.
        AddressOfNames,_     ' RVA de Base.
        AddressOfNameOrdinals:Entero ' RVA de Base.

Lo primero que debemos hacer es referenciar el nombre de la función al número ordinal del símbolo exportado. Por lo tanto, sólo sondear las matrices definidas por 'AddressOfNames' y 'AddressOfNameOrdinals' en paralelo hasta que encuentre el nombre necesario.

Ahora puede utilizar el número ordinal para leer la dirección evaluando el n-ésimo elemento de la matriz 'AddressOfFunctions'.

Liberando la libreria

Para liberar la librería cargada de manera personalizada, realice los siguientes pasos:

  • Llamar al punto de entrada para informar que la vamos a liberar.
Código: [Seleccionar]
Entry(BaseAddress,DLL_PROCESS_DETACH,0)
  • Liberar las librerías requeridas por la DLL que queríamos importar en realidad.
  • Liberar la memoria alojada por VirtualAlloc.

Citar
Este manual fue escrito por Joachim Bauch y traducido por Yuki para Underc0de.org.

Código fuente de ejemplo

10
Otros lenguajes / [Cramel] Librería MemDLL
« en: Agosto 05, 2017, 10:49:41 am »
Hace un tiempo largo descubrí que habia una manera de cargar librerías DLL directamente desde memoria, me profundice en el tema y logre crear una librería personalizada para Cramel, esta permitirá la libre creación de códigos portables.

Código: [Seleccionar]
Importar "Cramel.cml"

Estruct LIB_INFO,_
        Base,_ ' Dirección base de la librería en memoria.
        NumLibs,_ ' Número de librerías que esta importa.
        Librerías[]:Entero,_ ' Identificadores de las librerias importadas.
        @NT:IMAGE_NT_HEADERS,_ ' Cabecera PE.
        Inicializado:Booleano ' Establece si fue inicializado.

Prototipo LibEntryPoint(Instancia,Razón:Entero,Opcional Reservado:Entero):Entero

Proc FIELD_OFFSET(Estructura,Miembro:Entero):Entero
    Resultado = (Miembro - Estructura)
FinProc

Proc IMAGE_FIRST_SECTION(Referencia NT:IMAGE_NT_HEADERS):Entero
    Resultado = [email protected] + (FIELD_OFFSET([email protected],[email protected]) + NT.FileHeader.SizeOfOptionalHeader)
FinProc

Proc GET_HEADER_DICTIONARY(Mem:Entero,Indice:Byte):Entero
    Var @NT:IMAGE_NT_HEADERS
    [email protected] = GET_NT_HEADERS(Mem)
    Resultado = NT.OptionalHeader.DataDirectory[Indice]@
FinProc

Proc GET_DOS_HEADER(Mem:Entero):Entero
    Resultado = Mem
FinProc

Proc GET_NT_HEADERS(Mem:Entero):Entero
    Var @DOS_HEADER:IMAGE_DOS_HEADER
    [email protected] = GET_DOS_HEADER(Mem)
    Resultado = Mem + DOS_HEADER.e_lfanew
FinProc

Proc IMAGE_ORDINAL(Ordinal:Entero):Word
    Resultado = (Ordinal And &FFFF)
FinProc

Proc IMAGE_SNAP_BY_ORDINAL(Ordinal:Entero):Booleano
    Resultado = (Ordinal And IMAGE_ORDINAL_FLAG32)
FinProc

Proc GET_SECTION_PROTECTION(Characteristics:Entero):Entero
    Var Flag:Byte
    Si Characteristics And IMAGE_SCN_MEM_EXECUTE Entonces
        Flag = Flag + 1 ' Flag = 0 o 1
    FinSi
    Si Characteristics And IMAGE_SCN_MEM_READ Entonces
        Flag = Flag + 2 ' Flag = 1 o 2 o 3
    FinSi
    Si Characteristics And IMAGE_SCN_MEM_WRITE Entonces
        Flag = Flag + 3 ' Flag = 3 o 4 o 5 o 6
    FinSi
    Seleccionar Flag
        Caso 0 ' Nada :0
        Caso 1 ' Ejecutable
            Resultado = PAGE_EXECUTE
        Caso 2 ' Solo lectura
            Resultado = PAGE_READONLY
        Caso 3 ' Lectura y ejecutable
            Resultado = PAGE_EXECUTE_READ
        Caso 4 ' Ejecutable y editable
            Resultado = PAGE_EXECUTE_WRITECOPY
        Caso 5 ' Lectura y editable
            Resultado = PAGE_READWRITE
        Caso 6 ' Ejecutable, lectura y editable.
            Resultado = PAGE_EXECUTE_READWRITE
    FinSeleccionar
FinProc

' Copia las secciones del archivo en memoria.
Proc CopiarSecciones(Referencia Res:LIB_INFO,Referencia NT:IMAGE_NT_HEADERS,LibPtr:Entero)
    Var i:Entero
    Var @SECHeader:IMAGE_SECTION_HEADER
    Var Tamaño:Entero
    Var Des:Entero
    [email protected] = IMAGE_FIRST_SECTION(Res.NT)
    Contar i a (Res.NT.FileHeader.NumberOfSections - 1)
        Si SECHeader.SizeOfRawData = 0 Entonces
            Tamaño = NT.OptionalHeader.SectionAlignment
            Si Tamaño Entonces
                Des = VirtualAlloc(Res.Base + SECHeader.VirtualAddress,Tamaño,MEM_COMMIT,PAGE_READWRITE)
                SECHeader.Misc.PhysicalAddress = Des
                memset(Des,0,Tamaño)
            FinSi
        SiNo
            Des = VirtualAlloc(Res.Base + SECHeader.VirtualAddress,SECHeader.SizeOfRawData,MEM_COMMIT,PAGE_READWRITE)
            memcpy(Des,LibPtr + SECHeader.PointerToRawData,SECHeader.SizeOfRawData)
            SECHeader.Misc.PhysicalAddress = Des
        FinSi
        [email protected] = [email protected]@ + &IMAGE_SECTION_HEADER
    Seguir
FinProc

' Importamos las librerias requeridas por el archivo en memoria y registramos los procedimientos.
Proc RegImportaciones(Referencia Res:LIB_INFO):Booleano
    Var @Directorio:IMAGE_DATA_DIRECTORY
    Var @ImportDesc:IMAGE_IMPORT_DESCRIPTOR
    Var ResLoad:Entero
    Var @OrFirstThunk:Entero
    Var @ProcRef:Entero
    Var @ImgImport:IMAGE_IMPORT_BY_NAME
    [email protected] = GET_HEADER_DICTIONARY(Res.Base,IMAGE_DIRECTORY_ENTRY_IMPORT)
    Si Directorio.Size Entonces
        [email protected] = Res.Base + Directorio.VirtualAddress
        Mientras ImportDesc.Name
            ResLoad = LoadLibrary(CadDePtr(Res.Base + ImportDesc.Name))
            Si ImportDesc.OriginalFirstThunk Entonces
                [email protected] = Res.Base + ImportDesc.OriginalFirstThunk
            SiNo
                [email protected] = Res.Base + ImportDesc.FirstThunk
            FinSi
            [email protected] = Res.Base + ImportDesc.FirstThunk
            Mientras OrFirstThunk
                Si IMAGE_SNAP_BY_ORDINAL(OrFirstThunk) Entonces
                    ProcRef = GetProcAddress(ResLoad,EntCad(IMAGE_ORDINAL(OrFirstThunk)))
                SiNo
                    [email protected] = Res.Base + OrFirstThunk
                    ProcRef = GetProcAddress(ResLoad,CadDePtr(ImgImport.Name[0]@))
                FinSi
                Si ProcRef = 0 Entonces Salir Mientras
                [email protected] = [email protected]@ + &Entero
                [email protected] = [email protected]@ + &Entero
            FinMientras
            [email protected] = [email protected]@ + &IMAGE_IMPORT_DESCRIPTOR
            ' Almacenamos el identificador de la libreria cargada para ser liberada mas tarde.
            ReDim Preservar Res.Librerías,Res.NumLibs + 1
            Res.Librerías[Res.NumLibs] = ResLoad
            Res.NumLibs = Res.NumLibs + 1
        FinMientras
    FinSi
FinProc

' Liberamos las librerias importadas.
Proc LibImportaciones(Referencia Res:LIB_INFO):Booleano
    Var i:Entero
    Contar i a Res.NumLibs - 1
        Si Res.Librerías[i] <> INVALID_HANDLE_VALUE Entonces FreeLibrary(Res.Librerías[i])
    Seguir
FinProc

' Limpiamos de memoria las secciones y protegemos las que corresponden.
Proc LimpiarSecciones(Referencia Res:LIB_INFO)
    Var @SECHeader:IMAGE_SECTION_HEADER
    Var i:Entero
    Var Protección:Entero
    Var Tamaño:Entero
    [email protected] = IMAGE_FIRST_SECTION(Res.NT)
    Contar i a (Res.NT.FileHeader.NumberOfSections - 1)
        Si SECHeader.Characteristics And IMAGE_SCN_MEM_DISCARDABLE Entonces
            ' La sección es descartable, liberamos la memoria y retrocedemos a otra sección.
            VirtualFree(SECHeader.Misc.PhysicalAddress,SECHeader.SizeOfRawData,MEM_DECOMMIT)
            [email protected] = [email protected]@ - &IMAGE_SECTION_HEADER
        SiNo
            Protección = GET_SECTION_PROTECTION(SECHeader.Characteristics)
            Si SECHeader.Characteristics And IMAGE_SCN_MEM_NOT_CACHED Entonces Protección = Protección + PAGE_NOCACHE
            Tamaño = SECHeader.SizeOfRawData
            Si Tamaño Entonces
                Si SECHeader.Characteristics And IMAGE_SCN_CNT_INITIALIZED_DATA Entonces
                    Tamaño = Res.NT.OptionalHeader.SizeOfInitializedData
                OSi SECHeader.Characteristics And IMAGE_SCN_CNT_UNINITIALIZED_DATA Entonces
                    Tamaño = Res.NT.OptionalHeader.SizeOfUnitializedData
                FinSi
                Si Tamaño Entonces VirtualProtect(SECHeader.Misc.PhysicalAddress,SECHeader.SizeOfRawData,Protección)
            FinSi
        FinSi
        [email protected] = [email protected]@ + &IMAGE_SECTION_HEADER
    Seguir
FinProc

' Ajustamos las referencias de memoria.
Proc RelocaciónBase(Referencia Res:LIB_INFO)
    Var @Directorio:IMAGE_DATA_DIRECTORY
    Var @Reloc:IMAGE_BASE_RELOCATION
    Var @Des:Entero
    Var @RelocInfo:Word
    Var @Pos:Word
    Var i:Entero
    Var Tipo:Word
    [email protected] = GET_HEADER_DICTIONARY(Res.Base,IMAGE_DIRECTORY_ENTRY_BASERELOC)
    Si Directorio.Size Entonces
        [email protected] = Res.Base + Directorio.VirtualAddress
        Mientras Reloc.VirtualAddress
            [email protected] = [email protected]@ + IMAGE_SIZEOF_BASE_RELOCATION
            i = 0
            ' DIOS! COMO ME COSTO HACER ANDAR ESTE CÓDIGO!!
            ' PUT* Delphi, Put* C.
            Contar i a ((Reloc.SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2) - 1
                [email protected] = Res.Base + Reloc.VirtualAddress
                Si (RelocInfo Shr &C) = IMAGE_REL_BASED_HIGHLOW Entonces
                    [email protected] = [email protected]@ + (RelocInfo And &FFF)
                    Des = LOWORD(Des) + Res.Base
                FinSi
                [email protected] = [email protected]@ + &Word
            Seguir
            [email protected] = [email protected]@ + Reloc.SizeOfBlock
        FinMientras
    FinSi
FinProc

' Invocamos el punto de entrada.
Proc InvocarPuntoDeEntrada(Referencia Res:LIB_INFO,Bandera:Entero):Booleano
    Var @EntryPoint:LibEntryPoint
    Si Res.NT.OptionalHeader.AddressOfEntryPoint Entonces
        [email protected] = Res.Base + Res.NT.OptionalHeader.AddressOfEntryPoint
        Resultado = EntryPoint(Res.Base,Bandera,0)
        Res.Inicializado = Resultado
    FinSi
FinProc

Proc MemLoadLibrary(LibPtr:Entero):LIB_INFO

    Var @PEHeader:IMAGE_NT_HEADERS
    Var @DOSHeader:IMAGE_DOS_HEADER
    Var Headers:Entero
    Var Reubicar:Booleano
    Var LibBase:Entero
   
    [email protected] = GET_DOS_HEADER(LibPtr)
    [email protected] = GET_NT_HEADERS(LibPtr)
   
    Var Base:Entero
   
    Base = VirtualAlloc(PEHeader.OptionalHeader.ImageBase,PEHeader.OptionalHeader.SizeOfImage,MEM_RESERVE + MEM_COMMIT,PAGE_READWRITE)
   
    Si Base = 0 Entonces
        Base = VirtualAlloc(0,PEHeader.OptionalHeader.SizeOfImage,MEM_RESERVE + MEM_COMMIT,PAGE_READWRITE)
        Si Base = 0 Entonces Salir
        Reubicar = Verdadero
        LibBase = PEHeader.OptionalHeader.ImageBase
    FinSi
   
    ' Comprometemos la memoria para las cabeceras, esto se hacce re-invocando VirtualAlloc.
   
    Headers = VirtualAlloc(Base,PEHeader.OptionalHeader.SizeOfHeaders,MEM_COMMIT,PAGE_READWRITE)
   
    memcpy(Headers,LibPtr,DOSHeader.e_lfanew + PEHeader.OptionalHeader.SizeOfHeaders)
   
    Resultado.Base = Base
    [email protected] = [email protected]@
    Resultado.NT.OptionalHeader.ImageBase = Base
   
    CopiarSecciones(Resultado,PEHeader,LibPtr)
   
    Si Reubicar Entonces RelocaciónBase(Resultado)
   
    RegImportaciones(Resultado)
   
    LimpiarSecciones(Resultado)
   
    InvocarPuntoDeEntrada(Resultado,DLL_PROCESS_ATTACH)
   
    'VirtualFree(Base,0,MEM_RELEASE)
   
FinProc

Proc MemGetProcAddress(Referencia Modulo:LIB_INFO,Nombre:Cadena,Opcional Sensitivo:Booleano):Entero
    Var @Directorio:IMAGE_DATA_DIRECTORY
    Var @Export:IMAGE_EXPORT_DIRECTORY
    Var @NomRef:Entero
    Var @Ord:Word
    Var i:Entero
    Var iOrd:Entero
    Var @PtrProc:Entero
    iOrd = -1
    [email protected] = GET_HEADER_DICTIONARY(Modulo.Base,IMAGE_DIRECTORY_ENTRY_EXPORT)
    Si Directorio.Size Entonces
        [email protected] = Modulo.Base + Directorio.VirtualAddress
        Si (Export.NumberOfNames = 0) o (Export.NumberOfFunctions = 0) Entonces Salir
        [email protected] = Modulo.Base + Export.AddressOfNames
        [email protected] = Modulo.Base + Export.AddressOfNameOrdinals
        Contar i a Export.NumberOfNames - 1
            Si Sensitivo Entonces
                Si strcmp(CadDePtr(Modulo.Base + NomRef),Nombre) = 0 Entonces
                    iOrd = Ord
                    Salir Contar
                FinSi
            SiNo
                Si strcmpi(CadDePtr(Modulo.Base + NomRef),Nombre) = 0 Entonces
                    iOrd = Ord
                    Salir Contar
                FinSi
            FinSi
            NomRef = NomRef + &Entero
            Ord = Ord + &Word
        Seguir
        Si iOrd = -1 Entonces Salir
        Si iOrd > Export.NumberOfFunctions - 1 Entonces Salir
        [email protected] = (Modulo.Base + (Export.AddressOfFunctions + (iOrd * 4)))
        Resultado = Modulo.Base + PtrProc
    FinSi
FinProc

Proc MemFreeLibrary(Referencia Res:LIB_INFO)
    Var i:Entero
    Si Res.Inicializado Entonces
        InvocarPuntoDeEntrada(Res,DLL_PROCESS_DETACH)
        Res.Inicializado = Falso
        LibImportaciones(Res)
        Si Res.Base Entonces
            VirtualFree(Res.Base,0,MEM_RELEASE)
            Si [email protected]@ Entonces [email protected] = 0
            Res.Base = 0
            ReDim Res.Librerías,0
            Res.NumLibs = 0
        FinSi
    FinSi
FinProc

El código de ejemplo puede ser visto en PasteBin.

Debido a la corrección de errores del compilador, este código solo es funcional con la ultima versión de Cramel subida hoy 05/08/2017.

Este post es una referencia para la guia cargar DLL directamente de memoria.

¡Saludos!

11
C# - VB.NET / Re:FkN RAT SRC
« en: Julio 28, 2017, 10:57:18 pm »
Muy buen aporte, pero me gustaría que añadieras mas información en tus posts!

Saludos

12
Otros lenguajes / [Cramel] RunPE
« en: Julio 24, 2017, 12:44:52 am »
Hace un tiempo escribí este RunPE en Cramel, pero parece que olvide postearlo, así que acá se los dejo.

Código: [Seleccionar]
Importar "Cramel.cml"

' -------------------------------------------------------------------------------------------
' Nombre: RunPE
' Funcionamiento: Ejecuta un archivo en memoria.
' Programador: Yuki
' Parametros:
'            Archivo - Nombre del archivo a simular.
'            pArchivo - Puntero del buffer en memoria que contiene el archivo a ejecutar.
' Retorno:
'            Ninguno.

' -------------------------------------------------------------------------------------------
Proc RunPE(Referencia Archivo:Cadena,pArchivo:Entero)
    Var i:Entero
    Var @Pidh:IMAGE_DOS_HEADER
    Var @Pinh:IMAGE_NT_HEADERS
    Var @Pish:IMAGE_SECTION_HEADER
    Var SINFO:STARTUPINFO
    Var PINFO:PROCESS_INFORMATION
    Var Ctx:CONTEXT
    ' Iniciamos variables.
    SINFO.cb = &STARTUPINFO
    Ctx.ContextFlags = CONTEXT_FULL
    ' Obtenemos la estructura IMAGE_DOS_HEADER del archivo en memoria.
    [email protected] = pArchivo
    ' Obtenemos la estructura IMAGE_NT_HEADERS del archivo en memoria.
    [email protected] = pArchivo + Pidh.e_lfanew
    ' Creamos un nuevo proceso suspendido.
    CreateProcess(Archivo,"",,,Falso,CREATE_SUSPENDED,0,0,SINFO,PINFO)
    ' ???
    NtUnmapViewOfSection(PINFO.hProcess,Pinh.OptionalHeader.ImageBase)
    ' Creamos un buffer en el proceso creado con el tamaño del ejecutable en memoria.
    VirtualAllocEx(PINFO.hProcess,Pinh.OptionalHeader.ImageBase,Pinh.OptionalHeader.SizeOfImage,MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
    ' Escribimos en la memoria del proceso la cabecera del archivo en nuestra memoria.
    WriteProcessMemory(PINFO.hProcess,Pinh.OptionalHeader.ImageBase,pArchivo,Pinh.OptionalHeader.SizeOfHeaders,0)
    ' Sondeamos las secciones.
    Contar i a Pinh.FileHeader.NumberOfSections - 1
        ' Pish apunta a la información de las secciones disponibles.
        [email protected] = pArchivo + Pidh.e_lfanew + &IMAGE_NT_HEADERS + &IMAGE_SECTION_HEADER * i
        ' Escribimos los datos de las secciones.
        WriteProcessMemory(PINFO.hProcess,Pinh.OptionalHeader.ImageBase+Pish.VirtualAddress,pArchivo+Pish.PointerToRawData,Pish.SizeOfRawData,0)
    Seguir
    ' Obtenemos los valores de registros.
    GetThreadContext(PINFO.hThread,Ctx)
    ' Inicializamos los registros.
    WriteProcessMemory(PINFO.hProcess,Ctx.Ebx + 8,Pinh.OptionalHeader.ImageBase,4,0)
    Ctx.Eax = Pinh.OptionalHeader.ImageBase + Pinh.OptionalHeader.AddressOfEntryPoint
    SetThreadContext(PINFO.hThread,Ctx)
    ' Iniciamos el hilo del proceso creado.
    ResumeThread(PINFO.hThread)
FinProc

¡Saludos!

13
Otros lenguajes / [Cramel] Función DllCall
« en: Julio 23, 2017, 10:09:57 pm »
Les dejo un simple DllCall que escribí en Cramel utilizando asm inline, para los que no lo sepan, se utiliza para llamar funciones de manera dinámica.

Código: [Seleccionar]
Importar "Cramel.cml"

Proc DllCall(Dll,Función:Cadena,Referencia ParamArray[]:Entero):Entero
    !push DWORD[Param_Dll]
    !call [a_LoadLibrary]
    !test eax,eax
    !jz .Fin
    !mov ebx,eax
    !xor edx,edx
    !mov edi,DWORD[Param_ParamArray]
    !mov edi,DWORD[edi]
    !mov eax,DWORD[edi-4]
    !mov ecx,4
    !div ecx
    !mov ecx,eax
    !test ecx,ecx
    !jz .CallProc
    [email protected]@:
    !push DWORD[edi+ecx*4-4]
    !loop @b
    !.CallProc:
    !push DWORD[Param_Función]
    !push ebx
    !call [a_GetProcAddress]
    !test eax,eax
    !jz .Fin
    !call eax
    !.Fin:
FinProc

Var Parámetros[]:Entero
Var Str:Cadena
Var Str2:Cadena

Str = "Hola Mundo"
Str2 = "Title"

ReDim Parámetros,4

Parámetros[0] = 0
Parámetros[1] = [email protected]@
Parámetros[2] = [email protected]@
Parámetros[3] = 16

DllCall("User32","MessageBoxA",Parámetros)

¡Saludos!

14
Wargames y retos / Re:Reto - Descubre el valor oculto
« en: Julio 01, 2017, 11:53:02 pm »
A=2; B=3; C=6; D=8
ABCD = 2368

Es correcto, pero el chiste es programar  :'(

15
Wargames y retos / Reto - Descubre el valor oculto
« en: Julio 01, 2017, 08:07:03 am »
El día de ayer un amigo me enseñó una muy interesante cuestión matemática. El reto que les propongo es escribir y postear un código que les resuelva este acertijo. Pueden usar el lenguaje que quieran.


¡Suerte!

16
HOLA!!!

Gran Aporte @Yuki podria ponerla como libreria precargada en la prox version!

GRACIAS POR LEER!!!

Si, cuando la vi me puse manos a la obra, la modifique un poco y la documente. Solo falta que yo suba la nueva versión  :D

17
Otros lenguajes / Re:[Cramel] AdminFinder by 79137913 [Aplicación]
« en: Junio 26, 2017, 12:45:35 am »
Muy copada la aplicación, yo también estaba pensando en traducir los códigos de numéritos.

Me interesa ver el código fuente, espero con ansias la publicación!

salu2

18
Dudas y pedidos generales / Re:tabs o espacios
« en: Junio 23, 2017, 08:18:37 am »
El uso de espacio te genera malas practicas ya que en algunos lenguajes (la gran mayoría) te genera errores de sintaxis, ya que no se puede acceder a esa línea de código y genérandote errores.

Yo personalmente difiero, el uso de espacios no solo embellece el código sino que lo vuelve mas legible para el programador.

es buena practica de programacion usar 1 solo? porque no se pueden usar ambos? entiendo que en lenguajes como python solo se puede utilizar 1, pero por ejemplo Java? porque no ambos? porque tanto debate entre uno y otro?

Yo CREO que depende del gusto de los desarrolladores del lenguaje, yo por ejemplo, en Cramel no permití el uso de tabs (&09) fuera de una cadena constante por el simple hecho de que no todos los editores de textos le asignan la misma longitud (lo que producía que el código se desparejase y fuera incómodo leerlo o escribirlo), por lo que preferí que se utilizaran 4 espacios ("1 tab").

19
Antes de iniciar, me gustaría informar que en este post no se va a enseñar literalmente como programar en ensamblador sino que serán algunos consejos para aprender a escribir en lenguaje ensamblador sin problemas.

¿Que es ensamblador?
Ensamblador es básicamente el lenguaje más cercano al lenguaje maquina, utilizado por desarrolladores avanzados para escribir aplicaciones con alto nivel de rendimiento.

¿Como puedo aprender a programar en ensamblador de manera más fácil?
Pues esto es muy simple y la mejor manera de hacerlo es comprender que ensamblador consta de unos cuantos items.

  • Etiquetas
  • Registros
  • Instrucciones

Etiquetas
Las etiquetas son identificadores (nombres, alias, apodos, etc) que se les asigna a una porción de nuestro código (aveces a todo) de tal manera que nosotros podamos (valga la redundancia) identificar nuestro código ensamblador.

Estas etiquetas son muy utilizadas con instrucciones de salto.

Registros
Los registros son secciones internas de almacenamiento, si usted a programado en Cramel puede interpretar los registros como variables de tipo Entero (4 Bytes - x32 | 8 Bytes - x64).

Cualquier lenguaje de programación basado en la sintaxis de los procesadores Intel de 32 bits posee 9 registros.

  • EAX (A-cumulator) - Utilizado para retornar valores de procedimientos y almacenar valores que sera procesados por cálculos aritméticos.
  • EBX (B-ase) - Utilizado como apoyo para realizar cálculos, algunas instrucciones no dejan procesar valores directamente, se asigna el valor a ebx y se utiliza junto a la instrucción.
  • ECX (C-ounter) - Contador para bucles y registro de apoyo para cálculos o procesos lógicos (como la rotación de bits).
  • EDX (D-ata)- Utilizado mayormente para pasar parámetros a procedimientos con método de llamada como FASTCALL.
  • ESI (Source Index) - Utilizado generalmente como puntero para escribir en memoria.
  • EDI (Destination Index) - Utilizado generalmente como puntero para escribir en memoria.
  • EBP (Base Pointer) - Este registro generalmente apunta a la base de la pila y es utilizado por los procedimientos para apuntar a una nueva sección de la pila.
  • ESP (Stack Pointer) - Utilizado para almacenar la base previa de la pila y como referencia de escritura de la pila.
  • EIP (Instruction Pointer) - Almacena la dirección de la instrucción actualmente siendo procesada.
Usted puede utilizar estos registros para su propósito original o preservarlos en la pila para usarlos como desee.

Instrucciones
A diferencia de las instrucciones de lenguajes de alto nivel, las instrucciones de ensamblador solo realizan su única tarea asignada, por ejemplo, si quisiéramos declarar una sentencia "If/Si" tendríamos que primero escribir la instrucción para comparar y después la instrucción para saltar "en caso de".

Para su mejor memorización se pueden buscar por internet la descripción extendidas de los mnemónicos, por ejemplo:

  • jmp - Jump
  • jne - Jump Not Equal
  • jae - Jump Above Equal
  • jbe - Jump Below Equal
  • jb - Jump Below
  • ja - Jump Above
  • je - Jump Equal
  • jz - Jump Zero
  • js - Jump Sign
  • shl - Shift Left
  • shr - Shift Right
  • mov - Move
  • xchg - Change
  • movzx - Move Zero Extended

[Ultimo] Optimización
Las instrucciones ensamblador son representadas por el compilador a sus correspondientes opcodes, pero hay maneras de minimizar y por lo tanto aumentar la velocidad de ejecución de nuestro código ensamblador.

Supongamos que queremos limpiar el registro EAX, estableciéndolo a cero, la manera mas común seria hacer lo siguiente:

Código: (asm) [Seleccionar]
mov eax,0 ; B8 00 00 00 00 | 6 Bytes.
Pero la manera más optima de realizar esta misma tarea es utilizando XOR.

Código: (asm) [Seleccionar]
xor eax,eax ; 33 C0 | 2 Bytes.
O si quisieramos realizar una comparación en un registro, lo mas normal es:

Código: (asm) [Seleccionar]
cmp eax,1 ; 83 F8 01 | 3 Bytes.
Aunque más eficiente es:

Código: (asm) [Seleccionar]
test eax,eax ; 85 C0 | 2 Bytes.
Únete a los grupos de Underc0de!


Para ver la infografia visita Tips informáticos! - [Caído]

Saludos!

Páginas: [1] 2 3 4