a

よろしくのキワミ

Reversing-Challenges-List/Baby Writeup #1

Reversing-Challenges-List/Baby

Reversing-Challenges-Listの内容を解いていくことにする。
まずはBabyから

ASIS_CTF_2018_Quals_Warm_up

ファイル一覧を見る

$ ls
README.md  Warm_up.7z  writeup.md

7zで圧縮されたファイルがあるので解凍するとwarmupというファイルが見える。
中身を確認

$ cat warmup
#define M 37
#define q (2+M/M)
#define v (q/q)
#define ef ((v+q)/2)
#define f (q-v-ef)
#define k (8-ef)
struct b{int64_t y[13];}S;int m=1811939329,N=1,t[1<<26]={2},a,*p,i,e=73421233,s,c,U=1;g(d,h){for(i=s;i<1<<25;i*=2)d=d*1LL*d%m;for(p=t;p<t+N;p+=s)for(i=s,c=1;i;i--)a=p[s]*(h?c:1LL)%m,p[s]=(m*1U+*p-a)*(h?1LL:c)%m,*p=(a*1U+*p)%m,p++,c=c*1LL*d%m;}l(){while(e/=2){N*=2;U=U*1LL*(m+1)/2%m;for(s=N;s/=2;)g(136,0);for(p=t;p<t+N;p++)*p=*p*1LL**p%m*U%m;for(s=1;s<N;s*=2)g(839354248,1);for(a=0,p=t;p<t+N;)a+=*p<<(e&1),*p++=a%10,a/=10;}}z(n){int y=3,j,c;for(j=2;j<=n;){l();for(c=2;c<=y-1;c++){l();if(y%c==0)break;}if(c==y){l();j++;}y++;}l();return y-1;}main(a, pq) char* pq;{int b=sizeof(S),y=b,j=M;l();int x[M]={b-M-sizeof((short int) a),(b>>v)+(k<<v)+ (v<<(q|ef)) + z(v+(ef<<v)),(z(k*ef)<<v)-pow(ef,f), z(( (j-ef*k)|(ef<<k>>v)/k-ef<<v)-ef),(((y+M)&b)<<(k/q+ef))-z(ef+v),((ef<<k)-v)&y,y*v+v,(ef<<(q*ef-v-(k>>ef)))*q-v,(f<<q)|(ef<<(q*f+k))-j+k,(z(z(z(z(z(v)))))*q)&(((j/q)-(ef<<v))<<q)|(j+(q|(ef<<v))),y|(q+v),(ef<<ef)-v+ef*(((j>>ef)|j)-v+ef-q+v),(z(j&(b<<ef))&(z(v<<v)<<k))-(q<<v)-q,(k<<q)+q,(z(y)>>(ef<<v))+(z(k+v))-q,(z(z(k&ef|j))&b|ef|v<<f<<q<<v&ef>>k|q<<ef<<v|k|q)+z(v<<v)+v,(ef>>v)*q*z(k-v)+z(ef<<ef&q|k)+ef,z(k<<k)&v&k|y+k-v,z(f>>ef|k>>ef|v|k)*(ef>>v)*q,(ef<<k-ef<<v>>q<<ef*ef)-j+(ef<<v),z(ef*k)*z(v<<v)+k-v,z((z(k)<<z(v)))&y|k|v,z(ef<<ef<<v<<v)/ef+z(v<<ef|k|(b>>q)&y-f)-(ef<<q)+(k-v)-ef,k<<(ef+q)/z(ef)*z(q)&z(k<<k)|v,((z(y|j>>k*ef))%ef<<z(v<<v<<v)>>q<<q|j)/ef+v,(j-ef<<ef<<v*z(v>>v<<v)>>ef)/ef%z(k<<j)+q,z(k-v)+k|z(ef<<k>>v<<f)-z(q<<q)*ef>>v,(z(ef|y&j|k)%q|j+ef<<z(k|ef)%k<<q|ef|k<<ef<<q/ef|y/ef+j>>q)&k<<j|ef+v,84,z(v*ef<<ef<<q)*q%ef<<k|k|q-v,((z(20)*v)|(f>>q)|(k<<k))/ef-(ef<<(v*q+ef))-(k<<q)+z(k)-q};while(j--){putchar(x[M-v-j]);}printf(" From ASIS With Love <3\n");return 0;}

