Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];

Вниз

Как считать версию файла,образ которого находится в памяти ?   Найти похожие ветки 

 
Vorobyev Sergey   (2003-07-02 14:19) [0]

Привет всем!

ВОПРОС: Можно ли как-нибудь определить версию файла (аналогично функции API GetFileVersionInfo) для образа файла, который находится в памяти, НЕ ЗАПИСЫВАЯ ЕГО НА ДИСК (даже во временную папку)..?

ПОЯСНЕНИЕ: Дело в том, что исполнимый файл, версию которого необходимо определить, находится в ресурсах другой программы. Файл извлекается в память, необходимо определить его версию и в зависимости от этого он записывается на диск (или нет) и исполняется..
--
Спасибо


 
Soft   (2003-07-02 16:15) [1]

The CreateFileMapping function creates a named or unnamed file-mapping object for the specified file.

HANDLE CreateFileMapping(

HANDLE hFile, // handle to file to map
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security attributes
DWORD flProtect, // protection for mapping object
DWORD dwMaximumSizeHigh, // high-order 32 bits of object size
DWORD dwMaximumSizeLow, // low-order 32 bits of object size
LPCTSTR lpName // name of file-mapping object
);


 
Игорь Шевченко   (2003-07-02 17:26) [2]

Можно. Чтением и обработкой ресурса типа RT_VERSION


 
AlexRush   (2003-07-02 19:34) [3]

Аж самому интересно стало.
Написал процедурку. Работает, проверял.



function MapPEfromResource(resName,resType:string):DWORD;
var hFile,hRes,hResData:DWORD;
ptrResLock :pointer;
ptrMZ :PIMAGE_DOS_HEADER;
ptrPE :PIMAGE_NT_HEADERS;
ptrSH :PIMAGE_SECTION_HEADER;
hMappedPE :PIMAGE_DOS_HEADER;
dw :DWORD;
i :integer;
p:pointer;
begin
result:=0;
// Ищем ресурс, содержащий ПЕ
hRes:=FindResourceA(hInstance,PChar(resName),PChar(resType));
if (hRes=0)
then begin
result:=1;// внутренний код ошибки
exit;
end;
// Загружаем оный
hResData:=LoadResource(hInstance,hRes);
if (hResData=0)
then begin
result:=2;
exit;
end;
// получаем указатель на его данные
ptrResLock:=nil;
ptrResLock:=LockResource(hResData);

// для наглядности ptrMZ - указатель на DOS заголовок
ptrMZ:=ptrResLock;
// ptrPE - указатель на PE заголовок
ptrPE:=mkptr(ptrMZ,ptrMZ^._lfanew);
// проверка сигнатуры ПЕ
if ptrPE^.Signature<>IMAGE_NT_SIGNATURE
then exit;

// ptrSH - указатель на таблицу секций
ptrSH:=mkptr(ptrPE,sizeof(ptrPE^));
// здесь считаем необходимый размер памяти под загрузку ПЕ
dw:=0;
for i:=0 to ptrPE^.FileHeader.NumberOfSections-1
do begin
if (ptrSH^.VirtualAddress+ptrSH^.SizeOfRawData)>dw
then dw:=ptrSH^.VirtualAddress+ptrSH^.SizeOfRawData;
inc(ptrSH);
end;
inc(dw,sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_NT_HEADERS)+4096);

// и выделяем ее
hMappedPE:=HeapAlloc(GetProcessHeap(),0,dw);

// копируем DOS заголовок, Stub и PE заголовок
dw:=sizeof(ptrMZ^)+ptrMZ^._lfanew+sizeof(ptrPE^);
CopyMemory(hMappedPE,
ptrMZ,
dw);
ptrSH:=mkptr(ptrPE,sizeof(ptrPE^));

// копируем таблицк секций
CopyMemory(mkptr(hMappedPE,dw),
ptrSH,
ptrPE^.FileHeader.NumberOfSections*sizeof(ptrSH^));

// копируем секции согласно RVA
for i:=0 to ptrPE^.FileHeader.NumberOfSections-1
do begin
p:=mkptr(hMappedPE,ptrSH^.VirtualAddress);
CopyMemory(p,
mkptr(ptrMZ,ptrSH^.PointerToRawData),
ptrSH^.SizeOfRawData);
inc(ptrSH);
end;
// ВНИМАНИЕ !!!
// НЕ призводится развязка relocations"сов,
// Запускать (передавать управление нельзя !)

