Здесь я приведу пример как можно запустить программу не с диска, а из памяти. Конечно, строго говоря, программа запускается в контексте другого приложения, но не суть важно, поставленной цели мы добъемся. Мы поместим тестовую программу mem.exe, которую надо запустить, в ресурс нашего приложения, а затем при запуске нашего приложения загрузим ресурс и запустим программу mem.exe из памяти. В общем вот код Delphi: res.rc: [code] EXE RCDATA "mem.exe" [/code] project1.dpr: [code] program project1; uses Windows, rxtypes; {$R res.res} Var nb, i: Cardinal; function ZwUnmapViewOfSection(SectionHandle: THandle; p: Pointer): DWord; stdcall; external 'ntdll.dll'; function protect(characteristics: ULONG): ULONG; const mapping: array [0..7] of ULONG = ( PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE); begin Result := mapping[characteristics shr 29]; end; var pi: TProcessInformation; si: TStartupInfo; x, p, q: Pointer; nt: PIMAGE_NT_HEADERS; context: TContext; sect: PIMAGE_SECTION_HEADER; begin si.cb := SizeOf(si); CreateProcess(nil, 'cmd.exe', nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, si, pi); context.ContextFlags := CONTEXT_INTEGER; GetThreadContext(pi.hThread, context); ReadProcessMemory(pi.hProcess, PCHAR(context.ebx) + 8, @x, sizeof (x), nb ); ZwUnmapViewOfSection(pi.hProcess, x); p := LockResource(LoadResource(Hinstance, FindResource(Hinstance, 'EXE', RT_RCDATA))); if p = nil then exit; nt := PIMAGE_NT_HEADERS(PCHAR(p) + PIMAGE_DOS_HEADER(p).e_lfanew); q := VirtualAllocEx( pi.hProcess, Pointer(nt.OptionalHeader.ImageBase), nt.OptionalHeader.SizeOfImage, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(pi.hProcess, q, p, nt.OptionalHeader.SizeOfHeaders, nb); sect := PIMAGE_SECTION_HEADER(nt); Inc(PIMAGE_NT_HEADERS(sect)); for I := 0 to nt.FileHeader.NumberOfSections - 1 do begin WriteProcessMemory(pi.hProcess, PCHAR(q) + sect.VirtualAddress, PCHAR(p) + sect.PointerToRawData, sect.SizeOfRawData, nb); VirtualProtectEx( pi.hProcess, PCHAR(q) + sect.VirtualAddress, sect.SizeOfRawData, protect(sect.Characteristics), @x); Inc(sect); end; WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, @q, sizeof(q), nb); context.Eax := ULONG(q) + nt.OptionalHeader.AddressOfEntryPoint; SetThreadContext(pi.hThread, context); ResumeThread(pi.hThread); end. [/code] Модуль rxtypes и исходники вместе с примером находятся в аттаче. А вот исходный пример, делающий тоже самое на C (который и был переведен на Delphi): [code] #include extern "C" NTSYSAPI LONG NTAPI ZwUnmapViewOfSection(HANDLE, PVOID); ULONG protect(ULONG characteristics) { static const ULONG mapping[] = {PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE}; return mapping[characteristics >> 29]; } int main(int argc, char *argv[]) { PROCESS_INFORMATION pi; STARTUPINFO si = {sizeof si}; CreateProcess(0, "cmd", 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, &si, &pi); CONTEXT context = {CONTEXT_INTEGER}; GetThreadContext(pi.hThread, &context); PVOID x; ReadProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &x, sizeof x, 0); ZwUnmapViewOfSection(pi.hProcess, x); PVOID p = LockResource(LoadResource(0, FindResource(0, "Image", "EXE"))); PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS(PCHAR(p) + PIMAGE_DOS_HEADER(p)->e_lfanew); PVOID q = VirtualAllocEx(pi.hProcess, PVOID(nt->OptionalHeader.ImageBase), nt->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(pi.hProcess, q, p, nt->OptionalHeader.SizeOfHeaders, 0); PIMAGE_SECTION_HEADER sect = IMAGE_FIRST_SECTION(nt); for (ULONG i = 0; i < nt->FileHeader.NumberOfSections; i++) { WriteProcessMemory(pi.hProcess, PCHAR(q) + sect[i].VirtualAddress, PCHAR(p) + sect[i].PointerToRawData, sect[i].SizeOfRawData, 0); ULONG x; VirtualProtectEx(pi.hProcess, PCHAR(q) + sect[i].VirtualAddress, sect[i].Misc.VirtualSize, protect(sect[i].Characteristics), &x); } WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &q, sizeof q, 0); context.Eax = ULONG(q) + nt->OptionalHeader.AddressOfEntryPoint; SetThreadContext(pi.hThread, &context); ResumeThread(pi.hThread); return 0; } [/code]
|