BUUCTF之reverse(持续更新中)
easyre
拖入ida打开,反汇编直接看到flag
flag{this_Is_a_EaSyRe}
reverse1
ida打开看看
shift+f12查看字符串
看到flag的字符串,双击进去看看
发现在数据段上,调用的函数是sub_1400118C0,再双击函数进去看看,发现是汇编代码,反汇编一下,得到函数的代码
__int64 sub_1400118C0()
{
char *v0; // rdi
__int64 i; // rcx
size_t v2; // rax
size_t v3; // rax
char v5[36]; // [rsp+0h] [rbp-20h] BYREF
int j; // [rsp+24h] [rbp+4h]
char Str1[224]; // [rsp+48h] [rbp+28h] BYREF
unsigned __int64 v8; // [rsp+128h] [rbp+108h]
v0 = v5;
for ( i = 82i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
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("input the flag:");
sub_14001128F("%20s", Str1);
v3 = j_strlen(Str2);
if ( !strncmp(Str1, Str2, v3) )
sub_1400111D1("this is the right flag!\n");
else
sub_1400111D1("wrong flag\n");
sub_14001113B(v5, &unk_140019D00);
return 0i64;
}
分析代码可以看到,字符串str1就是输入的字符串,str2是我们刚刚看到的字符串{hello_world}
,然后接下来是比较str1和str2,直到完全匹配才会输出你得到flag,这里还有一个坑,就是前面的一个语句块
if ( Str2[j] == 111 )
Str2[j] = 48;
可以看到如果str2的字符串中的字符的ASCII值为111,会被换成48,查一下ASCII表,便知道约束的条件是'o' -> '0'
所以来说,最后需要与str1匹配的字符串为{hell0_w0rld}
,得到flag
reverse2
这题目跟上面的有点相似,用exeinfo PE查看一下
64位elf文件,用ida64打开,f5反汇编一下
大意就是输入字符串s2,如果输入的字符串和字符串flag一样,输出"this is the right flag!"
在比较之前,有一个语句
for ( i = 0; i <= strlen(&flag); ++i )
{
if ( *(&flag + i) == 105 || *(&flag + i) == 114 )
*(&flag + i) = 49;
}
就是在字符串中,如果有ASCII值为105('i')或者问114('r'),转换为49('1')
在数据段看一下
则经过转换后的字符串为"hack1ing_fo1_fun"
得到flagflag{hack1ing_fo1_fun}
2022/03/04
内涵的软件
ida反汇编看一下
看到v5就是flag
得到flag
flag{49d3c93df25caad81232130f3d2ebfad}
2022/03/04
新年快乐
查看有无壳
发现带了一个upx的壳,先手工脱壳一下
f2下断点
f9运行到这里,再f8,
一般就到了OEP
点击脱壳保存一下
检查是否已经脱壳
扔到ida看看
反汇编查看主函数
跟上一题类似,比较输入字符串和已有的字符串,在上面可以看见
strcpy(Str2, "HappyNewYear!");
显然str2为flag,得到flag
xor
查壳
无壳,用ida打开看看
分析代码
首先必须满足长度为33位,后一位与前一位进行异或运算,而后和global字符串比较,匹配即为flag
写一个脚本
s = ['f', 0x0A, 'k', 0x0C, 'w','&','O','.','@', 0x11, 'x', 0x0D, 'Z',';','U', 0x11, 'p', 0x19, 'F', 0x1F, 'v','"','M','#','D', 0x0E, 'g', 0x6, 'h',
0x0F, 'G','2','O', 0x0]
# 因为含有数字,首先转换成字符
for i in range(len(s)):
if type(s[i]) == int:
s[i] = chr(s[i])
flag = 'f'
for i in range(1, len(s)):
flag += chr(ord(s[i]) ^ ord(s[i - 1]))
print(flag)s = ['f', 0x0A, 'k', 0x0C, 'w','&','O','.','@', 0x11, 'x', 0x0D, 'Z',';','U', 0x11, 'p', 0x19, 'F', 0x1F, 'v','"','M','#','D', 0x0E, 'g', 0x6, 'h',
0x0F, 'G','2','O', 0x0]
# 因为含有数字,首先转换成字符
for i in range(len(s)):
if type(s[i]) == int:
s[i] = chr(s[i])
flag = 'f'
for i in range(1, len(s)):
flag += chr(ord(s[i]) ^ ord(s[i - 1]))
print(flag)
得到flag
2022/03/05
helloword
直接扔到ida查看
shift+f12查看字符串,右击选择过滤查看,得到flag
flag{7631a988259a00816deda84afb29430a}
reverse3
查壳,没有壳
ida查看main()函数
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
size_t v3; // eax
const char *v4; // eax
size_t v5; // eax
char v7; // [esp+0h] [ebp-188h]
char v8; // [esp+0h] [ebp-188h]
signed int j; // [esp+DCh] [ebp-ACh]
int i; // [esp+E8h] [ebp-A0h]
signed int v11; // [esp+E8h] [ebp-A0h]
char Destination[108]; // [esp+F4h] [ebp-94h] BYREF
char Str[28]; // [esp+160h] [ebp-28h] BYREF
char v14[8]; // [esp+17Ch] [ebp-Ch] BYREF
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_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);
其中
v4 = (const char *)sub_4110BE(Str, v3, v14);
是一个加密的函数,追踪看了半天的代码,没看懂,上网找了找WP才知道是base64加密
看一下加密字符串里面的字符串的内容,点进去
确实是base64
查看str2字符串
写一个脚本
import base64
str2='e3nifIH9b_C@n@dH'
flag=''
for i in range(0,len(str2)):
flag+=chr(ord(str2[i])-i)
print("加密:{}".format(flag))
print("解密:{}".format(base64.b64decode(flag).decode('utf-8')))
得到flag
不一样的flag
查壳
无壳,32位
ida打开看看
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char v3[29]; // [esp+17h] [ebp-35h] BYREF
int v4; // [esp+34h] [ebp-18h]
int v5; // [esp+38h] [ebp-14h] BYREF
int i; // [esp+3Ch] [ebp-10h]
_BYTE v7[12]; // [esp+40h] [ebp-Ch] BYREF
__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);
}
}
}
分析代码,是一个走迷宫的问题
*1111
01000
01010
00010
1111#
*代表起点,#代表终点
222441144222
试了半天最后才知道路径是flag。。。
2022/03/10
SimpleRev
查壳
发现是64位程序
ida打开看看
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char v4; // [rsp+Fh] [rbp-1h]
while ( 1 )
{
while ( 1 )
{
printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ");
v4 = getchar();
if ( v4 != 'd' && v4 != 'D' )
break;
Decry();
}
if ( v4 == 'q' || v4 == 'Q' )
Exit("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv);
puts("Input fault format!");
v3 = getchar();
putchar(v3);
}
}
打开Decry看看
unsigned __int64 Decry()
{
char v1; // [rsp+Fh] [rbp-51h]
int v2; // [rsp+10h] [rbp-50h]
int v3; // [rsp+14h] [rbp-4Ch]
int i; // [rsp+18h] [rbp-48h]
int v5; // [rsp+1Ch] [rbp-44h]
char src[8]; // [rsp+20h] [rbp-40h] BYREF
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
int v10; // [rsp+50h] [rbp-10h]
unsigned __int64 v11; // [rsp+58h] [rbp-8h]
v11 = __readfsqword(0x28u);
*(_QWORD *)src = 0x534C43444ELL;
v7 = 0LL;
v8 = 0;
v9[0] = 0x776F646168LL;
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;
}
自己分析了半天代码,头晕乎乎的,看了一些WP
看到有大佬写的代码转换,就懂了点(ಥ _ ಥ)
1 #include <bits/stdc++.h>
2
3 #pragma warning(disable:4996)
4
5 int main(void)
6 {
7 int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
8 char v1;
9 char flag[11] = { 0 };
10 char str2[104] = { 0 };
11 char key[] = "ADSFKNDCLS";
12 char text[] = "killshadow";
13
14
15 for (i = 0; i < v5; ++i)
16 {
17 if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
18 key[i] = key[v3 % v5] + 32;
19 ++v3;
20 }
21 printf("Please input your flag:");
22 while (1)
23 {
24 v1 = getchar();
25 printf("v1:%c\nv2:%d\n\n", v1, v2);
26 if (v1 == 10) {
27 printf("进入1\n");
28 break;
29 }
30 if (v1 == 32)
31 {
32 printf("进入2\n");
33 ++v2;
34 }
35 else
36 {
37 if (v1 <= 96 || v1 > 122)
38 {
39 if (v1 > 64 && v1 <= 90) {
40 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
41 printf("计算1\n");
42 }
43 }
44 else
45 {
46 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
47 printf("计算1\n");
48 }
49 if (!(v3 % v5))
50 putchar(' ');
51 ++v2;
52 }
53 }
54 if (!strcmp(text, str2))
55 puts("Congratulation!\n");
56 else {
57 printf("str2:%s\n", str2);
58 puts("Try again!\n");
59 }
60
61 system("PAUSE");
62 return 0;
63 }
第30~35行代码的实际作用是将大写字母转换为小写。
第37~61行代码实际上就是遍历输入的字符(flag),进行str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;运算,最后与text比较。
因此我们只要反向就能求出输入的v1
编写一个脚本
i, j, n = 0, 0, 0
v5 = 10
v3 = 0
v2 = 0
v1 = ''
flag = ['0' for data in range(10)]
str = ''
key = 'ADSFKNDCLS'
text = 'killshadow'
for i in range(v5):
if 90 >= ord(key[v3 % v5]) > 64:
key = key[:i] + chr(ord(key[v3 % v5]) + 32) + key[i + 1:]
v3 += 1
for j in range(10):
for v2 in range(10):
v1 = chr(ord(text[v2]) - 97 + 26 * j - 97 + ord(key[v3 % v5]) + 39)
v3 += 1
if 90 >= ord(v1) >= 65 or 122 >= ord(v1) >= 97:
flag[v2] = v1
n += 1
if n == 10:
s = ''
for i in flag:
s += i
print(s)
exit(0)
跑一下得到flag
Java逆向解密
.class
文件
用jd-gui打开看看
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<Integer> Resultlist = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
int result = arr[i] + 64 ^ 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<Integer> 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);
}
}
}
有一个加密函数Encrypt,分析是一个简单的异或操作
exp
KEY = [
180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
133, 191, 134, 140, 129, 135, 191, 65]
for i in KEY:
print(chr(i - 64 ^ 0x20), end='')
得到flag
[GXYCTF2019]luck_guy
查壳
64位,无壳,用ida打开
f5反汇编查看一下主函数
没有注入点,追踪patch_me函数
发现get_flag函数,基本上确定是flag了,继续点进去看看
unsigned __int64 get_flag()
{
unsigned int v0; // eax
int i; // [rsp+4h] [rbp-3Ch]
int j; // [rsp+8h] [rbp-38h]
__int64 s; // [rsp+10h] [rbp-30h] BYREF
char v5; // [rsp+18h] [rbp-28h]
unsigned __int64 v6; // [rsp+38h] [rbp-8h]
v6 = __readfsqword(0x28u);
v0 = time(0LL);
srand(v0);
for ( i = 0; i <= 4; ++i )
{
switch ( rand() % 200 )
{
case 1:
puts("OK, it's flag:");
memset(&s, 0, 0x28uLL);
strcat((char *)&s, f1);
strcat((char *)&s, &f2);
printf("%s", (const char *)&s);
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
s = 0x7F666F6067756369LL;
v5 = 0;
strcat(&f2, (const char *)&s);
break;
case 5:
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
*(&f2 + j) -= 2;
else
--*(&f2 + j);
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
}
return __readfsqword(0x28u) ^ v6;
}
使用了strcat函数进行字符串的拼接
先看一下f1和f2在数据段上的存储的内容
得到一半,还差一半肯定是f2
继续分析代码,在case5代码中可以看到给s赋值了一串数字,然后转换类型为字符串复制给f2,继而通过一个if语句块进行改造
exp
flag = 'GXY{do_not_'
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69]
# print(s)
for j in range(8):
if j % 2 == 1:
f2[j] -= 1
else:
f2[j] -= 2
f2[j] = chr(f2[j])
s = ''.join(f2)
flag += s[::-1]
print(flag)
附:需要注意端序的问题,先开始写的时候没有发现,直到输出的时候才知道后一半写反了。。。。
2022/03/16
刮开有奖
查壳
无壳,32位exe程序
ida打开看看
调用了函数DialogBoxParamA,不认识,百度查了一下,作用是创建一个模态的对话框。
看到参数里面有一个功能函数,点进去看看
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7[2]; // [esp+8h] [ebp-20030h] BYREF
int v8; // [esp+10h] [ebp-20028h]
int v9; // [esp+14h] [ebp-20024h]
int v10; // [esp+18h] [ebp-20020h]
int v11; // [esp+1Ch] [ebp-2001Ch]
int v12; // [esp+20h] [ebp-20018h]
int v13; // [esp+24h] [ebp-20014h]
int v14; // [esp+28h] [ebp-20010h]
int v15; // [esp+2Ch] [ebp-2000Ch]
int v16; // [esp+30h] [ebp-20008h]
CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF
if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 ) // a3=1001
{
memset(String, 0, 0xFFFFu); // 初始化为0
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
if ( strlen(String) == 8 ) // string的长度为8
{
v7[0] = 90;
v7[1] = 74;
v8 = 83;
v9 = 69;
v10 = 67;
v11 = 97;
v12 = 78;
v13 = 72;
v14 = 51;
v15 = 110;
v16 = 103;
sub_4010F0(v7, 0, 10); // 升序算法
memset(v18, 0, 0xFFFFu);
v18[0] = String[5];
v18[2] = String[7];
v18[1] = String[6];
v4 = (const char *)sub_401000(v18, strlen(v18));// base64加密,结果赋值给v4
memset(v18, 0, 0xFFFFu);
v18[1] = String[3];
v18[0] = String[2];
v18[2] = String[4];
v5 = (const char *)sub_401000(v18, strlen(v18));
if ( String[0] == v7[0] + 34 // 'U'
&& String[1] == v10 // 'J'
&& 4 * String[2] - 141 == 3 * v8 // 'W'
&& String[3] / 4 == 2 * (v13 / 9) // 'P'
&& !strcmp(v4, "ak1w") // 'ak1w'
&& !strcmp( // 'V1Ax'
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;
}
v4和v5解密一下,拼接起来得到flag
flag{UJWP1jMp}
[BJDCTF2020]JustRE
拿到exe先查壳
32位,无壳
拖入ida查看
shift+f12查看字符串
追踪一下调用它的函数
显然的打印出来的flag
BJD{1999902069a45792d233ac}
2022/08/23
简单注册器
下载的文件是安卓类型的
用jadx打开
很简单的一个加密
exp
x=['d','d','2','9','4','0','c','0','4','4','6','2','b','4','d','d','7','c','4','5','0','5','2','8','8','3','5','c','c','a','1','5']
x[2]=chr(ord(x[2])+ord(x[3])-50)
x[4]=chr(ord(x[2])+ord(x[5])-48)
x[30]=chr(ord(x[31])+ord(x[9])-48)
x[14]=chr(ord(x[27])+ord(x[28])-97)
for i in range(16):
x[31-i],x[i]=x[i],x[31-i]
print('flag{',end='')
for i in x:
print(i,end='')
print('}')
得到flag
flag{59acc538825054c7de4b26440c0999dd}
2022/08/23
[GWCTF 2019]pyre
下载的文件格式是pyc
找个在线网站反编译:https://tool.lu/pyc/
得到反编译的代码
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7
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 code
code = [
"\x1f",
"\x12",
"\x1d",
"(",
"0",
"4",
"\x01",
"\x06",
"\x14",
"4",
",",
"\x1b",
"U",
"?",
"o",
"6",
"*",
":",
"\x01",
"D",
";",
"%",
"\x13",
]
根据加密的代码写一个脚本跑一下
code = [
"\x1f",
"\x12",
"\x1d",
"(",
"0",
"4",
"\x01",
"\x06",
"\x14",
"4",
",",
"\x1b",
"U",
"?",
"o",
"6",
"*",
":",
"\x01",
"D",
";",
"%",
"\x13",
]
for i in range(len(code)-2,-1,-1):
code[i]=chr(ord(code[i])^ord(code[i+1]))
# print(hex(ord(code[i])))
for i in range(len(code)):
code[i]=chr((ord(code[i])+128-i)%128)
print(code[i],end='')
得到flag
flag{Just_Re_1s_Ha66y!}
2022/08/24
[ACTF新生赛2020]easyre
exe文件,查壳
32位,upx加壳
直接在Ubuntu下脱壳
➜ re sudo apt install upx # 安装upx
...
➜ re upx -d easyre.exe
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2018
UPX 3.95 Markus Oberhumer, Laszlo Molnar & John Reiser Aug 26th 2018
File size Ratio Format Name
-------------------- ------ ----------- -----------
28123 <- 21467 76.33% win32/pe easyre.exe
Unpacked 1 file.
脱壳成功后,放入ida
根据for循环编写exp
exp
v4_s='''*F'\"N,\"(I?+@'''
s_s=r"~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(" + chr(0x27) + r'&%$# !"'
v6=[chr(65),chr(67),chr(84),chr(70),chr(123)]
v10=chr(125)
print('flag{',end='')
for i in v4_s:
print(chr(s_s.find(i)+1),end='')
print('}')
2022/08/24
rsa
下载下来得是两个文件
打开公钥文件
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----
找一个在线网站解析:http://tool.chacuo.net/cryptrsakeyparse
得到e=65537,n=0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
一开始使用yafu分解n,后来跑了半天没跑出来,找了在线网站分解出来了
得到p和q
脚本跑一下
import gmpy2
import rsa
N = 0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
E = 65537
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
D = int(gmpy2.invert(E,(p-1)*(q-1)))
privkey = rsa.PrivateKey(N, E, D, p, q)
with open("flag.enc", "rb+") as file:
text = file.read()
message = rsa.decrypt(text,privkey)
print(message)
得到flag
2022/08/24
[ACTF新生赛2020]rome
查壳
32位,未加壳
拖入ida
直接看func函数
int func()
{
int result; // eax
int v1[4]; // [esp+14h] [ebp-44h]
unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
unsigned __int8 v3; // [esp+25h] [ebp-33h]
unsigned __int8 v4; // [esp+26h] [ebp-32h]
unsigned __int8 v5; // [esp+27h] [ebp-31h]
unsigned __int8 v6; // [esp+28h] [ebp-30h]
int v7; // [esp+29h] [ebp-2Fh]
int v8; // [esp+2Dh] [ebp-2Bh]
int v9; // [esp+31h] [ebp-27h]
int v10; // [esp+35h] [ebp-23h]
unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF
strcpy(v12, "Qsw3sj_lz4_Ujw@l");
printf("Please input:");
scanf("%s", &v2);
result = v2;
if ( v2 == 65 )
{
result = v3;
if ( v3 == 67 )
{
result = v4;
if ( v4 == 84 )
{
result = v5;
if ( v5 == 70 )
{
result = v6;
if ( v6 == 123 )
{
result = v11;
if ( v11 == 125 )
{
v1[0] = v7;
v1[1] = v8;
v1[2] = v9;
v1[3] = v10;
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
++*(_DWORD *)&v12[17];
}
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
return result;
++*(_DWORD *)&v12[17];
}
result = printf("You are correct!");// 执行到这里成功
}
}
}
}
}
}
return result;
}
关键的部分加密
exp
import string
s='Qsw3sj_lz4_Ujw@l'
t_low=string.ascii_lowercase
t_upp=string.ascii_uppercase
flag=''
for i in s:
if 64<ord(i)<=90:
flag+=t_upp[ord(i)-14-65]
elif 96<ord(i)<=122:
flag+=t_low[ord(i)-18-97]
else:
flag+=i
print('flag{'+flag+'}')
得到flag
flag{Cae3ar_th4_Gre@t}
2022/08/24
CrackRTF
查壳
32位,无壳
拖入ida
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
DWORD v3; // eax
DWORD v4; // eax
char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
int v7; // [esp+150h] [ebp-20Ch]
char String1[260]; // [esp+154h] [ebp-208h] BYREF
char Destination[260]; // [esp+258h] [ebp-104h] BYREF
memset(Destination, 0, sizeof(Destination));
memset(String1, 0, sizeof(String1));
v7 = 0;
printf("pls input the first passwd(1): ");
scanf("%s", Destination);
if ( strlen(Destination) != 6 )
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
v7 = atoi(Destination);
if ( v7 < 100000 )
ExitProcess(0);
strcat(Destination, "@DBApp"); //第一次输入的和'@DBApp'拼接
v3 = strlen(Destination);
sub_40100A((BYTE *)Destination, v3, String1);//加密验证
if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
{
printf("continue...\n\n");
printf("pls input the first passwd(2): ");
memset(Str, 0, sizeof(Str));
scanf("%s", Str);
if ( strlen(Str) != 6 )
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
strcat(Str, Destination);
memset(String1, 0, sizeof(String1));
v4 = strlen(Str);
sub_401019((BYTE *)Str, v4, String1);
if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
{
if ( !(unsigned __int8)sub_40100F(Str) )
{
printf("Error!!\n");
ExitProcess(0);
}
printf("bye ~~\n");
}
}
return 0;
}
可以看到两次密码验证
第一次中的加密函数
int __cdecl sub_401230(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
int result; // eax
DWORD i; // [esp+4Ch] [ebp-28h]
CHAR String2[4]; // [esp+50h] [ebp-24h] BYREF
BYTE v6[20]; // [esp+54h] [ebp-20h] BYREF
DWORD pdwDataLen; // [esp+68h] [ebp-Ch] BYREF
HCRYPTHASH phHash; // [esp+6Ch] [ebp-8h] BYREF
HCRYPTPROV phProv; // [esp+70h] [ebp-4h] BYREF
if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
return 0;
if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) )
{
if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
{
CryptGetHashParam(phHash, 2u, v6, &pdwDataLen, 0);
*lpString1 = 0;
for ( i = 0; i < pdwDataLen; ++i )
{
wsprintfA(String2, "%02X", v6[i]);
lstrcatA(lpString1, String2);
}
CryptDestroyHash(phHash);
CryptReleaseContext(phProv, 0);
result = 1;
}
else
{
CryptDestroyHash(phHash);
CryptReleaseContext(phProv, 0);
result = 0;
}
}
else
{
CryptReleaseContext(phProv, 0);
result = 0;
}
return result;
}
脚本爆破
import hashlib
string='@DBApp'
for i in range(100000,999999):
flag=str(i)+string
x = hashlib.sha1(flag.encode("utf8"))
y = x.hexdigest()
if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:
print(flag)
break
得到密码1
123321
密码2
rtf = '{\\rtf1' \\需要注意,\r需要转义,变成\\r
A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
password=''
for i in range(len(rtf)):
x = ord(rtf[i]) ^ A[i]
password+=chr(x)
print(password)
生成的rtf中有flag
得到flag
flag{N0_M0re_Free_Bugs}
2022/08/25
[FlareOn4]login
html文件
打开源码看看
<!DOCTYPE Html />
<html>
<head>
<title>FLARE On 2017</title>
</head>
<body>
<input type="text" name="flag" id="flag" value="Enter the flag" />
<input type="button" id="prompt" value="Click to check the flag" />
<script type="text/javascript">
document.getElementById("prompt").onclick = function () {
var flag = document.getElementById("flag").value;
var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {
alert("Correct flag!");
} else {
alert("Incorrect flag, rot again");
}
}
</script>
</body>
</html>
rot13加密的算法
wiki解释:
直接把对比的字符串跑一下脚本
exp
import string
s='PyvragFvqrYbtvafNerRnfl@syner-ba.pbz'
for i in s:
if i not in string.ascii_lowercase+string.ascii_uppercase:
print(i,end='')
else:
if i<='Z':
jud=ord('Z')
else:
jud=ord('z')
tmp=ord(i)+13
if jud>=tmp:
print(chr(tmp),end='')
else:
print(chr(tmp-26),end='')
跑一下得到flag
2022/08/28
[2019红帽杯]easyRE
elf64位文件
拖入ida看看
查看一下字符串,追踪第三个
几个字符串异或操作
exp
s_1=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
s_2='flag'
s_4=[chr(ord(s_2[i])^(s_1[i])) for i in range(len(s_2))]
flag=[chr((s_1[i])^ord(s_4[i%4])) for i in range(25)]
print(''.join(flag))
得到flag
flag{Act1ve_Defen5e_Test}
2022/09/03
[GUET-CTF2019]re
elf64位文件,加upx壳,直接拖入Linux脱掉
拖入ida,shift+f12查看字符串
进入判断的函数看看
写个脚本跑一下
import string
d_1=[166163712,731332800,357245568,1074393000,489211344,518971936,406741500,294236496,177305856,650683500,298351053,386348487,438258597,249527520,445362764,174988800,981182160,493042704,257493600,767478780,312840624,1404511500,316139670,619005024,372641472,373693320,498266640,452465676,208422720,515592000,719890500]
d_2=[1629056,6771600,3682944,10431000,3977328,5138336,7532250,5551632,3409728,13013670,6088797,7884663,8944053,5198490,4544518,3645600,10115280,9667504,5364450,13464540,5488432,14479500,6451830,6252576,7763364,7327320,8741520,8871876,4086720,9374400,5759124]
flag=''
for i in range(len(d_1)):
flag=flag+(chr(d_1[i]//d_2[i]))
print('缺少a1[6]的字符串: {}'.format(flag[:6]+' '+flag[6:]))
# 注意没有给a1[6],故需要爆破a1[6]
for i in (string.ascii_lowercase+string.ascii_uppercase+string.digits):
print('fill with {} a1[6]=:{}'.format(i,flag[:6]+i+flag[6:]))
得到flag
flag{e165421110ba03099a1c039337}
2022/09/04
[WUSTCTF2020]level1
查看文件信息
elf64位文件,未加壳
拖入ida查看,直接反汇编看主函数
给的output.txt有输出的数据
直接脚本跑一下
exp
s=[198,
232,
816,
200,
1536,
300,
6144,
984,
51200,
570,
92160,
1200,
565248,
756,
1474560,
800,
6291456,
1782,
65536000]
flag=[]
for i in range(19):
if (i+1)%2==1:
flag.append(chr(s[i]>>(i+1)))
else:
flag.append(chr(s[i]//(i+1)))
print(''.join(flag))
得到flag
flag{d9-dE6-20c}
2022/09/05
[SUCTF2019]SignIn
检查文件
elf64位文件,未加壳
拖入ida
看到65537和两串长长的字符串,当下知道是rsa算法
C=M^E mod N
根据程序知道
C=0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
E=65537
N=103461035900816914121390101299049044413950405173712170434161686539878160984549
用在线或者yafu分离N为P和Q
得到p和q
P=282164587459512124844245113950593348271
Q=366669102002966856876605669837014229419
脚本跑一下
exp
import gmpy2
C = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
E = 65537
N = 103461035900816914121390101299049044413950405173712170434161686539878160984549
P = 282164587459512124844245113950593348271
Q = 366669102002966856876605669837014229419
d = gmpy2.invert(E, (P - 1) * (Q - 1))
m = gmpy2.powmod(C, d, N)
print(hex(m))
print(bytes.fromhex(hex(m)[2:]))
得到flag
suctf{Pwn_@_hundred_years}
2022/09/05
[MRCTF2020]Transform
检查文件
exe64位程序,未加壳,拖入ida分析
分别查看参与操作的比特流
简单的逆向操作,修改了字符串的顺序而已
exp
s_1=[0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57, 0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57, 0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D]
# print(len(s_1))
s_2=[0x9, 0x0A, 0x0F, 0x17, 0x7, 0x18, 0x0C, 0x6, 0x1, 0x10, 0x3, 0x11, 0x20, 0x1D, 0x0B, 0x1E, 0x1B, 0x16, 0x4, 0x0D, 0x13, 0x14, 0x15, 0x2, 0x19, 0x5, 0x1F, 0x8, 0x12, 0x1A, 0x1C, 0x0E, 0x00]
# print(len(s_2))
flag=['' for i in range(len(s_1))]
for i in range(len(s_1)):
tmp=s_1[i]^s_2[i]
print(chr(tmp),end='')
flag[s_2[i]]=chr(tmp)
print()
print(''.join(flag))
得到flag
MRCTF{Tr4nsp0sltiON_Clph3r_1s_3z}
2022/09/06
[WUSTCTF2020]level2
检查文件
elf32位,加upx壳,直接在终端脱壳
拖入ida查看
签到题,直接拿到flag
2022/09/06
[ACTF新生赛2020]usualCrypt
检查文件
pe32位文件,未加壳
拖入ida看看
主函数
比较的字符串
进入关键的加密函数看看
一开始调用的函数修改了字典的顺序
修改的数据如下
最后返回的函数功能是大小写转换
程序运行思路
首先输入字符串,修改了base64表的位移,然后进行base64编码转换,最后进行大小写转换
exp
import base64
s='zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase() # 大小写转换
# print(s)
d=dict()
offset=0x40E0AA-0x40E0A0
k='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag=''
for i in range(len(k)):
d[k[i]]=k[i]
for i in range(6,15):
d[k[i]],d[k[i+offset]]=d[k[i+offset]],d[k[i]]
for i in s:
flag+=d[i]
flag=base64.b64decode(flag).decode('utf-8')
print(flag)
得到flag
flag{bAse64_h2s_a_Surprise}
2022/09/07
[HDCTF2019]Maze
看题目名字,感觉是一个迷宫题目
查看文件
pe32位,加upx壳
直接在终端脱壳
拖入ida
主函数
可以看到限制输入的字符串的长度是14
看完后,没有思路,上网找了一些wp看了看,知道是花指令
借鉴的wp:https://blog.csdn.net/weixin_46009088/article/details/110204937
选中main的汇编部分按p可以生成对应的函数
adsw,分别对应上下左右,根据最后的结果进行对比,如果相等说明成功crack
初始位置是(0,7),结果需要到(-4,5)
找到迷宫
*******+**
******* **
**** **
** *****
** **F****
** ****
**********
得到flag
flag{ssaaasaassdddw}
2022/09/07
Youngter-drive
检查文件
pe32位文件,加upx壳
拖入终端脱壳
拖入ida
查看第一个线程,发现一个加密的操作
发现和输入的字符串同时操作的字符串有效长度只有29,而遍历的次数是30次,这里有点摸不着头脑
看看第二个线程
exp
off_418004='TOiZiZtOrYaToUwPnToBsOaOapsyS'
off_418000='QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
flag=[]
for i in range(len(off_418004)):
if(i%2==0):
flag.append(off_418004[i])
else:
for j,k in enumerate(off_418000):
if off_418004[i]==k:
if chr(j+38).isupper():
flag.append(chr(j+38))
else:
flag.append(chr(j+96))
print(''.join(flag))
得到flag
ThisisthreadofwindowshahaIsES
因为之前遍历的问题,缺少一位,所以最后一位需要自己去补齐,经过几次尝试,得到最后一位是E
2022/09/09
相册
检查文件
apk文件,未加壳
用jeb打开
邮箱加密的方式是base64,
jeb不太会用,把so文件提取出来,直接拖入ida查看字符串
base64解码得到flag
flag{18218465125@163.com}
2022/09/09
[MRCTF2020]Xor
检查文件
pe32位,无壳
直接拖入ida
无法反汇编成c,那就直接看汇编
查看存储的字符串
简单的异或
exp
s=b'\x4dSAWB~FXZ:J:`tQJ"N@ bpdd}8g'
for i in range(len(s)):
print(chr(i^s[i]),end='')
跑一下得到flag
MRCTF{@_R3@1ly_E2_R3verse!}
2022/09/14
[MRCTF2020]hello_world_go
检查文件
elf64位,第一次碰到go语言写的程序,直接拖入ida尝试,f5反编译
???直接送flag,试了一下,果然是这个。。。
2022/09/14
[WUSTCTF2020]level3
检查文件
elf64位,未加壳,直接拖入ida
看着一串很像base64的字符,尝试解一下
有乱码,不对,但是有部分是对的,猜测是base64的变形
之前做过修改base64表的题目,就是这个[ACTF新生赛2020]usualCrypt
思路:直接把编码后的字符串修改为正常的base64表的即可
exp
import base64
flag=''
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s='d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD=='
d={}
for i in range(len(table)):
d[table[i]]=table[i]
for i in range(0,9+1):
d[table[i]],d[table[19-i]]=d[table[19-i]],d[table[i]]
for i in s:
if i in table:
flag+=d[i]
else:
flag+=i # 问了避免填充的等于号带入运算报错
print(flag)
# flag+='=='
print(base64.b64decode(flag).decode('utf-8'))
得到flag
wctf2020{Base64_is_the_start_of_reverse}
2022/09/14
[GWCTF 2019]xxor
检查文件
elf64位,未加壳,直接拖入ida
关键函数中的宏定义可以在ida安装的文件夹中的defs.h
里面找到
#define LODWORD(x) DWORDn(x,LOW_IND(x,_DWORD))
#define HIDWORD(x) DWORDn(x,HIGH_IND(x,_DWORD))
看一下加密的函数以及传入的参数
再看一下校验的函数
一堆数据关系,不知道怎么下手,找了一下wp看了一下,知道了使用z3约束器
from z3 import *
a0, a1, a2, a3, a4, a5 = Ints('a0 a1 a2 a3 a4 a5')
s = Solver()
s.add(a2 - a3 == 0x84A236FF)
s.add(a3 + a4 == 0xFA6CB703)
s.add(a2 - a4 == 0x42D731A8)
s.add(a0 == 0xDF48EF7E)
s.add(a5 == 0x84F30420)
s.add(a1 == 0x20CAACF4)
if s.check() == sat:
print(s.model())
得到
a2 = 3774025685
a1 = 550153460
a5 = 2230518816
a0 = 3746099070
a3 = 1548802262
a4 = 2652626477
对于异或操作,涉及到端序和异或问题,用python写了半天没弄出来,看了网上的wp用的是c写的,代码如下
#include <stdio.h>
int main()
{
int a1[6] = { 3746099070,550153460,3774025685,1548802262,2652626477,2230518816 };
unsigned int a2[4] = { 2,2,3,4 };
unsigned int v3;
unsigned int v4;
int v5;
for (unsigned int j = 0; j < 5; j += 2)
{
v3 = a1[j];
v4 = a1[j + 1];
v5 = 1166789954 * 64;
for (unsigned int i = 0; i < 64; i++)
{
v4 -= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
v3 -= (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
v5 -= 1166789954;
}
a1[j] = v3;
a1[j + 1] = v4;
}//小端序
for (unsigned int i = 0; i < 6; i++)
printf("%c%c%c", *((char*)&a1[i] + 2), *((char*)&a1[i] + 1), *(char*)&a1[i]);
}
得到flag
flag{re_is_great!}
2022/09/15
[FlareOn4]IgniteMe
检查文件
pe32位,未加壳,直接拖入ida
程序的运行思路:最后一个字符xor 0x4,然后之后按位和前一个异或,最后和403000比较
exp
byte_403000=[0x0D,0x26,0x49, 0x45, 0x2A, 0x17, 0x78, 0x44, 0x2B, 0x6C, 0x5D,0x5E, 0x45, 0x12, 0x2F, 0x17, 0x2B, 0x44, 0x6F, 0x6E, 0x56, 0x9,0x5F, 0x45, 0x47, 0x73, 0x26, 0x0A, 0x0D, 0x13, 0x17, 0x48, 0x42,0x1, 0x40, 0x4D, 0x0C, 0x2, 0x69, 0x0]
flag=""
L=len(byte_403000)-1
for i in range(len(byte_403000)):
if i==0:
byte_403000[L-i]= byte_403000[L-i]^0x4
byte_403000[L-i-1] = byte_403000[L-i-1]^byte_403000[L-i]
flag+=chr(byte_403000[L-i])
print(byte_403000)
print(flag[::-1])
得到flag
R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com
2022/09/21
[WUSTCTF2020]Cr0ssfun
检查文件
elf64位,无壳,扔进ida
继续看看
继续追踪
继续
exp
a1=['' for i in range(33)]
a1[10] = 'p'
a1[13] = '@'
a1[3] = 'f'
a1[26] = 'r'
a1[20] = 'e'
a1[7] = '0'
a1[16] = '_'
a1[11] = 'p'
a1[23] = 'e'
a1[30] = 'u'
a1[0] = 'w'
a1[6] = '2'
a1[22] = 's'
a1[31] = 'n'
a1[12] = '_'
a1[15] = 'd'
a1[8] = '{'
a1[18] = '3'
a1[28] = '_'
a1[21] = 'r'
a1[2] = 't'
a1[9] = 'c'
a1[32] = '}'
a1[19] = 'v'
a1[5] = '0'
a1[14] = 'n'
a1[4] = '2'
a1[17] = 'r'
a1[29] = 'f'
a1[17] = 'r'
a1[24] = '_'
a1[1] = 'c'
a1[25] = '@'
a1[27] = 'e'
print(''.join(a1))
得到
wctf2020{cpp_@nd_r3verse_@re_fun}
2022/09/21
[FlareOn6]Overlong
检查文件
pe32位,未加壳,拖入ida
瞅了半天没看懂逻辑,上网找了找相关的wp,知道了动调得到flag
用od打开(网上的师傅们写的有点简略,自己初学od,琢磨了半天才改成功QWQ)
先给跳转的函数下一个断点(在地址那里双击即可),然后选中上面的运行自动运行到断点
注意右下角的栈的变化,双击第三个变量,并把1c修改为AF
然后点击ok,运行得到flag
2022/09/22
[UTCTF2020]basic-re
检查文件
elf64位文件,未加壳,直接拖入ida
送分的题。。。
2022/09/22