想写点什么却又不知该写什么, 就写写BUUOJ的逆向题解记录吧
easyre
链接: https://buuoj.cn/challenges#easyre
EXE 64
IDA中 main 函数反编译结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 int __cdecl main (int argc, const char **argv, const char **envp) { int b; int a; _main(); scanf ("%d%d" , &a, &b); if ( a == b ) printf ("flag{this_Is_a_EaSyRe}" ); else printf ("sorry,you can't get flag" ); return 0 ; }
输入两个一样的数字即输出flag
flag{this_Is_a_EaSyRe}
reverse1
链接: https://buuoj.cn/challenges#reverse1
EXE 64
IDA中 sub_1400118C0 函数反编译结果如下
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 __int64 sub_1400118C0 () { char *v0; signed __int64 i; size_t v2; size_t v3; char v5; int j; char Str1; unsigned __int64 v8; v0 = &v5; for ( i = 82 i64; i; --i ) { *(_DWORD *)v0 = 0xCCCCCCCC ; v0 += 4 ; } for ( j = 0 ; ; ++j ) { v8 = j; v2 = j_strlen(Str2); if ( v8 > v2 ) break ; if ( Str2[j] == 111 ) Str2[j] = 48 ; } sub_1400111D1((__int64)"input the flag:" ); sub_14001128F("%20s" , &Str1); v3 = j_strlen(Str2); if ( !strncmp (&Str1, Str2, v3) ) sub_1400111D1((__int64)"this is the right flag!\n" ); else sub_1400111D1((__int64)"wrong flag\n" ); sub_14001113B(&v5, &unk_140019D00); return 0 i64; }
其中Str2="{hello_world}"
, 而函数在遍历Str2时, 会把'o'(111)
替换为'0'(49)
, 最后将用户的输入(Str1)与Str2进行比较
flag{hell0_w0rld}
reverse2
链接: https://buuoj.cn/challenges#reverse2
ELF 64
IDA中 main 函数反编译结果如下
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 int __cdecl main (int argc, const char **argv, const char **envp) { int result; int stat_loc; int i; __pid_t pid; char s2; unsigned __int64 v8; v8 = __readfsqword(0x28 u); pid = fork(); if ( pid ) { argv = (const char **)&stat_loc; waitpid(pid, &stat_loc, 0 ); } else { for ( i = 0 ; i <= strlen (&flag); ++i ) { if ( *(&flag + i) == 105 || *(&flag + i) == 114 ) *(&flag + i) = 49 ; } } printf ("input the flag:" , argv); __isoc99_scanf("%20s" , &s2); if ( !strcmp (&flag, &s2) ) result = puts ("this is the right flag!" ); else result = puts ("wrong flag!" ); return result; }
其中flag="{hacking_for_fun}"
, 函数在遍历flag时会将'i'(105)
和'r'(114)
替换为'1'(49)
flag{hack1ng_fo1_fun}
内涵的软件
链接: https://buuoj.cn/challenges#内涵的软件
EXE 32
IDA中 main_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 int main_0 () { int result; char v1; const char *v2; int v3; v3 = 5 ; v2 = "DBAPP{49d3c93df25caad81232130f3d2ebfad}" ; while ( v3 >= 0 ) { printf (aD, v3); sub_40100A(); --v3; } printf ( "\n" "\n" "\n" "这里本来应该是答案的,但是粗心的程序员忘记把变量写进来了,你要不逆向试试看:(Y/N)\n" ); v1 = 1 ; scanf ("%c" , &v1); if ( v1 == 89 ) { printf (aOdIda); result = sub_40100A(); } else { if ( v1 == 78 ) printf (asc_425034); else printf ("输入错误,没有提示." ); result = sub_40100A(); } return result; }
flag{49d3c93df25caad81232130f3d2ebfad}
新年快乐
链接: https://buuoj.cn/challenges#新年快乐
EXE 32
1 2 file 新年快乐.exe 新年快乐.exe: PE32 executable (console) Intel 80386, for MS Windows, UPX compressed
存在UPX壳
脱壳
1 2 3 4 5 6 7 8 9 10 upx -d 新年快乐.exe Ultimate Packer for eXecutables Copyright (C) 1996 - 2020 UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020 File size Ratio Format Name -------------------- ------ ----------- ----------- 27807 <- 21151 76.06% win32/pe 新年快乐.exe Unpacked 1 file.
IDA中 _main 函数反编译结果如下
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 result; char v4; __int16 v5; __int16 v6; __main(); strcpy (&v4, "HappyNewYear!" ); v5 = 0 ; memset (&v6, 0 , 0x1E u); printf ("please input the true flag:" ); scanf ("%s" , &v5); if ( !strncmp ((const char *)&v5, &v4, strlen (&v4)) ) result = puts ("this is true flag!" ); else result = puts ("wrong!" ); return result; }
flag{HappyNewYear!}
helloword
链接: https://buuoj.cn/challenges#helloword
Android
使用Android Studio打开
在java->com.example->helloworld->MainActivity
中得到flag
flag{7631a988259a00816deda84afb29430a}
xor
链接: https://buuoj.cn/challenges#xor
EXE 64
IDA中 _main 函数反编译结果如下
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 int __cdecl main (int argc, const char **argv, const char **envp) { char *v3; int result; signed int i; char v6[264 ]; __int64 v7; memset (v6, 0 , 0x100 uLL); v3 = (char *)256 ; printf ("Input your flag:\n" , 0LL ); get_line(v6, 256LL ); if ( strlen (v6) != 33 ) goto LABEL_12; for ( i = 1 ; i < 33 ; ++i ) v6[i] ^= v6[i - 1 ]; v3 = global; if ( !strncmp (v6, global, 0x21 uLL) ) printf ("Success" , v3); else LABEL_12: printf ("Failed" , v3); result = __stack_chk_guard; if ( __stack_chk_guard == v7 ) result = 0 ; return result; }
1 2 3 4 5 6 _global = [ 0x66 , 0x0A , 0x6B , 0x0C , 0x77 , 0x26 , 0x4F , 0x2E , 0x40 , 0x11 , 0x78 , 0x0D , 0x5A , 0x3B , 0x55 , 0x11 , 0x70 , 0x19 , 0x46 , 0x1F , 0x76 , 0x22 , 0x4D , 0x23 , 0x44 , 0x0E , 0x67 , 0x06 , 0x68 , 0x0F , 0x47 , 0x32 , 0x4F ]
用户输入经过异或操作后与global相比较, 则global为加密后的flag
解密脚本如下
1 2 3 4 5 6 7 8 9 10 cipher = [ 0x66 , 0x0A , 0x6B , 0x0C , 0x77 , 0x26 , 0x4F , 0x2E , 0x40 , 0x11 , 0x78 , 0x0D , 0x5A , 0x3B , 0x55 , 0x11 , 0x70 , 0x19 , 0x46 , 0x1F , 0x76 , 0x22 , 0x4D , 0x23 , 0x44 , 0x0E , 0x67 , 0x06 , 0x68 , 0x0F , 0x47 , 0x32 , 0x4F ]flag = chr (cipher[0 ]) for i in range (1 , len (cipher)): flag += chr (cipher[i]^cipher[i-1 ]) print(flag)
flag{QianQiuWanDai_YiTongJiangHu}
reverse3
链接: https://buuoj.cn/challenges#reverse3
EXE 32
IDA中 _main_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 __int64 main_0 () { size_t v0; const char *v1; size_t v2; int v3; __int64 v4; signed int j; signed int i; signed int v8; char Dest[108 ]; char Str; char v11; for ( i = 0 ; i < 100 ; ++i ) { if ( (unsigned int )i >= 0x64 ) j____report_rangecheckfailure(); Dest[i] = 0 ; } sub_41132F("please enter the flag:" ); sub_411375("%20s" , &Str); v0 = j_strlen(&Str); v1 = (const char *)sub_4110BE(&Str, v0, &v11); strncpy (Dest, v1, 0x28 u); v8 = j_strlen(Dest); for ( j = 0 ; j < v8; ++j ) Dest[j] += j; v2 = j_strlen(Dest); if ( !strncmp (Dest, Str2, v2) ) sub_41132F("rigth flag!\n" ); else sub_41132F("wrong flag!\n" ); HIDWORD(v4) = v3; LODWORD(v4) = 0 ; return v4; }
Str2 = "e3nifIH9b_C@n@dH"
1 2 3 4 5 6 cipher="e3nifIH9b_C@n@dH" string = "" for i in range (len (cipher)): string += chr (ord (cipher[i])-i) print(string)
解密得到字符串e2lfbDB2ZV95b3V9
在观察函数可以看到用户输入的字符串经过了函数sub_4110BE
的处理
跟进函数可以看到一个字符串
1 aAbcdefghijklmn="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
可以判断内容为Base64字符集, 即函数功能为Base64编码
1 2 echo -n "e2lfbDB2ZV95b3V9" | base64 -d{i_l0ve_you}
flag{i_l0ve_you}
不一样的flag
链接: https://buuoj.cn/challenges#不一样的flag
EXE 32
IDA中 _main 函数反编译结果如下
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 int __cdecl main (int argc, const char **argv, const char **envp) { char v3; int v4; int v5; signed int v6; int i; int v8; __main(); v4 = 0 ; v5 = 0 ; qmemcpy(&v3, _data_start__, 0x19 u); 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" , &v6); if ( v6 == 2 ) { ++v4; } else if ( v6 > 2 ) { if ( v6 == 3 ) { --v5; } else { if ( v6 != 4 ) LABEL_13: exit (1 ); ++v5; } } else { if ( v6 != 1 ) goto LABEL_13; --v4; } for ( i = 0 ; i <= 1 ; ++i ) { if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 ) exit (1 ); } if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41 ) == 49 ) exit (1 ); if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41 ) == 35 ) { puts ("\nok, the order you enter is the flag!" ); exit (0 ); } } }
输入"1234"分别对应上下左右, v4为Y轴, v5为X轴
这段代码用于检测Y轴与X轴的值是否在[0, 4]这个范围内
(v4, v5使用连续的内存空间, 目测是数组, 所以*(&v4 + i)可以指向v5)
1 2 3 4 5 for ( i = 0 ; i <= 1 ; ++i ){ if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 ) exit (1 ); }
_data_start__="*11110100001010000101111#"
且该值被赋给v3, v3为字符数组且开始内存为[esp+17h]
当v4 v5为0时, *((_BYTE *)&v8 + 5 * v4 + v5 - 41)
指向地址为[esp+17h], 即v3的开始内存
则通过v4与v5的值可以控制内存的指向, 可以画出迷宫地图
1 2 3 4 5 6 7 maze = """ * 1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 1 1 1 1 # """
当*((_BYTE *)&v8 + 5 * v4 + v5 - 41)
指向的值为'1'(49)
时, 程序退出
当*((_BYTE *)&v8 + 5 * v4 + v5 - 41)
指向的值为'#'(35)
时, 则走出迷宫
则可以得出flag
flag{222441144222}
SimpleRev
链接: https://buuoj.cn/challenges#SimpleRev
ELF 64
IDA中 main 函数反编译结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int __cdecl __noreturn main (int argc, const char **argv, const char **envp) { int v3; char v4; while ( 1 ) { while ( 1 ) { printf ("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: " , argv, envp); v4 = getchar(); if ( v4 != 100 && v4 != 68 ) break ; Decry(); } if ( v4 == 113 || v4 == 81 ) Exit(); puts ("Input fault format!" ); v3 = getchar(); putchar (v3); } }
跟进 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 = 357761762382LL ; v7 = 0LL ; v8 = 0 ; v9 = 512969957736LL ; 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; }
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97
key与str2的值已知, 则可以爆破v1
1 2 3 4 5 6 7 8 9 10 11 import stringstr2 = "killshadow" key = "adsfkndcls" flag = "" for _ in range (len (key)): for i in range (128 ): if ord (str2[_]) == (i-39 -ord (key[_])+97 )%26 +97 : if chr (i) in string.ascii_uppercase: flag += chr (i) print(flag)
实际爆破时, 会出现除了大写字母之外的其他结果, 但是本题的flag为大写字母
flag{KLDQCUDFZO}
Java逆向解密
链接: https://buuoj.cn/challenges#Java逆向解密
Java
jd-gui中反编译结果如下
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 import java.io.PrintStream;import java.util.ArrayList;import java.util.Scanner;public class Reverse { public static void main (String[] args) { Scanner s = new Scanner(System.in); System.out.println("Please input the flag :" ); String str = s.next(); System.out.println("Your input is :" ); System.out.println(str); char [] stringArr = str.toCharArray(); Encrypt(stringArr); } public static void Encrypt (char [] arr) { ArrayList Resultlist = new ArrayList(); for (int i = 0 ; i < arr.length; ++i) { int result = arr[i] + '@' ^ 0x20 ; Resultlist.add(Integer.valueOf(result)); } int [] KEY = { 180 , 136 , 137 , 147 , 191 , 137 , 147 , 191 , 148 , 136 , 133 , 191 , 134 , 140 , 129 , 135 , 191 , 65 }; ArrayList KEYList = new ArrayList(); for (int j = 0 ; j < KEY.length; ++j) { KEYList.add(Integer.valueOf(KEY[j])); } System.out.println("Result:" ); if (Resultlist.equals(KEYList)) System.out.println("Congratulations!" ); else System.err.println("Error!" ); } }
1 2 3 4 5 6 key = [180 , 136 , 137 , 147 , 191 , 137 , 147 , 191 , 148 , 136 , 133 , 191 , 134 , 140 , 129 , 135 , 191 , 65 ] flag = "" for i in range (len (key)): flag += chr ((key[i]-ord ('@' ))^0x20 ) print(flag)
flag{This_is_the_flag_!}
刮开有奖
链接: https://buuoj.cn/challenges#刮开有奖
EXE 32
IDA中 DialogFunc 函数反编译结果如下
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 BOOL __stdcall DialogFunc (HWND hDlg, UINT a2, WPARAM a3, LPARAM a4) { const char *v4; const char *v5; int v7; int v8; int v9; int v10; int v11; int v12; int v13; int v14; int v15; int v16; int v17; CHAR String; char v19; char v20; char v21; char v22; char v23; char v24; char v25; char v26; char v27; char v28; if ( a2 == 272 ) return 1 ; if ( a2 != 273 ) return 0 ; if ( (_WORD)a3 == 1001 ) { memset (&String, 0 , 0xFFFF u); GetDlgItemTextA(hDlg, 1000 , &String, 0xFFFF ); if ( strlen (&String) == 8 ) { v7 = 90 ; v8 = 74 ; v9 = 83 ; v10 = 69 ; v11 = 67 ; v12 = 97 ; v13 = 78 ; v14 = 72 ; v15 = 51 ; v16 = 110 ; v17 = 103 ; sub_4010F0(&v7, 0 , 10 ); memset (&v26, 0 , 0xFFFF u); v26 = v23; v28 = v25; v27 = v24; v4 = (const char *)sub_401000(&v26, strlen (&v26)); memset (&v26, 0 , 0xFFFF u); v27 = v21; v26 = v20; v28 = v22; v5 = (const char *)sub_401000(&v26, strlen (&v26)); if ( String == v7 + 34 && v19 == v11 && 4 * v20 - 141 == 3 * v9 && v21 / 4 == 2 * (v14 / 9 ) && !strcmp (v4, "ak1w" ) && !strcmp (v5, "V1Ax" ) ) { MessageBoxA(hDlg, "U g3t 1T!" , "@_@" , 0 ); } } return 0 ; } if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 ) return 0 ; EndDialog(hDlg, (unsigned __int16)a3); return 1 ; }
v7-v17为数组, String到v25为数组, v26到v28为数组
1 int arr_1 = {90 , 74 , 83 , 69 , 67 , 97 , 78 , 72 , 51 , 110 , 103 };
跟进 sub_4010F0 函数
代码逻辑有些复杂, 这里可以反编译代码之后修改成C语言代码再运行, 得出arr_1经过函数处理的结果
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 #include <stdio.h> int sub_4010F0 (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 = a1[i]; if ( a2 < result && i < result ) { do { if ( v6 > a1[result] ) { if ( i >= result ) break ; ++i; a1[v5] = a1[result]; if ( i >= result ) break ; while ( a1[i] <= v6 ) { if ( ++i >= result ) goto LABEL_13; } if ( i >= result ) break ; v5 = i; a1[result] = a1[i]; } --result; } while ( i < result ); } LABEL_13: a1[result] = v6; sub_4010F0(a1, a2, i - 1 ); result = a3; ++i; } return result; } int main () { int i; int arr_1[] = {90 , 74 , 83 , 69 , 67 , 97 , 78 , 72 , 51 , 110 , 103 }; sub_4010F0(arr_1, 0 , 10 ); for (i = 0 ; i < 11 ; i++) { printf ("%d " , arr_1[i]); } }
得到的结果为
1 51 67 69 72 74 78 83 90 97 103 110
后续的代码中有对于用户输入的校验
String == v7 + 34
v19 == v11
4 * v20 - 141 == 3 * v9
v21 / 4 == 2 * (v14 / 9)
!strcmp(v4, "ak1w")
!strcmp(v5, "V1Ax")
即
arr_2[0] == arr_1[0]+34
, arr_2[0] == 85
arr_2[1] == arr_1[4]
, arr_2[1] == 74
arr_2[2] == (3*arr_1[2]+141)/4
, arr_2[2] == 87
arr_2[3] == arr_1[7]/9*2*4
, arr_2[3] == 80
得出flag前四位为"UJWP"
sub_401000(arr_2[5:8]) == "ak1w"
sub_401000(arr_2[2:5]) == "V1Ax"
目测是Base64
1 2 3 4 5 echo -n "ak1w" | base64 -djMp echo -n "V1Ax" | base64 -dWP1
flag{UJWP1jMp}
[GXYCTF2019]luck_guy
链接: https://buuoj.cn/challenges#[GXYCTF2019]luck_guy
EXE 64
IDA中 get_flag 函数反编译结果如下
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 unsigned __int64 get_flag () { unsigned int v0; char v1; signed int i; signed int j; unsigned __int64 s; char v6; unsigned __int64 v7; v7 = __readfsqword(0x28 u); v0 = time(0LL ); srand(v0); for ( i = 0 ; i <= 4 ; ++i ) { switch ( rand() % 200 ) { case 1 : puts ("OK, it's flag:" ); memset (&s, 0 , 0x28 uLL); strcat ((char *)&s, f1); strcat ((char *)&s, &f2); printf ("%s" , &s); break ; case 2 : printf ("Solar not like you" ); break ; case 3 : printf ("Solar want a girlfriend" ); break ; case 4 : v6 = 0 ; s = 0x7F666F6067756369 LL; strcat (&f2, (const char *)&s); break ; case 5 : for ( j = 0 ; j <= 7 ; ++j ) { if ( j % 2 == 1 ) v1 = *(&f2 + j) - 2 ; else v1 = *(&f2 + j) - 1 ; *(&f2 + j) = v1; } break ; default : puts ("emmm,you can't find flag 23333" ); break ; } } return __readfsqword(0x28 u) ^ v7; }
f2为空字符串, f1="GXY{do_not_"
在case 4中对f2进行拼接字符串, 拼接内容为0x7F666F6067756369LL
(小端排序)
在case 5中对f2进行处理
在case 1中将f1, f2进行拼接并输出flag
1 2 3 4 5 6 7 8 9 flag = "GXY{do_not_" f2 = [0x7F , 0x66 , 0x6F , 0x60 , 0x67 , 0x75 , 0x63 , 0x69 ][::-1 ] for _ in range (len (f2)): if _ % 2 == 1 : flag += chr (f2[_]-2 ); else : flag += chr (f2[_]-1 ); print(flag)
flag{do_not_hate_me}
findit
链接: https://buuoj.cn/challenges#findit
Android
修改后缀名为zip, 提取classes.dex
使用dex2jar转为jar包
在jd-gui中反编译得到java代码
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 package com.example.findit;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.text.Editable;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends ActionBarActivity { protected void onCreate (Bundle paramBundle) { super .onCreate(paramBundle); setContentView(2130903064 ); paramBundle = (Button)findViewById(2131034173 ); EditText localEditText = (EditText)findViewById(2131034174 ); TextView localTextView = (TextView)findViewById(2131034175 ); paramBundle.setOnClickListener(new View.OnClickListener(new char [] { 84 , 104 , 105 , 115 , 73 , 115 , 84 , 104 , 101 , 70 , 108 , 97 , 103 , 72 , 111 , 109 , 101 }, localEditText, new char [] { 112 , 118 , 107 , 113 , 123 , 109 , 49 , 54 , 52 , 54 , 55 , 53 , 50 , 54 , 50 , 48 , 51 , 51 , 108 , 52 , 109 , 52 , 57 , 108 , 110 , 112 , 55 , 112 , 57 , 109 , 110 , 107 , 50 , 56 , 107 , 55 , 53 , 125 }, localTextView) { public void onClick (View paramView) { paramView = new char [17 ]; char [] arrayOfChar = new char [38 ]; int i = 0 ; if (i >= 17 ) { label12: if (!(String.valueOf(paramView).equals(this .val$edit.getText().toString()))) break label308; i = 0 ; if (i >= 38 ) { label42: paramView = String.valueOf(arrayOfChar); this .val$text.setText(paramView); return ; } } else { if (((this .val$a[i] < 'I' ) && (this .val$a[i] >= 'A' )) || ((this .val$a[i] < 'i' ) && (this .val$a[i] >= 'a' ))) paramView[i] = (char )(this .val$a[i] + '\18' ); while (true ) { i += 1 ; break label12: if (((this .val$a[i] >= 'A' ) && (this .val$a[i] <= 'Z' )) || ((this .val$a[i] >= 'a' ) && (this .val$a[i] <= 'z' ))) paramView[i] = (char )(this .val$a[i] - '\b' ); paramView[i] = this .val$a[i]; } } if (((this .val$b[i] >= 'A' ) && (this .val$b[i] <= 'Z' )) || ((this .val$b[i] >= 'a' ) && (this .val$b[i] <= 'z' ))) { arrayOfChar[i] = (char )(this .val$b[i] + '\16' ); if (((arrayOfChar[i] > 'Z' ) && (arrayOfChar[i] < 'a' )) || (arrayOfChar[i] >= 'z' )) arrayOfChar[i] = (char )(arrayOfChar[i] - '\26' ); } while (true ) { i += 1 ; break label42: arrayOfChar[i] = this .val$b[i]; } label308: this .val$text.setText("答案错了肿么办。。。不给你又不好意思。。。哎呀好纠结啊~~~" ); } }); } public boolean onOptionsItemSelected (MenuItem paramMenuItem) { if (paramMenuItem.getItemId() == 2131034176 ) return true ; return super .onOptionsItemSelected(paramMenuItem); } }
第一个字符串内容为"ThisIsTheFlagHome"
第二个字符串内容为"pvkq{m164675262033l4m49lnp7p9mnk28k75}"
目测是凯撒加密, 爆破即可得到flag
flag{c164675262033b4c49bdf7f9cda28a75}
简单注册器
链接: https://buuoj.cn/challenges#简单注册器
Android
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 public void onClick (View paramView) { int j = 1 ; paramView = this .val$editview.getText().toString(); if ((paramView.length() != 32 ) || (paramView.charAt(31 ) != 'a' ) || (paramView.charAt(1 ) != 'b' ) || (paramView.charAt(0 ) + paramView.charAt(2 ) - 48 != 56 )) j = 0 ; if (j == 1 ) { paramView = "dd2940c04462b4dd7c450528835cca15" .toCharArray(); 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 ); j = 0 ; while (true ) { if (j >= 16 ) { paramView = String.valueOf(paramView); this .val$textview.setText("flag{" + paramView + "}" ); return ; } int i = paramView[(31 - j)]; paramView[(31 - j)] = paramView[j]; paramView[j] = i; j += 1 ; } } this .val$textview.setText("输入注册码错误" ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 cipher = [] for _ in "dd2940c04462b4dd7c450528835cca15" : cipher.append(_) cipher[2 ] = chr (ord (cipher[2 ])+ord (cipher[3 ])-50 ) cipher[4 ] = chr (ord (cipher[2 ])+ord (cipher[5 ])-48 ) cipher[30 ] = chr (ord (cipher[31 ])+ord (cipher[9 ])-48 ) cipher[14 ] = chr (ord (cipher[27 ])+ord (cipher[28 ])-97 ) for j in range (16 ): i = cipher[(31 -j)] cipher[(31 -j)] = cipher[j] cipher[j] = i flag = "flag{" for _ in cipher: flag += _ flag += "}" print(flag)
flag{59acc538825054c7de4b26440c0999dd}
[GWCTF 2019]pyre
链接: https://buuoj.cn/challenges# [GWCTF 2019]pyre
Python
使用uncompyle6反编译pyc文件得到源代码
1 2 3 4 5 6 7 8 9 10 11 12 print 'Welcome to Re World!' print 'Your input1 is your flag~' l = len (input1) for i in range (l): num = ((input1[i] + i) % 128 + 128 ) % 128 code += num for i in range (l - 1 ): code[i] = code[i] ^ code[(i + 1 )] print codecode = ['\x1f' , '\x12' , '\x1d' , '(' , '0' , '4' , '\x01' , '\x06' , '\x14' , '4' , ',' , '\x1b' , 'U' , '?' , 'o' , '6' , '*' , ':' , '\x01' , 'D' , ';' , '%' , '\x13' ]
1 2 3 4 5 6 7 8 9 10 11 12 13 cipher = ['\x1f' , '\x12' , '\x1d' , '(' , '0' , '4' , '\x01' , '\x06' , '\x14' , '4' , ',' , '\x1b' , 'U' , '?' , 'o' , '6' , '*' , ':' , '\x01' , 'D' , ';' , '%' , '\x13' ] l = len (cipher) for _ in range (l): cipher[_] = ord (cipher[_]) for _ in range (l-2 , -1 , -1 ): cipher[_] = cipher[_]^cipher[_+1 ] for _ in range (l): cipher[_] = (cipher[_]-_)%128 flag = "" for _ in cipher: flag += chr (_) print(flag)
flag{Just_Re_1s_Ha66y!}
EOF