Salve manolos
, novamente aqui trazendo mais um tuto, hoje sobre como criar um HexDump em C#.
Para quem nunca ouviu falar nisso, HexDump é uma espécie de operação em que podemos listar o conteúdo de um arquivo ou ainda de uma área da memória, byte a byte em hexadecimal e ASCII. Muitas vezes é útil para ver o que existe no arquivo e conseguirmos algumas informações interessantes.
Para quem nunca viu ou talvez viu e não sabia o que era:

No nosso caso criaremos um HexDump para arquivos.
Vamos utilizar o Visual Studio (2005 ou superior). Criem um projeto do tipo Console Application, o nome do projeto fica da escolha de vcs.
Após a criação do projeto, criem uma classe com o nome de HexDump, e vamos começar a implementá-la.
Código PHP:
private const int MAXBYTES = 16;
private StreamWriter writer;
private string hexbyte;
private int gravados = 0;
private int[] bytes = new int[MAXBYTES];
Começamos declarando as variáveis/constantes da classe. A constante MAXBYTES irá controlar o número de bytes escritos em cada linha, já que estamos falando de hexadecimal, esse valor será 16. A variável writer (StreamWriter) não é nada mais do que o objeto que utilizaremos para escrever no nosso arquivo que irá gerar o hexdump. As variáveis hexbyte e gravados também irão nos auxiliar no controle e escrita dos bytes no arquivo, mais a frente o entendimento delas será mais fácil. Por último a array int[] bytes, irá guardar cada byte dos 16 bytes de cada linha.
Código PHP:
public Hexdump(string caminho)
{
writer = new StreamWriter(caminho);
}
Esse será o construtor da nossa classe. Ao instanciá-la devemos passar o caminho de onde será salvo nosso arquivo com o resultado do hexdump.
Código PHP:
public void GetByte(int b)
{
bytes[gravados] = b;
gravados++;
if (gravados == MAXBYTES)
{
Gravar();
}
}
O método GetByte será o método que irá receber cada byte lido do arquivo. Como vcs podem ver cada byte que é passado ao método é armazenado na array, até o momento que seja gravado 16 bytes dentro da array (MAXBYTES = 16) ou seja, 1 linha inteira. Vamos ver agora o que é o método Gravar().
Código PHP:
public void Gravar()
{
if (gravados <= 0)
{
return;
}
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
hexbyte = HexString(bytes[i]);
writer.Write(hexbyte);
writer.Write(" ");
}
}
writer.Write(" ");
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
char ch = Ascii(bytes[i]);
writer.Write(ch);
}
}
writer.WriteLine("");
gravados = 0;
}
Vamos dividir em 2 partes para entender esse método:
Código PHP:
if (gravados <= 0)
{
return;
}
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
hexbyte = HexString(bytes[i]);
writer.Write(hexbyte);
writer.Write(" ");
}
}
writer.Write(" ");
O método começa fazendo uma validação para verificar se a variável gravados é menor ou igual a zero. Caso verdadeiro, o método não deve fazer nada, pois não há bytes para gravar no arquivo. Em seguida, o loop varre os 16 bytes da array, convertendo cada byte em hexadecimal e escrevendo-o no arquivo, seguido de um espaço para separarmos cada byte. Após o loop terminar de varrer os 16 bytes, ele escreve um espaço no arquivo para iniciarmos a escrita ASCII de cada um desses bytes:
Código PHP:
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
char ch = Ascii(bytes[i]);
writer.Write(ch);
}
}
writer.WriteLine("");
gravados = 0;
Esse loop é bem parecido com o anterior, varre os 16 bytes da array, porém escreve-os no arquivo no formato ASCII, e termina pulando uma linha no arquivo (writer.WriteLine("")), para que os próximos 16 bytes já sejam escritos na linha correta, e assim por diante.
A variável "gravados" também é setada de volta para 0, afinal já gravamos todos os 16 bytes dessa linha.
Dentro do método Gravar(), utilizamos 2 funções que ainda não as criamos: HexString e Ascii. Então vamos criá-las...
Código PHP:
public static string HexString(int b)
{
return b.ToString("X").PadRight(2, '0');
}
O método HexString é bem simples, recebe o byte dentro de uma variável inteiro e a converte para hexadecimal. Para quem nunca viu isso, ao passar "X" para o método ToString, além de converter a variável para uma string, ele converte o valor para hexadecimal. Simples né? :P também chamamos o método PadRight para ter certeza que cada byte será representado por 2 caracteres. O zero deve ser exibido dessa forma '00'.
Código PHP:
public static char Ascii(int b)
{
if (b >= 32 && b <= 126)
{
return (char)b;
}
return '_';
}
O método Ascii serve para nos certificarmos que esse byte está dentro dos caracteres que conhecemos, ou seja, letras, números e etc. Caso ele não faça parte, será substituído por um _ (underline). Normalmente em um HexDump ao invés de underline, é utilizado um ponto (.), portanto fica da forma que vcs preferirem.
Código PHP:
public void Fechar()
{
writer.Close();
}
Por último, o método responsável por fechar a nossa Stream.
Nossa classe já está pronta agora falta implementar a parte que irá utilizar a nossa classe. Faremos isso direto dentro do método Main.
Código PHP:
Hexdump dump = new Hexdump(@"c:\dump.txt");
FileStream fs = File.OpenRead(@"c:\WINDOWS\system32\notepad.exe");
while (fs.Position < fs.Length)
{
int b = fs.ReadByte();
dump.GetByte(b);
}
dump.Fechar();
A primeira linha declara e instância a nossa classe, passando como parâmetro o local onde será salvo o nosso arquivo. Em seguida utilizamos a classe FileStream, para abrir como leitura um executável qualquer. O loop while irá ler o arquivo até o seu fim, desse modo a variável b receberá cada byte do arquivo e passará para o método GetByte da nossa classe que fará todo o trabalho. Finalizamos chamando o método que fechará a nossa stream, e consequentemente fechando e salvando o nosso arquivo.
Segue abaixo o código das classes HexDump.cs e Program.cs respectivamente:
HexDump.cs
Código PHP:
using System;
using System.IO;
namespace ConsoleApplication2
{
public class Hexdump
{
private const int MAXBYTES = 16;
private StreamWriter writer;
private string hexbyte;
private int gravados = 0;
private int[] bytes = new int[MAXBYTES];
public Hexdump(string caminho)
{
writer = new StreamWriter(caminho);
}
public void GetByte(int b)
{
bytes[gravados] = b;
gravados++;
if (gravados == MAXBYTES)
{
Gravar();
}
}
public static string HexString(int b)
{
return b.ToString("X").PadRight(2, '0');
}
public static char Ascii(int b)
{
if (b >= 32 && b <= 126)
{
return (char)b;
}
return '_';
}
public void Gravar()
{
if (gravados <= 0)
{
return;
}
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
hexbyte = HexString(bytes[i]);
writer.Write(hexbyte);
writer.Write(" ");
}
}
writer.Write(" ");
for (int i = 0; i < MAXBYTES; i++)
{
if (i >= gravados)
{
writer.Write(" ");
}
else
{
char ch = Ascii(bytes[i]);
writer.Write(ch);
}
}
writer.WriteLine("");
gravados = 0;
}
public void Fechar()
{
writer.Close();
}
}
}
Program.cs
Código PHP:
using System;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Hexdump dump = new Hexdump(@"c:\dump.txt");
FileStream fs = File.OpenRead(@"c:\WINDOWS\system32\notepad.exe");
while (fs.Position < fs.Length)
{
int b = fs.ReadByte();
dump.GetByte(b);
}
dump.Fechar();
}
}
}
Então é isso galere espero que gostem..
Qualquer dúvida ou problema tamo ae