csapp:bomb-lab 解题笔记

这是一个很是有趣的lab。

  你能够用gdb,和反编译破解做者设置的密码。固然,做者提供了不带实现的c源码和(估计使用0g优化级别)。下降难度。node

phase1


code:数组

0000000000400ee0 <phase_1>:
  400ee0:    48 83 ec 08              sub    $0x8,%rsp
  400ee4:    be 00 24 40 00           mov    $0x402400,%esi # 关键代码
  400ee9:    e8 4a 04 00 00           callq  401338 <strings_not_equal>
  400eee:    85 c0                    test   %eax,%eax
  400ef0:    74 05                    je     400ef7 <phase_1+0x17>
  400ef2:    e8 43 05 00 00           callq  40143a <explode_bomb>
  400ef7:    48 83 c4 08              add    $0x8,%rsp
  400efb:    c3                       retq

作了挺多无用功,好比靠函数名就能才猜到的功能不必去反推c源码。也了解了elf文件,知道如何定义程序入口。最后使用gdb查看地址找到密码:数据结构

0x402400: "Border relations with Canada have never been better."函数

phase2


000000000040145c <read_six_numbers>: #   (%rsp) in %rsi  offse comp to 400efe
  40145c:    48 83 ec 18              sub    $0x18,%rsp #  400efe-64
  401460:    48 89 f2                 mov    %rsi,%rdx #  rdx=rsp-40 save arg2
  401463:    48 8d 4e 04              lea    0x4(%rsi),%rcx 
  401467:    48 8d 46 14              lea    0x14(%rsi),%rax
  40146b:    48 89 44 24 08           mov    %rax,0x8(%rsp) 
  401470:    48 8d 46 10              lea    0x10(%rsi),%rax
  401474:    48 89 04 24              mov    %rax,(%rsp) #
  401478:    4c 8d 4e 0c              lea    0xc(%rsi),%r9 #
  40147c:    4c 8d 46 08              lea    0x8(%rsi),%r8 #
  401480:    be c3 25 40 00           mov    $0x4025c3,%esi
  401485:    b8 00 00 00 00           mov    $0x0,%eax 
  40148a:    e8 61 f7 ff ff           callq  400bf0 <__isoc99_sscanf@plt>
  40148f:    83 f8 05                 cmp    $0x5,%eax  
  401492:    7f 05                    jg     401499 <read_six_numbers+0x3d>
  401494:    e8 a1 ff ff ff           callq  40143a <explode_bomb>
  401499:    48 83 c4 18              add    $0x18,%rsp
  40149d:    c3                       retq

    read_six_number,根据传入的是栈指针,以及汇编一直在基于栈作赋值之类的运算,能够推测出arg2是数组。再用内存查看对0x4025c3,能够看到是"%d %d ..." 六个d。结合sscanf函数的意义,能够理解为把input,即参数0,以指定格式给到六个参数中,这六个参数应该是数组。oop

这里能够gdb而后画个图方便理解。优化

    再看phase2就比较简单了。this

0000000000400efc <phase_2>:
  400efc:    55                       push   %rbp
  400efd:    53                       push   %rbx
  400efe:    48 83 ec 28              sub    $0x28,%rsp # -40
  400f02:    48 89 e6                 mov    %rsp,%rsi
  400f05:    e8 52 05 00 00           callq  40145c <read_six_numbers>
  400f0a:    83 3c 24 01              cmpl   $0x1,(%rsp)
  400f0e:    74 20                    je     400f30 <phase_2+0x34>
  400f10:    e8 25 05 00 00           callq  40143a <explode_bomb>
  400f15:    eb 19                    jmp    400f30 <phase_2+0x34>
  400f17:    8b 43 fc                 mov    -0x4(%rbx),%eax
  400f1a:    01 c0                    add    %eax,%eax 
  400f1c:    39 03                    cmp    %eax,(%rbx)
  400f1e:    74 05                    je     400f25 <phase_2+0x29>
  400f20:    e8 15 05 00 00           callq  40143a <explode_bomb>
  400f25:    48 83 c3 04              add    $0x4,%rbx
  400f29:    48 39 eb                 cmp    %rbp,%rbx
  400f2c:    75 e9                    jne    400f17 <phase_2+0x1b> # jump to loop
  400f2e:    eb 0c                    jmp    400f3c <phase_2+0x40> # jump to exit
  400f30:    48 8d 5c 24 04           lea    0x4(%rsp),%rbx
  400f35:    48 8d 6c 24 18           lea    0x18(%rsp),%rbp
  400f3a:    eb db                    jmp    400f17 <phase_2+0x1b>
  400f3c:    48 83 c4 28              add    $0x28,%rsp
  400f40:    5b                       pop    %rbx
  400f41:    5d                       pop    %rbp
  400f42:    c3                       retq

    就是数组开头必须是1,而后依次*2.咱们也能够根据-4,+4,+0x18猜到这是一个int 数组。debug

    结果:1 2 4 8 16 323d

