
Windows 알림 기능을 위한 C# 유틸리티
This is the repository for Windows Notification Facility (WNF) tools. Currently, a C# port of the tools in wnfun developed by Alex Ionescu (@aionescu) and Gabrielle Viala (@pwissenlit) has been uploaded. When I develop additional tools for Windows Notification Facility, they will be uploaded here.
This tool dumps or manipulate information about WNF State Names. Equivalent to wnfdump.exe and WnfDump.py. I made some updates from the original tool (Exception Handling, Well-Known State Name and new WNF_DATA_SCOPE member).
To retrieve information of all Well-Known, Permanent and Persistent WNF State Names on your host, execute with -d (--dump) flag:```
PS C:\Dev> .\SharpWnfDump.exe -d
| WNF_WEBA_CTAP_DEVICE_STATE | S | W | N | RW | I | 0 | 12 | 0 | | WNF_WEBA_CTAP_DEVICE_CHANGE_NOTIFY | S | W | N | RW | I | 0 | 4 | 0 | | WNF_PNPA_DEVNODES_CHANGED | S | W | N | RO | U | 0 | 0 | 11 |
--snip--
시스템에서 사용된 상태 이름만 표시하려면 `-u`(`--used`) 플래그를 설정하세요.
이 플래그는 `-d` 및 `-b` 옵션에 적용할 수 있습니다:```
PS C:\Dev> .\SharpWnfDump.exe -d -u
| WNF State Name [WellKnown Lifetime] | S | L | P | AC | N | CurSize | MaxSize | Changes |
----------------------------------------------------------------------------------------------------------------------
| WNF_PNPA_DEVNODES_CHANGED | S | W | N | RO | U | 0 | 0 | 140 |
| WNF_AUDC_RENDER | S | W | N | RO | U | 4096 | 4096 | 7 |
| WNF_AUDC_CAPTURE | S | W | N | RO | U | 4096 | 4096 | 1 |
| WNF_AUDC_SPATIAL_STATUS | S | W | N | RO | U | 4096 | 4096 | 3 |
--snip--
Security Descriptor 정보를 검색하려면 -s (--sid) 플래그를 설정하세요:```
PS C:\Dev> .\SharpWnfDump.exe -d -s
| WNF_WEBA_CTAP_DEVICE_STATE | S | W | N | RW | I | 0 | 12 | 0 |
D:(A;;CCDC;;;SY)(A;;CCDC;;;BA)(A;;CCDC;;;S-1-5-80-242729624-280608522-2219052887-3187409060-2225943459)(A;;CC;;;AU)(A;;CC;;;AC)
| WNF_WEBA_CTAP_DEVICE_CHANGE_NOTIFY | S | W | N | RW | I | 0 | 4 | 0 |
D:(A;;CCDC;;;SY)(A;;CCDC;;;BA)(A;;CCDC;;;S-1-5-80-242729624-280608522-2219052887-3187409060-2225943459)(A;;CC;;;AU)(A;;CC;;;AC)
| WNF_PNPA_DEVNODES_CHANGED | S | W | N | RO | U | 0 | 0 | 11 |
D:(A;;CC;;;BU)(A;;CCDC;;;SY)
--snip--
버퍼 데이터를 검색하려면 `-v` (`--value`) 또는 `-r` (`--read`) 플래그를 설정하세요.
이 플래그들은 `-s` 플래그와 함께 사용할 수 있습니다:```
PS C:\Dev> .\SharpWnfDump.exe -d -v
| WNF State Name [WellKnown Lifetime] | S | L | P | AC | N | CurSize | MaxSize | Changes |
----------------------------------------------------------------------------------------------------------------------
| WNF_WEBA_CTAP_DEVICE_STATE | S | W | N | RW | I | 0 | 12 | 0 |
| WNF_WEBA_CTAP_DEVICE_CHANGE_NOTIFY | S | W | N | RW | I | 0 | 4 | 0 |
--snip--
| WNF_AUDC_RENDER | S | W | N | RO | U | 4096 | 4096 | 1 |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 | ........ ........
00000010 | 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 | ........ ........
00000020 | 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 | ........ ........
--snip--
호스트에서 모든 임시 WNF 상태 이름에 대한 정보를 검색하려면 -b (--brut) 플래그를 사용하여 실행하세요:```
PS C:\Dev> .\SharpWnfDump.exe -b
| 0x41C64E6DA3AC3845 | S | T | N | RW | A | 8 | ? | 1 | | 0x41C64E6DA3AC4845 | S | T | N | RW | A | 8 | ? | 1 | | 0x41C64E6DA3AC6845 | S | T | N | RW | A | 8 | ? | 1 |
--snip--
The `-b` (`--brut`) 플래그는 `-v` (`--value`) 또는 `-r` (`--read`) 플래그와 함께 사용할 수 있지만, `-s` (`--sid`) 플래그와는 함께 사용할 수 없습니다.
`--dump` 또는 `--brut` 옵션의 결과로 얻은 표의 각 열의 의미는 다음과 같습니다:
| Column Name | Description |
| :--- | :--- |
| `WNF State Name` | WNF State Name이 여기에 출력됩니다 |
| `S` | WNF State Name에 대한 데이터 범위. 표시되는 알파벳의 의미는 다음과 같습니다:<br><br>+ `S` : 시스템 범위<br>+ `s` : 세션 범위<br>+ `U` : 사용자 범위<br>+ `P` : 프로세스 범위<br>+ `M` : 머신 범위<br>+ `p` : 물리적 머신 범위 |
| `L` | WNF State Name에 대한 수명. 표시되는 알파벳의 의미는 다음과 같습니다:<br><br>+ `W` : Well-Known<br>+ `P` : 영구<br>+ `V` : 영속(휘발성)<br>+ `T` : 임시 |
| `P` | WNF State Name이 영구적인지 표시합니다:<br><br>+ `Y` : 예<br>+ `N` : 아니요 |
| `AC` | WNF State Name에 대한 액세스 제어:<br><br>+ `RW` : 읽기 및 쓰기 가능<br>+ `RO` : 읽기 전용<br>+ `WO` : 쓰기 전용<br>+ `NA` : 읽기 및 쓰기 불가 |
| `N` | 구독자 존재 여부를 표시합니다:<br><br>+ `A` : 구독자 있음<br>+ `I` : 구독자 없음<br>+ `U` : 알 수 없음 |
| `CurSize` | 이 숫자는 WNF State Name에 사용되는 현재 버퍼 크기를 의미합니다. |
| `MaxSize` | 이 숫자는 WNF State Name에 사용할 수 있는 최대 버퍼 크기를 의미합니다. |
| `Changes` | 이 숫자는 업데이트된 횟수를 의미합니다. |
특정 WNF State Name에 대한 정보를 검색하려면 다음과 같이 `-i` (`--info`) 옵션과 함께 `SharpWnfDump.exe`를 실행하십시오:```
PS C:\Dev> .\SharpWnfDump.exe -i WNF_SHEL_APPRESOLVER_SCAN
| WNF State Name | S | L | P | AC | N | CurSize | MaxSize | Changes |
----------------------------------------------------------------------------------------------------------------------
| WNF_SHEL_APPRESOLVER_SCAN | S | W | N | RW | A | 4 | 4 | 1 |
The -i (--info) 옵션은 -v (--value), -r (--read), 및 -s (--sid) 플래그와 함께 사용할 수 있습니다:```
PS C:\Dev> .\SharpWnfDump.exe -i WNF_SHEL_APPRESOLVER_SCAN -s -v
| WNF_SHEL_APPRESOLVER_SCAN | S | W | N | RW | A | 4 | 4 | 1 |
D:(A;;CC;;;WD)(A;;CCDC;;;AU)(A;;CCDC;;;AC)
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 01 00 00 00 | ....
특정 WNF 상태 이름에서 데이터를 읽으려면 `-r`(`--read`) 플래그를 다음과 같이 사용하세요:```
PS C:\Dev> .\SharpWnfDump.exe -r WNF_SHEL_APPRESOLVER_SCAN
WNF_SHEL_APPRESOLVER_SCAN:
00000000 | 11 00 00 00 | ....
특정 WNF State Name에 데이터를 쓰려면 다음과 같이 -w (--write) 플래그를 사용하십시오 (쓰기용 데이터는 파일로 제공해야 합니다):```
PS C:\Dev> "hi" | Out-File -Encoding ascii -FilePath C:\Dev\test.txt
PS C:\Dev> Get-Content -Path C:\Dev\test.txt
hi
PS C:\Dev> .\SharpWnfDump.exe -w WNF_SHEL_APPRESOLVER_SCAN C:\Dev\test.txt
[>] Trying to write data. [] Target WNF Name : WNF_SHEL_APPRESOLVER_SCAN [] Data Source : C:\Dev\test.txt [+] Data is written successfully.
PS C:\Dev> .\SharpWnfDump.exe -i WNF_SHEL_APPRESOLVER_SCAN -r
| WNF_SHEL_APPRESOLVER_SCAN | S | W | N | RW | A | 4 | 4 | 2 |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 68 69 0D 0A | hi..
### SharpWnfNameDumper
[맨 위로](#sharpwnfsuite)
[프로젝트](https://github.com/daem0nc0re/sharpwnfsuite/blob/main/SharpWnfSuite/SharpWnfNameDumper)
이 도구는 DLL(일반적으로 perf_nt_c.dll)에서 Well-Known State Name을 덤프합니다.
[WnfNameDumper.py](https://github.com/ionescu007/wnfun/blob/master/script_python/WnfNameDumper.py)와 동일합니다.
일반적으로 Well-Known State Name은 perf_nt_c.dll(Windows Performance Analyzer에 포함됨)에 들어 있습니다.
DLL에서 Well-Known State Name을 덤프하려면 다음과 같이 `-d`(`--dump`) 옵션과 함께 `SharpWnfNameDumper.exe`를 실행하세요.```
PS C:\Dev> .\SharpWnfNameDumper.exe -d perf_nt_c.dll
[>] Output results in C# style.
public enum WELL_KNOWN_WNF_NAME : ulong
{
WNF_9P_REDIRECTOR_STARTED = 0x41C61E54A3BC1075UL,
WNF_9P_UNKNOWN_DISTRO_NAME = 0x41C61E54A3BC0875UL,
--snip--
Well-Known State Names에 대한 설명을 덤프하려면 -v 플래그를 설정하세요:```
PS C:\Dev> .\SharpWnfNameDumper.exe -d perf_nt_c.dll -v
[>] Output results in C# style.
public enum WELL_KNOWN_WNF_NAME : ulong { // The Plan 9 Redirector was started and is ready to accept requests. WNF_9P_REDIRECTOR_STARTED = 0x41C61E54A3BC1075UL, // The Plan 9 Redirector got a request for an unknown WSL distribution and there is no user callback registered to query it. WNF_9P_UNKNOWN_DISTRO_NAME = 0x41C61E54A3BC0875UL,
--snip--
출력 형식을 지정하려면 `-f` (`--format`) 옵션을 사용하세요. `SharpWnfNameDumper.exe`는 C#, C (`-f c`) 및 Python (`-f py`) 형식을 지원합니다 (기본 형식은 C#):```
PS C:\Dev> .\SharpWnfNameDumper.exe -d perf_nt_c.dll -f py
[>] Output results in Python style.
g_WellKnownWnfNames = {
"WNF_9P_REDIRECTOR_STARTED": 0x41C61E54A3BC1075,
"WNF_9P_UNKNOWN_DISTRO_NAME": 0x41C61E54A3BC0875,
--snip--
결과를 파일로 출력하려면 -o (--output) 옵션을 사용하여 출력 파일 경로를 지정하세요:```
PS C:\Dev> .\SharpWnfNameDumper.exe -d perf_nt_c.dll -o result.txt
[>] Output results in C# style.
C:\dev>type result.txt public enum WELL_KNOWN_WNF_NAME : ulong { WNF_9P_REDIRECTOR_STARTED = 0x41C61E54A3BC1075UL, WNF_9P_UNKNOWN_DISTRO_NAME = 0x41C61E54A3BC0875UL,
--snip--
2개의 DLL에서 diff를 가져오려면 `-D` (`--diff`) 옵션을 사용하세요:```
PS C:\Dev> .\SharpWnfNameDumper.exe -D perf_nt_c_old.dll perf_nt_c_new.dll
[>] Output results in C# style.
################################################
# NEW KEYS #
################################################
public enum WELL_KNOWN_WNF_NAME : ulong
{
WNF_SHEL_CHAT_ICON_BADGE = 0x0D83063EA3B8A035UL,
WNF_SHEL_ENTERPRISE_START_PINS_POLICY_VALUE_CHANGED = 0x0D83063EA3B89475UL,
WNF_SHEL_FILE_EXPLORER_PINNED_FOLDERS = 0x0D83063EA3B8ACF5UL,
WNF_SHEL_MAC_AUTO_UPDATE_SUCCEEDED = 0x0D83063EA3B89875UL
}
WNF 상태 이름을 구독하기 위한 도구입니다. wnfclient-rtl.exe 및 WnfClientServer.py와 동등합니다.
예를 들어, WNF_SHEL_APPLICATION_STARTED 상태를 모니터링하려면 SharpWnfClient.exe를 다음과 같이 실행하십시오:```
PS C:\Dev> .\SharpWnfClient.exe WNF_SHEL_APPLICATION_STARTED
[>] Received data from server. [] Timestamp : 4 [] Buffer Size : 92 byte(s) [*] Data :
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 61 00 3A 00 6D 00 69 00-63 00 72 00 6F 00 73 00 | a.:.m.i. c.r.o.s.
00000010 | 6F 00 66 00 74 00 2E 00-77 00 69 00 6E 00 64 00 | o.f.t... w.i.n.d.
00000020 | 6F 00 77 00 73 00 74 00-65 00 72 00 6D 00 69 00 | o.w.s.t. e.r.m.i.
00000030 | 6E 00 61 00 6C 00 5F 00-38 00 77 00 65 00 6B 00 | n.a.l._. 8.w.e.k.
00000040 | 79 00 62 00 33 00 64 00-38 00 62 00 62 00 77 00 | y.b.3.d. 8.b.b.w.
00000050 | 65 00 21 00 61 00 70 00-70 00 00 00 | e.!.a.p. p...
그런 다음 메모장 애플리케이션을 시작하면 다음과 같은 결과가 표시됩니다:```
[>] Received data from server.
[*] Timestamp : 5
[*] Buffer Size : 90 byte(s)
[*] Data :
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 61 00 3A 00 6D 00 69 00-63 00 72 00 6F 00 73 00 | a.:.m.i. c.r.o.s.
00000010 | 6F 00 66 00 74 00 2E 00-77 00 69 00 6E 00 64 00 | o.f.t... w.i.n.d.
00000020 | 6F 00 77 00 73 00 6E 00-6F 00 74 00 65 00 70 00 | o.w.s.n. o.t.e.p.
00000030 | 61 00 64 00 5F 00 38 00-77 00 65 00 6B 00 79 00 | a.d._.8. w.e.k.y.
00000040 | 62 00 33 00 64 00 38 00-62 00 62 00 77 00 65 00 | b.3.d.8. b.b.w.e.
00000050 | 21 00 61 00 70 00 70 00-00 00 | !.a.p.p. ..
이 도구는 임시 수명을 가진 WNF State Name을 생성하고 구독자에게 메시지를 전송합니다. 이는 wnfserver.exe 및 WnfClientServer.py에 해당합니다.
새 WNF State Name 서버를 시작하려면 SharpWnfServer.exe를 실행하기만 하면 됩니다. 그러면 다음과 같은 대화형 셸이 표시됩니다:```
PS C:\Dev> .\SharpWnfServer.exe
[+] New WNF State Name is created successfully : 0x41C64E6DA3834945
Encoded State Name: 0x41C64E6DA3834945, Decoded State Name: 0x3F4931 Version: 1, Lifetime: Temporary, Scope: Machine, Permanent: NO, Sequence Number: 0x7E9, Owner Tag: 0x0
Sending input data to WNF subscriber...
[INPUT]>
`SharpWnfServer.exe`를 실행한 후, 다른 터미널에서 `SharpWnfServer.exe`에 제공된 WNF State Name을 사용하여 `SharpWnfClient.exe`를 실행하세요. `SharpWnfServer.exe`로부터 "Hello, world!" 메시지를 받아야 합니다:```
PS C:\Dev> .\SharpWnfClient.exe 0x41C64E6DA3834945
[>] Received data from server.
[*] Timestamp : 1
[*] Buffer Size : 13 byte(s)
[*] Data :
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 48 65 6C 6C 6F 2C 20 77-6F 72 6C 64 21 | Hello,.w orld!
SharpWnfClient.exe에 추가 메시지를 게시하려면 SharpWnfServer.exe의 대화형 셸에 메시지를 입력하세요:```
[INPUT]> This is WNF test
Sending input data to WNF subscriber...
[INPUT]>
그런 다음, `SharpWnfClient.exe`에 대해 터미널에 다음과 같은 메시지가 표시되어야 합니다:```
[>] Received data from server.
[*] Timestamp : 2
[*] Buffer Size : 16 byte(s)
[*] Data :
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 | 54 68 69 73 20 69 73 20-57 4E 46 20 74 65 73 74 | This.is. WNF.test
이 도구는 modexp의 wnfscan을 기반으로 하며, 프로세스에서 WNF 구독 정보를 덤프합니다.``` PS C:\Dev> .\SharpWnfScan.exe -h
SharpWnfScan - Tool for dumping WNF information from process.
Usage: SharpWnfScan.exe [Options]
-h, --help : Displays this help message.
-p, --pid : Specifies the target PID.
-P, --processname : Specifies the target process name.
-n, --name : Specifies a wnf state name for filtering.
-a, --all : Flag to dump information from all process.
-l, --list : Flag to list WNF State Name on this system.
-d, --debug : Flag to enable SeDebugPrivilege. Administrative privilege is required.
-v, --verbose : Flag to get verbose information.
특정 프로세스를 덤프하려면 `-p` 옵션을 다음과 같이 설정합니다:```
PS C:\Dev> .\SharpWnfScan.exe -p 5800
Process ID : 5800
Image File Name : C:\Windows\explorer.exe
Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x0000000001206660
WNF_NAME_SUBSCRIPTION @ 0x0000000001206B00
StateName : 0x0280032EA3BC0875 (WNF_CMFC_FEATURE_CONFIGURATION_CHANGED)
WNF_NAME_SUBSCRIPTION @ 0x000000000120AD10
StateName : 0x418B1929A3BC3835 (WNF_DWM_DUMP_REQUEST)
WNF_NAME_SUBSCRIPTION @ 0x0000000005099950
StateName : 0x41960A2EA3BC1835 (WNF_CDP_CDPUSERSVC_READY)
--snip--
WNF_USER_SUBSCRIPTION 정보를 얻으려면 -v 플래그를 다음과 같이 설정하세요:```
PS C:\Dev> .\SharpWnfScan.exe -p 5800 -v
Process ID : 5800 Image File Name : C:\Windows\explorer.exe Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x0000000001206660
WNF_NAME_SUBSCRIPTION @ 0x0000000001206B00
StateName : 0x0280032EA3BC0875 (WNF_CMFC_FEATURE_CONFIGURATION_CHANGED)
WNF_USER_SUBSCRIPTION @ 0x0000000001206A40
Callback @ 0x00007FFE88478470 (ntdll!RtlNotifyFeatureUsage+0x1C0)
Context @ 0x00007FFE886F0B20 (ntdll!NlsAnsiCodePage+0x2390)
WNF_NAME_SUBSCRIPTION @ 0x000000000120AD10
StateName : 0x418B1929A3BC3835 (WNF_DWM_DUMP_REQUEST)
WNF_USER_SUBSCRIPTION @ 0x0000000001207FD0
Callback @ 0x00007FF7073027C0 (explorer)
Context @ 0x0000000001208CC0 (N/A)
--snip--
`-P` 옵션으로 이름별로 대상 프로세스를 지정할 수 있습니다:```
PS C:\Dev> .\SharpWnfScan.exe -P notepad
Process ID : 8720
Image File Name : C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2401.26.0_arm64__8wekyb3d8bbwe\Notepad\Notepad.exe
Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x000001DE2B007560
WNF_NAME_SUBSCRIPTION @ 0x000001DE2B02D640
StateName : 0x41C61629A3BC2835 (WNF_DX_MONITOR_CHANGE_NOTIFICATION)
WNF_NAME_SUBSCRIPTION @ 0x000001DE2B03E040
StateName : 0x41950223A3BC1035 (WNF_NLS_USER_UILANG_CHANGED)
--snip--
상태 이름으로 필터링하려면 -n 옵션에 hex 또는 잘 알려진 wnf 이름 문자열을 다음과 같이 설정합니다:```
PS C:\Dev> .\SharpWnfScan.exe -P notepad -n WNF_RPCF_FWMAN_RUNNING
Process ID : 8720 Image File Name : C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2401.26.0_arm64__8wekyb3d8bbwe\Notepad\Notepad.exe Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x000001DE2B007560
WNF_NAME_SUBSCRIPTION @ 0x000001DE2B075040
StateName : 0x07851E3FA3BC0875 (WNF_RPCF_FWMAN_RUNNING)
PS C:\Dev> .\SharpWnfScan.exe -P notepad -n 0x07851E3FA3BC0875
Process ID : 8720 Image File Name : C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2401.26.0_arm64__8wekyb3d8bbwe\Notepad\Notepad.exe Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x000001DE2B007560
WNF_NAME_SUBSCRIPTION @ 0x000001DE2B075040
StateName : 0x07851E3FA3BC0875 (WNF_RPCF_FWMAN_RUNNING)
모든 프로세스를 한 번에 덤프하려면 `-a` 옵션을 사용하세요:```
PS C:\Dev> .\SharpWnfScan.exe -a
Process ID : 1180
Image File Name : C:\Windows\System32\svchost.exe
Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x000002101A806560
WNF_NAME_SUBSCRIPTION @ 0x000002101A830120
StateName : 0x07851E3FA3BC0875 (WNF_RPCF_FWMAN_RUNNING)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C1C0
StateName : 0x41C64E6DA3B0E045 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A833C50
StateName : 0x41C64E6DA3BC6145 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A846A50
StateName : 0x41C64E6DA3BD0945 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86CA00
StateName : 0x41C64E6DA3BB8045 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A806A00
StateName : 0x0280032EA3BC0875 (WNF_CMFC_FEATURE_CONFIGURATION_CHANGED)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C4C0
StateName : 0x41C64E6DA3B1E045 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C700
StateName : 0x41C64E6DA3A0F945 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x000002101A830EE0
StateName : 0x4195003AA3BC0875 (WNF_WNS_CONNECTIVITY_STATUS)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C880
StateName : 0x41C6072FA3BC3875 (WNF_BI_APPLICATION_SERVICING_START_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86CC40
StateName : 0x41C6072FA3BC1875 (WNF_BI_USER_LOGOFF_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A835E90
StateName : 0x41C6072FA3BC1075 (WNF_BI_USER_LOGON_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86CD00
StateName : 0x41C6072FA3BC2875 (WNF_BI_SESSION_DISCONNECT_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86CAC0
StateName : 0x41C6072FA3BC2075 (WNF_BI_SESSION_CONNECT_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C940
StateName : 0x41840B3EA3BC2075 (WNF_SEB_NETWORK_STATE_CHANGES)
WNF_NAME_SUBSCRIPTION @ 0x000002101A853920
StateName : 0x41C6072FA3BC3075 (WNF_BI_APPLICATION_UNINSTALL_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A836040
StateName : 0x41C6072FA3BC4875 (WNF_BI_LOCK_SCREEN_UPDATE_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C580
StateName : 0x41C6072FA3BC4075 (WNF_BI_APPLICATION_SERVICING_STOP_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A833B80
StateName : 0x41C6072FA3BC6075 (WNF_BI_QUIET_MODE_UPDATE_CHANNEL)
WNF_NAME_SUBSCRIPTION @ 0x000002101A86C400
StateName : 0x41C6072FA3BC5075 (WNF_BI_EVENT_DELETION)
Process ID : 2952
Image File Name : C:\Windows\System32\svchost.exe
Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x0000023DD3A065C0
WNF_NAME_SUBSCRIPTION @ 0x0000023DD3AF8B80
StateName : 0x41C64E6DA3B1E045 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x0000023DD3AF8C40
StateName : 0x41C64E6DA3BC6145 (N/A)
--snip--
SeDebugPrivilege를 활성화하려면 다음과 같이 -d 플래그를 설정합니다.
이 옵션은 관리자 권한이 필요합니다:```
PS C:\Dev> .\SharpWnfScan.exe -d -P winlogon
[+] SeDebugPrivilege is enabled successfully.
Process ID : 680 Image File Name : C:\Windows\System32\winlogon.exe Architecture : ARM64
WNF_SUBSCRIPTION_TABLE @ 0x00000265F4E05F80
WNF_NAME_SUBSCRIPTION @ 0x00000265F4E48AE0
StateName : 0x41C64E6DA3BC6145 (N/A)
WNF_NAME_SUBSCRIPTION @ 0x00000265F4E27AD0
StateName : 0x41C61629A3BC1035 (WNF_DX_MODE_CHANGE_NOTIFICATION)
--snip--
대상 시스템에서 사용되는 WNF State Names를 나열하려면 다음과 같이 `-l` 플래그를 설정하세요:```
PS C:\Dev> .\SharpWnfScan.exe -l
[>] Trying to list WNF State Names used in this system. Wait a moment.
[1304 WNF State Names]
[*] 0x07851E3FA3BC0875 (WNF_RPCF_FWMAN_RUNNING)
[*] 0x41C64E6DA3B0E045 (N/A)
[*] 0x41C64E6DA3BC6145 (N/A)
[*] 0x41C64E6DA3BD0945 (N/A)
[*] 0x41C64E6DA3BB8045 (N/A)
[*] 0x0280032EA3BC0875 (WNF_CMFC_FEATURE_CONFIGURATION_CHANGED)
[*] 0x41C64E6DA3B1E045 (N/A)
--snip--
[16 Access Denied Processes]
[*] svchost (PID : 2352)
[*] svchost (PID : 4952)
[*] MsMpEng (PID : 3132)
--snip--
[*] Done.
이 도구는 공격자가 코드 인젝션 기술에 WNF를 악용할 수 있는 방법을 조사하기 위한 것입니다:``` PS C:\Dev> .\SharpWnfInject.exe -h
SharpWnfInject - Tool to investigate WNF code injection technique.
Usage: SharpWnfInject.exe [Options]
-h, --help : Displays this help message.
-n, --name : Specifies WNF State Name to inject. Hex format or Well-known name format is accepted.
-p, --pid : Specifies PID to inject.
-i, --input : Specifies the file path to shellcode.
-d, --debug : Flag to enable SeDebugPrivilege. Requires administrative privilege.
[!] -n option is required.
이 도구는 특정 WNF State Name에 대한 `WNF_USER_SUBSCRIPTION`의 콜백 함수 포인터를 덮어씁니다.
이 코드 주입 기술은 모든 WNF State Name에서 작동하지 않습니다.
예를 들어, 이 기술은 Windows 11 23H2에서 `explorer.exe`가 사용하는 `WNF_SHEL_WINDOWSTIP_CONTENT_PUBLISHED`에 사용할 수 있는 것으로 알려져 있습니다.
이 기술을 테스트하려면 다음과 같이 이 도구를 실행하세요:```
PS C:\Dev> .\SharpWnfInject.exe -p 5800 -n WNF_SHEL_WINDOWSTIP_CONTENT_PUBLISHED -i .\notepad_arm64.bin
[*] Target WNF State Name is 0x0D83063EA3BE10F5 (WNF_SHEL_WINDOWSTIP_CONTENT_PUBLISHED).
[+] Got a handle from the target Process
[*] Process Name : explorer.exe
[*] Process ID : 5800
[*] Image File Name : C:\Windows\explorer.exe
[*] Architecture : ARM64
[+] Pointer for WNF_SUBSCRIPTION_TABLE is at 0x00007FFE886F4E20.
[+] WNF_SUBSCRIPTION_TABLE is at 0x0000000001206660.
[*] WNF_NAME_SUBSCRIPTION is at 0x0000000001273540.
[+] Got 1 WNF_USER_SUBSCRIPTION.
[*] Target callback pointer is at 0x00000000051C2250.
[*] Callback function is at 0x00007FFE54FD4D20 (twinui!DllGetClassObject+0x11AFF0).
[+] Shellcode buffer is at 0x0000000003270000.
[+] 344 bytes shellcode is written successfully.
[+] Callback pointer is overwritten successfully.
[>] Triggering shellcode.
[+] WNF State Data is updated successfully. Shellcode might be executed.
[+] Callback pointer is reverted successfully.
[*] Done.

SeDebugPrivilege를 활성화하려면 -d 플래그를 설정하고 관리자 권한으로 실행하세요.
메모장을 실행하는 샘플 셸코드는 Shellcode 디렉터리에 있습니다.
이 디렉터리의 프로젝트는 커널 익스플로잇을 위한 WNF 프리미티브를 시연하기 위한 것입니다. 자세한 내용은 Alex Plaskett의 발표 및 블로그에서 확인할 수 있습니다 (1부, 2부, 슬라이드).
PoC의 신뢰성은 100%가 아닙니다. Windows 10 x64의 모든 버전에 대한 커널 오프셋을 정의했지만, Windows 10 Version 1903 x64에서만 테스트했습니다.
| 프로젝트 | 설명 |
|---|---|
| PoolVulnDrv | WNF 커널 프리미티브를 테스트하기 위한 취약한 커널 드라이버입니다. |
| WnfPoolOverflow | PoolVulnDrv를 익스플로잇하기 위한 PoC입니다. |

이 디렉터리에는 나만의 WNF 콜백 셸코드를 빌드하기 위한 문서와 샘플 코드가 포함되어 있습니다. README.md를 참조하세요.
연구에 감사드립니다:
도움에 감사드립니다: