第一次在论坛发帖,多有不慎,还请多多包涵,如有错误,还请不吝见教!
这个题实在假如用ida7.5来反编译实在很简单,但是这里我是ida7.0,多少有些问题,以是直接在汇编层面来解决,趁便锻炼了我的汇编阅读能力,本人技能很菜,如有错误,还望师傅们不吝见教,谢谢!
先看到main函数,找到经过判断之后的关键函数:
这里看到传进来三个参数,但是在函数内里没有 用的这些参数,而且还有一些奇观的函数,这里判断应该是低版本的ida反编译了高版本的编译器编译的程序,以是直接在gdb内里看到汇编代码,直接对汇编举行分析。
先看到这是main函数在调用关键函数的时候的汇编代码
不难看出他只传进去了两个参数,这里看到[rbp-0x8]是我输入,$rsi内里是给出的加密字符串【DASCTF{5c715207e3abed7dfb7c8ea9c82d0e29}】
看到关键函数的汇编:
这里直接把我参数的内容保存下来,【rbp-0x38】是我的输入。
往下看:
这里解析出来了我ida内里没有解析出来的函数,我们把ida修补下:
修完的效果。
接下来就是确定关键函数的参数和这些局部变量的关系,以此来找到关键操作:
首先看前两行直到我们的输入被保存在了两个局部变量内里,然后看到:
相称于是【[rbp-0x20]=malloc(0x80) [rbp-0x20]=我的输入】
以是我的输入的放在了rbp-0x20指向的空间里
因为函数调用规则是从右到左,以是这里应该是:
rsi=[rax-0x7]//去除flag头的flag
rdi=[rbp-0x20]//输入
strcpy(rdi,rsi);
这里看到有一个[rax+0x7],这里是把我输入的flag的头去了,就剩中心的东西了
根据关键的异或,往上往下找到循环异或的代码块:
对其举行分析
0x00005555555553ca : mov eax,DWORD PTR [rbp-0x24] 0x00005555555553cd : movsxd rdx,eax #这里eax是计数器i,放到rdx的低位 0x00005555555553d0 : mov rax,QWORD PTR [rbp-0x20] #将输入放进rax内里 0x00005555555553d4 : add rax,rdx #rax+rdx就相称于array[i++]的意思,基地址+偏移 0x00005555555553d7 : movzx esi,BYTE PTR [rax] #给esi赋值,后面异或用到 0x00005555555553da : mov rdx,QWORD PTR [rip+0x2c2f] # 0x555555558010 0x00005555555553e1 : mov eax,DWORD PTR [rbp-0x24] 0x00005555555553e4 : cdqe 0x00005555555553e6 : add rax,rdx #和上面一样,这里是【偏移量+段地址】 0x00005555555553e9 : movzx ecx,BYTE PTR [rax] #较小的值拷贝给大的值,剩下0填充例如【0x00000xxxx】 0x00005555555553ec : mov eax,DWORD PTR [rbp-0x24] 0x00005555555553ef : movsxd rdx,eax 0x00005555555553f2 : mov rax,QWORD PTR [rbp-0x20] 0x00005555555553f6 : add rax,rdx #原理同上,这里rax指向了输入的第位 0x00005555555553f9 : xor esi,ecx //关键异或 0x00005555555553fb : mov edx,esi #结果保存在edx内里 0x00005555555553fd : mov BYTE PTR [rax],dl 0x00005555555553ff : add DWORD PTR [rbp-0x24],0x1 //计数器+1 0x0000555555555403 : mov eax,DWORD PTR [rbp-0x24] #计数器+1给到eax 0x0000555555555406 : movsxd rbx,eax #相称于计数器的值给到rbx的低八位 0x0000555555555409 : mov rax,QWORD PTR [rbp-0x20] #再把输入放进eax内里,规复eax在【】的状态 0x000055555555540d : mov rdi,rax #把指向输入字符的指针给rdi,当参数给strlen 0x0000555555555410 : call 0x555555555100 //返回输入字符串的长度 0x0000555555555415 : cmp rbx,rax #当前计数器的值(rbx)和strlen返回值rax比较 0x0000555555555418 : jb 0x5555555553ca #回到循环头 #rbx小于rax就跳,也就是说:计数器小于字符串长度就继续执行这里看到有一个变量:【rbp-0x24】,【rbp-0x20】,【rip+0x2c2f】。
【rbp-0x24】:这是计数器【i】;
赋初始值为0;
抑或完+1。
【rbp-0x20】:输入的字符串也就是flag在循环完事之后就是存放输入经过循环的结果
【rip+0x2c2f】:这里存放的是异或用的数组
看具体的异或过程,到底是谁和谁在异或:
0x00005555555553f9 : xor esi,ecx //关键异或对象是esi和ecx,看到对esi的操作:
就是输入的每一位。
看到ecx的操作:
总结:我输入的和给出的数组举行按位异或
关键循环分析完毕,在看到下面的代码:
0x000055555555541a : mov rcx,QWORD PTR [rip+0x2bff] # 0x555555558020 0x0000555555555421 : mov rdx,QWORD PTR [rbp-0x18] #rdx==mallco(0x80),给出的flag 0x0000555555555425 : mov rax,QWORD PTR [rbp-0x20] #输入经过循环异或的flag 0x0000555555555429 : mov rsi,rdx 0x000055555555542c : mov rdi,rax #传参 0x000055555555542f : call rcx #跳到rcx指向的地址, 0x0000555555555431 : add rsp,0x38 #堆栈平衡,函数预备结束 0x0000555555555435 : pop rbx 0x0000555555555436 : pop rbp 0x0000555555555437 : ret #函数结束发现有一个[rbp-0x18],没有出现在循环异或的程序里,往上看一下:
发现也是一个雷同于[rbp-0x20]的结构,相称于【[rbp-0x18]=mallco(0x80)】
动态调试发现rcx就是一个strcmp函数,比较的是 输入经过循环之后的值 和 一开始给出的值 是否相称。
相称返回1
这题就解了。
然后下载了ida7.5来验证自己的思绪,发现每一个函数都判断正确,但是在最后的call rcx那里还需要再完善一下。
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |