- Source: SECCON Beginners CTF 2025
- Author: Yunox
UUIDらしき文字列が書かれたtxtとWindowsスクリプトが与えられる。
ps_z.ps1
add-type '
using System;
using System.Runtime.InteropServices;
[StructLayout( LayoutKind.Sequential )]
public static class Kernel32{
[DllImport( "kernel32.dll" )]
public static extern IntPtr VirtualAlloc( IntPtr address, int size, int AllocType, int protect );
[DllImport( "kernel32.dll" )]
public static extern bool EnumSystemLocalesA( IntPtr buf, uint flags );
}
public static class Rpcrt4{
[DllImport( "rpcrt4.dll" )]
public static extern void UuidFromStringA( string uuid, IntPtr buf );
}';
$workdir = ( Get-Location ).Path;
[System.IO.Directory]::SetCurrentDirectory( $workdir );
$lines = [System.IO.File]::ReadAllLines( ".\sh.txt" );
$buf = [Kernel32]::VirtualAlloc( [IntPtr]::Zero, $lines.Length * 16, 0x1000, 0x40 );
$proc = $buf;
foreach( $line in $lines ){
$tmp = [Rpcrt4]::UuidFromStringA( $line, $buf );
$buf = [IntPtr]( $buf.ToInt64() + 16 )
}
$tmp = [Kernel32]::EnumSystemLocalesA( $proc, 0 );
sh.txt
56525153-4157-4150-5155-4889e54883e4
ec8348f0-6530-8b48-0425-60000000488b
8b482040-80b0-0000-0083-3e000f84a701
3e810000-0043-0054-7526-817e04460034
811d7500-087e-0042-3d00-7514837e0c31
8b480e75-481e-e3c1-0848-895c2420eb06
02c68348-c3eb-4865-8b04-256000000048
4818408b-408b-4820-8b00-488b7850488b
20b9481f-2000-2000-0020-004809cb48c1
334808e3-245c-4820-8b00-488b78504803
20b9481f-2000-2000-0020-004809cb4889
4820245c-588b-8b20-433c-4801d88bb888
48000000-df01-778b-2048-01de48ba0540
7d454e56-2a08-8948-5424-104831c98b14
da01488e-3a81-6547-7453-7514817a0474
75614864-810b-087a-6e64-6c657502eb05
ebc1ff48-8bd9-2477-4801-de668b0c4e8b
01481c77-8bde-8e04-4801-d848ba5b403a
13404150-4852-5489-2418-b9f5ffffffff
c08949d0-ba48-5908-0314-1059096b4889
778b2414-4820-de01-4831-c98b148e4801
573a81da-6972-7574-1481-7a0465436f6e
7a810b75-7308-6c6f-6575-02eb0548ffc1
778bd9eb-4824-de01-668b-0c4e48ba1f72
13044e56-681c-8948-5424-088b771c4801
8e048bde-0148-48d8-83ec-30488d542430
48c93148-f983-7404-124c-8b4c24504c33
894cca0c-ca0c-ff48-c1eb-e84c89c149c7
000020c0-4d00-c931-48c7-442420000000
48d0ff00-c483-eb30-0048-31c04889ec5d
58415941-5e5f-595a-5bc3-000000000000
これはUUID Shellcode Loaderというもので、マルウェアなどをUUID文字列として保存し、それをUuidFromStringAでメモリ上に復元して実行しているらしい。
まずはこのUUIDからシェルコードを復元する。このようなスクリプトを(LLMが)書いた。
import uuid
import sys
def uuid_to_shellcode(input_file, output_file):
print(f"[*] Reading from {input_file}...")
try:
with open(input_file, 'r') as f_in, open(output_file, 'wb') as f_out:
count = 0
for line in f_in:
line = line.strip()
# 空行やUUIDの形式でない行をスキップ
if not line or len(line) < 36:
continue
try:
# UUIDオブジェクトを作成
# 文字列を解析します
u = uuid.UUID(line)
# .bytes_le を使うことで Windows GUID 構造体のメモリレイアウト
# (Data1~3はリトルエンディアン、Data4はそのまま) でバイト列を取得
binary_data = u.bytes_le
f_out.write(binary_data)
count += 1
except ValueError:
print(f"[!] Invalid UUID format detected: {line}")
continue
print(f"[*] Successfully converted {count} UUIDs.")
print(f"[*] Saved to {output_file}")
except FileNotFoundError:
print(f"[!] Error: {input_file} not found.")
except Exception as e:
print(f"[!] Unexpected error: {e}")
if __name__ == "__main__":
# ファイル名を指定
INPUT_FILENAME = "sh.txt"
OUTPUT_FILENAME = "shellcode.bin"
uuid_to_shellcode(INPUT_FILENAME, OUTPUT_FILENAME)
これを逆アセンブルすると、それっぽいアセンブリが得られる。
ndisasm -b 64 shellcode.bin > output.asm
output.asm
00000000 53 push rbx
00000001 51 push rcx
00000002 52 push rdx
00000003 56 push rsi
00000004 57 push rdi
00000005 4150 push r8
00000007 4151 push r9
00000009 55 push rbp
0000000A 4889E5 mov rbp,rsp
0000000D 4883E4F0 and rsp,byte -0x10
00000011 4883EC30 sub rsp,byte +0x30
00000015 65488B0425600000 mov rax,[gs:0x60]
-00
0000001E 488B4020 mov rax,[rax+0x20]
00000022 488BB080000000 mov rsi,[rax+0x80]
00000029 833E00 cmp dword [rsi],byte +0x0
0000002C 0F84A7010000 jz near 0x1d9
00000032 813E43005400 cmp dword [rsi],0x540043
00000038 7526 jnz 0x60
0000003A 817E0446003400 cmp dword [rsi+0x4],0x340046
00000041 751D jnz 0x60
00000043 817E0842003D00 cmp dword [rsi+0x8],0x3d0042
0000004A 7514 jnz 0x60
0000004C 837E0C31 cmp dword [rsi+0xc],byte +0x31
00000050 750E jnz 0x60
00000052 488B1E mov rbx,[rsi]
00000055 48C1E308 shl rbx,byte 0x8
00000059 48895C2420 mov [rsp+0x20],rbx
0000005E EB06 jmp short 0x66
00000060 4883C602 add rsi,byte +0x2
00000064 EBC3 jmp short 0x29
00000066 65488B0425600000 mov rax,[gs:0x60]
-00
0000006F 488B4018 mov rax,[rax+0x18]
00000073 488B4020 mov rax,[rax+0x20]
00000077 488B00 mov rax,[rax]
0000007A 488B7850 mov rdi,[rax+0x50]
0000007E 488B1F mov rbx,[rdi]
00000081 48B9200020002000 mov rcx,0x20002000200020
-2000
0000008B 4809CB or rbx,rcx
0000008E 48C1E308 shl rbx,byte 0x8
00000092 48335C2420 xor rbx,[rsp+0x20]
00000097 488B00 mov rax,[rax]
0000009A 488B7850 mov rdi,[rax+0x50]
0000009E 48031F add rbx,[rdi]
000000A1 48B9200020002000 mov rcx,0x20002000200020
-2000
000000AB 4809CB or rbx,rcx
000000AE 48895C2420 mov [rsp+0x20],rbx
000000B3 488B5820 mov rbx,[rax+0x20]
000000B7 8B433C mov eax,[rbx+0x3c]
000000BA 4801D8 add rax,rbx
000000BD 8BB888000000 mov edi,[rax+0x88]
000000C3 4801DF add rdi,rbx
000000C6 8B7720 mov esi,[rdi+0x20]
000000C9 4801DE add rsi,rbx
000000CC 48BA0540564E457D mov rdx,0x2a087d454e564005
-082A
000000D6 4889542410 mov [rsp+0x10],rdx
000000DB 4831C9 xor rcx,rcx
000000DE 8B148E mov edx,[rsi+rcx*4]
000000E1 4801DA add rdx,rbx
000000E4 813A47657453 cmp dword [rdx],0x53746547
000000EA 7514 jnz 0x100
000000EC 817A0474644861 cmp dword [rdx+0x4],0x61486474
000000F3 750B jnz 0x100
000000F5 817A086E646C65 cmp dword [rdx+0x8],0x656c646e
000000FC 7502 jnz 0x100
000000FE EB05 jmp short 0x105
00000100 48FFC1 inc rcx
00000103 EBD9 jmp short 0xde
00000105 8B7724 mov esi,[rdi+0x24]
00000108 4801DE add rsi,rbx
0000010B 668B0C4E mov cx,[rsi+rcx*2]
0000010F 8B771C mov esi,[rdi+0x1c]
00000112 4801DE add rsi,rbx
00000115 8B048E mov eax,[rsi+rcx*4]
00000118 4801D8 add rax,rbx
0000011B 48BA5B403A504140 mov rdx,0x52134041503a405b
-1352
00000125 4889542418 mov [rsp+0x18],rdx
0000012A B9F5FFFFFF mov ecx,0xfffffff5
0000012F FFD0 call rax
00000131 4989C0 mov r8,rax
00000134 48BA085903141059 mov rdx,0x6b09591014035908
-096B
0000013E 48891424 mov [rsp],rdx
00000142 8B7720 mov esi,[rdi+0x20]
00000145 4801DE add rsi,rbx
00000148 4831C9 xor rcx,rcx
0000014B 8B148E mov edx,[rsi+rcx*4]
0000014E 4801DA add rdx,rbx
00000151 813A57726974 cmp dword [rdx],0x74697257
00000157 7514 jnz 0x16d
00000159 817A0465436F6E cmp dword [rdx+0x4],0x6e6f4365
00000160 750B jnz 0x16d
00000162 817A08736F6C65 cmp dword [rdx+0x8],0x656c6f73
00000169 7502 jnz 0x16d
0000016B EB05 jmp short 0x172
0000016D 48FFC1 inc rcx
00000170 EBD9 jmp short 0x14b
00000172 8B7724 mov esi,[rdi+0x24]
00000175 4801DE add rsi,rbx
00000178 668B0C4E mov cx,[rsi+rcx*2]
0000017C 48BA1F72564E0413 mov rdx,0x681c13044e56721f
-1C68
00000186 4889542408 mov [rsp+0x8],rdx
0000018B 8B771C mov esi,[rdi+0x1c]
0000018E 4801DE add rsi,rbx
00000191 8B048E mov eax,[rsi+rcx*4]
00000194 4801D8 add rax,rbx
00000197 4883EC30 sub rsp,byte +0x30
0000019B 488D542430 lea rdx,[rsp+0x30]
000001A0 4831C9 xor rcx,rcx
000001A3 4883F904 cmp rcx,byte +0x4
000001A7 7412 jz 0x1bb
000001A9 4C8B4C2450 mov r9,[rsp+0x50]
000001AE 4C330CCA xor r9,[rdx+rcx*8]
000001B2 4C890CCA mov [rdx+rcx*8],r9
000001B6 48FFC1 inc rcx
000001B9 EBE8 jmp short 0x1a3
000001BB 4C89C1 mov rcx,r8
000001BE 49C7C020000000 mov r8,0x20
000001C5 4D31C9 xor r9,r9
000001C8 48C7442420000000 mov qword [rsp+0x20],0x0
-00
000001D1 FFD0 call rax
000001D3 4883C430 add rsp,byte +0x30
000001D7 EB00 jmp short 0x1d9
000001D9 4831C0 xor rax,rax
000001DC 4889EC mov rsp,rbp
000001DF 5D pop rbp
000001E0 4159 pop r9
000001E2 4158 pop r8
000001E4 5F pop rdi
000001E5 5E pop rsi
000001E6 5A pop rdx
000001E7 59 pop rcx
000001E8 5B pop rbx
000001E9 C3 ret
000001EA 0000 add [rax],al
000001EC 0000 add [rax],al
000001EE 0000 add [rax],al
本質はこの部分。
00000015 65488B0425600000 mov rax,[gs:0x60]
-00
0000001E 488B4020 mov rax,[rax+0x20]
00000022 488BB080000000 mov rsi,[rax+0x80]
00000029 833E00 cmp dword [rsi],byte +0x0
0000002C 0F84A7010000 jz near 0x1d9
00000032 813E43005400 cmp dword [rsi],0x540043
00000038 7526 jnz 0x60
0000003A 817E0446003400 cmp dword [rsi+0x4],0x340046
00000041 751D jnz 0x60
00000043 817E0842003D00 cmp dword [rsi+0x8],0x3d0042
0000004A 7514 jnz 0x60
0000004C 837E0C31 cmp dword [rsi+0xc],byte +0x31
00000050 750E jnz 0x60
00000052 488B1E mov rbx,[rsi]
00000055 48C1E308 shl rbx,byte 0x8
00000059 48895C2420 mov [rsp+0x20],rbx
0000005E EB06 jmp short 0x66
00000060 4883C602 add rsi,byte +0x2
00000064 EBC3 jmp short 0x29
-
mov rax,[gs:0x60]: PEB (Process Environment Block) -
mov rax,[rax+0x20]: PEB -> ProcessParameters -
mov rsi,[rax+0x80]: ProcessParameters -> Environment
となり、これは環境変数を指している。それ以降はCTF4B=1という文字列があるかを見ており、見つかった場合はflagを出力する処理を行う。
よって、環境変数にCTF4B=1を与えてからこのコードを実行すれば良い。
> $Env:CTF4B=1
> .\ps_z.ps1
ctf4b{g3t_3nv1r0nm3n7_fr0m_p3b}
flagが得られた。
ctf4b{g3t_3nv1r0nm3n7_fr0m_p3b}