BUUCTF逆向工程-1
easyre
这题很水,拖进IDA就可以解出来
很明显,flag:this_Is_a_EaSyRe
reverse1
拖进IDA发现只有这么个东西
所以果断shift+F12从字符串寻找突破口,得到:
跟进可以进入到真正的主程序:
不难发现它将输入和Str2进行比较,并且在前面将Str2中的o变成了0,跟进Str2可以看见:
得到flag:hell0_w0rld
reverse2
比上一题仁慈,拽进IDA直接可以看代码:
将输入和flag作比较,并在之前把r和i变成1,跟进看见flag是:
得到flag:hack1ng_fo1_fun
内涵的软件
打开IDA可以看见v5这个抽象的玩意儿:
没错,这货就是答案,flag:49d3c93df25caad81232130f3d2ebfad
说实话,我不理解这题存在的意义
新年快乐
exeinfoPE告诉我它有壳并且可以使用自带的upx -d解决,所以就解决一下:
在拖入IDA可以看见主程序:
通过我们在小学二年级就学会的代码,可以读出来flag:HappyNewYear!
xor
拖进IDA可以看见:
它对输入进行了一通异或操作并且与global进行比较,将global提取出来异或回去即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> using namespace std;int main () { int key[99 ] = { 102 , 10 , 107 , 12 , 119 , 38 , 79 , 46 , 64 , 17 , 120 , 13 , 90 , 59 , 85 , 17 , 112 , 25 , 70 , 31 , 118 , 34 , 77 , 35 , 68 , 14 , 103 , 6 , 104 , 15 , 71 , 50 , 79 , 0 }; int i; for (i = 32 ; i >= 1 ; i--) { key[i] ^= key[i-1 ]; } for (i = 0 ; i <= 32 ; i++) { cout << char (key[i]); } return 0 ; }
得到flag:QianQiuWanDai_YiTongJiangHu
helloworld
打开APKIDE,找到主方法,可以看到:
得到flag:7631a988259a00816deda84afb29430a
reverse3
IDA里看见它对输入做了sub_4110BE操作,然后又做了一个简单的加法,最后和Str2比较:
点进sub_4110BE可以看见这么个抽象的东西:
看出这东西是个base64加密,搞一搞:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> using namespace std;int main () { int key[99 ] = { 101 , 51 , 110 , 105 , 102 , 73 , 72 , 57 , 98 , 95 , 67 , 64 , 110 , 64 , 100 , 72 }; int i; for (i = 0 ; i <= 15 ; i++) { key[i] -= i; cout << char (key[i]); } return 0 ; }
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 #include <iostream> #include <cstring> using namespace std;char base64[50 ];char base64char[100 ];int __cdecl base64_decode (char *base64, char *originChar) { int v2; int v3; int v4; unsigned __int8 temp[4 ]; unsigned __int8 k; int j; int i; i = 0 ; j = 0 ; while ( base64[i] ) { memset (temp, 255 , sizeof (temp)); for ( k = 0 ; k <= 0x3F u; ++k ) { if ( base64char[k] == base64[i] ) temp[0 ] = k; } for ( k = 0 ; k <= 0x3F u; ++k ) { if ( base64char[k] == base64[i + 1 ] ) temp[1 ] = k; } for ( k = 0 ; k <= 0x3F u; ++k ) { if ( base64char[k] == base64[i + 2 ] ) temp[2 ] = k; } for ( k = 0 ; k <= 0x3F u; ++k ) { if ( base64char[k] == base64[i + 3 ] ) temp[3 ] = k; } v2 = j++; originChar[v2] = (temp[1 ] >> 4 ) & 3 | (4 * temp[0 ]); if ( base64[i + 2 ] == 61 ) break ; v3 = j++; originChar[v3] = (temp[2 ] >> 2 ) & 0xF | (16 * temp[1 ]); if ( base64[i + 3 ] == 61 ) break ; v4 = j++; originChar[v4] = temp[3 ] & 0x3F | (temp[2 ] << 6 ); i += 4 ; } return j; } int main () { char de64[50 ]; int i; strcpy (base64, "e2lfbDB2ZV95b3V9" ); strcpy (base64char, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ); base64_decode (base64, de64); for (i = 0 ; i <= strlen (base64); i++) { cout << de64[i]; } return 0 ; }
得到flag:i_l0ve_you
不一样的flag
拖进IDA看见这个,可以推断是个迷宫题:
在最后可以看到结束条件是走到#
根据整体代码判断v3[25]是用来控制层数的,通过查阅v3的地址(00000035)和v7的地址(0000000C)恰好相差41可以推断最后它用来判断的v7就是v3,因此它的地图长这个样子:
*1111
01000
01010
00010
1111#
得到flag:222441144222
SimpleRev
打开IDA发现主要的加密在Decry函数中:
前面一段生成了key和text:
这里理论上下断点动调就可以得到最终结果,但是我动调会告诉我出现了一个奇奇怪怪的错误,所以我只好手动生成了,其中.elf采用逆序存储,因此需要反向解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string.h> using namespace std;int main () { long long v9 = 0x776F646168 ; long long src = 0x534C43444E ; int i; for (i = 0 ; i <= 4 ; i++) { cout << char (*((const char *)&v9 + i)); } cout << endl; for (i = 0 ; i <= 4 ; i++) { cout << char (*((const char *)&src + i)); } return 0 ; }
得到
text = “killshadow”
key = “adsfkndcls”
接下来就是依据输入对Str2进行操作:
可以写个深搜找到答案;
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 #include <iostream> #include <string.h> using namespace std;int main () { string text = "killshadow" ; string key = "adsfkndcls" ; int i, j, k; int v5 = key.size (); int tmp; for (i = 0 ; i <= 9 ; i++) { for (j = 65 ; j <= 122 ; j++) { if ((j >= 'a' && j <= 'z' ) || (j >= 'A' && j <= 'Z' )) { tmp = (j - 39 - key[i] + 97 ) % 26 + 97 ; if (tmp == text[i]) { cout << char (j); break ; } } } } return 0 ; }
得到flag:KLDQCUDFZO
其实这个地方很明显每一个大写输入其实都可以用一个小写字母代替,也可以达到相同的效果,这样的输入是efxkwoxzti。但是我不理解这题后续也没有相应的验证部分,为什么可以直接用大写的输入。。。
Java逆向解密
打开jd-gui可以看见:
这个hin简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> using namespace std;int main () { int ans[99 ] = {180 , 136 , 137 , 147 , 191 , 137 , 147 , 191 , 148 , 136 , 133 , 191 , 134 , 140 , 129 , 135 , 191 , 65 }; int i; for (i = 0 ; i < 18 ; i++) { ans[i] = (ans[i] ^ 0x20 ) - '@' ; cout << char (ans[i]); } return 0 ; }
得到flag:This_is_the_flag_!
[GXYCTF2019]luck_guy
这题点进去发现它会根据随机数除以200的余数进行操作:
但是随机数嘛,多半是假的,所以可以猜测一下他会按照case4,case5,case1的顺序运行,考虑到elf的逆序存储,搞一个脚本:
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 #include <iostream> #include <string.h> using namespace std;int main () { long long a = 0x7F666F6067756369 ; int i; char key2[99 ] = "" ; char key1[99 ] = "GXY{do_not_" ; for (i = 0 ; i <= 7 ; i++) { key2[i] = char (*((const char *)&a + i)); if (key2[i] % 2 == 1 ) { key2[i] -= 2 ; } else { key2[i]--; } } strcat (key1, key2); cout << key1; return 0 ; }
得到flag:do_not_gase_me
[BJDCTF2020]JustRE
拖进IDA里看见代码很抽象,所以shift+F12找到这个:
跟进可以看见这个:
得到flag:1999902069a45792d233ac
刮开有奖
点进去找到主函数:
v7到v16一看就是连在一起的,sub_4010F0对v7操作了一番,所以咱们也给它操作一番。sub_401000点进去发现是一个base64加密,所以写个解密脚本(要注意IDA里写的4*要删掉,那是电脑搜索int类型地址时使用的,因此会反编译出来,但是人类写的代码是不用的):
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 #include <iostream> #include <windows.h> using namespace std;int __cdecl sub_2F10F0 (int *a1, int a2, int a3) { int result; int i; int v5; int v6; result = a3; for ( i = a2; i <= a3; a2 = i ) { v5 = i; v6 = *(i + a1); if ( a2 < result && i < result ) { do { if ( v6 > *(a1 + result) ) { if ( i >= result ) break ; ++i; *(v5 + a1) = *(a1 + result); if ( i >= result ) break ; while ( *(a1 + i) <= v6 ) { if ( ++i >= result ) goto LABEL_13; } if ( i >= result ) break ; v5 = i; *(a1 + result) = *(i + a1); } --result; } while ( i < result ); } LABEL_13: *(a1 + result) = v6; sub_2F10F0 (a1, a2, i - 1 ); result = a3; ++i; } return result; } int main () { int v7[99 ]; v7[0 ] = 'Z' ; v7[1 ] = 'J' ; v7[2 ] = 'S' ; v7[3 ] = 'E' ; v7[4 ] = 'C' ; v7[5 ] = 'a' ; v7[6 ] = 'N' ; v7[7 ] = 'H' ; v7[8 ] = '3' ; v7[9 ] = 'n' ; v7[10 ] = 'g' ; sub_2F10F0 (v7, 0 , 10 ); int i; cout << char (v7[0 ] + 34 ); cout << char (v7[4 ]); cout << char ((v7[2 ] * 3 + 141 ) / 4 ); cout << char (v7[7 ] / 9 * 2 * 4 ); return 0 ; }
得到flag:UJWP1jMp
简单注册器
先在APKIDE中打开,让他把smail文件变成class文件,再用jd-jui打开,看见加密函数:
hiiiiiin简单的鸭子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string> using namespace std;int main () { string paramView = "dd2940c04462b4dd7c450528835cca15" ; paramView[2 ] = ((char )(paramView[2 ] + paramView[3 ] - 50 )); paramView[4 ] = ((char )(paramView[2 ] + paramView[5 ] - 48 )); paramView[30 ] = ((char )(paramView[31 ] + paramView[9 ] - 48 )); paramView[14 ] = ((char )(paramView[27 ] + paramView[28 ] - 97 )); for (int i = 0 ; i < 16 ; i++) { int temp = paramView[31 -i]; paramView[31 -i] = paramView[i]; paramView[i] = temp; } cout << paramView; return 0 ; }
得到flag:59acc538825054c7de4b26440c0999dd
pyre
在www.tool.lu/pyc/ 中打开pyc文件,可以将其变成py文件,但是内容嘛…
写一个简单的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> using namespace std;int main () { int ans[99 ] = {0x1f ,0x12 ,0x1d ,'(' ,'0' ,'4' ,0x01 ,0x06 ,0x14 ,'4' ,',' ,0x1b ,'U' ,'?' ,'o' ,'6' ,'*' ,':' ,1 ,'D' ,';' ,'%' ,0x13 }; for (int i = 21 ; i >= 0 ; i--) { ans[i] = ans[i] ^ ans[i+1 ]; } for (int i = 0 ; i < 23 ; i++) { for (int j = 32 ; j < 128 ; j++) { if ((j + i) % 128 % 128 == ans[i]) { cout << char (j); } } } return 0 ; }
得到flag:Just_Re_1s_Ha66y!
[ACTF新生赛2020]easyre
这题有壳,但是upx -d可以解决,所以脱以下子:
进去看见这个:
发现v10和v6应当是连在一起的,给他们make array一下:
之后使用我们在小学二年级就会的知识写个代码:
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 #include <iostream> using namespace std;int main () { int key[99 ] = {126 , 125 , 124 , 123 , 122 , 121 , 120 , 119 , 118 , 117 , 116 , 115 , 114 , 113 , 112 , 111 , 110 , 109 , 108 , 107 , 106 , 105 , 104 , 103 , 102 , 101 , 100 , 99 , 98 , 97 , 96 , 95 , 94 , 93 , 92 , 91 , 90 , 89 , 88 , 87 , 86 , 85 , 84 , 83 , 82 , 81 , 80 , 79 , 78 , 77 , 76 , 75 , 74 , 73 , 72 , 71 , 70 , 69 , 68 , 67 , 66 , 65 , 64 , 63 , 62 , 61 , 60 , 59 , 58 , 57 , 56 , 55 , 54 , 53 , 52 , 51 , 50 , 49 , 48 , 47 , 46 , 45 , 44 , 43 , 42 , 41 , 40 , 39 , 38 , 37 , 36 , 35 , 32 , 33 , 34 }; char ans[99 ] = "*F'\"N,\"(I?+@" ; int i, j; for (i = 0 ; i <= 11 ; i++) { for (j = 0 ; j <= 94 ; j++) { if (ans[i] == key[j]) { cout << char (j + 1 ); } } } return 0 ; }
得到flag:U9X_1S_W6@T?
findit
APKIDE弄出来的伪代码很奇怪,所以又找了一个高级的JEB用:、
是一个凯撒加密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> using namespace std;int main () { int ans[99 ] = {'p' , 'v' , 'k' , 'q' , '{' , 'm' , '1' , '6' , '4' , '6' , '7' , '5' , '2' , '6' , '2' , '0' , '3' , '3' , 'l' , '4' , 'm' , '4' , '9' , 'l' , 'n' , 'p' , '7' , 'p' , '9' , 'm' , 'n' , 'k' , '2' , '8' , 'k' , '7' , '5' , '}' }; for (int i = 0 ; i < 38 ; i++) { if (ans[i] >= 65 && ans[i] <= 90 || ans[i] >= 97 && ans[i] <= 0x7A ) { ans[i] += 16 ; if (ans[i] > 90 && ans[i] < 97 || ans[i] >= 0x7A ) { ans[i] -= 26 ; } } cout << char (ans[i]); } return 0 ; }
得到flag:c164675262033b4c49bdf7f9cda28a75
rsa
不是很能理解逆向里面放rsa的意图
得到flag:decrypt_256
[ACTF新生赛2020]rome
拖进IDA进行一个array的make和一个名字的改,得到这个东西:
在进行一个代码的写:
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 #include <iostream> using namespace std;int main () { char key[99 ] = "Qsw3sj_lz4_Ujw@l" ; int i, j, tmp; bool f; for (i = 0 ; i <= 15 ; i++) { f = true ; for (j = 65 ; j <= 122 ; j++) { if (j >= 'A' && j <= 'Z' ) { tmp = (j - 51 ) % 26 + 65 ; } if (j >= 'a' && j <= 'z' ) { tmp = (j - 79 ) % 26 + 97 ; } if (tmp == key[i]) { f = false ; cout << char (j); } } if (f == true ) { cout << key[i]; } } return 0 ; }
得到flag:Cae3ar_th4_Gre@t
[FlareOn4]login
我不理解,你逆向就好好逆向呗,搞个网页干什么…
边查代码边猜意思,写个脚本:
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 #include <iostream> using namespace std;int main () { char ans[99 ] = "PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" ; int i, j; int tmp, k; bool f; for (i = 0 ; i <= 35 ; i++) { f = true ; for (j = 32 ; j <= 122 ; j++) { if ((j >= 'a' && j <= 'z' ) || (j >= 'A' && j <= 'Z' )) { k = j; if (k <= 'Z' ) { tmp = 90 ; } else { tmp = 122 ; } k += 13 ; if (tmp < k) { k -= 26 ; } if (k == ans[i]) { cout << char (j); f = false ; } } } if (f == true ) { cout << ans[i]; } } return 0 ; }
得到flag:ClientSideLoginsAreEasy@flare-on.com
CrackRTF
很牛逼的一道题。进去可以看到又两次加密:
第一次是SHA1,且输入要求是大于100000的数,可以爆破,第二部分是MD5,其实也可以爆破www.somd5.com 很好用。但是题目的本意是跟踪sub_40100F():
经过百度,它是将一个叫AAA的资源与输入进行异或(在sub_401005()中),然后再将它怎么操作一番写入dbapp.rtf文件,推测文件的前几位就是rtf文件的文件头。可以写出脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import hashlibpasswd1 = "6e32d0943418c2c33385bc35a1470250dd8923a9" passwd2 = "27019e688a4e62a649fd99cadaafdb4e" suffix = "@DBApp" aaa = [0x5 , 0x7d , 0x41 , 0x15 , 0x26 , 0x1 ] rtf_header = [0x7b , 0x5c , 0x72 , 0x74 , 0x66 , 0x31 ] pass1 = "" pass2 = "" for i in range (100000 ,1000000 ): instr = str (i) + suffix res = hashlib.sha1(instr.encode('utf-8' )).hexdigest() if res == passwd1: pass1 = str (i) print ("passwd1 = " , pass1) break for i in range (6 ): res = aaa[i] ^ rtf_header[i] pass2 += chr (res) print ("passwd2 = " , pass2)
得到密码后运行一遍,在dbapp.rtf文件中得到flag:N0_M0re_Free_Bugs
但是它在创建文件的时候为什么会把flag写进去呢?在源代码中flag是以什么样的形式储存的呢?
[GUET-CTF2019]re
有壳,但是可以upx -d:
点进去通过shift+F12获取关键字,跳转到:
点进sub_4009AE函数,它会让你做32个乘法题,鼓捣鼓捣发现a1[6]不见了,所以爆破一下得到flag:e165421110ba03099a1c039337
[WUSTCTF2020]level1
拖进IDA发现:
再根据提供的输出文档,写一个简单的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> using namespace std;int main () { long long ans[99 ] = {0 ,198 ,232 ,816 ,200 ,1536 ,300 ,6144 ,984 ,51200 ,570 ,92160 ,1200 ,565248 ,756 ,1474560 ,800 ,6291456 ,1782 ,65536000 }; int i; for (i = 1 ; i <= 19 ; i++) { if ((i & 1 ) == 0 ) { cout << char (ans[i] / i); } else { cout << char (ans[i] >> i); } } return 0 ; }
得到flag:d9-dE6-20c
[2019红帽杯]easyRE
起始函数很抽象,shift+F12寻找特征字符串,跟进发现:
它做了10次base64加密,经过解密得到:https://bbs.pediy.com/thread-254172.htm
好,被骗了。。。
开始往前搜索信息:
把这一坨东西给他异或回去得到:Info:The first four chars are `flag`
怎么说呢,既有用,又没用。。。
不过在跟进off_6CC090中发现了这两个被函数调用过的给定数组:
跟进函数看见:
解读出v4这个东西异或之后首位是f,末位是g,推测整体异或之后是“flag”,反向把v4解出来,再讲for循环异或回去:
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 #include <iostream> using namespace std;int main () { int ans[99 ] = { 64 , 53 , 32 , 86 , 93 , 24 , 34 , 69 , 23 , 47 , 36 , 110 , 98 , 60 , 39 , 84 , 72 , 108 , 36 , 110 , 114 , 60 , 50 , 69 , 91 }; int i, tmp; int key[5 ]; char s[5 ] = "flag" ; for (i = 0 ; i <= 3 ; i++) { key[i] = ans[i] ^ s[i]; } for (i = 0 ; i <= 24 ; i++) { tmp = ans[i] ^ key[i % 4 ]; cout << char (tmp); } return 0 ; }
得到flag:Act1ve_Defen5e_Test
题出的很好,下次不要出了。
打开得到:
写出脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> using namespace std;int main () { int ans[99 ] = {103 , 121 , 123 , 127 , 117 , 43 , 60 , 82 , 83 , 121 , 87 , 94 , 93 , 66 , 123 , 45 , 42 , 102 , 66 , 126 , 76 , 87 , 121 , 65 , 107 , 126 , 101 , 60 , 92 , 69 , 111 , 98 , 77 }; int key[99 ] = {9 ,10 ,15 ,23 ,7 ,24 ,12 ,6 ,1 ,16 ,3 ,17 ,32 ,29 ,11 ,30 ,27 ,22 ,4 ,13 ,19 ,20 ,21 ,2 ,25 ,5 ,31 ,8 ,18 ,26 ,28 ,14 }; int flag[99 ]; int i; for (i = 0 ; i <= 32 ; i++) { ans[i] ^= key[i]; flag[key[i]] = ans[i]; } for (i = 0 ; i <= 32 ; i++) { cout << char (flag[i]); } return 0 ; }
得到flag:Tr4nsp0sltiON_Clph3r_1s_3z
[SUCTF2019]SignIn
这是个RSA,我不理解为什么要出这个。。。
flag:Pwn_@_hundred_years
[WUSTCTF2020]level2
有壳,但是可以upx -d,解决后进去即可得到flag:Just_upx_-d
[ACTF新生赛2020]usualCrypt
进去后可以分析出主加密函数在sub_401080
进去后很开心是个base64,直接解密得到乱码,观察发现函数开始和结尾分别有这两个诡异的东西:
一个更改密码表,一个更改结果,给它推回去:
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 #include <iostream> using namespace std;int main () { char key[99 ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; char ans[99 ] = "zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9" ; int i, tmp; for (i = 6 ; i < 15 ; i++) { tmp = key[i + 10 ]; key[i + 10 ] = key[i]; key[i] = tmp; } for (i = 0 ; i <= 35 ; i++) { if (ans[i] >= 'a' && ans[i] <= 'z' ) { ans[i] -= 32 ; } else { if (ans[i] >= 'A' && ans[i] <= 'Z' ) { ans[i] += 32 ; } } } for (i = 0 ; i <= 63 ; i++) { cout << key[i]; } cout << endl; for (i = 0 ; i <= 35 ; i++) { cout << ans[i]; } return 0 ; }
得到新的密码表:ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/
旧结果:ZmxhZ3tiGNXlXjHfaDTzN2FfK3LycRTpc2L9
拿着这两个东西解密得到flag:bAse64_h2s_a_Surprise
[HDCTF2019]Maze
有壳但是可以upx -d:
进去发现有一个花指令,给它nop掉:
正常编译后得到:
在跟进dword_408078和dword_40807C时顺带找出地图:
由起始坐标(7,0)和结束坐标(5,-4)在根据+和F的位置推出地图长这样:
*******+**
*******s**
****ssss**
**sss*****
**s**F****
**ssss****
**********
走一遍得到flag:ssaaasaassdddw
[MRCTF2020]Xor
进去F5发现IDA会报个错,跟进提示错误的函数先把它反编译出来,在回来反编译主函数就可以了。应该是IDA遇见了一个它不认识的东西,让他先认识一下就行了:
写个代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> using namespace std;int main () { int ans[99 ] = {77 , 83 , 65 , 87 , 66 , 126 , 70 , 88 , 90 , 58 , 74 , 58 , 96 , 116 , 81 , 74 , 34 , 78 , 64 , 32 , 98 , 112 , 100 , 100 , 125 , 56 , 103 }; int i; for (i = 0 ; i <= 26 ; i++) { ans[i] ^= i; cout << char (ans[i]); } return 0 ; }
得到flag:@_R3@1ly_E2_R3verse!
Youngter-drive
是一道多线程交替进行的题:
第一个线程是主加密函数:
可以写出解密脚本:
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 #include <iostream> #include <cstring> using namespace std;int main () { char ans[] = "TOiZiZtOrYaToUwPnToBsOaOapsyS" ; char key[] = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm" ; for (int i = 29 ; i > -1 ; i -= 2 ) { for (int j = 0 ; j < strlen (key); j++) { if (ans[i] == key[j]) { if (j + 38 >= 'A' && j + 38 <= 'Z' ) { ans[i] = j + 38 ; } else { ans[i] = j + 96 ; } break ; } } } cout << ans; return 0 ; }
得到:ThisisthreadofwindowshahaIsES。但是提交不对,经百度,可能题目哪里有那么一niuniu的小问题,需要最后加一个E才能通过。
得到flag:ThisisthreadofwindowshahaIsESE