Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: 85 en 22 Febrero 2013, 03:51 am



Título: Cadena de bytes a string
Publicado por: 85 en 22 Febrero 2013, 03:51 am
Bueno , en realidad el título puede que no lo exprese tal como es..
En este tema alguien había preguntado cómo se pasaba de un array de bytes a convertirlo en un array de chares por decirlo así, y la operación inversa también.
http://foro.elhacker.net/programacion_cc/variable_char_a_byte-t383683.0.html

Entonces usando una lógica que suelo utilizar, lo que hice fue crear una tabla con los 256 bytes, en realidad dos tablas. Una para obtener los bytes y la otra para obtener la posición de un byte en la tabla.
Luego de eso fue tan sólo crear 2 funciones separadas que hagan las operaciones, la una y la inversa, y probarlo

Código:
/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////
/////////////////////////////////////

char* hextabla[] = { //256 BYTES
"00","01","02","03","04","05","06","07","08","09",
"0A","0B","0C","0D","0E","0F","10","11","12","13",
"14","15","16","17","18","19","1A","1B","1C","1D",
"1E","1F","20","21","22","23","24","25","26","27",
"28","29","2A","2B","2C","2D","2E","2F","30","31",
"32","33","34","35","36","37","38","39","3A","3B",
"3C","3D","3E","3F","40","41","42","43","44","45",
"46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59",
"5A","5B","5C","5D","5E","5F","60","61","62","63",
"64","65","66","67","68","69","6A","6B","6C","6D",
"6E","6F","70","71","72","73","74","75","76","77",
"78","79","7A","7B","7C","7D","7E","7F","80","81",
"82","83","84","85","86","87","88","89","8A","8B",
"8C","8D","8E","8F","90","91","92","93","94","95",
"96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9",
"AA","AB","AC","AD","AE","AF","B0","B1","B2","B3",
"B4","B5","B6","B7","B8","B9","BA","BB","BC","BD",
"BE","BF","C0","C1","C2","C3","C4","C5","C6","C7",
"C8","C9","CA","CB","CC","CD","CE","CF","D0","D1",
"D2","D3","D4","D5","D6","D7","D8","D9","DA","DB",
"DC","DD","DE","DF","E0","E1","E2","E3","E4","E5",
"E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9",
"FA","FB","FC","FD","FE","FF",
};
//////////////

