Log in

View Full Version : how to Continue the execution of the win32 subsytem..


BanMe
June 4th, 2009, 20:32
the Aim of this small experiment was to see if I could act similarly to csrss, in which it loads under HKLM->SYSTEM->CurrentControlSet->Control->Session Manager->Subsystems placing the full path to the exe ie(%SystemRoot%\System32\Csrarss.exe)..then by placing that keyname in the Required keys list under windows..hmm im wondering if i load before "Windows" will csrss know im there?..(didnt test that yet..)..but anyways Its working now

* This Information came from Elicz posting on www.OpenRCE.com from his Thread on W32ASAP (Win32 As Soon As Possible).. *

Kayaker
June 4th, 2009, 21:43
I've never built a native application, but in browsing around it looks like a fun thing to do. So are you saying that if you don't NtTerminateProcess your native app, the system essentially hangs, waiting for it to finish?

You may have seen this already

http://www.codeproject.com/KB/winsdk/3Steps.aspx

but he seems to use a native app to inject a thread into svchost, as well as load a driver. Could you do something similar to "continue" your desired code execution elsewhere, and/or start up a separate gui application?

On a related note, nrun.c seems to use a different strategy to execute NT native applications

http://ashedel.chat.ru/source/

Cheers,
Kayaker

BanMe
June 5th, 2009, 14:51
Code:

#include "ProcessProfiler.h"

NTSTATUS Native_Server(void);
NTSTATUS Native_Accept(PACCEPT_PARAMS);