// рэзалт - хендл (он же указатель) загруженного модуля
result:=DWORD(hMappedPE);
end;


Ресурс в файл:


function ResourceExtractToFile(hInst:DWORD;resName,resType,FullFileName:string):DWORD;stdcall;
var hFile,dw_writed:DWORD;
hRes,hResData:DWORD;
ptrResLock:pointer;
begin
hRes:=FindResourceA(hInstance,PChar(resName),PChar(resType));
if (hRes=0)
then begin
result:=1;
exit;
end;
hResData:=LoadResource(hInstance,hRes);
if (hResData=0)
then begin
result:=2;
exit;
end;
ptrResLock:=nil;
ptrResLock:=LockResource(hResData);
if not Assigned(ptrResLock)
then begin
result:=3;
exit;
end;

//ptrResLock


hFile:= CreateFile("_testFile.exe",
GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_READ,
nil,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
if(hFile=INVALID_HANDLE_VALUE)
then begin
result:=4;
exit;
end;
dw_writed:=SizeofResource(hInstance,hRes);
if not LongBool(WriteFile(hFile,ptrResLock,dw_writed,@dw_writed,nil))
then begin
CloseHandle(hFile);
result:=5;
exit;
( hFile)
Аж самому интересно стало.
Написал процедурку. Работает, проверял.



function MapPEfromResource(resName,resType:string):DWORD;
var hFile,hRes,hResData:DWORD;
ptrResLock :pointer;
ptrMZ :PIMAGE_DOS_HEADER;
ptrPE :PIMAGE_NT_HEADERS;
ptrSH :PIMAGE_SECTION_HEADER;
hMappedPE :PIMAGE_DOS_HEADER;
dw :DWORD;
i :integer;
p:pointer;
begin
result:=0;
// Ищем ресурс, содержащий ПЕ
hRes:=FindResourceA(hInstance,PChar(resName),PChar(resType));
if (hRes=0)
then begin
result:=1;// внутренний код ошибки
exit;
end;
// Загружаем оный
hResData:=LoadResource(hInstance,hRes);
if (hResData=0)
then begin
result:=2;
exit;
end;
// получаем указатель на его данные
ptrResLock:=nil;
ptrResLock:=LockResource(hResData);

// для наглядности ptrMZ - указатель на DOS заголовок
ptrMZ:=ptrResLock;
// ptrPE - указатель на PE заголовок
ptrPE:=mkptr(ptrMZ,ptrMZ^._lfanew);
// проверка сигнатуры ПЕ
if ptrPE^.Signature<>IMAGE_NT_SIGNATURE
then exit;

// ptrSH - указатель на таблицу секций
ptrSH:=mkptr(ptrPE,sizeof(ptrPE^));
// здесь считаем необходимый размер памяти под загрузку ПЕ
dw:=0;
for i:=0 to ptrPE^.FileHeader.NumberOfSections-1
do begin
if (ptrSH^.VirtualAddress+ptrSH^.SizeOfRawData)>dw
then dw:=ptrSH^.VirtualAddress+ptrSH^.SizeOfRawData;
inc(ptrSH);
end;
inc(dw,sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_NT_HEADERS)+4096);

// и выделяем ее
hMappedPE:=HeapAlloc(GetProcessHeap(),0,dw);

// копируем DOS заголовок, Stub и PE заголовок
dw:=sizeof(ptrMZ^)+ptrMZ^._lfanew+sizeof(ptrPE^);
CopyMemory(hMappedPE,
ptrMZ,
dw);
ptrSH:=mkptr(ptrPE,sizeof(ptrPE^));

// копируем таблицк секций
CopyMemory(mkptr(hMappedPE,dw),
ptrSH,
ptrPE^.FileHeader.NumberOfSections*sizeof(ptrSH^));

// копируем секции согласно RVA
for i:=0 to ptrPE^.FileHeader.NumberOfSections-1
do begin
p:=mkptr(hMappedPE,ptrSH^.VirtualAddress);
CopyMemory(p,
mkptr(ptrMZ,ptrSH^.PointerToRawData),
ptrSH^.SizeOfRawData);
inc(ptrSH);
end;
// ВНИМАНИЕ !!!
// НЕ призводится развязка relocations"сов,
// Запускать (передавать управление нельзя !)

