Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
/**
* SECCON 2016 Online CTF
*
* Retrospective Reverse it.
* http://files.quals.seccon.jp/file
*
* flag is SECCON{LEGACY_VB_P_CODE}
*/
define('USER_INPUT', 'ユーザの入力値');
// 文字列の左端から指定された文字数分の文字列を返す
function Left(string $str, int $length) : string
{
return substr($str, 0, $length);
}
// 文字列の右端から指定された文字数分の文字列を返す
function Right(string $str, int $length) : string
{
return substr($str, (-1) * $length);
}
// 部分文字列ごとに区切られた文字列からゼロ ベースの 1 次元配列を作成し返す
function Split(string $str, string $d, int $length, int $c) : array
{
return explode($d, $str, $length);
}
// 文字列から指定された文字数分の文字列を返す
function Mid(string $str, int $start, int $length) : string
{
return substr($str, $start, $length);
}
// 文字に対応する文字コードを表す整数型の値を返す
function Asc(string $str) : int
{
return ord($str[0]);
}
// SHA1だと思う
// https://ja.wikipedia.org/wiki/SHA-1
function calchash(string $str) : string
{
return strtoupper(sha1($str));
}
// 入力値は8文字以上で, 'SECCON{' と '}' に挟まれている
if(strlen(USER_INPUT) < 8 || Left(USER_INPUT, 7) != 'SECCON{' || Right(USER_INPUT, 1) != '}')
{
exit();
}
// 入力値を '_' でセパレートする
$data = Split(substr(USER_INPUT, 7, -1), '_', -1, 0);
// 2つ以上の配列であるか
if(count($data) <= 2)
{
exit();
}
// 1つ目の文字列が 'LEGACY' であるか
if($data[0] != 'LEGACY')
{
exit();
}
/**
* (data[1][0] * 1) + (data[1][1] * 4) = 350
* => data[1][0] = 86 => 'V'
* data[1][1] = 66 => 'B'
*/
$value = 0;
for($i=0; $i<strlen($data[1]); $i++)
{
$value += Asc($data[1][$i]) * (4 ** $i);
}
if((strlen($data[1]) != 2) || ($value != 350))
{
exit();
}
/**
* 0x15E50 - 350 * 256 = 80 => 'P'
*/
$value = 350 * 256;
for($i=0; $i<strlen($data[2]); $i++)
{
$value += Asc($data[2][$i]) * (4 ** $i);
}
if($value != 0x15E50)
{
exit();
}
/**
* SECCON{LEGACY_VB_P_????}
* 残りはBrute Forceですぐに解読可能
*/
$value = 0;
for($i=0; $i<strlen(USER_INPUT); $i++)
{
$value += Asc(USER_INPUT[$i]) * (2 ** $i);
}
$hash = calchash(USER_INPUT);
if(($value == 1645164145) && ($hash == '8B292F1A9C4631B3E13CD49C64EF74540352D0C0'))
{
$h = 'Thank you f|| your purchase :-) ' . PHP_EOL . 'And, ' . USER_INPUT . ' is Flag.';
print($h);
}
@msakai

This comment has been minimized.

Copy link

commented Dec 19, 2016

この問題を自分も取り組んでいた( http://qiita.com/masahiro_sakai/items/7258ef1f9e98373de36f )のですが、ちょっと良くわからなかった箇所があったので質問させてください。

90行目からの箇所ですが、P-Codeを読むと、参照されているのは $data[2] ではなく $data[1] で、かつ「0x15E50 - 350 * 256 = 80 => 'P'」ではなく「0x15E56 - 350 * 256 = 86 => 'V'」だと思います。 なので、ここからは'P'を確定することは出来ないのではないでしょうか?

また、100行目からの箇所で「SECCON{LEGACY_VB_P_????} 」で「残りはBrute Forceですぐに解読可能」とありますが、残りが4文字であることを推測できる情報ってどこかにありましたか?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.