BYTE poshextabla[] = { //256 BYTES
/*1*/(BYTE)'\x00',(BYTE)'\x01',(BYTE)'\x02',(BYTE)'\x03',(BYTE)'\x04',(BYTE)'\x05',(BYTE)'\x06',(BYTE)'\x07',(BYTE)'\x08',(BYTE)'\x09',
/*2*/(BYTE)'\x0A',(BYTE)'\x0B',(BYTE)'\x0C',(BYTE)'\x0D',(BYTE)'\x0E',(BYTE)'\x0F',(BYTE)'\x10',(BYTE)'\x11',(BYTE)'\x12',(BYTE)'\x13',
/*3*/(BYTE)'\x14',(BYTE)'\x15',(BYTE)'\x16',(BYTE)'\x17',(BYTE)'\x18',(BYTE)'\x19',(BYTE)'\x1A',(BYTE)'\x1B',(BYTE)'\x1C',(BYTE)'\x1D',
/*4*/(BYTE)'\x1E',(BYTE)'\x1F',(BYTE)'\x20',(BYTE)'\x21',(BYTE)'\x22',(BYTE)'\x23',(BYTE)'\x24',(BYTE)'\x25',(BYTE)'\x26',(BYTE)'\x27',
/*5*/(BYTE)'\x28',(BYTE)'\x29',(BYTE)'\x2A',(BYTE)'\x2B',(BYTE)'\x2C',(BYTE)'\x2D',(BYTE)'\x2E',(BYTE)'\x2F',(BYTE)'\x30',(BYTE)'\x31',
/*6*/(BYTE)'\x32',(BYTE)'\x33',(BYTE)'\x34',(BYTE)'\x35',(BYTE)'\x36',(BYTE)'\x37',(BYTE)'\x38',(BYTE)'\x39',(BYTE)'\x3A',(BYTE)'\x3B',
/*7*/(BYTE)'\x3C',(BYTE)'\x3D',(BYTE)'\x3E',(BYTE)'\x3F',(BYTE)'\x40',(BYTE)'\x41',(BYTE)'\x42',(BYTE)'\x43',(BYTE)'\x44',(BYTE)'\x45',
/*8*/(BYTE)'\x46',(BYTE)'\x47',(BYTE)'\x48',(BYTE)'\x49',(BYTE)'\x4A',(BYTE)'\x4B',(BYTE)'\x4C',(BYTE)'\x4D',(BYTE)'\x4E',(BYTE)'\x4F',
/*9*/(BYTE)'\x50',(BYTE)'\x51',(BYTE)'\x52',(BYTE)'\x53',(BYTE)'\x54',(BYTE)'\x55',(BYTE)'\x56',(BYTE)'\x57',(BYTE)'\x58',(BYTE)'\x59',
/*10*/(BYTE)'\x5A',(BYTE)'\x5B',(BYTE)'\x5C',(BYTE)'\x5D',(BYTE)'\x5E',(BYTE)'\x5F',(BYTE)'\x60',(BYTE)'\x61',(BYTE)'\x62',(BYTE)'\x63',
/*11*/(BYTE)'\x64',(BYTE)'\x65',(BYTE)'\x66',(BYTE)'\x67',(BYTE)'\x68',(BYTE)'\x69',(BYTE)'\x6A',(BYTE)'\x6B',(BYTE)'\x6C',(BYTE)'\x6D',
/*12*/(BYTE)'\x6E',(BYTE)'\x6F',(BYTE)'\x70',(BYTE)'\x71',(BYTE)'\x72',(BYTE)'\x73',(BYTE)'\x74',(BYTE)'\x75',(BYTE)'\x76',(BYTE)'\x77',
/*13*/(BYTE)'\x78',(BYTE)'\x79',(BYTE)'\x7A',(BYTE)'\x7B',(BYTE)'\x7C',(BYTE)'\x7E',(BYTE)'\x7F',(BYTE)'\x80',(BYTE)'\x81',(BYTE)'\x82',
/*14*/(BYTE)'\x83',(BYTE)'\x84',(BYTE)'\x85',(BYTE)'\x86',(BYTE)'\x87',(BYTE)'\x88',(BYTE)'\x89',(BYTE)'\x8A',(BYTE)'\x8B',(BYTE)'\x8C',
/*15*/(BYTE)'\x8D',(BYTE)'\x8E',(BYTE)'\x8F',(BYTE)'\x90',(BYTE)'\x91',(BYTE)'\x92',(BYTE)'\x93',(BYTE)'\x94',(BYTE)'\x95',(BYTE)'\x96',
/*16*/(BYTE)'\x97',(BYTE)'\x98',(BYTE)'\x99',(BYTE)'\x9A',(BYTE)'\x9B',(BYTE)'\x9C',(BYTE)'\x9D',(BYTE)'\x9E',(BYTE)'\x9F',(BYTE)'\xA0',
/*17*/(BYTE)'\xA1',(BYTE)'\xA2',(BYTE)'\xA3',(BYTE)'\xA4',(BYTE)'\xA5',(BYTE)'\xA6',(BYTE)'\xA7',(BYTE)'\xA8',(BYTE)'\xA9',(BYTE)'\xAA',
/*18*/(BYTE)'\xAB',(BYTE)'\xAC',(BYTE)'\xAD',(BYTE)'\xAE',(BYTE)'\xAF',(BYTE)'\xB0',(BYTE)'\xB1',(BYTE)'\xB2',(BYTE)'\xB3',(BYTE)'\xB4',
/*19*/(BYTE)'\xB5',(BYTE)'\xB6',(BYTE)'\xB7',(BYTE)'\xB8',(BYTE)'\xB9',(BYTE)'\xBA',(BYTE)'\xBB',(BYTE)'\xBC',(BYTE)'\xBD',(BYTE)'\xBE',
/*20*/(BYTE)'\xBF',(BYTE)'\xC0',(BYTE)'\xC1',(BYTE)'\xC2',(BYTE)'\xC3',(BYTE)'\xC4',(BYTE)'\xC5',(BYTE)'\xC6',(BYTE)'\xC7',(BYTE)'\xC8',
/*21*/(BYTE)'\xC9',(BYTE)'\xCA',(BYTE)'\xCB',(BYTE)'\xCC',(BYTE)'\xCD',(BYTE)'\xCE',(BYTE)'\xCF',(BYTE)'\xD0',(BYTE)'\xD1',(BYTE)'\xD2',
/*22*/(BYTE)'\xD3',(BYTE)'\xD4',(BYTE)'\xD5',(BYTE)'\xD6',(BYTE)'\xD7',(BYTE)'\xD8',(BYTE)'\xD9',(BYTE)'\xDA',(BYTE)'\xDB',(BYTE)'\xDC',
/*23*/(BYTE)'\xDD',(BYTE)'\xDE',(BYTE)'\xDF',(BYTE)'\xE0',(BYTE)'\xE1',(BYTE)'\xE2',(BYTE)'\xE3',(BYTE)'\xE4',(BYTE)'\xE5',(BYTE)'\xE6',
/*24*/(BYTE)'\xE7',(BYTE)'\xE8',(BYTE)'\xE9',(BYTE)'\xEA',(BYTE)'\xEB',(BYTE)'\xEC',(BYTE)'\xED',(BYTE)'\xEE',(BYTE)'\xEF',(BYTE)'\xF0',
/*25*/(BYTE)'\xF1',(BYTE)'\xF2',(BYTE)'\xF3',(BYTE)'\xF4',(BYTE)'\xF5',(BYTE)'\xF6',(BYTE)'\xF7',(BYTE)'\xF8',(BYTE)'\xF9',(BYTE)'\xFA',
/*26*/(BYTE)'\xFB',(BYTE)'\xFC',(BYTE)'\xFD',(BYTE)'\xFE',(BYTE)'\xFF'
};

