Copy Link
Add to Bookmark
Report
Nascondere un programma all
NASCONDERE UN PROGRAMMA ALL'INTERNO DI UN ALTRO IN PASCAL
E' un sistema leggermente laborioso ma semplice una volta che si e' preso il
via. ;-)
Il turbo pascal 7 e' uno dei migliori compilatori che si possono trovare in
giro per quanto riguarda la programmazione sotto dos. Se il c e' sicuramente
piu' valido ed efficace sia per quanto riguarda la velocita', la flessibilita'
nello scrivere i sorgenti e tante altre cose, il tp offre un compilatore
ridotto ai minimi termini ( per compilare un programma e farne un eseguibile
sono sufficienti per la maggior parte delle applicazioni i files:
TPC.exe (54k compattati con wwp) e Turbo.tpl (48k) )
..in piu' normalmente compila creando eseguibili piu' corti rispetto al c.
Tutto questo fa del tp uno dei programmi piu' usati in assoluto ( dopo il C++
della Borland ..che sinceramente anch'io preferisco. ;-) hi hi)
..in relazione a questa cosa mi e' stato fatto notare, a seguito dello scorso
articolo sulla possibilita' di nascondere un programma all'interno di un
sorgente in VB, che in pascal non sarebbe possibile farlo perche' il
compilatore tp non lavora con sorgenti piu' lunghi di 6xKb.
E in effetti e' vero.. ma a questo mondo si puo' fare tutto quando ci si mette
di sbuzzo buono. :))
Il trucco sta nel costruirsi delle unit (in c sarebbe molto piu' semplice)
contenenti solo una parte del programma da riassemblare.
Ogni parte ovviamente sara composta da tante linee di sorgente fino a
non-occupare il compilatore per dimensioni maggiori del suo massimo
lavorativo..quindi riassemblare il tutto.
la procedura a blocchi e' questa:
Premesse : file_da_inglobare
Programma_contenitore
azioni: file_da_inglobare -> file_convertito_in_esadecimale
|
file suddiviso in Nx parti di xKb
|
creazione di Nx UNIT
|
aggiunta al programma_contenitore delle unit
|
aggiunta al programma pincipale di una procedura
di ricompattazione delle unit.
Si procede cosi'.
Per prima cosa si deve convertire il programma da inglobare in maniera tale da
avere lo stesso in formato esadecimale inglobato in una o piu' variabili da
poter poi riutilizzare con una procedura esterna.
Perche' esadecimale? .. perche' la rappresentazione ascii (che sarebbe la
migliore in quanto rappresenta un byte con un solo byte appunto! :) ) e'
inutilizzabile all'interno di un sorgente ..tp infatti l'editor usa alcuni
caratteri ascii come comandi e quindi non verrebbero rappresentati nella
maniera corretta.
La rappresentazione decimale richiede 3 byte per byte .. infatti il carattere
'd' tanto per fare un esempio dovrebbe essere rappresentato col suo
equivalente ascii e cioe' 100.
La rappresentazione esadecimale 00-ff e' quindi la strada ottimale da
percorrere.
I file saranno mediamenti piu' lunghi del 60/70 % .. ma poco importa visti
i vantaggi.
Si divide quindi file cosi' convertito in linee secondo questo formato
a:=' .... primi 40 byte della rappresentazione esadecimale del file .....';p;
a:=' .. successivi 40 byte della rappresentazione esadecimale del file ..';p;
...
...
ecc.. ecc...
"a" e' una variabile stringa, "p" e' una procedura che prelevera' dalla stringa
"a" i dati due alla volta per riscriverli con append sull'hd ricreando il file
primario.
la variabile "a" e la procedura "p" dovranno essere definite all'interno delle
varie unit.
ad ogni riga viene eseguita la procedura "p" per la crezione a blocchi di 40
byte del file originale.. quindi secondo come struttureremo la procedura "p"
stessa (e le unit) sara' possibile mettere solo un certo numero di linee
(come sopra) in una unit specifica e le altre restanti in altre unit diverse.
.. come prima cosa serve un programma che converta un file binario nella sua
rappresentazione esadecimale e lo converta nel formato a:' .. 40Hex ..';p
questo e' lo script in pascal
------------------------------------------ CONVERTI.PAS
program converti;
uses strings,crt;
function hex(l : longint) : string;
const hc : array[0..15] of char =
('0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f');
begin
hex:=hc[(l and $f0) shr 4]+hc[(l and $0f)]
end;
var k:integer;
o:char;
n:string;
h,l,t:integer;
fp1,fp2:text;
g: file of byte;
begin
k:=0;
l:=0;
n:='spp3.3ds'; { NOME DEL FILE DA CONVERTIRE }
assign(g,n);reset(g);t:=filesize(g);close(g);
assign(fp1,n);
reset(fp1);
assign(fp2,'testo.txt');
rewrite(fp2);
write(fp2,'a:=',chr(39));
while l<t do
begin
l:=l+1;
read(fp1,o);
h:=ord(o);
k:=k+1;
write(fp2,hex(h));
if k>39 then
begin
write(fp2,chr(39),';p;',chr(13),chr(10),'a:=',chr(39));
k:=0;
end;
end;
write(fp2,chr(39),';p;',chr(13),chr(10));
close(fp2);
close(fp1);
end.
-------------------------------------------------------------
per chi volesse, per confronto, anche la stessa procedura in C..
------------------------------------------ CONVERTI.C
#include <stdio.h>
main(){
FILE *fp1,*fp2;
unsigned char h;
int k=0;
char *file,*t="";
file="spp3.3ds"; /* NOME DEL FILE DA CONVERTIRE */
fp1=fopen(file,"rb");
fp2=fopen("testo.txt","wb");
fprintf(fp2,"a:='");
while(!feof(fp1)){
h=fgetc(fp1);k++;
if(h<16) fprintf(fp2,"0%x",h);
if(h>=16) fprintf(fp2,"%x",h);
if(k>39){
fprintf(fp2,"';p;%c%ca:='",13,10);
k=0;}}
fprintf(fp2,"';p;%c%c",13,10);
fclose(fp2);
fclose(fp1);
}
-------------------------------------------------------------
lo script produce come output un file con le specifiche sopra riportate.
ad esempio il file binario
-----------------------------------------------------------------LOGO.JPG
ˇÿˇ‡ JFIF ˇ€ C
$.
' ",#(7),01444'9=82<.342ˇ€ C
2!!222222
22222222222222222222222222222222222222222222ˇ¿ /‘" ˇƒ
ˇƒ µ } !1AQa"q2Åë°#B
±¡R—$3brÇ
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzÉÑÖÜáà
âäíìîïñóòôö¢£§•¶ß®©™≤≥¥µ∂∑∏π∫¬√ƒ≈∆«»… “”‘’÷◊ÿŸ⁄·‚„‰ÂÊÁËÈÍÒÚÛÙıˆ˜¯˘˙ˇƒ
ˇƒ µ w !1AQaq"
2ÅBë°±¡ #3Rbr—
$4·%Ò&'()*56789:CDEFGHIJSTUVWXYZcdefghijstu
vwxyzÇÉÑÖÜáàâäíìîïñóòôö¢£§•¶ß®©™≤≥¥µ∂∑∏π∫¬√ƒ≈∆«»… “”‘’÷◊ÿŸ⁄‚„‰ÂÊÁËÈÍÚÛÙıˆ
˜¯˘˙ˇ⁄
? À‘øh?YÍ∑ñ±È˙)Hfx‘¥2‰Äƒ
˛Û⁄™ˇ √Fxø˛Å⁄˝¯óˇ é÷¯√Úi⁄ˆøÆ
Õ®©ÉZ6©
ôAÊÜfiƒeÅ⁄~Rs»„Á ì¿⁄v´w·ßϘkiÆNˆ˚/∂¥∂Ô(rJ‡2·√
`E-E©æü¥Gå_üÏ›
˙·/ˇ ´~–0ì˛a⁄'◊»óˇ éV.ü·øÎs‹i∫CÎk~∞M%¥˜-ÜfçT(*)ÓqÔ[∫†ú~∞∫µ÷]E¨
˛Hä‚%#˜œªq(ã8«Aé¶ò…£¯Ô‚ÊÎßËø˜Ê_˛9VG«?˘q“?ÔÃø¸r≥ÙÔÈíxˇ R—ÔnÓJ¥Eïn—\§
çåíA_˘h§8ßJ«É√tÌaÓZE∫µΩ䬛~ͺÃÕ∏0#<*8‰äBlÍ◊„â€?ËZ8ˇ ∂RÒ ê|mÒ!8˚ìˇ
~§ˇ „ïç˝É·!‚1·£>∞⁄á⁄ëªVåCÁÁnvm›∑{8Ê°M√˙gámu
rMMÓß∏û‹Af—®Ãd€ôN#颶Ü
üs¨oã^,]5Ca§}ôÓ‹.LÔ
Òø¶UO¯]û$ˇ ü+˛˝Iˇ ≈’8¸>˙ßÖ-t˝"uñŸıi&˚L¨¡∂â…ïá
®$7˚JEq:≥È…©Õì$ÚŸ!
ì‡3‡rÿ `ú∏∆h–ø·u¯ì˛|¥Ø˚ı'ˇ ¶ˇ ¬ÌÒ¸˘i_˜ÍO˛9^b“ú
tÆûœM—-<5i´kCRòfiÕ,p•ì"Ì…b¿‰ù√ c°¢·ttçÒ√ƒÄÒc§ˇ fl©?¯Â¸oÒ4í§c—î≥ÀG >ßÃ
‡W7o¢hñ´+ÿfl›ˇ d€iÊ˙ËHÄœS¥ƒ8
ÃI\7Oõÿ”[LŒ•l≤Èw7÷“•‘0ΩΩϱ≥ í
FTªéx=E!=
◊∆fl⁄›M¥—$1;!xíGF¡∆Tâ0G°™ØÒ„≈ Òc£flô¯ÂbÀ·≠#O∫◊Óu9Øéôßj&¬Ì y≥>Á∆Xå.2Nfi
ecc.. ecc...
-------------------------------------------------------------------------
viene convertito cosi':
-------------------------------------------------------------TESTO.TXT
a:='ffd8ffe000104a46494600010100000100010000ffdb004300080606070605080707070909080a0c';p;
a:='140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27';p;
a:='393d38323c2e333432ffdb0043010909090c0b0c180d0d1832211c21323232323232323232323232';p;
a:='3232323232323232323232323232323232323232323232323232323232323232323232323232ffc0';p;
a:='001108012f02d403012200021101031101ffc4001f00000105010101010101000000000000000001';p;
a:='02030405060708090a0bffc400b5100002010303020403050504040000017d010203000411051221';p;
a:='31410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a2526272829';p;
a:='2a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a';p;
a:='838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6';p;
a:='c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f010003';p;
a:='0101010101010101010000000000000102030405060708090a0bffc400b511000201020404030407';p;
a:='05040400010277000102031104052131061241510761711322328108144291a1b1c109233352f015';p;
a:='6272d10a162434e125f11718191a262728292a35363738393a434445464748494a53545556575859';p;
a:='5a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6';p;
a:='a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9ea';p;
a:='f2f3f4f5f6f7f8f9faffda000c03010002110311003f00cbd4bf683f1659eab796b1e9fa29486678';p;
ecc... ecc...
-------------------------------------------------------------------------
per poter ricostruire il file in TP sarebe sufficiente estrapolare i dati
esadecimali da ogni singola riga (tramite la produra P) e ricreare il file
col proprio nome.
Purtroppo spesso e volentieri il numero di righe formattate relative a uno o
piu' programmi da includere necessari ai nostri scopi supera abbondantemente
i limiti del compilatore tpc .. da qui l'esigenza delle unit.
cominciamo con le facili procedure necessarie all'estrazione dei dati.
Serve innanzitutto una funzione che separi dalla stringa -a- i dati due a due.
Sarebbe comoda una cosa tipo il mid$ del basic.. come questa:
var a : string;
S : array[0..10] of char;
function mid(t:string;n,l:integer):string;
var i: integer;
begin
for i:=n to n+l-1 do s[i-n]:=t[i];
mid:=strpas(s);
end;
Poi una procedura per convertire i dati della ministringa esadecimale di 2
caratteri estratta in un intero decimale
function deci(t:string):integer;
var ix,rx,ox,px:integer;
begin
ox:=0;
for ix:=2 downto 1 do begin
case t[ix] of
'a'..'f':rx:=ord(t[ix])-ord('a')+10;
'A'..'F':rx:=ord(t[ix])-ord('A')+10;
'0'..'9':rx:=ord(t[ix])-ord('0');
end;
if ix=1 then begin ox:=ox+rx*16 end
else begin ox:=ox+rx end;
end;
deci:=ox;
end;
Quindi la procedura p (attaccata in fondo ad ogni stringa formattata) che
scriva nel file i caratteri rigenerati.
procedure p;
var i,fru:integer;
begin
i:=round(length(a)/2);
for fru:=1 to i do
Write(fruttolo,chr(deci(mid(a,1+(fru-1)*2,2))));
end;
.. "fruttolo" e' l'assegnazione della variabile di tipo file:text relativa al
file che stiamo ricreando e che andra' aperto a inzio procedura generale nella
unit.
a questo punto siamo in grado di strutturare un completo modulo generale per
la nostra (o le nostre unit)
--------------------------------------------------------- MODULO.pas
{$A+,B-,D+,E+,F-,G+,I-,L+,N+,O-,P+,Q-,R-,S-,T-,V-,X+,Y+}
{$M 16384,0,655360}
UNIT unop;
INTERFACE
uses Strings,crt;
var a : string;
S : array[0..10] of char;
fruttolo : Text;
PROCEDURE uno;
IMPLEMENTATION
function deci(t:string):integer;
var ix,rx,ox,px:integer;
begin
ox:=0;
for ix:=2 downto 1 do begin
case t[ix] of
'a'..'f':rx:=ord(t[ix])-ord('a')+10;
'A'..'F':rx:=ord(t[ix])-ord('A')+10;
'0'..'9':rx:=ord(t[ix])-ord('0');
end;
if ix=1 then begin ox:=ox+rx*16 end
else begin ox:=ox+rx end;
end;
deci:=ox;
end;
function mid(t:string;n,l:integer):string;
var i: integer;
begin
for i:=n to n+l-1 do s[i-n]:=t[i];
mid:=strpas(s);
end;
procedure p;
var i,fru:integer;
begin
i:=round(length(a)/2);
for fru:=1 to i do
Write(fruttolo,chr(deci(mid(a,1+(fru-1)*2,2))));
end;
procedure uno;
begin
Assign(fruttolo, 'passa');
Append(fruttolo);
{ ... }
{ qui va la fila di a:=' ....... 40 byte ....... ';p; }
{ a:=' ... altri 40 byte .... ';p; }
{ ... }
close(fruttolo);
end;
begin
end.
----------------------------------------------------------------------------
nella procedura uno (come dichiarato sopra ) andranno inserite le linee
generate dallo script converti.pas (file testo.txt)
si potranno inserire circa 800 righe di 40 bytes per un totale di circa
32.000 byte del programma originale.
Se il programma originale sara' di dimensioni >= 32K bastera' una sola unit
altrimenti per un programma di 80K ne serviranno 3 ..e cosi' via.
Come metodo generale per la creazione delle unit successive io sempre il
modulo sopra .. cambiando tutto gli 'uno' in 'due' per la seconda unit, 'uno'
in 'tre' per la terza ..a seguire.
Nel programma generale poi sara' sufficiente dichiarare le varie unit
consecutivamente
USES unop,duep,trep,quap, ... xxxp
quindi richamare per la ricostruzione completa del file le varie procedure
dichiarate
uno;due;tre;qua; ... xxx:
..un esempio di file che ricompatta due unit create col metodo sopra riportato:
------------------------------------------------------------------
{$A+,B-,D+,E+,F-,G+,I-,L+,N+,O-,P+,Q-,R-,S-,T-,V-,X+,Y+}
{$M 16384,0,655360}
uses unop,duep;
var f:text;
begin
assign(f,'miofile.bin');
rewrite(f);
close(f);
uno;
due;
end.
---------------------------------------------------------------------
le righe
assign(f,'miofile.bin');
rewrite(f);
close(f);
sono necessarie in quanto l'append usato nelle unit se trovasse gia presente
sull'hd un file chiamato come il nostro file da rigenerare non ricreerebbe ex
novo quest'ultimo ma lo AGGIUNGEREBBE brutalmente a quello trovato.
Con rewrite abbiamo la certezza che il nostro file venga ricreato in maniera
corretta e partendo dalla locazione 0.
.. sarebbe tutto qui in effetti
un vero esempio pratico e funzionante.. una demo grafica (poi ognuno potra'
invece accludere ai propri sorgenti cio' che piu' gli tornera' utile.. io
questo non lo voglio sapere. ) ]:-)
E' un programma che ho trovato in giro che ruota sullo schermo oggetti creati
col 3d studio .. l'unica cosa e' che una demo classica di solito prevede un
solo file exe...
allora ho unito il file spp3.3ds al sorgente col sistema citato sopra.
Addirittura ho usato 3 unit diverse (ne sarebbe bastata una sola) .. ma lo
scopo era appunto quello di mostrare un caso non proprio banale.
Sia i sorgenti del file Sppdemo che tutti gli altri ..compresi
il file spp3.3ds 30k
il file sppdemo.exe (compresso) 38k
i vari sorgenti delle unit necessarie al programma principale
(x3ds.pas, strprocs.pas, demoinit.pas)
le tre unit create col mio mudulo.pas
si trovano nel File supporti.zip
( per gli sfaticati ci sono anche i sorgenti del convertitore sia in c che
in pascal! convpas.pas, convpas.c )
-------------------------------------------------------------Supporti.zip
Convpas.c 497 (convertitore in c)
Convpas.pas 858 ""
Sppdemo.pas 13710 DEMO GRAFICA SPP
Demoint.pas 7660 |_unit di supporto per demo
X3ds.pas 5476 |__________ ""
Strprocs.pas 2691 |__________ ""
unop.pas 24812 |______________ 1/3 file spp3.3ds
duep.pas 21932 |______________ 2/3 ""
trep.pas 25614 |______________ 3/3 ""
Sppdemo.exe 38204 Sppdemo.pas compilato e compresso con
wwpack
Spp3.zip 11679 File spp3.3ds compresso
|
|_Spp3.3ds 30154 File creato con 3d Studio R4 per DOS.
-------------------------------------------------------------
Master - Parsifal
-= SPP MEMBER =-