📄 nthandle的实现过程和反汇编的c源代码.txt
字号:
NTHANDLE的实现过程和反汇编的C源代码
--------------------------------------------------------------------------------
FLASHSKY 时间:2003-11-30 22:04:05
NTHANDLE是www.sysinternals.com一个可以查看进程打开的内核句柄信息的工具。其实现主要过程是:
首先将两个驱动程序文件当作资源拷贝到自己的程序节内,这两个文件是nthandle.sys和nthandle.vdx,分别用于WINNT(2000)下的驱动和WIN9X下的驱动,程序在运行的时候通过判断操作系统版本来将对应的驱动文件拷贝到相应的系统驱动目录下,然后程序修改驱动服务的注册表项,然后利用未存挡的NtLoadDrive API启动驱动程序,然后建立一个设备连接。
然后程序用大家熟悉的NTQUERYSYSTEMINFORATION获得所有句柄的信息结构数组,然后将句柄复制到自己的进程空间,又利用一个未存档的API NtQueryObject就可以获取对应的类型名字等信息,如果该名字是process和thread,那么就可以使用NtQueryInformationProcess或NtQueryInformationThread查询其信息,检查打开其句柄的进程号是否于原句柄一样,就可以判断这个进程或线程是本来进程中的一个,还是打开的其他进程或线程的句柄。
对于非线程和进程句柄对象,则需要使用刚才提到的拷贝的驱动程序去查询其信息了。
在驱动程序中,首先根据传开的句柄所属的进程ID判断是否小于8(除了0外我不知道哪个进程还比8小),对于这种进程的句柄则使用未存档的PsLookupProcessByProcessId和KeAttachProcess连接以后,使用ObReferenceObjectByHandle获取句柄的引用的地址信息,对于其他的进程则直接使用ZwOpenProcess和ZwDuplicateObject复制句柄,然后使用ObReferenceObjectByHandle获取句柄的引用的地址信息。
对于获得的内核句柄的第一个DWORD,会比较是否等于0x700005,这个属于什么类型的内核对象不太清楚,这种对象的描述信息是由许多链表结构组成的,需要进行链表操作,将多个链表中的描述信息拷贝到一起来形成一个完整的描述,对于非这种类型的对象,则直接按如下方式操作:
利用ObQueryNameString API就可以获取对象具体使用的名字(也就是具体的描述信息了),然后将对应的信息拷贝到输出缓冲来,对于调用失败的处理,则通过MmIsAddressValid检查连接的指针是否有效来判断是否是属于一个链表组成的描述对象,是的话调用链表操作查询的子过程。
以上过程比较有趣的地方是:
1是把驱动当做资源文件,然后运行的时候拷贝,2是程序运行时通过注册表修改和调用NTLOADDRIVER启动驱动程序,这有点象驱动类型病毒的特征。
下面就是具体的C代码,由于没有反汇编vdx的文件,所有只对NT,2000有效,另外在SYS提供了获取令牌信息的接口,而我程序中并没使用,而是直接获取,对0,8号进程是无法正确获取运行用户身份的,如果需要则可以修改此处为调用驱动对应的接口来处理,另外驱动中虽然有对小于8(0)号进程处理的过程,但实际无论是我写的,还是NTHANDLE本身都无法列出0号进程具体打开句柄的更多的信息,具体原因还有待于深入研究。由于是反汇编而来,不免存在一些错误,而且对于驱动的反汇编,由于其是不带调试信息的驱动,无法加载符号表进行动态跟踪和调式,是能一味的看汇编静态代码而来,本身对驱动也不是很熟悉,错误可能更多,调式自己写的驱动的时候,蓝屏N次,不过后来基本还稳定了,但肯定还是有很多错误和BUG,希望大家指正。
//HANDLE。EXE的C代码,需要将SYS编译好以后加入到对应的资源类型,需要修改生成的资源ID号为字符串并于程序中使用的名字一致。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <Aclapi.h>
#include <stdio.h>
#include <winioctl.h>
#include <winerror.h>
#define NT_HANDLE_LIST 16
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[229];
PVOID Reserved3[59];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _HandleInfo
{
USHORT dwPid;
USHORT CreatorBackTraceIndex;
BYTE ObjType;
BYTE HandleAttributes;
USHORT HndlOffset;
DWORD dwKeObject;
ULONG GrantedAccess;
}HANDLEINFO, *PHANDLEINFO;
typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PVOID Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;
typedef struct _ANSI_STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
}ANSI_STRING,*PANSI_STRING;
typedef struct _MYOBJECTINFO {
DWORD pid;
DWORD objaddr;
DWORD objhandle;
} MYOBJECTINFO, *PMYOBJECTINFO;
typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
UNICODE_STRING *ObjectName;
ULONG Attributes;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
// 申明ntdll中使用的函数
typedef DWORD (CALLBACK* NTQUERYSYSTEMINFORMATION)( DWORD, PDWORD, DWORD, PVOID );
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
typedef DWORD (CALLBACK* RTLANSISTRINGTOUNICODESTRING)(PVOID, PVOID,DWORD);
RTLANSISTRINGTOUNICODESTRING RtlAnsiStringToUnicodeString;
typedef DWORD (CALLBACK* NTLOADDRIVER)(PVOID);
NTLOADDRIVER NtLoadDriver;
typedef DWORD (CALLBACK* RTLFREEUNICODESTRING)(PVOID);
RTLFREEUNICODESTRING RtlFreeUnicodeString;
typedef DWORD (CALLBACK* RTLNTSTATUSTODOSERROR)(DWORD, PDWORD, DWORD, PVOID );
RTLNTSTATUSTODOSERROR RtlNtStatusToDosError;
typedef DWORD (CALLBACK* NTQUERYINFORMATIONTHREAD)(HANDLE,DWORD,PVOID,DWORD,PDWORD);
NTQUERYINFORMATIONTHREAD NtQueryInformationThread;
typedef DWORD (CALLBACK* NTQUERYINFORMATIONPROCESS)(HANDLE,DWORD,PVOID,DWORD,PDWORD);
NTQUERYINFORMATIONPROCESS NtQueryInformationProcess;
typedef DWORD (CALLBACK* NTQUERYDIRECTORYOBJECT)( DWORD, PDWORD, DWORD, PVOID );
NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject;
typedef DWORD (CALLBACK* NTQUERYSYMBOLICLINKOBJECT)(HANDLE,PUNICODE_STRING,PULONG );
NTQUERYSYMBOLICLINKOBJECT NtQuerySymbolicLinkObject;
typedef DWORD (CALLBACK* NTOPNESYMBOLICLINKOBJECT)(PVOID, DWORD,PVOID);
NTOPNESYMBOLICLINKOBJECT NtOpenSymbolicLinkObject;
typedef DWORD (CALLBACK* NTOPNEDIRECTORYOBJECT)( DWORD, PDWORD, DWORD, PVOID );
NTOPNEDIRECTORYOBJECT NtOpenDirectoryObject;
typedef DWORD (CALLBACK* NTQUERYOBJECT)(HANDLE,DWORD, PVOID, DWORD,PDWORD);
NTQUERYOBJECT NtQueryObject;
typedef DWORD (CALLBACK* RTLFREEANSISTRING)(PVOID);
RTLFREEANSISTRING RtlFreeAnsiString;
typedef DWORD (CALLBACK* RTLUNICODESTRINGTOANSISTRING)(PANSI_STRING, PUNICODE_STRING,DWORD);
RTLUNICODESTRINGTOANSISTRING RtlUnicodeStringToAnsiString;
typedef DWORD (CALLBACK* RTLINITANSISTRING)(PVOID, PVOID);
RTLINITANSISTRING RtlInitAnsiString;
typedef VOID(CALLBACK* INITIALIZEOBJECTATTRIBUTES)(POBJECT_ATTRIBUTES,PUNICODE_STRING,ULONG,HANDLE,PSECURITY_DESCRIPTOR);
INITIALIZEOBJECTATTRIBUTES InitializeObjectAttributes;
HANDLE drv;
char workdir[256];
char sysdir[256];
char drivcedir[256];
HANDLE dh; //存放复制的对象句柄
void ChangePrivilege(HANDLE pmy,char * PrivilegeVal)
{
int isok;
TOKEN_PRIVILEGES NewState;
HANDLE hToken;
NewState.PrivilegeCount=1;
NewState.Privileges[0].Attributes=2;
NewState.Privileges[0].Luid.HighPart=0;
NewState.Privileges[0].Luid.LowPart=0;
isok=LookupPrivilegeValue(0,PrivilegeVal,&NewState.Privileges[0].Luid);
isok=OpenProcessToken(pmy,0x20,&hToken);
isok=AdjustTokenPrivileges(hToken,0,&NewState,0x10,0,0);
CloseHandle(hToken);
}
void GetProcessAuth(long pid)
{
//获得运行进程的用户身份,此处对于8以上的进程没问题,对于8,0进程无法列出,可以替换成使用驱动对应的例程,就可以列举0,8进程运行的用户身份
SID_NAME_USE peUse;
HANDLE hp;
HANDLE hToken;
int isok;
char buf[0x400];
char buf1[100];
char buf2[100];
DWORD dwNumBytesRet;
DWORD dwNumBytesRet1;
hp=OpenProcess(0x400,0,pid);
isok=OpenProcessToken(hp,0x20008,&hToken);
isok=GetTokenInformation(hToken,TokenUser,&buf,0x400,&dwNumBytesRet);
if(isok)
{
dwNumBytesRet = 100;
dwNumBytesRet1 = 100;
isok = LookupAccountSid(NULL,(DWORD *)(*(DWORD*)buf),buf1,&dwNumBytesRet,buf2,&dwNumBytesRet1,&peUse);
printf("Run Auth:%s\\%s \n",buf2,buf1);
CloseHandle(hToken);
}
CloseHandle(hp);
}
int RegHandelDev(char * exename)
{
//修改注册表启动NTHANDLE驱动程序
char subkey[200];
LSA_UNICODE_STRING buf1;
LSA_UNICODE_STRING buf2;
int buflen;
HKEY hkResult;
char Data[4];
DWORD isok;
buflen = sprintf(subkey,"System\\CurrentControlSet\\Services\\%s",exename);
subkey[buflen]=0;
isok = RegCreateKey(HKEY_LOCAL_MACHINE,subkey,&hkResult);
if(isok!=ERROR_SUCCESS)
return false;
Data[0]=1;
Data[1]=0;
Data[2]=0;
Data[3]=0;
isok=RegSetValueEx(hkResult,"Type",0,4,(const unsigned char *)Data,4);
isok=RegSetValueEx(hkResult,"ErrorControl",0,4,(const unsigned char *)Data,4);
isok=RegSetValueEx(hkResult,"Start",0,4,(const unsigned char *)Data,4);
buflen = sprintf(drivcedir,"%s\\Drivers\\NTHANDLE.SYS",sysdir);
buflen = sprintf(subkey,"\\??\\%s",drivcedir);
subkey[buflen]=0;
isok=RegSetValueEx(hkResult,"ImagePath",0,1,(const unsigned char *)subkey,buflen);
RegCloseKey(hkResult);
buflen = sprintf(subkey,"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s",exename);
subkey[buflen]=0;
buf2.Buffer = (PVOID)subkey;
buf2.Length = buflen;
RtlAnsiStringToUnicodeString(&buf1,&buf2,1);
//加载驱动程序
isok = NtLoadDriver(&buf1);
RtlFreeUnicodeString(&buf1);
buflen=sprintf(subkey,"%s%s\\Enum","System\\CurrentControlSet\\Services\\",exename);
subkey[buflen]=0;
//删除注册表项
RegDeleteKey(HKEY_LOCAL_MACHINE,subkey);
buflen=sprintf(subkey,"%s%s\\Security","System\\CurrentControlSet\\Services\\",exename);
subkey[buflen]=0;
RegDeleteKey(HKEY_LOCAL_MACHINE,subkey);
buflen=sprintf(subkey,"%s%s","System\\CurrentControlSet\\Services\\",exename);
subkey[buflen]=0;
RegDeleteKey(HKEY_LOCAL_MACHINE,subkey);
buflen=sprintf(subkey,"\\\\.\\%s",exename);
subkey[buflen]=0;
//建立设备连接
drv = CreateFile(subkey,GENERIC_READ|GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(drv==INVALID_HANDLE_VALUE)
{
buflen=sprintf(subkey,"\\\\.\\Global\\%s",exename);
subkey[buflen]=0;
drv = CreateFile(subkey,GENERIC_READ|GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(drv==INVALID_HANDLE_VALUE)
return false;
}
return true;
}
int CopyMyDrivceNt()
{
//将资源文件拷贝出来成为NTHANDLE。SYS驱动程序
//源程序还区分是98就拷贝NTHANDLE。VDX。此处没有进行98的处理
FILE * fp;
HRSRC ntdrivce;
long buflen;
HGLOBAL re;
DWORD resize;
LPVOID readdr;
GetSystemDirectory(sysdir,256);
buflen = sprintf(drivcedir,"%s\\Drivers\\NTHANDLE.SYS",sysdir);
//"NTDRV"是加入资源文件时定义的名字,"BINRES"是加入资源文件时定义的资源类名,可以修改,只要与你加入的定义一致就可以
ntdrivce = FindResource(NULL,"NTDRV","BINRES");
if(ntdrivce==NULL)
{
printf("don't load resource\n");
return false;
}
re = LoadResource(NULL,ntdrivce);
resize = SizeofResource(NULL,ntdrivce);
readdr = LockResource(re);
fp = fopen(drivcedir,"wb");
if(fp==NULL)
return false;
fwrite(readdr,1,resize,fp);
fclose(fp);
return true;
}
DWORD callnthandle(DWORD opcode,PVOID inbuf,DWORD inbuflen,PVOID outbuf,DWORD outbuflen)
{
DWORD returnnum=0;
DWORD isok;
isok=DeviceIoControl(drv,opcode,inbuf,inbuflen,outbuf,outbuflen,&returnnum,NULL);
return isok;
}
int main(int argc,char *argv[])
{
HMODULE hNtdll = NULL;
PHANDLEINFO pHandleInfo;
HANDLE pmy;
hNtdll = LoadLibrary( "ntdll.dll" );
PDWORD pdwHandInfo;
DWORD isok;
DWORD dwNumBytesRet;
DWORD dwSize;
DWORD ver;
if ( !hNtdll )
{
printf( "LoadLibrary( NTDLL.DLL ) Error:%d\n", GetLastError() );
return false;
}
NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
GetProcAddress( hNtdll, "NtQuerySystemInformation");
RtlAnsiStringToUnicodeString = (RTLANSISTRINGTOUNICODESTRING)
GetProcAddress( hNtdll, "RtlAnsiStringToUnicodeString");
RtlFreeUnicodeString = (RTLFREEUNICODESTRING)
GetProcAddress( hNtdll, "RtlFreeUnicodeString");
NtLoadDriver = (NTLOADDRIVER)
GetProcAddress( hNtdll, "NtLoadDriver");
NtOpenSymbolicLinkObject = (NTOPNESYMBOLICLINKOBJECT)
GetProcAddress( hNtdll, "NtOpenSymbolicLinkObject");
InitializeObjectAttributes = (INITIALIZEOBJECTATTRIBUTES)
GetProcAddress( hNtdll, "InitializeObjectAttributes");
NtQuerySymbolicLinkObject = (NTQUERYSYMBOLICLINKOBJECT)
GetProcAddress( hNtdll, "NtQuerySymbolicLinkObject");
NtQueryObject = (NTQUERYOBJECT)
GetProcAddress( hNtdll, "NtQueryObject");
NtQueryInformationThread = (NTQUERYINFORMATIONTHREAD)
GetProcAddress( hNtdll, "NtQueryInformationThread");
NtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
GetProcAddress( hNtdll, "NtQueryInformationProcess");
RtlUnicodeStringToAnsiString = (RTLUNICODESTRINGTOANSISTRING)
GetProcAddress( hNtdll, "RtlUnicodeStringToAnsiString");
GetCurrentDirectory(256,workdir);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -