CpawCTF解法メモ。
level3
Q23.[Reversing]またやらかした!
200pt
問題
またprintf()をし忘れたプログラムが見つかった。
とある暗号を解くプログラムらしい…
reversing200
解法
とりあえずfile
コマンドを叩く
rev200: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24,
BuildID[sha1]=e87140105d6b5c8ea9b0193380ab3b79bfdcd85b, not stripped
ということなので、Level1と同様に32bitのubuntuの仮想環境を立ち上げてそこで解析。
chmod 777 ./rev200
./rev200
と実行してみるが、反応はない。
print文が抜けているということは、flagは実行中メモリに確保されているはずなので、デバッグしてみる。
gdb ./rev200
gdb$ disas main
とすると
Dump of assembler code for function main:
0x080483ed <+0>: push ebp
0x080483ee <+1>: mov ebp,esp
0x080483f0 <+3>: push edi
0x080483f1 <+4>: push ebx
0x080483f2 <+5>: add esp,0xffffff80
0x080483f5 <+8>: mov DWORD PTR [ebp-0x78],0x7a
0x080483fc <+15>: mov DWORD PTR [ebp-0x74],0x69
0x08048403 <+22>: mov DWORD PTR [ebp-0x70],0x78
0x0804840a <+29>: mov DWORD PTR [ebp-0x6c],0x6e
0x08048411 <+36>: mov DWORD PTR [ebp-0x68],0x62
0x08048418 <+43>: mov DWORD PTR [ebp-0x64],0x6f
0x0804841f <+50>: mov DWORD PTR [ebp-0x60],0x7c
0x08048426 <+57>: mov DWORD PTR [ebp-0x5c],0x6b
0x0804842d <+64>: mov DWORD PTR [ebp-0x58],0x77
0x08048434 <+71>: mov DWORD PTR [ebp-0x54],0x78
0x0804843b <+78>: mov DWORD PTR [ebp-0x50],0x74
0x08048442 <+85>: mov DWORD PTR [ebp-0x4c],0x38
0x08048449 <+92>: mov DWORD PTR [ebp-0x48],0x38
0x08048450 <+99>: mov DWORD PTR [ebp-0x44],0x64
0x08048457 <+106>: mov DWORD PTR [ebp-0x7c],0x19
0x0804845e <+113>: lea ebx,[ebp-0x40]
0x08048461 <+116>: mov eax,0x0
0x08048466 <+121>: mov edx,0xe
0x0804846b <+126>: mov edi,ebx
0x0804846d <+128>: mov ecx,edx
0x0804846f <+130>: rep stos DWORD PTR es:[edi],eax
0x08048471 <+132>: mov DWORD PTR [ebp-0x80],0x0
0x08048478 <+139>: jmp 0x8048491 <main+164>
0x0804847a <+141>: mov eax,DWORD PTR [ebp-0x80]
0x0804847d <+144>: mov eax,DWORD PTR [ebp+eax*4-0x78]
0x08048481 <+148>: xor eax,DWORD PTR [ebp-0x7c]
0x08048484 <+151>: mov edx,eax
0x08048486 <+153>: mov eax,DWORD PTR [ebp-0x80]
0x08048489 <+156>: mov DWORD PTR [ebp+eax*4-0x40],edx
0x0804848d <+160>: add DWORD PTR [ebp-0x80],0x1
0x08048491 <+164>: cmp DWORD PTR [ebp-0x80],0xd
0x08048495 <+168>: jle 0x804847a <main+141>
0x08048497 <+170>: mov eax,0x0
0x0804849c <+175>: sub esp,0xffffff80
0x0804849f <+178>: pop ebx
0x080484a0 <+179>: pop edi
0x080484a1 <+180>: pop ebp
0x080484a2 <+181>: ret
End of assembler dump.
とディスアセンブリされたコードが出てくる。
<+8> ~ <+106>あたりでmov
命令でメモリ[ebp-0x78]
~[ebp-0x44]
に0x7aやら0x69やらを書き込んでいるようなので、書き込んだ後のメモリの状態をみてみる。
b *[命令のアドレス]
でブレークポイントを作ってc
を打ち込むことでその命令までプログラムを実行できるので、書き込んだ後の命令<+113>のアドレスを指定。
gdb$ b *0x0804845e
gdb$ c
i r
コマンドでレジスタの値をみるとebpレジスタの値は0xffffcfb8
だとわかる。
eax 0xf7fb6dbc 0xf7fb6dbc
ecx 0x6448b547 0x6448b547
edx 0xffffcfe4 0xffffcfe4
ebx 0x0 0x0
esp 0xffffcf30 0xffffcf30
ebp 0xffffcfb8 0xffffcfb8
esi 0xf7fb5000 0xf7fb5000
edi 0xf7fb5000 0xf7fb5000
eip 0x804845e 0x804845e <main+113>
ここでxコマンド(x/[表示する数][メモリサイズ(b,h,w,g)][表示フォーマット(s,i,x)] [先頭メモリアドレス]
)を使う。
メモリサイズはb(バイト)、h(半ワード、2バイト), w(ワード、4バイト),g(Giantワード、8バイト))の指定が可能。
表示フォーマットはs(文字列)、i(命令)、x(16進数)の指定が可能。
gdb$ x/32hs 0xffffcfb8-0x80
すると、怪しげな文字列が格納されているが、flagではなさそうである。
暗号を解読するプログラムらしいのでこの後の命令で何らかの処理を加えているのだろう。
<+139>~<+168>の命令を見てみると
<+139>で<+164>へジャンプ
<+164>で[ebp-0x80]の値と0xd(=14)を比較
<+168>で、比較の結果が等しくなければ<+141>にジャンプ
をしている。
<+160>では[ebp-0x80]に0x1(=1)を足しているので、これらの命令は<+141>~<+156>の命令を14回ループさせていることがわかる。
<+141>~<+156>の命令をさらによく見てみると
格納していた各文字列と[ebp-0x7c]のxorをとって[ebp-0x40]以降のアドレスに書き込んでいるようである。
先ほど同様このループの後の命令<+170>まで行ってメモリを見てみるとebp-0x40以降に、Flagが書き込まれているのが確認できるので、Flagゲット。
gdb$ b *0x08048497
gdb$ c
gdb$ x/32hs $ebp-0x80
また、暗号の復号を以下のように実装してもよい。
crypt = []
crypt.append(0x7a)
crypt.append(0x69)
crypt.append(0x78)
crypt.append(0x6e)
crypt.append(0x62)
crypt.append(0x6f)
crypt.append(0x7c)
crypt.append(0x6b)
crypt.append(0x77)
crypt.append(0x78)
crypt.append(0x74)
crypt.append(0x38)
crypt.append(0x38)
crypt.append(0x64)
key = 0x19
for c in crypt:
print(chr(key^c))
Q24.[Web]Baby's SQLi - Stage 2-
200pt
問題
うーん,ぱろっく先生深くまで逃げ込んでたか.
そこまで難しくは無いと思うんだけども…….
えっ?何の話か分からない?
さてはStage 1をクリアしてないな.
待っているから,先にStage 1をクリアしてからもう一度来てね.
Caution: sandbox.spica.bzの80,443番ポート以外への攻撃は絶対にしないようにお願いします.
解法
Stage 1(Q22)の問題でnext stage のURLが手に入るのでそこからアクセス。
認証を突破してくれと言われる。
認証の問題では有名な脆弱性としてここのようなものがある
ユーザ名は問題で指定してくれてるので、パスワードのところに
' or 1=1 --
と入力してFlagゲット。
Q26.[PPC]Remainder theorem
200pt
問題
x ≡ 32134 (mod 1584891)
x ≡ 193127 (mod 3438478)
x = ?
フラグはcpaw{xの値}です!
解法
modというのはその数字で割った余りを示すので、
一つ目の条件から、nを自然数としてxは1584891 * n + 32134 であることがわかる。
nを1, 2, ... と大きくしながら、二つ目の条件を満たすx を見つければ良い。
すなわち (1584891 * n + 32134) % 3438478 == 193127 となるnを見つける。
以下、pythonでのコード例
a = 32134
b = 1584891
c = 193127
d = 3438478
for i in range(d):
x = b * i + a
if x % d == c:
print(x)
Q29.[Crypto] Common World
200pt
問題
Cpaw君は,以下の公開鍵を用いて暗号化された暗号文Cを受け取りました.しかしCpaw君は秘密鍵を忘れてしまいました.Cpaw君のために暗号文を解読してあげましょう.
(e, N) = (11, 236934049743116267137999082243372631809789567482083918717832642810097363305512293474568071369055296264199854438630820352634325357252399203160052660683745421710174826323192475870497319105418435646820494864987787286941817224659073497212768480618387152477878449603008187097148599534206055318807657902493850180695091646575878916531742076951110529004783428260456713315007812112632429296257313525506207087475539303737022587194108436132757979273391594299137176227924904126161234005321583720836733205639052615538054399452669637400105028428545751844036229657412844469034970807562336527158965779903175305550570647732255961850364080642984562893392375273054434538280546913977098212083374336482279710348958536764229803743404325258229707314844255917497531735251105389366176228741806064378293682890877558325834873371615135474627913981994123692172918524625407966731238257519603614744577)
暗号文: 80265690974140286785447882525076768851800986505783169077080797677035805215248640465159446426193422263912423067392651719120282968933314718780685629466284745121303594495759721471318134122366715904
これは…?
フラグは以下のシンタックスです.
cpaw{復号した値}
※復号した値はそのままで良いですが,実は意味があります,余力がある人は考えてみてください.
解法
ヒントとして、同じNを用いたe=13の場合の暗号文が与えられている。
こういう場合はcommon_modulus_attackというのがあるらしい。
このページがRSAへの攻撃をまとめていて、分かりやすい。
python(2系)で実装したコードもその辺に転がっているので、利用すれば簡単に解ける。
flagは、実は意味があるとのこと。
5以下の2つの数値がペアになっているように見えるので、
ポリュビオスの暗号表を使って復号すると、RSAISEASY
となる。