Introduction

A "binary bomb" is a program provided to students as an object code file. When run, it 
prompts the user to type in 6 different strings. If any of these is incorrect, the bomb 
"explodes," printing an error message and logging the event on a grading server. Students 
must "defuse" their own unique bomb by disassembling and reverse engineering the program 
to determine what the 6 strings should be. The lab teaches students to understand assembly
language, and also forces them to learn how to use a debugger. It's also great fun. A
legendary lab among the CMU undergrads.Here's a Linux/x86-64 binary bomb that you can 
try out for yourself. The feature that notifies the grading server has been disabled, 
so feel free to explode this bomb with impunity. If you're an instructor with a CS:APP 
account, then you can download the solution.
一个'binary bomb'是一个作为目标代码文件提供给学生的程序。当运行的时候, 它会提醒用户输入六个
不同的字符串。如果其中任何一个不正确,炸弹就会爆炸,打印错误消息并将事件记录在评分服务器上。
学生必须通过对程序进行反汇编和逆向工程来"拆除"他们自己独特的炸弹, 以确定6个字符串应该是什么。
这个lab教学生理解汇编语言,并强迫他们学习如何使用调试器。这也很有趣。CMU 本科生中的传奇实验室。
这是一个 Linux/x86-64 二进制炸弹,您可以自己尝试. ......

一:Overview

1.1. Binary Bombs

A "binary bomb" is a Linux executable C program that consists of six "phases." 
Each phase expects the student to enter a particular string on stdin. If the student 
enters the expected string, then that phase is "defused." Otherwise the bomb "explodes" 
by printing "BOOM!!!". The goal for the students is to defuse as many phases as possible.
“binary bomb”是由六个“阶段”组成的Linux可执行C程序. 每个阶段都希望学生在标准输入上输入一个特定
的字符串。 如果学生输入了预期的字符串,则该阶段被“拆除”。否则炸弹会通过打印“BOOM!!!”来“爆炸”。
学生的目标是消除尽可能多的阶段。

1.2. Solving Binary Bombs

In order to defuse the bomb, students must use a debugger, typically gdb or ddd, to 
disassemble the binary and single-step through the machine code in each phase. The idea 
is to understand what each assembly statement does, and then use this knowledge to infer 
the defusing string. Students earn points for defusing phases, and they lose points 
(configurable by the instructor, but typically 1/2 point) for each explosion. Thus, 
they quickly learn to set breakpoints before each phase and the function that explodes 
the bomb. It's a great lesson and forces them to learn to use a debugger. 
为了拆除炸弹, 学生必须使用调试器, 通常是gdb或ddd, 来反汇编二进制文件并单步执行每个阶段的
机器代码. 这个想法是了解每个汇编语句的作用,然后使用这些知识来推断拆解字符串。因此,他们很
快学会了在每个阶段之前设置断点以及引爆炸弹的功能。这是一个很好的迫使他们学习使用调试器的
学习机会.

1.3. Autograding Service

We have created a stand-alone user-level autograding service that
handles all aspects of the Bomb Lab for you: Students download their
bombs from a server. As the students work on their bombs, each
explosion and defusion is streamed back to the server, where the
current results for each bomb are displayed on a Web "scoreboard."
There are no explicit handins and the lab is self-grading.

The autograding service consists of four user-level programs that run
in the main ./bomblab directory:

- Request Server (bomblab-requestd.pl). Students download their bombs
and display the scoreboard by pointing a browser at a simple HTTP
server called the "request server." The request server builds the
bomb, archives it in a tar file, and then uploads the resulting tar
file back to the browser, where it can be saved on disk and
untarred. The request server also creates a copy of the bomb and its
solution for the instructor.

- Result Server (bomblab-resultd.pl). Each time a student defuses a
bomb phase or causes an explosion, the bomb sends a short HTTP
message, called an "autoresult string," to an HTTP "result server,"
which simply appends the autoresult string to a "scoreboard log file."

- Report Daemon (bomblab-reportd.pl). The "report daemon" periodically
scans the scoreboard log file. The report daemon finds the most recent
defusing string submitted by each student for each phase, and
validates these strings by applying them to a local copy of the
student's bomb.  It then updates the HTML scoreboard that summarizes
the current number of explosions and defusions for each bomb, rank
ordered by the total number of accrued points.