/////

El usuario ingresa una array de bytes y la función arregla el resultado en una cadena de chares, lo hace por medio de buscar en una tabla diseñada específicamente para esta situación.
Código:
void Test1(){ //Cadena de bytes a string

BYTE* cadena_de_bytes = (BYTE*)"\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
int largo_de_la_cadena_de_bytes = strlen( (char*)cadena_de_bytes);
char* cadena_de_bytes_en_formato_string = (char*)"000000000000000000000\0";
int pos_string=0;

int i;
for(i=0; i<largo_de_la_cadena_de_bytes; i++)
{
for(int j=0; j<256; j++)
{
if(cadena_de_bytes[i] == poshextabla[j])
{
int pos = j;
for(int k=0;k<2;k++){
cadena_de_bytes_en_formato_string[pos_string++]=hextabla[pos][k];
}
}
}
}
printf(cadena_de_bytes_en_formato_string);
printf("\n");
system("pause");
}

//////////

El usuario ingresa una cadena con números que representan bytes,
la función convierte la cadena a un array de bytes.

Código:
void Test2(){//String a cadena de bytes

char* cadena_de_bytes = (char*)"686868686868FFFFFFFF69\0";
BYTE* cadena_de_bytes_resultante = (BYTE*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
int largo_de_la_cadena_de_bytes = strlen( cadena_de_bytes);
int pos_bytes=0;

int i;
for(i=0; i<largo_de_la_cadena_de_bytes; i+=2)
{
for(int j=0; j<256; j++)
{
if(cadena_de_bytes[i] == hextabla[j][0] && cadena_de_bytes[i+1] == hextabla[j][1])
{
int pos = j;

cadena_de_bytes_resultante[pos_bytes++]=poshextabla[pos];
}
}
}

for(int x=0; x<largo_de_la_cadena_de_bytes/2; x++){
printf("%X",*(cadena_de_bytes_resultante+x));
}
printf("\n");
system("pause");
}

///////

Código:
int main(){


Test1();
Test2();

return 0;
}

voy a dejar el proyecto en MSVCPP 6
DESCARGA (http://www.mediafire.com/?tpp059i6c2t9t70)

está listo para compilar en modo 'Release', pero si sólo quitan el archivo .cpp para usarlo en otro compilador, compilen en modo Release también..

//////////////////////////////////////////////////////////////////////

EDITADO:

Debido a que mi código dejó de ser algo didáctico para ser criticado por ser costoso con la utilización de recursos, entonces lo que hice fue simplificar mi código siguiendo la misma lógica con la cual venía trabajando.

Ahora sólo se dispone de una tabla, dicha tabla se usa como lookup en la primera función y en la segunda se requiere recorrerla pero no más de lo necesario.


atte

Código:
/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////
/////////////////////////////////////

char* hextabla[] = { //256 BYTES
"00","01","02","03","04","05","06","07","08","09",
"0A","0B","0C","0D","0E","0F","10","11","12","13",
"14","15","16","17","18","19","1A","1B","1C","1D",
"1E","1F","20","21","22","23","24","25","26","27",
"28","29","2A","2B","2C","2D","2E","2F","30","31",
"32","33","34","35","36","37","38","39","3A","3B",
"3C","3D","3E","3F","40","41","42","43","44","45",
"46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59",
"5A","5B","5C","5D","5E","5F","60","61","62","63",
"64","65","66","67","68","69","6A","6B","6C","6D",
"6E","6F","70","71","72","73","74","75","76","77",
"78","79","7A","7B","7C","7D","7E","7F","80","81",
"82","83","84","85","86","87","88","89","8A","8B",
"8C","8D","8E","8F","90","91","92","93","94","95",
"96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9",
"AA","AB","AC","AD","AE","AF","B0","B1","B2","B3",
"B4","B5","B6","B7","B8","B9","BA","BB","BC","BD",
"BE","BF","C0","C1","C2","C3","C4","C5","C6","C7",
"C8","C9","CA","CB","CC","CD","CE","CF","D0","D1",
"D2","D3","D4","D5","D6","D7","D8","D9","DA","DB",
"DC","DD","DE","DF","E0","E1","E2","E3","E4","E5",
"E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9",
"FA","FB","FC","FD","FE","FF",
};


Código:

void Test1(BYTE* array_de_bytes, char* cadena_de_bytes_en_formato_string){ //Cadena de bytes a string

for(int i=0; i<(int)strlen( (char*)array_de_bytes); i++)
strcat(cadena_de_bytes_en_formato_string,hextabla[(int)array_de_bytes[i]]);
printf(cadena_de_bytes_en_formato_string);
printf("\n");
}

//////////

void Test2(char* cadena_de_bytes, BYTE* cadena_de_bytes_resultante){//String a cadena de bytes

int bytes=0;
for(int i=0; i<(int)strlen( cadena_de_bytes); i+=2){
for(int j=0; j<256; j++){
if( cadena_de_bytes[i]==hextabla[j][0] && cadena_de_bytes[i+1]==hextabla[j][1] ){
cadena_de_bytes_resultante[bytes++]=j;
j=256;
}
}
}
for(int x=0; x<(int)strlen( cadena_de_bytes)/2; x++)
printf("%X",*(cadena_de_bytes_resultante+x));
printf("\n");
}

///////

int main(){//Programa

BYTE* array_de_bytes = (BYTE*)"\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
char cadena_de_bytes_en_formato_string[256];
memset(cadena_de_bytes_en_formato_string,0,sizeof(cadena_de_bytes_en_formato_string));
printf("TEST1:\n");
Test1(array_de_bytes, cadena_de_bytes_en_formato_string);
system("pause");

char* cadena_de_bytes = (char*)"686868686868FFFFFFFF69\0";
BYTE* cadena_de_bytes_resultante = (BYTE*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
printf("TEST2:\n");
Test2(cadena_de_bytes, cadena_de_bytes_resultante);
system("pause");

return 0;
}


Título: Re: Cadena de bytes a string
Publicado por: rir3760 en 22 Febrero 2013, 16:02 pm
Algunos comentarios que espero se tomen como una critica constructiva.

Cuando se utilizan tablas de valores es por eficiencia, para obtener (que mas) un valor en tiempo constante en lugar de realizar una búsqueda.

Dos problemas en tu programa son: en la primera función la tabla no es necesaria porque el byte se puede descomponer utilizando los operadores de división y modulo. En la segunda función la tabla si es necesaria pero no realizas un "lookup", es su lugar realizas una búsqueda secuencial y esta es la de mayor costo (en comparación con otras).

En base a lo anterior el programa se puede reducir a:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4.  
  5. void to_str(void);
  6. void to_char(void);
  7.  
  8. int main(void)
  9. {
  10.   to_str();
  11.   to_char();
  12.  
  13.   return EXIT_SUCCESS;
  14. }
  15.  
  16. void to_str(void)
  17. {
  18.   const unsigned char *in = "\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
  19.   int i;
  20.  
  21.   for (i = 0; in[i] != '\0'; i++){
  22.      putchar("0123456789ABCDEF"[in[i] / 16]);
  23.      putchar("0123456789ABCDEF"[in[i] % 16]);
  24.   }
  25.   putchar('\n');
  26. }
  27.  
  28. void to_char(void)
  29. {
  30.   unsigned char val[UCHAR_MAX] = {0};
  31.   char digit[] = "0123456789ABCDEF";
  32.  
  33.   char in[] = "686868686868FFFFFFFF69";
  34.   unsigned char out[sizeof in / 2];
  35.   int i;
  36.  
  37.   for (i = 1; digit[i] != '\0'; i++)
  38.      val[digit[i]] = i;
  39.  
  40.   for (i = 0; in[i] != '\0'; i += 2){
  41.      out[i / 2] = val[in[i]] * 16 + val[in[i + 1]];
  42.   }
  43.  
  44.   for (i = 0; i < (int) sizeof out; i++)
  45.      printf("%X", out[i]);
  46.   putchar('\n');
  47. }

Otra opción es utilizar las funciones de la biblioteca estándar de C como sprintf, sscanf, etc.

Un saludo


Título: Re: Cadena de bytes a string
Publicado por: 85 en 22 Febrero 2013, 17:19 pm
Hola,
En verdad mi código no tiene problemas, mirá yo te cuento en realidad el uso de tablas viene a razón de que muchos no saben como manejar bytes y al resultarles ilustrativo el hecho de utilizar una tabla en donde se puede observar
el proceso detalladamente.

Al mismo tiempo es reducido en cuanto a líneas de código (funciones simples pero las tablas lo hacen parecer grande) pero costoso en procesamiento debido a la búsqueda secuencial que realiza cada función por separado. Buscar en una tabla de 255 elementos contínuamente, de forma secuencial es obviamente un tanto costoso. Se puede hacer algo como cortar la búsqueda una vez que se encuentra el elemento, eso reduciría la cantidad de ciclos.
Hacer un lookup sería un acceso directo mucho mejor.
Las tablas estoy de acuerdo que su mejor utilización es cuando se las usa como lookups.

Tu código es de la misma forma reducido en líneas de código y posiblemente más rápido, aunque vemos que usás operaciones aritméticas de tipo divisorias, que dependiendo del cpu, y considerando los avances actuales en compiladores y procesadores, que tratan de reemplazar estas operaciones costosas automáticamente con otras (multiplicaciones, operaciones de bits, etc)
también se debe tomar en cuenta, no precisamente en tu código que son algunas pero no tantas.

Te dejo unos enlaces al respecto ya que es un tema que me interesaba en un proyecto anterior..
http://stackoverflow.com/questions/226465/should-i-use-multiplication-or-division
http://bytes.com/topic/c/answers/811057-how-replace-division-operator
http://www.cplusplus.com/forum/general/17811/
http://en.wikibooks.org/wiki/Optimizing_C%2B%2B/Code_optimization/Faster_operations
http://gamedev.stackexchange.com/questions/27196/which-opcodes-are-faster-at-the-cpu-level




Título: Re: Cadena de bytes a string
Publicado por: rir3760 en 23 Febrero 2013, 17:30 pm
Algunos comentarios sobre la función actualizada para obtener la representación en cadena:
Código
  1. void Test1(BYTE* array_de_bytes, char* cadena_de_bytes_en_formato_string){ //Cadena de bytes a string
  2. for(int i=0; i<(int)strlen( (char*)array_de_bytes); i++)
  3. strcat(cadena_de_bytes_en_formato_string,hextabla[(int)array_de_bytes[i]]);
  4. printf(cadena_de_bytes_en_formato_string);
  5. printf("\n");
  6. }
Las recomendaciones sobre lo subjetivo (estilo): dale un nombre descriptivo a la función y unos mas cortos a las variables.

Lo objetivo: no es necesario utilizar la función strlen ya que puedes conocer donde termina el array de bytes comparando contra '\0', si te preocupa que alguno de los bytes tenga ese valor entonces debes cambiar de aproximación ya que strlen tendrá el mismo problema. Lo mejor en ese escenario seria pasar el numero de bytes a procesar como un parámetro adicional.

Y si piensas utilizar la función strcat deberías colocar a cero el primer elemento del array "cadena_de_bytes_en_formato_string" (programación defensiva).

Considerando que la posición a procesar de un array define la posición en el otro una alternativa (mas) es utilizar la función sprintf mas aritmética de punteros:
Código
  1. void to_str(const unsigned char *byte, char *str)
  2. {
  3.   int i;
  4.  
  5.   for (i = 0; byte[i] != '\0'; i++)
  6.      sprintf(str + i * 2, "%02X", byte[i]);
  7. }

De nuevo espero se tome de forma constructiva.

Un saludo


Título: Re: Cadena de bytes a string
Publicado por: 85 en 24 Febrero 2013, 00:18 am
Hola,  te cuento algo acerca de las recomendaciones, en verdad te digo que se trata de un 'Test' osea una prueba , no tanto de una publicación que intenta reemplazar una funcionalidad ya bastante conocida.
Código:
void Test1(BYTE* array_de_bytes, char* cadena_de_bytes_en_formato_string){ //Cadena de bytes a string

el nombre es parte de una prueba pero tiene el comentario que indica lo que hace, los nombres de las variables son demasiado descriptivos, la gente los va a entender mejor, al menos los principiantes..

STRLEN realmente está mal implementada en mi edición, lo raro es que no lo hayas notado, ya que dentro de un FOR está ejecutándose muchas veces, se debe utilizar como estaba antes.
Incluso STRCAT puede ser reemplazada a como se copiaba en la primera edición, pero bueno son detalles que se me escaparon.

te muestro otra solución para la función 2, en este caso no hecha por mi, pero vale igualmente

Código:
void Test2(char* cadena_de_bytes, BYTE* cadena_de_bytes_resultante)
{
static  BYTE Tabla[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

int Position;
int Length_de_bytes_resultante; // :)

Position = 0;
while (cadena_de_bytes[Position] != '\0')
{
cadena_de_bytes_resultante[Position >> 1] = (Tabla[cadena_de_bytes[Position]] << 4) + Tabla[cadena_de_bytes[Position + 1]];
Position = Position + 2;
}
Length_de_bytes_resultante = Position >> 1;

for (Position = 0; Position < Length_de_bytes_resultante; Position = Position + 1)
{
printf("%02X", cadena_de_bytes_resultante[Position]);
}
printf("\n");

}

Saludos