From c39cad30b41e0ed40506b1a4345f289fe9b6c48d Mon Sep 17 00:00:00 2001
From: "18218461270@163.com" <18218461270@163.com>
Date: Sun, 3 Aug 2025 22:06:02 +0800
Subject: [PATCH] blog only
---
homework/chapter2/README.md | 39 ----
homework/chapter3/README.md | 42 -----
labs/bomb/README.md | 357 ------------------------------------
labs/datalab/README.md | 15 --
4 files changed, 453 deletions(-)
delete mode 100644 homework/chapter2/README.md
delete mode 100644 homework/chapter3/README.md
delete mode 100644 labs/bomb/README.md
delete mode 100644 labs/datalab/README.md
diff --git a/homework/chapter2/README.md b/homework/chapter2/README.md
deleted file mode 100644
index 62132d7..0000000
--- a/homework/chapter2/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-## 2.65
-每一次操作,将 $w$ 位的整数 $x$ 从中间分成两个 $\frac{w}{2}$ 位的整数 $y$ 和 $z$,接着令 `x = y ^ z`。进行 5 次操作后即得到答案。
-
-我们将这样的思路称为“折半递归法”。
-
-## 2.66
-第 $k$ 次操作,令 `x = x | (x >> (1 << (k - 1)))`。通过 5 次操作即可实现提示中的转换。
-
-## 2.75
-$x,y$ 是补码数,$x'=T2U_w(x),y'=T2U_w(y)$。
-
-$$
-\begin{aligned}
-x'\cdot y'&=(x+x_{w-1}\cdot 2^w)\times(y+y_{w-1}\cdot 2^w)\\
-&=x\cdot y+(x_{w-1}\cdot y+y_{w-1}\cdot x)2^w+x_{w-1}\cdot y_{w-1}\cdot 2^{2w}
-\end{aligned}$$
-
-进一步,令 `a = signed_high_prod(x, y), b = unsigned_high_prod(x', y')`,有
-$$b\cdot 2^w+x'*^u_w y'=a\cdot 2^w+T2U_w(x*^t_wy)+(x_{w-1}\cdot y+y_{w-1}\cdot x)2^w+x_{w-1}\cdot y_{w-1}\cdot 2^{2w}$$
-
-化简得
-$$b=a+x_{w-1}\cdot y+y_{w-1}\cdot x+x_{w-1}\cdot y_{w-1}\cdot 2^w$$
-
-即
-$$\begin{aligned}
-b&=(a+x_{w-1}\cdot y+y_{w-1}\cdot x)\bmod 2^w\\
-&=T2U_w(a)+^u_t x_{w-1}\cdot y'+^u_t y_{w-1}\cdot x'
-\end{aligned}$$
-
-## 2.80
-$$
-\texttt{threefourths(x)}=\left\{\begin{aligned}
-&3\cdot\lfloor x/4\rfloor+x\bmod 3-[x\bmod 3\neq0], &x\ge0\\
-&3\cdot\lfloor x/4\rfloor+x\bmod 3, &x<0
-\end{aligned}\right.
-$$
-
-## 2.97
-在某些情况下,舍入会导致最高位提高一位。对于这种情况,我们要将舍入时的最低有效位相应提高一位。
\ No newline at end of file
diff --git a/homework/chapter3/README.md b/homework/chapter3/README.md
deleted file mode 100644
index 45ae3bf..0000000
--- a/homework/chapter3/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-## 3.64
-
- - $\&A[i][j][k]=x_A+L(i\cdot S\cdot T+j\cdot T+k)$;
- - $R=7,S=5,T=13$。
-
-
-## 3.68
-由汇编第 2 行可知,$A\in(4,8]$;由第 3 行可知,$B\in(6,10]$;由第 4 行可知,$A\cdot B\in(44,46]$。因此,$A=5,B=9$。
-
-## 3.69
-
- - 由汇编第 4 至 6 行可知,`a_struct` 大小为 40 字。再结合第 1 行可知 $CNT=7$;
- - 由汇编第 6 至 8 行可知,`idx` 在 `x` 之前,类型均为 `long`(或 `long` 数组)。结合 `a_struct` 大小为 40 字,得到其声明如下:
-```c
-typedef struct {
- long idx;
- long x[4];
-} a_struct;
-```
-
-
-
-
-## 3.70
-
- -
-| 字段 | 偏移量 |
-| --- | --- |
-| `e1.p` | 0 |
-| `e1.y` | 8 |
-| `e2.x` | 0 |
-| `e2.next` | 8 |
-
- - 2 个
- -
-```c
-void proc (union ele *up) {
- up->e2.x = *(up->e2.next->e1.p) - (up->e2.next->e1.y);
-}
-```
-
-
\ No newline at end of file
diff --git a/labs/bomb/README.md b/labs/bomb/README.md
deleted file mode 100644
index e65899a..0000000
--- a/labs/bomb/README.md
+++ /dev/null
@@ -1,357 +0,0 @@
-输入命令 `objdump -s -S -d -M att bomb > bomb.s` 进行反汇编。
-
-## Phase 1
-对 `phase_1` 进行逆向:
-```c
-void phase_1(char str[]) {
- if (strings_not_equal(str, "Border relations with Canada have never been better.") != 0) {
- explode_bomb();
- }
-}
-```
-
-> `explode_bomb` 函数将炸弹引爆;`strings_not_equal` 函数接受两个字符串作为参数,在两者不相等时返回 `1`,否则返回 `0`。
-
-显然,输入应为 `Border relations with Canada have never been better.`。
-
-## Phase 2
-逆向工程循环的一些技巧:
-- 框选出循环范围,将跳转指令的地址改成标号;
-- 尝试移动整段代码,并修改相应的跳转指令;
-- 最终使之符合任意一种通用策略。
-
-在这里,我们将 `400f0a` 至 `400f3a` 部分整理如下:
-```esm
- cmpl $0x1,(%rsp)
- je .L1
- call explode_bomb
-.L1:
- lea 0x4(%rsp),%rbx
- lea 0x18(%rsp),%rbp
-.L2:
- mov -0x4(%rbx),%eax
- add %eax,%eax
- cmp %eax,(%rbx)
- je .L3
- call explode_bomb
-.L3:
- add $0x4,%rbx
- cmp %rbp,%rbx
- jne .L2
-```
-基于此逆向得到:
-```c
-void phase_2(char str[]) {
- int x[6];
- read_six_numbers(x);
-
- if (x[0] != 1) {
- explode_bomb();
- } else {
- for (int i = 1; i < 6; i++) {
- if (x[i] != x[i - 1] * 2) {
- explode_bomb();
- }
- }
- }
-}
-```
-
-> `read_six_numbers(int x[])` 读入 6 个整数,并依次存贮到 `x[0]` 至 `x[5]`。
-
-由此可知,输入应为 `1 2 4 8 16 32`。
-
-## Phase 3
-这个 phase 包含一个跳转表,逆向为 switch 语句:
-```c
-void phase_3(char str[]) {
- int x, y;
- if (sscanf(str, "%d %d", &x, &y) <= 1) {
- explode_bomb();
- }
-
- if (x > 7 || x < 0) {
- explode_bomb();
- }
- int z;
- switch (x) {
- case 0:
- z = 0xcf;
- break;
- case 2:
- z = 0x2c3;
- break;
- case 3:
- z = 0x100;
- break;
- case 4:
- z = 0x185;
- break;
- case 5:
- z = 0xce;
- break;
- case 6:
- z = 0x2aa;
- break;
- case 7:
- z = 0x147;
- break;
- default:
- z = 0x137;
- }
- if (y != z) {
- explode_bomb();
- }
-}
-```
-由此可知,输入的第 1 个数必须在 0 到 7 之间,第二个数与之相应即可。
-
-## Phase 4
-`400fd6` 至 `400fdd` 部分使用了原书 2.3.7 中提到的方法实现除以 2。
-```c
-int func4(int x, int y, int z) {
- int mid = y + (z - y) / 2;
- if (mid <= x) {
- if (mid >= x) {
- return 0;
- } else {
- return 2 * func4(x, mid + 1, z) + 1;
- }
- } else {
- return 2 * func4(x, y, mid - 1);
- }
-}
-
-void phase_4(char str[]) {
- int x, y;
- if (sscanf(str, "%d %d", &x, &y) != 2) {
- explode_bomb();
- }
-
- if (x > 15 || x < 0) {
- explode_bomb();
- }
- if (func4(x, 0, 15) != 0 || y != 0) {
- explode_bomb();
- }
-}
-```
-结合线段树知识,输入的第 1 个数可以是 `0`、`1`、`3` 和 `7`,第二个数是 `0`。
-
-## Phase 5
-将 `40107f` 至 `4010c6` 部分整理如下:
-```esm
- cmp $0x6,%eax
- je .L1
- call explode_bomb
-.L1:
- mov $0x0,%eax
-.L2:
- movzbl (%rbx,%rax,1),%ecx
- mov %cl,(%rsp)
- mov (%rsp),%rdx
- and $0xf,%edx
- movzbl 0x4024b0(%rdx),%edx
- mov %dl,0x10(%rsp,%rax,1)
- add $0x1,%rax
- cmp $0x6,%rax
- jne .L2
- movb $0x0,0x16(%rsp)
- mov $0x40245e,%esi
- lea 0x10(%rsp),%rdi
- call strings_not_equal
- test %eax,%eax
- je .L3
- call explode_bomb
-.L3:
-```
-基于此逆向得到:
-```c
-void phase_5(char str[]) {
- if (string_length(str) != 6) {
- explode_bomb();
- }
-
- char str2[7];
- for (int i = 0; i < 6; i++) {
- str2[i] = "maduiersnfotvbyl"[str[i] & 0xF];
- }
- str2[6] = 0;
-
- if (strings_not_equal(str2, "flyers") != 0) {
- explode_bomb();
- }
-}
-```
-一个可行的输入是 `9?>567`。
-
-## Phase 6
-将 `401176` 至 `4011a9` 部分整理如下:
-```esm
- mov $0x0,%esi
-.L1:
- mov $0x6032d0,%edx
- mov (%rsp,%rsi,1),%ecx
- cmp $0x1,%ecx
- jle .end
- mov $0x1,%eax
-.L2:
- mov 0x8(%rdx),%rdx
- add $0x1,%eax
- cmp %ecx,%eax
- jne .L2
-.end:
- mov %rdx,0x20(%rsp,%rsi,2)
- add $0x4,%rsi
- cmp $0x18,%rsi
- jne .L1
-```
-为了理解代码对以地址 `0x6032d0` 开头的一段内存的读写操作,我们还需研究其中数据的组织方式,例如:
-```txt
- 6032d0 4c010000 01000000 e0326000 00000000 L........2`.....
-```
-结合汇编代码,不难猜到这块区域依次存储了两个 4 字整数和一个指针,组成一个结构。我们给出它的声明:
-```c
-struct chain_node {
- int val;
- int id;
- struct chain_node *next;
-};
-```
-综合以上,逆向得到:
-```c
-struct chain_node {
- int val;
- int id;
- struct chain_node *next;
-} c[6] = {{0x014c, 1, &c[1]},
- {0x00a8, 2, &c[2]},
- {0x039c, 3, &c[3]},
- {0x02b3, 4, &c[4]},
- {0x01dd, 5, &c[5]},
- {0x01bb, 6}};
-
-void phase_6(char str[]) {
- int x[6];
- read_six_numbers(x);
-
- for (int i = 0; ; i++) {
- if (x[i] <= 0 || x[i] > 6) {
- explode_bomb();
- }
- if (i == 5) {
- break;
- }
- for (int j = i + 1; j < 6; j++) {
- if (x[i] == x[j]) {
- explode_bomb();
- }
- }
- }
-
- for (int i = 0; i < 6; i++) {
- x[i] = 7 - x[i];
- }
-
- struct chain_node *y[6];
- for (int i = 0; i < 6; i++) {
- chain_node *p = c[0];
- for (int j = 1; j < x[i]; j++) {
- p = p->next;
- }
- y[i] = p;
- }
-
- for (int i = 1; i < 6; i++) {
- y[i - 1]->next = y[i];
- }
- y[5]->next = NULL;
-
- chain_node *p = y[0];
- for (int i = 5; i > 0; i--) {
- if (p->val < p->next->val) {
- explode_bomb();
- }
- p = p->next;
- }
-}
-```
-结合链表知识,输入应为 `4 3 2 1 6 5`。
-
-## 进入 Secret Phase
-唯一对 `secret_phase` 的调用位于 `phase_defused` 中。观察 `phase_defused`,在 `num_input_strings`(每次调用 `read_line` 都会使它加 1)等于 6,即完成 Phase 6 后的调用时,该函数从以地址 `0x603870` 开头的字符串中先后提取了两个整数和一个字符串,并检查提取的字符串是否与 `DrEvil` 相等,若相等,则调用 `secret_phase`。
-
-`0x603870` 这个地址并没有在其他任何地方出现过,但是在 `skip` 和`read_line` 中,出现了地址 `0x603780`。对这两个函数逆向,大致如下:
-```c
-char input[MAXLEN]; // 0x603780
-int num_input_strings = 0;
-FILE *infile;
-
-int skip() {
- fgets(input + 90 * num_input_strings, 90, infile);
- ...
-}
-
-char* read_line() {
- ...
- char *start = input + 90 * num_input_strings;
- ...
- num_input_strings++;
- ...
- return start;
-}
-```
-由此可知,以地址 `0x603870` 开头的字符串就是 Phase 4 时输入的字符串,而在 Phase 4 中恰好要输入两个整数,在它们之后再输入 `MrEvil`,我们就能够进入 Secret Phase。
-
-## Secret Phase
-```c
-struct tree_node {
- int val;
- struct tree_node *ls, *rs;
- long place_holder;
-} t[15] = {{0x024, &t[1], &t[2]},
- {0x008, &t[5], &t[3]},
- {0x032, &t[4], &t[6]},
- {0x016, &t[12], &t[10]},
- {0x02d, &t[7], &t[13]},
- {0x006, &t[8], &t[11]},
- {0x06b, &t[9], &t[14]},
- {0x028, NULL, NULL},
- {0x001, NULL, NULL},
- {0x063, NULL, NULL},
- {0x023, NULL, NULL},
- {0x007, NULL, NULL},
- {0x014, NULL, NULL},
- {0x02f, NULL, NULL},
- {0x3e9, NULL, NULL}};
-
-int fun7(struct tree_node *x, int y) {
- if (x == NULL) {
- return -1;
- } else {
- if (x->val <= y) {
- if (x->val == y) {
- return 0;
- } else {
- return 2 * fun7(x->rs, y) + 1;
- }
- } else {
- return 2 * fun7(x->ls, y);
- }
- }
-}
-
-void secret_phase() {
- long x = strtol(read_line(), NULL, 10);
-
- if (x > 1001 || x < 1) {
- explode_bomb();
- }
-
- if (fun7(t, x) != 2) {
- explode_bomb();
- }
- ...
-}
-```
-结合二叉搜索树知识,输入应为 `22`。
\ No newline at end of file
diff --git a/labs/datalab/README.md b/labs/datalab/README.md
deleted file mode 100644
index bcc817c..0000000
--- a/labs/datalab/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# datalab
-## `isTmax`
-$Tmax$ 的位表示为 `011...11`。注意到 `x + 1 == ~x` 当且仅当 $x=-1$ 或 $x=Tmax$。类似的,判断 `x + x + 2 == 0` 看似也可行,但实际上编译器将这条式子优化成了 `x == -1`。
-
-## `allOddBits`、`logicalNeg`
-使用“折半递归法”,参见作业 2.65。
-
-## `conditional`
-设计函数 `f(x) = ~!x + 1`:当 $x=0$ 时 `f(x) = 0xFFFFFFFF`,而 $x\neq 0$ 时 `f(x) = 0x00000000`。
-
-## `isLessOrEqual`
-先判断 $x,y$ 是否异号;接着判断 `y - x`,即 `y + ~x + 1` 的符号位,当 $x,y$ 同号时不会溢出。
-
-## `howManyBits`
-为了只考虑 $x$ 为正数的情况,令 `x ^= x >> 31`。接下来可通过“折半递归法”解决。
\ No newline at end of file