Как "вручную" запускать Exe-файлы?
===================================================
Program EXELoader;
Uses Dos;
Type
EXEHeader = Record
Signature : Array[1..2] Of Char; { $5A4D EXE file signature ('MZ').}
PartialPage : Word; {Length of partial page at end (generally ignored).}
PagesCount : Word; {Length of image in 512-byte pages, include header.}
ReloCount : Word; {Number of items in relocation table.}
HeaderSize : Word; {Size of header in 16-byte paragraphs.}
MinAlloc : Word; {Minimum RAM needed above end of prog (paragraphs).}
MaxAlloc : Word; {Maximum RAM needed above end of prog (paragraphs).}
InitSS : Word; {Segment offset of stack segment (for setting SS).}
InitSP : Word; {Value for SP register when started.}
CheckSum : Word; {File checksum (negative sum of all words in file).}
InitIP : Word; {Value for IP register when started.}
InitCS : Word; {Segment offset of code segment (for setting CS).}
TableOffset : Word; {File-offset of first relo item (often 001cH).}
OverlayNumber : Word; {Overlay number (0 for base module).}
end;
Var
EXE : EXEHeader;
EXEData : Array[1..3000] Of Byte;
Stack : Array[1..5000] Of Byte;
EXEFile : File;
EXEByte : Byte;
Segment : Word;
Offset : Word;
Index : Word;
CPURegs : Registers;
ReloSeg : Word;
ReloOfs : Word;
Start : Pointer;
StackSeg : Word;
StartCS : Word;
Begin
Assign(EXEFile,'HELLO.EXE');
ReSet(EXEFile,1);
BlockRead(EXEFile,EXE,SizeOf(EXE));
WriteLn('EXEFileName=HELLO.EXE.');
WriteLn('EXESignature='+EXE.Signature[1]+EXE.Signature[2]);
WriteLn('BytesInPartialPage=',EXE.PartialPage,'.');
WriteLn('PagesInImage=',EXE.PagesCount,'.');
WriteLn('RelocationItems=',EXE.ReloCount,'.');
WriteLn('SizeOfHeader=',EXE.HeaderSize,'.');
WriteLn('MinimumMemory=',EXE.MinAlloc*$10,'.');
WriteLn('MaximumMemory=',EXE.MaxAlloc*$10,'.');
WriteLn('InitialSSSegment=',EXE.InitSS,'.');
WriteLn('InitialSPValue=',EXE.InitSP,'.');
WriteLn('InitialCSSegment=',EXE.InitCS,'.');
WriteLn('InitialIPValue=',EXE.InitIP,'.');
WriteLn('RelocationTableOffsetInFile=',EXE.TableOffset,'.');
WriteLn('EXECheckSum=',EXE.CheckSum,'.');
WriteLn('OverlayNumber=',EXE.OverlayNumber,'.');
WriteLn('ImageSize=',((EXE.PagesCount*512)-(EXE.HeaderSize*16))-EXE.PartialPage,'.');
Seek(EXEFile,EXE.TableOffset);
For Index:=1 To EXE.ReloCount Do
Begin
BlockRead(EXEFile,Offset,2);
BlockRead(EXEFile,Segment,2);
ReloSeg:=Seg(EXEData)+Segment;
MemW[ReloSeg:Offset]:=MemW[ReloSeg:Offset]+Segment;
end;
CPURegs.Ah:=$26;
CPURegs.Dx:=Seg(EXEData);
MsDos(CPURegs);
Seek(EXEFile,EXE.HeaderSize*16);
BlockRead(EXEFile,EXEData[$10A],((EXE.PagesCount*512)-(EXE.HeaderSize*16))-EXE.PartialPage,CPURegs.Ax);
Close(EXEFile);
Start:=Ptr(Seg(EXEData)+EXE.InitCS,EXE.InitIP);
StartCS:=Seg(EXEData)+EXE.InitCS;
StackSeg:=Seg(Stack)+EXE.InitSS;
Asm
Mov Ax,10h;
Cli;
Mov Sp,EXE.InitSP;
Mov Bp,StackSeg;
Mov Ss,Bp;
Sti;
Mov Dx,StartCS;
Push Dx;
Mov Dx,EXE.InitIP;
Push Dx;
Mov Dx,Seg EXEData;
Mov Es,Dx;
Mov Ds,Dx;
Retf;
end;
{ 11. Initialize registers and execute the program:
a. ES = DS = PSP
b. Set AX to indicate the validity of drive IDs in command line
c. SS = START_SEG+ReloSS, SP = ExeSP
d. CS = START_SEG+ReloCS, IP = ExeIP
}
end.
ExeHeaderRec
Offset Size Contents
ßßßßßß ßßßß ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
+0 2 wSignature 5a4dH .EXE file signature ('MZ')
+2 2 wPartPage length of partial page at end (generally ignored)
+4 2 wPageCnt length of image in 512-byte pages, incl. header
+6 2 wReloCnt number of items in relocation table
+8 2 wHdrSize size of header in 16-byte paragraphs
+0aH 2 wMinAlloc minimum RAM needed above end of prog (paragraphs)
+0cH 2 wMaxAlloc maximum RAM needed above end of prog (paragraphs)
+0eH 2 wInitSS segment offset of stack segment (for setting SS)
+10H 2 wInitSP value for SP register when started
+12H 2 wChkSum file checksum (negative sum of all words in file)
+14H 2 wInitIP value for IP register when started
+16H 2 wInitCS segment offset of code segment (for setting CS)
+18H 2 wTablOff file-offset of first relo item (often 001cH)
+1aH 2 wOverlayNo overlay number (0 for base module)
28 size of formatted portion of EXE header
+? 4*? alReloTbl variable-length relocation table
+? ? abFiller filler to paragraph boundary
+? ? abImage start of program image
Since an EXE file may be loaded on any segment, all absolute segment
references (such as FAR CALLs, long address pointers, and references such
as MOV AX,data_seg) must be adjusted to work for the memory location in
which they are loaded. Here are the steps used by the DOS program loader
(fn 4bH ) to load an EXE file:
1. Create a PSP via DOS Fn 26H.
2. Read 1cH bytes of the EXE file (the formatted portion of the EXE
header) into a local memory area.
3. Determine the load module size:
size=((wPageCnt*512)-(wHdrSize*16))-wPartPage
4. Determine file offset of load module = (wHdrSize * 16)
5. Select a segment addr, START_SEG, for loading (usually PSP+10H)
6. Allocate enough memory to hold the load module, honoring the
settings in wMaxMem and wMinMem.
7. Read the load module into memory starting at START_SEG:0000
8. LSEEK to the start of the relocation table (wTablOff)
9. For each relocation item (wReloCnt):
a. read the item as two 16-bit words (I_OFF,I_SEG)
b. add RELO_SEG=START_SEG+I_SEG (find the address of
relocation ref)
c. fetch the word at RELO_SEG:I_OFF (read current value)
d. add START_SEG to that word (perform the segment fixup)
e. store the sum back at its original address (RELO_SEG:I_OFF)
10. Allocate memory for the program according to wMaxMem and wMinMem
11. Initialize registers and execute the program:
a. ES = DS = PSP
b. Set AX to indicate the validity of drive IDs in command line
c. SS = START_SEG+ReloSS, SP = ExeSP
d. CS = START_SEG+ReloCS, IP = ExeIP
Note: Recent additions to the EXE format, specifically the CodeView,
OS/2, and Windows versions of the EXE file contain additional
information embedded in the executable file. Sorry, but these
additions are not covered here.
Если Win, то CreateProcess( ...... ) все тебе запустит.
Цитата:
Originally posted by inquirer
Я почитал справку в TechHelp и написал на Паскале програмку, которая должна вроде бы нормально таблицу релокаций обрабатывать и готовить регистры к запуску екзешника. Несмотря на мои отчаянные старания соделать что-то нормальное, ничего у меня не получилось. Сколько ни смотрел, нигде не смог найти исходник на Паскале или Бейсике, который бы прочитывал из файла екзешник, настраивал таблицы релокейшинов и запускал его на выполнение, а затем чтобы происходил возврат назад в мою программу. Запускать *.COM-файлы легко - я писал подобные проги ещё несколько лет назад (чтобы не воспринимали меня не всерьёз, думая, мол, "тупой пацанчик не знает как писать", скажу в защиту своей репутации - мне почти 23 года, у меня опыт работы в Паскале, Си, Бейсике и Ассемблере - пять лет! Причём в среде ДОС. Так что помогите, прошу Вас!!!). Ниже приводится собственно мой галимый исходник:
Я почитал справку в TechHelp и написал на Паскале програмку, которая должна вроде бы нормально таблицу релокаций обрабатывать и готовить регистры к запуску екзешника. Несмотря на мои отчаянные старания соделать что-то нормальное, ничего у меня не получилось. Сколько ни смотрел, нигде не смог найти исходник на Паскале или Бейсике, который бы прочитывал из файла екзешник, настраивал таблицы релокейшинов и запускал его на выполнение, а затем чтобы происходил возврат назад в мою программу. Запускать *.COM-файлы легко - я писал подобные проги ещё несколько лет назад (чтобы не воспринимали меня не всерьёз, думая, мол, "тупой пацанчик не знает как писать", скажу в защиту своей репутации - мне почти 23 года, у меня опыт работы в Паскале, Си, Бейсике и Ассемблере - пять лет! Причём в среде ДОС. Так что помогите, прошу Вас!!!). Ниже приводится собственно мой галимый исходник:
ShellExecute, WinExec ещё есть
#include <stdio.h>
#include <conio.h>
#define start_addr 0x1912
struct file_header
{
//File of MZ-Format
unsigned short Signature;
unsigned short SizeLastPage;
unsigned short MZLegthFile;
unsigned short SizeOfJumpTable;
unsigned short SizeOfHeader;
unsigned short MinExtPara;
unsigned short MaxExtPara;
unsigned short ss_reg;
unsigned short sp_reg;
unsigned short ControlSum;
unsigned short ip_reg;
unsigned short cs_reg;
unsigned short OffsetJumpTable;
unsigned short NumOvrModule;
//File of NE-Format
};
struct JumpTable
{
unsigned short offset;
unsigned short segment;
};
char far *buf=(char far *)0x19120000L;
void main()
{
file_header file;
JumpTable JT;
FILE *infile;
unsigned long file_size;
clrscr();
infile=fopen("test.exe","r");
if (!infile)
return;
fseek(infile,0,SEEK_END);
file_size=ftell(infile);
fseek(infile,0,SEEK_SET);
fread(&file, 1, sizeof(file_header), infile);
cout << "Signature: " << (char)(file.Signature & 0xff)
<< (char)((file.Signature & 0xff00) >> 8) << endl;
cout << "Size of last page: " << file.SizeLastPage << endl;
cout << "Size of file of MZ-format: "
<< (long)file.MZLegthFile*512 << endl;
cout << "Size of jump table: "
<< file.SizeOfJumpTable << endl;
cout << "Size of header: " << file.SizeOfHeader*16 << endl;
cout << "Min of extended paragraphs: " << file.MinExtPara << endl;
cout << "Max of extended paragraphs: " << file.MaxExtPara << endl;
cout << "SS register: " << file.ss_reg << endl;
cout << "SP register: " << file.sp_reg << endl;
cout << "Control sum: " << file.ControlSum << endl;
cout << "IP register: " << file.ip_reg << endl;
cout << "CS register: " << file.cs_reg << endl;
cout << "Offset of jump table: " << file.OffsetJumpTable << endl;
cout << "Number of overlay module: " << file.NumOvrModule << endl;
cout << endl;
fseek(infile,file.SizeOfHeader*16,SEEK_SET);
fread(buf,1,file_size-file.SizeOfHeader,infile);
int i;
cout << hex;
fseek(infile, file.OffsetJumpTable, SEEK_SET);
unsigned short far *ptr;
unsigned long addr;
for(i=0; i<file.SizeOfJumpTable; i++)
{
fread(&JT, 1, 4, infile);
addr=(start_addr+JT.segment);
addr<<=16;
addr+=JT.offset;
// cout << "addr=" << addr << endl;
ptr=(unsigned short *)addr;
// cout << hex << "*ptr=" << *ptr << endl;
(*ptr)=(*ptr)+start_addr;
// cout << hex << "*ptr=" << *ptr << endl;
// cout << "Addr(" << (i+1) << "): " << JT.segment << ':' << JT.offset << endl;
}
// cin >> i;
// clrscr();
asm {
pusha
push es
push ds
mov ax,start_addr+4
mov ss,ax
mov sp,256
db 0xea
dw 0
dw start_addr
pop ds
pop es
popa
}
cin >> file_size;
fclose(infile);
}
Правда, немного Beta версия и некоторые названия переменных корявые слегка... писал в Borland C 5.02 (на всяк случай)... начал писать, потом бросил... тестировал на проге кот. выводит два сообщения "Hello!" друг под другом, второе сообщение смещается почему-то вправо... если что пиши в асю 258464925... я тоже
люблю DOS... :)
Цитата:
...
#define start_addr 0x1912
...
и еще... start_addr взял из Turbo Debbuger'a, просто взял файл "test.exe", закинул его в дебагер и посмотрел значение регистра CS...
Цитата:
...
mov ax,start_addr+4
mov ss,ax
...
значение SS, от туда же... только надо смотреть относительно CS (+4)...
модель файла "test.exe" - LARGE, размер стека - 256
JumpTable - RealocationTable (у меня название корявое)
терь, вроде всё...