知识点

将一个文件的数据附加到另一个可执行文件的末尾,而不影响原可执行文件的运行,同时原可执行文件可以通过特定方式读取这些附加的数据。

技术原理:

① 可执行文件格式(如 Windows 的 PE、Linux 的 ELF)允许在文件末尾添加额外数据而不影响其执行

② 程序 A 在程序 B 末尾先写入附加文件的内容,再写入文件大小(8 字节)。

③ 程序 B 运行时,读取程序 B 末尾附件文件的大小,再定位并读取附加内容

代码与实现

程序 A(文件写入器)的功能是将指定文件附加到程序 B 的末尾

#include <QCoreApplication>
#include <QFile>
#include <QDebug>

// 程序A:将一个文件附加到程序B的末尾
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 检查参数
    if (argc != 4) {
        qDebug() << QString::fromLocal8Bit("用法: ") << argv[0] << QString::fromLocal8Bit("<程序B路径> <要附加的文件路径> <输出文件路径>");
        return 1;
    }

    QString programBPath = argv[1];
    QString fileToAppendPath = argv[2];
    QString outputPath = argv[3];

    // 打开程序B
    QFile programB(programBPath);
    if (!programB.open(QIODevice::ReadOnly)) {
        qDebug() << QString::fromLocal8Bit("无法打开程序B: ") << programB.errorString();
        return 1;
    }

    // 打开要附加的文件
    QFile fileToAppend(fileToAppendPath);
    if (!fileToAppend.open(QIODevice::ReadOnly)) {
        qDebug() << QString::fromLocal8Bit("无法打开要附加的文件: ") << fileToAppend.errorString();
        programB.close();
        return 1;
    }

    // 创建输出文件
    QFile outputFile(outputPath);
    if (!outputFile.open(QIODevice::WriteOnly)) {
        qDebug() << QString::fromLocal8Bit("无法创建输出文件: ") << outputFile.errorString();
        programB.close();
        fileToAppend.close();
        return 1;
    }

    // 写入程序B的内容
    outputFile.write(programB.readAll());

    // 写入要附加的文件内容
    outputFile.write(fileToAppend.readAll());

    // 先写入附加文件的大小(8字节),方便程序B读取时定位
    qint64 fileSize = fileToAppend.size();
    outputFile.write((char*)&fileSize, sizeof(qint64));

    qDebug() << QString::fromLocal8Bit("文件已成功附加到程序B末尾");

    // 关闭所有文件
    programB.close();
    fileToAppend.close();
    outputFile.close();

    return 0;
}

程序 B(读取器)的功能是执行自身并读取被附加的文件内容:

#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QString>

// 程序B:读取自身末尾附加的文件内容
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 获取当前程序的路径
    QString programPath = QCoreApplication::applicationFilePath();

    // 打开当前程序文件
    QFile programFile(programPath);
    if (!programFile.open(QIODevice::ReadOnly)) {
        qDebug() << QString::fromLocal8Bit("无法打开程序文件: ") << programFile.errorString();
        return 1;
    }

    // 获取文件大小
    qint64 fileSize = programFile.size();

    // 移动到文件末尾前8个字节的位置(存储了文件大小)
    if (!programFile.seek(fileSize - sizeof(qint64))) {
        qDebug() << QString::fromLocal8Bit("无法定位到文件大小存储位置");
        programFile.close();
        return 1;
    }

    // 读取附加文件的大小
    qint64 appendedFileSize;
    programFile.read((char*)&appendedFileSize, sizeof(qint64));

    // 移动到附加文件的起始位置
    qint64 appendedFileOffset = fileSize - sizeof(qint64) - appendedFileSize;
    if (!programFile.seek(appendedFileOffset)) {
        qDebug() << QString::fromLocal8Bit("无法定位到附加文件的起始位置");
        programFile.close();
        return 1;
    }

    // 读取附加的文件内容
    QByteArray appendedData = programFile.read(appendedFileSize);

    qDebug() << QString::fromLocal8Bit("成功读取到附加的文件内容,大小为") << appendedData.size() << QString::fromLocal8Bit("字节");
    qDebug() << QString::fromLocal8Bit("内容如下:");
    qDebug() << QString(appendedData);

    programFile.close();

    return 0;
}

程序运行截图如下:

1.txt内容:

注意

如果是Linux,使用chmod设置下权限,或者直接root去操作即可。

如果是windows,就需要以管理员身份运行。或者编辑权限(与linux chmod原理一致)

更多推荐