一次对软件的逆向分析

本次逆向分析的软件是朋友大一期末大作业。
运行环境windows10,Dev-c++ 5.11

以下为源代码:

include<stdio.h>

include<stdlib.h>

include<string.h>

define L sizeof(struct book)

struct book //定义储存信息的结构体
{
long num;
char name[40];
char day[20];
float price;
struct book *next;
};
FILE *f; //定义文件指针,用于读文件
FILE *p; //定义文件指针,用于写文件
struct book *add1; //全局add储存结构体 首 地址
struct book *add2; //全局add储存结构体 尾 地址
int n; //一号开关,用于控制
int a; //二号记号,用于控制
int akt; //记录链表节点数,用于循环读写文件

void guanlicaidan(void); //用于 展示管理员界面 的函数
void addbook(void); //用于 添加图书 的函数
void change(void); //用于 修改图书信息 的函数
void delbook(void); //用于 删除所有图书 的函数
void del(void); //用于 删除单本书 的函数
void showbook(void); //用于 列出所有图书 的函数
void checkbook(void); //用于 查询指定图书 的函数
void move(void); //用于 移动图书位置 的函数
void turnoff(void); //用于 关闭系统 的函数
void baocuo(void); //用于 报错 的函数
void write(void); //用于 读文件 的函数
void read(void); //用于 写文件 的函数