難読化されているがCのsource codeっぽいので拡張子.cをつけ、コンパイルするとたくさんのwarningが出る。

warningは存在してもコンパイルできるはずなのでどこかでerrorが出てるはず。
errorを探す、すると

 error: unknown type name ‘int64_t’

が表示されていた。

int64_tが定義されていないとのことなので定義してやる

#define M 37
#define    q (2+M/M)
#define    v (q/q)
#define    ef ((v+q)/2)
#define    f (q-v-ef)
#define k (8-ef)

typedef long int int64_t; // ここ

...

実行すると、かなり待たされる。
ちらっと見た感じだとeという変数に少し長めの数値を入れていたので暗号に関する処理をしていたのかな...?

変数名は適当につけてる可能性が高いのであまり気にしないことにした

$ ./warmup
ASIS{hi_all_w31c0m3_to_ASISCTF}       From ASIS With Love <3

Nuit_du_Hack_CTF_Quals_2016_Matriochka-Step_1

渡されたファイルを実行してみる。

$ ./stage1.bin
Usage: ./stage1.bin <pass>

引数を渡して再び実行すると...

$ ./stage1.bin test
Try again...

と出てくる。

おそらく引数にフラグを渡してやればよいのだと思う。
まずはmain関数の中を見る

gdb-peda$ disass main
Dump of assembler code for function main:
   0x000000000040064d <+0>:     push   rbp
   0x000000000040064e <+1>:     mov    rbp,rsp
   0x0000000000400651 <+4>:     sub    rsp,0x20
   0x0000000000400655 <+8>:     mov    DWORD PTR [rbp-0x14],edi
   0x0000000000400658 <+11>:    mov    QWORD PTR [rbp-0x20],rsi
   0x000000000040065c <+15>:    cmp    DWORD PTR [rbp-0x14],0x2
   0x0000000000400660 <+19>:    je     0x400687 <main+58>

コマンドライン引数の数が0x2と同値が比べており、そうでなければ使い方を表示して終了する。
2というのは./stage.bin<pass>のことだ。

次の処理を見ていく

   0x0000000000400687 <+58>:    mov    rax,QWORD PTR [rbp-0x20]
   0x000000000040068b <+62>:    add    rax,0x8
   0x000000000040068f <+66>:    mov    rax,QWORD PTR [rax]
   0x0000000000400692 <+69>:    mov    esi,0x40e079
   0x0000000000400697 <+74>:    mov    rdi,rax
   0x000000000040069a <+77>:    call   0x400520 <strcmp@plt>
   0x000000000040069f <+82>:    test   eax,eax
   0x00000000004006a1 <+84>:    jne    0x400773 <main+294>

strcmp関数を呼び出ししているところがある。
ここで文字列を比較してflagの判断をしているのではと考えたので、breakpointを設定する。

gdb-peda$ b *0x40069a

もう一度プログラムを走らせてレジスタの値を見てみると

RSI: 0x40e079 ("Much_secure__So_safe__Wow")

が見える。
この文字をコマンドライン引数に渡して実行するとgoodgoodと共にとてつもなく長い文字列が表示されるが、末尾が==なのでBase64でdecodeできるのではないかと考え試してやる

$ cat strings | base64 -d > flag
$ file flag
flag: POSIX tar archive (GNU)

アーカイブなので解凍してやる

$ tar -vxf flag
stage2.bin

問題がまた出てきた

Nuit_du_Hack_CTF_Quals_2016_Matriochka-Step_2

stage2.binという実行ファイルが見つかる。
実行してみる

$ file stage2.bin
stage2.bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=7b2fd52d0de50c9e575793a0fd17fdd2574c5c53, stripped
$ ./stage2.bin
Usage: ./stage2.bin <pass>