// рэзалт - хендл (он же указатель) загруженного модуля
result:=DWORD(hMappedPE);
end;


Ресурс в файл:


function ResourceExtractToFile(hInst:DWORD;resName,resType,FullFileName:string):DWORD;stdcall;
var hFile,dw_writed:DWORD;
hRes,hResData:DWORD;
ptrResLock:pointer;
begin
hRes:=FindResourceA(hInstance,PChar(resName),PChar(resType));
if (hRes=0)
then begin
result:=1;
exit;
end;
hResData:=LoadResource(hInstance,hRes);
if (hResData=0)
then begin
result:=2;
exit;
end;
ptrResLock:=nil;
ptrResLock:=LockResource(hResData);
if not Assigned(ptrResLock)
then begin
result:=3;
exit;
end;

//ptrResLock


hFile:= CreateFile("_testFile.exe",
GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_READ,
nil,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
if(hFile=INVALID_HANDLE_VALUE)
then begin
result:=4;
exit;
end;
dw_writed:=SizeofResource(hInstance,hRes);
if not LongBool(WriteFile(hFile,ptrResLock,dw_writed,@dw_writed,nil))
then begin
CloseHandle(hFile);
result:=5;
exit;
end;
CloseHandle(hFile);
result:=0;
end;


 
AlexRush   (2003-07-02 19:37) [4]

Тестировал так:
ResourceExtractToFile(MapPEfromResource("#101","DIGITHEX"),
"#101","DIGITHEX",PathName);
Чуть не забыл :)

//function MapPEfromResource(resName,resType:string):DWORD;
// ПОЛУЧАЕТ Имя и Тип ресурса,который содержит PE-файл.
// ( выделяет сама!)
Тестировал так:
ResourceExtractToFile(MapPEfromResource("#101","DIGITHEX"),
"#101","DIGITHEX",PathName);
Чуть не забыл :)

//function MapPEfromResource(resName,resType:string):DWORD;
// ПОЛУЧАЕТ Имя и Тип ресурса,который содержит PE-файл.
// Грузит PE - в память (выделяет сама!) согласно с таблицей секций
// ВОЗВРАЩАЕТ хендл модуля, который можно использовать
// в функциях работы С РЕСУРСАМИ.




 
Vorobyev Sergey   (2003-07-03 08:49) [5]

> AlexRush
Пытаюсь разобраться.. Честно говоря для меня это немного сложно, но пытаюсь..
Если бегло, то это возможно как раз то, что мне нужно..
Попробовал в Delphi6, вот так с ходу не откомпилилось..
Описания для PIMAGE_DOS_HEADER и т.п. взял из "Delphi\Demos\ResXplor\rxtypes.pas"
Пока такие вопросы:
1. Что за функция mkptr?
2. Какие юниты еще надо подключать?


 
AlexRush   (2003-07-03 11:22) [6]

Смысл функции MapPEfromResource состоит в том, что она возаращает хенд процесса (HINSTANCE),который затем можно использовать при работе с апишками. В противном случае пришлось бы перебирать блок памяти, соответствующий PE файлу, руками. Это довольно проблематично и многие существующие ф-и пришлось бы переписывать.
Так как ф-я сама выделяет памать для отображения модуля, ее желательно освободить:

hPE :DWORD;
........
hPE := MapPEfromResource("#101","DIGITHEX");
........
HeapFree(GetProcessHeap(),0,pointer(hPE));


Заголовоки и функции:

unit PE;

interface
USES windows;
type
PBYTE = ^byte;

PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;
PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;
IMAGE_SECTION_HEADER_ARRAY = packed array of IMAGE_SECTION_HEADER;
PIMAGE_SECTION_HEADER_ARRAY = ^IMAGE_SECTION_HEADER_ARRAY;
PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
//-------------------------------------------------
IMAGE_IMPORT_DESCRIPTOR = packed record
OriginalFirstThunk :DWORD;
TimeDateStump :DWORD;
ForwardChain :DWORD;
Name :DWORD;
FirstThunk :DWORD;
end;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
//-------------------------------------------------
IMAGE_IMPORT_BY_NAME = packed record
Hint :WORD;
Name :char;
end;
PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME;
//-------------------------------------------------
IMAGE_THUNK_DWORD = packed record
case integer of
0:(dwThunk :DWORD);
1:(w_Ord :WORD);
2:(pImportByName :PIMAGE_IMPORT_BY_NAME);
end;
PIMAGE_THUNK_DWORD = ^IMAGE_THUNK_DWORD;
//-------------------------------------------------
IMAGE_BASE_RELOCATION = packed record
VirtualAddress :DWORD;
SizeOfBlock :DWORD;
end;
PIMAGE_BASE_RELOCATION = ^IMAGE_BASE_RELOCATION;
//-------------------------------------------------
CONST
IMAGE_REL_BASED_ABSOLUTE = 0;
IMAGE_REL_BASED_HIGHLOW = 3;
IMAGE_REL_TYPE_MASK = WORD($F000);
IMAGE_REL_OFFSET_MASK = WORD($0FFF);

function ReadFile(hFile: THandle;
pBuffer:pointer;
nNumberOfBytesToRead: DWORD;
lpNumberOfBytesRead: PDWORD;
lpOverlapped: POverlapped): BOOL; stdcall; external "kernel32.dll" name "ReadFile";

function WriteFile(hFile: THandle;
pBuffer:pointer;
nNumberOfBytesToWrite: DWORD;
lpNumberOfBytesWritten: PDWORD;
lpOverlapped: POverlapped): BOOL; stdcall;external "kernel32.dll" name "WriteFile";


function mkptr(ptrBase:DWORD;addValue:DWORD):pointer;overload;assembler;
function mkptr(ptrBase:pointer;addValue:DWORD):pointer;overload;assembler;

implementation

function mkptr(ptrBase:DWORD;addValue:DWORD):pointer;overload;assembler;
asm
add eax,edx
ret
end;


function mkptr(ptrBase:pointer;addValue:DWORD):pointer;overload;assembler;
asm
add eax,edx
ret
end;

end.



 
Vorobyev Sergey   (2003-07-03 12:49) [7]

>AlexRush

> Смысл функции MapPEfromResource состоит в том, что ...

Спасибо.. Смысл этой функции я понял..

Откомпилилась (с небольшими исправлениями) и все равно не работает. А как ты проверял?

Чтобы много вопросов не задавать, спрошу просто..
Я в программу в ресурс типа RT_RCDATA занес exe-файл и назвал ресурс "EXEFILE"
1. Как с помощью связки ResourceExtractToFile, MapPEfromResource извлечь иконку (ресурс "MAINICON") из этого "EXEFILE"
У меня не получилось?
Подробно писать очень много, всякое уж перепробовал..


 
цук   (2003-07-03 13:11) [8]

Удалено модератором
Примечание: Offtopic


 
AlexRush   (2003-07-03 14:48) [9]

Извеняй, я реально загнался. Функцию ResourceExtractToFile я малость переделывал из другой для твоего случая и забыл вместо hInstance передавать hInst. Таким образом тестирокание не обосновано.

Исправляюсь, пределываю, выкладываю.

- загнал другой exe"шник внутрь своего


// FILE: CODE.RC
#include "CODE.h"
IDR_CODEHEX DIGITHEX DISCARDABLE "msvcrt.sys"

//FILE CODE.H
#define IDR_CODEHEX 101


$> brc32 CODE.RC

- подменил файл и загнал СВОЙ exe"шник САМ В СЕБЯ.
Таким образом у нас в ресурсе содержится exe"шник, в ресурсах которого так же содержится exe.

- и юзал функции следующим образом:


ResourceExtractToFile(MapPEfromResource("#101",
"DIGITHEX"),
"#101",
"DIGITHEX",
PathName);


Т.Е. MapPEfromResource получает имя и тип (свой, заметь) ресурса и размещает его в память, как и положено PE-модулю.
При этом она не делает работы, связанной с выполнением ПЕ модуля (развязка relocations, загрузка ДЛЛ и связавание импорта)
Возвращаемое ею значение интерпретируется, как hInstance и передается ф-и ResourceExtractToFile. Таким образом в ее теле функции FindResourceA(), LoadResource() и SizeofResource() работают уже с вновь размешенным PE и ВНУТРИ НЕГО находят ресурс с именем и типом и сохраняют на диск.
Это я проверил. Работает точно (точнее, чем в прошлый раз :)


 
AlexRush   (2003-07-03 15:06) [10]

