I was trying to create a sort of compressing/decompressing algorithm and now that works I was thinking on how to write down to file its decompressed hex code.
I tried to convert it in an array of byte but something strange happens:
the result file is bigger than the original one even if the decompressed hex string and the original one are equal. When I try to open it, it gives me Compatibility issue with current Windows version
To create the decompressed exe and so writing in it its hex code I used this code:
Any suggestions?FileOutputStream stream=new FileOutputStream("Hello2.exe");
stream.write(hex.getBytes());
stream.close();

- 33
- 8
-
What is the content of `hex`? – Sizik Jan 16 '15 at 15:05
-
@Sizik In hex is contained the bynary data of an exe file converted in hex. The exe file just prints hello world – Dev01 Jan 16 '15 at 15:21
-
So, for example, if the binary data was `{0x61, 0x73, 0x64, 0x66}`, would the hex string would be `"61736466"`, or would it be `"asdf"`? – Sizik Jan 16 '15 at 15:30
-
@Sizik Well I think so, I just read from the file and converting the read byte using this : `String.format("%02X",buffer[i])` Where buffer is an array of byte. – Dev01 Jan 16 '15 at 15:33
3 Answers
Try following
byte[] hex = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64};
FileOutputStream stream = new FileOutputStream("Hello2.exe");
stream.write(hex);
stream.close();
if this creates a Hello2.exe
which only contains the words hello world
, your hex.getBytes() already returns the wrong data.

- 22,518
- 3
- 53
- 69
-
Doesn't work, it gives me the same error as said before. I tried to rewrite the exe file using the hex code which was read at the beginning but the same error is given. – Dev01 Jan 16 '15 at 15:18
-
You should not execute the `Hello2.exe` from my example. View it with an editor. If the `Hello2.exe` has not a size of 11 bytes, you do something wrong. The code posted in my answer does create the expected file. Otherwise post the hex dump of the file which my code creates on your PC. – SubOptimal Jan 16 '15 at 15:21
-
Yes sorry it creates a 11 bytes sized file. I thought that it was one of the tests used to check one of the first exe loader in ms/dos. (I saw previously a link which talked about this) – Dev01 Jan 16 '15 at 15:26
-
The problem is that you're reading the bytes into a hex string, then writing the hex string directly to the file without converting it back to the appropriate bytes first.
Let's say the file contents are hello world
. As an array of bytes, this is {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64}
. After you read it into a string, you have "48656c6c6f20776F726C64"
. When you call getBytes()
on this string, you get the following byte array back: {0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63, 0x36, 0x66, 0x32, 0x30, 0x37, 0x37, 0x36, 0x46, 0x37, 0x32, 0x36, 0x43, 0x36, 0x34}
. Thus, your output file is 48656c6c6f20776F726C64
, rather than hello world
.
This is because you're getting the byte representation of each individual character in the string, NOT the byte values of the hex pairs represented by the string.
See this question for a way to convert the string to bytes correctly: Convert a string representation of a hex dump to a byte array using Java?
I don't know about Java but c# did the same task.Compile following code and then use it with -h falg. For whole project you can take a look at https://github.com/Jhangju/portable-executable-2-hex-code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace pe2hex
{
internal class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
PrintUsage();
return;
}
IEmitter emitter;
if (args[0] == "-h")
{
emitter = new HexEmitter();
}
else if (args[0] == "-s")
{
emitter = new PerLineEmitter();
}
else
{
PrintUsage();
return;
}
try
{
string path = args[1];
if (!File.Exists(path))
{
Console.WriteLine("File does not exist: {0}", path);
return;
}
using (FileStream fs = File.OpenRead(path))
{
while (true)
{
int b = fs.ReadByte();
if (b == -1)
{
break;
}
emitter.PrintByte(b);
}
emitter.Flush();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public static void PrintUsage()
{
Console.WriteLine("usage: PrintHex.exe -<switch> <filename>");
Console.WriteLine(" -h hex dump");
Console.WriteLine(" -s one byte per line");
}
}
/**
* Interface for formatting byte output.
*/
public interface IEmitter
{
/**Called for every byte*/
void PrintByte(int b);
/**Called after class is finished with*/
void Flush();
}
/**
* Prints one byte per line as character, decimal and hex value.
*/
public class PerLineEmitter : IEmitter
{
public void PrintByte(int b)
{
char ch = Util.ToSafeAscii(b);
Console.WriteLine(ch + "\t" + b + "\t" + Util.ToHexString(b));
}
public void Flush() { }
}
/**
* Prints multiple bytes per line followed by characters.
*/
public class HexEmitter : IEmitter
{
private const int NBUFF = 16;
private int buffered = 0;
private int[] bytes = new int[NBUFF];
public void PrintByte(int b)
{
bytes[buffered] = b;
buffered++;
if (buffered == NBUFF)
{
Flush();
}
}
public void Flush()
{
if (buffered <= 0)
{
return;
}
for (int i = 0; i < NBUFF; i++)
{
if (i >= buffered)
{
Console.Write(" ");
}
else
{
string hex = Util.ToHexString(bytes[i]);
File.AppendAllText("hex.txt", hex);
Console.Write(hex);
Console.Write(" ");
}
}
/* Console.Write(" ");
for (int i = 0; i < NBUFF; i++)
{
if (i >= buffered)
{
Console.Write(" ");
}
else
{
char ch = Util.ToSafeAscii(bytes[i]);
Console.Write(ch);
}
}*/
Console.WriteLine();
buffered = 0;
}
}
/**
* Utility methods.
*/
public class Util
{
/**
* Converts a byte to a hexadecimal string value.
*/
public static string ToHexString(int b)
{
const int mask1 = 0x0F;
const int mask2 = 0xF0;
string ret = "";
int c1 = (b & mask1);
int c2 = (b & mask2) >> 4;
ret = ret + ToHexChar(c2) + ToHexChar(c1);
return ret;
}
/**
* Converts the given byte to a hex character.
*/
private static char ToHexChar(int b)
{
const int ascii_zero = 48;
const int ascii_a = 65;
if (b >= 0 && b <= 9)
{
return (char)(b + ascii_zero);
}
if (b >= 10 && b <= 15)
{
return (char)(b + ascii_a - 10);
}
return '?';
}
public static char ToSafeAscii(int b)
{
if (b >= 32 && b <= 126)
{
return (char)b;
}
return '_';
}
}
}

- 21
- 6