That's number 2. Keep going!指针

phase3


    应该是lab里面最简单的一个了。方法本地分配两个变量,假设0x8(%rsp)=a,0xc(%rsp)=b,那么只须要知足公式:8a+0x400f7c=b便可,那么设置a=0,指令会跳转到0x400f7c处,能够看到直接赋值%rax 0xcf,那么咱们只须要另b=207就好了。400fbe地址处

400f43:    48 83 ec 18              sub    $0x18,%rsp
  400f47:    48 8d 4c 24 0c           lea    0xc(%rsp),%rcx 
  400f4c:    48 8d 54 24 08           lea    0x8(%rsp),%rdx
  400f51:    be cf 25 40 00           mov    $0x4025cf,%esi
  400f56:    b8 00 00 00 00           mov    $0x0,%eax
  400f5b:    e8 90 fc ff ff           callq  400bf0 <__isoc99_sscanf@plt>
  400f60:    83 f8 01                 cmp    $0x1,%eax
  400f63:    7f 05                    jg     400f6a <phase_3+0x27>
  400f65:    e8 d0 04 00 00           callq  40143a <explode_bomb>
  400f6a:    83 7c 24 08 07           cmpl   $0x7,0x8(%rsp) # arg1<=7
  400f6f:    77 3c                    ja     400fad <phase_3+0x6a>
  400f71:    8b 44 24 08              mov    0x8(%rsp),%eax
  400f75:    ff 24 c5 70 24 40 00     jmpq   *0x402470(,%rax,8)
  400f7c:    b8 cf 00 00 00           mov    $0xcf,%eax
  400f81:    eb 3b                    jmp    400fbe <phase_3+0x7b>
  400f83:    b8 c3 02 00 00           mov    $0x2c3,%eax
  400f88:    eb 34                    jmp    400fbe <phase_3+0x7b>
  400f8a:    b8 00 01 00 00           mov    $0x100,%eax
  400f8f:    eb 2d                    jmp    400fbe <phase_3+0x7b>
  400f91:    b8 85 01 00 00           mov    $0x185,%eax
  400f96:    eb 26                    jmp    400fbe <phase_3+0x7b>
  400f98:    b8 ce 00 00 00           mov    $0xce,%eax
  400f9d:    eb 1f                    jmp    400fbe <phase_3+0x7b>
  400f9f:    b8 aa 02 00 00           mov    $0x2aa,%eax
  400fa4:    eb 18                    jmp    400fbe <phase_3+0x7b>
  400fa6:    b8 47 01 00 00           mov    $0x147,%eax
  400fab:    eb 11                    jmp    400fbe <phase_3+0x7b>
  400fad:    e8 88 04 00 00           callq  40143a <explode_bomb>
  400fb2:    b8 00 00 00 00           mov    $0x0,%eax
  400fb7:    eb 05                    jmp    400fbe <phase_3+0x7b>
  400fb9:    b8 37 01 00 00           mov    $0x137,%eax
  400fbe:    3b 44 24 0c              cmp    0xc(%rsp),%eax
  400fc2:    74 05                    je     400fc9 <phase_3+0x86>
  400fc4:    e8 71 04 00 00           callq  40143a <explode_bomb>
  400fc9:    48 83 c4 18              add    $0x18,%rsp
  400fcd:    c3                       retq

     答案:0 207

Halfway there!

phase4


