前言:在分析代码的时候常遇到不好逆向的逻辑,如求余(%)等,下面就是含有求余的两道逆向题目
例题一:buuctf [ACTF新生赛2020]rome 1.查壳
无壳32位exe.2.ida32打开并分析main函数 发现主要函数 func()
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 int func () { int result; int v1; int v2; int v3; int v4; unsigned __int8 v5; unsigned __int8 v6; unsigned __int8 v7; unsigned __int8 v8; unsigned __int8 v9; int v10; int v11; int v12; int v13; unsigned __int8 v14; char v15; char v16; char v17; char v18; char v19; char v20; char v21; char v22; char v23; char v24; char v25; char v26; char v27; char v28; char v29; char v30; char v31; int i; v15 = 81 ; v16 = 115 ; v17 = 119 ; v18 = 51 ; v19 = 115 ; v20 = 106 ; v21 = 95 ; v22 = 108 ; v23 = 122 ; v24 = 52 ; v25 = 95 ; v26 = 85 ; v27 = 106 ; v28 = 119 ; v29 = 64 ; v30 = 108 ; v31 = 0 ; printf ("Please input:" ); scanf ("%s" , &v5); result = v5; if ( v5 == 65 ) { result = v6; if ( v6 == 67 ) { result = v7; if ( v7 == 84 ) { result = v8; if ( v8 == 70 ) { result = v9; if ( v9 == 123 ) { result = v14; if ( v14 == 125 ) { v1 = v10; v2 = v11; v3 = v12; v4 = v13; for ( i = 0 ; i <= 15 ; ++i ) { if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51 ) % 26 + 65 ; if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79 ) % 26 + 97 ; } for ( i = 0 ; i <= 15 ; ++i ) { result = (unsigned __int8)*(&v15 + i); if ( *((_BYTE *)&v1 + i) != (_BYTE)result ) return result; } result = printf ("You are correct!" ); } } } } } } return result; }
函数逻辑大概就是:一个字符组v1[ ]经过一系列变化,最后再与v15[ ]的进行比较是否相等 脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 v15=[81 ,115 ,119 ,51 ,115 ,106 ,95 ,108 ,122 ,52 ,95 ,85 ,106 ,119 ,64 ,108 ] flag='' for i in range (len (v15)): for j in range (0 ,127 ): a=j if (j>64 and j<=90 ): j=(j-51 )%26 +65 if (j>96 and j<=122 ): j=(j-79 )%26 +97 if (j==v15[i]): flag+=chr (a) print (flag)
flag{Cae3ar_th4_Gre@t} 目的就是让数据经过上面的处理得到新数据,如果新数据和v15【】相等,那么就取它的值
buuctf SimpleRev 1.查壳 elf64位文件,2.用ida64打开,分析main函数 跟进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 unsigned __int64 Decry () { char v1; int v2; int v3; int i; int v5; char src[8 ]; __int64 v7; int v8; __int64 v9; __int64 v10; int v11; unsigned __int64 v12; v12 = __readfsqword(0x28 u); *(_QWORD *)src = 'SLCDN' ; #记得大端序和小端序,下同。 v7 = 0LL ; v8 = 0 ; v9 = 'wodah' ; v10 = 0LL ; v11 = 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:" , src); 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 ; } else { str2[v2] = (v1 - 39 - key[v3++ % v5] + 97 ) % 26 + 97 ; } if ( !(v3 % v5) ) putchar (32 ); ++v2; } } if ( !strcmp (text, str2) ) puts ("Congratulation!\n" ); else puts ("Try again!\n" ); return __readfsqword(0x28 u) ^ v12; }
大致逻辑是:将输入的v1经过处理和text【】进行比较是否相等。 发现处理过程有 % 操作,所以考虑用暴力破解。 脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 text = 'killshadow' key = 'adsfkndcls' v3=0 v5=len (key) dict1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" flag = "" for i in range (0 ,10 ): n=0 for char in dict1: x = (ord (char) - 39 - ord (key[v3%v5])+97 )%26 +97 if (chr (x)==text[i]): n = n+1 if (n==1 ): print (char,end="" ) v3=v3+1
flag{KLDQCUDFZO}
总结: 1.在有结果的时候,并且逆向逻辑比较困难是可以考虑用暴力破解 2.字符串不是很长时,也可以考虑暴力破解