Studna
Studna > ╚lßnky > Runtime Error at ... > RTE 00:06



Runtime Error at 00:06 aneb SpustitelnΘ soubory

V tomto dφle RTEΦka je menÜφ pojednßnφ o spustiteln²ch souborech. Snahou bylo zp°φstupnit co nejvφce informacφ o souborech typu EXE, COM, DLL a tak dßle. ╚erpal jsem z n∞kolika dokument∙ a trochu se r∙znφ, tak₧e snad vyberu jen to nejlepÜφ.

COM program

NejstarÜφ spustiteln² soubor, kter² se objevoval snad u₧ pod operaΦnφm systΘmem CP/M a jeÜt∞ nynφ se objevujφ guruovΘ, kte°φ je pφÜφ (nap° fox :-)))).

Program typu com se cel² nahrßvß do jednoho segmentu, tudφ₧ jeho dΘlka musφ b²t nejvφce FFFFh bytes (ale v∞tÜinou asi o 200 bytes menÜφ) a musφ mφt data a k≤d v tomto jednom segmentu. Nemß hlaviΦku a na zaΦßtku je (v∞tÜinou) skok na startovacφ mφsto. Obvykle se program nahrßvß od adresy 100h (myslφm, ₧e se to nastavuje p°φkazem org 100h, ale ruku bych za to do ohn∞ nedal), Φeho₧ se dß vyu₧φt pro n∞jakΘ samozobrazovßnφ (viz. RTE at 00:02) nebo podobnΘ akce. StaΦφ si ·pln∞ na konec programu v assembleru dßt label jako ukazatel na data a potΘ klasick²m p°φkazem copy /b program.com + data.dtx program.com vytvo°it com program i s daty (musφte ovÜem dßt pozor na dΘlku koneΦnΘho souboru !!!!!!!).

EXE program

Nov∞jÜφ nßstupce comu, v∞tÜina z nßs se s nφm ji₧ setkala :-), proto₧e ho vytvß°ejφ skoro vÜechny kompilßtory od tasm p°es bp a delphi a₧ po kompilßtory cΘΦka. S p°φchodem windows∙ se jejich struktura mφrn∞ zm∞nila a rozÜφ°ila.

EXE program zaΦφnß hlaviΦkou, kterß je NEJM╔N╠ 32 bytes dlouhß, ale m∙₧e byt i delÜφ (nap°. tasm vytvß°φ hlaviΦku dlouhou 512 bytes). HlaviΦka je tzv. paragraph-aligned, co₧ znamenß, ₧e jejφ dΘlka je v nßsobcφch 16ti (pokud je hlaviΦka 512-aligned, dos ji pr² zavßdφ rychleji).

Klasickß hlaviΦka DOSovskΘho programu mß tuto strukturu:

nßzev	offset	dΘlka	popis	
Signat	00h		word	.exe signatura, v∞tÜinou word 5A4Dh = 'MZ' nebo  4D5Ah = 'ZM'	
PartPag	02h		word	poΦet byt∙ v poslednφ strßnce (strßnka=512 bytes)	
PageCnt	04h		word	poΦet strßnek i s hlaviΦkou (poslednφ strßnka, kterß nemß 512 bytes) se zapoΦφtßvß takΘ)	
ReloCnt	06h		word	poΦet polo₧ek v relokaΦnφ tabulce	
HdrSize	08h		word	dΘlka hlaviΦky v paragrafech (zapoΦφtßvß se i relokaΦnφ tabulka), hodφ se pro nalezenφ poΦßtku zavßd∞nΘho modulu v souboru)	
MinMem	0Ah		word	minimßlnφ pam∞¥ pot°ebnß za koncem programu (v paragrafech)	
MaxMem	0Ch		word	maximßlnφ pam∞¥ pot°ebnß za koncem programu (v paragrafech), je-li MinMem = MaxMem = 0, program je nahrßn co nejv²Üe	
ReloSS	0Eh		word	poΦßteΦnφ hodnota SS relativnφ ke startu programu (musφ se relokovat)	
ExeSP	10h		word	poΦßteΦnφ hodnota registru SP	
ChkSum	12h		word	kontrolnφ souΦet (dopln∞k k souΦtu vÜech word∙ souboru)	
ExeIP	14h		word	poΦßteΦnφ hodnota registru IP	
ReloCS	16h		word	poΦßteΦnφ hodnota pro nastavenφ CS (musφ se relokovat)	
TablOff	18h		word	pozice prvnφ relokaΦnφ tabulky v souboru (v∞tÜinou na pozici 001Ch)	
Overlay	1Ah		word	Φφslo overlaye (pro hlavnφ program 00h)	

