bomblab

Bomb lab

Let’s do reverse engineering

(Unfortunately, we cannot get CMU version bomb … We won’t lose points when the bomb blows up.)

Bomb lab how to

  • read the writeup
  • You get three files
    • the README
    • the executable
    • the source file (Heavily redacted, you need to use gdb to figure out the acutal code)

Useful utilities

  • objdump
    • -d for disassembly
    • -t for print the symbol table entries of the file
  • strings to extract all printable strings
  • gdb to do the main job
  • man to get the help you need
  • readelf to get read-only data section

(also IDA, Ghidra, radare2 and other reverse engineering tools, but you will lose your precious hand-on experience for reconstruct c code from assembly, not recommended.)

Get started

Gather information

  • There are 6 phases in the bomb

  • The bomb use sscanf to get input

  • The bomb can accept a command line argument and treat it as input, end with EOF and then switch to stdin. So we can faciliate this feature to easy our pain of retyping.(Thank you Dr. Evil :crying_cat_face: )

  • Although objdump -d gives you a lot of information, it doesn’t tell you the whole story.

    For example

    a call to sscanf might appear as:

    1
    8048c36: e8 99 fc ff ff call 80488d4 <_init+0x1a0>

    while in gdb this is

    1
    0x000000000000075e <+68>:	callq  0x5f0 <__isoc99_sscanf@plt>

    (but I got the same result in objdump )

  • strings bomb

    • It seems that there will be a secret stage : Wow! You've defused the secret stage!

    • ctrl-c don’t work : So you think you can stop the bomb with ctrl-c, do you?

      (Laterly it turned out that ctrl-c does not get banned: Well...OK. :-) )

    • It still try to connet to the server ? Let’s check the code to figure this out.

      1
      2
      3
      4
      5
      6
      greatwhite.ics.cs.cmu.edu
      angelshark.ics.cs.cmu.edu
      makoshark.ics.cs.cmu.edu
      Error: HTTP request failed with error %d: %s
      GET /%s/submitr.pl/?userid=%s&lab=%s&result=%s&submit=submit HTTP/1.0
      Error: Unable to connect to server %s
    • compile options

      1
      GNU C 4.8.1 -mtune=generic -march=x86-64 -ggdb -O1 -fstack-protector

      (canary found)

  • less bomb.c

    • phase 4 has something to do with math
    • phase 5 play with memory
    • there must be a secret stage
  • objdump -t bomb

    Potential useful symbols

    1
    2
    3
    4
    5
    6
    7
    8
    num_input_strings
    explode_bomb
    fun7
    func4
    string_length
    secret_phase
    strings_not_equal
    read_six_numbers

    Static analysis

