Shi0shishi0

汐鹿生

ASIS CTF Quals 2018 Writeup

はじめに

いつもと違うチームでASIS CTF 2018に参加しました。全然解けなくて駄目。

warmup(Reverse, 27pt)

  • Cのソースファイルを与えられる.
#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,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))�<<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�<<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;}
hamasho30@hamasho30-virtual-machine:~$ gcc warmup.c 
warmup.c:7:8: error: unknown type name ‘int64_tstruct 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,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))�<<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�<<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;}
        ^
(省略)
  • 上のエラーメッセージで、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;

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,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))�<<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�<<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;}
  • 今度はコンパイルが通る.(warningは残るが無視する)
  • 生成されたファイルを実行して暫く待つとFlagが表示される.
hamasho@hamasho-virtual-machine:~$ ./a.out 
ASIS{hi_all_w31c0m3_to_ASISCTF} From ASIS With Love <3

Flag : ASIS{hi_all_w31c0m3_to_ASISCTF}

Plastic(Misc, 64pt)

  • 画像ファイルが与えられる.

    • Flagの一部が見えている.
  • 画像ファイルの中にBase64っぽい部分があるのでデコードする.

    • Base64エンコードされたデータっぽいものの中に「&#xA;」という文字列が何度も出てくるが、これは削除する.
<rdf:li xml:lang="x-default">AAAFWHjabVRfbBRFGJ/ZOeifa+m2hVJaoNf2iohQtndX9ipS29IeVuwVe/1zbfc4&#xA;5/bm7pbu7V5255DjaDISozExaggxSIxC+2KRqBhjCPFBQwgmPggtSnySFx98IP57&#xA;ML4590dEw2w2+33fzHzz+37fbyeW0TWbStIdKCDHuvUvngi7jxPL1kwj7DZjx4hK&#xA;7Vk3ttSUxsOTbmpmGgB85cLHYntFZXtHp7trx2M7H9/1RI+/78DgoWeC4zNhJarG&#xA;U7pp0ym3kdX1tapqZ02TayYY6l4gOXuOf8t5p92qjm17pXZDnVjf0LhxExMYYg62&#xA;jq1nFaySVbHqlc3NW1pat27b3sacrIZtYHWsnrWwVraNbWeucAzbRNcMMqWaumlN&#xA;ps04maIa1Uk4YxGcjukkksZJQ0toKqa8pMk4piQq1sWwupC0zKwRP1jYOGebWUsl&#xA;k+QE7QTlsbZ7j7N7rzQVDE0cGlKCoeLCUAarZFzcJXX3+fd5fL19/j6/S+qWJLnH&#xA;I/XxIXsLrkf2eX0Sj/YCEbLaVY/X1ztXKtbAaRIumcSeKadd2if/Y4aDofEiO6Jj&#xA;1fnk/qdmOV02tTQjycQjPFH/0xx+MDSWpZhXFyrOLPcPyHxfyVkbch4cHgk88Dn0&#xA;QcqtWJYSmzWwLawxKq4qcVPNpolBi0jme6QMjeSxRTVVJ4vVStYmvNIFnCTz3Cxg&#xA;tiP5IseLri4eibsSpsVfg7qK0Yd35HHatnPpGF+ZxjRl/3+uEHzU3HyWJvyRvGZk&#xA;OFJDLR2UyOouarpoLkNccc3ivOg5bmDV0jhWl5rCFlYp12t1QWajh8cuPss2XnyO&#xA;bWLN08FQgAO8c+T5CWdocmqa+yHtJOHEJAI6TtrcD/LCOgd2lhouiqyJbZ4eMw2s&#xA;mpzp2blyhqV5uWzxaOQoJ3RYUwtqwlZuKSLz4As4KjY8xHO8RP1STH5kvHNgqHTk&#xA;KnEmkoUfg2ocyOCXfrLwp/oT28pTasf4mcNcrUsLctkqKDK9Vwr0uPgDWG2h05mR&#xA;AGsr9fRAXoklXIOh0dCiku+V0l4l6stkbCWa7R1RomNeGXPx+5RofNyQlehonyFN&#xA;ECVKU96x9nZlkR+ZPR4VGx9I698al7MRuSi6wyRH4oPlq+B27uSkZZqUQVAJ6kEL&#xA;6AR7gAfIYB5gkAIZkAenwevgDfAWOAPOgrfBOXAevAveAx+AS+Ay+Ah8Aj4Fn4HP&#xA;wVVwDXwBboBvwC3wPfgR3Ae/Qwesg82wDXZBD4xCDFWYgjY8BV+Gr8I34Tl4Hr4P&#xA;V+CH8DK8Aq/Dm/AWvAvvwfvwF/gb/EP4WvhWuC2sCd8Jd4UfhHvCz8Kvwl8IoCrk&#xA;RLWoDjWhVtSButBu1IP60SAKoHl0FNnoFHoJvYbOoLPoHXQBLaNL6Aq6iq6hr9B1&#xA;dAPddFQ4ahwdjh0Ov2O/Y6DUQQGWr4s8+M9wDP0NfUGwlA==&#xA;</rdf:li>
  • デコードすると変なバイナリデータが得られた.
    • とりあえずbinwalkに喰わせてみる.