- Main daemon (bomblab.pl). The "main daemon" starts and nannies the
request server, result server, and report deamon, ensuring that
exactly one of these processes (and itself) is running at any point in
time. If one of these processes dies for some reason, the main daemon
detects this and automatically restarts it. The main daemon is the
only program you actually need to run.
我们创建了一个独立的用户级自动评分服务,为您处理Bomb Lab的所有方面, 学生从服务器下载他
们的炸弹。当学生们处理他们的炸弹时,每次爆炸和拆解都会流回服务器,每个炸弹的当前结果显示
在网络“记分牌”上。没有明确的交接,lab是自我评分的。

自动分级服务由四个在主 ./bomblab 目录中运行的用户级程序组成:

- 请求服务器(bomblab-requestd.pl)。学生通过将浏览器指向一个称为“请求服务器”的
简单 HTTP 服务器来下载他们的炸弹并显示记分板。请求服务器构建炸弹,将其存档在 tar 文件中
,然后将生成的 tar 文件上传回浏览器,在那里可以将其保存在磁盘上并解压缩。请求服务器还为教
员创建炸弹及其解决方案的副本。

- 结果服务器(bomblab-resultd.pl)。每次学生拆除炸弹阶段或引起爆炸时,炸弹都会向
HTTP“结果服务器”发送一条名为“自动结果字符串”的简短 HTTP 消息,该服务器只是将自动结果
字符串附加到“记分板日志文件”。

- 报告守护程序(bomblab-reportd.pl)。 “报告守护程序”定期扫描记分板日志文件。
报告守护程序查找每个学生为每个阶段提交的最近的拆弹字符串,并通过将它们应用于学生炸
弹的本地副本来验证这些字符串。然后它更新 HTML 记分板,该记分板总结了每个炸弹的当前
爆炸和拆除次数,按累计点数排序。

- 主守护进程 (bomblab.pl)。 “主守护进程”启动并保姆
请求服务器、结果服务器和报告守护程序,确保
这些进程中的一个(及其本身)在任何时间点都在运行
时间。如果这些进程之一因某种原因死亡,主守护进程
检测到这一点并自动重新启动它。主要守护进程是
只有你真正需要运行的程序。

二:Files

The ./bomblab directory contains the following files:

Makefile                - For starting/stopping the lab and cleaning files
bomblab.pl*             - Main daemon that nannies the other servers & daemons
Bomblab.pm              - Bomblab configuration file    
bomblab-reportd.pl*     - Report daemon that continuously updates scoreboard
bomblab-requestd.pl*    - Request server that serves bombs to students
bomblab-resultd.pl*     - Result server that gets autoresult strings from bombs
bomblab-scoreboard.html - Real-time Web scoreboard
bomblab-update.pl*      - Helper to bomblab-reportd.pl that updates scoreboard
bombs/                  - Contains the bombs sent to each student
log-status.txt          - Status log with msgs from various servers and daemons
log.txt                 - Scoreboard log of autoresults received from bombs
makebomb.pl*            - Helper script that builds a bomb
scores.txt              - Summarizes current scoreboard scores for each student
src/                    - The bomb source files
writeup/                - Sample Latex Bomb Lab writeup
./bomblab 目录包含以下文件:

Makefile - 用于启动/停止实验室和清理文件
bomblab.pl* - 主守护进程,为其他服务器和守护进程保驾护航
Bomblab.pm - Bomblab 配置文件
bomblab-reportd.pl* - 不断更新记分板的报告守护程序
bomblab-requestd.pl* - 向学生提供炸弹的请求服务器
bomblab-resultd.pl* - 从炸弹中获取自动结果字符串的结果服务器
bomblab-scoreboard.html - 实时网络记分牌
bomblab-update.pl* - 更新记分板的bomblab-reportd.pl 的助手
炸弹/ - 包含发送给每个学生的炸弹
log-status.txt - 带有来自各种服务器和守护进程的消息的状态日志
log.txt - 从炸弹收到的自动结果的记分板日志
makebomb.pl* - 构建炸弹的辅助脚本
score.txt - 总结每个学生的当前记分板分数
src/ - 炸弹源文件
writeup/ - 解题示例

三:Bomb Terminology

