6

I want to take a binary file (exe, msi, dll, whatever) and be able to actually "see" the binary code or whatever base I'd like (hexadecimal whatever). Figured the easiest way would be just to output the code into a txt so I can examine it.

Whats the best and easiest way to do this? Basically I am looking to convert the binary code into a picture for a project of mine.

Similarly, it would be nice if I could take some binary code, and then convert it into a binary file.

What are your methods for doing this, I listed C, C++, and C# because these seem to be the fastest programming languages and I figured this may take some time. I guess I am more interested in an answer in C, but I am mostly looking for some logic behind this.

Abel
  • 56,041
  • 24
  • 146
  • 247
ParoX
  • 5,685
  • 23
  • 81
  • 152
  • 1
    How do you mean "convert"? These files are binary already. – Dirk Vollmar Aug 04 '10 at 19:02
  • What? You want to render the bytes out of an EXE file as an image? – Matthew Whited Aug 04 '10 at 19:02
  • 2
    Sorry I probably should have used better terminology. I want to examine the binary code of a program, do something with it, and convert it back to a valid file. – ParoX Aug 04 '10 at 19:04
  • Maybe you mean that you want to make the binary code viewable? I.e., as in binary to hexadecimal notation? – Abel Aug 04 '10 at 19:06
  • +1 for the idea of converting executable code into an image. I doubt it'll look interesting though. Mostly like noise. – Mchl Aug 04 '10 at 19:06
  • `C--` sounds great, is the the inverse of `C++`? :P – Abel Aug 04 '10 at 19:08
  • Woops. I meant C and used -- as a statement divider lol. – ParoX Aug 04 '10 at 19:10
  • Do you want to see (a) hex number for every byte in the file, (b) binary number for every byte in the file or (c) assembly code for the code portion of the file (disassembly)? –  Aug 04 '10 at 19:11
  • I want to see a (b) a binary number for every byte.... And then maybe (a) too. – ParoX Aug 04 '10 at 19:16
  • 1
    Whoah! Full-on double rainbow! What does it mean? – Kennet Belenky Aug 04 '10 at 19:19
  • 2
    @Abel: C-- actually does exist. It's a C-like language, but simpler, designed as an intermediate language between assembly and a high-level language, to be easily autogenerated and compiled. See also http://en.wikipedia.org/wiki/C-- – Thomas Aug 04 '10 at 19:22
  • @Thomas: nice, I didn't know that. Seems a bit dead(ish) but sounds like fun for a rainy winter day ;) – Abel Aug 04 '10 at 19:30
  • 2
    This question wins for the amount of confusion it generates. – Jeff Davis Aug 04 '10 at 19:50

6 Answers6

14

Here's a way to pack the bytes into an image... the fun part is if you record the original file length and use a lossless image format you could safely extract the binary data later.

Packed as ARGB...

var exefile = Directory.GetFiles(".", "*.exe").First();
var fi = new FileInfo(exefile);

var dimension = (int)Math.Sqrt((fi.Length + 1d) / 4);

using (var bitmap = new Bitmap(dimension, dimension + 2))
{
    //store the file length in the first pixel.
    bitmap.SetPixel(0, 0, Color.FromArgb((int)fi.Length));

    var buffer = new byte[fi.Length + 4 - fi.Length % 4];
    Array.Copy(File.ReadAllBytes(exefile), buffer, fi.Length);

    int x = 1, y = 0;
    for (var offset = 0; offset < buffer.Length; offset += 4)
    {
        var colorValue = BitConverter.ToInt32(buffer, offset);
        bitmap.SetPixel(x, y, Color.FromArgb(colorValue));

        x++;
        if (x >= dimension)
        {
            x = 0;
            y++;
        }
    }

    bitmap.Save(Path.ChangeExtension(exefile, ".png"), ImageFormat.Png);
}

Packed as Black & White Binary...

var width = (int)Math.Sqrt(fi.Length * 8);
width = width + 8 - (width % 8);
var length = (int)(fi.Length * 8 / width);

Func<byte, int, Color> getcolor =
        (b, m) => (b & m) == m ? Color.Black : Color.White;