void guanlicaidan(void) //实现 展示管理员界面 及 命令中转 *
{
int zhiling;
system("color 06");
printf("=\n");
printf("| |\n");
printf("| 欢迎使用下北泽图书管理系统! |\n");
printf("| 该版本为1.2.0内测版本! |\n");
printf("| 请选择您要执行的操作: |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 2.列出所有书籍 |\n");
printf("| 3.修改书籍信息 |\n");
printf("| 4.删除指定书籍 |\n");
printf("| 5.移动书籍位置 |\n");
printf("| 0.退出系统 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&zhiling);
system("cls");
if(zhiling1)
addbook();
else if(zhiling
2)
showbook();
else if(zhiling3)
change();
else if(zhiling
4)
del();
else if(zhiling5)
move();
else if(zhiling
0)
turnoff();
else
baocuo();
return;
}

void addbook(void) //添加书籍 函数 *
{
struct book p1,p2,*p3;
int xuanze,shuliang,i=1;
printf("=\n");
printf("| |\n");
printf("| 请选择: |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze0) //返回主菜单还是继续执行
return;
else if(xuanze
1)
{
printf("=\n");
printf("| |\n");
printf("| 请输入需要添加的书籍的数量: |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&shuliang);
system("cls");
if(shuliang<=0)
{
baocuo();
return;
}
else
{
p1=p2=NULL;
printf("=\n");
printf("| |\n");
printf("| 请按照"名字 日期 价格"的格式输入: |\n");
printf("| |\n");
printf("
=\n\n");
p1=(struct book *)malloc(L);
scanf("%s %s %f",p1->name,p1->day,&p1->price);
p3=p2=p1;
for(i=2;;i++)
{
if(shuliang1)
break;
p2=p1;
p1=(struct book *)malloc(L);
scanf("%s %s %f",p1->name,p1->day,&p1->price);
p2->next=p1;
if(i
shuliang)
break;
}
p1->next=NULL;
if(add1NULL) //判断是否为结构体第一个节点
{
add1=p3;
add2=p1;
for(i=1;;i++)
{
p3->num=i;
if(i
shuliang)
break;
p3=p3->next;
}
}
else if(add1!=NULL)
{
add2->next=p3;
for(i=1;;i++)
{
p3->num=(add2->num)+i;
if(ishuliang)
break;
p3=p3->next;
}
add2=p1;
}
system("cls");
printf("
=\n");
printf("| |\n");
printf("| 输入完毕! |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
===\n\n");
getchar();
getchar();
system("cls");
return;
}
}
else
{
baocuo();
return;
}
}

void showbook(void) //列出所有图书 函数 *
{
struct book p1,p2;
int xuanze;
if(add1NULL)
{
printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息,请添加书籍! |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
1)
{
addbook();
return;
}
else if(xuanze0)
return;
else
{
baocuo();
return;
}
}
else
{
p1=p2=add1;
printf("
=\n");
printf(" \n");
for(;😉
{
printf("编号:%ld 书名:%s 日期:%s 价格:%.2f元\n",p1->num,p1->name,p1->day,p1->price);
if(p1->next!=NULL)
p1=p1->next;
else
break;
}
printf(" \n");
printf("
=\n");
printf("\n");
printf("
=\n");
printf("| |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
===\n\n");
getchar();
getchar();
system("cls");
return;
}
}

void change(void) //修改图书信息函数 函数*
{
struct book p1,p2;
int xuanze,weizhi=1,shuliang=0,cishu=0;
p1=p2=add1;
if(add1NULL) //展示所有书籍
{
printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息! |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
system("cls");
return;
}
else
{
p1=p2=add1;
printf("
=\n");
printf(" \n");
if(add1
add2)
{
printf("编号:%ld 书名:%s 日期:%s 价格:%.2f元\n",p1->num,p1->name,p1->day,p1->price);
}
for(;😉
{
printf("编号:%ld 书名:%s 日期:%s 价格:%.2f元\n",p1->num,p1->name,p1->day,p1->price);
if(p1->next!=NULL)
p1=p1->next;
else
break;
}
printf(" \n");
printf("
=\n\n");
}
printf("
=\n");
printf("| |\n");
printf("| 请输入需修改的书籍的数量 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&shuliang);
system("cls");
if(shuliang<=0)
{
baocuo();
return;
}
for(cishu=1;cishu<=shuliang;cishu++) //开始修改
{
p1=p2=add1; //展示所有书籍
printf("
=\n");
printf(" \n");
if(add1
add2)
{
printf("编号:%ld 书名:%s 日期:%s 价格:%.2f元\n",p1->num,p1->name,p1->day,p1->price);
}
for(;😉
{
printf("编号:%ld 书名:%s 日期:%s 价格:%.2f元\n",p1->num,p1->name,p1->day,p1->price);
if(p1->next!=NULL)
p1=p1->next;
else
break;
}
printf(" \n");
printf("
=\n\n");
printf("
=\n");
printf("| |\n");
printf("| 请输入需要修改的书籍编号 |\n");
printf("| 或输入0返回主菜单(修改已保存) |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
p1=p2=add1;
if(xuanze
0)
return;
else if((xuanze<0)||(xuanze>add2->num))
{
baocuo();
return;
}
else
{
while(weizhi!=xuanze)
{
p1=p1->next;
weizhi++;
}
printf("
=\n\n");
printf(" 这是修改前的信息:\n");
printf(" 书名:%s 日期:%s 价格:%5.2f\n\n",p1->name,p1->day,p1->price);
printf("
=\n\n");
printf("
=\n");
printf("| |\n");
printf("| 请输入修改后的信息: |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%s %s %f",p1->name,p1->day,&p1->price);
system("cls");
if(cishu<shuliang)
{
printf("
=\n");
printf("| |\n");
printf("| 修改成功! |\n");
printf("| 输入Enter键开始修改下一本书籍 |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
system("cls");
}
else
{
printf("
=\n");
printf("| |\n");
printf("| 所有书籍修改完毕! |\n");
printf("| 输入Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=====\n\n");
getchar();
getchar();
system("cls");
return;
}
}
}
}

void del(void)
{
long delnum;
struct book *p = add1;
struct book *prev = NULL;
struct book *t;
struct book p1,p2;
int xuanze;
if(add1NULL)
{ printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息,请添加书籍! |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 2.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
1)
addbook();
else
guanlicaidan();
}
else
{
p1=p2=add1;
printf("=\n");
printf(" \n");
while(p2->next!=NULL||p2
p1)
{
p2=p1;
printf("编号:%ld 书名:%s 日期:%s 价格:%5.2f元\n",p1->num,p1->name,p1->day,p1->price);
p1=p1->next;
}
printf(" \n");
printf("
===\n");
printf("\n");

	printf("==================================================\n");
	printf("|                                                |\n");
	printf("|             请输入删除的图书编号:             |\n");
	printf("|                                                |\n");
	printf("==================================================\n");
scanf("%ld", &delnum);

while (p != NULL)
{
    if (p->num == delnum)
    {
        if (prev == NULL) // 删除头节点的情况
        {
            add1 = p->next;
        }
        else
        {
            prev->next = p->next;
        }

        t = p;
        p = p->next;
        free(t);
    system("cls");
    printf("==================================================\n");
	printf("|                                                |\n");
	printf("|                   图书删除成功!               |\n");
	printf("|              输入Enter键返回主菜单!            |\n");
	printf("|                                                |\n");
	printf("==================================================\n");
        break;
    }
    else
    {
        prev = p;
        p = p->next;
    }
}

if (prev == NULL&&p==NULL)
{
	system("cls");
    printf("===================================================\n");
	printf("|                                                  |\n");
	printf("|                未找到需要删除的图书!            |\n");
	printf("|                输入Enter键返回主菜单!            |\n");
	printf("|                                                  |\n");
	printf("===================================================\n");
}
else
{
    // 更新图书编号
    p = add1;
    long Num = 1;
    while (p != NULL)
    {
        p->num = Num;
        Num++;
        p = p->next;
    }

    // 更新尾节点
    struct book *last = add1;
    while (last->next != NULL)
    {
        last = last->next;
    }
    add2 = last;
}

// 清空输入缓冲区
while (getchar() != '\n')
	;

getchar();  // 暂停等待用户按下ENTER

system("cls");
guanlicaidan();

}
}

void move(void)
{
long nodeNum;
int newPosition;
long Num=1;
struct book p1,p2;
int xuanze;
if(add1NULL)
{ printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息,请添加书籍! |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 2.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
1)
addbook();
else
guanlicaidan();
}
else
{
p1=p2=add1;
printf("=\n");
printf(" \n");
while(p2->next!=NULL||p2
p1)
{
p2=p1;
printf(" 编号:%ld 书名:%s 日期:%s 价格:%5.2f元\n",p1->num,p1->name,p1->day,p1->price);
p1=p1->next;
}
printf(" \n");
printf("
===\n");
printf("\n");

	printf("====================================================\n");
	printf("|                                                  |\n");
	printf("|             请输入要移动的图书编号:             |\n");
	printf("|                                                  |\n");
	printf("====================================================\n");
scanf("%ld", &nodeNum);

	printf("=====================================================\n");
	printf("|                                                   |\n");
	printf("|             请输入要移动到的目标编号:            |\n");
	printf("|                                                   |\n");
	printf("=====================================================\n");
scanf("%d", &newPosition);

struct book *prev = NULL;
struct book *p = add1;

system("cls"); 


// 遍历链表,找到目标节点和其前一个节点
while (p != NULL && p->num != nodeNum)
{
    prev = p;
    p = p->next;
}

// 如果找到了目标节点
if (p != NULL)
{
	if (newPosition == nodeNum)
    {
    system("cls");
    printf("============================================================\n");
	printf("|                                                          |\n");
	printf("|             书籍已经在目标位置上,无需移动!             |\n");
	printf("|                  输入Enter键返回主菜单!                  |\n");
	printf("|                                                          |\n");
	printf("============================================================\n");

	    
    }
    // 将目标节点从链表中断开
    if (prev != NULL)
    {
        prev->next = p->next;
    }
    else
    {
        add1 = p->next;
    }

    // 根据新位置插入目标节点
    if (newPosition == 1)
    {
        p->next = add1;
        add1 = p;
    }
    else
    {
        struct book *temp = add1;
        int count = 1;

        while (temp->next != NULL && count < newPosition - 1)
        {
            temp = temp->next;
            count++;
        }

        p->next = temp->next;
        temp->next = p;
    }

    // 更新尾节点
    struct book *last = add1;
    while (last->next != NULL)
    {
        last = last->next;
    }
    add2 = last;
	p = add1;
while (p != NULL)
{
    p->num = Num;
    Num++;
    p = p->next;
}
	system("cls");
    printf("==================================================\n");
	printf("|                                                |\n");
	printf("|                   书籍移动成功!               |\n");
	printf("|               输入Enter键返回主菜单!           |\n");
	printf("|                                                |\n");
	printf("==================================================\n");
    
    
}
else
{
	system("cls");
    printf("================================================\n");
	printf("|                                              |\n");
	printf("|         未找到编号,请更换编号后再试!       |\n");
	printf("|             输入Enter键返回主菜单!           |\n");
	printf("|                                              |\n");
	printf("================================================\n");
    
}
while (getchar() != '\n')
	;

getchar();  // 暂停等待用户按下ENTER
system("cls");
guanlicaidan();

}
}

void turnoff(void) //关闭系统 函数 *
{
int xuanze;
printf("=\n");
printf("| |\n");
printf("| ");
printf("\x1b[31m" "您确定要退出系统吗?" "\x1b[0m");
printf("\x1b[33m" " |\n" "\x1b[0m");
printf("\x1b[33m" "| |\n" "\x1b[0m");
printf("\x1b[33m" "| " "\x1b[0m");
printf("\x1b[37m" "1.确定" "\x1b[0m");
printf("\x1b[33m" " |\n" "\x1b[0m");
printf("\x1b[33m" "| 0.取消 |\n" "\x1b[0m");
printf("\x1b[33m" "| |\n" "\x1b[0m");
printf("\x1b[33m" "
=\n\n" "\x1b[0m");
scanf("%d",&xuanze);
system("cls");
system("color 06");
if(xuanze1)
{
printf("
=\n");
printf("| |\n");
printf("| 感谢您的使用,期待下一次见面! |\n");
printf("| 按Enter键退出系统! |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
write();
exit(0);
}
else if(xuanze
0)
return;
else
{
baocuo();
return;
}
}

void baocuo(void) //报错 函数 *
{
system("color 06");
printf("=\n");
printf("| |\n");
printf("| 输入错误! |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
system("cls");
return;
}

void read(void) //读文件 函数 *
{
struct book p1,p2;
int i;
p1=(struct book *)malloc(L);
add2=add1=p2=p1;
fscanf(f,"%ld %s %s %f",&p1->num,p1->name,p1->day,&p1->price);
p1->next=NULL;
if(akt!=1)
{
for(i=2;i<=akt;i++)
{
p1=(struct book *)malloc(L);
fscanf(f,"%ld %s %s %f ",&p1->num,p1->name,p1->day,&p1->price);
p2->next=p1;
p2=p1;
}
p1->next=NULL;
add2=p1;
}
return;
}

void write(void) //写文件 函数 *
{
struct book p1,p2;
int i;
char h='0';
char mn='#';
if(add2NULL)
{
fputc(mn,p);
return;
}
p2=p1=add1;
h=(char)((add2->num)+48);
fputc(h,p);
for(;😉
{
p2=p1;
fprintf(p,"%ld %s %s %.2f ",p1->num,p1->name,p1->day,p1->price);
if(p1->next
NULL)
break;
p1=p1->next;
}
fclose(p);
return;
}

int main()
{
char h='0';
char name[]="114514.txt";
system("mode con cols=108 lines=30"); // 窗口宽度高度
system("color 06"); //设置控制台背景为黑,字体为黄
add1=add2=NULL;
f=fopen(name,"r+"); //定义文件指针 f
h=fgetc(f); //用 h 读出文件状态
if(h!='#') //如果为空文档跳过读的过程
{
akt=(int)(h)-48;
read();
}
p=fopen(name,"w"); //定义文件指针p(“w”覆盖先前数据)
for(;😉
{
system("cls");
guanlicaidan(); //调用管理员菜单,开始执行程序
}
return 0;
}
主要存在的问题如下:
1.功能不完善,缺少查询指定书籍和删除所有书籍等功能
2.部分变量命名规则模糊,不利于理解和维护

以下为修改部分:

include<stdio.h>

include<stdlib.h>

include<string.h>

define L sizeof(struct book)

struct book //定义储存信息的结构体
{
long num;
char name[40];
char day[20];
float price;
struct book *next;
};
FILE *pointer_read; //定义文件指针,用于读文件
FILE *pointer_write; //定义文件指针,用于写文件
struct book *add1; //全局add储存结构体 首 地址
struct book *add2; //全局add储存结构体 尾 地址
int disjunctor; //开关,用于控制
int Number_structNode; //记录链表节点数,用于循环读写文件

void checkbook(void) //查询指定图书 函数 *
{
struct book p1,p2;
char mubiao[40];
int xuanze;
p1=p2=add1;
if(add1NULL) //判断书库有无书籍
{
printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息,请添加书籍! |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
1)
{
addbook();
return;
}
else if(xuanze0)
return;
else
{
baocuo();
return;
}
}
else
{
printf("
=\n");
printf("| |\n");
printf("| 请选择: |\n");
printf("| |\n");
printf("| 1.根据编号检索 |\n");
printf("| 2.根据书名检索 |\n");
printf("| 3.根据日期检索 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
0)
return;
else if(xuanze1) //根据编号查找
{
printf("
=\n");
printf("| |\n");
printf("| 请输入需要查询的编号: |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze<1||xuanze>add2->num)
{
baocuo();
return;
}
else
{
while((p2->next!=NULL)||(add1
add2))
{
if(p1->numxuanze)
break;
else if(p1
add2)
{
printf("=\n");
printf("| |\n");
printf("| 未找到目标书籍! |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
system("cls");
return;
}
p2=p1;
p1=p1->next;
}
printf("=\n\n");
printf("编号:%d 书名:%s 日期:%s 价格:%.2f元\n\n",p1->num,p1->name,p1->day,p1->price);
printf("
=\n");
printf("=\n");
printf("| |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=\n\n");
getchar();
getchar();
system("cls");
return;
}
}
else if((xuanze2)||(xuanze3)) //根据书名和日期查找
{
if(xuanze2)
{
printf("
=\n");
printf("| |\n");
printf("| 请输入需要查询的书名: |\n");
printf("| |\n");
printf("
=\n\n");
}
else
{
printf("
=\n");
printf("| |\n");
printf("| 请输入需要查询的日期: |\n");
printf("| |\n");
printf("
=\n\n");
}
scanf("%s",mubiao);
system("cls");
printf("
=\n\n");
while((p2->next!=NULL||p1
p2)&&(xuanze
2)) //书名
{
if(strcmp(p1->name,mubiao)
0)
{
printf("编号:%d 书名:%s 日期:%s 价格:%.2f\n",p1->num,p1->name,p1->day,p1->price);
disjunctor=1;
break;
}
p2=p1;
p1=p1->next;
}
while((p2->next!=NULL||p1
p2)&&(xuanze!=2)) //日期
{
if(strcmp(p1->day,mubiao)
0)
{
printf("编号:%d 书名:%s 日期:%s 价格:%.2f\n",p1->num,p1->name,p1->day,p1->price);
disjunctor=1;
}
p2=p1;
p1=p1->next;
}
if(disjunctor
0)
{
printf(" 未找到目标书籍! \n");
}
printf("\n");
printf("
=\n\n");
printf("
=\n");
printf("| |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
===============\n\n");
disjunctor=0;
getchar();
getchar();
system("cls");
return;
}
else
{
baocuo();
return;
}
}
}

void delbook(void) //删除所有图书 函数 *
{
struct book p1,p2;
int xuanze;
if(add1NULL) //判断书库中有没有书
{
printf("
=\n");
printf("| |\n");
printf("| 书库中暂无书籍信息,请添加书籍! |\n");
printf("| |\n");
printf("| 1.添加书籍 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n\n");
scanf("%d",&xuanze);
system("cls");
if(xuanze
1)
{
addbook();
return;
}
else if(xuanze0)
return;
else
{
baocuo();
return;
}
}
else
{
printf("
=\n");
printf("| |\n");
printf("| ");
printf("\x1b[31m" "您确定要删除所有书籍信息吗?" "\x1b[0m");
printf("\x1b[33m" " |\n" "\x1b[0m");
printf("\x1b[33m" "| |\n" "\x1b[0m");
printf("\x1b[33m" "| " "\x1b[0m");
printf("\x1b[37m" "1.确定" "\x1b[0m");
printf("\x1b[33m" " |\n" "\x1b[0m");
printf("\x1b[33m" "| 0.取消 |\n" "\x1b[0m");
printf("\x1b[33m" "| |\n" "\x1b[0m");
printf("\x1b[33m" "
=\n\n" "\x1b[0m");
scanf("%d",&xuanze);
system("cls");
system("color 06");
if(xuanze
0)
return;
else if(xuanze1)
{
printf("
=\n");
printf("| |\n");
printf("| 所有书籍信息已删除! |\n");
printf("| |\n");
printf("| 1.恢复书籍信息 |\n");
printf("| 0.返回主菜单 |\n");
printf("| |\n");
printf("
=\n");
scanf("%d",&xuanze);
if(xuanze
1)
{
printf("=\n");
printf("| |\n");
printf("| 所有书籍信息已恢复! |\n");
printf("| 按Enter键返回主菜单! |\n");
printf("| |\n");
printf("
=\n\n");
return;
}
else
{
p1=p2=add1;
for(;😉 //循环删除并释放内存
{
if(p1==add2)
{
free(p1);
p1=NULL;
break;
}
p1=p1->next;
free(p2);
p2=NULL;
p2=p1;
}
add2=add1=NULL; //重置首地址尾地址
system("cls");
return;
}
}
else
{
baocuo();
return;
}
}
}
软件测试截图如下:












总结:
经过这次简单的逆向工程,我深刻意识到逆向工程是一项非常考验编码经验、耐心、兴趣的工作。在这次逆向中,我多次因难以读懂源码逻辑、变量命名规则混乱而一筹莫展,最终还是靠着对未知编程结构的好奇完全理解了代码,那种拨云见日的快感,堪比程序员界的"尤里卡时刻"。

posted @ 2025-02-27 21:23  赫曼  阅读(29)  评论(0)    收藏  举报