1
$ objdump -d bomb > codedump.s
  • main has the same code shown by bomb.c

  • num_input_strings is called by read_line

  • Function submitr try to connect to the server, but it can only be called by driver_post, and driver_post doesn’t called by any function. So the bomb won’t connect to CMU’s server when it explode.

    1
    2
    $ readelf -x .rodata bomb
    $ readelf -p .rodata bomb
    1
    2
    3
    4
    5
    6
    7
    8
    000000000040143a <explode_bomb>:
    40143a: 48 83 ec 08 sub $0x8,%rsp
    40143e: bf a3 25 40 00 mov $0x4025a3,%edi
    401443: e8 c8 f6 ff ff callq 400b10 <puts@plt>
    401448: bf ac 25 40 00 mov $0x4025ac,%edi
    40144d: e8 be f6 ff ff callq 400b10 <puts@plt>
    401452: bf 08 00 00 00 mov $0x8,%edi
    401457: e8 c4 f7 ff ff callq 400c20 <exit@plt>
    1
    2
    3
    4
    5
    6
    void explode_bomb(void){
    puts("BOOM!!!");
    puts("The bomb has blown up.");
    exit(8);
    }
    //no call to submitr() and driver_post()
  • Phase 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
    1
    2
    3
    4
    5
    6
    7
    8
    void phase_1(char* input){
    int esi = 0x402400;
    //address at section .rodata
    //Border relations with Canada have never been better.
    int eax = strings_not_equal(input , (char*)esi);
    if (eax != 0) explode_bomb();
    return ;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    0000000000401338 <strings_not_equal>:
    401338: 41 54 push %r12
    40133a: 55 push %rbp
    40133b: 53 push %rbx
    40133c: 48 89 fb mov %rdi,%rbx
    40133f: 48 89 f5 mov %rsi,%rbp
    401342: e8 d4 ff ff ff callq 40131b <string_length>
    401347: 41 89 c4 mov %eax,%r12d
    40134a: 48 89 ef mov %rbp,%rdi
    40134d: e8 c9 ff ff ff callq 40131b <string_length>
    401352: ba 01 00 00 00 mov $0x1,%edx
    401357: 41 39 c4 cmp %eax,%r12d
    40135a: 75 3f jne 40139b <strings_not_equal+0x63>
    40135c: 0f b6 03 movzbl (%rbx),%eax
    40135f: 84 c0 test %al,%al
    401361: 74 25 je 401388 <strings_not_equal+0x50>
    401363: 3a 45 00 cmp 0x0(%rbp),%al
    401366: 74 0a je 401372 <strings_not_equal+0x3a>
    401368: eb 25 jmp 40138f <strings_not_equal+0x57>
    40136a: 3a 45 00 cmp 0x0(%rbp),%al
    40136d: 0f 1f 00 nopl (%rax)
    401370: 75 24 jne 401396 <strings_not_equal+0x5e>
    401372: 48 83 c3 01 add $0x1,%rbx
    401376: 48 83 c5 01 add $0x1,%rbp
    40137a: 0f b6 03 movzbl (%rbx),%eax
    40137d: 84 c0 test %al,%al
    40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
    401381: ba 00 00 00 00 mov $0x0,%edx
    401386: eb 13 jmp 40139b <strings_not_equal+0x63>
    401388: ba 00 00 00 00 mov $0x0,%edx
    40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
    40138f: ba 01 00 00 00 mov $0x1,%edx
    401394: eb 05 jmp 40139b <strings_not_equal+0x63>
    401396: ba 01 00 00 00 mov $0x1,%edx
    40139b: 89 d0 mov %edx,%eax
    40139d: 5b pop %rbx
    40139e: 5d pop %rbp
    40139f: 41 5c pop %r12
    4013a1: c3 retq
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    000000000040131b <string_length>:
    40131b: 80 3f 00 cmpb $0x0,(%rdi)
    40131e: 74 12 je 401332 <string_length+0x17>
    401320: 48 89 fa mov %rdi,%rdx
    401323: 48 83 c2 01 add $0x1,%rdx
    401327: 89 d0 mov %edx,%eax
    401329: 29 f8 sub %edi,%eax
    40132b: 80 3a 00 cmpb $0x0,(%rdx)
    40132e: 75 f3 jne 401323 <string_length+0x8>
    401330: f3 c3 repz retq
    401332: b8 00 00 00 00 mov $0x0,%eax
    401337: c3 retq
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int string_length(char * s){
    if (s[0] == '\0') return 0;
    char * rdx = s;
    int res ;
    do{
    rdx++;
    res = rdx - s;
    }while(*rdx != '\0');
    return res;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    int strings_not_equal(char * input , char * target){
    int inputlen = string_length(input);
    int targetlen = string_length(target);
    int res = 1;
    if ( inputlen != targetlen){ return res; }
    else if (input[0] == '\0') {
    res = 0;
    return res;
    }
    else{
    while (*input == *target){
    input++;
    target++;
    if(*input == '\0'){
    res = 0; return res;
    }
    }
    res = 1;
    return res;
    }
    }
    1
    Phase 1 defused. How about the next one?
  • Phase 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    0000000000400efc <phase_2>:
    400efc: 55 push %rbp
    400efd: 53 push %rbx
    400efe: 48 83 ec 28 sub $0x28,%rsp
    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>
    400f2e: eb 0c jmp 400f3c <phase_2+0x40>
    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
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    000000000040145c <read_six_numbers>:
    40145c: 48 83 ec 18 sub $0x18,%rsp
    401460: 48 89 f2 mov %rsi,%rdx
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void read_six_numbers(char* input , int buf [6]){
    int * rdx = buf;
    int* rcx = buf + 1;
    int * local1 = buf + 5;
    int * local0 = buf + 4;
    int * r9 = buf + 3;
    int * r8 = buf + 2;
    int res = sscanf(input , "%d %d %d %d %d %d" , rdx , rcx , r8 , r9 , local0 ,local1);
    //On success, the function returns the number of items in the argument list successfully filled.
    if (res > 5) return ;
    else explode_bomb();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void phase_2(char * input){
    int numbers [6] ;
    read_six_numbers(char* input , numbers );
    if(numbers[0] != 1) explode_bomb();
    int* rbx = numbers + 1;
    int* rbp = numbers + 6;
    do{
    int temp = (*(rbx-1))*2;
    if (temp == *rbx )
    rbx++;
    else explode_bomb();
    }while(rbp != rbx);
    //1 2 4 8 16 32
    }
    1
    That's number 2.  Keep going!
  • Phase 3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    0000000000400f43 <phase_3>:
    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)
    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) # use gdb
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /* .rodata
    0x00402470 7c0f4000 00000000 b90f4000 00000000 |.@.......@.....
    0x00402480 830f4000 00000000 8a0f4000 00000000 ..@.......@.....
    0x00402490 910f4000 00000000 980f4000 00000000 ..@.......@.....
    0x004024a0 9f0f4000 00000000 a60f4000 00000000 ..@.......@.....
    */

    void phase_3(char * input){
    int * temp1 = alloca(sizeof(int));
    int * temp0 = alloca(sizeof(int));
    int receive_cot = sscanf(input , "%d %d" , temp0 , temp1);
    if (receive_cot > 1){
    if ((unsigned int)*temp0 > 7u) {explode_bomb(); /* return 0;*/ }
    else{
    int res = *temp0;
    switch(res){
    case 0:
    res = 207;break;
    case 1:
    res = 331;break;
    case 2:
    res = 707;break;
    case 3:
    res = 256;break;
    case 4:
    res = 389;break;
    case 5:
    res = 206;break;
    case 6:
    res = 682;break;
    case 7:
    res = 327;break;
    }
    if (res != *temp1) explode_bomb();
    }
    }
    else explode_bomb();
    }
    /*
    0 207
    */
    1
    Halfway there!
  • Phase 4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    000000000040100c <phase_4>:
    40100c: 48 83 ec 18 sub $0x18,%rsp
    401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
    401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
    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 400fce <func4>
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void phase_4(char* input){
    int * temp1 = alloca(sizeof(int));
    int * temp0 = alloca(sizeof(int));
    int receiv = sscanf(input , "%d %d" , temp0 ,temp1);
    if (receiv != 2) explode_bomb();
    if (*temp0 > 14u ) explode_bomb();
    int res = func4(*temp0 , 0 , 14);
    if (res != 0) explode_bomb();
    if (*temp1 != 0) explode_bomb();
    return;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    0000000000400fce <func4>:
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    int func4(int  temp0 , int esi, int edx){
    int res = edx - esi;
    res = res + ((unsigned int)res >> 31);
    res >>= 1;
    int local = res + esi;
    if (local <= temp0){
    res = 0;
    if (local >= temp0) return res;
    else {
    return func4(temp0 , local + 1 , edx)* 2 + 1;
    }
    }
    else{
    edx = local - 1;
    return func4(temp0 , esi , edx)*2;
    }
    }
    //7 0
    1
    So you got that one.  Try this one.
  • Phase 5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    0000000000401062 <phase_5>:
    401062: 53 push %rbx
    401063: 48 83 ec 20 sub $0x20,%rsp
    401067: 48 89 fb mov %rdi,%rbx
    # get canary value
    #40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
    #401071: 00 00
    #401073: 48 89 44 24 18 mov %rax,0x18(%rsp)
    401078: 31 c0 xor %eax,%eax
    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>
    #check canary value
    #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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    void phase_5(char* input){
    int inputlen = string_length(input);
    char local [6];
    if (inputlen == 6){
    //Tag:
    int rax = 0;
    do{
    char ecx = input[rax];
    char rdx = ecx & 0xf;
    char * addr = 0x4024b0;
    //0x00 0x40 0x24 0xb0 0x6d 0x61 0x64 0x75 0x69 0x65 0x72 0x73 0x6e 0x66 0x6f 0x74 0x76 0x62 0x79 0x6c
    //m a d u i e r s n f o t v b y l
    rdx = *(addr + rdx);
    local[rax] = rdx;
    rax++;
    while(rax != 6);
    local[6] = '\0';
    int res = strings_not_equal(local , 0x40245e);
    //"flyers"
    if (res != 0) explode_bomb();
    }
    else{
    explode_bomb();
    //goto Tag;
    //the compiler generate some codes which will never be executed.
    }
    }
    //9,f,e,5,6,7
    //''.join([chr(0x40+i) for i in [9,0xf,0xe,5,6,7]])
    //IONEFG
    1
    Good work!  On to the next...
  • Phase 6

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    00000000004010f4 <phase_6>:
    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>
    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>
    401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi
    401158: 4c 89 f0 mov %r14,%rax
    40115b: b9 07 00 00 00 mov $0x7,%ecx
    401160: 89 ca mov %ecx,%edx
    401162: 2b 10 sub (%rax),%edx
    401164: 89 10 mov %edx,(%rax)
    401166: 48 83 c0 04 add $0x4,%rax
    40116a: 48 39 f0 cmp %rsi,%rax
    40116d: 75 f1 jne 401160 <phase_6+0x6c>
    40116f: be 00 00 00 00 mov $0x0,%esi
    401174: eb 21 jmp 401197 <phase_6+0xa3>
    401176: 48 8b 52 08 mov 0x8(%rdx),%rdx
    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
    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
    401195: 74 14 je 4011ab <phase_6+0xb7>
    401197: 8b 0c 34 mov (%rsp,%rsi,1),%ecx
    40119a: 83 f9 01 cmp $0x1,%ecx
    40119d: 7e e4 jle 401183 <phase_6+0x8f>
    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>
    4011ab: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx
    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
    4011cb: 74 05 je 4011d2 <phase_6+0xde>
    4011cd: 48 89 d1 mov %rdx,%rcx
    4011d0: eb eb jmp 4011bd <phase_6+0xc9>
    4011d2: 48 c7 42 08 00 00 00 movq $0x0,0x8(%rdx)
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    void phase_6(char* input){
    int numbers[6];
    int * walk = numbers;
    read_six_numbers(input , numbers);
    int * r14 = numbers;
    int check_times = 0;
    Loop:
    int * rbp = walk;
    if ( (*walk - 1) > 5u) { explode_bomb();}
    check_times++;
    if (check_times == 6){
    //change numbers to (7 - origin number)
    int * end = numbers+6;
    int * p = numbers;
    do{
    *p = 7 - *p;
    p++;
    }
    while( p != end);

    //use memory value to update stack value
    int index = 0; //rsi

    while ((rcx = numbers[index]) <= 1){
    int rdx = 0x6032d0;
    Resume:
    *(numbers + 8 + 2*index) = rdx; //write memory value to stack space
    index++;

    if (index == 6) {

    int rbx = *(numbers+8); //6032d0
    int * res = numbers+10; //6032e0
    int * boundary = numbers + 20;
    int rcx = *(numbers+8) ;

    //write back value fetched from memory, beware of the order
    do{
    int rdx = *res;
    *((long *)(rcx+0x8)) = rdx;
    res+=2;
    }
    while(res != boundary , rcx = rdx);

    //final 6 checks

    *(rdx+0x8) = 0; //clear a chunk of memory
    int cnt = 5; //rbp
    do{
    res = *((long *)rbx+0x8);
    res = *res;
    //compare stack value, *rbx, and memory value, res
    if ( *rbx < res) { explode_bomb(); }
    rbx = *(rbx+0x8);
    cnt--;
    }
    while (cnt != 0 );
    return;
    }
    }

    //fetch a value from memory : *(0x6032d0 + 8*(rcx-1))
    rax = 1;
    rdx = 0x6032d0;
    do{
    rdx = *(rdx + 8);
    //0x6032e0 //0x6032f0 //0x603300 //0x603310 //0x603320
    rax++;
    }
    while(rax != rcx);
    //offset (rcx - 1) times
    goto Resume;
    }
    else{
    //int rbx = r12;
    int cot = check_times; // %ebx is the cot
    do{
    int next = numbers[cot];
    if (*walk == next) { explode_bomb();}
    cot++;
    }while( cot <= 5);
    walk ++;
    goto Loop;
    //every round of checking r13 points to next number
    }
    }

    /*
    1. every number - 1 should <= 5u
    2. evry number should be different
    */

    Dynamic analysis for phase 6

1
2
3
4
5
6
7
8
pwndbg> x /14gx 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
0x603330: 0x0000000000000000 0x0000000000000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0x6032d0 : 0x000000010000014c # value
0x6032d8 : 0x00000000006032e0 # pointer
0x6032e0 : 0x00000002000000a8 # value
0x6032e8 : 0x00000000006032f0 # pointer
0x6032f0 : 0x000000030000039c # value
0x6032f8 : 0x0000000000603300 # pointer
0x603300 : 0x00000004000002b3 # value
0x603308 : 0x0000000000603310 # pointer
0x603310 : 0x00000005000001dd # value
0x603318 : 0x0000000000603320 # pointer
0x603320 : 0x00000006000001bb # value
0x603328 : 0x0000000000000000 # 0
0x603330 : 0x0000000000000000 # 0
# 5 pointers , 6 values
1
2
3
4
5
6
7
8
9
10
11
12
pwndbg> x /12gx $rsp
0x7fffffffe320: 0x0000000000000000 0x00007ffff7dcda00
0x7fffffffe330: 0x0000000000603910 # end of number array
0x7fffffffe338: 0x0000000000000000

# start of hidden space
0x7fffffffe340: 0x00007fffffffe480 0x0000000000000000
0x7fffffffe350: 0x0000000000000000 0x00000000004013cc
0x7fffffffe360: 0x00007fffffffe488 0x0000000000603910
# end of hiddne space

0x7fffffffe370: 0x00007fffffffe488 0x0000000000402210
1
2
3
4
5
6
7
pwndbg> x /12gx 0x6032d0                                              
0x6032d0 <node1>: 0x000000010000014c 0x00000000006032e0
0x6032e0 <node2>: 0x00000002000000a8 0x0000000000000000
0x6032f0 <node3>: 0x000000030000039c 0x0000000000603300
0x603300 <node4>: 0x00000004000002b3 0x0000000000603310
0x603310 <node5>: 0x00000005000001dd 0x0000000000603320
0x603320 <node6>: 0x00000006000001bb 0x00000000006032d0

Correct C code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
void explode_bomb();
void phase_6(char* input){
int numbers[6];
int * walk = numbers;
read_six_numbers(input , numbers);
int check_times = 0;
Loop:
if ( (*walk - 1) > 5u) { explode_bomb();} // numbers should be in set{1, 2, 3, 4, 5, 6}
check_times++;
if (check_times == 6){
//change numbers to (7 - origin number)
int * end = numbers+6;
int * p = numbers;
do{
*p = 7 - *p;
p++;
}
while( p != end);

//use memory value to update stack value
//update one by one use rdx
int index = 0; //rsi
//instruction at 0x401197
while ((rcx = numbers[index]) <= 1){
//instruction at 401183
int rdx = 0x6032d0;
Resume:
*(numbers + 8 + 2*index) = rdx; //write memory value to stack space 6 times
index++;

if (index == 6) {

int mstartp = *(numbers+8);
int * next = numbers+10;
int * boundary = numbers + 20;
int saver = *(numbers+8) ;

//write back value fetched from memory, only write 5 times, the first value is preserved to indicate start point of final check
//Beware of the order
do{

long content = *next ;
*(saver+0x8) = content ; //only value at address in form of 0x........8 can be changed
//use saver as a pointer to write to the position (saver + 0x8)
next+=2;
}
while(next != boundary , saver = content );
/* violate C syntax here
* valid code can be like
*
* do{
* ......
* if (next != boundary ) break;
* saver = content;
* }while(1);
*
*/

//final 5 checks
*(rdx+0x8) = 0; //set the last node of pointing chain's "link" to 0x0
//instruction at 0x00000000004011da
int cnt = 5; //%rbp
do{
//mstartp can serve as a pointer of pointer
int * adjacent = *(mstartp+0x8);
//compare memory values
if ( *mstartp < *adjacent) { explode_bomb(); }
mstartp = adjacent;
//update mstartp to what it is pointing
cnt--;
} while (cnt != 0 );
return;
}
}

//fetch a value from memory : *(0x6032d0 + 8*(rcx-1))
rax = 1;
//instruction at 0x4011a4
rdx = 0x6032d0;
do{
rdx = *(rdx + 8); //0x6032e0 //0x6032f0 //0x603300 //0x603310 //0x603320
rax++;
}
while(rax != rcx); //offset (rcx - 1) times
goto Resume;
}
else{
int cot = check_times; // %ebx is the cot
do{
int next = numbers[cot];
if (*walk == next) { explode_bomb();}
cot++;
}while( cot <= 5 );
walk ++;
goto Loop;
//after one round of checking r13 points to next number
//every number should be different
}
}

Correct layout of memory values

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# movl to retrive value from memory
# so the data type is int rather than long !!!!
d = {
fifth 0x6032d0 : 332 # value
0x6032d8 : 0x6032e0 # pointer
0x6032e0 : 168 # value
0x6032e8 : 0 # pointer
first 0x6032f0 : 924 # value
0x6032f8 : 0x603300 # pointer
second 0x603300 : 691 # value
0x603308 : 0x603310 # pointer
third 0x603310 : 477 # value
0x603318 : 0x603320 # pointer
fourth 0x603320 : 443 # value
0x603328 : 0x6032d0 # 0
0x603330 : 0x000000000 # 0
}
# 4 3 2 1 6 5
1
Congratulations! You've defused the bomb!

When working with low level codes the most important thing is patience.

Secret Phase

by examing the assembly code generated by objdump, we can see that there is a call to secret_phase in function phase_defused

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
00000000004015c4 <phase_defused>:
4015c4: 48 83 ec 78 sub $0x78,%rsp
# canary
#4015c8: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
#4015cf: 00 00
#4015d1: 48 89 44 24 68 mov %rax,0x68(%rsp)
4015d6: 31 c0 xor %eax,%eax
4015d8: 83 3d 81 21 20 00 06 cmpl $0x6,0x202181(%rip) # 603760 <num_input_strings>
4015df: 75 5e jne 40163f <phase_defused+0x7b>
4015e1: 4c 8d 44 24 10 lea 0x10(%rsp),%r8
4015e6: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
4015eb: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
4015f0: be 19 26 40 00 mov $0x402619,%esi
4015f5: bf 70 38 60 00 mov $0x603870,%edi
4015fa: e8 f1 f5 ff ff callq 400bf0 <__isoc99_sscanf@plt>
4015ff: 83 f8 03 cmp $0x3,%eax
401602: 75 31 jne 401635 <phase_defused+0x71>
401604: be 22 26 40 00 mov $0x402622,%esi
401609: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
40160e: e8 25 fd ff ff callq 401338 <strings_not_equal>
401613: 85 c0 test %eax,%eax
401615: 75 1e jne 401635 <phase_defused+0x71>
401617: bf f8 24 40 00 mov $0x4024f8,%edi
40161c: e8 ef f4 ff ff callq 400b10 <puts@plt>
401621: bf 20 25 40 00 mov $0x402520,%edi
401626: e8 e5 f4 ff ff callq 400b10 <puts@plt>
40162b: b8 00 00 00 00 mov $0x0,%eax
401630: e8 0d fc ff ff callq 401242 <secret_phase>
401635: bf 58 25 40 00 mov $0x402558,%edi
40163a: e8 d1 f4 ff ff callq 400b10 <puts@plt>
#check canary
#40163f: 48 8b 44 24 68 mov 0x68(%rsp),%rax
#401644: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
#40164b: 00 00
40164d: 74 05 je 401654 <phase_defused+0x90>
#40164f: e8 dc f4 ff ff callq 400b30 <__stack_chk_fail@plt>
401654: 48 83 c4 78 add $0x78,%rsp
401658: c3 retq
401659: 90 nop
40165a: 90 nop
40165b: 90 nop
40165c: 90 nop
40165d: 90 nop
40165e: 90 nop
40165f: 90 nop

What is num_input_strings ?

  • No codes named num_input_string in assembly

  • Search the symbols

    1
    2
    $ cat symbols | grep 'num_input_strings'
    0000000000603760 g O .bss 0000000000000004 num_input_strings

    But what is .bss section ?

    1
    2
    $ readelf -x .bss bomb
    Section '.bss' has no data to dump.
  • uninitialized static data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdlib.h>
#include <stdio.h>
static int num_input_strings; //count of input string number
char * slution_to_phase_4 = "7 0"
void phase_defused(void){
if (num_input_strings != 6){
return;
}
else{
short* local0 = alloca(2);
short* local1 = alloca(2);
char * local2 ;
int receive = sscanf(slution_to_phase_4 , "%d %d %s" , local0 , local1 ,local2);
//we need to append an extra string to solution_of_phase_4
if (receive != 3) {
Normal:
puts("Congratulations! You've defused the bomb!");
return;
}
else{
int res = strings_not_equal(local2 , "DrEvil");
if (res != 0){ goto Normal ;}
else{
puts("Curses, you've found the secret phase!");
puts("But finding it and solving it are quite different...");
res = 0;
secret_phase();
goto Normal;
}
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
0000000000401242 <secret_phase>:
401242: 53 push %rbx
401243: e8 56 02 00 00 callq 40149e <read_line>
401248: ba 0a 00 00 00 mov $0xa,%edx
40124d: be 00 00 00 00 mov $0x0,%esi
401252: 48 89 c7 mov %rax,%rdi
401255: e8 76 f9 ff ff callq 400bd0 <strtol@plt>
40125a: 48 89 c3 mov %rax,%rbx
40125d: 8d 40 ff lea -0x1(%rax),%eax
401260: 3d e8 03 00 00 cmp $0x3e8,%eax
401265: 76 05 jbe 40126c <secret_phase+0x2a>
401267: e8 ce 01 00 00 callq 40143a <explode_bomb>
40126c: 89 de mov %ebx,%esi
40126e: bf f0 30 60 00 mov $0x6030f0,%edi
401273: e8 8c ff ff ff callq 401204 <fun7>
401278: 83 f8 02 cmp $0x2,%eax
40127b: 74 05 je 401282 <secret_phase+0x40>
40127d: e8 b8 01 00 00 callq 40143a <explode_bomb>
401282: bf 38 24 40 00 mov $0x402438,%edi
401287: e8 84 f8 ff ff callq 400b10 <puts@plt>
40128c: e8 33 03 00 00 callq 4015c4 <phase_defused>
401291: 5b pop %rbx
401292: c3 retq
401293: 90 nop
401294: 90 nop
401295: 90 nop
401296: 90 nop
401297: 90 nop
401298: 90 nop
401299: 90 nop
40129a: 90 nop
40129b: 90 nop
40129c: 90 nop
40129d: 90 nop
40129e: 90 nop
40129f: 90 nop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void secret_phase(){
char * input = read_line();
long number = strtol(input , '\0' , 10);
long save = number; //rbx
number = number - 1;
if (number <= 0x3e8u ){
int res = fun7(0x6030f0 , save);
if(res == 2){
puts("Wow! You've defused the secret stage!");
}
else{
explode_bomb();
}
phase_defused();
return;
}
else{
explode_bomb();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0000000000401204 <fun7>:
401204: 48 83 ec 08 sub $0x8,%rsp
401208: 48 85 ff test %rdi,%rdi
40120b: 74 2b je 401238 <fun7+0x34>
40120d: 8b 17 mov (%rdi),%edx
40120f: 39 f2 cmp %esi,%edx
401211: 7e 0d jle 401220 <fun7+0x1c>
401213: 48 8b 7f 08 mov 0x8(%rdi),%rdi
401217: e8 e8 ff ff ff callq 401204 <fun7>
40121c: 01 c0 add %eax,%eax
40121e: eb 1d jmp 40123d <fun7+0x39>
401220: b8 00 00 00 00 mov $0x0,%eax
401225: 39 f2 cmp %esi,%edx
401227: 74 14 je 40123d <fun7+0x39>
401229: 48 8b 7f 10 mov 0x10(%rdi),%rdi
40122d: e8 d2 ff ff ff callq 401204 <fun7>
401232: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
401236: eb 05 jmp 40123d <fun7+0x39>
401238: b8 ff ff ff ff mov $0xffffffff,%eax
40123d: 48 83 c4 08 add $0x8,%rsp
401241: c3 retq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int fun7(int one, int two){
if (one == 0 ){
return 0xffffffff;
}
else{
int edx = *one;
if ( edx <= two ){
int res = 0;
if (edx == two){
return res;
}
else{
one = *(one + 0x10);
return 1 +fun7(one , two)*2;
}
}
else{
one = *(one + 0x8);
return fun7(one , two)*2;
}
}
}

Once dump the memory 0x6030f0, I was surprised to find that this is a binary tree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
0x6030f0 <n1>:	0x0000000000000024	0x0000000000603110
0x603100 <n1+16>: 0x0000000000603130 0x0000000000000000
0x603110 <n21>: 0x0000000000000008 0x0000000000603190
0x603120 <n21+16>: 0x0000000000603150 0x0000000000000000
0x603130 <n22>: 0x0000000000000032 0x0000000000603170
0x603140 <n22+16>: 0x00000000006031b0 0x0000000000000000
0x603150 <n32>: 0x0000000000000016 0x0000000000603270
0x603160 <n32+16>: 0x0000000000603230 0x0000000000000000
0x603170 <n33>: 0x000000000000002d 0x00000000006031d0
0x603180 <n33+16>: 0x0000000000603290 0x0000000000000000
0x603190 <n31>: 0x0000000000000006 0x00000000006031f0
0x6031a0 <n31+16>: 0x0000000000603250 0x0000000000000000
0x6031b0 <n34>: 0x000000000000006b 0x0000000000603210
0x6031c0 <n34+16>: 0x00000000006032b0 0x0000000000000000
0x6031d0 <n45>: 0x0000000000000028 0x0000000000000000
0x6031e0 <n45+16>: 0x0000000000000000 0x0000000000000000
0x6031f0 <n41>: 0x0000000000000001 0x0000000000000000
0x603200 <n41+16>: 0x0000000000000000 0x0000000000000000
0x603210 <n47>: 0x0000000000000063 0x0000000000000000
0x603220 <n47+16>: 0x0000000000000000 0x0000000000000000
0x603230 <n44>: 0x0000000000000023 0x0000000000000000
0x603240 <n44+16>: 0x0000000000000000 0x0000000000000000
0x603250 <n42>: 0x0000000000000007 0x0000000000000000
0x603260 <n42+16>: 0x0000000000000000 0x0000000000000000
0x603270 <n43>: 0x0000000000000014 0x0000000000000000
0x603280 <n43+16>: 0x0000000000000000 0x0000000000000000
0x603290 <n46>: 0x000000000000002f 0x0000000000000000
0x6032a0 <n46+16>: 0x0000000000000000 0x0000000000000000
0x6032b0 <n48>: 0x00000000000003e9 0x0000000000000000
0x6032c0 <n48+16>: 0x0000000000000000 0x0000000000000000
1
2
3
4
5
6
7
8
      ....36....         
/ \
.8.. ..50.
/ \ / \
6 22 45 107
/ \ / \ / \ / \
1 7 20 35 40 0 99 1001
/\ /\ /\ /\ /\ /\ /\ / \
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//BST search for signal value
int fun7(int * root, int signal){
if (root == NULL ){
return -1;
}
int value = *root; //0x24 = 36
if ( value <= signal ){

if (value == signal){ return 0; }
else{
//root = *(root + 0x10);
root = root->right;
return 1 +fun7(root , signal)*2;
}
}
else{
//root = *(root + 0x8);
root = root->left;
return fun7(root , signal)*2;
}
}

I was so tired to think, so just write some shity code to solve the problem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class BSTNode(object):

def __init__(self, parent, k):
self.key = k
self.parent = parent
self.left = None
self.right = None

def insertleft(self, node):
if node is None:
return
if self.left is None:
node.parent = self
self.left = node
else:
self.left.insertleft(node)

def insertright(self, node):
if node is None:
return
if self.right is None:
node.parent = self
self.right = node
else:
self.right.insertright(node)

def fsearch(self , target):
if self == None:
return -1
value = self.key
if value <= target:
if value == target :
return 0
else:
if self.right == None : return -1
return 1+self.right.fsearch(target)*2
else:
if self.left == None : return -1
return self.left.fsearch(target) * 2


n1 = BSTNode(None , 0x24)

n21 = BSTNode(None , 0x8)
n22 = BSTNode(None , 0x32)
n32 = BSTNode(None , 0x16)
n33 = BSTNode(None , 0x2d)
n31 = BSTNode(None , 0x06)
n34 = BSTNode(None , 0x6b)
n45 = BSTNode(None , 0x28)
n41 = BSTNode(None , 0x1)
n47 = BSTNode(None , 0x63)
n44 = BSTNode(None , 0x23)
n42 = BSTNode(None , 0x7)
n43 = BSTNode(None , 0x14)
n46 = BSTNode(None , 0x0)
n48 = BSTNode(None , 0x3e9)

n1.insertleft(n21)
n1.insertright(n22)
n21.insertleft(n31)
n21.insertright(n32)
n22.insertleft(n33)
n22.insertright(n34)
n32.insertleft(n43)
n32.insertright(n44)
n33.insertleft(n45)
n33.insertright(n46)
n31.insertleft(n41)
n31.insertright(n42)
n34.insertleft(n47)
n34.insertright(n48)

ls = [0x8,0x32,0x16,0x2d,0x06,0x6b,0x28,0x1,0x63,0x23,0x7,0x14,0x0,0x3e9]
for i in ls :
print(n1.fsearch(i) , "when search :" , i)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0 when search : 8
1 when search : 50
2 when search : 22
1 when search : 45
0 when search : 6
3 when search : 107
1 when search : 40
0 when search : 1
3 when search : 99
6 when search : 35
4 when search : 7
2 when search : 20
-8 when search : 0
7 when search : 1001

Both 20 and 22 will do the favor for you

1
2
Wow! You've defused the secret stage!
Congratulations! You've defused the bomb!

End

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat answer
Border relations with Canada have never been better.
1 2 4 8 16 32
0 207
7 0 DrEvil
IONEFG
4 3 2 1 6 5
22
$ ./bomb answer
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...
Curses, you've found the secret phase!
But finding it and solving it are quite different...
Wow! You've defused the secret stage!
Congratulations! You've defused the bomb!