using (var bitmap = new Bitmap(width, length + 1))
{
    var buffer = File.ReadAllBytes(exefile);

    int x = 0, y = 0;
    foreach (var @byte in buffer)
    {
        bitmap.SetPixel(x + 0, y, getcolor(@byte, 0x80));
        bitmap.SetPixel(x + 1, y, getcolor(@byte, 0x40));
        bitmap.SetPixel(x + 2, y, getcolor(@byte, 0x20));
        bitmap.SetPixel(x + 3, y, getcolor(@byte, 0x10));

        bitmap.SetPixel(x + 4, y, getcolor(@byte, 0x8));
        bitmap.SetPixel(x + 5, y, getcolor(@byte, 0x4));
        bitmap.SetPixel(x + 6, y, getcolor(@byte, 0x2));
        bitmap.SetPixel(x + 7, y, getcolor(@byte, 0x1));

        x += 8;
        if (x >= width)
        {
            x = 0;
            y++;
        }
    }

    bitmap.Save(Path.ChangeExtension(exefile, ".tif"), ImageFormat.Tiff);
}

... and yeah, it looks like noise

Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
  • Yes. This is basically what I want to do. – ParoX Aug 04 '10 at 19:20
  • +1 for giving a quick and useful example of a rather funny exercise. I didn't come any further than creating a hex-viewer in that timeframe :) – Abel Aug 04 '10 at 19:38
  • BTW, if you want to modify this to be B&W binary for the bits you should consider using B&W TIFF with RLE compression. That will give you the most bang for your buck. But remember that image will have 8 times the number of pixels as the file has bytes. – Matthew Whited Aug 04 '10 at 19:39
  • @Brian, I just added a B&W version... the images as smaller than I was thinking they would be. And they look pretty cool. I didn't pack the binary version with the file length. – Matthew Whited Aug 04 '10 at 20:48
  • I ran into a problem with var colorValue- it states: Destination array is not long enough to copy all the items in the collection. Check array index and length. Weird because it made a png of a 8MB file, but its choking on a 400KB one. I just downloaded Visual C# 2010 express...so not really sure (yet) how to move on. Any help is appreciated :).. Edit: just noticed you did one for black and white (you are awesome)...trying it now... – ParoX Aug 04 '10 at 20:57
  • @Brian, yeah you may need to add a bounds check to the part that uses `BitConverter.ToInt32(buffer, offset);`. That will try to grab the next 4 bytes out of the byte[] and if it's not something that is divisible by 4 that could be an issue. – Matthew Whited Aug 04 '10 at 23:31
  • @Brian, see the change I just added. – Matthew Whited Aug 04 '10 at 23:37
  • Im porting this to a c++ mp3 to png app. What does the "1d" mean in "var dimension"? Is it the hex value for 29? – nebkat Dec 07 '10 at 20:36
  • @Neb, `1d` creates a double with the value of 1. It would be the same as saying `1.0`. In this application its main use it to ensure that floating point math is used instead of integer division. – Matthew Whited Dec 18 '10 at 02:08
7

I'm not quite sure what you are trying to do, but it sounds a bit like you're looking for a hex editor.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • Yes but can switch from hex to binary or whatever. I didnt think they had "binary modes" in hex editors but I guess I should google it. I still need to extract this code into something I can work with in an automated fashion (a txt file or something) – ParoX Aug 04 '10 at 19:06
  • 2
    You can't switch from hex to binary in your head? That's the whole point of hexadecimal. This is literally a hex editor's entire purpose in life, so that's almost certainly what you want. – mqp Aug 04 '10 at 19:13
  • OK. I am wanting to make a black pixel for 1 and a white pixel for 0. This is why I need to "see" the binary. I guess I could copy and paste the hexadecimal from the hex editor and then have a program convert it to binary...but...The whole point to convert it to binary in the first place? – ParoX Aug 04 '10 at 19:15
  • Oh. I think people were getting confused, then. You said you want to "see" it in binary, but you don't want to see it at all; you want to process it with a program and create a bitmap out of it. I agree then with the above answer -- you ought to use File.ReadAllBytes and then process the bytes to make your image. A hex editor is not helpful for you, since you're not interested in examining or editing it manually. – mqp Aug 04 '10 at 19:16
  • @Brian, okay... that is more nuts than my example would host. using a pixel per bit will make a huge image. – Matthew Whited Aug 04 '10 at 19:19
