阅读:18144回复:10
RtlCreateUserProcess 为什么不能从Ring 0 调用
我这里有一个问题,我希望在Ring 0启动一个Ring 3程序,我的方法是用RtlCreateUserProcess ,可是如果我将这段代码加入(譬如:Filemon),程序编译没有问题,但加载失败,StartService失败,GetLastError()返回 ERROR_PROC_NOT_FOUND。
那位大侠用过这个东东,可否指点一二 我的代码为: NTSTATUS _ExecuteImage( IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING CommandLine OPTIONAL, IN PUNICODE_STRING Curdir OPTIONAL, IN PUNICODE_STRING Environment OPTIONAL, OUT NTSTATUS* ExitCode OPTIONAL ) { NTSTATUS Status; PRTL_USER_PROCESS_PARAMETERS pp; RTL_PROCESS_INFO pi; // // Create process. // Status = RtlCreateProcessParameters(&pp, ImageFileName, NULL, Curdir, CommandLine, Environment, NULL, NULL, NULL, NULL ); if(STATUS_SUCCESS != Status) { return Status; } // // Call Rtl to create the process. // Status = RtlCreateUserProcess( ImageFileName, OBJ_CASE_INSENSITIVE, pp, NULL, NULL, NULL, TRUE, NULL, NULL, &pi ); RtlDestroyProcessParameters(pp); // // Return status if failed. // if(STATUS_SUCCESS != Status) { return Status; } // // Allow only native applications to be executed. // if(IMAGE_SUBSYSTEM_NATIVE != pi.ImageInfo.SubsystemType) { Status = STATUS_INVALID_IMAGE_FORMAT; NtTerminateProcess(pi.ProcessHandle, Status); } else { NtResumeThread(pi.ThreadHandle, NULL); NtWaitForSingleObject(pi.ThreadHandle, FALSE, NULL); if(NULL != ExitCode) *ExitCode = GetProcessExitCode(pi.ProcessHandle); } // // Close our handles. // NtClose(pi.ThreadHandle); NtClose(pi.ProcessHandle); // // And return to our caller. // return Status; } |
|
沙发#
发布于:2004-03-08 18:30
RtlCreateUserProcess只在NTDLL中导出,内核中没有该函数,你如何能使用???
|
|
|
板凳#
发布于:2004-03-08 19:04
我现在明白了,是不是所有ntdll.lib中的函数如果内河中没有都不能调用。那请问有什么样的办法可以从内河启动一个ring3的例程娜?
|
|
地板#
发布于:2004-03-08 19:20
不清楚,有个PsCreateSystemProcess,可能只能创建内核进程。
|
|
|
地下室#
发布于:2004-03-08 19:24
PsCreateSystemProcess我也看到了,但不知怎么用。没有示例代码。
我经常看到你出现在论坛里,而且很热心,谢谢。 |
|
5楼#
发布于:2004-03-08 19:25
你在那个城市
|
|
6楼#
发布于:2004-03-08 19:30
上海,嘿嘿。。。
NTSTATUS PsCreateSystemProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ) /*++ Routine Description: This routine creates a system process object. A system process has an address space that is initialized to an empty address space that maps the system. The process inherits its access token and other attributes from the initial system process. The process is created with an empty handle table. Arguments: ProcessHandle - Returns the handle for the new process. DesiredAccess - Supplies the desired access modes to the new process. ObjectAttributes - Supplies the object attributes of the new process. Return Value: TBD --*/ { NTSTATUS st; PAGED_CODE(); st = PspCreateProcess( ProcessHandle, DesiredAccess, ObjectAttributes, PspInitialSystemProcessHandle, FALSE, (HANDLE) NULL, (HANDLE) NULL, (HANDLE) NULL ); return st; } NTSTATUS PspCreateProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess OPTIONAL, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL ) /*++ Routine Description: This routine creates and initializes a process object. It implements the foundation for NtCreateProcess and for system initialization process creation. Arguments: ProcessHandle - Returns the handle for the new process. DesiredAccess - Supplies the desired access modes to the new process. ObjectAttributes - Supplies the object attributes of the new process. ParentProcess - Supplies a handle to the process' parent process. If this parameter is not specified, then the process has no parent and is created using the system address space. SectionHandle - Supplies a handle to a section object to be used to create the process' address space. If this parameter is not specified, then the address space is simply a clone of the parent process' address space. DebugPort - Supplies a handle to a port object that will be used as the process' debug port. ExceptionPort - Supplies a handle to a port object that will be used as the process' exception port. Return Value: TBD --*/ { NTSTATUS st; PEPROCESS Process; PEPROCESS Parent; KAFFINITY Affinity; KPRIORITY BasePriority; PVOID SectionToMap; PVOID ExceptionPortObject; PVOID DebugPortObject; ULONG WorkingSetMinimum, WorkingSetMaximum; HANDLE LocalProcessHandle; KPROCESSOR_MODE PreviousMode; HANDLE NewSection; NTSTATUS DuplicateStatus; INITIAL_PEB InitialPeb; BOOLEAN CreatePeb; ULONG_PTR DirectoryTableBase[2]; BOOLEAN AccessCheck; BOOLEAN MemoryAllocated; PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; NTSTATUS accesst; NTSTATUS savedst; BOOLEAN BreakAwayRequested; PUNICODE_STRING AuditName = NULL ; PAGED_CODE(); BreakAwayRequested = FALSE; CreatePeb = FALSE; DirectoryTableBase[0] = 0; DirectoryTableBase[1] = 0; PreviousMode = KeGetPreviousMode(); // // Parent // if (ARGUMENT_PRESENT(ParentProcess) ) { st = ObReferenceObjectByHandle( ParentProcess, PROCESS_CREATE_PROCESS, PsProcessType, PreviousMode, (PVOID *)&Parent, NULL ); if ( !NT_SUCCESS(st) ) { return st; } // // Until CSR understands priority class, don't // inherit base priority. This just makes things // worse ! // BasePriority = (KPRIORITY) NORMAL_BASE_PRIORITY; // //BasePriority = Parent->Pcb.BasePriority; // Affinity = Parent->Pcb.Affinity; WorkingSetMinimum = PsMinimumWorkingSet; // FIXFIX WorkingSetMaximum = PsMaximumWorkingSet; } else { Parent = NULL; Affinity = KeActiveProcessors; BasePriority = (KPRIORITY) NORMAL_BASE_PRIORITY; WorkingSetMinimum = PsMinimumWorkingSet; // FIXFIX WorkingSetMaximum = PsMaximumWorkingSet; } // // Section // if (ARGUMENT_PRESENT(SectionHandle) ) { // // Use Object manager tag bits to indicate that breakaway is // desired // if ( (UINT_PTR)SectionHandle & 1 ) { BreakAwayRequested = TRUE; } st = ObReferenceObjectByHandle( SectionHandle, SECTION_MAP_EXECUTE, MmSectionObjectType, PreviousMode, (PVOID *)&SectionToMap, NULL ); if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } return st; } } else { SectionToMap = NULL; } // // DebugPort // if (ARGUMENT_PRESENT(DebugPort) ) { st = ObReferenceObjectByHandle ( DebugPort, 0, LpcPortObjectType, KeGetPreviousMode(), (PVOID *)&DebugPortObject, NULL ); if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } if (SectionToMap) { ObDereferenceObject(SectionToMap); } return st; } } else { DebugPortObject = NULL; } // // ExceptionPort // if (ARGUMENT_PRESENT(ExceptionPort) ) { st = ObReferenceObjectByHandle ( ExceptionPort, 0, LpcPortObjectType, KeGetPreviousMode(), (PVOID *)&ExceptionPortObject, NULL ); if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } if (SectionToMap) { ObDereferenceObject(SectionToMap); } if (DebugPortObject) { ObDereferenceObject(DebugPortObject); } return st; } } else { ExceptionPortObject = NULL; } st = ObCreateObject( KeGetPreviousMode(), PsProcessType, ObjectAttributes, KeGetPreviousMode(), NULL, (ULONG) sizeof(EPROCESS), 0, 0, (PVOID *)&Process ); if ( !NT_SUCCESS( st ) ) { if (Parent) { ObDereferenceObject(Parent); } if (SectionToMap) { ObDereferenceObject(SectionToMap); } if (DebugPortObject) { ObDereferenceObject(DebugPortObject); } if (ExceptionPortObject) { ObDereferenceObject(ExceptionPortObject); } return st; } // // The process object is created set to NULL. Errors // That occur after this step cause the process delete // routine to be entered. // // Teardown actions that occur in the process delete routine // do not need to be performed inline. // RtlZeroMemory(Process,sizeof(EPROCESS)); InitializeListHead(&Process->ThreadListHead); Process->CreateProcessReported = FALSE; Process->DebugPort = DebugPortObject; Process->ExceptionPort = ExceptionPortObject; PspInheritQuota(Process,Parent); ObInheritDeviceMap(Process,Parent); if ( Parent ) { Process->DefaultHardErrorProcessing = Parent->DefaultHardErrorProcessing; Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId; Process->SessionId = Parent->SessionId; } else { Process->DefaultHardErrorProcessing = 1; Process->InheritedFromUniqueProcessId = NULL; } Process->ExitStatus = STATUS_PENDING; Process->LockCount = 1; Process->LockOwner = NULL; KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE); // // Initialize the security fields of the process // The parent may be null exactly once (during system init). // Thereafter, a parent is always required so that we have a // security context to duplicate for the new process. // st = PspInitializeProcessSecurity( Parent, Process ); if (!NT_SUCCESS(st)) { if ( Parent ) { ObDereferenceObject(Parent); } if (SectionToMap) { ObDereferenceObject(SectionToMap); } ObDereferenceObject(Process); return st; } // // Clone parent's object table. // If no parent (booting) then use the current object table created in // ObInitSystem. // if (Parent) { // // Calculate address space // // If Parent == PspInitialSystem // if (!MmCreateProcessAddressSpace(WorkingSetMinimum, Process, &DirectoryTableBase[0])) { ObDereferenceObject(Parent); if (SectionToMap) { ObDereferenceObject(SectionToMap); } PspDeleteProcessSecurity( Process ); ObDereferenceObject(Process); return STATUS_INSUFFICIENT_RESOURCES; } } else { Process->ObjectTable = PsGetCurrentProcess()->ObjectTable; DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]; DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1]; // // Initialize the Working Set Mutex and address creation mutex // for this "hand built" process. // Normally, the call the MmInitializeAddressSpace initializes the // working set mutex, however, in this case, we have already initialized // the address space and we are now creating a second process using // the address space of the idle thread. // //KeInitializeMutant(&Process->WorkingSetLock, FALSE); ExInitializeFastMutex(&Process->WorkingSetLock); ExInitializeFastMutex(&Process->AddressCreationLock); KeInitializeSpinLock (&Process->HyperSpaceLock); // // Initialize virtual address descriptor root. // ASSERT (Process->VadRoot == NULL); Process->Vm.WorkingSetSize = PsGetCurrentProcess()->Vm.WorkingSetSize; KeQuerySystemTime(&Process->Vm.LastTrimTime); Process->Vm.VmWorkingSetList = MmWorkingSetList; } Process->Vm.MaximumWorkingSetSize = WorkingSetMaximum; KeInitializeProcess( &Process->Pcb, BasePriority, Affinity, &DirectoryTableBase[0], (BOOLEAN)(Process->DefaultHardErrorProcessing & PROCESS_HARDERROR_ALIGNMENT_BIT) ); Process->Pcb.ThreadQuantum = PspForegroundQuantum[0]; Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; if (Parent) { // // this used to happen in basesrv\srvtask.c // if ( Parent->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE || Parent->PriorityClass == PROCESS_PRIORITY_CLASS_BELOW_NORMAL ) { Process->PriorityClass = Parent->PriorityClass; } // // if address space creation worked, then when going through // delete, we will attach. Of course, attaching means that the kprocess // must be initialized, so we delay the object stuff till here. // st = ObInitProcess(InheritObjectTable ? Parent : (PEPROCESS)NULL,Process); if (!NT_SUCCESS(st)) { ObDereferenceObject(Parent); if (SectionToMap) { ObDereferenceObject(SectionToMap); } PspDeleteProcessSecurity( Process ); ObDereferenceObject(Process); return st; } } st = STATUS_SUCCESS; savedst = STATUS_SUCCESS; // // Initialize the process address space // The address space has four possibilities // // 1 - Boot Process. Address space is initialized during // MmInit. Parent is not specified. // // 2 - System Process. Address space is a virgin address // space that only maps system space. Process is same // as PspInitialSystemProcess. // // 3 - User Process (Cloned Address Space). Address space // is cloned from the specified process. // // 4 - User Process (New Image Address Space). Address space // is initialized so that it maps the specified section. // if ( SectionToMap ) { // // User Process (New Image Address Space). Don't specify Process to // clone, just SectionToMap. // st = MmInitializeProcessAddressSpace( Process, NULL, SectionToMap, &AuditName ); ObDereferenceObject(SectionToMap); ObInitProcess2(Process); if ( NT_SUCCESS(st) ) { // // In order to support relocating executables, the proper status // (STATUS_IMAGE_NOT_AT_BASE) must be returned, so save it here. // savedst = st; st = PspMapSystemDll(Process,NULL); } CreatePeb = TRUE; goto insert_process; } if ( Parent ) { if ( Parent != PsInitialSystemProcess ) { Process->SectionBaseAddress = Parent->SectionBaseAddress; // // User Process ( Cloned Address Space ). Don't specify section to // map, just Process to clone. // st = MmInitializeProcessAddressSpace( Process, Parent, NULL, NULL ); CreatePeb = TRUE; } else { // // System Process. Don't specify Process to clone or section to map // st = MmInitializeProcessAddressSpace( Process, NULL, NULL, NULL ); } } insert_process: // // If MmInitializeProcessAddressSpace was NOT successful, then // dereference and exit. // if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } KeAttachProcess(&Process->Pcb); ObKillProcess(FALSE, Process); KeDetachProcess(); PspDeleteProcessSecurity( Process ); ObDereferenceObject(Process); return st; } // // Reference count of process is not biased here. Each thread in the // process bias the reference count when they are created. // st = ObInsertObject( Process, NULL, DesiredAccess, 0, (PVOID *)NULL, &LocalProcessHandle ); if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } return st; } // // See if the parent has a job. If so reference the job // and add the process in. // if ( Parent && Parent->Job && !(Parent->Job->LimitFlags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK) ) { if ( BreakAwayRequested ) { if ( !(Parent->Job->LimitFlags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) ) { st = STATUS_ACCESS_DENIED; if (Parent) { ObDereferenceObject(Parent); } ZwClose(LocalProcessHandle); return st; } } else { ObReferenceObject(Parent->Job); Process->Job = Parent->Job; st = PspAddProcessToJob(Process->Job,Process); if ( !NT_SUCCESS(st) ) { if (Parent) { ObDereferenceObject(Parent); } ZwClose(LocalProcessHandle); return st; } } } PsSetProcessPriorityByClass(Process,PsProcessPriorityBackground); ExAcquireFastMutex(&PspActiveProcessMutex); InsertTailList(&PsActiveProcessHead,&Process->ActiveProcessLinks); ExReleaseFastMutex(&PspActiveProcessMutex); if (Parent && CreatePeb ) { // // For processes created w/ a section, // a new "virgin" PEB is created. Otherwise, // for forked processes, uses inherited PEB // with an updated mutant. RtlZeroMemory(&InitialPeb, FIELD_OFFSET(INITIAL_PEB, Mutant)); InitialPeb.Mutant = (HANDLE)(-1); if ( SectionToMap ) { try { Process->Peb = MmCreatePeb(Process,&InitialPeb); } except(EXCEPTION_EXECUTE_HANDLER) { ObDereferenceObject(Parent); ZwClose(LocalProcessHandle); return GetExceptionCode(); } } else { InitialPeb.InheritedAddressSpace = TRUE; Process->Peb = Parent->Peb; ZwWriteVirtualMemory( LocalProcessHandle, Process->Peb, &InitialPeb, sizeof(INITIAL_PEB), NULL ); } // // The new process should have a handle to its // section. The section is either from the specified // section, or the section of its parent. // if ( ARGUMENT_PRESENT(SectionHandle) ) { DuplicateStatus = ZwDuplicateObject( NtCurrentProcess(), SectionHandle, LocalProcessHandle, &NewSection, 0L, 0L, DUPLICATE_SAME_ACCESS ); } else { DuplicateStatus = ZwDuplicateObject( ParentProcess, Parent->SectionHandle, LocalProcessHandle, &NewSection, 0L, 0L, DUPLICATE_SAME_ACCESS ); } if ( NT_SUCCESS(DuplicateStatus) ) { Process->SectionHandle = NewSection; } ObDereferenceObject(Parent); } if ( Parent && ParentProcess != PspInitialSystemProcessHandle ) { st = ObGetObjectSecurity( Process, &SecurityDescriptor, &MemoryAllocated ); if ( !NT_SUCCESS(st) ) { ZwClose(LocalProcessHandle); return st; } // // Compute the subject security context // SubjectContext.ProcessAuditId = Process; SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process); SubjectContext.ClientToken = NULL; AccessCheck = SeAccessCheck( SecurityDescriptor, &SubjectContext, FALSE, MAXIMUM_ALLOWED, 0, NULL, &PsProcessType->TypeInfo.GenericMapping, PreviousMode, &Process->GrantedAccess, &accesst ); PsDereferencePrimaryToken(SubjectContext.PrimaryToken); ObReleaseObjectSecurity( SecurityDescriptor, MemoryAllocated ); if ( !AccessCheck ) { Process->GrantedAccess = 0; } // // It does not make any sense to create a process that can not // do anything to itself // Process->GrantedAccess |= (PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_SET_INFORMATION); } else { Process->GrantedAccess = PROCESS_ALL_ACCESS; } if ( SeDetailedAuditing ) { SeAuditProcessCreation( Process, Parent, AuditName ); } KeQuerySystemTime(&Process->CreateTime); try { *ProcessHandle = LocalProcessHandle; } except(EXCEPTION_EXECUTE_HANDLER) { return st; } if (savedst != STATUS_SUCCESS) { st = savedst; } return st; } |
|
|
7楼#
发布于:2004-03-08 19:41
太巧了,我也在上海。
谢谢,等一下我再研究一下代码。 我每天在msn上,mz9782@hotmail.com, 有空我们可以聊一聊。 |
|
8楼#
发布于:2005-07-08 12:09
这个问题各位搞定没有呢。
我在做这个尝试,编译OK,运行不行。 在DRIVERENTRY中开了个线程,线程里再试图开启用户进程。 但是线程中一旦调用某个未公开的函数比如RtlCreateProcessParameters或者RtlDosPathNameToNtPathName_U,就会无法打开驱动,并报错997,重叠IO进行中。 请指点! |
|
9楼#
发布于:2005-07-08 12:30
看看老外是如何做的
Showtime : *WORKING* CreateProcess in KernelMode! By: valerino I don't think this code needs any comment. Say welcome to usermode calls in kernel land..... with this technique you can even call MessageBox from inside your driver. No more ugly non-working phrack samples, this is the real stuff :) 1) The APC injector //************************************************************************ // NTSTATUS UtilInstallUserModeApcForCreateProcess(char* CommandLine, PKTHREAD pTargetThread, PKPROCESS pTargetProcess) // // Setup usermode APC to execute a process //************************************************************************/ NTSTATUS UtilInstallUserModeApcForCreateProcess(char* CommandLine, PKTHREAD pTargetThread, PEPROCESS pTargetProcess) { PRKAPC pApc = NULL; PMDL pMdl = NULL; PVOID MappedAddress = NULL; ULONG size; KAPC_STATE ApcState; PKEVENT pEvent = NULL; // check params if (!pTargetThread || !pTargetProcess) return STATUS_UNSUCCESSFUL; // allocate memory for apc and event pApc = ExAllocatePool (NonPagedPool,sizeof (KAPC)); if (!pApc) return STATUS_INSUFFICIENT_RESOURCES; pEvent = ExAllocatePool (NonPagedPool,sizeof (KEVENT)); if (!pEvent) { ExFreePool (pApc); return STATUS_INSUFFICIENT_RESOURCES; } // allocate mdl big enough to map the code to be executed size = (unsigned char*)UtilUserApcCreateProcessEnd - (unsigned char*)UtilUserApcCreateProcess; pMdl = IoAllocateMdl (UtilUserApcCreateProcess, size, FALSE,FALSE,NULL); if (!pMdl) { ExFreePool (pEvent); ExFreePool (pApc); return STATUS_INSUFFICIENT_RESOURCES; } // lock the pages in memory __try { MmProbeAndLockPages (pMdl,KernelMode,IoWriteAccess); } __except (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl (pMdl); ExFreePool (pEvent); ExFreePool (pApc); return STATUS_UNSUCCESSFUL; } // map the pages into the specified process KeStackAttachProcess (pTargetProcess,&ApcState); MappedAddress = MmMapLockedPagesSpecifyCache (pMdl,UserMode,MmCached,NULL,FALSE,NormalPagePriority); if (!MappedAddress) { // cannot map address KeUnstackDetachProcess (&ApcState); IoFreeMdl (pMdl); ExFreePool (pEvent); ExFreePool (pApc); return STATUS_UNSUCCESSFUL; } // copy commandline memset ((unsigned char*)MappedAddress + 160, 0, 260); memcpy ((unsigned char*)MappedAddress + 160, CommandLine,strlen (CommandLine)); KeUnstackDetachProcess (&ApcState); // initialize apc KeInitializeEvent(pEvent,NotificationEvent,FALSE); KeInitializeApc(pApc,pTargetThread, OriginalApcEnvironment,&UtilUserApcCreateProcessKernelRoutine, NULL, MappedAddress, UserMode, (PVOID) NULL); // schedule apc if (!KeInsertQueueApc(pApc,pEvent,NULL,0)) { // failed apc delivery MmUnlockPages(pMdl); IoFreeMdl (pMdl); ExFreePool (pEvent); ExFreePool (pApc); return STATUS_UNSUCCESSFUL; } // and fire it by manually alerting the thread (for reference, this set the KTHREAD.ApcState.KernelApcInProgress) // beware, this could be not compatible with everything ..... it works on 2k/XP anyway, tested on SP2 too..... *((unsigned char *)pTargetThread+0x4a)=1; // apc is fired, wait event to signal completion KeWaitForSingleObject (pEvent,Executive,KernelMode,FALSE,NULL); // free event ExFreePool (pEvent); // unmap and unlock pages / mdl . Note that there's no need to call MmUnmapLockedPages on paged locked with MmProbeAndLockPages, // since MmUnlockPages does this for us automatically. MmUnlockPages(pMdl); IoFreeMdl (pMdl); return STATUS_SUCCESS; } 2) This routine just frees the APC allocated memory as soon as it's fired //************************************************************************ // VOID UtilUserApcCreateProcessKernelRoutine( IN struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, // IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2 ) // // This routine just frees the APC //************************************************************************/ VOID UtilUserApcCreateProcessKernelRoutine( IN struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2 ) { PKEVENT pEvent; KDebugPrint (1,("%s APC KernelRoutine called, freeing APC.\n", MODULE)); // free apc ExFreePool(Apc); // set event to signal apc execution pEvent = (PKEVENT)*SystemArgument1; KeSetEvent (pEvent,IO_NO_INCREMENT,FALSE); } 3) This is the usermode routine launched by the APC. It gets Kernel32 base and find imports by a hash, then calls winexec (simpler than call createprocess, but anyway this is just an example....). Use this NASM macro to calculate the needed hashes for whatever usermode functions you may need to call : ; ; HASH - NASM macro for calculating win32 symbol hashes ; Usage: HASH instruction, 'SymbolName' ; %macro HASH 2 %assign i 1 ; i = 1 %assign h 0 ; h = 0 %strlen len %2 ; len = strlen(%2) %rep len %substr char %2 i ; fetch next character %assign h \ (h<<0x13) + \ (h>>0x0d) + \ char ; rotate and add %assign i i+1 ; increment i %endrep %1 h ; return instruction with hash %endmacro I can't remember where i got this shellcode, it was lying already modified on my hd for long time. Anyway it's not mine.... i just rearranged it to my needs. Whoever recognizes it as his code, email me at valeryno@hotmail.com and i'll put the proper credits :) //************************************************************************ // void UtilUserApcCreateProcess(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) // // This is where we call createprocess. We're in usermode here :) //************************************************************************/ __declspec(naked) void UtilUserApcCreateProcess(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) { __asm { push ebp mov ebp,esp push ebx push esi push edi jmp __startup; ; these are just functions.... skip __find_kernel32: push esi ; Save esi push 0x30 pop ecx mov eax, fs:[ecx] ; Extract the PEB mov eax, [eax + 0x0c] ; Extract the PROCESS_MODULE_INFO pointer from the PEB mov esi, [eax + 0x1c] ; Get the address of flink in the init module list lodsd ; Load the address of blink into eax mov eax, [eax + 0x8] ; Grab the module base address from the list entry pop esi ; Restore esi ret ; Return __find_function: pushad ; Save all registers mov ebp, [esp + 0x24] ; Store the base address in eax mov eax, [ebp + 0x3c] ; PE header VMA mov edx, [ebp + eax + 0x78] ; Export table relative offset add edx, ebp ; Export table VMA mov ecx, [edx + 0x18] ; Number of names mov ebx, [edx + 0x20] ; Names table relative offset add ebx, ebp ; Names table VMA __find_function_loop: jecxz __find_function_finished ; Jump to the end if ecx is 0 dec ecx ; Decrement our names counter mov esi, [ebx + ecx * 4] ; Store the relative offset of the name add esi, ebp ; Set esi to the VMA of the current name xor edi, edi ; Zero edi xor eax, eax ; Zero eax cld ; Clear direction __compute_hash_again: lodsb ; Load the next byte from esi into al test al, al ; Test ourselves. jz __compute_hash_finished ; If the ZF is set, we've hit the null term. ror edi, 0xd ; Rotate edi 13 bits to the right add edi, eax ; Add the new byte to the accumulator jmp __compute_hash_again ; Next iteration __compute_hash_finished: cmp edi, [esp + 0x28] ; Compare the computed hash with the requested hash jnz __find_function_loop ; No match, try the next one. mov ebx, [edx + 0x24] ; Ordinals table relative offset add ebx, ebp ; Ordinals table VMA mov cx, [ebx + 2 * ecx] ; Extrapolate the function's ordinal mov ebx, [edx + 0x1c] ; Address table relative offset add ebx, ebp ; Address table VMA mov eax, [ebx + 4 * ecx] ; Extract the relative function offset from its ordinal add eax, ebp ; Function VMA mov [esp + 0x1c], eax ; Overwrite stack version of eax from pushad __find_function_finished: popad ; Restore all registers ret 8 __begin: nop pop edi ; Pop address mov ebx, __execute sub ebx, __command_line sub edi, ebx ; filename offset mov esi,edi ; filename to edi call __find_kernel32 ; Find kernel32 address mov ebx, eax ; Save address in ebx jmp short __execute ; Skip data __startup: call __begin ; Fetch our data address __execute: push 0x0e8afe98 ; WinExec hash push ebx ; kernel32 base address call __find_function ; find address xor ecx,ecx inc ecx ; ecx = 1 push ecx ; uCmdShow push esi ; lpCmdLine. We already have the exe path in esi call eax ; call WinExec jmp __end __command_line: ; Space (~300 bytes) for commandline nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop __end: pop edi ; restore registers pop esi pop ebx pop ebp ret 0x0c } } //************************************************************************ // void UtilUserApcCreateProcessEnd() // // This is just a reference to calculate size of the above usermode apc routine //************************************************************************/ void UtilUserApcCreateProcessEnd() { } The end. Cowabunga, Valerio read comments (6) / write comment |
|
10楼#
发布于:2005-07-08 15:27
谢谢,仔细拜读先!
|
|