题目来源: 游戏过关 - Bugku CTF
挺简单的一道签到题. 直接动态调试拿内存就行.
IDA静态分析
f5拿到伪代码
拖到IDA里打开, f5转伪代码, 一直跟踪函数跳转, 直到进入主函数_main_0
. 得到程序主循环, 其代码大致如下:
void __cdecl main_0()
{
//...
while ( 1 )
{
while ( 1 )
{
sub_CCA7BE("input n,n(1-8)\n");
sub_CC9418();
sub_CCA7BE("n=");
sub_CC96D4("%d", &v1);
sub_CCA7BE("\n");
if ( v1 >= 0 && v1 <= 8 )
break;
sub_CCA7BE("sorry,n error,try again\n");
}
if ( v1 )
{
sub_CC76D6(v1 - 1);
}
else
{
for ( i = 0; i < 8; ++i )
{
if ( (unsigned int)i >= 9 )
j____report_rangecheckfailure();
byte_DA2E28[i] = 0;
}
}
j__system("CLS");
sub_CC8054();
if ( byte_DA2E28[0] == 1 && byte_DA2E28[1] == 1 && byte_DA2E28[2] == 1 && byte_DA2E28[3] == 1 && byte_DA2E28[4] == 1 && byte_DA2E28[5] == 1 && byte_DA2E28[6] == 1 && byte_DA2E28[7] == 1 )
{
sub_CC7AB4(); // 这里极有可能是打印flag的函数
}
}
}
直接跳到函数sub_CC7AB4
, 一直追踪函数跳转情况, 得到关键代码如下所示:
int sub_CCE940()
{
//...
for ( i = 0; i < 56; ++i )
{
*(&v2 + i) ^= *(&v59 + i);
*(&v2 + i) ^= 0x13u;
}
return sub_CCA7BE("%s\n");
}
此处即为打印flag的函数. 尝试使用x32dbg动态调试程序, 将内存里的flag数据拿出来.
动态调试
使用x32dbg加载程序, 在"内存布局"窗口查看代码段的基址,在IDA的edit->segments->rebase program处设置基址, 找到上文所述的函数sub_CC7AB4
的地址, 在x32dbg中跳转到该地址, 在函数返回处设置断点.
在x32dbg中右键选择"设置新的运行点", 把EIP指到上述函数的循环体的起始处, 点击运行, 其会运行到返回语句处断掉, 此时即可在寄存器窗口看到flag
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}