Hi guys,
I've added to my code above so it now supports any file to be attached as a data stub to an EXE. As well, it supports packing and RC4 encryption. I haven't tested it much but it has worked for me on several attempts.
newcoder : I think you would appreciate packing and encryption on the program listings you intend to imbed on your interpreter runtime exe.
terryhough : I believe newcoder wanted to attach a data stub to an existing EXE rather than creating it in the PB IDE as you suggest.
Geotrail : thanks!
Max2 : ADS streams look interesting! Maybe I re-invent the wheel too much?
append.pb is a simple, generic utility that allows you to attach a data stub to any executable. The data stub can be a text file or any binary file.
Code: Select all
; ... EXE Data Stub Appender 0.1d by Griz October 2004 ...
; Appends a data stub to EXE : exe+data+packedsize(long)+unpackedsize(long)
Global datafile.s : datafile=""
Global exein.s : exein=""
Global exeout.s : exeout=""
Global messageout.s : messageout=""
Global password.s : password=""
Global originalsize
Procedure Mod(a,b)
ProcedureReturn a-(a/b)*b
EndProcedure
; RC4 from Pille / Rings
Procedure.l RC4Mem(Mem.l, memLen.l, Key.s)
Dim S.w(255)
Dim K.w(255)
i.l=0: j.l=0: t.l=0: x.l=0
temp.w=0: Y.w=0
Outp.s=""
For i = 0 To 255
S(i) = i
Next
j = 1
For i = 0 To 255
If j > Len(key)
j = 1
EndIf
K(i) = Asc(Mid(key, j, 1))
j = j + 1
Next i
j = 0
For i = 0 To 255
j = Mod(j + S(i) + K(i), 256)
temp = S(i)
S(i) = S(j)
S(j) = temp
Next i
i = 0
j = 0
For x = 0 To memLen-1
i = Mod(i + 1, 256)
j = Mod(j + S(i),256)
temp = S(i)
S(i) = S(j)
S(j) = temp
t = Mod(S(i) + Mod(S(j), 256) , 256)
Y = S(t)
PokeB(Mem+x, PeekB(Mem+x)!Y)
Next
ProcedureReturn Mem
EndProcedure
MessageRequester("Appender","version 0.1d by Griz",#PB_MessageRequester_Ok)
exein=OpenFileRequester("Choose Source EXE", "", "Executable (*.exe)|*.exe|All files (*.*)|*.*" , 0)
If exein
datafile=OpenFileRequester("Choose Source Data File", "", "Text (*.txt)|*.txt;*.bat|All files (*.*)|*.*" , 0)
If datafile
exeout=SaveFileRequester("Filename for output EXE", "", "Executable (*.exe)|*.exe;*.bat|All files (*.*)|*.*" , 0)
If exeout
password.s=InputRequester("RC4 Encryption","Please enter a password :","test123")
If ReadFile(0, datafile)
FileLength = Lof()
source=AllocateMemory(FileLength)
If filelength And source
; read data stub into memory
ReadData(source,filelength)
; pack the data
originalsize=filelength
sourcetemp=AllocateMemory(filelength+8)
If sourcetemp
f=PackMemory(source,sourcetemp,filelength)
FreeMemory(source)
source=AllocateMemory(f)
CopyMemory(sourcetemp,source,f)
FreeMemory(sourcetemp)
filelength=f
; read the exe into memory
If ReadFile(1,exein)
exefilelength=Lof()
destination=AllocateMemory(filelength+exefilelength+4+4)
If destination
ReadData(destination,exefilelength)
CopyMemory(source,destination+exefilelength,filelength)
; size of data (packed)
PokeL(destination+exefilelength+filelength,filelength)
; size of data (unpacked)
PokeL(destination+exefilelength+filelength+4,originalsize)
; encrypt the data stub
rc4mem(destination+exefilelength,filelength,password)
; write the destination exe
If OpenFile(2,exeout)
WriteData(destination,exefilelength+filelength+4+4)
MessageRequester("Success!", "EXE Generated")
EndIf
FreeMemory(destination)
EndIf
EndIf
EndIf
FreeMemory(source)
EndIf
CloseFile(0)
EndIf
EndIf
EndIf
EndIf
End
program.pb demonstrates accessing the data stub that
append.pb added to the exe. This demonstration will show the
first 512 bytes of a text file, but it should work on binary files too.
Code: Select all
; .. EXE Data Stub Decoder 0.1d by Griz October 2004 ..
; Read the last 4 bytes (long) as Data size then
; Read the data stub appended to end of the EXE
Global password.s : password="test123" ; rc4 password
Global originalsize
; API Call to get EXE Name
Procedure.s GetExeName()
sApp.s=Space(256)
GetModuleFileName_(GetModuleHandle_(0), @sApp, 256)
ProcedureReturn sApp
EndProcedure
Procedure Mod(a,b)
ProcedureReturn a-(a/b)*b
EndProcedure
; RC4 from Pille / Rings
Procedure.l RC4Mem(Mem.l, memLen.l, Key.s)
Dim S.w(255)
Dim K.w(255)
i.l=0: j.l=0: t.l=0: x.l=0
temp.w=0: Y.w=0
Outp.s=""
For i = 0 To 255
S(i) = i
Next
j = 1
For i = 0 To 255
If j > Len(key)
j = 1
EndIf
K(i) = Asc(Mid(key, j, 1))
j = j + 1
Next i
j = 0
For i = 0 To 255
j = Mod(j + S(i) + K(i), 256)
temp = S(i)
S(i) = S(j)
S(j) = temp
Next i
i = 0
j = 0
For x = 0 To memLen-1
i = Mod(i + 1, 256)
j = Mod(j + S(i),256)
temp = S(i)
S(i) = S(j)
S(j) = temp
t = Mod(S(i) + Mod(S(j), 256) , 256)
Y = S(t)
PokeB(Mem+x, PeekB(Mem+x)!Y)
Next
ProcedureReturn Mem
EndProcedure
Procedure GetExeData()
pfile.s=getexename()
psize=FileSize(pfile)
infile=ReadFile(#pb_any, pfile)
If infile
; read packed size of data stub
FileSeek(psize-8)
msize=ReadLong()
; read unpacked size of data stub
FileSeek(psize-4)
originalsize=ReadLong()
FileSeek(psize-8-msize)
source=AllocateMemory(msize)
If source
; read data stub into memory buffer
ReadData(source,msize)
; decrypt the data stub
rc4mem(source,msize,password)
; unpack the data stub
sourcetemp=AllocateMemory(originalsize)
If sourcetemp
UnpackMemory(source,sourcetemp)
FreeMemory(source)
source=AllocateMemory(originalsize)
CopyMemory(sourcetemp,source,originalsize)
FreeMemory(sourcetemp)
; ----------------------------------------
; data is now contained in 'source' memory bank
; below we simply capture it all as a string (for example)
d$=PeekS(source,originalsize)
If Len(d$)>512 ; only show the first 100 characters in messagebox
d$=Left(d$,512)+" <more...>"
EndIf
MessageRequester("Success!", "data size ="+Str(msize)+"/"+Str(originalsize)+Chr(13)+Chr(10)+Chr(13)+Chr(10)+d$)
FreeMemory(source)
; ----------------------------------------
EndIf
EndIf
CloseFile(infile)
EndIf
EndProcedure
getexedata()