hamasho@hamasho-virtual-machine:~$ binwalk 1.bin

DECIMAL     HEX         DESCRIPTION
-------------------------------------------------------------------------------------------------------
  • 本当に???と思って-aオプションを付ける.
    • zlibデータが埋まっているらしい.
hamasho@hamasho-virtual-machine:~$ binwalk -a 1.bin

DECIMAL     HEX         DESCRIPTION
-------------------------------------------------------------------------------------------------------
4           0x4         zlib compressed data
  • binwalkでzlibデータを--ddオプション等で切り出そうと思ったが抽出してくれなかった. 手動で切り出す.

    • binwalkってzlibは取り出してくれないんでしたっけ?
  • zlibで圧縮されているデータはPythonでデコードする.

    • 適当にググったら過去のCTFのWriteupでワンライナーを書いている方がいたので流用させていただきました.
  • stringsコマンドに掛けると「ASIS」の文字が見えた.

hamasho@hamasho-virtual-machine:~$ python -c 'import zlib; print zlib.decompress(open("1.bin").read())' | strings
bplist00
wxX$versionX$objectsY$archiverT$top
!"#$%&'()*+189=AGHNOWX\_cdhlostU$null
 WNS.keysZNS.objectsV$class
 XbaselineUcolorTmodeUtitleXpreamble]magnificationTdate_