000000000040100c <phase_4>:
  40100c:    48 83 ec 18              sub    $0x18,%rsp  # arg1=0 arg0<=e
  401010:    48 8d 4c 24 0c           lea    0xc(%rsp),%rcx # 参数1
  401015:    48 8d 54 24 08           lea    0x8(%rsp),%rdx # 参数0
  40101a:    be cf 25 40 00           mov    $0x4025cf,%esi
  40101f:    b8 00 00 00 00           mov    $0x0,%eax
  401024:    e8 c7 fb ff ff           callq  400bf0 <__isoc99_sscanf@plt>
  401029:    83 f8 02                 cmp    $0x2,%eax
  40102c:    75 07                    jne    401035 <phase_4+0x29>
  40102e:    83 7c 24 08 0e           cmpl   $0xe,0x8(%rsp)
  401033:    76 05                    jbe    40103a <phase_4+0x2e>
  401035:    e8 00 04 00 00           callq  40143a <explode_bomb>
  40103a:    ba 0e 00 00 00           mov    $0xe,%edx
  40103f:    be 00 00 00 00           mov    $0x0,%esi
  401044:    8b 7c 24 08              mov    0x8(%rsp),%edi
  401048:    e8 81 ff ff ff           callq  c <func4> # arg0, 0, e
  40104d:    85 c0                    test   %eax,%eax
  40104f:    75 07                    jne    401058 <phase_4+0x4c>
  401051:    83 7c 24 0c 00           cmpl   $0x0,0xc(%rsp)
  401056:    74 05                    je     40105d <phase_4+0x51>
  401058:    e8 dd 03 00 00           callq  40143a <explode_bomb>
  40105d:    48 83 c4 18              add    $0x18,%rsp
  401061:    c3                       retq

func4

0000000000400fce <func4>: # x in %rdi , y in %rsi z in %rdx
  400fce:    48 83 ec 08              sub    $0x8,%rsp
  400fd2:    89 d0                    mov    %edx,%eax
  400fd4:    29 f0                    sub    %esi,%eax
  400fd6:    89 c1                    mov    %eax,%ecx
  400fd8:    c1 e9 1f                 shr    $0x1f,%ecx
  400fdb:    01 c8                    add    %ecx,%eax
  400fdd:    d1 f8                    sar    %eax
  400fdf:    8d 0c 30                 lea    (%rax,%rsi,1),%ecx
  400fe2:    39 f9                    cmp    %edi,%ecx
  400fe4:    7e 0c                    jle    400ff2 <func4+0x24>
  400fe6:    8d 51 ff                 lea    -0x1(%rcx),%edx
  400fe9:    e8 e0 ff ff ff           callq  400fce <func4>
  400fee:    01 c0                    add    %eax,%eax
  400ff0:    eb 15                    jmp    401007 <func4+0x39>
  400ff2:    b8 00 00 00 00           mov    $0x0,%eax
  400ff7:    39 f9                    cmp    %edi,%ecx
  400ff9:    7d 0c                    jge    401007 <func4+0x39>
  400ffb:    8d 71 01                 lea    0x1(%rcx),%esi
  400ffe:    e8 cb ff ff ff           callq  400fce <func4>
  401003:    8d 44 00 01              lea    0x1(%rax,%rax,1),%eax
  401007:    48 83 c4 08              add    $0x8,%rsp
  40100b:    c3                       retq

这一题要结合phase4 和fun4来看。

  首先看sscanf的参数,%rsi0x4025cf处,gdb查看是要求两个整数,根据40102c行也能得出此结论。40102e行说明参数须要0小于等于14,而后0,和e被看成参数1,2传递给fun4.再根据fun4的汇编反汇编一下,通过几版优化,基本能够得出它的功能如上,一直用z模2,直到z==x,不然返回2*fun(x,y,--z),其实else不用管它,由于若是你x传递0,那么0*任何数都会返回0。并且结合401051 行。发现第二个输入的数,也要是0,那么就更不会走第二个状况了。

感受这题须要的debug会比较多一点。

答案:0 0

鄙人可能错误的反汇编

int fun4(int x, int y, int z) //arg0,0,e ,should return 0
{  
    z %=2;//offset%2
    if(z == x){
        return 0;
    }
    else{
        return 2*fun(x,y,--z);
    }
}

So you got that one. Try this one.

  成功的喜悦~

phase5


