BH01 - 500pts

Briefing

Download the file and find a way to get the flag. Contents: program
Challenge Files:

Solution

  1. 1.
    Inputting some random letters into the program prints some of the flag:
    1
    What is the magic word?
    2
    djyawthvdbhgsajdghytwilhqypdoasgdbhwgdytqvdkbfuhgyabkhsj
    3
    Flag: aLittLeObfuScatIo������uF?9��
    4
    Did you understand that?
    Copied!
    However, the amount of the flag that is printed changes each time we run the program using the same input. There appears to be 4 different variations so a random number generator is involved. Using an input that consists of a single character seems to always produce the same output.
  2. 2.
    We can decompile the binary using Ghidra to see what the program does:
    main function:
    1
    undefined8 FUN_00101209(void)
    2
    3
    {
    4
    byte bVar1;
    5
    byte bVar2;
    6
    int iVar3;
    7
    uint uVar4;
    8
    time_t tVar5;
    9
    long in_FS_OFFSET;
    10
    uint local_90;
    11
    time_t local_88;
    12
    undefined4 local_7d;
    13
    undefined local_79;
    14
    undefined8 local_78;
    15
    undefined8 local_70;
    16
    undefined8 local_68;
    17
    undefined8 local_60;
    18
    undefined4 local_58;
    19
    undefined8 local_48;
    20
    undefined8 local_40;
    21
    undefined8 local_38;
    22
    undefined8 local_30;
    23
    undefined8 local_28;
    24
    undefined2 local_20;
    25
    long local_10;
    26
    27
    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    28
    tVar5 = time(&local_88);
    29
    srand((uint)tVar5);
    30
    local_48 = 0;
    31
    local_40 = 0;
    32
    local_38 = 0;
    33
    local_30 = 0;
    34
    local_28 = 0;
    35
    local_20 = 0;
    36
    local_7d = 0x16120a05;
    37
    local_79 = 0x18;
    38
    puts("What is the magic word?");
    39
    fflush(stdout);
    40
    fgets((char *)&local_48,0x28,stdin);
    41
    local_78 = 0x103f4f6c803a05b6;
    42
    local_70 = 0x9f2abbb5f5e62364;
    43
    local_68 = 0x982b00094580efba;
    44
    local_60 = 0x3f4675fb93f9dfb2;
    45
    local_58 = 0x1afcba39;
    46
    iVar3 = rand();
    47
    uVar4 = (int)*(char *)((long)&local_48 + (long)(int)*(char *)((long)&local_7d + (long)(iVar3 % 5))
    48
    ) - 0x5a;
    49
    local_90 = 0;
    50
    while (local_90 < uVar4) {
    51
    bVar1 = ~*(byte *)((long)&local_78 + (ulong)local_90) + 0x2f;
    52
    bVar2 = (byte)local_90;
    53
    bVar1 = (~(~(0x57 - (~(bVar1 * -0x80 | bVar1 >> 1) - 0x33)) - 0x3f) ^ bVar2) + 0x4e ^ bVar2;
    54
    bVar1 = ~((bVar1 * '\x02' | bVar1 >> 7) + 0x3d) ^ bVar2;
    55
    bVar1 = ~(bVar1 << 3 | bVar1 >> 5);
    56
    if ((int)uVar4 < 0) break;
    57
    bVar1 = ~((bVar1 << 5 | bVar1 >> 3) - bVar2) - 0x17;
    58
    bVar1 = ~((bVar1 * -0x80 | bVar1 >> 1) - bVar2);
    59
    bVar1 = 0xad - ((bVar1 << 3 | bVar1 >> 5) + 0x3c);
    60
    bVar1 = (bVar1 * ' ' | bVar1 >> 3) + bVar2;
    61
    bVar1 = (bVar1 * '\b' | bVar1 >> 5) - bVar2;
    62
    bVar1 = ~(bVar1 * -0x80 | bVar1 >> 1) ^ bVar2;
    63
    bVar2 = (bVar1 * -0x40 | (byte)-bVar1 >> 2) - bVar2;
    64
    bVar1 = ~(~(~(bVar2 * ' ' | bVar2 >> 3) ^ 0x45) - 8);
    65
    *(byte *)((long)&local_78 + (ulong)local_90) =
    66
    (0xd1 - ((bVar1 << 2 | bVar1 >> 6) ^ 0xef) ^ 0x65) - 0x3a;
    67
    local_90 = local_90 + 1;
    68
    }
    69
    puts((char *)&local_78);
    70
    puts("Did you understand that?");
    71
    if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    72
    return 0;
    73
    }
    74
    /* WARNING: Subroutine does not return */
    75
    __stack_chk_fail();
    76
    }
    Copied!
  3. 3.
    The program picks a random byte from local_7d and uses that byte to index the user input to get a single character uVar4. Next, a loop runs that prints the flag character by character. However, it only iterates trough the loop uVar4 - 0x5a times. Therefore, the letter that is selected from the input has to have an ascii code minus 0x5a (90) that is greater than the length of the flag.
  4. 4.
    } has a large ascii value. If we sent a lot of }s into the program, it will print the flag: python -c "print('}'*50)" | ./program. This is because the program selects a random character from our input, subtracts 90 from it, and then prints that many characters of the flag. So, 125 - 90 = 35 which means the loop runs 35 times and successfully displays the 29 character flag. We cannot use just one } because the program selects a random character from the input and it a character does not exist at the chosen index, it selects \x00 (a null byte).
    1
    What is the magic word?
    2
    }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    3
    Flag: aLittLeObfuScatIonalCharActEr
    4
    Did you understand that?
    Copied!

Flag

aLittLeObfuScatIonalCharActEr
Copy link