pwnable.tw的calc和pwnable.kr的memcpy难度提升得让我突然像是到了一片知识的孤岛上,举目所望是无尽的未知。才发现自己的汇编基础实在薄弱,另外只通过0day安全分析学了windows的堆管理,对linux的堆管理实在是所知甚少,鉴于此,在补足基础的时候,打算做一下bugku上的逆向维持一下基本的做题感觉。
bugku逆向的前三题都是用IDA打开就看到答案了,所以从游戏过关这一题开始。
用IDA打开,搜索main,没看到,搜索_main查到主函数。
一进主函数就看到
sub_45A7BE((int)&unk_50B110, v21);
sub_45A7BE((int)&unk_50B158, v3);
sub_45A7BE((int)&unk_50B1A0, v4);
sub_45A7BE((int)&unk_50B1E8, v5);
sub_45A7BE((int)&unk_50B230, v6);
sub_45A7BE((int)&unk_50B278, v7);
sub_45A7BE((int)&unk_50B2C0, v8);
sub_45A7BE((int)&unk_50B308, v9);
sub_45A7BE((int)&unk_50AFD0, v10);
sub_45A7BE((int)"| by 0x61 |\n", v11);
sub_45A7BE((int)"| |\n", v12);
sub_45A7BE((int)"|------------------------------------------------------|\n", v13);
sub_45A7BE(
(int)"Play a game\n"
"The n is the serial number of the lamp,and m is the state of the lamp\n"
"If m of the Nth lamp is 1,it's on ,if not it's off\n"
"At first all the lights were closed\n",
v14);
这样一篇看不懂的代码,sub_45A7BE竟然还Decompliation failure,直接打开程序知道了是一个把黑灯全转化成亮灯的游戏。
顺着main函数查看
while ( 1 )
{
sub_45A7BE((int)"input n,n(1-8)\n", v22);
sub_459418();
sub_45A7BE((int)"n=", v19);
sub_4596D4("%d", &v24);
sub_45A7BE((int)"\n", v20);
if ( v24 >= 0 && v24 <= 8 )
break;
sub_45A7BE((int)"sorry,n error,try again\n", v22);
}
if ( v24 )
{
sub_4576D6(v24 - 1);
}
else
{
for ( i = 0; i < 8; ++i )
{
if ( (unsigned int)i >= 9 )
j____report_rangecheckfailure(a1, a2, a3);
byte_532E28[i] = 0;
}
}
通过sub_4596D4知道了v24就是我们输入的值,else就是重置游戏,通过byte_532E28[i]=0知道0是关灯的状态,那main函数最后的if语句就是判断游戏胜利的条件了。
if ( byte_532E28[0] == 1
&& byte_532E28[1] == 1
&& byte_532E28[2] == 1
&& byte_532E28[3] == 1
&& byte_532E28[4] == 1
&& byte_532E28[5] == 1
&& byte_532E28[6] == 1
&& byte_532E28[7] == 1 )
{
sub_457AB4();
}
跟进sub_457AB4,看到一百多个从v3-v116的参数,后面跟着一个函数
for ( i = 0; i < 56; ++i )
{
*(&v3 + i) ^= *(&v60 + i);
*(&v3 + i) ^= 0x13u;
}
return sub_45A7BE((int)"%s\n", (unsigned int)&v3);
明白了这114个参数分成两组进行异或运算,最后再和0x13异或。
把一百多个参数直接复制到nodepad++里面,然后按着alt选择前面几列删除,把分号替换成逗号,在这114行数字前加上a=[,末尾加上],就变成了一个python列表了
for i in range(0,56):
print(chr((a[i]^a[i+57])^19))
加上一个循环,成功输出flag
其实这道题并没有怎么顺着分析。。点开main函数顶部的unk_50B110,碰巧在数据段内发现flag
.rdata:0050B0F0 aDoneTheFlagIs db 'done!!! the flag is ',0
.rdata:0050B0F0 ; DATA XREF: sub_45E940+28↑o
.rdata:0050B105 db 0
.rdata:0050B106 db 0
.rdata:0050B107 db 0
.rdata:0050B108 db 0
.rdata:0050B109 db 0
.rdata:0050B10A db 0
.rdata:0050B10B db 0
.rdata:0050B10C aS db '%s',0Ah,0 ; DATA XREF: sub_45E940+288↑o
.rdata:0050B110 unk_50B110 db 20h ; DATA XREF: _main_0+1E↑o
然后右键选择Xrefs graph to就发现了sub_45E940调用了这个字段,搜索到这个函数后一路倒着进入了main函数,就明白了flag怎么得到了。