攻防世界-逆向-难度3
幻想成为ctf糕手的第七天
insanity
32位无壳
ida打开,查看字符串看到9447{This_is_a_flag}
game
刚打开运行,按顺序输入1-8就得到flag了。。。
32位无壳
ida打开,字符串中找到关键词,双击进入,找到该函数
在最下面for循环中,可以看到有异或
v2:22字节的数组,前2字节是"{ “,后续字节为硬编码值
v3:32字节的数组,前12字节是"S,yhn _uec{”`,后续字节为硬编码值
循环56次(i从0到55),对v2[i]进行两次异或操作
v2[i] ^= v5[i](用v5的对应字节解密)
v2[i] ^= 0x13(再次异或固定值0x13)
最后调用sub_45A7BE(“%s\n”)输出解密后的v2
int sub_45E940() { int i; // [esp+D0h] [ebp-94h] char v2[22]; // [esp+DCh] [ebp-88h] BYREF char v3[32]; // [esp+F2h] [ebp-72h] BYREF char v4[4]; // [esp+112h] [ebp-52h] BYREF char v5[64]; // [esp+120h] [ebp-44h] sub_45A7BE("done!!! the flag is "); v5[0] = 18; v5[1] = 64; v5[2] = 98; v5[3] = 5; v5[4] = 2; v5[5] = 4; v5[6] = 6; v5[7] = 3; v5[8] = 6; v5[9] = 48; v5[10] = 49; v5[11] = 65; v5[12] = 32; v5[13] = 12; v5[14] = 48; v5[15] = 65; v5[16] = 31; v5[17] = 78; v5[18] = 62; v5[19] = 32; v5[20] = 49; v5[21] = 32; v5[22] = 1; v5[23] = 57; v5[24] = 96; v5[25] = 3; v5[26] = 21; v5[27] = 9; v5[28] = 4; v5[29] = 62; v5[30] = 3; v5[31] = 5; v5[32] = 4; v5[33] = 1; v5[34] = 2; v5[35] = 3; v5[36] = 44; v5[37] = 65; v5[38] = 78; v5[39] = 32; v5[40] = 16; v5[41] = 97; v5[42] = 54; v5[43] = 16; v5[44] = 44; v5[45] = 52; v5[46] = 32; v5[47] = 64; v5[48] = 89; v5[49] = 45; v5[50] = 32; v5[51] = 65; v5[52] = 15; v5[53] = 34; v5[54] = 18; v5[55] = 16; v5[56] = 0; qmemcpy(v2, "{ ", 2); v2[2] = 18; v2[3] = 98; v2[4] = 119; v2[5] = 108; v2[6] = 65; v2[7] = 41; v2[8] = 124; v2[9] = 80; v2[10] = 125; v2[11] = 38; v2[12] = 124; v2[13] = 111; v2[14] = 74; v2[15] = 49; v2[16] = 83; v2[17] = 108; v2[18] = 94; v2[19] = 108; v2[20] = 84; v2[21] = 6; qmemcpy(v3, "`S,yhn _uec{", 12); v3[12] = 127; v3[13] = 119; v3[14] = 96; v3[15] = 48; v3[16] = 107; v3[17] = 71; v3[18] = 92; v3[19] = 29; v3[20] = 81; v3[21] = 107; v3[22] = 90; v3[23] = 85; v3[24] = 64; v3[25] = 12; v3[26] = 43; v3[27] = 76; v3[28] = 86; v3[29] = 13; v3[30] = 114; v3[31] = 1; strcpy(v4, "u~"); for ( i = 0; i < 56; ++i ) { v2[i] ^= v5[i]; v2[i] ^= 0x13u; } return sub_45A7BE("%s\n"); }使用python代码得到flag
v6=[18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]v3=([123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6]+list(b'`S,yhn _uec{')+[127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1]+list(b'u~'))flag_bytes=[]foriinrange(56):decrypted=v3[i]^v6[i]^0x13flag_bytes.append(decrypted)print(bytes(flag_bytes).decode())#zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}open-source
打开可以看到代码
在主函数中,可以看到argc!=4,会输出 what? 应该是报错的意思吧,所以arcg应该=4,但是这个arcg在后面的hash运算时用不上
- 第二段if也是一样 的道理,可以看出first应该=0xcafe
- 第三段if则需要两个式子都为假 second % 5 == 3为假,或者second % 17 != 8为假即second % 5 != 3 and second % 17== 8
- 第三段是和"h4cky0u"比较,所以 argv[3]=h4cky0u
最后再经过运算 first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207即可得到flag
#include<stdio.h>#include<string.h>intmain(intargc,char*argv[]){if(argc!=4){printf("what?\n");exit(1);}unsignedintfirst=atoi(argv[1]);if(first!=0xcafe){printf("you are wrong, sorry.\n");exit(2);}unsignedintsecond=atoi(argv[2]);if(second%5==3||second%17!=8){printf("ha, you won't get it!\n");exit(3);}if(strcmp("h4cky0u",argv[3])){printf("so close, dude!\n");exit(4);}printf("Brr wrrr grr\n");unsignedinthash=first*31337+(second%17)*11+strlen(argv[3])-1615810207;printf("Get your key: ");printf("%x\n",hash);return0;}脚本如下,second也可以只取随便一个满足条件的数
first=0xcafethird="h4cky0u"flag=[]forsecondinrange(101):ifsecond%5!=3andsecond%17==8:hash_value=first*31337+(second%17)*11+len(third)-1615810207flag.append(hex(hash_value)[2:])print(flag)#['c0ffee', 'c0ffee', 'c0ffee', 'c0ffee']simple-unpack
32位upx壳
使用upx脱壳,丢到ida里面
进入直接能看到flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}
