这题flag长度29,切成4部分,分4步验证:
简单的亦或操作:
int v5[5];
v5[0] = 61;
v5[1] = 11;
v5[2] = 95;
v5[3] = 8;
v5[4] = 67;
int i=8;
for(int j=0;j<5;j++){
cout<<(v5[j]^110)<<" "<<(char)(v5[j]^110)<<" ";
}
第三步验证,这一步作为OD动态调试试手我觉得挺好的
image.png
这里v11,v12都是可以直接知道的,check数组在这里直接看不出,但是动态调试的时候就可以发现它其实是"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"(这串字符在IDA里直接看到的会少了个A)
image.png
这里的主要操作就是将接下来的9位flag每三位通过4个运算去切取check然后存到v13中去,每3位flag生成4位,具体是这样的
t=0;
v13[t++]=check[(第一个 >> 2) & 0x3f]
v13[t++]=check[(第二个 >> 4 ) & 0xf | 16 * (第一个 & 3)]
v13[t++]=check[4 * (第二个 & 0xF) | (第三个 >> 6) & 3]
v13[t++]=check[第三个 & 0x3f]
然后是验证切出来的12位
image.png
这里的&v11[1] 我一开始以为是v11[1]的低8位(因为v11是已知的,下意识的就想用现成的)但是其实v11[1]做为一个地址,这里我们需要从OD动态调试取得数据
image.png
EDX存的就是 &v11[1] + v9 了单步12次拿出来跟上面的计算就可以写出脚本了,这里我用了比较笨的方法选择3个3个跑
for(int i=32;i<=126;i++){
for(int j=32;j<=126;j++){
for(int k=32;k<=126;k++){
if(check[(i >> 2) & 0x3f]==(char)a[0]){
if(check[(j >> 4) & 0xf | 16 * (i & 3)] == (char)a[1]){
if(check[4 * (j & 0xf) | (k >> 6) & 3] == (char)a[2]){
if(check[k & 0x3f]==(char)a[3]){
cout<<(char)i<<" "<<(char)j<<" "<<(char)k<<endl;
}
}
}
}
}
}
}
接下来最后一步验证,也需要从OD中获得数据
image.png
跟第三步一样动态跑出 &v3 + result -22 就行了
image.png
记下EBX的6个数据
int a[6]={0x61,0x65,0x32,0x66,0x67,0x23};
for(int i=0;i<6;i++)
cout<<(char)(a[i]-2)<<" ";
结合四步跑出来的flag就是 gxnnctf{Se1f-M0difying_c0de!}
网友评论