# PicoCTF - Easy as GDB ## Source code :::spoiler IDA Main Function ```cpp= int __cdecl main(int argc, const char **argv, const char **envp) { char *str_len; // eax int v5; // [esp-8h] [ebp-20h] int v6; // [esp-4h] [ebp-1Ch] char *input_flag; // [esp+4h] [ebp-14h] size_t str_len_1; // [esp+8h] [ebp-10h] char *src; // [esp+Ch] [ebp-Ch] input_flag = calloc(0x200u, 1u); printf("input the flag: "); fgets(input_flag, 512, stdin); str_len = strnlen(aZNh, 512, v5, v6); src = enc_input(str_len, str_len); sub_7C2(src, 1, 1); if ( check_flag(src, str_len_1) == 1 ) puts("Correct!"); else puts("Incorrect."); return 0; } ``` ::: :::spoiler IDA Main Encryption Part ```cpp= char *__cdecl sub_82B(char *src, size_t enc_flag_len) { unsigned int i; // [esp+0h] [ebp-18h] char *dest; // [esp+Ch] [ebp-Ch] size_t enc_flag_len_and; // [esp+24h] [ebp+Ch] enc_flag_len_and = (enc_flag_len & 0xFFFFFFFC) + 4; dest = malloc(enc_flag_len_and + 1); strncpy(dest, src, enc_flag_len_and); for ( i = 0xABCF00D; i < 0xDEADBEEF; i += 0x1FAB4D ) main_enc_part(dest, enc_flag_len_and, i); return dest; } ``` ::: :::spoiler IDA Main Encryption Part 2 ```cpp= unsigned int __cdecl sub_6BD(int dest, unsigned int enc_flag_len_and, int idx) { unsigned int result; // eax unsigned int i; // [esp+14h] [ebp-14h] char v5[4]; // [esp+18h] [ebp-10h] unsigned int v6; // [esp+1Ch] [ebp-Ch] v6 = __readgsdword(0x14u); v5[0] = HIBYTE(idx); // 0x0a v5[1] = BYTE2(idx); // 0xbc v5[2] = BYTE1(idx); // 0xf0 v5[3] = idx; // 0x0d for ( i = 0; i < enc_flag_len_and; ++i ) *(dest + i) ^= v5[i & 3]; result = __readgsdword(0x14u) ^ v6; if ( result ) sub_B20(); return result; } ``` ::: ## Recon 這一題算簡單,但搞了好久,一方面是ida有些東西翻的很醜,一方面gdb看不出來main, encryption等等function symbol,所以一些動態的address的提示都沒有,會有點妨礙,但整體來說他做的事情就是他先把index的每一個bytes,都獨立出來,以0x0abcf00d來說, v5[0]=0x0a v5[1]=0xbc v5[2]=0xf0 v5[3]=0x0d 然後跟我們的input的每一個bytes都進行XOR,當第一round結束後new index = 0x0abcf00d + 0x1FAB4D,然後重複前面執行的部分,所以我們要做的事情就只是重複剛剛所有的過程,就可以拿到flag了。 至於要比較的ciphertext可以直接從gdb的動態看出來 ## Exploit ```python= cipher = bytes.fromhex("2E6E40681D53657C175816436D5862366F436230016347333F6314636d7a00") flag = [] for i in range(len(cipher)): flag.append(hex(cipher[i])[2:]) for i in range(0xABCF00D, 0xdea62e4b, 0x1FAB4D): tmp_idx = hex(i)[2:].encode() if len(tmp_idx) < 8: tmp_idx = b'0' + tmp_idx key = [int(tmp_idx[-8:-6], 16), int(tmp_idx[-6:-4], 16), int(tmp_idx[-4:-2], 16), int(tmp_idx[-2:], 16)] for j in range(len(cipher)): tmp = hex(int(flag[j], 16) ^ key[j % 4])[2:] flag[j] = tmp # cipher[j] = bytes.fromhex(hex(cipher[j] ^ key[j % 4])[2:]) print(bytes.fromhex("".join(flag)).decode('cp437')) ```