PicoCTF - Easy as GDB
Source code
:::spoiler IDA Main Function
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
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
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
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'))