DΘlka hlaviΦky (formßtovanΘho zßhlavφ) je 1Ch. Z tΘto tabulky se dajφ vypoΦφtat zajφmavΘ hodnoty, pou₧itelnΘ pro prßci s exe-programy. Nap°φklad dΘlka zavßd∞nΘho modulu exe-souboru se vypoΦφtß takto:

((PageCnt*512)-(HdrSize*16)-PartPag;

Celkovß dΘlka exe-souboru se vypoΦφtß takto:

If PartPag=0 then PartPag:=512;
((PageCnt-1)*512)+PartPag;

DΘlka hlaviΦky (nebo offset zavßd∞nΘho modulu - zaΦφnß zde t∞lo exe-souboru):

HdrSize*16;

Za formßtovanou Φßstφ hlaviΦky dßle nßsleduje relokaΦnφ tabulka (pokud je ReloCnt <> 0) o dΘlce ReloCnt * 4 s tφmto formßtem:

RelokaΦnφ tabulka se pou₧φvß z d∙vodu, ₧e exe program m∙₧e b²t nahrßn na jakoukoliv adresu (do libovolnΘho segmentu) a vÜechny ukazatele na pam∞¥ (nap°. FAR CALL, dlouhΘ pam∞¥ovΘ ukazatele a odkazy typu MOV AX,data_seg) musφ b²t upraveny na adresy, na kterΘ jsou nahrßny. To se provßdφ nßsledovn∞:

var i, t_ofs, t_seg, relo_seg, hodnota:word

for i:=1 to relocnt do begin {opakuj pro kazdou polozku}
  nacti t_ofs, t_seg {nacti ze souboru polozku jako dva wordy}
  relo_seg := start_seg + t_seg {pricti startovaci segment}
  hodnota := memw[relo_seg:t_ofs] {nacti aktualni hodnotu}
  hodnota := hodnota + start_seg {pricti k ni start. segment}
  memw[relo_seg:t_seg] := hodnota {uloz hodnotu zpet}
end

Tak a mßme upraveny vÜechny skoky a odkazy na segment, v kterΘm je program nahrßn. Dßle se jeÜt∞ musφ upravit hodnoty pro ReloSS a ReloCS tφm, ₧e k nim op∞t p°iΦteme startovacφ segment.

Za relokaΦnφ tabulkou nßsleduje v²pl≥ na hranici paragrafu a pak ji₧ samotnΘ t∞lo programu.

Detailnφ popis nahrßvßnφ exe souboru je v²born∞ popsßn v SYSMANovi, tak₧e to sem nebudu p°episovat.

novΘ p°φdavky

Asi tak nejd∙le₧it∞jÜφm zßsahem do programu exe jsou ·pravy pro novΘ OS (jako nap°φklad wind≤zy a OS/2).

Zda se jednß o tento formßt programu se dß zjistit naΦtenφm doublewordu na adrese 3Ch od zaΦßtku souboru, pokud je na tΘto adrese n∞co ne₧ 00000000h (co₧ je pro klasick² dosovsk² program - jak kdy, pokud mß program dlouhou relokaΦnφ tabulku, tak ta zasahuje i do tΘto Φßsti a tento doubleword obsahuje n∞co jinΘho ne₧ 0), podφvßme se na tuto adresu. Zde by m∞lo b²t n∞jakΘ slova z tΘto tabulky:

NE	windows nebo os/2 1.x "new executable" program (segmentovan²)	
LE	windows virtual device driver (VxD) (lineßrnφ)	
LX	varianta LE pou₧φvanß v os/2 2.x	
W3	windows WIN386.EXE soubor (kolekce LE soubor∙)	
W4	windows95 VMM32.VXD soubor	
PE	win32 (win NT a win32s) p°enositeln² program zalo₧en² na Unix COFF	

Pokud tam je, jednß se o n∞jak² rozÜφ°en² formßt exe souboru (pokud ne, jednß se o dosovsk² exe program). Tyto programy majφ takΘ obvyklou dosovou hlaviΦku, ve kterΘ jsou hodnoty odkazujφcφ na tzv. stub program (kra¥oulinkat² exe), kter² nßm vypφÜe, ₧e "This program must be run under Microsoft Windows." nebo "This program cannot be run in a DOS session." a odskoΦφ zp∞t do dosu. Tato hlaviΦka je v∞tÜinou 82h bytes dlouhß (obvykle obsahuje i n∞kterou z v²Üe uveden²ch signatur rozÜφ°enΘho exe souboru) a neobsahuje relokaΦnφ tabulku (obvykle).

Stub-program si m∙₧eme naprogramovat sami (ale jde to jen v C-Φku, paskalu asi ne) a ud∞lat nap°φklad program, kter² ve woknech napφÜe, ₧e vy₧aduje dos a ukonΦφ se (tak, jak to d∞lajφ windousovskΘ programy v dosu). Ve stub-programu se m∙₧e provßd∞t skoro cokoliv, akorßt musφ b²t kratÜφ ne₧ 64kb a relokaΦnφ tabulka stub-u musφ b²t za adresou 003Dh (co₧ pr² nenφ problΘm pro Φerstv∞ zkompilovanΘ nebo PKLITEm zabalenΘ programy).

V²bornou ukßzkou vyu₧itφ stub-u jsou pomocnΘ programy ke QEMMu 8.0 od Quarterdecku, kterΘ majφ stub ud∞lan², aby se v dosu spustila dosovskß verze a ve windousech se spustil windousowskß verze (d∞lß to nap°. Manifest). Za nevhodnΘ pova₧uji to, kdy₧ si windousowsk² program spuÜt∞n² v dosu spustφ windousy se sebou (kdo mß Φekat na to, a₧ se mu to spustφ, ne ?!?!)

Jedna poznßmka: DLL knihovny (.dll) , screensavery (.scr), fonty (.fon), knihovny OCX, VBX, device drivery (.drv) jsou vÜechno spustitelnΘ programy (majφ rozÜφ°enφ 'PE', 'NE' nebo 'LE'). Jo, TrueType fonty majφ formßt shodn² s fonty v os/2 (schvßln∞ se podφvejte na truetype font z w95 a najd∞te si °et∞zec 'OS/2'.

V hlaviΦce exe-souboru se takΘ dajφ nalΘzt informace o tom, Φφm byl program linkovßn, pakovßt atd. Zde je popis toho zajφmav∞jÜφho:

Borland TLINK

offset 	1Eh	byte	signatura FBh
	1Fh	byte	verze TLINK u (hlavnφ Φφslo ve vyÜÜφch 4 bitech, vedlejÜφ v ni₧Üφch)

ARJ - samorozbalovacφ archφv

offset	1Ch	dword	signatura "RJSFX" (starÜφ verze, novß signatura je "aRJsFX" v prvnφch 1000 bytech souboru

LZEXE 0.90 zabalen² spustiteln² soubor

offset	1Ch	dword	signatura "LZ09"

LZEXE 0.91 zabalen² spustiteln² soubor

offset	1Ch	dword	signatura "LZ91"

PKLITE zabalen² spustiteln² soubor offset 1Ch byte vedlejÜφ Φφslo verze 1Dh byte bity 0-3: hlavnφ Φφslo verze bit 4: extra komprese bit 5: velk² (multi-segmentov²) soubor 1Eh 6 bytes signatura "PKLITE" nßsledovanß zprßvou o copyrightu

LHarc 1.x samorozbalovacφ archφv

offset	20h	3bytes	skok na start vybalovacφho k≤du
	25h	12 bytes	signatura "LHarc's SFX"

LHA 2.x samorozbalovacφ archφv

offset	24h	10 bytes	signatura "LHa's SFX" (verze 2.10) nebo "LHA's SFX" (v 2.13)

RAR samorozbalovacφ archφv

offset	1Ch	4 bytes	signatura "RSFX"

Jak pou₧φvat data, p°ipojenß k EXE souboru

P°ipojenφ dat k exe souboru se provßdφ znßm²m zp∙sobem (jen pro p°ipomenutφ: copy /b program.exe + data.dtx program2.exe. Jak ale na tato data p°istupovat. Dß se to provΘst takto:

var f:file;
    pagecnt,partpag:word; 
    dummy:word;
    seeking:longint;
begin
assign(f,paramstr(0)); reset(f,1); {otevre sam sebe}
blockread(f,dummy,2);{preskoci 'MZ'}
blockread(f,partpag,2);{nacte pocet bytu na posledni strance}
blockread(f,pagecnt,2);{nacte pocet stranek}
if partpag=0 then partpag:=512;{pokud je posledni stranka 512-bytes aligned}
seeking:=(pagecnt-1)*512+partpag;{kde zacinaji data}
seek(f,seeking);{presuneme se na konec}
end;

Zde jen malß poznßmka:

  1. Pokud je partpag rovno nule, je program zarovnßn na 512 bytes, a jeliko₧ pagecnt je poΦet strßnek i s ne·plnou strßnkou, musφme polo₧ku partpag (pokud je nulovß) naplnit hodnotou 512.
  2. Funkce FileSize v borland pascalu vracφ celkovou dΘlku programu, tedy i s p°ipojen²mi daty, proto m∙₧eme vypoΦφtat dΘlku p°ipojen²ch dat pomocφ filesize(f)-seeking, co₧ se obΦas m∙₧e hodit.

Jinak p°iklßdßm takΘ zdrojßky k mΘ unit∞ Mygrp, kterß se starß o prßci s group-soubory (vφce soubor∙ spojen²ch do jednoho velkΘho), zjiÜ¥uje si sama, zda je grp soubor p°ipojen za exe-program nebo je mimo, pou₧φvß kompresi (voliteln∞) a tak dßle.

Jak p°evΘst com na exe

To se provede velice jednoduÜe. P°ipravφme si 32 bytes dlouhou hlaviΦku a za nφ zapφÜeme cel² com soubor. Je nutnΘ si uv∞domit, ₧e dos nahrßvß t∞lo exe souboru na adresu PSP+10h:0 a p°ipoΦφtßvß ji k ReloCS a tato hodnota je pak CS programu. ProblΘm je v tom, ₧e com program se nahrßvß na adresu PSP segmentu, proto musφ mφt polo₧ka ReloCS hodnotu FFF0h, kterß je pak p°idßna k hodnot∞ PSP+10h a zφskßvßme PSP segment.

Progrßmek by mohl vypadat takto:

program com2exe;

{nevytvari true-exe!}

type
  hlava=record
    signature:array[1..2]of char; {'MZ' nebo 'ZM'}
    partpag:word;   {pocet bytes v posledni strance}
    pagecnt:word;   {pocet stranek}
    relocnt:word;   {pocet relokacnich polozek}
    hdrsize:word;   {delka hlavicky v paragrafech (*16 bytes)}
    minmem:word;    {minimalni potrebna pamet}
    maxmem:word;    {maximalni potrebna pamet}
    reloss:word;
    exesp:word;
    chksum:word;    {kontrolni soucet (vetsinou 0)}
    exeip:word;
    relocs:word;
    tabloff:word; {zacatek relokacni tabulky (ofs od zacatku)}
    overlay:word; {pocet overlayu (vetsinou 0)}
  end;

var fi,fo:file;
    h:hlava;
    dummy:longint;
    i,j:integer;
    b:array[1..2048]of byte;

begin
  writeln('com2exe convertor v0.1 freeware by paulsoft/no!future (c) 1997'); writeln;
  if paramcount<>2 then writeln('parameterz: infile.com outfile.exe') else begin
  {$i-}assign(fi,paramstr(1)); reset(fi,1);

  if ioresult<>0 then begin writeln('error while opening input file'); halt(1); end;
  assign(fo,paramstr(2)); rewrite(fo,1); {$i+}
  if ioresult<>0 then begin writeln('error while opening output file'); halt(1); end;
  h.signature:='ZM';{at se trochu lisime}
  h.partpag:=(filesize(fi)+32) mod 512;
                   {pocet bytu v posledni strance}
  h.pagecnt:=round((filesize(fi)+32)/512)+1; {pocet stranek}
  h.relocnt:=0;    {relokacni tabulku nepotrebujem}
  h.hdrsize:=2;    {delka hlavicky je 2 paragrafy (32bytes)}
  h.minmem:=($ffff-filesize(fi))div 16;      {minimum pameti}
  h.maxmem:=$ffff;                 {maximum pameti - vsechna}
  h.reloss:=$fff0; {pretece to}
  h.exesp:=$fffe;  {vlastnost comu}
  h.chksum:=0;
  h.exeip:=$100;   {vlastnost comu}
  h.relocs:=$fff0; {stejne jako sp}
  h.tabloff:=0;    {relokacni tabulku nepotrebujem - cokoliv}
  h.overlay:=0;    {overlaye nemame}
  blockwrite(fo,h,sizeof(h));
  dummy:=$114A5010;{musime doplnit hlavicku na 32bytes}
  blockwrite(fo,dummy,sizeof(dummy));
  repeat
    blockread(fi,b,sizeof(b),i);
    blockwrite(fo,b,i,j);
  until (i=0)or(i<>j);
  close(fi); close(fo);
  writeln('converting done');
  end;
end.

jak si do hlaviΦky text napsat

Do hlaviΦky si m∙₧eme napsat jakΘkoliv texty nebo si ji m∙₧eme zkompresovat (nap°. po kompilaci tasmem se vytvß°φ hlaviΦka dlouhß 512 bajt∙, ale mohla by b²t dlouhß t°eba jen 48 bajt∙). StaΦφ si p°eΦφst hlaviΦku, relokaΦnφ tabulku, v hlaviΦce upravit pozici relokaΦnφ tabulky, dΘlku hlaviΦky v paragrafech, doplnit hlaviΦku na dΘlku paragrafu (tzn. aby jejφ dΘlka byla d∞litelnß 16ti bezezbytku) a vÜe zapsat do novΘho souboru i s t∞lem programu. M∙₧eme si do hlaviΦky zapsat takΘ n∞jakΘ texty a ud∞lat v podstat∞ to sam² a kdekdo bude p°ekvapen, co to v tΘ hlaviΦce mßme.

Napsal jsem takΘ progrßmek v pascalu, jmenuje se exetext.pas, kter² toto vÜechno provßdφ (mßm pocit, ₧e i hlaviΦku zkrßtφ). Program funguje, ale obΦas funguje trochu zßhadn∞, proto₧e mi dos po spuÜt∞nφ upravenΘho souboru oznamuje, ₧e tento exe mß Üpatn² formßt :-(( Tak₧e neruΦφm za poÜkozenφ program∙!!!!!!! (Jß vßs varoval).

Doufßm, ₧e jsem pokryl skoro vÜechno pot°ebnΘ.

Zdar Pavel

Pou₧itß literatura:
Advanced linking 1, 2 - Φlßnek v Φasopise Imphobia 10 od Ervina z Abaddon
Sysman 3.1
Ralf Brown's Interrupt List Release 53 (12.1.97)

Pou₧itΘ programy:
Hacker's View v 4.16 by SEN 1991-1993
Hexlist v0.2 by paulsoft/no!future 1997


kontakt:
mail jislp@feld.cvut.cz
http http://cs.felk.cvut.cz/~jislp/
irc kanßly #cs, #cz, #cesi; nick xpj


Zp∞t nahoru ]
Copyright © 1997, 1998 Pavel Jisl, jislp@feld.cvut.cz