Autor
|
Tema: De Perl a C (Leído 25,758 veces)
|
krootca
Desconectado
Mensajes: 4
|
Hola buenas tardes, he estado intentando convertir este código de Perl a C en una función llama pvepush, pero aun no logro que la salida de código sea similar a la de Perl, básicamente este código de Perl sirve para convertir cadenas de texto en un direcciones para la pila, me gustaría que me den alguna ayuda para que el código funcione de manera similar al de Perl: El código de C es este: void pvepush(char* strToPush) { if (strlen(strToPush) == 0) { printf("usage: pvepush \"String to put on stack\"\n"); return; } printf("String length: %ld\n", strlen(strToPush)); printf("Opcodes to push this string onto the stack:\n\n"); int cnt = 0; int bytecnt = 0; char strHex[13] = ""; char strOpcodes[1000] = ""; char strPush[100] = ""; while (cnt < strlen(strToPush)) { char strThisChar[5]; sprintf(strThisChar, "\\x%02x", strToPush[cnt]); if (bytecnt < 3) { strcat(strHex, strThisChar); bytecnt++; } else { if (strlen(strHex) < 12) { strcat(strHex, "\\x20"); } sprintf(strPush, "\"\\x68%s\" //PUSH 0x%s%s%s%s\n", strHex, &strHex[8], &strHex[6], &strHex[4], &strHex[2]); strcat(strOpcodes, strPush); strcpy(strHex, ""); bytecnt = 0; } cnt++; } if (strlen(strHex) > 0) { sprintf(strPush, "\"\\x68%s\\x00\" //PUSH 0x%s%s%s%s\n", strHex, &strHex[8], &strHex[6], &strHex[4], &strHex[2]); strcat(strOpcodes, strPush); } else { strcat(strOpcodes, "\"\\x68\\x20\\x20\\x20\\x00\" //PUSH 0x00202020\n"); } printf("%s", strOpcodes); }
El código de Perl es este: # Este script toma una cadena como argumento # y producirá los opcodes # para empujar esta string a la pila. use strict; use warnings; # Comprobar que se proporcionó un argumento if ($#ARGV ne 0) { print " usage: $0 ".chr(34)."String to put on stack".chr(34)."\n"; } # Convertir la cadena a bytes my $strToPush = $ARGV[0]; my $strThisChar = ""; my $strThisHex = ""; my $cnt = 0; my $bytecnt = 0; my $strHex = ""; my $strOpcodes = ""; my $strPush = ""; # Imprimir la longitud de la cadena # Iterar a través de cada carácter en la cadena while ($cnt < length($strToPush)) { # Obtener el siguiente carácter de la cadena $strThisChar = substr($strToPush, $cnt, 1); # Convertir el carácter a su representación hexadecimal $strThisHex = "\\x".ascii_to_hex($strThisChar); # Agregar el carácter hexadecimal a la cadena de hexadecimales if ($bytecnt < 3) { $strHex .= $strThisHex; $bytecnt++; } else { # Imprimir la cadena de hexadecimales y el opcode PUSH $strPush = $strHex.$strThisHex; $strPush =~ tr/\\x//d; $strOpcodes .= chr(34)."\\x68".$strHex.$strThisHex.chr(34). $strHex = ""; $bytecnt = 0; } # Incrementar el contador de caracteres $cnt++; } # Imprimir la última línea de opcodes # Agregar espacios a la cadena de hexadecimales para completar los 12 bytes while (length($strHex) < 12) { $strHex .= "\\x20"; } # Imprimir la cadena de hexadecimales y el opcode PUSH $strPush = $strHex.$strThisHex; $strPush =~ tr/\\x//d; $strOpcodes .= chr(34)."\\x68".$strHex.$strThisHex.chr(34). } else { # Agregar la línea con espacios + el byte nulo (terminador de cadena) $strOpcodes .= chr(34)."\\x68\\x20\\x20\\x20\\x00".chr(34). " //PUSH 0x00202020"."\n"; } # Imprimir los opcodes generados # Función para convertir un carácter ASCII a hexadecimal sub ascii_to_hex ($) { (my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg; }
Con respecto a la salida de código despues de compilar y pasarle un string "hola" en el script de C: String length: 4 Opcodes to push this string onto the stack: "\x68\x68\x6f\x6c" //PUSH 0x\x6c6f\x6c\x6f\x6c68\x6f\x6c "\x68\x20\x20\x20\x00" //PUSH 0x00202020
Con la salida de Perl con el mismo string "hola": String length : 4 "\x68\x68\x6f\x6c\x61" //PUSH 0x616c6f68 "\x68\x20\x20\x20\x00" //PUSH 0x00202020
Nota: El código de Perl es de Peter Van Eeckhoutte
|
|
« Última modificación: 30 Agosto 2023, 21:46 pm por krootca »
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Algo así. No entendí lo de los 12 bytes ni la línea con espacios. void pvepush(char* strToPush) { char strOpcodes[1024] = "\"\\x68"; char strHex[6]; size_t strToPush_len = strlen(strToPush ); if (strToPush_len == 0) { printf("usage: pvepush \"String to put on stack\"\n"); return; } printf("String length: %ld\n", strToPush_len ); printf("Opcodes to push this string onto the stack:\n\n"); for(size_t i = 0; i < strToPush_len; ++i) { sprintf(strHex , "\\x%x", strToPush [i ]); } strcat(strOpcodes , "\" //PUSH "); for(size_t i = strToPush_len; i > 0; --i) { sprintf(strHex , "%x", strToPush [i -1]); } }
|
|
|
En línea
|
|
|
|
krootca
Desconectado
Mensajes: 4
|
El código es funcional, pero con respecto al al código de perl, por ejemplo en perl sale algo así al agregar una linea caracter más, osea "holaa": String length : 5 Opcodes to push this string onto the stack : "\x68\x61\x20\x20\x00" //PUSH 0x00202061 "\x68\x68\x6f\x6c\x61" //PUSH 0x616c6f68
En cambio con respecto al código c "holaa": String length: 5 Opcodes to push this string onto the stack: "\x68\x68\x6f\x6c\x61\x61" //PUSH 61616c6f68
El objetivo es que no pierda la funcionalidad del código que hizo Peter Van Eeckhoutte, basicamente transladarlo al codigo en C, he hecho una versión del código de Peter en Perl comentada linea por linea para explicar el funcionamiento del código: #!/usr/bin/perl # Scrit de Perl escrito por Peter Van Eeckhoutte # http://www.corelan.be:8800 # Este script toma una string como argumento # y producirá los opcodes # para empujar esta string a la pila. # # La primera línea, if ($#ARGV ne 0), verifica si el usuario ha proporcionado algún argumento # al programa. Si el usuario no ha proporcionado ningún argumento, # el programa imprimirá un mensaje de uso y se cerrará. if ($#ARGV ne 0) { print " usage: $0 ".chr(34)."String to put on stack".chr(34)."\n"; } ############## # Las siguientes líneas con variables # de convertir string a bytes # my $strToPush=$ARGV[0], my $strThisChar="", my $strThisHex="", my $cnt=0, my $bytecnt=0, my $strHex="", my $strOpcodes="", y my $strPush="" # declaran algunas variables e inicializan sus valores. # La variable $strToPush almacenará la cadena que el usuario ha proporcionado como argumento. my $strToPush=$ARGV[0]; #argumento que el usuario proporcionó my $strThisChar=""; #caracter actual my $strThisHex=""; #representacion hexadecimal my $cnt=0; # se utilizará para hacer un bucle while my $bytecnt=0; # recuento de bytes my $strHex=""; # la representación hex de los tres bytes actuales my $strOpcodes=""; # el texto que proximamente va almacenar los opcodes my $strPush=""; # el texto que almacenara la cadena de instrucciones # Las variables $strThisChar, $strThisHex, $cnt, $bytecnt, $strHex, y $strOpcodes # se utilizarán para almacenar el carácter actual, su representación hexadecimal, el recuento de bytes actual, # la representación hexadecimal de los tres bytes actuales, y la cadena de instrucciones, respectivamente. ############## ############## # La siguiente línea, print "String length : " . length($strToPush), imprime la longitud de la cadena en la consola. print "Numero de strings : " . length($strToPush)."\n"; # La siguiente línea, print "Opcodes to push this string onto the stack :\n\n", imprime un mensaje en la consola indicando que las siguientes líneas imprimirán las instrucciones para empujar la cadena a la pila. print "Opcodes para pushear estos strings en el stack :\n\n"; ############## ############## # El bucle while, while ($cnt < length($strToPush)) itera sobre los caracteres de # la cadena. Para cada carácter, se realizan los siguientes pasos: # 1- El carácter actual se almacena en la variable $strThisChar. # 2- La representación hexadecimal del carácter actual se almacena en la variable $strThisHex. # 3- El recuento de bytes se incrementa. # 4- Si el recuento de bytes es menor que 3, la representación hexadecimal del carácter actual se agrega a la variable $strHex. # 5- De lo contrario, la representación hexadecimal de los tres bytes actuales se almacena en la variable $strPush. Los caracteres en $strPush se convierten luego a sus representaciones ASCII y la cadena resultante se almacena de vuelta en $strPush. La representación hexadecimal de los tres bytes actuales también se agrega a la variable $strOpcodes. # 6- El recuento de bytes se reinicia a 0. # 7- El contador $cnt se incrementa. # 8- El bucle while continúa hasta que se alcanza el final de la cadena. # Finalmente, la cadena de instrucciones se imprime en la consola while ($cnt < length($strToPush)){ #itera para cada caracter $strThisChar=substr($strToPush,$cnt,1); #caracter actual $strThisHex="\\x".ascii_to_hex($strThisChar); #representacion hex del caracter actual if ($bytecnt < 3){ #si el recuento de bytes es menor a 3 entra aqui $strHex=$strHex.$strThisHex; # la representación hexadecimal del carácter actual se agrega a la variable $strHex. $bytecnt=$bytecnt+1; #el recuento de bytes aumenta en 1 ############## #La primera línea, }else{, se ejecuta si la variable $strHex está vacía. #Esto significa que el bucle while no se ejecutó y la variable $strHex no se llenó con la representación hexadecimal de la cadena. }else{ $strPush = $strHex.$strThisHex; #combinan la representación hexadecimal de la cadena actual ($strThisHex) con la representación hexadecimal que se ha acumulado hasta el momento ($strHex). $strPush =~ tr/\\x//d; #convierte la representación hexadecimal de la cadena en su representación ASCII. Esto se hace para que la cadena se pueda imprimir en la consola. ######## # La siguiente linea $strHex crea una nueva cadena que representa la instrucción PUSH para la cadena actual # La cadena comienza con el carácter ", seguido de la representación hexadecimal de la instrucción PUSH, # seguida de la representación hexadecimal de la cadena actual, seguida del carácter"`. # # La cadena también incluye un comentario que indica el valor hexadecimal de la cadena actual. ######### $strOpcodes=$strHex."\n".$strOpcodes; #agrega la nueva cadena a la variable $strOpcodes. La variable $strOpcodes contiene una cadena de todas las instrucciones PUSH que se han generado. $strHex="";#borra la variable $strHex para prepararla para la siguiente cadena. $bytecnt=0; #reinicia el recuento de bytes } $cnt=$cnt+1; #aumenta el valor para para el bucle } ############## # Esta línea verifica si la variable $strHex no está vacía. Si no está vacía, entonces se ejecutará el siguiente código: ######## # Este bucle while asegura que la variable $strHex tenga una longitud de 12. Si la longitud de $strHex es menor que 12, # entonces el carácter \x20 (que es un carácter de espacio en hexadecimal) se agrega a $strHex hasta que la longitud sea 12. $strHex=$strHex."\\x20"; } ######## # Estas dos siguientes líneas convierten la representación hexadecimal de la cadena en # $strHex a su representación ASCII y la almacenan en la variable $strPush. $strPush = $strHex; $strPush =~ tr/\\x//d; ############### ##### Esta línea crea una nueva cadena que contiene la representación hexadecimal del opcode PUSH, seguido de la representación ##### hexadecimal de la cadena en $strHex, seguido de un byte NULL (\x00). ##### ##### La representación hexadecimal de la cadena en ##### $strHex se obtiene tomando los primeros cuatro caracteres de $strPush, los siguientes dos caracteres de $strPush y los ##### últimos dos caracteres de $strPush. $strHex=chr(34)."\\x68".$strHex."\\x00".chr(34)." //PUSH 0x00".substr($strPush,4,2).substr($strPush,2,2).substr($strPush,0,2); #generar una instrucción PUSH que empuja un byte NULL a la pila. ############### #### agrega la nueva cadena a la variable $strOpcodes. La variable $strOpcodes contiene una cadena de todas las instrucciones PUSH que se han generado. $strOpcodes=$strHex."\n".$strOpcodes; ################ ################ }else{ #se ejecuta si la variable $strHex está vacía # Esta cadena representa la representación hexadecimal del opcode PUSH, seguido de cuatro espacios seguido de un byte NULL. $strOpcodes=chr(34)."\\x68\\x20\\x20\\x20\\x00".chr(34)." //PUSH 0x00202020"."\n".$strOpcodes; } print $strOpcodes; #imprime el valor de la variable $strOpcodes a la consola. ############ # se utiliza para convertir una cadena a su representación hexadecimal. # La función toma una cadena como argumento y devuelve una nueva cadena # que contiene la representación hexadecimal de la cadena original. sub ascii_to_hex ($){ # Esta siguente línea convierte la cadena que se pasa como argumento a su representación hexadecimal. # La expresión regular (.|\n) hace coincidir cualquier carácter, incluyendo el carácter de nueva línea (\n). # La función sprintf() formatea el resultado de la expresión regular como un número hexadecimal de dos caracteres. (my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg; } ############
|
|
|
En línea
|
|
|
|
explorer
Desconectado
Mensajes: 102
Analista/Programador Perl
|
En esta línea: sprintf(strPush , "\"\\x68%s\" //PUSH 0x%s%s%s%s\n", strHex , &strHex [8], &strHex [6], &strHex [4], &strHex [2]);
estás pasando la dirección de inicio de strHex, strHex[8], strHex[6]... como cadenas de caracteres (%s), pero no estás indicando cuántos caracteres de largo tienen esas cadenas de caracteres. Quizás debería ser sprintf(strPush , "\"\\x68%s\" //PUSH 0x%2s%2s%2s%2s\n", ...
En el código Perl aparecen recortados a 2 caracteres:
|
|
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Entonces en tu ejemplo original en vez de String length : 4 "\x68\x68\x6f\x6c\x61" //PUSH 0x616c6f68 "\x68\x20\x20\x20\x00" //PUSH 0x00202020 Debería ser String length : 4 "\x68\x20\x20\x20\x00" //PUSH 0x00202020 "\x68\x68\x6f\x6c\x61" //PUSH 0x616c6f68
Porque el byte '\x00' debe ir siempre en la primera línea en la última posición.
Un bonito ejercicio. Creo que esto hace lo que pides: #include <stdlib.h> #include <stdio.h> #include <string.h> // para cortar la cadena en CHUNK bytes #define CHUNK 4 char *strNormalizer(const char *); char *hexLeftToRight(const char *); char *hexRightToLeft(const char *); void pvepush(char *strToPush) { // aloja el resultado char strOpcodes[1024] = ""; // contiene espacio necesario para alojar la cadena representativa del byte en hexadecimal char *aux; // contiene una copia de strToPush con un tamaño múltiplo de CHUNK char *normalizedStr; // tamaño de la cadena strToPush size_t strToPush_len = strlen(strToPush ); // tamaño de la cadena normalizada size_t normalized_len; // La cadena argumento está vacía. Avisar y regresar. if (strToPush_len == 0) { printf("usage: pvepush \"String to put on stack\"\n"); return; } printf("String length: %ld\n", strToPush_len ); printf("Opcodes to push this string onto the stack:\n\n"); // Normaliza la cadena strToPush y obtiene el tamaño total normalizedStr = strNormalizer(strToPush); normalized_len = strlen(normalizedStr ) + 1; // Bucle. Va tomando CHUNK bytes desde el final hasta el inicio for(int i = normalized_len - CHUNK; i >= 0; i -= CHUNK) { // dato fijo strcat(strOpcodes , "\"\\x68"); // concatena el trozo obtenido con los bytes de izquierda a derecha aux = hexLeftToRight(&normalizedStr[i]); // dato fijo strcat(strOpcodes , "\" //PUSH 0x"); // concatena el trozo obtenido con los bytes de derecha a izquierda aux = hexRightToLeft(&normalizedStr[i]); // dato fijo } // Muestra el resultado } // Normaliza la cadena original adaptándola a un tamaño múltiplo de CHUNK. Rellena con espacios por la derecha. char *strNormalizer(const char *original) { size_t original_len = strlen(original ); size_t retValue_len; char *retValue; retValue_len = original_len + (CHUNK - original_len % CHUNK); retValue = calloc(retValue_len , sizeof(char)); for(int i = original_len; i < retValue_len - 1; ++i) { retValue[i] = ' '; } return retValue; } // Devuelve una cadena representando en hexadecimal los bytes de la cadena original. // El sentido será el mismo que el de la cadena original. // Cada byte tendrá el prefijo \x char *hexLeftToRight(const char *original) { char *retValue = malloc(6 * CHUNK * sizeof(char)); char strHex[6]; for(size_t i = 0; i < CHUNK; ++i) { sprintf(strHex , "\\x%.2x", original [i ]); } return retValue; } // Devuelve una cadena representando en hexadecimal los bytes de la cadena original. // El sentido inverso a la cadena original. char *hexRightToLeft(const char *original) { char *retValue = malloc(3 * CHUNK * sizeof(char)); char strHex[3]; for(size_t i = CHUNK; i > 0; --i) { sprintf(strHex , "%.2x", original [i -1]); } return retValue; } int main() { pvepush("hola"); }
Aunque lo veo un poco tocho, seguro que se puede optimizar más.
|
|
« Última modificación: 31 Agosto 2023, 23:55 pm por Eternal Idol »
|
En línea
|
|
|
|
krootca
Desconectado
Mensajes: 4
|
La verdad que te ha salido bastante bien @MAFUS, sin embargo hay en el script de Perl algo más: -Cuando supera 3 caracteres hace un nuevo push, ejemplo: ; Al principio siempre pone \x68, seguido de el hex del string: # string "ñ" \x68[\xf1]\x20\x20\x00 invertido 00 20 20 [f1] # string "ña" \x68[\xf1\x61]\x20\x00 invertido 00 20 [61 f1] # string "ñap" \x68[\xf1\x61\x70]\x00 invertido 00 [70 61 f1] ; Cuando supera los 3 caracteres hace esto: por ejemplo aqui le puse "ñapa" # \x68\x20\x20\x20\x00 invertido 00 20 20 20 # string "ñapa" \x68[\xf1\x61\x70\x61] invertido [61 70 61 f1] ; y cuando pasa los 4 caracteres, pasa esto: # \x68\xf6\x20\x20\x00 invertido 00 20 20 [f6] # string "ñapal" \x68[\xf1\x61\x70\x61] invertido 61 70 61 f1] ; la secuencia se repite, nuevamente cuando pasa los 7 caracteres, para llegar a 8 hace lo mismo que cuando pasa los 3 caracteres
|
|
« Última modificación: 1 Septiembre 2023, 23:25 pm por krootca »
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Creo que eso está resuelto:
Entrada: abc
Salida: String length: 3 Opcodes to push this string onto the stack:
"\x68\x61\x62\x63\x00" //PUSH 0x00636261
Entrada: abcd
Salida: String length: 4 Opcodes to push this string onto the stack:
"\x68\x20\x20\x20\x00" //PUSH 0x00202020 "\x68\x61\x62\x63\x64" //PUSH 0x64636261
Entrada: abcde
Salida: String length: 5 Opcodes to push this string onto the stack:
"\x68\x65\x20\x20\x00" //PUSH 0x00202065 "\x68\x61\x62\x63\x64" //PUSH 0x64636261
|
|
|
En línea
|
|
|
|
krootca
Desconectado
Mensajes: 4
|
Oh ya, ahora lo probé, me había confundido con otro script que me pertenecia  , la verdad que bastante bien hecho! 
|
|
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Resuelto un bug por el que el programa sacaba basura cuando se compilaba y ejecutaba en Windows. Cambiada la función de malloc por calloc en hexLeftToRight y hexRightToLeft. #include <stdlib.h> #include <stdio.h> #include <string.h> // para cortar la cadena en CHUNK bytes #define CHUNK 4 char *strNormalizer(const char *); char *hexLeftToRight(const char *); char *hexRightToLeft(const char *); void pvepush(char *strToPush) { // aloja el resultado char strOpcodes[1024] = ""; // contiene espacio necesario para alojar la cadena representativa del byte en hexadecimal char *aux; // contiene una copia de strToPush con un tamaño múltiplo de CHUNK char *normalizedStr; // tamaño de la cadena strToPush size_t strToPush_len = strlen(strToPush ); // tamaño de la cadena normalizada size_t normalized_len; // La cadena argumento está vacía. Avisar y regresar. if (strToPush_len == 0) { printf("usage: pvepush \"String to put on stack\"\n"); return; } printf("String length: %ld\n", strToPush_len ); printf("Opcodes to push this string onto the stack:\n\n"); // Normaliza la cadena strToPush y obtiene el tamaño total normalizedStr = strNormalizer(strToPush); normalized_len = strlen(normalizedStr ) + 1; // Bucle. Va tomando CHUNK bytes desde el final hasta el inicio for(int i = normalized_len - CHUNK; i >= 0; i -= CHUNK) { // dato fijo strcat(strOpcodes , "\"\\x68"); // concatena el trozo obtenido con los bytes de izquierda a derecha aux = hexLeftToRight(&normalizedStr[i]); // dato fijo strcat(strOpcodes , "\" //PUSH 0x"); // concatena el trozo obtenido con los bytes de derecha a izquierda aux = hexRightToLeft(&normalizedStr[i]); // dato fijo } // Muestra el resultado } // Normaliza la cadena original adaptándola a un tamaño múltiplo de CHUNK. Rellena con espacios por la derecha. char *strNormalizer(const char *original) { size_t original_len = strlen(original ); size_t retValue_len; char *retValue; retValue_len = original_len + (CHUNK - original_len % CHUNK); retValue = calloc(retValue_len , sizeof(char)); for(int i = original_len; i < retValue_len - 1; ++i) { retValue[i] = ' '; } return retValue; } // Devuelve una cadena representando en hexadecimal los bytes de la cadena original. // El sentido será el mismo que el de la cadena original. // Cada byte tendrá el prefijo \x char *hexLeftToRight(const char *original) { char *retValue = calloc(6 * CHUNK , sizeof(char)); char strHex[6]; for(size_t i = 0; i < CHUNK; ++i) { sprintf(strHex , "\\x%.2x", original [i ]); } return retValue; } // Devuelve una cadena representando en hexadecimal los bytes de la cadena original. // El sentido inverso a la cadena original. char *hexRightToLeft(const char *original) { char *retValue = calloc(3 * CHUNK , sizeof(char)); char strHex[3]; for(size_t i = CHUNK; i > 0; --i) { sprintf(strHex , "%.2x", original [i -1]); } return retValue; } int main() { pvepush("hola"); }
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Libros de Perl online [PERL]
Scripting
|
madpitbull_99
|
0
|
4,167
|
18 Mayo 2011, 21:49 pm
por madpitbull_99
|
|
|
[Perl] Creacion de un Joiner en Perl
Scripting
|
BigBear
|
0
|
3,138
|
15 Marzo 2013, 16:12 pm
por BigBear
|
|
|
[PERL]Busco recomendacion para empezar con Perl
Scripting
|
Ocelot1994
|
1
|
2,792
|
6 Julio 2016, 10:59 am
por explorer
|
|
|
[Perl] Salió Perl v5.28
Scripting
|
explorer
|
2
|
2,869
|
26 Junio 2018, 22:23 pm
por explorer
|
|
|
Perl v5.40
Scripting
|
explorer
|
0
|
3,119
|
11 Junio 2024, 12:12 pm
por explorer
|
|