0000000000401062 <phase_5>:
  401062:    53                       push   %rbx
  401063:    48 83 ec 20              sub    $0x20,%rsp
  401067:    48 89 fb                 mov    %rdi,%rbx
  40106a:    64 48 8b 04 25 28 00     mov    %fs:0x28,%rax #40
  401071:    00 00 
  401073:    48 89 44 24 18           mov    %rax,0x18(%rsp) # 24 金丝雀值
  401078:    31 c0                    xor    %eax,%eax # eax=0;
  40107a:    e8 9c 02 00 00           callq  40131b <string_length>
  40107f:    83 f8 06                 cmp    $0x6,%eax
  401082:    74 4e                    je     4010d2 <phase_5+0x70>
  401084:    e8 b1 03 00 00           callq  40143a <explode_bomb>
  401089:    eb 47                    jmp    4010d2 <phase_5+0x70>
~  40108b:    0f b6 0c 03              movzbl (%rbx,%rax,1),%ecx
~  40108f:    88 0c 24                 mov    %cl,(%rsp)
~  401092:    48 8b 14 24              mov    (%rsp),%rdx
~  401096:    83 e2 0f                 and    $0xf,%edx
~  401099:    0f b6 92 b0 24 40 00     movzbl 0x4024b0(%rdx),%edx
~  4010a0:    88 54 04 10              mov    %dl,0x10(%rsp,%rax,1)
~  4010a4:    48 83 c0 01              add    $0x1,%rax
~  4010a8:    48 83 f8 06              cmp    $0x6,%rax
~  4010ac:    75 dd                    jne    40108b <phase_5+0x29>
~  4010ae:    c6 44 24 16 00           movb   $0x0,0x16(%rsp)
~  4010b3:    be 5e 24 40 00           mov    $0x40245e,%esi
~  4010b8:    48 8d 7c 24 10           lea    0x10(%rsp),%rdi
~  4010bd:    e8 76 02 00 00           callq  401338 <strings_not_equal>
  4010c2:    85 c0                    test   %eax,%eax
  4010c4:    74 13                    je     4010d9 <phase_5+0x77>
  4010c6:    e8 6f 03 00 00           callq  40143a <explode_bomb>
  4010cb:    0f 1f 44 00 00           nopl   0x0(%rax,%rax,1)
  4010d0:    eb 07                    jmp    4010d9 <phase_5+0x77>
  4010d2:    b8 00 00 00 00           mov    $0x0,%eax
  4010d7:    eb b2                    jmp    40108b <phase_5+0x29>
  4010d9:    48 8b 44 24 18           mov    0x18(%rsp),%rax
  4010de:    64 48 33 04 25 28 00     xor    %fs:0x28,%rax
  4010e5:    00 00 
  4010e7:    74 05                    je     4010ee <phase_5+0x8c>
  4010e9:    e8 42 fa ff ff           callq  400b30 <__stack_chk_fail@plt>
  4010ee:    48 83 c4 20              add    $0x20,%rsp
  4010f2:    5b                       pop    %rbx
  4010f3:    c3                       retq

比较核心的代码就是我用‘~’号标记出来的。大体的意思是取你输入字符的最后一个字节,保留低4位,在加上基地址0x4024b0 取到一个字符,凑6个成字符串,再和0x40245e处的字符比较,同样退出,不然引爆。

比较难懂的是40106amov %fs:0x28,%rax。搜索得知这是利用段寄存器得到随机值。还有4010a4: add $0x1,%rax的目的。弄明白这两个基本没有问题。

这题没有固定答案,只要你输入的字符串每一个字节低四位依次等于9fe567的二进制表示就行。个人答案:9/.567

Good work! On to the next...

phase6

这是六个语句中最长的一句。总共有三个部分。

部分1

