通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
文章搜索:
热门搜索:红客 黑鹰 红客技术 安全动画 红客培训
首页 文章 软件 动画 资源 励志 论坛 邮箱 会员 军事 科技 博客 爱心红客 最近更新 800g资源
 业内新闻 漏洞公告 病毒公告 电脑知识 网络知识 菜鸟入门 攻防教程 黑客攻防 安全编程 工具使用 综合安全 个人安全 安全相关 Q Q安全 原创精华 红客人物 站内事件
您现在的位置: 爱国者安全网 >> 文章类 >> 原创精华 >> 文章正文
推荐:Phrack最新公布的内核态RootKit的技术细节
责任编辑:古典辣M°   更新日期:2005-10-24
 

The callback tables located in the DRIVER_OBJECT of the file system
drivers are patched: The IRP handlers of the needed drivers are replaced.
This includes replacing the pointers to base 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 visible as a
service called "Virtual Memory Manager".

"Slanret 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 the
system as a device driver, then accepts commands from
the server instructing it on what files or processes
to conceal." [3]

----[ 3. Stealth on disk, in registry and in memory

The lower the I/O interception in a rootkit is performed, the harder
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 then be hooked either by manipulating the Ke-
ServiceDescriptorTable or directly patching the function body. It is
usually quite easy to detect that pointers in KeServiceDescriptorTable
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 then checking DEVICE_OBJECT->StackSize.

All normal drivers have 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 too 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 introduced changes need to be hidden anyway,
why make two similar but differing procedures (for hiding changes to a
file as well as hiding the existance of a file) instead 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 that 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 substitute 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 IoQueueWorkItem 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 relatively simple means. The original content of the manipu-
lated file could for example be stored in the trojan's file after 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 useful
socket from a driver though, 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 way.

First variant
=============

We could start our code in the context of some process, using a shell-
code quite similar to that used 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, searches for
kernel32.dll in memory and loads the winsock library. All that needs to be
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 the
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 attached 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 used 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 complete, and
then restore the original cont again. 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-
sult if the thread is in a nonalertable wait state. Fortunately, 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 full-
fledged win32-process requires it's registration in the CSRSS subsystem.
This is accomplished by using 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.

This port is not open in the SYSTEM process context. Opening it never
succeeded (ZwConnectPort returned STATUS_PORT_CONNECTION_REFUSED). Play-
ing with SECURITY_QUALITY_OF_SERVICE didn't help. While disassembling
ntdll.dll I saw that ZwConnectPort calls were preceded by ZwCreateSection.
But there was no time and no desire to play with sections. Here is the
code that didn't work:

VOID InformCsrss(HANDLE hProcess,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.ProcessInforma

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]  ... 下一页  >> 

  • 上一篇文章:
  • 下一篇文章:
  • 最近更新
    固顶文章 爱国者安全网2007年度优秀版主评选
    普通文章 瑞星公司01月11日发布 每日计算机病毒及木马播报
    普通文章 破解博彩神助(专注彩票) V2.8.01
    推荐文章 推荐:跨站脚本执行漏洞代码的六点思路
    普通文章 Windows系统下的远程堆栈溢出 实战篇
    普通文章 Windows系统下的远程堆栈溢出 原理篇
    普通文章 MsSQLServer是如何加密口令的
    普通文章 浅谈国内的渗透评估过程
    普通文章 Dvbbs8.1 0DAY(通杀Access和mssql版本)
    普通文章 微软:我们的代码比赛门铁克更安全
    热门文章
    普通文章REAL蛀虫利用播放器漏洞下载恶意程序
    普通文章李彦宏:中国要在互联网领域逐渐超越美国
    普通文章马云:阿里巴巴的成功是一个生态链的成功
    普通文章Ingres用户认证非授权访问漏洞
    普通文章TCPreen FD_SET()函数远程栈溢出漏洞
    普通文章Winace UUE文件解压堆溢出漏洞
    普通文章Pclxav木马猎手第一代特征码引擎源代码
    普通文章IE收藏夹管理小精灵算法分析
    普通文章Extra Drive Pro算法分析历程
    普通文章雨过天晴自我注册
    精彩专题