home *** CD-ROM | disk | FTP | other *** search
- {
- Hi !
-
- Here is some source code I acquired from a Pascal echo some time
- ago. It shows one method of detecting which TP compiler created
- an .EXE:
-
- -------------------------------------------------------------------
- { to compile type: tpc foo.pas }
- { exe: 9776 bytes by TP5.5 }
-
- {$A+,B-,E-,F-,I+,N-,O-,V+}
- {$M 4500,0,0}
- {$ifndef debug}
- {$D-,L-,R-,S-}
- {$else}
- {$D+,L+,R+,S+}
- {$endif}
-
- Program foo;
-
- Uses
- DOS; { dos unit from turbo pascal }
-
- TYPE { normal exe file header }
- EXEH = RECORD
- id, { exe signature }
- Lpage, { exe file size mod 512 bytes; < 512 bytes }
- Fpages, { exe file size div 512 bytes; + 1 if Lpage > 0 }
- relocitems, { number of relocation table items }
- size, { exe header size in 16-byte paragraphs }
- minalloc, { min mem. required in additional to exe image }
- maxalloc, { extra max. mem. desired beyond that required
- to hold exe's image }
- ss, { displacement of stack segment }
- sp, { initial SP register value }
- chk_sum, { complemented checksum }
- ip, { initial IP register value }
- cs, { displacement of code segment }
- ofs_rtbl, { offset to first relocation item }
- ovr_num : word; { overlay numbers }
- END;
- { window exe file header }
- WINH = RECORD
- id : word; { ignore the rest of data structures }
- END;
-
- str2 = string [2];
- str4 = string [4];
- str10 = string [10];
-
- CONST
- no_error = 0; { no system error }
- t = #9; { ascii: hortizon tab }
- dt = t+t;
- tt = t+t+t;
- qt = t+t+t+t;
- cr = #13#10; { ascii: carriage return and line feed }
-
- VAR
- f : file; { source file, untyped }
- exehdr : exeh; { exe header contents }
- winhdr : winh; { window exe header contents }
- blocks_r : word; { number of blocks actually read }
-
- exe_size , { exe file length }
- hdr_size , { exe header size }
- img_size , { load module or exe image size }
- min_xmem , { min. extra memory needed }
- max_xmem , { max. extra memory wanted }
- o_starup : longint; { offset to start up code }
-
- dirfile : searchrec;
- compressed : boolean;
-
- function Hex(B :byte) :str2;
- CONST strdex :array [0..$F] of char = '0123456789ABCDEF';
- BEGIN Hex := concat(strdex[B shr 4], strdex[B and $F]); END;
-
- function HexW(W :word) :str4;
- VAR byt :array [0..1] of byte absolute W;
- BEGIN HexW := Hex(byt[1])+Hex(byt[0]); END;
-
- function HexL(L :longint) :str10;
- TYPE Cast = RECORD
- Lo :word;
- Hi :word;
- END;
- BEGIN HexL := HexW(Cast(L).Hi)+' '+HexW(Cast(L).Lo); END;
-
- procedure print_info;
- CONST
- psp_size = $100; { size of psp, bytes }
- VAR i : byte;
- BEGIN
- hdr_size := longint(exehdr.size) shl 4; { exe header size, bytes }
- img_size := longint(exe_size) - hdr_size; { exe image size, bytes }
- min_xmem := longint(exehdr.minalloc) shl 4; { mim xtra mem, bytes }
- max_xmem := longint(exehdr.maxalloc) shl 4; { max xtra mem, bytes }
- o_starup := hdr_size + longint(exehdr.cs) shl 4
- +longint(exehdr.ip); { ofs to start up code }
- writeln(
- qt, 'Dec':8, '':6, 'Hex', cr,
- 'EXE file size:', tt, exe_size:8, '':3, hexl(exe_size), cr,
- 'EXE header size:', dt, hdr_size:8, '':3, hexl(hdr_size), cr,
- 'Code + initialized data size:', t, img_size:8, '':3, hexl(img_size)
- );
-
- writeln(
- 'Pre-relocated SS:SP', tt, '':3, hexw(exehdr.ss), ':', hexw(exehdr.sp)
- , cr,
- 'Pre-relocated CS:IP', tt, '':3, hexw(exehdr.cs), ':', hexw(exehdr.ip)
- );
-
- writeln(
- 'Min. extra memory required:', t, min_xmem:8, '':3, hexl(min_xmem), cr,
- 'Max. extra memory wanted:', t, max_xmem:8, '':3, hexl(max_xmem), cr,
- 'Offset to start up code:', dt, '':3, hexl(o_starup), cr,
- 'Offset to relocation table:', dt, '':3, hexw(exehdr.ofs_rtbl):9
- );
-
- writeln(
- 'Number of relocation pointers:', t, exehdr.relocitems:8, cr,
- 'Number of MS overlays:', dt, exehdr.ovr_num:8, cr,
- 'File checksum value:', tt, '':3, hexw(exehdr.chk_sum):9, cr,
- 'Memory needed to start:', dt, img_size+min_xmem+psp_size:8
- );
- END; { print_info }
-
- procedure id_signature; { the core of this program }
- CONST
- o_01 = 14; { relative offset from cstr0 to cstr1 }
- o_02 = 16; { " " " cstr0 to cstr2 }
- o_03 = 47; { " " " cstr0 to cstr3 }
- cstr0 = 'ntime'; { constant string existed in v4-6 }
- cstr1 = 'at '#0'.'; { constant string existed in v4-6 }
- cstr2 = '$4567'; { constant string existed in v5-6 }
- cstr3 = '83,90'; { constant string existed in v6 only }
- strlen = 5; { length of cstr? }
- ar_itm = 3; { items+1 of string array }
-
- { the following figures have been turn-up explicitly and
- should not be changed }
-
- ofs_rte = 25 shl 4; { get close to 'run time error' str contants }
- maxchar = 11 shl 4; { max. size of buffer; for scanning }
-
- TYPE
- arstr = array [0..ar_itm] of string[strlen];
- arbuf = array [0..maxchar] of char;
-
- VAR
- i, j, k : word; { index counter for array buffer }
- cstr : arstr; { signatures generated by tp compiler }
- o_fseg : word; { to hold segment value of any far call }
- o_sysseg: longint; { offset to tp system_unit_segment }
- buffer : arbuf; { searching for target strings }
-
- BEGIN
- {d} Seek(f, o_starup + 3); { move file pointer
- forward 3 bytes }
- {d} BlockRead(f, o_fseg, sizeof(o_fseg)); { get far call segment
- value }
- o_sysseg := longint(o_fseg) shl 4 +hdr_size; { ofs to system obj code }
- if (o_sysseg + ofs_rte <= dirfile.size) then
- BEGIN
- {d} Seek(f, o_sysseg+ofs_rte); { offset nearby tp
- signatures }
- {d} BlockRead(f, buffer, sizeof(buffer), blocks_r);
- for i := 0 to ar_itm do
- BEGIN
- cstr[i][0] := char(strlen);
- fillchar(cstr[i][1], strlen, '*');
- END;
- i := 1; j := 1; k := 0;
- repeat
- if buffer[i] in ['n','t','i','m','e'] then
- BEGIN
- if (k > 0) and (k = i - 1) then
- inc(j);
- cstr[0][j] := buffer[i];
- k := i;
- END;
- inc(i);
- until (cstr[0] = cstr0) or (i > maxchar) or (j > strlen);
- if (i+o_03 <= maxchar) then
- BEGIN
- dec(i, strlen);
- move(buffer[i+o_01], cstr[1][1], strlen);
- if (cstr[1] = cstr1) then
- BEGIN
- writeln(
- cr, 'Offset to TP system code:', dt, '':3,
- hexl(o_sysseg):9
- );
-
- write('Compiled by Borland TP v');
-
- move(buffer[i-o_02], cstr[2][1], strlen);
-
- if (cstr[2] = cstr2) then
- BEGIN
- move(buffer[i+o_03], cstr[3][1], strlen);
- if (cstr[3] = cstr3) THEN
- writeln('6.0')
- ELSE
- writeln('5.0/5.5');
- END
- ELSE
- writeln('4.0');
- END;
- END;
- END;
- END; {procedure}
-
- procedure process_exefile;
- CONST
- ofs_whdr = $3C; { offset to MS-Window exe file id }
- exwid = $454E; { MS-Window exe file id }
- VAR
- o_sign,
- fsize :longint;
- BEGIN
- if (exe_size = dirfile.size) then
- BEGIN
- print_info;
- if not compressed then
- id_signature;
- writeln;
- END
- else
- BEGIN
- {d} Seek(f, ofs_whdr); { offset to 'offset to window exe
- signature' }
- {d} BlockRead(f, hdr_size, sizeof(hdr_size));
- {d} if (hdr_size <= dirfile.size) then
- BEGIN
- Seek(f, hdr_size); { offset to new exe signature }
- {d} BlockRead(f, winhdr, sizeof(winhdr));
- END;
- if (winhdr.id = exwid) then
- BEGIN
- writeln('Dos/MS-Window EXE or DLL file');
- print_info;
- EXIT;
- END
- else
- BEGIN
- print_info;
- writeln(
- cr,
- 'file size (', exe_size, ') calculated from EXE header ',
- '(load by DOS upon exec)', cr,
- 'doesn''t match with file size (', dirfile.size, ') ',
- 'recorded on file directory.', cr, cr,
- '* EXE file saved with extra bytes at eof (e.g. debug info)', cr,
- '* EXE file may contain overlays', cr,
- '* possible a corrupted EXE file', cr
- );
-
- EXIT;
- END;
- END;
- END;
-
- procedure id_file;
- CONST
- exeid = $5A4D; { MS-DOS exe file id }
-
- VAR
- zero : str2;
-
- BEGIN
- if (exehdr.id = exeid) then
- BEGIN
- if (exehdr.cs = $FFF0) and
- (exehdr.ip = $0100) and
- (exehdr.ofs_rtbl = $50) or
- (exehdr.ofs_rtbl = $52) then
- BEGIN
- writeln('Compressed by PKLITE');
- compressed := true;
- END;
- if (exehdr.size = 2) and (exehdr.chk_sum = $899D) then
- BEGIN
- writeln( 'Compressed by DIET');
- compressed := true;
- END;
- if (exehdr.Lpage > 0) then
- exe_size := longint(exehdr.Fpages - 1) shl 9+exehdr.Lpage
- else
- exe_size := longint(exehdr.Fpages) shl 9;
- process_exefile;
- END
- else
- writeln('Not EXE file');
- END; {procedure}
-
- CONST
- blocksize = 1; { file r/w block size in one-byte unit }
-
- VAR
- path : dirstr;
- name : namestr;
- ext : extstr;
- fstr : string[48];
- n : byte;
-
- BEGIN
- if paramcount < 1 then
- n := 0
- else
- n := 1;
-
- fsplit(paramstr(n), path, name, ext);
- if (name+ext = '*.*') or (name+ext = '.' ) or (name+ext = '' ) then
- fstr := path+'*.exe'
- else
- if (path+ext = '') then
- fstr := paramstr(n)+'.exe'
- else
- if not boolean(pos('.', ext)) then
- BEGIN
- path := path+name+'\';
- fstr := path+'*.exe';
- END
- else
- fstr := paramstr(n);
-
- n := 0;
- {d} findfirst(fstr, anyfile, dirfile);
- while (doserror = no_error) do
- BEGIN
- if (dirfile.attr and volumeid <> volumeid) and
- (dirfile.attr and directory <> directory) and
- (dirfile.attr and sysfile <> sysfile) then
- BEGIN
- compressed := false;
- Assign(f, path+dirfile.name); {$I-}
- {d} Reset(f, blocksize); {$I+}
- if (IOResult = no_error) then
- BEGIN
- writeln(cr, dirfile.name);
- {d} BlockRead(f, exehdr, sizeof(exehdr), blocks_r);
- if (blocks_r = sizeof(exehdr)) then
- id_file
- else
- writeln('err:main');
- close(f);
- inc(n);
- END;
- END;
- {d} findnext(dirfile);
- END;
-
- if (n = 0) then
- if doserror = 3 then
- writeln('path not found')
- else
- writeln('file not found')
- else
- writeln(n,' files found');
- END.