4010f4:    41 56                    push   %r14
  4010f6:    41 55                    push   %r13
  4010f8:    41 54                    push   %r12
  4010fa:    55                       push   %rbp
  4010fb:    53                       push   %rbx
  4010fc:    48 83 ec 50              sub    $0x50,%rsp
  401100:    49 89 e5                 mov    %rsp,%r13
  401103:    48 89 e6                 mov    %rsp,%rsi
  401106:    e8 51 03 00 00           callq  40145c <read_six_numbers>
  40110b:    49 89 e6                 mov    %rsp,%r14
  40110e:    41 bc 00 00 00 00        mov    $0x0,%r12d
  401114:    4c 89 ed                 mov    %r13,%rbp # --------------
  401117:    41 8b 45 00              mov    0x0(%r13),%eax
  40111b:    83 e8 01                 sub    $0x1,%eax
  40111e:    83 f8 05                 cmp    $0x5,%eax
  401121:    76 05                    jbe    401128 <phase_6+0x34>  # 
  401123:    e8 12 03 00 00           callq  40143a <explode_bomb>
  401128:    41 83 c4 01              add    $0x1,%r12d
  40112c:    41 83 fc 06              cmp    $0x6,%r12d
  401130:    74 21                    je     401153 <phase_6+0x5f>
  401132:    44 89 e3                 mov    %r12d,%ebx
  401135:    48 63 c3                 movslq %ebx,%rax
  401138:    8b 04 84                 mov    (%rsp,%rax,4),%eax
  40113b:    39 45 00                 cmp    %eax,0x0(%rbp)
  40113e:    75 05                    jne    401145 <phase_6+0x51>  # 2 
  401140:    e8 f5 02 00 00           callq  40143a <explode_bomb>
  401145:    83 c3 01                 add    $0x1,%ebx
  401148:    83 fb 05                 cmp    $0x5,%ebx
  40114b:    7e e8                    jle    401135 <phase_6+0x41>
  40114d:    49 83 c5 04              add    $0x4,%r13
  401151:    eb c1                    jmp    401114 <phase_6+0x20>  # (%r13+4)-1<=5
  401153:    48 8d 74 24 18           lea    0x18(%rsp),%rsi # [5]
  401158:    4c 89 f0                 mov    %r14,%rax # [0]
  40115b:    b9 07 00 00 00           mov    $0x7,%ecx
  401160:    89 ca                    mov    %ecx,%edx
  401162:    2b 10                    sub    (%rax),%edx # [i]= 7- [i] i start with 0
  401164:    89 10                    mov    %edx,(%rax)  
  401166:    48 83 c0 04              add    $0x4,%rax # i++
  40116a:    48 39 f0                 cmp    %rsi,%rax # while (i!=5) loop.
  40116d:    75 f1                    jne    401160 <phase_6+0x6c>

检测你输入的数是否大于7,或者是否有重复的。这里有for循环嵌套比较难看懂。接着把每一个数-=7。

部分2

40116f:    be 00 00 00 00           mov    $0x0,%esi # rsi = i
  401174:    eb 21                    jmp    401197 <phase_6+0xa3>
  # -------------------------------- 
  401176:    48 8b 52 08              mov    0x8(%rdx),%rdx # amazing code!
  40117a:    83 c0 01                 add    $0x1,%eax
  40117d:    39 c8                    cmp    %ecx,%eax
  40117f:    75 f5                    jne    401176 <phase_6+0x82>
  # --------------------------------
  401181:    eb 05                    jmp    401188 <phase_6+0x94>
  # -----------------------------------------------
  401183:    ba d0 32 60 00           mov    $0x6032d0,%edx
  # ------------------------------------内循环 i 找到a[i]>1的,同时对i++
  401188:    48 89 54 74 20           mov    %rdx,0x20(%rsp,%rsi,2)
  40118d:    48 83 c6 04              add    $0x4,%rsi
  401191:    48 83 fe 18              cmp    $0x18,%rsi # i < 6
  401195:    74 14                    je     4011ab <phase_6+0xb7> # jump out from loop
  401197:    8b 0c 34                 mov    (%rsp,%rsi,1),%ecx
  40119a:    83 f9 01                 cmp    $0x1,%ecx
  40119d:    7e e4                    jle    401183 <phase_6+0x8f>
  # -----------------------------------------------
  # ------------------------------------else
  40119f:    b8 01 00 00 00           mov    $0x1,%eax
  4011a4:    ba d0 32 60 00           mov    $0x6032d0,%edx
  4011a9:    eb cb                    jmp    401176 <phase_6+0x82>

将栈上分配6个变量存放链表指针。这里功能最少确是最复杂的。由于引入了复杂数据结构(即便是最简单的),因此让反汇编起来难以理解,特别是双重循环的关系。到底谁是外循环,谁又是内循环,哪一个寄存器控制着跳出条件?而后就是慢慢完善c语言,最后让c和汇编的逻辑一一对应。

从gdb看得出来是链表