LabID: Each instance (offering) of the lab is identified by a unique
name, e.g., "f12" or "s13", that the instructor chooses. Explosion and
diffusions from bombs whose LabIDs are different from the current
LabID are ignored. The LabID must not have any spaces.

BombID: Each bomb in a given instance of the lab has a unique
non-negative integer called the "bombID."

Notifying Bomb: A bomb can be compiled with a NOTIFY option that
causes the bomb to send a message each time the student explodes or
defuses a phase. Such bombs are called "notifying bombs." 

Quiet Bomb: If compiled with the NONOTIFY option, then the bomb
doesn't send any messages when it explodes or is defused. Such bombs
are called "quiet bombs."

We will also find it helpful to distinguish between custom and
generic bombs:

Custom Bomb: A "custom bomb" has a BombID > 0, is associated with a
particular student, and can be either notifying or quiet. Custom
notifying bombs are constrained to run on a specific set of Linux
hosts determined by the instructor. On the other hand, custom quiet
bombs can run on any Linux host.

Generic Bomb: A "generic bomb" has a BombID = 0, isn't associated with
any particular student, is quiet, and hence can run on any host.

四. Offering the Bomb Lab

There are two basic flavors of Bomb Lab: In the "online" version, the
instructor uses the autograding service to handout a custom notifying
bomb to each student on demand, and to automatically track their
progress on the realtime scoreboard. In the "offline" version, the
instructor builds, hands out, and grades the student bombs manually,
without using the autograding service.

While both version give the students a rich experience, we recommend
the online version. It is clearly the most compelling and fun for the
students, and the easiest for the instructor to grade. However, it
requires that you keep the autograding service running non-stop,
because handouts, grading, and reporting occur continuously for the
duration of the lab. We've made it very easy to run the service, but
some instructors may be uncomfortable with this requirement and will
opt instead for the offline version.

Here are the directions for offering both versions of the lab.

4.1. Create a Bomb Lab Directory

Identify the generic Linux machine ($SERVER_NAME) where you will
create the Bomb Lab directory (./bomblab) and, if you are offering the
online version, run the autograding service. You'll only need to have
a user account on this machine. You don't need root access.

Each offering of the Bomb Lab starts with a clean new ./bomblab
directory on $SERVER_NAME. For example:

    linux> tar xvf bomblab.tar
    linux> cd bomblab   
    linux> make cleanallfiles

4.2 Configure the Bomb Lab

Configure the Bomb Lab by editing the following file:

./Bomblab.pm - This is the main configuration file. You will only need
to modify or inspect a few variables in Section 1 of this file. Each
variable is preceded by a descriptive comment. If you are offering the
offline version, you can ignore most of these settings.

If you are offering the online version, you will also need to edit the 
following file:

./src/config.h - This file lists the domain names of the hosts that
notifying bombs are allowed to run on. Make sure you update this
correctly, else you and your students won't be able to run your bombs.

4.3. Update the Lab Writeup

Once you have updated the configuration files, modify the Latex lab
writeup in ./writeup/bomblab.tex for your environment. Then type the
following in the ./writeup directory:

	unix> make clean
	unix> make 

This will create ps and pdf versions of the writeup

4.4 Running the Online Bomb Lab

------
4.4.1. Short Version
------
From the ./bomblab directory:

(1) Reset the Bomb Lab from scratch by typing
    linux> make cleanallfiles

(2) Start the autograding service by typing
    linux> make start

(3) Stop the autograding service by typing
    linux> make stop    

You can start and stop the autograding service as often as you like
without losing any information. When in doubt "make stop; make start"
will get everything in a stable state. 

However, resetting the lab deletes all old bombs, status logs, and the
scoreboard log. Do this only during debugging, or the very first time
you start the lab for your students.

Students request bombs by pointing their browsers at 
    http://$SERVER_NAME:$REQUESTD_PORT/

Students view the scoreboard by pointing their browsers at      
    http://$SERVER_NAME:$REQUESTD_PORT/scoreboard 

------
4.4.2. Long Version
------

(1) Resetting the Bomb Lab. "make stop" ensures that there are no
servers running. "make cleanallfiles" resets the lab from scratch,
deleting all data specific to a particular instance of the lab, such
as the status log, all bombs created by the request server, and the
scoreboard log. Do this when you're ready for the lab to go "live" to
the students.

