使用 Java 将十六进制代码转换为 exe 文件
Convert Hex code to exe file using Java
我试图创建一种 compressing/decompressing 算法,现在它起作用了,我正在考虑如何写下它的解压缩十六进制代码来归档。
我试图将它转换为字节数组,但发生了一些奇怪的事情:
结果文件比原始文件大,即使解压缩的十六进制字符串和原始文件相同。当我尝试打开它时,它给了我 Compatibility issue with current Windows version
为了创建解压缩的 exe 并在其中写入十六进制代码,我使用了以下代码:
FileOutputStream stream=new FileOutputStream("Hello2.exe");
stream.write(hex.getBytes());
stream.close();
有什么建议吗?
尝试关注
byte[] hex = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64};
FileOutputStream stream = new FileOutputStream("Hello2.exe");
stream.write(hex);
stream.close();
如果这创建了一个只包含 hello world
字样的 Hello2.exe
,您的 hex.getBytes() 已经 returns 了错误的数据。
问题是您将字节读入十六进制字符串,然后将十六进制字符串直接写入文件,而不先将其转换回适当的字节。
假设文件内容是hello world
。作为字节数组,这是 {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64}
。将其读入字符串后,您有 "48656c6c6f20776F726C64"
。当您对该字符串调用 getBytes()
时,您将返回以下字节数组:{0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63, 0x36, 0x66, 0x32, 0x30, 0x37, 0x37, 0x36, 0x46, 0x37, 0x32, 0x36, 0x43, 0x36, 0x34}
。因此,您的输出文件是 48656c6c6f20776F726C64
,而不是 hello world
.
这是因为您得到的是字符串中每个单独字符的字节表示,而不是字符串表示的十六进制对的字节值。
请参阅此问题以了解将字符串正确转换为字节的方法:Convert a string representation of a hex dump to a byte array using Java?
我不知道 Java 但 c# 做了相同的 task.Compile 下面的代码,然后将它与 -h falg 一起使用。对于整个项目,您可以查看 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 '_';
}
}
}
我试图创建一种 compressing/decompressing 算法,现在它起作用了,我正在考虑如何写下它的解压缩十六进制代码来归档。
我试图将它转换为字节数组,但发生了一些奇怪的事情:
结果文件比原始文件大,即使解压缩的十六进制字符串和原始文件相同。当我尝试打开它时,它给了我 Compatibility issue with current Windows version
为了创建解压缩的 exe 并在其中写入十六进制代码,我使用了以下代码:
有什么建议吗?FileOutputStream stream=new FileOutputStream("Hello2.exe");
stream.write(hex.getBytes());
stream.close();
尝试关注
byte[] hex = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64};
FileOutputStream stream = new FileOutputStream("Hello2.exe");
stream.write(hex);
stream.close();
如果这创建了一个只包含 hello world
字样的 Hello2.exe
,您的 hex.getBytes() 已经 returns 了错误的数据。
问题是您将字节读入十六进制字符串,然后将十六进制字符串直接写入文件,而不先将其转换回适当的字节。
假设文件内容是hello world
。作为字节数组,这是 {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64}
。将其读入字符串后,您有 "48656c6c6f20776F726C64"
。当您对该字符串调用 getBytes()
时,您将返回以下字节数组:{0x34, 0x38, 0x36, 0x35, 0x36, 0x63, 0x36, 0x63, 0x36, 0x66, 0x32, 0x30, 0x37, 0x37, 0x36, 0x46, 0x37, 0x32, 0x36, 0x43, 0x36, 0x34}
。因此,您的输出文件是 48656c6c6f20776F726C64
,而不是 hello world
.
这是因为您得到的是字符串中每个单独字符的字节表示,而不是字符串表示的十六进制对的字节值。
请参阅此问题以了解将字符串正确转换为字节的方法:Convert a string representation of a hex dump to a byte array using Java?
我不知道 Java 但 c# 做了相同的 task.Compile 下面的代码,然后将它与 -h falg 一起使用。对于整个项目,您可以查看 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 '_';
}
}
}