easyre 下载下来的程序打开并没有什么东西,用IDA打开,按Shift +F12 可以看到程序里的字符串
拿到flag
reverse1 下载下来的程序用IDA打开,按Shift +F12 查找程序里的字符串
看到这个this is the right flag!点进去跟进这个交叉引用
按F5 查看伪代码
看到 strncmp(Str1, Str2, v3) 它是拿输入的Str1和Str2比较,双击Str2跟进,看看Str2存的是什么数据
可以看到Str2存的是{hello_world},提交这个,是错的,回到伪代码里再看,看回那个for循环,它将”o”都变成”0”了
所以flag是flag{hell0_w0rld}
reverse2 下载下来的文件不是exe,用file命令看看是什么文件,是ELF,用strings命令解析一下,找到一个类似flag格式的东西{hacking_for_fun}
提交后是错的,用IDA打开,按Shift +F12 查找字符串
双击跟进这个字符串
按F5 查看伪代码
for循环里把”i”和”r”都变成了”1”
跟进flag,就是{hacking_for_fun}
把{hacking_for_fun}里的”i”和”r”都变成”1”就是flag了
新年快乐 附件用IDA打开,找不到什么东西,可能是加壳了,用脱壳软件打开看看
有一个UPXI壳,去掉后再用IDA打开,跟进字符串
按F5 查看伪代码
可以看到是拿Str1与Str2比较,跟进Str2,找不到东西,原来Str2是在上面用strcpy函数赋值的,为HappyNewYear!
flag{HappyNewYear]}
reverse3 附件看看有没有壳,没有壳,然后用IDA打开
跟进这个字符串,查看主函数伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int __cdecl main_0 (int argc, const char **argv, const char **envp) { size_t v3; const char *v4; size_t v5; char v7; char v8; signed int j; int i; signed int v11; char Destination[108 ]; char Str[28 ]; char v14[8 ]; for ( i = 0 ; i < 100 ; ++i ) { if ( (unsigned int )i >= 0x64 ) j____report_rangecheckfailure(); Destination[i] = 0 ; } sub_41132F("please enter the flag:" , v7); sub_411375("%20s" , (char )Str); v3 = j_strlen(Str); v4 = (const char *)sub_4110BE(Str, v3, v14); strncpy (Destination, v4, 0x28u ); v11 = j_strlen(Destination); for ( j = 0 ; j < v11; ++j ) Destination[j] += j; v5 = j_strlen(Destination); if ( !strncmp (Destination, Str2, v5) ) sub_41132F("rigth flag!\n" , v8); else sub_41132F("wrong flag!\n" , v8); return 0 ; }
看到哪个sub_4110BE()函数,并不知道是什么,跟进这个函数,查看伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 void *__cdecl sub_411AB0 (char *a1, unsigned int a2, int *a3) { int v4; int v5; int v6; int v7; int i; unsigned int v9; int v10; int v11; void *v12; char *v13; if ( !a1 || !a2 ) return 0 ; v9 = a2 / 3 ; if ( (int )(a2 / 3 ) % 3 ) ++v9; v10 = 4 * v9; *a3 = v10; v12 = malloc (v10 + 1 ); if ( !v12 ) return 0 ; j_memset(v12, 0 , v10 + 1 ); v13 = a1; v11 = a2; v4 = 0 ; while ( v11 > 0 ) { byte_41A144[2 ] = 0 ; byte_41A144[1 ] = 0 ; byte_41A144[0 ] = 0 ; for ( i = 0 ; i < 3 && v11 >= 1 ; ++i ) { byte_41A144[i] = *v13; --v11; ++v13; } if ( !i ) break ; switch ( i ) { case 1 : *((_BYTE *)v12 + v4) = aAbcdefghijklmn[(int )(unsigned __int8)byte_41A144[0 ] >> 2 ]; v5 = v4 + 1 ; *((_BYTE *)v12 + v5) = aAbcdefghijklmn[((byte_41A144[1 ] & 0xF0 ) >> 4 ) | (16 * (byte_41A144[0 ] & 3 ))]; *((_BYTE *)v12 + ++v5) = aAbcdefghijklmn[64 ]; *((_BYTE *)v12 + ++v5) = aAbcdefghijklmn[64 ]; v4 = v5 + 1 ; break ; case 2 : *((_BYTE *)v12 + v4) = aAbcdefghijklmn[(int )(unsigned __int8)byte_41A144[0 ] >> 2 ]; v6 = v4 + 1 ; *((_BYTE *)v12 + v6) = aAbcdefghijklmn[((byte_41A144[1 ] & 0xF0 ) >> 4 ) | (16 * (byte_41A144[0 ] & 3 ))]; *((_BYTE *)v12 + ++v6) = aAbcdefghijklmn[((byte_41A144[2 ] & 0xC0 ) >> 6 ) | (4 * (byte_41A144[1 ] & 0xF ))]; *((_BYTE *)v12 + ++v6) = aAbcdefghijklmn[64 ]; v4 = v6 + 1 ; break ; case 3 : *((_BYTE *)v12 + v4) = aAbcdefghijklmn[(int )(unsigned __int8)byte_41A144[0 ] >> 2 ]; v7 = v4 + 1 ; *((_BYTE *)v12 + v7) = aAbcdefghijklmn[((byte_41A144[1 ] & 0xF0 ) >> 4 ) | (16 * (byte_41A144[0 ] & 3 ))]; *((_BYTE *)v12 + ++v7) = aAbcdefghijklmn[((byte_41A144[2 ] & 0xC0 ) >> 6 ) | (4 * (byte_41A144[1 ] & 0xF ))]; *((_BYTE *)v12 + ++v7) = aAbcdefghijklmn[byte_41A144[2 ] & 0x3F ]; v4 = v7 + 1 ; break ; } } *((_BYTE *)v12 + v4) = 0 ; return v12; }
看到aAbcdefghijklmn这个数组,看它存的是什么东西
很明显是base64加密,这时看回Str2存的是什么
拿到了Str2,按照主函数的逻辑逆推flag就好了
1 2 3 4 5 6 import base64s = "e3nifIH9b_C@n@dH" x = "" for i in range (0 , len (s)): x += chr (ord (s[i])-i) print (base64.b64decode(x))
拿到flag{i_l0ve_you}
xor 附件用IDA64打开,查看主函数伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int __cdecl main (int argc, const char **argv, const char **envp) { int i; char __b[264 ]; memset (__b, 0 , 0x100u LL); printf ("Input your flag:\n" ); get_line(__b, 256LL ); if ( strlen (__b) != 33 ) goto LABEL_7; for ( i = 1 ; i < 33 ; ++i ) __b[i] ^= __b[i - 1 ]; if ( !strncmp (__b, global, 0x21u LL) ) printf ("Success" ); else LABEL_7: printf ("Failed" ); return 0 ; }
跟进global,看它存的是什么数据
拿到了数据,按照伪代码反向写脚本
1 2 3 4 5 6 7 8 9 s = ['f' , 0xA , 'k' , 0xC , 'w' , '&' , 'O' , '.' , '@' , 0x11 , 'x' , 0xD , 'Z' , ';' , 'U' , 0x11 , 'p' , 0x19 , 'F' , 0x1F , 'v' , '"' , 'M' , '#' , 'D' , 0xE , 'g' , 6 , 'h' , 0xF , 'G' , '2' , 'O' ] flag = 'f' for i in range (1 , len (s)): if (isinstance (s[i], int )): s[i] = chr (s[i]) for i in range (1 , len (s)): flag += chr (ord (s[i]) ^ ord (s[i-1 ])) print (flag)
flag{QianQiuWanDai_YiTongJiangHu}
不一样的flag 附件用IDA32打开,查看主函数伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 int __cdecl __noreturn main (int argc, const char **argv, const char **envp) { char v3[29 ]; int v4; int v5; int i; _BYTE v7[12 ]; __main(); v4 = 0 ; strcpy (v3, "*11110100001010000101111#" ); while ( 1 ) { puts ("you can choose one action to execute" ); puts ("1 up" ); puts ("2 down" ); puts ("3 left" ); printf ("4 right\n:" ); scanf ("%d" , &v5); if ( v5 == 2 ) { ++*(_DWORD *)&v3[25 ]; } else if ( v5 > 2 ) { if ( v5 == 3 ) { --v4; } else { if ( v5 != 4 ) LABEL_13: exit (1 ); ++v4; } } else { if ( v5 != 1 ) goto LABEL_13; --*(_DWORD *)&v3[25 ]; } for ( i = 0 ; i <= 1 ; ++i ){ if ( *(int *)&v3[4 * i + 25 ] < 0 || *(int *)&v3[4 * i + 25 ] > 4 ) exit (1 ); } if ( v7[5 * *(_DWORD *)&v3[25 ] - 41 + v4] == 49 ) exit (1 ); if ( v7[5 * *(_DWORD *)&v3[25 ] - 41 + v4] == 35 ) { puts ("\nok, the order you enter is the flag!" ); exit (0 ); } } }
打开程序,参照上面的源码,可以看出来这是一个迷宫,迷宫的地图就是上面的 *11110100001010000101111#
把地图按照5*5的格式排列
* 1 1 1 1
0 1 0 0 0
0 1 0 1 0
0 0 0 1 0
1 1 1 1 #
参照代码,0是路,1是墙,从*开始,到#结束,可以得到路径222441144222
flag{222441144222}
SimpleRev 附件用IDA64打开,查找字符串
跟进这两个字符串,查看Decry函数伪代码
这里有小端存储,可以认为是凡是需要手动转成字符串的字符串读取的时候都要倒序处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 unsigned __int64 Decry () { char v1; int v2; int v3; int i; int v5; char src[8 ]; __int64 v7; int v8; __int64 v9[2 ]; int v10; unsigned __int64 v11; v11 = __readfsqword(0x28u ); *(_QWORD *)src = 0x534C43444EL L; v7 = 0LL ; v8 = 0 ; v9[0 ] = 0x776F646168L L; v9[1 ] = 0LL ; v10 = 0 ; text = (char *)join(key3, v9); strcpy (key, key1); strcat (key, src); v2 = 0 ; v3 = 0 ; getchar(); v5 = strlen (key); for ( i = 0 ; i < v5; ++i ) { if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 ) key[i] = key[v3 % v5] + 32 ; ++v3; } printf ("Please input your flag:" ); while ( 1 ) { v1 = getchar(); if ( v1 == 10 ) break ; if ( v1 == 32 ) { ++v2; } else { if ( v1 <= 96 || v1 > 122 ) { if ( v1 > 64 && v1 <= 90 ) { str2[v2] = (v1 - 39 - key[v3 % v5] + 97 ) % 26 + 97 ; ++v3; } } else { str2[v2] = (v1 - 39 - key[v3 % v5] + 97 ) % 26 + 97 ; ++v3; } if ( !(v3 % v5) ) putchar (32 ); ++v2; } } if ( !strcmp (text, str2) ) puts ("Congratulation!\n" ); else puts ("Try again!\n" ); return __readfsqword(0x28u ) ^ v11; }
根据上面的逻辑,写脚本
1 2 3 4 5 6 7 8 9 10 key = "adsfkndcls" text = "killshadow" alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" flag = "" for i in range (0 , len (text)): for j in alphabet: if ((ord (j) - 39 - ord (key[i]) + 97 ) % 26 + 97 ) == ord (text[i]): flag += j print (flag)
flag{KLDQCUDFZO}