NTSTATUS Native_Server(void)
{
OBJECT_ATTRIBUTES ObjAttr = {0};
UNICODE_STRING PortName = {0};
LARGE_INTEGER SectionSize = {LARGE_MESSAGE_SIZE};
PORT_MESSAGE MessageHeader = {0};
NTSTATUS Status = 0;
HANDLE LpcPortHandle = INVALID_HANDLE_VALUE;
HANDLE SectionHandle = INVALID_HANDLE_VALUE;
ACCEPT_PARAMS Params = {0};
HANDLE hThread = INVALID_HANDLE_VALUE;
CLIENT_ID ClientId = {0};
__try
{
Status = NtCreateSection(&SectionHandle,SECTION_MAP_READ | SECTION_MAP_WRITE,NULL,&SectionSize,PAGE_EXECUTE_READWRITE,SEC_COMMIT,NULL);
if(!NT_SUCCESS(Status))
__leave;
RtlInitUnicodeString(&PortName, LpcPortName);
InitializeObjectAttributes(&ObjAttr, &PortName, 0, NULL, NULL);
Status = NtCreatePort(&LpcPortHandle,&ObjAttr,NULL,sizeof(PORT_MESSAGE),0);
if(!NT_SUCCESS(Status))
__leave;
ContinueListening:
Status = NtListenPort(LpcPortHandle, &MessageHeader);
if(!NT_SUCCESS(Status))
__leave;
else
{
Params.LpcPortHandle = LpcPortHandle;
Params.SectionHandle = SectionHandle;
Params.MessageHeader = MessageHeader;
Status = RtlCreateUserThread(NtCurrentProcess(),0,0,0,0,0,(PUSER_THREAD_START_ROUTINE)Native_Accept,&Params,&hThread,&ClientId);
if(!NT_SUCCESS(Status))
__leave;
__asm jmp ContinueListening;
}
}
__finally
{
if(LpcPortHandle != NULL)
NtClose(LpcPortHandle);
if(SectionHandle != NULL)
NtClose(SectionHandle);
_ultow(Status,PortName.Buffer,10);
NtDisplayString(&PortName);
}
return Status;
}
NTSTATUS Native_Accept(PACCEPT_PARAMS Accept)
{
UNICODE_STRING Err = {0};
HANDLE ServerHandle = NULL;
PORT_VIEW ServerView = {0};
REMOTE_PORT_VIEW ClientView;
NTSTATUS Status = 0;
ServerView.Length = sizeof(PORT_VIEW);
ServerView.SectionHandle = Accept->SectionHandle;
ServerView.SectionOffset = 0;
ServerView.ViewSize = LARGE_MESSAGE_SIZE;
ClientView.Length = sizeof(REMOTE_PORT_VIEW);
Status = NtAcceptConnectPort(&ServerHandle,NULL,&Accept->MessageHeader,TRUE,&ServerView,&ClientView);
if(!NT_SUCCESS(Status))
{
_ultow(Status,Err.Buffer,10);
//RtlAppendUnicodeToString(&Err,L"\nIn NtAcceptPort";
NtDisplayString(&Err);
return Status;
}
Status = NtCompleteConnectPort(ServerHandle);
if(!NT_SUCCESS(Status))
{
_ultow(Status,Err.Buffer,10);
//RtlAppendUnicodeToString(&Err,L"\nIn NtCompleteConnect";
NtDisplayString(&Err);
return Status;
}
Status = NtReplyWaitReceivePort(ServerHandle,NULL,NULL,&Accept->MessageHeader);
if(!NT_SUCCESS(Status))
{
_ultow(Status,Err.Buffer,10);
//RtlAppendUnicodeToString(&Err,L"\nIn NtReplyWaitRecievePort";
NtDisplayString(&Err);
return Status;
}
//write to ClientView.ViewBase;
Status = NtReplyPort(Accept->LpcPortHandle, &Accept->MessageHeader);
{
_ultow(Status,Err.Buffer,10);
NtDisplayString(&Err);
return Status;
}
if(ServerHandle != 0)
NtClose(ServerHandle);
if(Accept->LpcPortHandle != 0)
NtClose(Accept->LpcPortHandle);
if(Accept->SectionHandle != 0)
NtClose(Accept->SectionHandle);
return Status;
}
DWORD GetUid(VOID) {
for(; {
LUID Luid;
DWORD Uid;
NtAllocateLocallyUniqueId(&Luid);
Uid = Luid.LowPart + Luid.HighPart;
if((Uid > 0x10) && (Uid != 0xFFFFFFFF)) {
return(Uid);
}
}
}

NTSTATUS WINAPI SmSsContinue(VOID)
{

DWORD Uid;
HANDLE SmApiPort;
NTSTATUS Status;
Uid = GetUid();
SECURITY_QUALITY_OF_SERVICE QoS = {sizeof(QoS), DEFAULT_IMPERSONATION_LEVEL, SECURITY_DYNAMIC_TRACKING, TRUE};
UNICODE_STRING ApiPortName;
SB_CONNECTION_REQUEST SbConnectionRequest;
ULONG SbConnectionRequestSize;
SbConnectionRequest.SbImageType = Uid;
ApiPortName.MaximumLength = sizeof(L"\\SmApiPort";
ApiPortName.Length = ApiPortName.MaximumLength - 2;
ApiPortName.Buffer = L"\\SmApiPort";
memcpy(SbConnectionRequest.SbApiPortName,ApiPortName.Buffer,ApiPortName.MaximumLength);
SbConnectionRequestSize = sizeof(SbConnectionRequest);
__try
{
Status = ZwConnectPort(&SmApiPort, &ApiPortName, &QoS, NULL, NULL, NULL, &SbConnectionRequest, &SbConnectionRequestSize);
if(!NT_SUCCESS(Status))
{
__leave;
}
}
__except(1)
{
_ultow(Status,ApiPortName.Buffer,10);
NtDisplayString(&ApiPortName);
}
return Status;
}


void NtProcessStartup( PSTARTUP_ARGUMENT Argument )
{
SmSsContinue();
Native_Server();
NtTerminateProcess( NtCurrentProcess(), 0 );
}


ProcessProfiler.h
Code:

#define _X86_
#include <windows.h>
#include "ntdll.h"

#define LARGE_MESSAGE_SIZE 0x5000
#define LpcPortName L"\\LpcInterceptPort"
#define DelayExecution "NtDelayExecution"

BOOL NtDelayExecutionEx(DWORD dwSeconds);

typedef struct {
ULONG Unknown[21];
UNICODE_STRING CommandLine;
UNICODE_STRING ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;

typedef struct {
ULONG Unknown[3];
PENVIRONMENT_INFORMATION Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;

typedef struct {
HANDLE LpcPortHandle;
HANDLE SectionHandle;
PORT_MESSAGE MessageHeader;
}ACCEPT_PARAMS,*PACCEPT_PARAMS;

typedef struct _SB_CONNECTION_REQUEST {
ULONG SbImageType; /* Windows - 2, OS/2 - 5, POSIX - 7 */
WCHAR SbApiPortName[120];
} SB_CONNECTION_REQUEST, *PSB_CONNECTION_REQUEST;



typedef NTSTATUS (NTAPI*NTDELAYEXECUTION)(BOOL,PLARGE_INTEGER);
BOOL NtDelayExecutionEx(DWORD dwSeconds)
{
ANSI_STRING FnName = {0};
PVOID DllHandle = 0;
NTDELAYEXECUTION Delay;
LARGE_INTEGER Interval = {0};
Interval.QuadPart = -(__int64)dwSeconds * 10000 * 1000;
if(!NT_SUCCESS(LdrLoadDll(0,0,(PUNICODE_STRING)L"ntdll.dll",&DllHandle)))
{
return FALSE;
}
RtlInitAnsiString(&FnName,DelayExecution);
if(!NT_SUCCESS(LdrGetProcedureAddress(DllHandle,&FnName,0,(PVOID*)&Delay)))
{
return FALSE;
}
if(NT_SUCCESS(Delay(FALSE, &Interval)))
{
return TRUE;
}
else
{
return FALSE;
}
}


1 word of warning to everyone that connects to smss.. use GetUid dont use some made up number..
i tried 2 and it crashs winlogon o_0..i can differentiate my crashs where it says "Subsystem Process" on crash and "Winlogon"..so yea, dont do that.. xD

BanMe
June 5th, 2009, 22:21
included in the post above is a Native Code Application that loads directly after csrss.. also included in this post is entire source (for Visual Studio 2k5 ) it can be compiled and run with either with Subsystem:Windows or Subsytem:Native (windows has more benefits,But Native is funner)

1 small step in the right direction xD
this is the Server that will Intercept Csrss's LPC Communications and forward them or w/e ..
this Server will also be responsible for handling Code chunks sent by my BaseProcessStartThunk and BaseThreadStartThunk for analysis to the server..this is where I think im gonna need to compile it as a Subsystem:Windows in order to do symbol analysis.. or do it in the hooks and then communicate the code..

this is the beggining of Csrarss
Csr active reversing subsystem..though much is still needed..deciding on a disasmbler is not to fun.. Olly's older one doesnt recognize data(though i suppose i could) and syser requires a driver..but adds the benefit of being able to disasmble drivers to the subsystem..Much more to Come..

to install and test it use the method provided in w32asap

Mad Props To:
Elicz for providing the Framework for my SmSsContinue ..
Kayaker for Teaching,Not Flaming
and many others..

Regards BanMe.

Kayaker
June 6th, 2009, 00:35
This is going to take a bit of study to get a handle on, but it's nice to see something wicked new and innovative. I'm going to try to compile it and see wtf this is and what it can do. Props and thanks for the source and info.

bilbo
June 8th, 2009, 22:49
Well, tried it (after converting to plain C and compiling from commandline, sorry) on XP both SP2 and SP3, and here are my impressions:

(1) the debugging is painful: NtDisplayString does not work, and DbgPrint neither (using Sysinternal DebugView with the option "log boot"; the only way is to log to a file, as Elicz does

(2) the LPC with SMSS does not work: in my tries the program hungs inside NtListenPort(), waiting from messages from SM; this is also the case of Elicz SlowTasks()

(3) why are you using "__asm jmp label"? "goto" is supported - fortunately - in C,C++ and C#

(4) I do not yet understand the use of LPC-ing with SM (alias creating a subsystem): the subject is not documented at all...

I hope to find the time to make more experiments
Best regards, bilbo

BanMe
June 9th, 2009, 12:27
excellent observations,

I will try to help, and give a little more info from gathered sources..(i.e. I will try and remember where they came from..)

there are several ways to properly execute a native application.
SessionManager BootExecute Key..or the SessionManager->Subsystem Container(as explained above)
there are several improper ways to load..nrun.c is one(though these methods should/will be utilized to create Helper process's in the context of the current Session..
#Mark Russonivich's blog...www.sysinternals.com
#Elicz Postings..OpenRce and others..


#debugging Natives..
Try NtDelayExecution to delay it before the main thread hits NtTerminateProcess to allow for string output to screen.
Alternatives include Native Thread Injection (article at codeproject:Native Thread Injection, injects smss to display strings)
im sure there are other ways, not found yet..

SmSsContinue works.. without it win32 mode will not load.. (because of the Servers Main Thread waiting for a connection request, similar to csrss..Except im listening on L"\\LpcInterceptPort"

If you look carefully at Elicz code on w32asap,he is not waiting on messages from smss..im pretty sure hes waiting on messages to his termination port for his subsystem...

I like asm.. and I think goto is ugly in C.. :[

yes subsystem development is very sparse on the internet but there are a few examples out there. Cygwin is one and im sure there are others out there, though how "documented" it is , let alone find, is what I plan on working on..

[sidenote:]I would love to help with those experiments
Kind Regards BanMe

BanMe
June 11th, 2009, 18:43
Goals for Project
goal 1 remedy the current error with Native_MapFile Statusone
goal 2 add more recoverable error handling Status:Todo List
goal 3 figure out how to redirect CsrApiPort with or without hooks I also need to integrate a secondary server to manage the
CsrApiMessages(just log and forward) Status: I Have theoretical solution...in short a csrss loader.

subgoals for Csrss Loader
become the man in the middle of csrss's ports.patch all references to the port, load csrsrv,patch the check for
serverprocess in self to also act as a server..

goal 4 implement user process code chunk communication,implement a __stdcall function call functaion in every new loaded image by extending the last section a tiny bit.

goal 5 implement manualmapping with the use of the peb, i.e. MapModuleQueryAlignment + Ldr Peb routines .


many more features to add and test all on the long todo list..

CallGate's(test calling a DriverEntry,test Managing Debug Register..more)
Hardware\Software Breakpoint Manager
RtlRemoteCall manager..a idea off of alex ionescue's posting..(btw if you read this alex, ive been waiting for that for a long time..get on it ..)

alot more to do on the profiling side to.. though Piotr's recent release should help me alot in that area (thank you piotr for the wonderful paper!)

updated source..
Please see my blog..for Downloads

regards BanMe