VB隐藏进程问题的讨论由来已久,效果有好有坏,反正是各有各的招,偶然机会看到planet-source一段隐藏进程的文章,作者说采用了kernel mode driver!方法, 单从技术方法而言,这是目前见到隐藏进程中最强悍的了(个人见解,井底之蛙了),不过这种东西用在正义的人手上是一个除暴安良的利器,用心叵测者就不好说了,但是技术终归是技术,好的东西还是应该用心学习.
原贴中的程序已有更新,更新的程序中提供了VB.Net 8 的实现
使用方法可以查看示例代码,示例代码直接支持会报Class has not been initialized的错误,可以按上面的方式编译,然后去掉对工程的直接引用,再在引用中重新选择生成后的Dll文件.
Since the DOS age, people have been trying to figure out ways to hide their
processes from being detected. One can recall the Interruption Hook method used
in the early DOS. With the introduction of the new operating system, Microsoft
Windows 95 and the new security issues, the old method simply didn't work.
So, people had to find a new way, and they did indeed. They convinced the OS that
their program was a service. That way, it didn't show up in the task manager.
These tricks used to work well until Windows NT, and its successors were released.
Everything has changed, the task manager now includes a list of all currently
running processes (CRPs) that makes completely hiding a process almost impossible.
As a result of many hours of hard work, and about 8 Blue Screens of Death, and a
couple of unexpected reboots, I finally figured out how to completely hide
a process from being listed in *ANY* program that lists CRPs.
How did I do it?
The key to this problem is the Kernel-Mode Drivers' ability to do whatever they
wish to the system, there're no restrictions, they simply run in Ring-0!
So, i had to write a simple kernel mode driver that does the dirty job :)
NOTE: To compile the driver's source (.c), you have to have the NTDDK.
The CRPs list is formed by interlinking the "ActiveProcessLinks" member of
the "EPROCESS" structure. The head of this list is stored in the internal
global variable "PsActiveProcessHead". Unfortunately, the "PsActiveProcessHead"
variable is not exported by "ntoskrnl.exe", but we can use the function
"PsGetCurrentProcess" that returns a pointer to our EPROCESS structure
from which we can traverse the list.
typedef struct _EPROCESS
/*000*/ KPROCESS Pcb;
/*06C*/ NTSTATUS ExitStatus;
/*070*/ KEVENT LockEvent;
/*080*/ DWORD LockCount;
/*084*/ DWORD d084;
/*088*/ LARGE_INTEGER CreateTime;
/*090*/ LARGE_INTEGER ExitTime;
/*098*/ PVOID LockOwner;
/*09C*/ DWORD UniqueProcessId;
/*0A0*/ LIST_ENTRY ActiveProcessLinks;
list goes on... }
As you can see from the above structure (EPROCESS), the offset to
"ActiveProcessLinks" is +0xA0 (+160) and the offset to "UniqueProcessId"
which is the current process id is +0x9C (+156), both relative to the EPROCESS
structure. These offsets apply to Windows 2000, but using the kernel debugger,
we can obtain the new offsets for Windows XP and NT easily.
So, as these offsets depend mainly on the version of windows currently running,
they're given to the driver from the user mode program. Currently, only
Windows NT4.0, XP, 2000, and 2003 server are supported by the driver, earlier
versions of windows (9x/ME) are also supported through the old method of
convincing the operating system that the process is a service.
Back to where we where! So, as i was saying, hiding a process is as simple as
removing it from the CRPs chain! Take a look at the LIST_ENTRY structure:
typedef struct _LIST_ENTRY
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
As you can see, all CRPs are interlinked through that structure (by the pointer
"ActiveProcessLinks"). So, by changing the flink of the previous entry to point
to the flink of the following entry, we can remove our entry from the chain.
Not only that, we also need to change the blink of the following entry to point
to the flink of the previous entry. Sounds confusing, isn't it? Well, take a look
at following illustration:
========== ========== ==========
| 1 | | 2 | | 3 |
========== ========== ==========
| Flink |<-----*------>| Flink |<-----*------>| Flink |
|--------| | |--------| | |--------|
| Blink | |-------| Blink | |-------| Blink |
|________| |________| |________|
1, 2, and 3 represent three distinct processes and assuming that our process
is the middle one (2). Now the situation is:
Blink of (2) points to Flink of (1), Flink of (1) points to Flink of (2) and
Blink of (3) points to Flink of (2).
So, by making Flink of (1) points to Flink of (3) and Blink of (3) points to
Flink of (1), we can effectively remove our process from the CRPs chain!
How to use it?
See the included example. It's really easy!
Just add a reference to the DLL (after it's compiled) and include the DLL file with your
exe distribution package.
Included are the VB source code for the user mode test project, the source code
for the kernel mode driver, this ReadMe, and the binaries of the driver compiled
for Windows NT/2000 and XP included in the resource file (/Files/Project1.RES).
Don't worry about extracting the binaries (.sys files) and putting them into your
system32/drivers directory as the example included does everything for you easily.
Just run the example and enjoy the show!
I'm sure that this library won't be perfectly stable, on some systems it may
cause the system to behave unpredictably, for example, the system may reboot,
or even worse, might show up the infamous BSoD (Blue Screen of Death).
So, here is a small disclaimer:
In no way will the author (Islam Adel) be held any responsibility for the
actions or damages resulting from the use or misuse of the library (hideproc).
Anyway, hope you find that useful, and if it is, please vote for me at PSC.
All constructive comments are welcomed.