Что каксается ResourceExtractToFile, то в ее теле нужно все hInstance заменить на hInst.
Кроме того, в данном примере я не использую третий параметр и сохраняю в "_testFile.exe".

hFile:= CreateFile("_testFile.exe",
.......


Для сравнения же версий файлов, я так полагаю, следует юзать VerQueryValue()


BOOL VerQueryValue(
const LPVOID pBlock, // buffer for version resource
LPTSTR lpSubBlock, // value to retrieve
LPVOID *lplpBuffer, // buffer for version value pointer
PUINT puLen ( с небольшими исправлениями)
Что каксается ResourceExtractToFile, то в ее теле нужно все hInstance заменить на hInst.
Кроме того, в данном примере я не использую третий параметр и сохраняю в "_testFile.exe".

hFile:= CreateFile("_testFile.exe",
.......


Для сравнения же версий файлов, я так полагаю, следует юзать VerQueryValue()


BOOL VerQueryValue(
const LPVOID pBlock, // buffer for version resource
LPTSTR lpSubBlock, // value to retrieve
LPVOID *lplpBuffer, // buffer for version value pointer
PUINT puLen // version length
);

В качестве параметра pBlock следует наверное передавать адрес ресурса версии. Думаю, сработает.
Еще я наткнулся на ф-и VerFindFile и VerInstallFile - если ты их не используешь, почитай описание, может пригодятся или какую идею подкинут.
Кстати
> Откомпилилась (с небольшими исправлениями) и все равно не
>работает.
- Какие изменения конкретно ? (у меня D6)


 
Vorobyev Sergey   (2003-07-03 15:22) [11]

>AlexRush
Ура! заработало!!

Честно говоря, я уже начал было копать PE и COFF форматы, формат ресурсов и т.п. (наверное, закопался бы)

Спасибо!


 
AlexRush   (2003-07-03 15:28) [12]

>Vorobyev Sergey
Кстати, как ты версии сравнивал ? Ато у меня руки не дошли, а все-таки интересно :)


 
Vorobyev Sergey   (2003-07-03 15:55) [13]


> Кстати, как ты версии сравнивал ? Ато у меня руки не дошли,
> а все-таки интересно :)


function GetResourceExeFileVersion(resName:string):string;
var rs:TResourceStream;
dump:DWORD;
TransBuffer, VersionPointer:PChar;
temp:integer;
CalcLangCharSet: string;
begin
rs := TResourceStream.Create(MapPEfromResource(resName, RT_RCDATA), "#1",
RT_VERSION);
try
VerQueryValue(rs.Memory,"\VarFileInfo\Translation",pointer(TransBuffer),dump);
if dump>=4 then
begin
temp:=0;
StrLCopy(@temp,TransBuffer,2);
CalcLangCharSet:=IntToHex(temp,4);
StrLCopy(@temp,TransBuffer+2,2);
CalcLangCharSet:=CalcLangCharSet+IntToHex(temp,4);
end;
VerQueryValue(rs.Memory,pchar("\StringFileInfo\"+CalcLangCharSet+"\"+
"FileVersion"),pointer(VersionPointer),dump);
( dump>1)

> Кстати, как ты версии сравнивал ? Ато у меня руки не дошли,
> а все-таки интересно :)


function GetResourceExeFileVersion(resName:string):string;
var rs:TResourceStream;
dump:DWORD;
TransBuffer, VersionPointer:PChar;
temp:integer;
CalcLangCharSet: string;
begin
rs := TResourceStream.Create(MapPEfromResource(resName, RT_RCDATA), "#1",
RT_VERSION);
try
VerQueryValue(rs.Memory,"\VarFileInfo\Translation",pointer(TransBuffer),dump);
if dump>=4 then
begin
temp:=0;
StrLCopy(@temp,TransBuffer,2);
CalcLangCharSet:=IntToHex(temp,4);
StrLCopy(@temp,TransBuffer+2,2);
CalcLangCharSet:=CalcLangCharSet+IntToHex(temp,4);
end;
VerQueryValue(rs.Memory,pchar("\StringFileInfo\"+CalcLangCharSet+"\"+
"FileVersion"),pointer(VersionPointer),dump);
if (dump>1) then
Result := VersionPointer
else
Result:="";
finally
rs.Free;
end;
end;



