A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #159  by EP_X0FF
 Mon Mar 15, 2010 9:59 am
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
Attachments
(4.06 KiB) Downloaded 88 times
 #165  by Alex
 Mon Mar 15, 2010 11:07 am
I also wrote own implementation of native process creation. Processes and threads objects don't have names, I added these names just for fun and prove that processes/threads (NtOpenProcess/Thread) can be open also by object names as Nebbett wrote in his book. All implementations I see (your, Nebbett's) they use system services mixed with other functions like CsrClientCalServer. I replaced them with my own code which calls system services directly (the partial implementation of my code can be found in NtUserConsoleControl_Exp exploit, where I create native thread). I planned to write example shellcode inspired Piotr Bania's articleWindows Syscall Shellcode, which will create process using only system services, but I understand it will be too big, so I dropped the idea. If I find my old code written in C, I'll upload it here.

Alex
 #170  by EP_X0FF
 Mon Mar 15, 2010 1:28 pm
Nebbett code does not working > Windows 2000 due to lack of authors understanding in Win32 subsystem notification. I created this one based on some public definitions and kernel32.dll reversing.
Also if somebody have example how to create process using native only on Vista/Seven it will be great if you post it here :)
(yes I know it is now should be much more simple, because most of code migrated to kernel mode).
 #177  by __Genius__
 Mon Mar 15, 2010 3:12 pm
Good example EP, thank you, yes you're right, seems the module is not public, but I think JEDI Native API lib could be help in this project .
I have been attached it :)
Attachments
(187.44 KiB) Downloaded 63 times
 #180  by Twister
 Mon Mar 15, 2010 3:31 pm
I have STATUS_ACCESS_VIOLATION (C0000005) at call of CsrClientCallServer() in NotifyWin32() (win7):
Code: Select all
777E301A   56               PUSH ESI
777E301B   56               PUSH ESI
777E301C   FF35 EC708577    PUSH DWORD PTR DS:[_CsrPortHandle]
777E3022   E8 7928FEFF      CALL ntdll.ZwRequestWaitReplyPort
777E3027   85FF             TEST EDI,EDI
777E3029   0F85 3B7D0000    JNZ ntdll.777EAD6A
777E302F   5B               POP EBX
777E3030   85C0             TEST EAX,EAX
777E3032   0F8C 4D8A0100    JL ntdll.777FBA85
777E3038   8B46 20          MOV EAX,DWORD PTR DS:[ESI+20] <-- Here we have STATUS_ACCESS_VIOLATION
I don't know field name at this offset in PORT_MESSAGE structure, may be this is novelty of Windows Seven.
 #188  by EP_X0FF
 Mon Mar 15, 2010 4:34 pm
Sure it will not work on Seven or Vista :D
There are major changes inside Vista/Seven.
I doubt that this structures and definitions is valid for something > 3790 :)
NtCreateUserProcess doing some of listed here job.

However as I told before I will be happy to see working solution for something greater 3790.
 #225  by Cr4sh
 Mon Mar 15, 2010 9:29 pm
What practical value of this method in comparison with creating process from shellcode, that executed by APC or KiFastCallRet hooking? I am confused with undocummented manipulations to notify csrss about new process.
 #232  by EP_X0FF
 Tue Mar 16, 2010 1:20 am
Practical value is none :)
Maybe just to learn how to create threads with Native in user mode.
 #255  by Gunther
 Wed Mar 17, 2010 2:42 am
Although it's not practical but i agreed with EP_X0FF that it will be good for people who just started to learn on such topics.

Keep it up mate.

BR,
[ Gunther ]