Resetting is also useful while you're preparing the lab. Before the
lab goes live, you'll want to request a few bombs for yourself, run
them, defuse a few phases, explode a few phases, and make sure that
the results are displayed properly on the scoreboard.  If there is a
problem (say because you forgot to update the list of machines the
bombs are allowed to run in src/config.h) you can fix the
configuration, reset the lab, and then request and run more test
bombs.

CAUTION: If you reset the lab after it's live, you'll lose all your
records of the students bombs and their solutions. You won't be able
to validate the students handins. And your students will have to get
new bombs and start over.

(2) Starting the Bomb Lab. "make start" runs bomblab.pl, the main
daemon that starts and nannies the other programs in the service,
checking their status every few seconds and restarting them if
necessary:

(3) Stopping the Bomb Lab. "make stop" kills all of the running
servers. You can start and stop the autograding service as often as
you like without losing any information. When in doubt "make stop;
make start" will get everything in a stable state.

Request Server: The request server is a simple special-purpose HTTP
server that (1) builds and delivers custom bombs to student browsers
on demand, and (2) displays the current state of the real-time
scoreboard.

A student requests a bomb from the request daemon in two
steps: First, the student points their favorite browser at

    http://$SERVER_NAME:$REQUESTD_PORT/

For example, <http://foo.cs.cmu.edu:15213/>.  The request server
responds by sending an HTML form back to the browser.  Next, the
student fills in this form with their user name and email address, and
then submits the form. The request server parses the form, builds and
tars up a notifying custom bomb with bombID=n, and delivers the tar
file to the browser. The student then saves the tar file to disk. When
the student untars this file, it creates a directory (./bomb<n>) with
the following four files:

    bomb*        Notifying custom bomb executable
    bomb.c       Source code for the main bomb routine
    ID           Identifies the student associated with this bomb
    README       Lists bomb number, student, and email address

The request server also creates a directory (bomblab/bombs/bomb<n>)
that contains the following files:

    bomb*        Custom bomb executable 
    bomb.c       Source code for main routine
    bomb-quiet*  A quiet version of bomb used for autograding
    ID           Identifies the user name assigned to this bomb
    phases.c     C source code for the bomb phases
    README       Lists bombID, user name, and email address
    solution.txt The solution for this bomb

Result Server: Each time a student defuses a phase or explodes their
bomb, the bomb sends an HTTP message (called an autoresult string) to
the result server, which then appends the message to the scoreboard
log. Each message contains a BombID, a phase, and an indication of the
event that occurred.  If the event was a defusion, the message also
contains the "defusing string" that the student typed to defuse the
phase.

Report Daemon: The report daemon periodically scans the scoreboard log
and updates the Web scoreboard. For each bomb, it tallies the number
of explosions, the last defused phase, validates each last defused
phase using a quiet copy of the bomb, and computes a score for each
student in a tab delimited text file called "scores.txt." The update
frequency is a configuration variable in Bomblab.pm.

Instructors and students view the scoreboard by pointing their
browsers at:

    http://$SERVER_NAME:$REQUESTD_PORT/scoreboard 

------
4.4.3. Grading the Online Bomb Lab
------
The online Bomb Lab is self-grading. At any point in time, the
tab-delimited file (./bomblab/scores.txt) contains the most recent
scores for each student. This file is created by the report daemon
each time it generates a new scoreboard.

------
4.4.4. Additional Notes on the Online Bomb Lab
------
* Since the request server and report daemon both need to execute
bombs, you must include $SERVER_NAME in the list of legal machines in
your bomblab/src/config.h file.

