Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

ethan (3163)

ethan
  reversethis-{ed. ... rap.nov.olissat}

Being a 25-year old chap living in the western-most town of Germany. Stuying communication and information science and being a huge fan of XS-related things.

Journal of ethan (3163)

Friday June 27, 2003
12:21 AM

self-executing wav files

[ #13089 ]

Despite its uselessnes you might like this one. It turns a wav file into an executable by attaching some playback routines to the wav file (or rather, attaching the wav data to the player executable):

This is w2e.c. Should work for both of the common byte-orders:

#include <errno.h>

#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#include <sys/stat.h>

#include <stdio.h>
#include <stdlib.h>

#define DEVICE "/dev/dsp"

typedef unsigned char UC;

static struct {
        UC riff[4];
        UC size[4];
        UC wave[4]; /* format chunk */
        UC fmt_[4];
        UC lenf[4];
        UC x__1[2];
        UC chan[2];
        UC freq[4];
        UC bytes_sec[4];
        UC bytes_sample[2];
        UC bits_sample[2];
} WH;

struct {
        int fmt;
        int chans;
        int speed;
} PLAY_PARAMS = { 0, 0, 0 };

static int AUDIO_FD;
static unsigned char buf[4096];

int calculate_offset (int fd) {
        struct stat STAT;
        fstat(fd, &STAT);
        return STAT.st_size - WAVE_SIZE;
}

int configure_device (void) {
        int fmt, chans, speed;

        AUDIO_FD = open(DEVICE, O_WRONLY);
        if (AUDIO_FD == -1) return -1;

        fmt = WH.bits_sample[0] + (WH.bits_sample[1]<<8);
        chans = WH.chan[0] + (WH.chan[1]<<8);
        speed = WH.freq[0] + (WH.freq[1]<<8) +
                          (WH.freq[2]<<16) + (WH.freq[3]<<24);

        switch(fmt) {
                case 8:
                        fmt = AFMT_U8;
                        break;
                case 16:
                        fmt = AFMT_S16_NE;
                        break;
                default:
                        return -2;
        }

        if (ioctl(AUDIO_FD, SNDCTL_DSP_RESET) == -1)
                return -1;
        if (ioctl(AUDIO_FD, SNDCTL_DSP_SETFMT, &fmt) == -1)
                return -1;
        if (ioctl(AUDIO_FD, SNDCTL_DSP_CHANNELS, &chans) == -1)
                return -1;
        if (ioctl(AUDIO_FD, SNDCTL_DSP_SPEED, &speed) == -1)
                return -1;

        return 0;
}

int main (int argc, char **argv) {
        int me = open(argv[0], O_RDONLY);
        int last_read;
        int config_ok;
        int offset;

        if (me == -1) {
                perror("Error opening embedded wav-file");
                exit(1);
        }

        offset = calculate_offset(me);
        if (lseek(me, offset, SEEK_SET) == -1) {
                perror("Error seeking to wav-data");
                exit(1);
        }

        read(me, (void*)&WH, sizeof(WH));
        config_ok = configure_device();
        if (config_ok == -1) {
                perror("Configuring device");
                exit(1);
        } else if (config_ok == -2) {
                fprintf(stderr, "Format of wav file not supported\n");
                exit(2);
        }

        if(lseek(me, 8, SEEK_CUR) == -1) {
                perror("Skipping 8 bytes in chunk data");
                exit(1);
        }

        while ((last_read = read(me, (void*)buf, 4096)) > 0)
                write(AUDIO_FD, (void*)buf, last_read);

        close(AUDIO_FD);
        return 0;
}

And this is the corresponding Perl script that triggers the compilation of the above C file and attach the wav file passed as argument. Change $OPTIMIZE accordingly:

#! /usr/bin/perl -w

my $wav = shift;
my $size = -s $wav;
(my $exec = $wav) =~ s/\.wav$/.exec/;

my $CFLAGS = "-Wall";
my $OPTIMIZE = "-O3 -march=athlon";

my $command = "gcc w2e.c $CFLAGS $OPTIMIZE -DWAVE_SIZE=$size -o $exec";
print $command, "\n";
system($command) != 0 and exit 1;

open EXEC, ">>$exec" or die "$exec: $!\n";
open WAVE, $wav or die "$wav: $!\n";

binmode EXEC;
binmode WAVE;
local $/;
print EXEC <WAVE>;

close EXEC;
close WAVE;

The generated executable is about 5K larger than the original wav file.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • And this is the corresponding Perl script that triggers the compilation of the above C file and attach the wav file passed as argument.

    You seem to have missed some bits out of this perl code. Notably the routine that forks off during playback to find other sound samples on your disk to convert them to executables, and the routine that then mails them out as attachements to all your friends saying "Hey, I just got this great track"

    • Notably the routine that forks off during playback to find other sound samples on your disk to convert them to executables, and the routine that then mails them out as attachements to all your friends saying "Hey, I just got this great track"

      Hmmh, interesting idea. A P2P worm. The C code could be extended a little to spawn a daemon so that it can also receive files from other worms in the wild. File-sharing has never been more convenient: infect yourself and see new tracks magically coming in. Admittedly,