backgroundColorZsourceText#
./0UNSRGB\NSColorSpaceO
*0.9862459898 0.007120999973 0.02743400075
2345Z$classnameX$classesWNSColor
67WNSColorXNSObject
:;<YNS.string
23>?_
NSMutableString
>@7XNSString
CDEFXNSString\NSAttributes
\documentclass[10pt]{article}
\usepackage[usenames]{color} %used for font color
\usepackage{amssymb} %maths
\usepackage{amsmath} %maths
\usepackage[utf8]{inputenc} %useful to type directly diacritic characters
VNSFont
STUVVNSSizeXNSfFlagsVNSName#@(
VMonaco
23YZVNSFont
[7VNSFont
23]^\NSDictionary
23`a_
NSAttributedString
NSAttributedString#@B
fgWNS.time#A
23ijVNSDate
k7VNSDate
m/0F1 1 1
CpEF
={\bf ASIS}\{50m3\_4pps\_u5E\_M37adat4\_dOn7\_I9n0Re\_th3M!!\}
23uv_
NSMutableDictionary
u]7_
NSKeyedArchiver
yzTroot
  • 「Some Apps Use Metadata don't Ignore them」 か?

Flag : ASIS{50m3_4pps_u5E_M37adat4_dOn7_I9n0Re_th3M!!}

baby C(Reverse, 83pt)

  • 激しく難読化されている感じがするELFファイルが与えられる.
  • ハードコードされている文字列 "m0vfu3c4t0r!" を "movfuscator"に置き換えてGoogle検索.

  • 調べると対応する難読化解除ツールっぽいものが見つかった.

  • 難読化を解除したバイナリを読んでいく.

    • x86のELFファイル.
hamasho@hamasho-virtual-machine:‾$ file babyc2
babyc2: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
  • 適当な文字を入力すると「Wrong!」と表示されて落ちる.
hamasho@hamasho-virtual-machine:‾$ ./babyc2
A
Wrong!

Segmentation fault (コアダンプ)
  • IDA Proでバイナリを眺めていく.

    • 静的解析だけで進めるのは辛そうなので, IDA Pro の Remote Linux Debuggerでデバッグする.
  • 最初に read() で標準入力からの入力を受け付ける.

  • ハードコードされている文字列を dword_804D050 にコピーする処理が複数回行われる.

    • "0y1ng:(" がEAXの指すアドレスに保存されている.
.text:08048ECB mov     edx, dword_81F6110
.text:08048ED1 mov     [eax], edx
.text:08048ED3 mov     dword_804D050, '0'

.text:08048F00 mov     dl, byte ptr dword_804D050
.text:08048F06 mov     [eax], dl
.text:08048F08 mov     dword_804D050, 'y'

.text:08048FBC mov     dl, byte ptr dword_804D050
.text:08048FC2 mov     [eax], dl
.text:08048FC4 mov     dword_804D050, '1'

.text:08049078 mov     dl, byte ptr dword_804D050
.text:0804907E mov     [eax], dl
.text:08049080 mov     dword_804D050, 'n

.text:08049134 mov     dl, byte ptr dword_804D050
.text:0804913A mov     [eax], dl
.text:0804913C mov     dword_804D050, 'g'

.text:08049163 mov     dl, byte ptr dword_804D050
.text:08049169 mov     [eax], dl
.text:0804916B mov     dword_804D050, ':'

.text:0804921F mov     dl, byte ptr dword_804D050
.text:08049225 mov     [eax], dl
.text:08049227 mov     dword_804D050, '('

.text:080492DB mov     dl, byte ptr dword_804D050
.text:080492E1 mov     [eax], dl
.text:080492E3 mov     dword_804D05C, 0Ch
  • "m0vfu3c4t0r!"という文字列も使用するっぽい.
.text:0804933D mov     eax, offset aM0vfu3c4t0r        ; "m0vfu3c4t0r!"
.text:08049342 mov     dword_804D05C, eax
.text:08049347 mov     eax, dword_804D05C
  • 上の処理の後で、strncmp() を実行する.
.text:0804956C mov     dword_85F61C4, offset loc_8048280
...
.plt:08048280 jmp     ds:strncmp_ptr
...
  • strncmp()で比較している文字列を確認すると, 入力値の先頭から4文字目の値から順にチェックしているっぽい.
  • 比較対象は上のハードコードされていた文字列.

    • 6D, 30, 76 と続いているので、入力値[3:]からの値が m0vfu3c4t0r! かどうかをチェックしている.
    • 入力を期待される文字列は "???m0vfu3c4t0r!" のような形.
  • dword_804D05C に注目しつつ更に見ていくと, 似たような処理の塊が3つ続いている.

    • このハードコードされた3文字 "Ah_" が "m0vfu3c4t0r!" の前に来るはずの3文字と推測できる.
.text:080498C8 mov     dl, byte ptr dword_804D050
.text:080498CE mov     edx, dword_81F5B70[edx*4]
.text:080498D5 mov     dword_804D05C, edx
.text:080498DB mov     dword_804D058, 'A'
...
.text:08049B1F test    eax, eax
.text:08049B21 nop
.text:08049B22 nop
.text:08049B23 nop
.text:08049B24 nop
.text:08049B25 nop
.text:08049B26 jnz     loc_804B3F6
...
...
.text:08049BF2 mov     dl, byte ptr dword_804D050
.text:08049BF8 mov     edx, dword_81F5B70[edx*4]
.text:08049BFF mov     dword_804D05C, edx
.text:08049C05 mov     dword_804D058, 'h'
...
.text:08049E49 test    eax, eax
.text:08049E4B nop
.text:08049E4C nop
.text:08049E4D nop
.text:08049E4E nop
.text:08049E4F nop
.text:08049E50 jnz     loc_804B3F6
...
...
.text:08049F1C mov     dl, byte ptr dword_804D050
.text:08049F22 mov     edx, dword_81F5B70[edx*4]
.text:08049F29 mov     dword_804D05C, edx
.text:08049F2F mov     dword_804D058, '_'
...
.text:0804A173 test    eax, eax
.text:0804A175 nop
.text:0804A176 nop
.text:0804A177 nop
.text:0804A178 nop
.text:0804A179 nop
.text:0804A17A jnz     loc_804B3F6
  • 更に進めていくと、再び strncmp() で文字列の比較が行われる.

    • 今度は最初の方に確認した "0y1ng:(" がチェックされている.
    • "Ah_m0vfu3c4t0r!0y1ng:(" で通りそうだなと思って入力したら違った.
  • もう少し見ていくと、他にもハードコードされている文字列があった.

    • "y0"の部分を上書きしているか?
.text:0804A7BD mov     dword_804D058, 'y0nn'
  • 入力値は "Ah_m0vfu3c4t0r!nn0y1ng:(" で良さそう!と思って意気揚々と入力したがまたしてもwrong!になった.

    • 細かく確認せずに飛ばしていた, 2回目の strncmp() の比較処理を確認する.
    • 内部では, 入力値の一部である "1ng:(" と "0y1ng:(" が比較されている.(2文字分のズレがある)
      • ハードコードされた "nn0y" の前に2文字追加してあげると比較処理を抜けられそう.
      • 適当にAAを詰めて "Ah_m0vfu3c4t0r!AAnn0y1ng:(" と入力してみたところ、比較処理を抜けた.
  • そのままデバッグしていくと puts() を実行してCorrect :) と出力された.

    • 適当に入れた2文字についてはどうやらチェックしていないようで, 値はなんでも良さそう.
    • 問題文をちゃんと読んでおらず忘れていたが, 「flag is ASIS{sha1(input[:14])}」 と書いてあるので, 必要な文字列は「Ah_m0vfu3c4t0r」まで.
    • だから "!" 直後の2文字は何でも良い形になっているのか?
hamasho@hamasho-virtual-machine:‾$ ./babyc2
Ah_m0vfu3c4t0r!AAnn0y1ng:(


Correct :)

Segmentation fault (コアダンプ)

hamasho@hamasho-virtual-machine:‾$ echo -n "Ah_m0vfu3c4t0r" | openssl sha1
(stdin)= 574a1ebc69c34903a4631820f292d11fcd41b906

Flag : ASIS{574a1ebc69c34903a4631820f292d11fcd41b906}

Trashy Or Classy(Forensics, 118pt)

  • 解けなかった問題.

  • pcapファイルが与えられる.

  • IPアドレス 167 . 99 . 233 . 88 に対して大量の通信が発生している.

    • 通信の殆どがHTTPリクエストで、404 Not Foundが返っている.
    • 適当なパスだったり, 特定のアプリケーションが使用するファイルパスだったりに通信しようとしている.
  • 404 以外が返っているリクエストは無いのかな~と思って探してみると, 401 Unauthorized が返っているのがあった.

    • 401が返ったあとで, Authorizationヘッダにデータを追加して再アクセスを行い, 200 OKが返っている.
    • これはDigest認証っぽい. 仕組みはWikipediaとかをご参照ください.
    • https://ja.wikipedia.org/wiki/Digest認証
  • 5943番のTCPストリーム

GET /private/ HTTP/1.1
Host: 167.99.233.88
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 401 Unauthorized
Date: Fri, 27 Apr 2018 21:32:35 GMT
Server: Apache
WWW-Authenticate: Digest realm="Private Area", nonce="dUASPttqBQA=7f98746b6b66730448ee30eb2cd54d36d5b9ec0c", algorithm=MD5, domain="/", qop="auth"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
Connection: close

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>
  • 5944番のTCPストリーム
GET /private/ HTTP/1.1
Host: 167.99.233.88
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Authorization: Digest username="admin", realm="Private Area", nonce="dUASPttqBQA=7f98746b6b66730448ee30eb2cd54d36d5b9ec0c", uri="/private/", algorithm=MD5, response="3823c96259b479bfa6737761e0f5f1ee", qop=auth, nc=00000001, cnonce="edba216c81ec879e"

HTTP/1.1 200 OK
Date: Fri, 27 Apr 2018 21:32:38 GMT
Server: Apache
Authentication-Info: rspauth="05d0b41966929e0102e595da3d4e8ab4", cnonce="edba216c81ec879e", nc=00000001, qop=auth
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 432
Content-Type: text/html;charset=UTF-8
Connection: keep-alive

............_o. ....).x.[r.t...3.v.EK...TMS...6*.........xS.nZ....r.1..I....b....SX|=.Nb =....1Y&..a......q<#...~....Br.F.^y-...y.6.,...^Rl6..-KWV<.%....uS..6...c..p...MD.-  .j.C....J..p.....*#.....I<.....>.(...,"..hv2...f|.........6.....*SR../..R=./.4L"....+k.(..]...U.....A..T......oa,N/..e2.h".u..:$l..4...d..{h.5.[.....Khov*/<a.=.I.......;.U....5.<..\.{.....?.......]op.....1.>#../.k$.ZH.../.V{...2R/^...../....Hq...17...nt^>1...
  • 更に見ていくと, /private/ の下に flag.castr と flag.caidx が存在することが分かった.
GET /private/flag.castr/ HTTP/1.1
Host: 167.99.233.88
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://167.99.233.88/private/
DNT: 1
Authorization: Digest username="admin", realm="Private Area", nonce="dUASPttqBQA=7f98746b6b66730448ee30eb2cd54d36d5b9ec0c", uri="/private/flag.castr/", algorithm=MD5, response="4eb62a087ed8f9a95c8eb4172a23d085", qop=auth, nc=00000002, cnonce="6a93259e6d1b94e9"
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 403 Forbidden
Date: Fri, 27 Apr 2018 21:32:40 GMT
Server: Apache
Content-Length: 228
Content-Type: text/html; charset=iso-8859-1
Connection: close

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /private/flag.castr/
on this server.<br />
</p>
</body></html>
GET /private/flag.caidx HTTP/1.1
Host: 167.99.233.88
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://167.99.233.88/private/
DNT: 1
Authorization: Digest username="admin", realm="Private Area", nonce="dUASPttqBQA=7f98746b6b66730448ee30eb2cd54d36d5b9ec0c", uri="/private/flag.caidx", algorithm=MD5, response="a4db2608bc1c9cb99cea65438cfb61ac", qop=auth, nc=00000003, cnonce="3a46ba35c226ab51"
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Date: Fri, 27 Apr 2018 21:32:45 GMT
Server: Apache
Authentication-Info: rspauth="9feb03ba70ce0cc785e46b07fbe1c49b", cnonce="3a46ba35c226ab51", nc=00000003, qop=auth
Last-Modified: Sun, 08 Apr 2018 10:29:57 GMT
Accept-Ranges: bytes
Content-Length: 29384
Connection: keep-alive
  • この /private/ にアクセスする必要がありそうな気がする.

    • ただし, flag.castr へのアクセスは adminユーザでも失敗しているので, ログインするだけでは駄目かもしれない.
    • 同じディレクトリに他のファイル(ヒント)があったりするのか?
  • Digest認証は様々なデータをAuthorizationヘッダで送信する.

    • 今回は、パケットからusername、realm、http_method、uri、qop、nc、cnonce、nonce、responceが分かる.
    • 分からないのはpasswordぐらい.
    • 他の要素からpasswordを推測出来ないか考えてみる.
  • Digest認証で送信するデータの形は以下のようになる.

    • ログイン成功時に送信していた response が "3823c96259b479bfa6737761e0f5f1ee" なので, passwordの部分だけを変えてブルートフォースを行い, md5(md5(a1):nonce:nc:cnonce:qop:md5(a2)) が "3823c96259b479bfa6737761e0f5f1ee" になる値を探れば良さそう.
a1 = username:realm:password
a2 = http_method:uri
response = md5(md5(a1):nonce:nc:cnonce:qop:md5(a2))
  • 単純な総当たりは時間がかかりそうだったので、適当なパスワードリストを拾ってきて, それを使ってブルートフォースした.

    • password = "rainbow" の時に responce の値が一致した.
  • admin:rainbowで http://167.99.233.88/private/ にアクセスしてみるとログインできた.

  • この拡張子でググると、casyncというツールがヒットした.

    • https://github.com/systemd/casync
    • また, .caidxファイルはディレクトリツリーの情報を持つインデックスファイルの一種であることがわかった.
    • このツールを使うと.caidxファイルの調査が行えそうだったが, ツールのインストールが上手くいかず止まってしまった.
    • 他の方のwriteupを見る感じだと、casyncで調査して行く感じであっていたっぽいので悔しい

おわりに

ツールのを動かすための環境構築でハマって時間が溶けるのが辛い。手を付けられていないpwnとreverseの問題を復習したい。