【问题标题】:Convert Hex code to exe file using Java使用Java将十六进制代码转换为exe文件
【发布时间】:2022-03-28 03:54:32
【问题描述】:

我试图创建一种压缩/解压缩算法,现在我正在考虑如何写下它的解压缩十六进制代码。 我试图将它转换为一个字节数组,但发生了一些奇怪的事情:
即使解压缩的十六进制字符串和原始文件相等,结果文件也比原始文件大。当我尝试打开它时,它给了我Compatibility issue with current Windows version
要创建解压缩的 exe 并在其中写入十六进制代码,我使用了以下代码:
FileOutputStream stream=new FileOutputStream("Hello2.exe"); stream.write(hex.getBytes()); stream.close(); 有什么建议吗?

【问题讨论】:

  • hex的内容是什么?
  • @Sizik In hex 包含转换为 hex 的 exe 文件的二进制数据。 exe 文件只打印 hello world
  • 那么,例如,如果二进制数据是{0x61, 0x73, 0x64, 0x66},那么十六进制字符串是"61736466",还是"asdf"
  • @Sizik 好吧,我想是的,我只是从文件中读取并使用此转换读取的字节:String.format("%02X",buffer[i]) 其中缓冲区是一个字节数组。

标签: java windows hex exe


【解决方案1】:

问题是您将字节读入十六进制字符串,然后将十六进制字符串直接写入文件,而不先将其转换回适当的字节。

假设文件内容是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?

【讨论】:

  • 我真是个白痴。非常感谢,现在它可以工作了!
【解决方案2】:

尝试关注

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 worldHello2.exe,那么您的 hex.getBytes() 已经返回了错误的数据。

【讨论】:

  • 不起作用,它给了我与之前所说的相同的错误。我尝试使用开头读取的十六进制代码重写 exe 文件,但给出了相同的错误。
  • 你不应该执行我的例子中的Hello2.exe。使用编辑器查看它。如果Hello2.exe 的大小不是 11 个字节,则说明您做错了。我的答案中发布的代码确实创建了预期的文件。否则,发布我的代码在您的 PC 上创建的文件的十六进制转储。
  • 是的,抱歉,它会创建一个 11 字节大小的文件。我认为这是用于检查 ms/dos 中第一个 exe 加载程序之一的测试之一。 (我之前看到过一个关于这个的链接)
  • 知道为什么编写文件的原始十六进制代码不起作用吗?
【解决方案3】:

我不了解 Java,但 c# 完成了相同的任务。编译以下代码,然后将其与 -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 '_';
        }

    }

}

【讨论】:

    猜你喜欢
    • 2014-01-15
    • 2019-01-01
    • 1970-01-01
    • 2017-10-06
    • 2014-05-14
    • 2023-02-21
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多