Jim Lawless' Blog


WSH2EXE part 2

Originally published on: Sat, 25 Apr 2009 22:39:18 +0000

My goals and requirements for WSH2EXE were simple:

  1. WSH2EXE would be a command-line program
  2. WSH2EXE should be able to run either the windowed script-interpreter (wscript.exe) or the console script-interpreter against the embedded script
  3. WSH2EXE should be able to invoke either a VBScript script or a JavaScript script
  4. WSH2EXE should allow the developer to specify a temporary directory by name

The data held in WSH2EXE would be a set of flags and variables containing the settings from the above and two stub EXE's; I would need a console-mode EXE to launch a console version of a script and a windowed-mode EXE to launch a windowed version of a script.

Keep in mind that I want the end-result EXE to contain the scripts and all of the above configuration data. My choices in storing this data in an already-compiled EXE include the option to overwrite some known portion of the EXE file itself, append the data to the EXE, or I could find a way to embed all of the data that I want as a Windows Resource data block into the EXE.

I chose to explore the second option; I would build a utility to stamp a block of data into a compiled EXE.

Please consider the source code for embedded.c below:


#include <stdio.h>

struct internalData {
   int someNumber;
   char someString[20];
} *dat;


char globalData[sizeof(struct internalData)]="[[[[[[[[" ;


int main(int argc,char **argv) {
   dat=(struct internalData *) globalData;
   printf("someNumber is %d\n",dat->someNumber);
   printf("someString is %s\n",dat->someString);
   return 0;
}

The output from this compiled code is: someNumber is 1532713819 someString is [[[[

I have set a pointer to a struct of type internalData to refer to a char block that I have initialized with eight left-bracket characters. When the someNumber element is displayed, it has treated each of the first four '[' characters as data and displays the number 1532713819.

The element someString occupies the remainder of the block of data. When we display it, we only see the first four characters ( which are the last four '[' characters of the eight that I had specified ) and then nothing else once the zero byte is encountered.

I created the string of eight '[' bytes to act as a sentinel value so that I could create a separate utility to find and overwrite that block of the EXE.

Please consider the following program stamp.c:


#include <stdio.h>
#include <string.h>
#include <malloc.h>

struct internalData {
   int someNumber;
   char someString[20];
} ;


int main(int argc,char **argv) {
#define MAX (1024*1024)
   FILE *fin,*fout;
   char *buff;
   struct internalData tmp;
   int i,sz;

   tmp.someNumber=42;
   strcpy(tmp.someString,"Don't look up!");
   fin=fopen("embedded.exe","rb");
   if(fin==NULL) {
      fprintf(stderr,"Cannot open input file embedded.exe \n");
      return 1;
   }
   fout=fopen("embedded2.exe","wb");
   if(fout==NULL) {
      fclose(fin);
      fprintf(stderr,"Cannot open output file embedded2.exe \n");
      return 1;
   }

   buff=(char *)malloc(MAX);
   sz=fread(buff,1,MAX,fin);
   if(sz<=0) {
      fclose(fin);
      fclose(fout);
      fprintf(stderr,"Unable to read input file.");
      return 1;
   }
   fclose(fin);
   for(i=0;i<(sz-7);i++) {
      if( (buff[i]=='[')&&
          (buff[i+1]=='[')&&
          (buff[i+2]=='[')&&
          (buff[i+3]=='[')&&
          (buff[i+4]=='[')&&
          (buff[i+5]=='[')&&
          (buff[i+6]=='[')&&
          (buff[i+7]=='[')) {
             memcpy(buff+i,&tmp,sizeof(struct internalData));
             break;
      }
   }
   fwrite(buff,1,sz,fout);
   fclose(fout);
   return 0;
}

The above program will open embedded.exe, which should be the output of the compiled embedded.c program, and will overwrite the internalData struct so that someString is "Don't look up!" and someNumber is 42.

Stamp.exe will then write the new EXE to a file named embedded2.exe.

The output of embedded2.exe is: someNumber is 42 someString is Don't look up!

The data-stamping technique looked to be a plausible option. However, I didn't feel like defining a static buffer in WSH2EXE big enough to hold all of the data that would be needed by the two stub EXE's. I chose to use the stamping technique to embed the flags and variables.

My next proof-of-concept was to build a mechanism to append the stub EXE's to WSH2EXE.

To be continued...

Unless otherwise noted, all code and text entries are Copyright ©2009 by James K. Lawless

del_icio_us Save to del.icio.us
stumbleupon Save to StumbleUpon
digg Digg it
reddit Save to Reddit
facebook Share on Facebook
twitter Share on Twitter
aolfav More bookmarks



Previous post: WSH2EXE part 1
Next post:Stacking Images with PerlMagick


Search this Blog (and site)

Search this Site with PicoSearch


Subscribe to this Blog

 Subscribe!


Contact Me

Email: jimbo@radiks.net


Follow me on Twitter

http://twitter.com/lawlessGuy


Recent Posts

Mad Schemes : Learning Lisp via SICP

Auto Save Clipboard Images Redux

Extending SpiderMonkey JavaScript on Windows

Rhino JavaScript to EXE with launch4j

Compiling Rhino JavaScript to Java

Directory Traversal in Rhino JavaScript

Taking Shape

We've Moved!


Popular Posts

A Command-Line MP3 Player for Windows

Auto Save Images from the Clipboard

Java in a Windows EXE with launch4j

An Interview with Tom Zimmer: Forth System Developer

Setting Windows Console Text Colors in C


Random Posts

JRuby as a Java Obfuscation Utility

Tracing XSLT with a Tiny Java Web Server

Compiling Rhino JavaScript to Java

Blogoversary

Auto Save Images from the Clipboard

Shrouding CSharp and Java Source Code with AWK

An Interview with Game Developer James Hague

Switching a Console Window to Full Screen or Windowed Mode

A GUI for urlx

We've Moved!


Full List of Posts

http://www.mailsend-online.com/bloglist.htm


Blogroll

MicroISV on a Shoestring
DadHacker
The Bottom Feeder
Writin' That Code!
The Recursive ISV
The Thomsen Blog
Prototypically Speaking
The Reinvigorated Programmer