
KeePass 프로세스에 주입되면 데이터베이스를 평문으로 내보내는 독립형 DLL입니다.
KeePass 프로세스에 주입되면 데이터베이스를 평문으로 내보내는 독립 실행형 DLL입니다.
훌륭한 KeeFarce, KeeThief 및 KeePassHax 프로젝트에서 많은 영감을 받았습니다.
몇 년 전, @denandz는 KeePass 데이터베이스를 평문으로 추출하도록 설계된 최초의 공격 도구인 KeeFarce를 출시했습니다. 이 도구는 실행 중인 프로세스에 DLL을 주입한 다음 ClrMD를 사용하여 힙을 탐색해 필요한 개체를 찾고 리플렉션을 통해 KeePass의 내장 내보내기 메서드를 호출합니다. 당시의 유일한 단점은 대상에 여러 파일을 드롭해야 한다는 점이었습니다(추출 DLL + ClrMD DLL + 인젝터 + 부트스트랩 DLL).
1년 후, @tifkin_와 @harmj0y는 KeePass를 대상으로 한 공격 기법에 대한 심층 리뷰를 발표했습니다(harmj0y의 블로그에서는 더 이상 볼 수 없지만, 기사는 Wayback Machine에서 찾을 수 있습니다: part 1, part 2). 그 결과 KeePass의 마스터키를(대체 인증 방법이 사용될 때 포함) 복호화할 수 있는 도구인 KeeThief가 출시되었습니다. 너무 잘 작동해서 KeePass 개발자들은 이 기법을 완화하기 위해 매개변수를 추가했습니다(사용자에게 충분한 권한이 있다면 KeePass 구성 파일을 편집하여 비활성화할 수 있으며, 이는 상당히 일반적입니다).
이 도구들은 침투 테스트 중 빠르게 제 기본 선택이 되었지만, 주입 기법(즉, 유명한 Win32 API 무리인 VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, WriteProcessMemory 등)이 이제 즉시 탐지를 유발하면서 곧 쓸모없게 되었습니다. @snovvcrash는 D/Invoke로 주입 메커니즘을 개선하기 위해 KeeThief를 포크하고(현재는 비공개 리포지토리에 있지만 여기에서 여전히 접근 가능) 그가 따랐던 과정을 자세히 설명하는 훌륭한 기사를 작성하여 이 문제를 해결했습니다. 이것이 KeeThief를 유지 관리할 가능성을 입증했지만, KeeThief의 코드가 인젝터와 밀접하게 연결되어 있기 때문에 새로운 주입 기법을 정기적으로 구현하는 것이 어렵다고 생각합니다.
@holly-cracker는 단일 DLL로 제공되며 리플렉션만 사용하여 KeePass의 마스터키를 복호화하는 KeePassHax도 출시했습니다. 이 작업에서 영감을 받아 KeeFarce에서도 동일한 방식을 적용하고 다음과 같은 기능을 가진 나만의 KeePass 추출 도구를 작성하기로 결정했습니다:
KeeFarce Reborn은 또한 인젝터를 신경 쓸 필요 없이 KeePass가 스스로 주입하도록 만드는 KeePass 플러그인 DLL을 제공합니다!
코드가 외부 종속성 없이 .NET Framework만 사용하므로 Visual Studio 2015 이상에서 쉽게 컴파일할 수 있습니다.
KeeFarce Reborn에는 KeePass 프로세스에 DLL을 로드하는 인젝터가 포함되어 있지 않습니다. 이는 의도적인 것으로, 인젝터는 몇 달마다 쓸모없어지기 때문에 여러분만의 것을 사용해야 합니다. 다음 부분에서는 주입을 수행하는 두 가지 일반적인 방법을 보여줍니다.
전제 조건: KeePass 플러그인 디렉터리에 대한 쓰기 권한.
KeePass는 사용자에게 추가 기능을 제공하기 위한 플러그인 프레임워크를 제공합니다. 이는 KeePass 프로세스에 DLL을 로드하여 플러그인 개발자가 KeePass 애플리케이션 도메인 내에서 작업을 수행할 수 있도록 하는 방식으로 작동합니다.
결과적으로, 우리는 외부 인젝터를 사용할 필요조차 없이 이 기능을 악용하여 KeeFarce Reborn을 플러그인으로 로드할 수 있습니다! KeeFarceRebornPlugin 프로젝트를 컴파일하고 DLL을 플러그인 디렉터리(전역 설치의 경우 KeePass 루트, 즉 *"C:\Program Files\KeePass Password Safe 2\Plugins"*에 위치)에 복사하기만 하면 됩니다.
프로젝트를 올바르게 빌드하려면 대상 KeePass.exe 어셈블리 버전을 KeeFarceRebornPlugin 디렉터리에 복사하거나, 결과 플러그인이 모든 KeePass 버전과 호환되도록 하려면 PLGX를 사용해야 합니다.
다음에 KeePass가 시작되고 데이터베이스가 잠금 해제되면 DLL이 로드되고 주입이 수행됩니다. KeePass가 이미 실행 중이라면 주입이 발생할 때까지 다음 재시작을 기다려야 합니다(또는 직접 재시작을 강제).
⚠️ 플러그인이 로드되면 KeePass가 닫힐 때까지 DLL 파일이 쓰기 보호됩니다. 평가 중에 악성 플러그인을 남기지 않도록 이 점을 명심하세요.
KeePass 플러그인 디렉터리에 대한 쓰기 권한이 없는 경우, 플러그인 캐시를 통해 더 낮은 권한으로 플러그인을 로드하는 방법을 보여주는 Quarkslab의 기사를 살펴볼 수 있습니다.
전제 조건: KeePass가 실행 중 + 사용자가 데이터베이스 잠금 해제 + KeePass 프로세스에 주입할 수 있는 충분한 권한.
개인적으로 원격 프로세스에 DLL보다 셸코드를 은밀하게 주입하는 것이 더 쉽다고 생각하기 때문에, 일반적으로 가장 먼저 시작하는 것은 우리 DLL에서 위치 독립적 셸코드를 생성하는 것입니다. @odzhan과 @TheWover의 donut 프로젝트가 우리의 요구에 완벽하게 부합하는 것 같습니다!
donut을 dev 브랜치의 특정 커밋에서 컴파일합니다. 이 커밋은 기본 도메인에서 리플렉션을 수행하지 못하게 하는 애플리케이션 도메인 관리 문제를 수정하기 때문입니다.
git clone https://github.com/TheWover/donut/
cd donut
git checkout 9d781d8da571eb1499122fc0e2d6e89e5a43603c
Visual Studio의 x64 Native Tools 명령 프롬프트에서 nmake 유틸리티로 쉽게 빌드할 수 있습니다:
nmake -f Makefile.msvc
셸코드 생성은 다음과 같이 간단합니다:
.\donut.exe "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll" -c KeeFarceReborn.Program -m Main -e 1
[ Donut shellcode generator v0.9.3
[ Copyright (c) 2019 TheWover, Odzhan
[ Instance type : Embedded
[ Module file : "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll"
[ Entropy : None
[ File type : .NET DLL
[ Class : KeeFarceReborn.Program
[ Method : Main
[ Target CPU : x86+amd64
[ AMSI/WDLP : continue
[ Shellcode : "loader.bin"
-e 1은 엔트로피를 비활성화하는 데 필요합니다. 그렇지 않으면 주입된 프로세스가 기본 애플리케이션 도메인에 있지 않게 됩니다.
인젝터 코드에 더 쉽게 통합하기 위해 PowerShell을 사용하여 압축해 보겠습니다:
$bytes = [System.IO.File]:https://raw.githubusercontent.com/d3lb3/keefarcereborn/HEAD/:ReadAllBytes(%22C:%5Cdonut%5Cloader.bin%22)
[System.IO.MemoryStream] $outStream = New-Object System.IO.MemoryStream
$deflateStream = New-Object System.IO.Compression.DeflateStream($outStream, [System.IO.Compression.CompressionLevel]::Optimal)
$deflateStream.Write($bytes, 0, $bytes.Length)
$deflateStream.Dispose()
$outBytes = $outStream.ToArray()
$outStream.Dispose()
$b64 = [System.Convert]::ToBase64String($outBytes)
Write-Output $b64 | clip
이제 좋아하는 기법으로 주입할 준비가 된 페이로드가 생겼습니다. 무엇을 해야 할지 모르겠다면 ired.team 코드 및 프로세스 주입 페이지를 확인하여 개념에 익숙해지는 것이 좋습니다. @SEKTOR7의 악성코드 개발 강좌는 여유가 된다면 훌륭한 학습 자료로 가득 차 있습니다.
예를 들어, D/Invoke를 사용하는 snovvcrash의 VeraCryptThief 코드(그 자체로 SEKTOR7 강좌에서 영감을 받음)를 사용하여 페이로드를 주입해 보겠습니다. 데모를 위해 그의 프로젝트를 SampleInjector 폴더에 복사했으며, 압축된 셸코드를 붙여넣은 다음 x64로 컴파일하기만 하면 됩니다.
현재(2022년 11월)에는 여전히 Defender를 우회하지만, 최신 EDR을 우회하려면 물론 자신만의 인젝터를 직접 만져봐야 할 것입니다. 이 샘플 인젝터는 모든 것이 예상대로 작동한다는 것을 보여주기 위한 것일 뿐입니다.
열려 있는 KeePass 데이터베이스와 함께 .\SampleInjector.exe를 실행하면 DLL이 로드되고 주입이 수행됩니다.
주입이 수행되면 MessageBox에 디버그 메시지가 인쇄되는 것을 볼 수 있으며(실제 침투 테스트 시나리오에서는 당연히 제거해야 합니다), 그런 다음 현재 사용자의 *%APPDATA%*에서 내보낸 데이터베이스를 찾을 수 있습니다(기본적으로 선택되며, KeePass가 쓰기 권한을 가지고 있음이 확실하기 때문입니다). 내보낸 XML 파일은 나중에 비밀번호를 묻지 않고 모든 KeePass 데이터베이스로 가져올 수 있습니다.
플러그인 또는 내보내기 기능이 정책에 의해 비활성화된 경우, 쓰기 권한이 있다면 KeePass.config.xml을 편집하여 계속 활성화할 수 있습니다:
<Policy>
<Plugins>true</Plugins>
<Export>true</Export>
</Policy>
KeePass 추출 도구 탐지와 관련된 주요 문제는 인젝터이지만, 메모리 내 스캔은 셸코드나 플러그인 DLL을 분석할 때 경고를 트리거할 수도 있습니다. 인젝터와 함께 사용할 셸코드를 난독화 및/또는 암호화해야 할 수도 있습니다.
플러그인 DLL이 정적 분석에 의해 결국 플래그될 경우, KeePass의 PLGX 플러그인 형식을 사용하여 탐지를 피할 수도 있습니다.
DISM.exe를 사용하여 명령줄에서 수동으로 설정할 수 있습니다.Pull Request는 언제나 환영합니다. 개선 사항을 제안하려면 이슈를 열거나 Twitter에서 DM을 보내주세요.
일부 코드는 KeeFarce, KeeThief, KeePassHax 프로젝트에서 가져왔습니다.
샘플 주입 메커니즘은 snovvcrash의 프로젝트에서 직접 가져왔습니다.