Your Ad Here

---[ Phrack Magazine Volume 8, Issue 54 Dec 25th, 1998, article 12 of 12

-------------------------[ Phrack Magzine Extraction Utility

--------[ Phrack Staff

New this issue: A win32 version.

---------------------8<------------CUT-HERE----------->8---------------------

<++> EX/PMEU/extract3.c /* extract.c by Phrack Staff and sirsyko * * (c) Phrack Magazine, 1997, 1998 * version 3 (P54): 07.14.98 * - patched by Cipso to allow for redirection from stdin * - patched by route to return heap memory when no longer needed * version 2 (P53): 01.08.98 rewritten by route * - aesthetics * - now accepts file globs
* todo: * - more info in tag header (file mode, checksum) * * Extracts textfiles from a specially tagged flatfile into a hierarchical * directory strcuture. Use to extract source code from any of the articles * in Phrack Magazine (first appeared in Phrack 50). * * gcc -o extract extract.c *
* Usage: * * ./extract file1 file2 file3 ... * OR * bzip2 -dc P54-*.bz2 | ./extract - */

include

include

include

include

include

include

define BEGIN_TAG "<++> "

define END_TAG "<-->"

define BTSIZE strlen(BEGINTAG)

define ETSIZE strlen(ENDTAG)

struct fname { uchar name[256]; struct f_name *next; };

int main(int argc, char **argv) { uchar b[256], *bp, *fn; int i, j = 0; FILE *inp, *outp = NULL; struct fname *fn_p = NULL, *head = NULL, *tmp = NULL; char *name;

if (argc < 2)
{
    printf("Usage: %s file1 file2 ... filen\n", argv[0]);
    exit(0); 
}

/*
 *  Fill the f_name list with all the files on the commandline (ignoring
 *  argv[0] which is this executable).  This includes globs.
 */
for (i = 1; (fn = argv[i++]); )
{
    if (!head)
    {
        if (!(head = (struct f_name *)malloc(sizeof(struct f_name))))
        {
            perror("malloc");
            exit(1);
        }
        strncpy(head->name, fn, sizeof(head->name));
        head->next = NULL;
        fn_p = head;
    }
    else
    {
        if (!(fn_p->next = (struct f_name *)malloc(sizeof(struct f_name))))
        {
            perror("malloc");
            exit(1);
        }
        fn_p = fn_p->next;
        strncpy(fn_p->name, fn, sizeof(fn_p->name));
        fn_p->next = NULL;
    }
}
/*
 *  Sentry node.
 */
if (!(fn_p->next = (struct f_name *)malloc(sizeof(struct f_name))))
{
    perror("malloc");
    exit(1);
 }
fn_p = fn_p->next;
fn_p->next = NULL;

/*
 *  Check each file in the f_name list for extraction tags.
 */
for (fn_p = head; fn_p->next;)
{
    if (!strcmp(fn_p->name, "-"))
    {
           in_p = stdin;
           name = "stdin";
    }
    else if (!(in_p = fopen(fn_p->name, "r")))
    {
        fprintf(stderr, "Could not open input file %s.\n", fn_p->name);
    continue;
    }
    else
    {
        name = fn_p->name;
    }
    fprintf(stderr, "Opened %s\n", name);        

    while (fgets(b, 256, in_p))
    { 
        if (!strncmp (b, BEGIN_TAG, BT_SIZE))
        { 
        b[strlen(b) - 1] = 0;           /* Now we have a string. */
            j++;

            if ((bp = strchr(b + BT_SIZE + 1, '/')))
            {
                while (bp)
                {
            *bp = 0;
            if (mkdir(b + BT_SIZE, 0700) == -1 && errno != EEXIST)
                    {
                        perror("mkdir");
                        exit(1);
                    }
            *bp = '/';
            bp = strchr(bp + 1, '/'); 
        }
            }
            if ((out_p = fopen(b + BT_SIZE, "w")))
            {
                printf("- Extracting %s\n", b + BT_SIZE);
            }
            else
            {
        printf("Could not extract '%s'.\n", b + BT_SIZE);
        continue;
        }
    } 
        else if (!strncmp (b, END_TAG, ET_SIZE))
        {
        if (out_p) fclose(out_p);
        else
            {
                fprintf(stderr, "Error closing file %s.\n", fn_p->name);
                continue;
            }
        } 
        else if (out_p)
        {
            fputs(b, out_p);
        }
    }
    if (in_p != stdin) fclose(in_p);
    tmp = fn_p;
    fn_p = fn_p->next;
    free(tmp);
}
if (!j) printf("No extraction tags found in list.\n");
else printf("Extracted %d file(s).\n", j);
return (0);

}

/* EOF */ <--> <++> EX/PMEU/extract.pl

Daos daos@nym.alias.net

!/bin/sh -- # -- perl -- -n

eval 'exec perl $0 -S ${1+"$@"}' if 0;

$opening=0;

if (/^\<++>/) {$curfile = substr($_ , 5); $opening=1;}; if (/^\<-->/) {close ctex; $opened=0;}; if ($opening) {
chop $curfile;
$sex
dir= substr( $curfile, 0, ((rindex($curfile,'/'))) ) if ($curfile =~ m/\//); eval {mkdir $sexdir, "0777";}; open(ctex,">$curfile"); print "Attempting extraction of $curfile\n"; $opened=1; } if ($opened && !$opening) {print ctex $}; <-->

<++> EX/PMEU/extract.awk

!/usr/bin/awk -f

#

Yet Another Extraction Script

-

# /^\<++>/ { ind = 1 File = $2 split ($2, dirs, "/") Dir="." while ( dirs[ind+1] ) { Dir=Dir"/"dirs[ind] system ("mkdir " Dir" 2>/dev/null") ++ind } next } /^\<-->/ { File = "" next } File { print >> File } <--> <++> EX/PMEU/extract.sh

!/bin/sh

exctract.sh : Written 9/2/1997 for the Phrack Staff by

#

note, this file will create all directories relative to the current directory

originally a bug, I've now upgraded it to a feature since I dont want to deal

with the leading / (besides, you dont want hackers giving you full pathnames

anyway, now do you :)

Hopefully this will demonstrate another useful aspect of IFS other than

haxoring rewt

#

Usage: ./extract.sh

cat $* | ( Working=1 while [ $Working ]; do OLDIFS1="$IFS" IFS= if read Line; then IFS="$OLDIFS1" set -- $Line case "$1" in "<++>") OLDIFS2="$IFS" IFS=/ set -- $2 IFS="$OLDIFS2" while [ $# -gt 1 ]; do File=${File:-"."}/$1 if [ ! -d $File ]; then echo "Making dir $File" mkdir $File fi shift done
File=${File:-"."}/$1 echo "Storing data in $File" ;; "<-->") if [ "x$File" != "x" ]; then unset File fi ;; *) if [ "x$File" != "x" ]; then IFS= echo "$Line" >> $File IFS="$OLDIFS1" fi ;; esac IFS="$OLDIFS1" else echo "End of file" unset Working fi done )
<--> <++> EX/PMEU/extract.py

! /bin/env python

extract.py Timmy 2tone _spoon_@usa.net

import sys, string, getopt, os

class Datasink: """Looks like a file, but doesn't do anything.""" def write(self, data): pass def close(self): pass

def extract(input, verbose = 1): """Read a file from input until we find the end token."""

if type(input) == type('string'):
    fname = input
    try: input = open(fname)
    except IOError, (errno, why):
        print "Can't open %s: %s" % (fname, why)
        return errno
else:
    fname = '<file descriptor %d>' % input.fileno()

inside_embedded_file = 0
linecount = 0
line = input.readline()
while line:

    if not inside_embedded_file and line[:4] == '<++>':

        inside_embedded_file = 1
        linecount = 0

        filename = string.strip(line[4:])
        if mkdirs_if_any(filename) != 0:
            pass

        try: output = open(filename, 'w')
        except IOError, (errno, why):
            print "Can't open %s: %s; skipping file" % (filename, why)
            output = Datasink()
            continue

        if verbose:
            print 'Extracting embedded file %s from %s...' % (filename,
                                                              fname),

    elif inside_embedded_file and line[:4] == '<-->':
        output.close()
        inside_embedded_file = 0
        if verbose and not isinstance(output, Datasink):
            print '[%d lines]' % linecount

    elif inside_embedded_file:
        output.write(line)

    # Else keep looking for a start token.
    line = input.readline()
    linecount = linecount + 1

def mkdirsifany(filename, verbose = 1): """Check for existance of /'s in filename, and make directories."""

path, file = os.path.split(filename)
if not path: return

errno = 0
start = os.getcwd()
components = string.split(path, os.sep)
for dir in components:
    if not os.path.exists(dir):
        try:
            os.mkdir(dir)
            if verbose: print 'Created directory', path

        except os.error, (errno, why):
            print "Can't make directory %s: %s" % (dir, why)
            break

    try: os.chdir(dir)
    except os.error, (errno, why):
        print "Can't cd to directory %s: %s" % (dir, why)
        break

os.chdir(start)
return errno

def usage(): """Blah.""" die('Usage: extract.py [-V] filename [filename...]')

def main(): try: optlist, args = getopt.getopt(sys.argv[1:], 'V') except getopt.error, why: usage() if len(args) <= 0: usage()

if ('-V', '') in optlist: verbose = 0
else: verbose = 1

for filename in args:
    if verbose: print 'Opening source file', filename + '...'
    extract(filename, verbose)

def db(filename = 'P51-11'): """Run this script in the python debugger.""" import pdb sys.argv[1:] = ['-v', filename] pdb.run('extract.main()')

def die(msg, errcode = 1): print msg sys.exit(errcode)

if name == 'main': try: main() except KeyboardInterrupt: pass

except getopt.error, why: usage()
if len(args) <= 0: usage()

if ('-V', '') in optlist: verbose = 0
else: verbose = 1

for filename in args:
    if verbose: print 'Opening source file', filename + '...'
    extract(filename, verbose)

def db(filename = 'P51-11'): """Run this script in the python debugger.""" import pdb sys.argv[1:] = [filename] pdb.run('extract.main()')

def die(msg, errcode = 1): print msg sys.exit(errcode)

if name == 'main': try: main() except KeyboardInterrupt: pass # No messy traceback. <--> <++> EX/PMEU/extract-win.c /************************/ / WinExtract / / / / Written by Fotonik fotonik@game-master.com. / / / / Coding of WinExtract started on 22aug98. / / / / This version (1.0) was last modified on 22aug98. / / / / This is a Win32 program to extract text files from a specially tagged / / flat file into a hierarchical directory structure. Use to extract / / source code from articles in Phrack Magazine. The latest version of / / this program (both source and executable codes) can be found on my / / website: http://www.altern.com/fotonik / /************************/

include

include

include

void PowerCreateDirectory(char *DirectoryName);

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { OPENFILENAME OpenFile; /* Structure for Open common dialog box / char InFileName[256]=""; char OutFileName[256]; char Title[]="WinExtract - Choose a file to extract files from."; FILE *InFile; FILE *OutFile; char Line[256]; char DirName[256]; int FileExtracted=0; / Flag used to determine if at least one file was / int i; / extracted */

ZeroMemory(&OpenFile, sizeof(OPENFILENAME)); OpenFile.lStructSize=sizeof(OPENFILENAME); OpenFile.hwndOwner=HWNDDESKTOP; OpenFile.hInstance=hThisInst; OpenFile.lpstrFile=InFileName; OpenFile.nMaxFile=sizeof(InFileName)-1; OpenFile.lpstrTitle=Title; OpenFile.Flags=OFNFILEMUSTEXIST | OFN_HIDEREADONLY;

if(GetOpenFileName(&OpenFile)) { if((InFile=fopen(InFileName,"r"))==NULL) { MessageBox(NULL,"Could not open file.",NULL,MB_OK); return 0; }

/* If we got here, InFile is opened. / while(fgets(Line,256,InFile)) { if(!strncmp(Line,"<++> ",5)) / If line begins with "<++> " */ { Line[strlen(Line)-1]='\0'; strcpy(OutFileName,Line+5);

     /* Check if a dir has to be created and create one if necessary */
     for(i=strlen(OutFileName)-1;i>=0;i--)
        {
        if((OutFileName[i]=='\\')||(OutFileName[i]=='/'))
           {
           strncpy(DirName,OutFileName,i);
           DirName[i]='\0';
           PowerCreateDirectory(DirName);
           break;
           }
        }

     if((OutFile=fopen(OutFileName,"w"))==NULL)
        {
        MessageBox(NULL,"Could not create file.",NULL,MB_OK);
        fclose(InFile);
        return 0;
        }

     /* If we got here, OutFile can be written to */
     while(fgets(Line,256,InFile))
        {
        if(strncmp(Line,"<-->",4)) /* If line doesn't begin w/ "<-->" */
           {
           fputs(Line, OutFile);
           }
        else
           {
           break;
           }
        }
     fclose(OutFile);
     FileExtracted=1;
     }
  }

fclose(InFile); if(FileExtracted) { MessageBox(NULL,"Extraction sucessful.","WinExtract",MBOK); } else { MessageBox(NULL,"Nothing to extract.","Warning",MBOK); } } return 1; }

/* PowerCreateDirectory is a function that creates directories that are / / down more than one yet unexisting directory levels. (e.g. c:\1\2\3) */ void PowerCreateDirectory(char *DirectoryName) { int i; int DirNameLength=strlen(DirectoryName); char DirToBeCreated[256];

for(i=1;i<DirNameLength;i++) /* i starts at 1, because we never need to / { / create '/' */ if((DirectoryName[i]=='\')||(DirectoryName[i]=='/')|| (i==DirNameLength-1)) { strncpy(DirToBeCreated,DirectoryName,i+1); DirToBeCreated[i+1]='\0'; CreateDirectory(DirToBeCreated,NULL); } } } <--> ----[ EOF