(gdb) x/6xg 0x7fffffffde40
0x7fffffffde40:    0x00000000006032d0    0x0000000000603320
0x7fffffffde50:    0x0000000000603310    0x0000000000603300
0x7fffffffde60:    0x00000000006032f0    0x00000000006032e0
x/12xg 0x6032d0
0x6032d0 <node1>:    0x000000010000014c    0x00000000006032e0
0x6032e0 <node2>:    0x00000002000000a8    0x00000000006032f0
0x6032f0 <node3>:    0x000000030000039c    0x0000000000603300
0x603300 <node4>:    0x00000004000002b3    0x0000000000603310
0x603310 <node5>:    0x00000005000001dd    0x0000000000603320
0x603320 <node6>:    0x00000006000001bb    0x0000000000000000

部分3

4011ab:    48 8b 5c 24 20           mov    0x20(%rsp),%rbx # b=node1
  4011b0:    48 8d 44 24 28           lea    0x28(%rsp),%rax # 
  4011b5:    48 8d 74 24 50           lea    0x50(%rsp),%rsi #
  4011ba:    48 89 d9                 mov    %rbx,%rcx
  4011bd:    48 8b 10                 mov    (%rax),%rdx #  
  4011c0:    48 89 51 08              mov    %rdx,0x8(%rcx) # 
  4011c4:    48 83 c0 08              add    $0x8,%rax # 
  4011c8:    48 39 f0                 cmp    %rsi,%rax # not 
  4011cb:    74 05                    je     4011d2 <phase_6+0xde>
  4011cd:    48 89 d1                 mov    %rdx,%rcx # rcx 
  4011d0:    eb eb                    jmp    4011bd <phase_6+0xc9>  #  0x6032d0 332
  4011d2:    48 c7 42 08 00 00 00     movq   $0x0,0x8(%rdx) # *(d->next)=0
  4011d9:    00 
  4011da:    bd 05 00 00 00           mov    $0x5,%ebp
  4011df:    48 8b 43 08              mov    0x8(%rbx),%rax
  4011e3:    8b 00                    mov    (%rax),%eax
  4011e5:    39 03                    cmp    %eax,(%rbx)
  4011e7:    7d 05                    jge    4011ee <phase_6+0xfa>
  4011e9:    e8 4c 02 00 00           callq  40143a <explode_bomb>
  4011ee:    48 8b 5b 08              mov    0x8(%rbx),%rbx
  4011f2:    83 ed 01                 sub    $0x1,%ebp
  4011f5:    75 e8                    jne    4011df <phase_6+0xeb>
  4011f7:    48 83 c4 50              add    $0x50,%rsp
  4011fb:    5b                       pop    %rbx
  4011fc:    5d                       pop    %rbp
  4011fd:    41 5c                    pop    %r12
  4011ff:    41 5d                    pop    %r13
  401201:    41 5e                    pop    %r14
  401203:    c3                       retq

其实这一部分仍是能够根据4011d9: 00 分红2部分。第一部分把0x6032d0处的链表链接起来。具体是node6->node1;其他从小到大依次链接。

mov    0x8(%rbx),%rax
    mov    (%rax),%eax
    cmp    %eax,(%rbx)
    jge    4011ee <phase_6+0xfa>
    callq  40143a <explode_bomb>

第二部分(上面代码)就是要求前面后四位的要大于后面的。要求node1~node6 数据后4位从大到小排列。即对

(gdb) x/12xg 0x6032d0
0x6032d0 <node1>:    0x000000010000014c    0x0000000000603320
0x6032e0 <node2>:    0x00000002000000a8    0x00000000006032f0
0x6032f0 <node3>:    0x000000030000039c    0x0000000000603300
0x603300 <node4>:    0x00000004000002b3    0x0000000000603310
0x603310 <node5>:    0x00000005000001dd    0x0000000000603320
0x603320 <node6>:    0x00000006000001bb    0x0000000000603310

排列。而这个数据是在第二部放置的。
应该的顺序:3 4 5 6 1 2。然而在部分1会对全部输入-=7。
因此答案:4 3 2 1 6 5
Congratulations! You've defused the bomb!

至此,bomblab主线完成,听说还有一个secret phase .弃。

Welcome to my fiendish little bomb. You have 6 phases with which to blow yourself up. Have a nice day! Phase 1 defused. How about the next one? That's number 2. Keep going! Halfway there! So you got that one. Try this one. Good work! On to the next... Congratulations! You've defused the bomb!
相关文章
相关标签/搜索