This test project was developed long time ago, and I want to share it sources.
All what it is doing -> trying to create process notepad.exe using only Native API calls.
So basically it copies behavior of Windows CreateProcess function (CreateProcessInternal).
Application is written on Delphi5 with using some private modules so it can't be compiled without
some additional work.
All Native API functions here used in their Zw naming alias instead of Nt. This is not important.
Steps to create process under NT5.x (in Vista/Seven most of process creation code moved from kernel32.dll into kernel mode).
1. Create section from file
You need to create section from file you want to execute (I think code is self-explanatory)
[syntax="delphi"]function CreateSectionFromFile(
phSection: PHANDLE;
hFile: THANDLE;
usFileName: PUNICODE_STRING): NTSTATUS; stdcall;
var
ns: NTSTATUS;
hFile2: THANDLE;
iost: IO_STATUS_BLOCK;
attr: OBJECT_ATTRIBUTES;
begin
ns := STATUS_SUCCESS;
hFile2 := hFile;
if (usFileName.PStr <> nil) then
begin
InitializeObjectAttributes(@attr, usFileName, OBJ_CASE_INSENSITIVE, hFile, nil);
ns := ZwOpenFile(@hFile2, FILE_EXECUTE or SYNCHRONIZE, @attr, @iost, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT);
end;
if (ns = STATUS_SUCCESS) then
begin
ns := ZwCreateSection(phSection, SECTION_ALL_ACCESS, nil, nil, PAGE_EXECUTE, SEC_IMAGE, hFile2);
if (hFile2 <> hFile) then ZwClose(hFile2);
end;
result := ns;
end;[/syntax]
2. Create "Process" object
Next it is necessary to allocate Process object by calling ZwCreateProcess
[syntax="delphi"]function CreateProcessFromSection(
phProcess: PHANDLE;
hSection: THANDLE;
hParent: THANDLE;
SectionInfo: PSECTION_IMAGE_INFORMATION): NTSTATUS; stdcall;
var
attr: OBJECT_ATTRIBUTES;
ns: NTSTATUS;
begin
InitializeObjectAttributes(@attr, nil, OBJ_CASE_INSENSITIVE, 0, nil);
ns := ZwCreateProcess(phProcess, PROCESS_ALL_ACCESS, @attr, hParent, false, hSection, 0, 0);
if (ns = STATUS_SUCCESS) then
ns := ZwQuerySection(hSection, SectionImageInformation, SectionInfo, sizeof(SECTION_IMAGE_INFORMATION), nil);
result := ns;
end;[/syntax]
3. Create primary thread
Process without thread(s) is dead object, which will be removed by system.
Before calling ZwCreateThread it is obviously required to allocate thread stack and set up thread context.
4. Create process parameters (such as Environment block)
5. Notify Win32 about new process
If your process belongs to Win32 subsystem you must to notify csrss (client-server runtime process) about that.
This can be done through call of CsrClientCallServer
[syntax="delphi"]function NotifyWin32(
hProcess: THANDLE;
hThread: THANDLE;
ClientId: PCLIENT_ID;
Subsystem: ULONG;
CreationFlags: ULONG
): NTSTATUS; stdcall;
var
msg: _BASE_API_MSG;
begin
memzero(@msg, sizeof(msg));
msg.u.CreateProcess.ProcessHandle := hProcess;
msg.u.CreateProcess.ThreadHandle := hThread;
msg.u.CreateProcess.ClientId.UniqueProcess := ClientId.UniqueProcess;
msg.u.CreateProcess.ClientId.UniqueThread := ClientId.UniqueThread;
msg.u.CreateProcess.CreationFlags := CreationFlags;
result := CsrClientCallServer(@msg, nil, CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess), sizeof(msg.u.CreateProcess));
end;[/syntax]
6. Resume primary thread to start execution of newly created process.
In attach you can find source code of the above.
All these can be buggy, so feel free for constructive critics :)
MD5 for CreateProcessTest.exe
90124a3318ff7bd1e9919f1c4a41ecf0
All what it is doing -> trying to create process notepad.exe using only Native API calls.
So basically it copies behavior of Windows CreateProcess function (CreateProcessInternal).
Application is written on Delphi5 with using some private modules so it can't be compiled without
some additional work.
All Native API functions here used in their Zw naming alias instead of Nt. This is not important.
Steps to create process under NT5.x (in Vista/Seven most of process creation code moved from kernel32.dll into kernel mode).
1. Create section from file
You need to create section from file you want to execute (I think code is self-explanatory)
[syntax="delphi"]function CreateSectionFromFile(
phSection: PHANDLE;
hFile: THANDLE;
usFileName: PUNICODE_STRING): NTSTATUS; stdcall;
var
ns: NTSTATUS;
hFile2: THANDLE;
iost: IO_STATUS_BLOCK;
attr: OBJECT_ATTRIBUTES;
begin
ns := STATUS_SUCCESS;
hFile2 := hFile;
if (usFileName.PStr <> nil) then
begin
InitializeObjectAttributes(@attr, usFileName, OBJ_CASE_INSENSITIVE, hFile, nil);
ns := ZwOpenFile(@hFile2, FILE_EXECUTE or SYNCHRONIZE, @attr, @iost, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT);
end;
if (ns = STATUS_SUCCESS) then
begin
ns := ZwCreateSection(phSection, SECTION_ALL_ACCESS, nil, nil, PAGE_EXECUTE, SEC_IMAGE, hFile2);
if (hFile2 <> hFile) then ZwClose(hFile2);
end;
result := ns;
end;[/syntax]
2. Create "Process" object
Next it is necessary to allocate Process object by calling ZwCreateProcess
[syntax="delphi"]function CreateProcessFromSection(
phProcess: PHANDLE;
hSection: THANDLE;
hParent: THANDLE;
SectionInfo: PSECTION_IMAGE_INFORMATION): NTSTATUS; stdcall;
var
attr: OBJECT_ATTRIBUTES;
ns: NTSTATUS;
begin
InitializeObjectAttributes(@attr, nil, OBJ_CASE_INSENSITIVE, 0, nil);
ns := ZwCreateProcess(phProcess, PROCESS_ALL_ACCESS, @attr, hParent, false, hSection, 0, 0);
if (ns = STATUS_SUCCESS) then
ns := ZwQuerySection(hSection, SectionImageInformation, SectionInfo, sizeof(SECTION_IMAGE_INFORMATION), nil);
result := ns;
end;[/syntax]
3. Create primary thread
Process without thread(s) is dead object, which will be removed by system.
Before calling ZwCreateThread it is obviously required to allocate thread stack and set up thread context.
4. Create process parameters (such as Environment block)
5. Notify Win32 about new process
If your process belongs to Win32 subsystem you must to notify csrss (client-server runtime process) about that.
This can be done through call of CsrClientCallServer
[syntax="delphi"]function NotifyWin32(
hProcess: THANDLE;
hThread: THANDLE;
ClientId: PCLIENT_ID;
Subsystem: ULONG;
CreationFlags: ULONG
): NTSTATUS; stdcall;
var
msg: _BASE_API_MSG;
begin
memzero(@msg, sizeof(msg));
msg.u.CreateProcess.ProcessHandle := hProcess;
msg.u.CreateProcess.ThreadHandle := hThread;
msg.u.CreateProcess.ClientId.UniqueProcess := ClientId.UniqueProcess;
msg.u.CreateProcess.ClientId.UniqueThread := ClientId.UniqueThread;
msg.u.CreateProcess.CreationFlags := CreationFlags;
result := CsrClientCallServer(@msg, nil, CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess), sizeof(msg.u.CreateProcess));
end;[/syntax]
6. Resume primary thread to start execution of newly created process.
In attach you can find source code of the above.
All these can be buggy, so feel free for constructive critics :)
MD5 for CreateProcessTest.exe
90124a3318ff7bd1e9919f1c4a41ecf0
Attachments
(4.06 KiB) Downloaded 88 times
Ring0 - the source of inspiration