2

You can read all bytes of a file in C# or any .NET language by calling the static method ReadAllBytes.

byte[] allBytes = File.ReadAllBytes("YourPath");

It will put all the bytes into an array.

If you want to covert it to HexaDecimal see here.

Community
  • 1
  • 1
David Basarab
  • 72,212
  • 42
  • 129
  • 156
  • This is what I want. Thanks. Any method to taking bytes to a file. I do not use c# or any .NET languages (yet). Can I assume its File.WriteAllBytes :) – ParoX Aug 04 '10 at 19:08
2

Already done for you! Very convieniently a binary file is already stored in binary!

STW
  • 44,917
  • 17
  • 105
  • 161
  • I know. How can I see this binary code and edit it easily. I guess like a hex editor, but a binary editor lol. – ParoX Aug 04 '10 at 19:05
  • 3
    @Brian: A hex editor *is* a binary editor: it shows you a visual representation of the binary code, which is commonly done in hexadecimal, byte for byte. When you edit inside a hex editor, it will be converted back to the underlying binary representation of that byte. – Abel Aug 04 '10 at 19:09
  • I dont want to see it in hex. I want to see it in binary. I won't be editing it manually, but rather applying a technique. – ParoX Aug 04 '10 at 19:11
  • I think he just wants to see 1's and 0's. – STW Aug 04 '10 at 19:28
  • 1
    @Brian: you can't *see* binary. Just like you can't *see* a BLOB in a database. The only way to see it, is to use some representation. An image will tell you little, hex, octal, binary (zero/one) are string representations. But your idea is fun, useless, but fun: making an image of it is yet another non-binary representation (in the picture viewer) in another binary format (the image file) of a binary file (the original EXE). Confusing? – Abel Aug 04 '10 at 19:36
1

Just triggered by your question, I come in a bit late in the discussion, but wondered how easy it could be done. Here's a minimal implementation that gives you the binary output of the currently executing assembly (i.e. your current running EXE):

byte[] bytes = File.ReadAllBytes(Assembly.GetExecutingAssembly().Location);

// this can get large, we know how large, so allocate early and try to be correct
// note: a newline is two bytes
StringBuilder sb = new StringBuilder(bytes.Length * 3 + (bytes.Length / 16) * 4);

for (int i = 0; i < bytes.Length; i++)
{
    sb.AppendFormat("{0:X2} ", bytes[i]);
    if (i % 8 == 0 && i % 16 != 0)
        sb.Append("  ");
    if (i % 16 == 0)
        sb.Append("\n");

}

If you output the StringBuilder contents, you see the following (which is my test executable) for the first some bytes:

5A 90 00 03 00 00 00 04   00 00 00 FF FF 00 00 B8 
00 00 00 00 00 00 00 40   00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00   00 00 00 80 00 00 00 0E 
1F BA 0E 00 B4 09 CD 21   B8 01 4C CD 21 54 68 69 
73 20 70 72 6F 67 72 61   6D 20 63 61 6E 6E 6F 74 
20 62 65 20 72 75 6E 20   69 6E 20 44 4F 53 20 6D 
6F 64 65 2E 0D 0D 0A 24   00 00 00 00 00 00 00 50 
Abel
  • 56,041
  • 24
  • 146
  • 247
0

Here's the code to print out the bytes at 1's and 0's in C:

#include <stdio.h>

void putbits(unsigned char byte)
{
    unsigned char mask = 0x01;

    for (int bit = 7; bit >= 0; bit--)
    {
        if ((mask << bit) & byte)
        {
            printf("1");
        }
        else
        {
            printf("0");
        }
    }

    // Uncomment the following line to get each byte on it's own line.
    //printf("\n");
}

int main (int argc, const char * argv[])
{
    int c;

    while ((c = getchar()) != EOF)
    {
        putbits(c);
    }

    return 0;
}

You can build and run it on the command line like this:

gcc main.c --std=c99 -o printer
./printer < printer > printer.txt

It will then output it's 1's and 0's to printer.txt.

Douglas
  • 36,802
  • 9
  • 76
  • 89