CSAWCTF_2017: tablEZ

Category: Reverse Points: 100 Description:

Bobby was talking about tables a bunch, so I made some table stuff. I think this is what he was talking about...

Write-up

This one was slightly tricky, we get started with the main fuction. Our pseudocode decompiler spits out the following for main,

int main() {
    puts("Please enter the flag:");
    fgets(&var_90, 0x80, *__TMC_END__);
    *(int8_t *)(rbp + (strlen(&var_90) - 0x1) + 0xffffffffffffff70) = 0x0;
    var_C8 = strlen(&var_90);
    for (var_D0 = 0x0; var_D0 < var_C8; var_D0 = var_D0 + 0x1) {
            *(int8_t *)(var_D0 + &var_90) = get_tbl_entry(sign_extend_64(*(int8_t *)(var_D0 + &var_90) & 0xff));
    }
    if (var_C8 != 0x25) {
            puts("WRONG");
            rax = 0x1;
    }
    else {
            var_C0 = 0xb1e711f59d73b327;
            if (strncmp(&var_90, &var_C0, 0x26) == 0x0) {
                    puts("CORRECT <3");
                    rax = 0x0;
            }
            else {
                    puts("WRONG");
                    rax = 0x1;
            }
    }
    rsi = *0x28 ^ *0x28;
    if (rsi != 0x0) {
            rax = __stack_chk_fail();
    }
    return rax;
}

Looks like the flag has something to do with having the processed string equals to 0xb1e711f59d73b327 but that doesn't make sense, considering we need a length of 37! This is a lesson on the reliability of pseudocode decompilers. Going to assembly view, we get the following string.

00000000000008ba         movabs     rax, 0xb1e711f59d73b327
00000000000008c4         movabs     rdx, 0x30f4f9f9b399beb3
00000000000008ce         mov        qword [rbp+var_C0], rax
00000000000008d5         mov        qword [rbp+var_B8], rdx
00000000000008dc         movabs     rax, 0xb19965237399711b
00000000000008e6         movabs     rdx, 0xf9279923be111165
00000000000008f0         mov        qword [rbp+var_B0], rax
00000000000008f7         mov        qword [rbp+var_A8], rdx
00000000000008fe         mov        dword [rbp+var_A0], 0x65059923
0000000000000908         mov        word [rbp+var_9C], 0xce

This computes to b1e711f59d73b32730f4f9f9b399beb3b19965237399711bf9279923be11116565059923ce. How will we get the flag though? Well, this is actually computed through the get_tbl_entry fuction. Essentially, in steps of two, search through the trans_tbl table for the corresponding character and return the character above it. The trick is that because it checks from the base address while returning the address offsetted by 1, you pick the character above.

b1 b
e7 4
11 t
f5 {
9d g
73 a
b3 l
27 f

30 u
f4 k
f9 0
f9 0
b3 l
99 _
be e
b3 l

b1 b
99 _
65 3
23 r
73 a
99 _
71 s
1b p

f9 0
27 f
99 _
23 r
be e
11 t
11 t
65 3

65 3
05 m
99 _
23 r

ce }

Therefore, the flag is flag{t4ble_l00kups_ar3_b3tter_f0r_m3}.