* All of the servers and daemons are stateless, so you can stop ("make
stop") and start ("make start") the lab as many times as you like
without any ill effects. If you accidentally kill one of the daemons,
or you modify a daemon, or the daemon dies for some reason, then use
"make stop" to clean up, and then restart with "make start". If your
Linux box crashes or reboots, simply restart the daemons with "make
start".

* Information and error messages from the servers are appended to the
"status log" in bomblab/log-status.txt. Servers run quietly, so they
can be started from initrc scripts at boot time.

* See src/README for more information about the anatomy of bombs and
how they are constructed. You don't need to understand any of this to
offer the lab. It's provided only for completeness.

* Before going live with the students, we like to check everything out
by running some tests. We do this by typing

    linux> make cleanallfiles   
    linux> make start

Then we request a bomb for ourselves by pointing a Web browser at

    http://$SERVER_NAME:$REQUESTD_PORT

After saving our bomb to disk, we untar it, copy it to a host in the
approved list in src/config.h, and then explode and defuse it a couple
of times to make sure that the explosions and diffusion are properly
recorded on the scoreboard, which we check at

    http://$SERVER_NAME:$REQUESTD_PORT/scoreboard

Once we're satisfied that everything is OK, we stop the lab

    linux> make stop

and then go live:

    linux> make cleanallfiles
    linux> make start
        
Once we go live, we type "make stop" and "make start" as often as we
need to, but we are careful never to type "make cleanallfiles" again.

----
4.5. Running the Offline Bomb Lab
----
In this version of the lab, you build your own quiet bombs manually
and then hand them out to the students.  The students work on defusing
their bombs offline (i.e., independently of any autograding service)
and then handin their solution files to you, each of which you grade
manually.

You can use the makebomb.pl script to build your own bombs
manually. The makebomb.pl script also generates the bomb's solution.
Type "./makebomb.pl -h" to see its arguments.

Option 1: The simplest approach for offering the offline Bomb Lab is
to build a single generic bomb that every student attempts to defuse:

    linux> ./makebomb.pl -s ./src -b ./bombs

This will create a generic bomb and some other files in ./bombs/bomb0: 

    bomb*        Generic bomb executable (handout to students)
    bomb.c       Source code for main routine (handout to students)
    bomb-quiet*  Ignore this
    ID           Ignore this
    phases.c     C source code for the bomb phases
    README       Ignore this    
    solution.txt The solution for this bomb 

You will handout only two of these files to the students: ./bomb and ./bomb.c 

The students will handin their solution files, which you can validate
by feeding to the bomb:

    linux> cd bombs/bomb0
    linux> ./bomb < student_solution.txt

This option is easy for the instructor, but we don't recommend it
because it is too easy for the students to cheat.

Option 2. The other option for offering an offline lab is to use the
makebomb.pl script to build a unique quiet custom bomb for each
student:

    linux> ./makebomb.pl -i <n> -s ./src -b ./bombs -l bomblab -u <email> -v <uid>

This will create a quiet custom bomb in ./bombs/bomb<n> for the
student whose email address is <email> and whose user name is <uid>:

    bomb*        Custom bomb executable (handout to student)
    bomb.c       Source code for main routine (handout to student)
    bomb-quiet*  Ignore this
    ID           Identifies the student associated with this bomb
    phases.c     C source code for the bomb phases
    README       Lists bomb number, student, and email address
    solution.txt The solution for this bomb

You will handout four of these files to the student: bomb, bomb.c, ID,
and README.

Each student will hand in their solution file, which you can validate
by hand by running their custom bomb against their solution:

    linux> cd ./bombs/bomb<n>
    linux> ./bomb < student_n_solution.txt

The source code for the different phase variants is in ./src/phases/.

五:分析程序

Untitled
Untitled

每个phase_defused函数都是打印拆解成功的字符串

phase_1-phase_6就是我们要分析的六个比较

phase_1:

__int64 __fastcall phase_1(__int64 a1)
{
  __int64 result; // rax

  result = strings_not_equal(a1, "Border relations with Canada have never been better.");
  if ( result )
    explode_bomb();
  return result;
}
__int64 __fastcall strings_not_equal(_BYTE *a1, _BYTE *a2)
{
  _BYTE *v2; // rbx
  _BYTE *v3; // rbp
  int v4; // er12
  int v5; // eax
  unsigned int v6; // edx

  v2 = a1;
  v3 = a2;
  v4 = (string_length)();
  v5 = string_length(a2);
  v6 = 1;
  if ( v4 == v5 )
  {
    if ( *a1 )
    {
      if ( *a1 == *a2 )
      {
        do
        {
          ++v2;
          ++v3;
          if ( !*v2 )                           // 遍历整个字符串直到\\0
            return 0;
        }
        while ( *v2 == *v3 );
        return 1;                               // 返回1就boom
      }
      else
      {
        return 1;
      }
    }
    else
    {
      return 0;
    }
  }
  return v6;
}

显然第一个字符串就是"Border relations with Canada have never been better."

phase_2:

__int64 __fastcall phase_2(__int64 a1)
{
  __int64 result; // rax
  char *adr; // rbx
  int v3; // [rsp+0h] [rbp-38h] BYREF
  char v4; // [rsp+4h] [rbp-34h] BYREF
  char v5; // [rsp+18h] [rbp-20h] BYREF

  read_six_numbers(a1, (__int64)&v3);
  if ( v3 != 1 )                                // 先比较第一个数是否是1, 不是1就爆炸    arr[0] = 1
    explode_bomb();
  adr = &v4;                                    // v4是输入数字在栈中存放的第一个的下一个数字的地址
  do
  {
    result = (unsigned int)(2 * *((_DWORD *)adr - 1));// result = 2 * (arr[i-1])
    if ( *(_DWORD *)adr != (_DWORD)result )     // *(adr)就是arr[i], 所以这个循环比较的意思就是arr[i] = 2 * (arr[i-1])
      explode_bomb();
    adr += 4;                                   // 地址偏移4取下一个数字
  }
  while ( adr != &v5 );
  return result;
}
arr = [0]*6
arr[0] = 1
for i in range(1, 6, 1):
    arr[i] = 2 * arr[i-1]
print(arr)
# [1, 2, 4, 8, 16, 32]

得到六个数字为:1, 2, 4, 8, 16, 32

phase_3:

输入两个数字

这里有八种情况可以通过

__int64 __fastcall phase_3(__int64 a1)
{
  __int64 temp; // rax
  int num1; // [rsp+8h] [rbp-10h] BYREF
  int num2; // [rsp+Ch] [rbp-Ch] BYREF

  if ( (int)__isoc99_sscanf(a1, "%d %d", &num1, &num2) <= 1 )// sscanf成功返回参数个数, 失败返回-1
    explode_bomb();
  switch ( num1 )
  {
    case 0:
      temp = 207LL;
      break;
    case 1:
      temp = 311LL;
      break;
    case 2:
      temp = 707LL;
      break;
    case 3:
      temp = 256LL;
      break;
    case 4:
      temp = 389LL;
      break;
    case 5:
      temp = 206LL;
      break;
    case 6:
      temp = 682LL;
      break;
    case 7:
      temp = 327LL;
      break;
    default:
      explode_bomb();
  }
  if ( (_DWORD)temp != num2 )
    explode_bomb();
  return temp;
}
0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327

phase_4:

__int64 __fastcall phase_4(__int64 a1)
{
  __int64 result; // rax
  unsigned int num1; // [rsp+8h] [rbp-10h] BYREF
  int num2; // [rsp+Ch] [rbp-Ch] BYREF

  if ( __isoc99_sscanf(a1, "%d %d", &num1, &num2) != 2 || num1 > 0xE )
    explode_bomb();
  result = func4(num1, 0LL, 14LL);
  if ( result || num2 )                         // 传入num1的func4返回值和num2都必须为0
    explode_bomb();
  return result;
}
__int64 __fastcall func4(__int64 num1, __int64 zero, __int64 cnt14)
{
  int v3; // ecx
  __int64 result; // rax

  v3 = (cnt14 - zero) / 2 + zero;               // 14 / 2
  if ( v3 > num1 )
    return 2 * func4(num1, zero, (v3 - 1));
  result = 0LL;
  if ( v3 < num1 )
    return 2 * func4(num1, (v3 + 1), cnt14) + 1;
  return result;                                // 当num1 == 14/2时返回0
}

7 0

phase_5:

用我们输入的长度为6的字符串的每个字符的ASCII码&0xf来当下标取出arr中的字符元素赋值到另外一个数组中, 最后比较这个产生的字符串和"flyers"

unsigned __int64 __fastcall phase_5(__int64 a1)
{
  __int64 i; // rax
  char v3[8]; // [rsp+10h] [rbp-18h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-10h]

  v4 = __readfsqword(0x28u);
  if ( string_length(a1) != 6 )
    explode_bomb();
  for ( i = 0LL; i != 6; ++i )
    v3[i] = array_3449[*(a1 + i) & 0xF];        // 用我们输入的长度为6的字符串的每个字符的ASCII码&0xf来当下标取出arr中的字符元素赋值到另外一个数组中, 最后比较这个产生的字符串和flyers
  v3[6] = 0;
  if ( strings_not_equal(v3, "flyers") )
    explode_bomb();
  return __readfsqword(0x28u) ^ v4;
}
import string
arr = [0x6D, 0x61, 0x64, 0x75, 0x69, 0x65, 0x72, 0x73, 0x6E, 0x66, 0x6F, 0x74, 0x76, 0x62, 0x79, 0x6C]
cmp_string = "flyers"
Scope = string.digits + string.ascii_lowercase + string.ascii_uppercase
# 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
for i in range(len(cmp_string)):
    for x in Scope:     # 32, 127可以得到: )/.%&'
        if ord(cmp_string[i]) == arr[ord(x) & 15]:
            print(x, end='')
            break
# 9on567

phase_6:

__int64 __fastcall phase_6(__int64 a1)
{
  int *v1; // r13
  int ind; // er12
  int temp; // ebx
  char *adr; // rax
  unsigned __int64 i; // rsi
  __int64 *v6; // rdx
  int v7; // eax
  int one; // ecx
  __int64 l; // rbx
  char *r; // rax
  __int64 j; // rcx
  __int64 v12; // rdx
  int v13; // ebp
  __int64 result; // rax
  int our_number[6]; // [rsp+0h] [rbp-78h] BYREF
  char v16; // [rsp+18h] [rbp-60h] BYREF
  __int64 v17; // [rsp+20h] [rbp-58h]
  char v18; // [rsp+28h] [rbp-50h] BYREF
  char end_adr; // [rsp+50h] [rbp-28h] BYREF

  v1 = our_number;
  read_six_numbers(a1, our_number);
  ind = 0;
  while ( 1 )                                   // 每个字符在输入字符串中出现过后不能在后面再次出现
  {                                             // 数字不能有重复
    if ( (unsigned int)(*v1 - 1) > 5 )          // 输入数字-1不能大于5, 即不能大于6
      explode_bomb();
    if ( ++ind == 6 )
      break;
    temp = ind;
    do
    {
      if ( *v1 == our_number[temp] )
        explode_bomb();
      ++temp;
    }
    while ( temp <= 5 );
    ++v1;
  }
  adr = (char *)our_number;
  do
  {
    *(_DWORD *)adr = 7 - *(_DWORD *)adr;        // 用7来减去每个num
    adr += 4;
  }
  while ( adr != &v16 );
  for ( i = 0LL; i != 24; i += 4LL )
  {
    one = our_number[i / 4];
    if ( one <= 1 )
    {
      v6 = &node1;
    }
    else
    {
      v7 = 1;
      v6 = &node1;
      do
      {
        v6 = (__int64 *)v6[1];                  // 根据our_number取出的来更新v6
        ++v7;
      }
      while ( v7 != one );
    }
    *(__int64 *)((char *)&v17 + 2 * i) = (__int64)v6;// 每个元素存为8字节
  }
  l = v17;
  r = &v18;
  for ( j = v17; ; j = v12 )                    // 根据上面排序得到的v17设置每个node的next指针
  {
    v12 = *(_QWORD *)r;
    *(_QWORD *)(j + 8) = *(_QWORD *)r;
    r += 8;
    if ( r == &end_adr )
      break;
  }
  *(_QWORD *)(v12 + 8) = 0LL;
  v13 = 5;
  do                                            // 检测结点中数据的大小, 必须是递减的
  {
    result = **(unsigned int **)(l + 8);
    if ( *(_DWORD *)l < (int)result )           // 用低四个字节来比较
      explode_bomb();
    l = *(_QWORD *)(l + 8);
    --v13;
  }
  while ( v13 );
  return result;
}
arr = [0x10000014C, 0x2000000A8, 0x30000039C, 0x4000002B3, 0x5000001DD, 0x6000001BB]
new = []
for i in range(len(arr)):
    print(hex(arr[i] & 0xffff), end=', ')
# 递减顺序为: 3 4 5 6 1 2
# 那么7减去的num序列就为: 4 3 2 1 6 5

六:验证


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。