2017 Dimi CTF Prequal WhatIsTheEnd
메인을 보면 33글자를 입력받을 받는다. 그리고 어떠한 연산을 하고 맞는지 비교해준다.
int __cdecl main(int a1)
{
int v2; // [esp-Ah] [ebp-70h]
int v3; // [esp-6h] [ebp-6Ch]
int v4; // [esp-2h] [ebp-68h]
char v5; // [esp+1h] [ebp-65h]
signed int i; // [esp+2h] [ebp-64h]
signed int j; // [esp+2h] [ebp-64h]
char v8; // [esp+6h] [ebp-60h]
char v9; // [esp+7h] [ebp-5Fh]
char v10; // [esp+8h] [ebp-5Eh]
char v11; // [esp+9h] [ebp-5Dh]
char v12; // [esp+Ah] [ebp-5Ch]
char v13; // [esp+Bh] [ebp-5Bh]
char v14; // [esp+Ch] [ebp-5Ah]
char v15; // [esp+Dh] [ebp-59h]
char v16; // [esp+Eh] [ebp-58h]
char v17; // [esp+Fh] [ebp-57h]
char v18; // [esp+10h] [ebp-56h]
char v19; // [esp+11h] [ebp-55h]
char v20; // [esp+12h] [ebp-54h]
char v21; // [esp+13h] [ebp-53h]
char v22; // [esp+14h] [ebp-52h]
char v23; // [esp+15h] [ebp-51h]
char v24; // [esp+16h] [ebp-50h]
char v25; // [esp+17h] [ebp-4Fh]
char v26; // [esp+18h] [ebp-4Eh]
char v27; // [esp+19h] [ebp-4Dh]
char v28; // [esp+1Ah] [ebp-4Ch]
char v29; // [esp+1Bh] [ebp-4Bh]
char v30; // [esp+1Ch] [ebp-4Ah]
char v31; // [esp+1Dh] [ebp-49h]
char v32; // [esp+1Eh] [ebp-48h]
char v33; // [esp+1Fh] [ebp-47h]
char v34; // [esp+20h] [ebp-46h]
char v35; // [esp+21h] [ebp-45h]
char v36; // [esp+22h] [ebp-44h]
char v37; // [esp+23h] [ebp-43h]
char v38; // [esp+24h] [ebp-42h]
char v39; // [esp+25h] [ebp-41h]
__int16 v40; // [esp+26h] [ebp-40h]
int v41; // [esp+28h] [ebp-3Eh]
__int16 v42; // [esp+2Ch] [ebp-3Ah]
int v43; // [esp+2Eh] [ebp-38h]
int v44; // [esp+32h] [ebp-34h]
int v45; // [esp+36h] [ebp-30h]
int v46; // [esp+3Ah] [ebp-2Ch]
int v47; // [esp+3Eh] [ebp-28h]
int v48; // [esp+42h] [ebp-24h]
int v49; // [esp+46h] [ebp-20h]
unsigned int v50; // [esp+4Ah] [ebp-1Ch]
int v51; // [esp+4Eh] [ebp-18h]
int v52; // [esp+52h] [ebp-14h]
int v53; // [esp+56h] [ebp-10h]
int *v54; // [esp+5Ah] [ebp-Ch]
v54 = &a1;
v50 = __readgsdword(0x14u);
v40 = 0;
v8 = 172;
v9 = 171;
v10 = 30;
v11 = 44;
v12 = 166;
v13 = 161;
v14 = 156;
v15 = 232;
v16 = 255;
v17 = 97;
v18 = 9;
v19 = 83;
v20 = 37;
v21 = 20;
v22 = 130;
v23 = 60;
v24 = 165;
v25 = 145;
v26 = 165;
v27 = 219;
v28 = 233;
v29 = 4;
v30 = 96;
v31 = 224;
v32 = 26;
v33 = 110;
v34 = 97;
v35 = 65;
v36 = 183;
v37 = 79;
v38 = 83;
v39 = 205;
LOBYTE(v40) = 27;
v41 = 0;
v49 = 0;
memset((&v42 & 0xFFFFFFFC), 0, 4 * (((&v41 - (&v42 & 0xFFFFFFFC) + 34) & 0xFFFFFFFC) >> 2));
printf("INPUT: ");
__isoc99_scanf(
"%33s",
&v41,
v2,
v3,
v4,
0,
*&v8,
*&v12,
*&v16,
*&v20,
*&v24,
*&v28,
*&v32,
*&v36,
*&v40,
*(&v41 + 2),
v43,
v44,
v45,
v46,
v47,
v48,
v49);
v53 = 0;
v52 = 1;
v51 = 0;
v5 = ptrace(0, 0, 1, 0);
for ( i = 0; i <= 32; ++i )
*(&v41 + i) ^= v5 ^ rand();
for ( j = 0; j <= 32; ++j )
{
if ( (*(&v8 + j) ^ *(&v41 + j)) != *(&v41 + j + 1) )
{
puts("Nope!");
return -1;
}
}
puts("Correct!");
return 0;
}
여기서는 v8[i] ^ input[i] ^ rand[i] == input[i+1] ^ rand[i+1]
이러한 연산을 하고 있는데 우선 v8은 고정 값이고 rand()는 시드 값이 없으니까 그냥 긁어오면 된다.
ptrace는 디버깅중이 아니니까 0을 리턴하니까 xor연산해도 같은 값이 나오니까 무시해도 된다. 디버깅 중이면 -1을 리턴한다.
나는 라이브러리를 불러와서 rand값을 다 구하고 z3 이용해서 풀었다.
from ctypes import CDLL
from z3 import *
libc = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
rand_table = []
table = [172,171,30,44,166,161,156,232,255,97,9,83,37,20,130,60,165,145,165,219,233,4,96,224,26,110,97,65,183,79,83,205,27]
for i in range(33):
rand_table.append(libc.rand()%256)
s = Solver()
a1 = [BitVec('a%i'%i,8)for i in range(33)]
s.add(a1[0] == ord('d'))
s.add(a1[1] == ord('i'))
s.add(a1[2] == ord('m'))
s.add(a1[3] == ord('i'))
for i in range(32):
s.add(table[i] ^ a1[i] ^ rand_table[i] == a1[i+1] ^ rand_table[i+1])
print s.check()
m = s.model()
print ''.join(chr(int(str((m.evaluate(a1[i]))))) for i in range(33))
FLAG : dimigo{Always_String_END_is_NULL}