step1と同様コマンドライン引数をflagにして実行するプログラムっぽい

gdbで処理を追っていくと以下のような処理に出会う

gdb-peda$ x/5
   0x400742:    call   0x400510 <strlen@plt>
   0x400747:    lea    rdx,[rax+0x1]
   0x40074b:    mov    rax,rdx
   0x40074e:    shl    rax,0x2
   0x400752:    add    rax,rdx
gdb-peda$
   0x400755:    shl    rax,0x2
   0x400759:    add    rax,rdx
   0x40075c:    add    rax,rax
   0x40075f:    cmp    rax,0x1f8
   0x400765:    jne    0x40099a

これはコマンドライン引数の長さを調べ、flagの長さと同じかどうかの確認をしている処理だ

しかし、受け取った長さをただ使用せずに何かしらの処理をして比較している
最終的に比較する値は0x1f8なので10進数に直すと504になる

処理を見ていくと

0x400747:    lea    rdx,[rax+0x1] ; 文字列長+1をrdxに移動
0x40074b:    mov    rax,rdx ; raxにrdx(文字列長)を移動
0x40074e:    shl    rax,0x2 ; 左に2シフト(4倍)
0x400752:    add    rax,rdx ; 4倍された文字列長に元の文字列長を足す(5倍)
0x400755:    shl    rax,0x2 ; 左に2シフト(20倍)
0x400759:    add    rax,rdx ; 20倍された文字列長に元の文字列長を足す(21倍)
0x40075c:    add    rax,rax ; 20倍された文字列長に20倍された文字列長を足す(42倍)
0x40075f:    cmp    rax,0x1f8 ; `0x1f8`と比較
0x400765:    jne    0x40099a

というわけで42倍された文字列長と0x1f8を比較していることがわかる。
つまりflagとなる文字列は

0x1f8 / 42 - 1
11

となる

set AAAAABBBBBC

を引数としてセットしておき再実行。
ここからは文字列を1文字ずつ比較していくことになる

0x400776:    add    rax,0x8
0x40077a:    mov    rax,QWORD PTR [rax]
0x40077d:    movzx  eax,BYTE PTR [rax]
0x400780:    cmp    al,0x50
0x400782:    je     0x40078b

0文字目と0x50を比較しているので1文字目はP

0x400796:    add    rax,0x3
0x40079a:    movzx  eax,BYTE PTR [rax]
0x40079d:    movsx  eax,al
0x4007a0:    add    eax,eax
0x4007a2:    cmp    eax,0xc8

3文字目は0xc8 / 2をしてdだとわかる

0x4007be:    movsx  eax,al ; eaxに0文字目の値を代入
0x4007c1:    lea    edx,[rax+0x10] ; edxにrax(0x50)と0x10を足し算した値(0x60)を代入
0x4007c4:    mov    rax,QWORD PTR [rbp-0x30]
0x4007c8:    add    rax,0x8
0x4007cc:    mov    rax,QWORD PTR [rax]
0x4007cf:    add    rax,0x6
0x4007d3:    movzx  eax,BYTE PTR [rax]
0x4007d6:    movsx  eax,al
0x4007d9:    sub    eax,0x10 ; 6文字目から0x10を引いて
0x4007dc:    cmp    edx,eax

6文字目は0文字目の0x500x10を足した値と6文字目から0x10を引いた値を比較しているので0x70 = 'p'

0x4007ef:    mov    rax,QWORD PTR [rax]
0x4007f2:    add    rax,0x5
0x4007f6:    movzx  eax,BYTE PTR [rax]
0x4007f9:    movsx  rbx,al
0x4007fd:    mov    rax,QWORD PTR [rbp-0x30]
0x400801:    add    rax,0x8
0x400805:    mov    rax,QWORD PTR [rax]
0x400808:    mov    rdi,rax

というように解いていくとflagはPandi_pandaだとわかる。

flagを渡し実行するとstep1と同じようにBase64エンコードされた文字列が表示された

プライバシーポリシー お問い合わせ