CpawCTF write up(Level3)

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
```

ということなので、Level１と同様に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(半ワード、２バイト), w(ワード、4バイト）,g(Giantワード、８バイト))の指定が可能。
表示フォーマットはs(文字列)、i（命令）、x（１６進数）の指定が可能。

```
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
```

また、暗号の復号を以下のように実装してもよい。

```q23.py
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が手に入るのでそこからアクセス。
認証を突破してくれと言われる。
認証の問題では有名な脆弱性として[ここ](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/502.html)のようなものがある  
ユーザ名は問題で指定してくれてるので、パスワードのところに
```
' 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でのコード例

```q26.py
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](http://elliptic-shiho.hatenablog.com/entry/2015/12/14/043745)というのがあるらしい。  
この[ページ](http://elliptic-shiho.hatenablog.com/entry/2015/11/12/182219)がRSAへの攻撃をまとめていて、分かりやすい。
python(2系)で実装した[コード](https://gist.github.com/horoama/688c94fe629a321284c2b4706c75be98)もその辺に転がっているので、利用すれば簡単に解ける。

flagは、実は意味があるとのこと。
5以下の2つの数値がペアになっているように見えるので、
[ポリュビオスの暗号表](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A5%E3%83%93%E3%82%AA%E3%82%B9%E3%81%AE%E6%9A%97%E5%8F%B7%E8%A1%A8)を使って復号すると、`RSAISEASY`となる。