使用 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 '_';
        }

    }

}