Problem
Crack me.
Solution
A PowerShell script is given:
1
2
3
4
5
6
7
8
| $ECCON="";
$ECCON="";
$ECCON+=[char](3783/291);
$ECCON+=[char](6690/669);
$ECCON+=[char](776-740);
# ...
$ECCON+=[char](520-510);
Write-Progress -Completed -Activity "Extracting Script";.([ScriptBlock]::Create($ECCON))
|
Notice the last command .([ScriptBlock]::Create($ECCON))
. It creates and
sources a PowerShell script from $ECCON
on the fly. So we changed it to
echo $ECCON > stage2.ps1
to extract the script.
stage2.ps1
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
| $ErrorActionPreference = "ContinueSilently"
# A very very long line to draw the SECCON logo
<# Host Check #>
Write-Host -b 00 -f 15 Checking Host... Please wait... -n
Try{
If ((Get-EventLog -LogName Security | Where EventID -Eq 4624).Length -Lt 1000) {
Write-Host "This host is too fresh!"
Exit
}
}Catch{
Write-Host "Failed: No admin rights!"
Exit
}
Write-Host "Check passed"
$keytone=@{'a'=261.63}
$pk='a'
ForEach($k in ('w','s','e','d','f','t','g','y','h','u','j','k')){
$keytone+=@{$k=$keytone[$pk]*[math]::pow(2,1/12)};$pk=$k
}
Write-Host -b 00 -f 15 "Play the secret melody."
Write-Host -b 15 -f 00 -n ' '
Write-Host -b 00 -f 15 -n ' '
Write-Host -b 15 -f 00 -n ' '
# ...
Write-Host -b 15 -f 00 ' '
Write-Host
$stage1=@();$f="";
While($stage1.length -lt 14){
$key=(Get-Host).ui.RawUI.ReadKey("NoEcho,IncludeKeyDown")
$k=[String]$key.Character
$f+=$k;
If($keytone.Contains($k)){
$stage1+=[math]::floor($keytone[$k])
[console]::beep($keytone[$k],500)
}
}
$secret=@(440,440,493,440,440,493,440,493,523,493,440,493,440,349)
If($secret.length -eq $stage1.length){
For ($i=1; $i -le $secret.length; $i++) {
If($secret[$i] -ne $stage1[$i]){
Exit
}
}
x "Correct. Move to the next stage."
}
$text=@"
YkwRUxVXQ05DQ1NOE1sVVU4TUxdTThBBFVdDTUwTURVTThMqFldDQUwdUxVRTBNEFVdAQUwRUxtT
TBEzFVdDQU8RUxdTbEwTNxVVQUNOEFEVUUwdQBVXQ0NOE1EWUUwRQRtVQ0FME1EVUU8RThdVTUNM
EVMVUUwRFxdVQUNCE1MXU2JOE0gWV0oxSk1KTEIoExdBSDBOE0MVO0NKTkAoERVDSTFKThNNFUwR
...
ShtME0EVTBFGF0BOE0gVQhNDF0wTVxVBTxFKF0wdQxVOEygXTBE2FxROE10VShZOTBFTF2E=
"@
$plain=@()
$byteString = [System.Convert]::FromBase64String($text)
$xordData = $(for ($i = 0; $i -lt $byteString.length; ) {
for ($j = 0; $j -lt $f.length; $j++) {
$plain+=$byteString[$i] -bxor $f[$j]
$i++
if ($i -ge $byteString.Length) {
$j = $f.length
}
}
})
iex([System.Text.Encoding]::ASCII.GetString($plain))
|
It checks if the host has admin rights, but they aren’t necessary. We can simply
remove that part to pass the check.
Wow, there’s a piano! @bayaheuro
Let me take a guess… $secret
has the score. 440 Hz is A4, blah blah. Then we
get “hhjhhjhjkjhjhf”.
I remember that I transferred at Musashi-Koganei (武蔵小金井駅) when I visited
Japan last year
Now, notice the last command again. iex
executes the given expression. We
changed that line to
echo [System.Text.Encoding]::ASCII.GetString($plain) > stage3.ps1
.
stage3.ps1
:
1
2
3
4
5
| ${;}=+$();${=}=${;};${+}=++${;};${@}=++${;};${.}=++${;};${[}=++${;};
${]}=++${;};${(}=++${;};${)}=++${;};${&}=++${;};${|}=++${;};
${"}="["+"$(@{})"[${)}]+"$(@{})"["${+}${|}"]+"$(@{})"["${@}${=}"]+"$?"[${+}]+"]";
${;}="".("$(@{})"["${+}${[}"]+"$(@{})"["${+}${(}"]+"$(@{})"[${=}]+"$(@{})"[${[}]+"$?"[${+}]+"$(@{})"[${.}]);
${;}="$(@{})"["${+}${[}"]+"$(@{})"[${[}]+"${;}"["${@}${)}"];"${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${(}${+}+${"}${&}${@}+${"}${+}${=}${+}+${"}${|}${)}+${"}${+}${=}${=}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${[}${]}+${"}${&}${=}+${"}${+}${+}${[}+${"}${+}${+}${+}+${"}${+}${=}${|}+${"}${+}${+}${@}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${(}${|}+${"}${+}${+}${=}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${+}${+}${[}+${"}${.}${@}+${"}${+}${+}${(}+${"}${+}${=}${[}+${"}${+}${=}${+}+${"}${.}${@}+${"}${+}${+}${@}+${"}${|}${)}+${"}${+}${+}${]}+${"}${+}${+}${]}+${"}${+}${+}${|}+${"}${+}${+}${+}+${"}${+}${+}${[}+${"}${+}${=}${=}+${"}${.}${|}+${"}${+}${.}+${"}${+}${=}+${"}${)}${.}+${"}${+}${=}${@}+${"}${[}${=}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${.}${@}+${"}${[}${]}+${"}${+}${=}${+}+${"}${+}${+}${.}+${"}${.}${@}+${"}${.}${|}+${"}${&}${=}+${"}${[}${&}+${"}${+}${+}${|}+${"}${(}${|}+${"}${+}${+}${[}+${"}${.}${(}+${"}${)}${@}+${"}${]}${+}+${"}${[}${|}+${"}${[}${|}+${"}${.}${|}+${"}${[}${+}+${"}${+}${@}${.}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${)}${+}+${"}${+}${+}${+}+${"}${+}${+}${+}+${"}${+}${=}${=}+${"}${.}${@}+${"}${)}${[}+${"}${+}${+}${+}+${"}${|}${&}+${"}${.}${.}+${"}${.}${|}+${"}${]}${|}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${[}+${"}${&}${.}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${.}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${]}+${"}${.}${[}+${"}${+}${.}+${"}${+}${=}+${"}${+}${@}${]}|${;}"|&${;}
|
Looks so ugly, but we can get a hint from sorting the original script:
1
2
| If($host."na`m`e" -ne "C`on`s`o`l`e`H`o`st"){"D`eb`u`g`g`in`g is `pr`o`h`ib`it`e`d";Exit}
If(Test-Path variable:global:psISE){"D`eb`u`g`g`in`g is `pr`o`h`ib`it`e`d";Exit}
|
Because this check isn’t present in stage3.ps1
, we can use PowerShell ISE to
debug the script. Open ISE, execute stage3.ps1
, type anything, press Ctrl-B
and click the break button!
Now we have the flag.