一道CTF逆向题,首先查壳为无壳,运行程序如下图,
直接用OD动态分析,
首先在地址0X401047处接收输入的flag,地址0X401050处计算输入flag的长度,保存在寄存器EAX。地址0X401058处判断flag的长度,只有小于0X1E才正确,这里大胆猜测flag的长度应该为0X1D位。
在地址OX4010F5处循环4次比较输入的flag前四位是否为"EIS{",循环4次后在0X4010DA处跳转到OX401120处,所以得知flag前四位为"EIS{"。
在地址0X401124处比较flag的第0X1D位是否ASCII码是否为0X7D,即‘}’,所以可以得知flag的长度为0X1D,即十进制的29位。可以看出在地址0X40115E处若跳转则显示正确(congratulations!)。所以地址0X40114F处为关键算法函数,
以下反汇编是将输入的字符串字符进行大小写转换大写转小写,小写转大写。
地址0X4013C0处函数对字符串进一步处理,将字符与55进行异或,然后再加48,地址0X401397处将被处理的字符串与"GONDPHyGjPEKruv{{pj]X@rF"进行比较。相同则正确。
知道了算法,然后用C语言编写了代码来计算flag:
#include<stdio.h> int main() { int a,b,c; int x[38]={0x47,0x4f ,0x4E ,0x44 ,0x50 ,0x48 ,0x79 ,0x47 ,0x6A ,0x50 ,0x45 ,0x4B ,0x72 ,0x75 ,0x76 ,0x7B,0x7B ,0x70 ,0x6A ,0x5D ,0x58 ,0x40 ,0x72 ,0x46}; int y[38]={0xd,0x13 ,0x17 ,0x11 ,0x02 ,0x01 ,0x20 ,0x1D ,0x0C ,0x02 ,0x19 ,0x2F ,0x17 ,0x2B ,0x24 ,0x1F ,0x1E ,0x16 ,0x09 ,0x0F ,0x15 ,0x27 ,0x13 ,0x26}; printf("EIS{"); for(int i=0;i<=23;i++) { c=x[i]^y[i]; b=c-0x48; b=b^0x55; if((b>=0x61)&&(b<=0x7a)) printf("%c\n",b-0x20); else if((b>=0x41)&&(b<=0x5a)) printf("%c",b+0x20); else printf("%c",b); } printf("}"); return 0; }
在IDA中找到函数然后F5分析伪代码看看:
其实我这里对于IDA中的伪代码看起来很费劲,感觉没有OD动态分析来得清楚,都说IDA强大,不知道各位有没有什么技巧看这个伪代码呢?