bomb 实验

2024-08-28 19:52
文章标签 实验 bomb

本文主要是介绍bomb 实验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GDB常用命令:

GDB调试常用命令-CSDN博客

原理:

编译与反汇编过程-CSDN博客

Bomb实验实现

阶段一: 

分析

  • 分配空间sub $0x8,%rsp 为局部变量分配栈空间。
  • 设置参数mov $0x402400,%esi 将字符串地址加载到 %esi
  • 比较字符串call 401338 <strings_not_equal> 调用函数比较字符串。
  • 判断结果test %eax,%eax 检查返回值,决定是否触发“炸弹”。
  • 触发或返回:不相等则 call 40143a <explode_bomb>,相等则恢复栈指针并返回。

答案:        "Border relations with Canada have never been better." 

 结构化汇编代码:

esi = $0x402400         // 字符串地址
strings_not_equal()
if eax == 0 {release_sp()
}else{explode_bomb()
}

 C_Like代码:

//  phase_1
int main(){std::string string_ = read();bool check = strings_not_equal(string_,"对应参数");if (!check){explode_bomb();}return 0;
}

阶段二(数组:

注意:

(1)区分清楚赋值是地址(lea),还是数据(mov)

(2)栈分配40个字节,剩余的字节可能用于对齐或存储其他局部变量(如寄存器的保存) 

(3)寄存器地址偏移通过逐步调整通用寄存器(如 rbx)的值,遍历数组中的元素。例如,int 类型增加 4 字节,char 类型增加 1 字节。

 (4)答案:        1 2 4 8 16 32

 结构化汇编代码:

阶段二:
rsp -= 0x28   
rsi = rspread_six_numbers()  if *rsp != 1{explode_bomb()
}rbx = rsp + 4       // 栈顶第2个元素地址
rbp = rsp + 0x18    // 栈顶第6个元素地址do{eax = *(rbx - 4)   // rbx前一个元素if *rbx - eax*2 !=0 {      explode_bomb()} rbx += 4        // rbx指向下一个元素
}while (rbx - rbp <= 0) // // rbx为栈顶第7个元素地址(实际不存在)...释放栈帧
rsp += 0x28

C_Like代码:

int main(){int array[6];read_six_numbers(array);// 检查第一个数字是否为1if(array[0] == 1){explode_bomb();}// 检查剩余数字是否满足条件for(int i = 1; i < 6; i++){if(array[i] != array[i-1] * 2){explode_bomb();}}return 0;
}

阶段三(switch: 

注意:

(1)cmpl $0x7, 0x8(%rsp) 这条指令是将 rsp + 0x08 处的内存内容(值)与 0x07 进行比较,而不是比较地址本身。

(2)调用函数前,rdi第一个参数,rsi第二个参数,rdx第三个参数,rcx第四个参数

sscanf 函数的核心参数如下:输入字符串(RDI):char* output
格式字符串(RSI):定义解析规则,例如 "%d %d"。
变量地址(RDX 和 RCX):用于存储解析后的数据,即 x 和 y 的地址。

(3)0x402470 是跳转表的基地址(起始地址)

  400f75:	ff 24 c5 70 24 40 00 	jmp    *0x402470(,%rax,8)

(4) 例如:

0         0xcf
0         207
1         311
2         707
3         256
4         389
5         206
6         682
7         327

 结构化汇编代码:

// Phase 3rsp = rsp - 0x18// 调用函数前参数设置   (output为rdi   num_1)
rcx = rsp + 0xc     // num_4
rdx = rsp + 8       // num_3
esi = $0x4025cf     // num_2eax = 0             // 获取函数返回值
__isoc99_sscanf@plt()if eax <= 1 {   //  有符号比较explode_bomb()
}if *(rsp + 8) - 7 > 0 {    //  无符号比较explode_bomb()
}eax = *(rsp + 8)
jmp 0x402470 + 8 *eaxswitch(x) {case 0x400f7c:eax = 0xcf;break;case 0x400f83:eax = 0x2c3;break;case 0x400f8a:eax = 0x100;break;case 0x400f91:eax = 0x185;break;case 0x400f98:eax = 0xce;break;case 0x400f9f:eax = 0x2aa;break;case 0x400fa6:eax = 0x147;break;case 0x400fad:call explode_bomb();break;case 0x400fb2:eax = 0x0;break;case 0x400fb9:eax = 0x137;
}if eax != *(rsp + 0xc){explode_bomb()
}ret

 C_Like代码:

//  phase_3
int main(char * output){int x,y;int  check = sscanf(output,"%d %d",&x,&y); // 四个元素if (check <= 1){explode_bomb();}if(x > 7){explode_bomb();}int ret;switch (x) {case 0:ret = 0xcf; // corresponding to 0x400f7cbreak;case 1:ret = 0x2c3; // corresponding to 0x400f83break;case 2:ret = 0x100; // corresponding to 0x400f8abreak;case 3:ret = 0x185; // corresponding to 0x400f91break;case 4:ret = 0xce; // corresponding to 0x400f98break;case 5:ret = 0x2aa; // corresponding to 0x400f9fbreak;case 6:ret = 0x147; // corresponding to 0x400fa6break;case 7:explode_bomb(); // corresponding to 0x400fadbreak;case 8:ret = 0x0; // corresponding to 0x400fb2break;case 9:ret = 0x137; // corresponding to 0x400fb9break;}if (ret != y){explode_bomb();}return 0;
}

阶段四(递归: 

分析

(1)sar    %eax相当于 sar $1,eax        (eax右移1位

(2)func_4功能:

  • 找到目标值 x:返回 0
  • 在左半部分找到 x:返回偶数。
  • 在右半部分找到 x:返回奇数。

总体结果: 

  • 始终在左半部分查找,返回 0
  • 有一次出现在右半部分,返回非0

(3)要求:        返回值必须为0,y也必须为0        (eg.        x: 1        y:0

 结构化汇编代码:

void phase_4() {// 减小栈指针,准备局部变量空间rsp -= 18;// 函数参数设置int* num_4 = (int*)(rsp + 0xc); // num_4 (y)int* num_3 = (int*)(rsp + 8);   // num_3 (x)// 读取用户输入esi = 0x4025cf;  // 指向输入格式字符串eax = 0;int result = __isoc99_sscanf(esi, "%d %d", num_4, num_3);// 判断输入是否合法if (result != 2) {explode_bomb();}// 判断 num_3 是否超出范围if (*num_3 > 0xe) {explode_bomb();}// 设置参数,准备调用 func_4int num_2 = 0;        // num_2int num_1 = *num_3;   // num_1int max_value = 0xe;  // 最大值 (edx)// 调用 func_4eax = func_4(num_1, num_2, max_value);// 判断 func_4 的返回值是否合法if (eax <= 0) {explode_bomb();} else {// 判断 num_4 是否为0if (*num_4 != 0) {explode_bomb();}}// 恢复栈指针并返回rsp += 24;return;
}int func_4(int num_1, int num_2, int max_value) {// 减小栈指针,准备局部变量空间rsp -= 8;// 计算中间值int mid = (max_value - num_2) / 2 + num_2;// 递归处理if (mid > num_1) {max_value = mid - 1;eax = func_4(num_1, num_2, max_value);eax *= 2;} else if (mid < num_1) {num_2 = mid + 1;eax = func_4(num_1, num_2, max_value);eax = eax * 2 + 1;} else {eax = 0;}// 恢复栈指针并返回rsp += 8;return eax;
}

 C_Like代码:

int func_4(int target, int low, int high) {int range_size = high - low;    // 当前搜索范围的大小range_size = (range_size + (range_size >> 31)) >> 1;   // 处理符号位并计算中点偏移量int mid = range_size + low;     // 计算当前中间点的值if(mid > target) {return 2 * func_4(target, low, mid - 1); // 在左半部分继续搜索} else if(mid < target) {return 2 * func_4(target, mid + 1, high) + 1; // 在右半部分继续搜索} else {return 0; // 找到目标值,返回0}
}int main(char *output) {int x, y;int check = sscanf(output, "%d %d", &x, &y); // 解析用户输入if (check != 2) {explode_bomb(); // 如果输入格式不对,触发炸弹}if (x > 14) {explode_bomb(); // 如果 x 超过 14,触发炸弹}// x 小于等于 14check = func_4(x, 0, 14); // 调用 func_4 进行计算if (check != 0 || y != 0) {explode_bomb(); // 如果返回值不正确,触发炸弹 }return 0;
}

阶段五: 

分析

(1)nopl (%rax) 用于指令对齐和填充特定字节

(2)repz ret 提供防攻击优化,提升特定处理器性能;ret 为标准返回指令。

(3)在字符串处理中,每个字符占 1 字节add $0x1, %rdxrdx 指向下一个字符的地址

(4)__stack_chk_fail@plt() 防止攻击,检查金丝雀值

(5)flyers六个字母对应maduiersnfotvbyl的下标分别为 9 15 14 5 6 7 ,对应ASCIL表编码进行&0xf操作后低四位

答案:

  • IONEFG
  • ionefg

 结构化汇编代码:

// phase_5int string_length(string * str){if(str == 0){return 0;}string * str_offset_addr = strdo{str_offset_addr += 1str_len = str_offset_addr - str}while(*str_offset_addr != 0);return str_len;
}void return_(){eax = edx        pop rbxpop rbppop r12ret
};int strings_not_equal(){push r12push rbppush rbxrbx = rdirbp = rsistring_length()r12 = eaxrdi = rbpstring_length()edx = 1if(r12 != eax){return_();}eax = *rbxif(al == 0){edx = 0return_();}if(al == *rbp){ while(true){rbx += 1rbp += 1eax = *(rbx)if(al == 0){edx = 0return_();}if(al != *rbp){edx = 1return_();}}}else{edx = 1return_();}}void phase_5(){push rbxrsp -= 0x20rbx = rdi rax = *(fs + 0x28)rax = *(rsp + 0x18) int check = string_length();if(check != 6){explode_bomb()}eax = 0do{ecx = *(rbx + rax)*(rsp) = clrdx = *(rsp)edx = edx & 0xfedx = *(rdx + 0x4024b0)*(rsp + rax + 16) = dlrax += 1 }while(rax != 6)*(rsp + 0x16) = 0esi = 0x40245erdi = rsp + 16int check_ = strings_not_equal()if(check_ != 0){explode_bomb()}rax = *(rsp + 0x18)rax ^= *(fs + 0x28)if(rax != 0){__stack_chk_fail@plt()      // 检测金丝雀值}     rsp += 0x20pop rbxret
}

 C_Like代码:

// phase_5int string_length(string * str){if(!(*str)[0]){return 0;}string * str_offset_addr = str;int str_len = 0;do{str_offset_addr += 1;str_len = str_offset_addr - str;}while((*str_offset_addr)[0]);return str_len;
}bool strings_not_equal(string * str1, string * str2){if(string_length(str1) != string_length(str2)){return true;}if(!(*str1)[0]){return false;}int i = 0;while((*str1)[i] == (*str2)[i]){i++;if(!(*str1)[i]){return false;}if((*str1)[i] != (*str2)[i]){return true;}}return true;
}void phase_5(){string output = "maduiersnfotvbylSo";int len = string_length(&output);if(len != 6){explode_bomb();}string *other;for(int i = 0;i < 6;i++){char c = (output)[i]; c = c & 0xf;(*other)[i] = *(char*)(0x4024b0 + c);}string target = "flyers";bool check = strings_not_equal(other, &target);if(check){explode_bomb();}
}

阶段六:

分析

(1)链表结构:        嵌套解指针的结构

            for(eax = 1;eax == ecx;eax += 1){rdx = rdx + 8}   

(2)32位系统中,指针为4位,故这个结构体大小为8位

typedef struct {int val;Node* node_next;
}Node;

(3)GDB命令

1.查看寄存器的值

info reg rsp

2.查看内存的值

x/gx 0x7fffffffe000 + 0x20x: 表示 examine(查看),用于查看内存。
/gx: 指定查看格式。
g: 表示以 8 字节(64 位)长的整数格式查看。
x: 表示以十六进制格式显示值。

x/gx 0x00000000006032d0 返回 0x000000010000014c:下一个节点的地址:0x00000001
节点的值:0x0000014c (即 332)

可得链表:

332       168       924       691       477       443
0x6032d0->0x6032e0->0x6032f0->0x603300->0x603310->0x603320

(4)链表地址数组 

0x6032F0    链表地址数组第一个

0x6032F0 + 8 指向 next_node地址

mov    0x20(%rsp),%rbx  ->     rbx = 0x6032F0
mov    %rbx,%rcx        ->     rcx = 0x6032F0mov    (%rax),%rdx      ->     rdx = 0x6032F0
mov    %rdx,0x8(%rcx)   ->     *(0x6032F0 + 8) = 0x603300
(*(0x6032F0 + 8) 指向第一个元素的next 地址)

答案:        "Border relations with Canada have never been better." 

 友好的汇编代码(重点,作为汇编阅读方式):

00000000004010f4 <phase_6>:4010fc:	48 83 ec 50          	sub    $0x50,%rsp401100:	49 89 e5             	mov    %rsp,%r13401103:	48 89 e6             	mov    %rsp,%rsi401106:	e8 51 03 00 00       	call   40145c <read_six_numbers>40110b:	49 89 e6             	mov    %rsp,%r1440110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d   # i = 0
# num_1:  外层循环
-------------------------------------------------401114:	4c 89 ed             	mov    %r13,%rbp401117:	41 8b 45 00          	mov    0x0(%r13),%eax40111b:	83 e8 01             	sub    $0x1,%eax# 爆炸(eax > 6)---------------------40111e:	83 f8 05             	cmp    $0x5,%eax401121:	76 05                	jbe    401128 <phase_6+0x34>401123:	e8 12 03 00 00       	call   40143a <explode_bomb>  ---------------------401128:	41 83 c4 01          	add    $0x1,%r12d             # i += 140112c:	41 83 fc 06          	cmp    $0x6,%r12d             # i == 6401130:	74 21                	je     401153 <phase_6+0x5f>  # 退出整个循环401132:	44 89 e3             	mov    %r12d,%ebx#  内层循环-------------------------------------------------  401135:	48 63 c3             	movslq %ebx,%rax401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax# 爆炸(eax == *rbp)---------------------40113b:	39 45 00             	cmp    %eax,0x0(%rbp)40113e:	75 05                	jne    401145 <phase_6+0x51>401140:	e8 f5 02 00 00       	call   40143a <explode_bomb>---------------------401145:	83 c3 01             	add    $0x1,%ebx              # j += 1401148:	83 fb 05             	cmp    $0x5,%ebx              # j > 540114b:	7e e8                	jle    401135 <phase_6+0x41>  # 退出内层循环------------------------------------------------- 40114d:	49 83 c5 04          	add    $0x4,%r13401151:	eb c1                	jmp    401114 <phase_6+0x20>-------------------------------------------------------------401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi401158:	4c 89 f0             	mov    %r14,%rax  # addr = rsp40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
# num_2 循环
-------------------------------------------------------------401160:	89 ca                	mov    %ecx,%edx401162:	2b 10                	sub    (%rax),%edx401164:	89 10                	mov    %edx,(%rax)401166:	48 83 c0 04          	add    $0x4,%rax              # addr += 440116a:	48 39 f0             	cmp    %rsi,%rax              # addr == rsp + 0x1840116d:	75 f1                	jne    401160 <phase_6+0x6c>  # 退出循环
-------------------------------------------------------------40116f:	be 00 00 00 00       	mov    $0x0,%esi401174:	eb 21                	jmp    401197 <phase_6+0xa3># num_3 外层循环
-------------------------------------------------------------# num_3 内层循环1-------------------------------------------------------------401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx40117a:	83 c0 01             	add    $0x1,%eax40117d:	39 c8                	cmp    %ecx,%eax40117f:	75 f5                	jne    401176 <phase_6+0x82>   -------------------------------------------------------------401181:	eb 05                	jmp    401188 <phase_6+0x94># num_3 循环开始# num_3 内层循环2-------------------------------------------------------------401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)40118d:	48 83 c6 04          	add    $0x4,%rsi401191:	48 83 fe 18          	cmp    $0x18,%rsi401195:	74 14                	je     4011ab <phase_6+0xb7>num_3 start: 401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx40119a:	83 f9 01             	cmp    $0x1,%ecx40119d:	7e e4                	jle    401183 <phase_6+0x8f>-------------------------------------------------------------40119f:	b8 01 00 00 00       	mov    $0x1,%eax4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx4011a9:	eb cb                	jmp    401176 <phase_6+0x82>
-------------------------------------------------------------4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi4011ba:	48 89 d9             	mov    %rbx,%rcx# num_4 循环
-------------------------------------------------------------4011bd:	48 8b 10             	mov    (%rax),%rdx4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)4011c4:	48 83 c0 08          	add    $0x8,%rax// break;  4011c8:	48 39 f0             	cmp    %rsi,%rax4011cb:	74 05                	je     4011d2 <phase_6+0xde>4011cd:	48 89 d1             	mov    %rdx,%rcx4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>
-------------------------------------------------------------4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)4011d9:	00 4011da:	bd 05 00 00 00       	mov    $0x5,%ebp# num_5 循环
-------------------------------------------------------------4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax4011e3:	8b 00                	mov    (%rax),%eax4011e5:	39 03                	cmp    %eax,(%rbx)4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>4011e9:	e8 4c 02 00 00       	call   40143a <explode_bomb>4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx4011f2:	83 ed 01             	sub    $0x1,%ebp4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
-------------------------------------------------------------4011f7:	48 83 c4 50          	add    $0x50,%rsp401203:	c3                   	ret 

 结构化汇编代码:


void phase_6(){r13 = rsprsi = rspread_six_numbers()r14 = rspr12 = 0         # i = 0
# num_1 外层循环
-------------------------------------------------   rbp = r13   (rsp 副本)eax =  *rsp - 1if(eax <= 5){explode_bomb()}r12 += 1        # i += 1# 退出整个循环(i == 6)if(r12 == 6){   break;}ebx = r12   # j = r12# 内层循环-------------------------------------------------   rax = ebxeax = *(rsp + rax + 4)if(rbp == eax){explode_bomb()}ebx += 1    # j += 1# 退出内层循环(j > 5)if(ebx > 5){break;}-------------------------------------------------   r13 += 4-------------------------------------------------   rax = r14   # addr = rsp# num_2 循环
-------------------------------------------------------------for(rax = rsp;rax != rsp + 0x18;rax += 4){edx = 7edx -= *rax *rax = edx        }-------------------------------------------------------------# num_3 循环
-------------------------------------------------------------for(rsi = 0;rsi != 0x18;rsi += 4){ecx = *(rsp + rsi)if(ecx > 1){edx = 0x6032d0          }else{edx = 0x6032d0 for(eax = 1;eax == ecx;eax += 1){rdx = rdx + 8}   }            *(rsp + rsi*2 + 0x20) = rdx   }
-------------------------------------------------------------rcx = *(rsp + 0x20)# num_4 循环(关于rax的操作只有 rax+=8 
#                   => 可以预见不可能中途退出,故可以直接判断为for循环)
-------------------------------------------------------------for(rax = rsp + 0x28;rax != rsp + 0x50;){rdx = *rax*(rcx + 8) = rdxrax += 8if(rax == rsp + 0x50){break;}rcx = rdx        }-------------------------------------------------------------*(rdx + 8) = 0# num_5 循环
-------------------------------------------------------------for(ebp = 5;ebp != 0;ebp -= 1){rax = *(rbx + 8)eax = *raxif(*rbx < eax){explode_bomb()  }rbx = *(rbx + 8)}
-------------------------------------------------------------return 0;}

这篇关于bomb 实验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115731

相关文章

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

61.以太网数据回环实验(4)以太网数据收发器发送模块

(1)状态转移图: (2)IP数据包格式: (3)UDP数据包格式: (4)以太网发送模块代码: module udp_tx(input wire gmii_txc ,input wire reset_n ,input wire tx_start_en , //以太网开始发送信

LTspice模拟CCM和DCM模式的BUCK电路实验及参数计算

关于BUCK电路的原理可以参考硬件工程师炼成之路写的《 手撕Buck!Buck公式推导过程》.实验内容是将12V~5V的Buck电路仿真,要求纹波电压小于15mv. CCM和DCM的区别: CCM:在一个开关周期内,电感电流从不会到0. DCM:在开关周期内,电感电流总会到0. CCM模式Buck电路仿真: 在用LTspice模拟CCM电路时,MOS管驱动信号频率为100Khz,负载为10R(可自

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

pta-2024年秋面向对象程序设计实验一-java

文章申明:作者也为初学者,解答仅供参考,不一定是最优解; 一:7-1 sdut-sel-2 汽车超速罚款(选择结构) 答案: import java.util.Scanner;         public class Main { public static void main(String[] arg){         Scanner sc=new Scanner(System

如何校准实验中振镜频率的漂移

在实验过程中,使用共振扫描振镜(如Cambridge Technology的8kHz振镜)时,频率漂移是一个常见问题,尤其是在温度变化或长期运行的情况下。为了确保实验的准确性和稳定性,我们需要采取有效的校准措施。本文将介绍如何监测、调节和校准振镜频率,以减少漂移对实验结果的影响。 1. 温度管理和稳定性控制 振镜的频率变化与温度密切相关,温度的升高会导致机械结构的变化,进而影响振镜的共

实验C语言“union”的最基础语法

目标 最近在看Rust的“菜鸟教程”,看到 Rust 枚举类 时我发现它所定义的“枚举类”虽然也能像C语言枚举类那样使用,但是多了些功能:对于某个枚举的成员,还可以附带独特的数据,这让我想起了C语言中的union。 而我事实上对union没有使用经验,我自己写程序的时候不用它,看其他的项目的程序时印象里也没见过它。所以我对union的设计意图理解不深(可能只是为了节省内存?)。本篇的目标是对其

Oracle高级压缩和透明数据加密组合实验

本文参考了实验DB Security - Advanced Compression with Transparent Data Encryption(TDE),其申请地址在这里。 本文只使用了实验中关于高级压缩和在线重定义的部分。并对要点进行说明及对实验进行了简化。 准备:环境设置 原文中的实验环境实际上是改自Oracle示例Sample Schema,其实唯一的改动就是去掉了SALES表中