攻防世界逆向高手题之EasyRE
继续开启全栈梦想之逆向之旅~
这题是攻防世界逆向高手题的EasyRE
下载附件,照例扔入exeinfope中查看信息:
64位ELF文件,无壳,照例扔入IDA64中查看信息,有Main函数就看main函数:(PS:下面被我注释了一下内容,不过不影响)
照例分析代码:
puts(input); //这里名称被我重命名过,判断依据是程序运行时的Input字符串在这里被引用,所以这里是输出函数
v12 = 0;
v13 = 0;
*(_OWORD *)input_flag = '\0';
v11 = '\0';
sub_401050("%s", input_flag);
v3 = strlen(input_flag);
if ( v3 >= 16 && v3 == 24 ) // 这里两个条件其实是多余的,输入flag等于24即可
{
v4 = 0;
v5 = (char *)&v11 + 7; // v5取v11的64位地址下面的7位地址处,这里的(char*)只是对地址转换,并没有取地址的数,也就是说v5还是地址,而且后7位刚好是input_flag开始的24个字节范围的末尾,就是我们输入24字节flag的最后一个。 PS:这里之所以是v11地址的下面7位处是因为这是在main函数内的栈,栈是从下到上的(从高地址到底地址),栈变量都是从第一个分配地址往下划分内存的,后面会再讲~
do
{
v6 = *v5--; // 从v5开始取,然后减一个地址,v5现在是input_flag的起始地址开始的24字节的末尾了指针了,也就是指向用户输入字符串的最后一个字符,这里循环24次,符合前面我们输入input_flag长度为24的判断条件。
byte_40336C[v4++] = v6; //这里把v6的值也就是我们inpu_flag末尾位置的值开始,一个个赋值给v4开头,这就造成了v4是我们输入24位flag的反向字符,后续对v4数组操作也是对用户输入的24字符flag的反向操作。
}
while ( v4 < 24 );
for ( i = 0; i < 24; ++i )
byte_40336C[i] = (byte_40336C[i] + 1) ^ 6;// 赋完值之后有对自身进行异或操作,进一步修改,注意这里是我们输入的24位字符的反向数组
v8 = strcmp(byte_40336C, aXircjR2twsv3pt); // 异或完后简单的比较,aXircjR2twsv3pt双击跟踪后一个被/x7f截断的字符串,前18位是xIrCj~<r|2tWsv3PtI,发现不满足24位后再查看才发现后面还有,第19位是/x7f,20~24是zndka。这里留个心眼,/x7f可以阻断字符串
if ( v8 )
v8 = v8 < 0 ? -1 : 1;
if ( !v8 )
{
puts("right\n");
system("pause");
}
}
return 0;
}
分析完了,附上图回顾一下以前犯错的思路,给自己日后提个醒:
犯下第一个错误是对关键数组地址修改的地方不敏感,一开始我只看到了对v4数组异或的代码:
for ( i = 0; i < 24; ++i )
byte_81336C[i] = (byte_81336C[i] + 1) ^ 6;
结果逆向逻辑出来后的flag是反的,大概长这样:}NsDkw9sy3qPto4UqNx{galf,可能还是能看出来是反的flag,单要是换其他字符串就不一定了。所以我们应该要注意前面还有对v4操作的代码,也要分析:(分析在前面)
if ( v3 >= 16 && v3 == 24 )
{
v4 = 0;
v5 = (char *)&v11 + 7;
do
{
v6 = *v5--;
byte_81336C[v4++] = v6;
}
while ( v4 < 24 );
犯下第二个错误就是对栈不熟练,就是基于对前面v4数组操作的分析,才发现这里有个栈操作让v4数组反向获取用户输入的字符串:
之前在IDA权威指南中了解过栈视图,这里v11是var_14,input_flag就是我们输入24位字符串的首地址,这里给了一个混淆就是v11,前面v5 = (char *)&v11 + 7;就是在v11地址往下取7位,就是0D了,刚好在var_C前面,input_flag首地址24到var_C前面0D处就是完整的24位input_flag地址,所以这里v11的过渡作用混淆了我,我们可以直接在栈中把v11删除,改input_flag为24位字符串,这里也就解释了v4数组取input_flag反向字符的原因了:
犯下第三个错误是在写脚本中发现的,减号的优先级高于^符号,下面脚本中 flag+=chr((ord(data[i]) ^ 6)-1) #要是写成chr((ord(data[i]) ^ 6 - 1)那就GG了,由于优先级不同所以结果会不同,给的警示是最好什么都用括号括起来,毕竟这种优先级问题是很难发现的,还以为是自己逻辑梳理错误呢。
data="xIrCj~<r|2tWsv3PtI\x7Fzndka"
flag=""
for i in range(24):
flag+=chr((ord(data[i])^6)-1)
print(flag)
print(flag[::-1])
结果:
总结:
1:
犯下第一个错误是对关键数组地址修改的地方不敏感,一开始我只看到了对v4数组异或的代码,结果逆向逻辑出来后的flag是反的,大概长这样:}NsDkw9sy3qPto4UqNx{galf,可能还是能看出来是反的flag,单要是换其他字符串就不一定了。所以我们应该要注意前面还有对v4操作的代码,也要分析!
2:犯下第二个错误就是对栈不熟练,就是基于对前面v4数组操作的分析,才发现这里有个栈操作让v4数组反向获取用户输入的字符串。之前在IDA权威指南中了解过栈视图,这里v11是var_14,input_flag就是我们输入24位字符串的首地址,这里给了一个混淆就是v11,前面v5 = (char *)&v11 + 7;就是在v11地址往下取7位,就是0D了,刚好在var_C前面,input_flag首地址24到var_C前面0D处就是完整的24位input_flag地址,所以这里v11的过渡作用混淆了我,我们可以直接在栈中把v11删除,改input_flag为24位字符串,这里也就解释了v4数组取input_flag反向字符的原因了。
3:犯下第三个错误是在写脚本中发现的,减号的优先级高于^符号,下面脚本中 flag+=chr((ord(data[i]) ^ 6)-1) 要是写成chr((ord(data[i]) ^ 6 - 1)那就GG了,由于优先级不同所以结果会不同,给的警示是最好什么都用括号括起来,毕竟这种优先级问题是很难发现的,还以为是自己逻辑梳理错误呢。
解毕!敬礼!