Проверено!!! :-)


 
AlexRush   (2003-07-03 16:04) [14]

Ок. :) Глюдишь, и самому пригодится :)))


 
Vorobyev Sergey   (2003-07-09 11:47) [15]

>AlexRush
И снова возвращаюсь к функции MapPEfromResource..
Выяснился один неприятный момент :-((( Под Win98 похоже она работает некорректно и возвращает неправильный Instance.

Проверял GetResourceExeFileVersion (см. Vorobyev Sergey (03.07.03 15:55)), и выдает ошибку "Resource #1 not found", т.е. как будто бы НЕ ТОТ INSTANCE..
В чем может быть причина???


 
AlexRush   (2003-07-09 13:39) [16]

Причина может быть в 9х.. :( Я когда-то тоже сталкивался с тем, что код, работающий с ПЕ-форматом под НТ работал нормально, а под 9х глючил.
У меня сейчас нет системы 9х, так что проверить не смогу.
Попробуй в куске hMappedPE:=HeapAlloc(GetProcessHeap(),0,dw); сделать изменения, чтобы hMappedPE был кратен FFFF. Может понадобиться дополнительная память +FFFE:
hMappedPE:=HeapAlloc(GetProcessHeap(),0,dw+$FFFF);
Если что, пиши на мыло.


 
Igor__   (2003-07-14 13:07) [17]

Это все очень даже интересно!!!

Но я почемуто в этом плаваю.

1. Чем отличается HeapAlloc от GetMem?

2. Неужели HInstance это фактически указатель. Помойму HInstance одинаков для всех процессов, т.е. это должен быть указатель на память общую для всех процессов, а в NT поидее такого нет в отличие от 9х.

3. То что все же нужно для роботоспособности в 9х (может кто-то докопался до истины)?

4. Что еще нужно доделать, чтобы можно было запустить процесс из памяти, без записи на диск (т.е. как осуществить эту развязку relocations"сов и что это есть). Потом как запустить процесс, помойму Windows подгружает ехе по частям и по надобности. Как это обойти.

Когда-то я писал программу которая "ставит на программы пароль", т.е. дописывает до моего модуля другую програму в конец, потом при запуске, модуль спрашывает пароль и при правильном пароле сохраняет код программы на диске под случайным именем и розширением, а потом CreateProcess"ом запускает, WaitforSingleProcess"ом ждет завершения, а после завершения удаляет файл. Хочу программу переделать чтобы загружала не с временного файла, а з памяти, поэтому и заинтересовала ветка.

Поделитесь опытом.


 
NightAngel   (2003-07-15 12:25) [18]

> Igor__ © (14.07.03 13:07)
>1. Чем отличается HeapAlloc от GetMem?
>2. Неужели HInstance это фактически указатель. Помойму >HInstance одинаков для всех процессов, т.е. это должен быть >указатель на память общую для всех процессов, а в NT поидее >такого нет в отличие от 9х.


Об этом лучше почитать в книгах, тем более, что Вы "плаваете" в этих вопросах, а цитировать справочники у меня желания нет.

>>4. Что еще нужно доделать, чтобы можно было запустить процесс >из памяти, без записи на диск (т.е. как осуществить эту >развязку relocations"сов и что это есть). Потом как запустить >процесс,

Доделывать придется много. Лучше бросьте эту идею вообще, т.к. надо будет эмулировать все действия загрузчика, но об этом информации мало, поэтому вкратце: Все нижесказанное справедливо как для exe, так и для dll (формат у них один - это PE файлы). Загрузчик выделяет память для ВСЕГО модуля (в память грузятся все заголовки, таблица секций, секции в порядке перечисления в таблице), не грузится только оверлей - это участок кода\данных, который не загружается в память вместе с программой. Обычно присутствует в последней секции, но теоретически может находиться и в другой. Значение Image Base (адресс по которому будет загружен модуль) выравнивается на границу 64 Кб (10000h). Все заголовки и секции выравниваются в памяти на размер страницы (для интел это 4 Кб). На диске все заголовки и секции выравнены на размер сектора (обычно 512 Кб), поэтому все exe и dll в памяти, НЕ СООТВЕСТВУЮТ своему образу на диске. Если загрузчику не удаётся загрузить модуль по указанному Image Base, то он использует специальные секции .reloc или .fixup для того, чтобы перенастроить все VA адреса в программе. Эти секции содержат таблицу базовых поправок (base relocation). Базовая поправка — это настройка по отношению к инструкции или значению инициализированной переменной. Инструкции JMP и CALL, генерируемые компилятором, используют смещения относительно этих инструкций, а не действительные смещения в 32-разрядном сегменте. Если модуль не удается загрузить по Image Base, не нужно изменять эти инструкции, поскольку они используют относительную адресацию. В результате поправок не так много. Поправки обычно требуются только для инструкций, использующих 32-разрядные смещения для данных. Это и есть настройка адресов, или как Вы написАли "развязка" (хотя это бред, в терминологии и так достаточно путаницы). Далее загрузчик загружает используемые библиотеки и настраивает таблицу импортов. Затем перенастраиваются TLSCallBack (если есть). Производится настройка массива виртуальных адресов функций, которые будут вызваны загрузчиком после создания потока и после ее завершения (Эта секция связана с семейством функций TlsAlloc()). После чего устанавливается защита для секций в соответствии с их характеристиками в таблице секций, инициализируются все регистры общего назначения и передается управление программе по Entry point RVA. Так вот, для того чтобы запустить процесс из памяти, все эти действия Вам придется совершать в своей программе.

> помойму Windows подгружает ехе по частям и по надобности.

Это не совсем верно, точнее совсем неверно. Ну да ладно... Рекомендую взять описание какого-нибудь процессора (начиная с 386), там будут главы посвященные организации памяти. Лучше ничего нет.

> Как это обойти.

Т.к. exe будет загружен в контекст процесса, то пусть Вас это не беспокоит. В режиме сегментно-страничной адресации (с которой и работает Win32) физический адрес НЕ СОВПАДАЕТ с линейным, а получается путем разбиения линейного адреса на 3 части и путешествия по каталогам и таблицам страниц. Реальная физическая память выделяется не при выделении страниц, а при первом к ним доступе.

> Когда-то я писал программу которая "ставит на программы пароль", т.е. дописывает до моего модуля другую програму в конец, потом при запуске, модуль спрашывает пароль и при правильном пароле сохраняет код программы на диске под случайным именем и розширением, а потом CreateProcess"ом запускает, WaitforSingleProcess"ом ждет завершения, а после завершения удаляет файл. Хочу программу переделать чтобы загружала не с временного файла, а з памяти, поэтому и заинтересовала ветка.

Это пустая трата времени. Все "навесные защиты" ломаются в течении 15 минут, если они каким-то образом не контролируют носителя. В данном случае достаточно будет "отцепить" другую программу от Вашего модуля и запускать ее без всякого пароля. То, что Вы хотите, можно сделать гораздо проще, и намного эфективнее.

> Поделитесь опытом.

Ну вот, вроде-бы поделился...


 
Igor__   (2003-07-15 17:20) [19]

NightAngel:

> Об этом лучше почитать в книгах, тем более, что Вы "плаваете"
> в этих вопросах, а цитировать справочники у меня желания
> нет.

Ну уж извините у меня таких книг нет. "Плаваю" - это не означает полный ноль, а означает что знаю но далеко не все. Потом я не прошу вас цитировать книгу. Мне просто в двух словах.


> Доделывать придется много. Лучше бросьте эту идею вообще,
> т.к. надо будет эмулировать все действия загрузчика

Емулировать действия загрузчика вы у меня охоту убили. Но есть одна идея. Правда тоже не очень четко выраженная: CreateProcess сначала загружает файл в память, апотом делает с ним что надо. Если загрузку вместо него зделать самому (с ресурса например), а потом передать ему управление в точку которая соответсвует манипуляциями в памяти (т. е. до адреса процедуры добавить смещение до нужной точки). Но ЭТА идея помойму малоосуществима. Каково ваше мнение?


> Это не совсем верно, точнее совсем неверно.

Причем тут организация памяти??? Впрочем если это совсем неверно, то предыдущая идея становится все более теоретически веороятной.


> Т.к. exe будет загружен в контекст процесса, то пусть Вас
> это не беспокоит. В режиме сегментно-страничной адресации
> (с которой и работает Win32) физический адрес НЕ СОВПАДАЕТ
> с линейным, а получается путем разбиения линейного адреса
> на 3 части и путешествия по каталогам и таблицам страниц.
> Реальная физическая память выделяется не при выделении страниц,
> а при первом к ним доступе.


Про то что память выделяется при первом доступе я знаю. А вот с физическим и линейным адресами вы меня совсем запутали. Ведь приложение не роботает с физическими адресами вообще. Каждый процесс имеет свой нулевой адресс, а физически их росположение контроллирует операционка.


> Это пустая трата времени. Все "навесные защиты" ломаются
> в течении 15 минут, если они каким-то образом не контролируют
> носителя. В данном случае достаточно будет "отцепить" другую
> программу от Вашего модуля и запускать ее без всякого пароля.
> То, что Вы хотите, можно сделать гораздо проще, и намного
> эфективнее.


Чесно говоря даже та версия что делает временный файл в школе прошла. Я ею долго тероризировал любителей поиграть в школе. И что самое удивительное - только один человек приблезительно через пол года припустил принцып роботы программы и то не дошел до конца. Правда у нас в школе только несколько человек которые чето могут и то они знали все папроли с самого начала :)))).


 
Klev   (2003-07-15 17:46) [20]

>Igor__
Если хочешь написать программу для зашиты exe-файлов паролями, то я советую посмотреть аналогичную программу PE password protector написанную кем-то из SMF.
Вот ссылочка на эту прогу: http://smf.chat.ru/files/passw.zip
В архиве находятся также ее исходники на ASm`е.


 
Igor__   (2003-07-15 18:27) [21]

Klev:
ого-о-о-о-о-о-о-о-о. Нифига се!!!
Но жаль асама не знаю.
:(((((((((((((((((((((((((((((((((((((((((((((


 
Klev   (2003-07-15 19:07) [22]

>Igor__
Если в этой проге изменить на что-нибудь диалог проверки пароля то можно получить полнофункциональный Win32.EXE."..." vir.
Проверено, получилось, правда под NT работает некорректно.


 
Igor__   (2003-07-15 19:34) [23]


> Klev

тока асам знать нуно :((((((((((((((((((((((


 
Igor__   (2003-07-16 19:49) [24]

Не, так не интересно!!!


 
NightAngel   (2003-07-17 05:28) [25]

> Igor__ ©

> Ну уж извините у меня таких книг нет
> Мне просто в двух словах.


Но ведь как-то Вы попадаете на этот сайт. В сети очень много информации (в том числе и книг) по интересующим Вас вопросам, ищите. А в двух словах...

> CreateProcess сначала загружает файл в память, апотом делает с ним что надо. Если загрузку вместо него зделать самому (с ресурса например), а потом передать ему управление в точку которая соответсвует манипуляциями в памяти (т. е. до адреса процедуры добавить смещение до нужной точки).

Честно говоря я вообще ничего из этого не понял. Это бред какой-то, извините конечно. CreateProcess() не загружает файл в память, а делает то о чем и говорит ее название - создает новый процесс, а уж загрузка файла при этом производится далеко не в первую очередь.

> Но ЭТА идея помойму малоосуществима. Каково ваше мнение?

Эта идея вообще не осуществима.

> Причем тут организация памяти??? Впрочем если это совсем неверно, то предыдущая идея становится все более теоретически веороятной.

А Вы все-таки почитайте про страничную организацию памяти и у Вас многие вопросы отпадут.

P.S. Все дальнейшие рассуждения по какому-либо поводу будут offtopic, поэтому, если хотите задать какой-то вопрос, создайте свою ветку.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.59 MB
Время: 0.009 c
4-58964
Manticore
2003-07-17 00:14
2003.09.18
Реализация панели инструментов на АПИ


14-58858
SaT
2003-08-30 18:17
2003.09.18
ПОМОГИТЕ С ТЕКСТОВУХОЙ


14-58890
MIN
2003-08-29 15:11
2003.09.18
Warcraft III


7-58949
Atom
2003-07-02 17:39
2003.09.18
Работа с Com портом


1-58709
Nucl
2003-09-08 09:36
2003.09.18
Знатоки ! Нужен совет





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский