【CTF对抗-KCTF 2024 第七题 星际移民 WriteUp】此文章归类为:CTF对抗。
用ida打开, 先给一些全局变量改个名;
1 2 3 4 5 6 7 8 9 10 | int __cdecl main( int argc, const char **argv, const char **envp)
{
printf_1( "Input User:\n" );
gets_1(&user);
printf_1( "Input Serial:\n" );
gets_1(&serial);
off_403FD4(&off_403FD0);
getchar ();
return 0;
}
|
首先是第一段:
1 2 3 4 5 6 7 8 9 | int __cdecl sub_401120(unsigned __int8 **a1)
{
tmp = hex2bin_401000(::serial);
qmemcpy(serial, tmp, 0x43u);
free (tmp);
v2 = a1[1];
for ( i = 0; i < 0x2B9; ++i )
serial[i % 0x43u] ^= v2[i];
}
|
其中a1是off_403FD0
:
1 2 3 4 5 6 7 | .data: 00403FD0 off_403FD0 dd offset _main ; DATA XREF: _main + 2C ↑o
.data: 00403FD0 ; .data: 0040302C ↑o
.data: 00403FD4 ; _DWORD (__cdecl * off_403FD4)(_DWORD)
.data: 00403FD4 off_403FD4 dd offset sub_401120 ; DATA XREF: _main + 31 ↑r
.data: 00403FD8 ; int (__cdecl * gets_1)(_DWORD)
.data: 00403FD8 gets_1 dd 0 ; DATA XREF: _main + 10 ↑r
.data: 00403FD8 ; _main + 26 ↑r ...
|
所以a1[1]
应该是指向sub_401120
函数的指针, 其中的数据就是该函数的字节码
1 2 3 4 5 6 7 | bin = open ( 'decode.exe' , 'rb' ).read()
text_base = bin .find(b '\x83\xec\x18\xa1' )
code_401120 = bin [text_base + 0x120 :text_base + 0x120 + 0x2B9 ]
for i in range ( 697 ):
serial[i % 0x43 ] ^ = code_401120[i]
|
反向计算操作相同;
之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | v4 = serial[0];
for ( j = 1; j < 66; v4 ^= serial[j - 2] ^ serial[j - 1] ^ serial[j - 3] ^ v6 )
{
v6 = serial[j + 1] ^ serial[j];
j += 5;
}
v7 = v4 ^ serial[66];
serial[66] ^= v4;
v8 = serial;
v9 = 66;
do
{
*v8++ ^= v7;
--v9;
}
while ( v9 );
|
交换一下j += 5
和for
里的v4 ^= serial[j - 2] ^ serial[j - 1] ^ serial[j - 3] ^ v6
, j += 5
是先执行的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | v4 = serial[0];
for ( j = 1; j < 66; j += 5 )
{
v6 = serial[j + 1] ^ serial[j];
v4 ^= serial[j + 3] ^ serial[j + 4] ^ serial[j + 2] ^ v6;
}
v7 = v4 ^ serial[66];
serial[66] ^= v4;
v8 = serial;
v9 = 66;
do
{
*v8++ ^= v7;
--v9;
}
while ( v9 );
|
可以转化为:
1 2 3 4 5 6 7 8 | xor_char = 0
for i in range ( 66 ):
xor_char ^ = serial[i]
serial[ 66 ] ^ = xor_char
xor_char = serial[ 66 ]
for i in range ( 66 ):
serial[i] ^ = xor_char
|
其反向计算为
1 2 3 4 5 6 7 8 | xor_char = serial[ 66 ]
for i in range ( 66 ):
serial[i] ^ = xor_char
xor_char = 0
for i in range ( 66 ):
xor_char ^ = serial[i]
serial[ 66 ] ^ = xor_char
|
下一段先备好xor_char2
1 2 3 4 5 6 7 8 9 10 11 12 13 | v10 = user;
xor_char2 = 0;
v12 = &user;
if ( user )
{
do
{
++v12;
xor_char2 ^= v10;
v10 = *v12;
}
while ( *v12 );
}
|
1 2 3 4 | user = b 'KCTF'
xor_char2 = 0
for i in range ( 4 ):
xor_char2 ^ = user[i]
|
之后分析下一段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | main_code = * a1;
p_serial = serial;
serial_23 = &serial[ 2 * (xor_char2 & 0xF )];
sep = 2 * (xor_char2 & 0xF );
if ( sep > = 0 && serial_23 ! = serial )
{
size = sep;
pmain_code = main_code;
if ( (unsigned int )sep < 4 )
{
LABEL_13:
if ( !size )
goto LABEL_22;
}
else
{
while ( * (_DWORD * )pmain_code = = * (_DWORD * )p_serial )
{
size - = 4 ;
p_serial + = 4 ;
pmain_code + = 4 ;
if ( size < 4 )
goto LABEL_13;
}
}
v18 = * pmain_code - * p_serial;
if ( !v18 )
{
if ( size < = 1 )
goto LABEL_22;
v18 = pmain_code[ 1 ] - p_serial[ 1 ];
if ( !v18 )
{
if ( size < = 2 )
goto LABEL_22;
v18 = pmain_code[ 2 ] - p_serial[ 2 ];
if ( !v18 )
{
if ( size < = 3 )
goto LABEL_22;
v18 = pmain_code[ 3 ] - p_serial[ 3 ];
}
}
}
if ( (v18 >> 31 ) | 1 )
return printf( "fail.\n" );
}
LABEL_22:
v19 = 44 - sep;
if ( 44 - sep > 0 )
{
v20 = &serial[sep + 23 ];
v21 = &main_code[sep + 23 ];
if ( v19 < 4 )
{
LABEL_26:
if ( !v19 )
goto LABEL_35;
}
else
{
while ( * (_DWORD * )v21 = = * (_DWORD * )v20 )
{
v19 - = 4 ;
v20 + = 4 ;
v21 + = 4 ;
if ( v19 < 4 )
goto LABEL_26;
}
}
v22 = * v21 - * v20;
if ( v22 )
goto LABEL_34;
if ( v19 > 1 )
{
v22 = v21[ 1 ] - v20[ 1 ];
if ( v22 )
goto LABEL_34;
if ( v19 > 2 )
{
v22 = v21[ 2 ] - v20[ 2 ];
if ( v22 )
goto LABEL_34;
if ( v19 > 3 )
{
v22 = v21[ 3 ] - v20[ 3 ];
LABEL_34:
if ( (v22 >> 31 ) | 1 )
return printf( "fail.\n" );
}
}
}
}
|
由sep(2 * (xor_char2 & 0xF))
, sep+23
将serial
分成三段, 将前后两段与main_code
对应位置内容比较, 需要相同否则就会fail
下一段是:
1 2 3 4 | qmemcpy(&serial_23_1, serial_23, 20u);
v23 = serial_23 + 20;
*((_WORD *)&serial_23_1 + 10) = *((_WORD *)serial_23 + 10);
*((_BYTE *)&serial_23_1 + 22) = v23[2];
|
qmemcpy复制了20字节, _WORD指针从10*2=20
继续复制2字节, _BYTE指针复制1字节, 总共从serial_23复制了23字节
下一段为:
1 2 3 4 5 6 7 8 9 10 11 | code_401120 = a1[1];
p_serial23 = &serial_23_1;
v26 = 23;
do
{
v27 = *p_serial23 >> (8 - (*code_401120 & 7));
v28 = *p_serial23++ << (*code_401120++ & 7);
--v26;
*(p_serial23 - 1) = v28 | v27;
}
while ( v26 );
|
是通过<<
与>>
以code_401120的数据为基准做一个循环移位操作
python实现为
1 2 3 | for i in range ( 23 ):
shn = code_401120[i] & 7
serial_23[i] = ((serial_23[i] >> ( 8 - shn))& 0xff ) | ((serial_23[i] << shn)& 0xff )
|
其反向操作为
1 2 3 | for i in range ( 23 ):
shn = code_401120[i] & 7
serial_23[i] = ((serial_23[i] << ( 8 - shn))& 0xff ) | ((serial_23[i] >> shn)& 0xff )
|
最后一段将serial_23
与KCTF-2024-CRACK-SUCCESS
比较:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | v29 = 23 ;
v30 = "KCTF-2024-CRACK-SUCCESS" ;
p_serial_23 = &serial_23_1;
while ( * (_DWORD * )p_serial_23 = = * (_DWORD * )v30 )
{
v29 - = 4 ;
v30 + = 4 ;
p_serial_23 + = 4 ;
if ( v29 < 4 )
{
if ( * v30 = = * p_serial_23 && v30[ 1 ] = = p_serial_23[ 1 ] && v30[ 2 ] = = p_serial_23[ 2 ] )
return printf( "***success***.\n" );
return printf( "fail.\n" );
}
}
|
最后的python代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | import codecs
bin = open ( 'decode.exe' , 'rb' ).read()
text_base = bin .find(b '\x83\xec\x18\xa1' )
code_401120 = bin [text_base + 0x120 :text_base + 0x120 + 697 ]
code_main = bin [text_base + 0xd0 :text_base + 0xd0 + 0x43 ]
serial_23 = bytearray(b 'KCTF-2024-CRACK-SUCCESS' )
for i in range ( 23 ):
shn = code_401120[i] & 7
serial_23[i] = ((serial_23[i] << ( 8 - shn))& 0xff ) | ((serial_23[i] >> shn)& 0xff )
serial = bytearray( 0x43 )
name = b 'KCTF'
xor_char = 0
for i in range ( 4 ):
xor_char ^ = name[i]
sep = (xor_char & 0xf ) * 2
j = 0
for i in range ( 0x43 ):
if i > = sep and i < sep + 23 :
serial[i] = serial_23[j]
j + = 1
else :
serial[i] = code_main[i]
xor_char = serial[ 66 ]
for i in range ( 0 , 66 ):
serial[i] ^ = xor_char
xor_char = 0
for i in range ( 66 ):
xor_char ^ = serial[i]
serial[ 66 ] ^ = xor_char
for i in range ( 697 ):
serial[i % 0x43 ] ^ = code_401120[i]
print (codecs.encode(serial, "hex" ))
|
更多【CTF对抗-KCTF 2024 第七题 星际移民 WriteUp】相关视频教程:www.yxfzedu.com