这一题卡了很久,因为之前没遇到过这种题型,特此记录一下
前面很简单,第一次的输入异或上i等于比较数据,提取数据进行异或即可得到输入
#include <stdio.h>
int main() {
unsigned char data[36] = {
0x49, 0x6F, 0x64, 0x6C, 0x3E, 0x51, 0x6E, 0x62, 0x28, 0x6F, 0x63, 0x79, 0x7F, 0x79, 0x2E, 0x69,
0x7F, 0x64, 0x60, 0x33, 0x77, 0x7D, 0x77, 0x65, 0x6B, 0x39, 0x7B, 0x69, 0x79, 0x3D, 0x7E, 0x79,
0x4C, 0x40, 0x45, 0x43};
for(int j=0;j<36;j++)
{
printf("%c",data[j]^j);
}
return 0;
}
input1=“Info:The first four chars are `flag`”,提醒我们输入的前四个是flag。接着往下
第一次输入正确后会提醒continue,v16存储第二次的输入,长度要求是39个字节,接下来是对数据进行十次相同的操作,点进函数观察很容易可以看到base64的那个表,就算没看出来也能从比较数据哪里看出来大概率是base64编码,提取比较数据进行十次base64 得到一个网址:https://bbs.pediy.com/thread-254172.htm
很明显被骗了,查看评论区发现很多同行。接下来就是煎熬了,因为我一般遇到的base64题目,如果想上点难度的话就是反调试换表,但是这个题目我按下x查看base64的表发现啥都没有
于是乎卡了非常久,搜索了很久放弃了这个想法。
在后来的调试中发现比较数据附近有一个数据比较可以 查看它的引用之后跟进了这样一个函数
但是很离谱,这个函数根本就没有在main函数被调用,我以为他会藏在某个函数的角落被调用,然后在这个函数内部下满了断点都无济于事。但是重大发现是在 经过第二次检测后,不论有没有输入正确,都会在返回之后跳转到这个函数
在这里之后f8,然后点击ida的绿色箭头就会击中刚才在那个可以函数下的断点。再接着就陷入了僵局,因为脑子里还是想着这道题和反调试有关系,然后又在这个函数里看到了sys_time函数,更觉得这是根据程序运行速度判断程序是否被调试从而进行反调试的类型了,最终陷入了死局。在翻阅wp之后,没了反调试这个干扰之后还是比较容易分析的。
有两个点应该比较好判断,cpdata是比较数据,然后v4数组是一个密钥,长度为4字节,从下面的j%4就可以看出他是对整段数据进行循环的异或,接下来的要点就是得到v4,根据上面的if判断,cpdata第一个数据异或上v1的末八位 是字符 ' f ',hibyte提取v1/v4前八位异或上cpdata的第四个数据是 'g ',其实到这里看到f和g出现在第一第四位ctfer们的新应该是激动的,结合前面的提示头四字节是flag,然后根据cpdata的前四个数据异或得到密钥
#include <stdio.h>
int main() {
unsigned char cpdata[4] = {0x40, 0x35, 0x20, 0x56};
char flag[]="flag";
for(int i=0;i<4;i++)
{
printf("%c",cpdata[i]^flag[i]);
}
return 0;
}
//&YA1
然后根据密钥进行异或即可得到flag
#include <stdio.h>
int main() {
unsigned char cpdata[25] = {
0x40, 0x35, 0x20, 0x56, 0x5D, 0x18, 0x22, 0x45, 0x17, 0x2F, 0x24, 0x6E, 0x62, 0x3C, 0x27, 0x54,
0x48, 0x6C, 0x24, 0x6E, 0x72, 0x3C, 0x32, 0x45, 0x5B};
char key[]="&YA1";
for(int i=0;i<=24;i++)
{
printf("%c",cpdata[i]^key[i%4]);
}
return 0;
}
//flag{Act1ve_Defen5e_Test}
在做完这道题目之后我陷入了沉思,在这道题目上少说耗费了一天半的时间,我不理解这题的原理是什么,在网上查看很多师傅的wp也没看到有解释的,最后在微信公众号查到了官方wp
敲重点:init、fini
在函数列表的开头和结尾 确实出现了两个函数一个位于init节区,一个位于fini节区,当然这不是特有的,在elf的可执行程序中都是存在的,但一般张这个样子
在本题中,他长这个样子
以后做题可以多留意这一块。