bomb 实验

news2024/9/21 20:40:36

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 = rsp

read_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);

    // 检查第一个数字是否为1
    if(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 3

rsp = rsp - 0x18
    // 调用函数前参数设置   (output为rdi   num_1)
rcx = rsp + 0xc     // num_4
rdx = rsp + 8       // num_3
esi = $0x4025cf     // num_2

eax = 0             // 获取函数返回值
__isoc99_sscanf@plt()

if eax <= 1 {   //  有符号比较
    explode_bomb()
}

if *(rsp + 8) - 7 > 0 {    //  无符号比较
    explode_bomb()
}

eax = *(rsp + 8)
jmp 0x402470 + 8 *eax

switch(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 0x400f7c
            break;
        case 1:
            ret = 0x2c3; // corresponding to 0x400f83
            break;
        case 2:
            ret = 0x100; // corresponding to 0x400f8a
            break;
        case 3:
            ret = 0x185; // corresponding to 0x400f91
            break;
        case 4:
            ret = 0xce; // corresponding to 0x400f98
            break;
        case 5:
            ret = 0x2aa; // corresponding to 0x400f9f
            break;
        case 6:
            ret = 0x147; // corresponding to 0x400fa6
            break;
        case 7:
            explode_bomb(); // corresponding to 0x400fad
            break;
        case 8:
            ret = 0x0; // corresponding to 0x400fb2
            break;
        case 9:
            ret = 0x137; // corresponding to 0x400fb9
            break;
    }
    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_4
    int num_2 = 0;        // num_2
    int num_1 = *num_3;   // num_1
    int max_value = 0xe;  // 最大值 (edx)

    // 调用 func_4
    eax = func_4(num_1, num_2, max_value);

    // 判断 func_4 的返回值是否合法
    if (eax <= 0) {
        explode_bomb();
    } else {
        // 判断 num_4 是否为0
        if (*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 小于等于 14

    check = 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_5

int string_length(string * str){
    if(str == 0){
        return 0;
    }
    string * str_offset_addr = str

    do{
        str_offset_addr += 1
        str_len = str_offset_addr - str
    }
    while(*str_offset_addr != 0);

    return str_len;
}


 void return_(){
    eax = edx        
    pop rbx
    pop rbp
    pop r12
    ret
};

int strings_not_equal(){
    push r12
    push rbp
    push rbx
    rbx = rdi
    rbp = rsi
    string_length()
    r12 = eax
    rdi = rbp
    string_length()
    edx = 1

    if(r12 != eax){
        return_();
    }

    eax = *rbx

    if(al == 0){
        edx = 0
        return_();
    }


    if(al == *rbp){ 
        while(true){
            rbx += 1
            rbp += 1
            eax = *(rbx)
            
            if(al == 0){
                edx = 0
                return_();
            }

            if(al != *rbp){
                edx = 1
                return_();
            }
        }
    }else{
        edx = 1
        return_();
    }

}

void phase_5(){

    push rbx
    rsp -= 0x20
    rbx = rdi 
    rax = *(fs + 0x28)
    rax = *(rsp + 0x18) 
    int check = string_length();
    if(check != 6){
        explode_bomb()
    }

    eax = 0
    do{
        ecx = *(rbx + rax)
        *(rsp) = cl
        rdx = *(rsp)

        edx = edx & 0xf
        edx = *(rdx + 0x4024b0)

        *(rsp + rax + 16) = dl
        rax += 1 
    }while(rax != 6)

    *(rsp + 0x16) = 0
    esi = 0x40245e
    rdi = rsp + 16
    int check_ = strings_not_equal()
    if(check_ != 0){
        explode_bomb()
    }
    rax = *(rsp + 0x18)

    rax ^= *(fs + 0x28)
    if(rax != 0){
        __stack_chk_fail@plt()      // 检测金丝雀值
    }     

    rsp += 0x20
    pop rbx
    ret
}

 C_Like代码:

// phase_5


int 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 + 0x20

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

 

 

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

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

00000000004010f4 <phase_6>:

  4010fc:	48 83 ec 50          	sub    $0x50,%rsp
  401100:	49 89 e5             	mov    %rsp,%r13
  401103:	48 89 e6             	mov    %rsp,%rsi
  401106:	e8 51 03 00 00       	call   40145c <read_six_numbers>
  40110b:	49 89 e6             	mov    %rsp,%r14

  40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d   # i = 0
# num_1:  外层循环
-------------------------------------------------
  401114:	4c 89 ed             	mov    %r13,%rbp
  401117:	41 8b 45 00          	mov    0x0(%r13),%eax
  40111b:	83 e8 01             	sub    $0x1,%eax

      # 爆炸(eax > 6)
      ---------------------
  40111e:	83 f8 05             	cmp    $0x5,%eax
  401121:	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 += 1

  40112c:	41 83 fc 06          	cmp    $0x6,%r12d             # i == 6
  401130:	74 21                	je     401153 <phase_6+0x5f>  # 退出整个循环

  401132:	44 89 e3             	mov    %r12d,%ebx
  #  内层循环
  -------------------------------------------------  
  401135:	48 63 c3             	movslq %ebx,%rax
  401138:	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 += 1

  401148:	83 fb 05             	cmp    $0x5,%ebx              # j > 5
  40114b:	7e e8                	jle    401135 <phase_6+0x41>  # 退出内层循环

  ------------------------------------------------- 

  40114d:	49 83 c5 04          	add    $0x4,%r13
  401151:	eb c1                	jmp    401114 <phase_6+0x20>

-------------------------------------------------------------



  401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi
  401158:	4c 89 f0             	mov    %r14,%rax  # addr = rsp
  40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
# num_2 循环
-------------------------------------------------------------
      401160:	89 ca                	mov    %ecx,%edx
      401162:	2b 10                	sub    (%rax),%edx
      401164:	89 10                	mov    %edx,(%rax)
      401166:	48 83 c0 04          	add    $0x4,%rax              # addr += 4

      40116a:	48 39 f0             	cmp    %rsi,%rax              # addr == rsp + 0x18
      40116d:	75 f1                	jne    401160 <phase_6+0x6c>  # 退出循环
-------------------------------------------------------------


  40116f:	be 00 00 00 00       	mov    $0x0,%esi
  401174:	eb 21                	jmp    401197 <phase_6+0xa3>

# num_3 外层循环
-------------------------------------------------------------
  # num_3 内层循环1
  -------------------------------------------------------------
  401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
  40117a:	83 c0 01             	add    $0x1,%eax
  40117d:	39 c8                	cmp    %ecx,%eax
  40117f:	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,%edx
    401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
    40118d:	48 83 c6 04          	add    $0x4,%rsi
    401191:	48 83 fe 18          	cmp    $0x18,%rsi
    401195:	74 14                	je     4011ab <phase_6+0xb7>
  num_3 start: 
    401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
    40119a:	83 f9 01             	cmp    $0x1,%ecx
    40119d:	7e e4                	jle    401183 <phase_6+0x8f>
  -------------------------------------------------------------

  40119f:	b8 01 00 00 00       	mov    $0x1,%eax
  4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx
  4011a9:	eb cb                	jmp    401176 <phase_6+0x82>
-------------------------------------------------------------

  4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
  4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
  4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
  4011ba:	48 89 d9             	mov    %rbx,%rcx

# num_4 循环
-------------------------------------------------------------
    
    4011bd:	48 8b 10             	mov    (%rax),%rdx
    4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
    4011c4:	48 83 c0 08          	add    $0x8,%rax

    // break;  
    4011c8:	48 39 f0             	cmp    %rsi,%rax
    4011cb:	74 05                	je     4011d2 <phase_6+0xde>

    4011cd:	48 89 d1             	mov    %rdx,%rcx
    4011d0:	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),%rax
    4011e3:	8b 00                	mov    (%rax),%eax
    4011e5:	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),%rbx
    4011f2:	83 ed 01             	sub    $0x1,%ebp
    4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
-------------------------------------------------------------


  4011f7:	48 83 c4 50          	add    $0x50,%rsp
  401203:	c3                   	ret 

 结构化汇编代码:


void phase_6(){
    r13 = rsp
    rsi = rsp
    read_six_numbers()
    r14 = rsp
    r12 = 0         # i = 0
# num_1 外层循环
-------------------------------------------------   
    rbp = r13   (rsp 副本)
    eax =  *rsp - 1

    if(eax <= 5){
        explode_bomb()
    }

    r12 += 1        # i += 1
                    # 退出整个循环(i == 6)
    if(r12 == 6){   
        break;
    }

    ebx = r12   # j = r12

    # 内层循环
    -------------------------------------------------   
    rax = ebx
    eax = *(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 = 7
        edx -= *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) = rdx
        rax += 8
        if(rax == rsp + 0x50){
            break;
        }
        rcx = rdx        
    }

-------------------------------------------------------------
 
    *(rdx + 8) = 0
    
# num_5 循环
-------------------------------------------------------------
    for(ebp = 5;ebp != 0;ebp -= 1){
        rax = *(rbx + 8)
        eax = *rax
        if(*rbx < eax){
        explode_bomb()  
        }
        rbx = *(rbx + 8)
    }
-------------------------------------------------------------

    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2082097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MMsegmentation与MMdeploy简单使用

最近涉及到了图像分割的任务&#xff0c;于是拿来写下博客加深下使用。 MMsegmentation与MMdeploy的环境配置暂不做讲解&#xff0c;在官网和其他博客中有很多说明。 MMdeploy主要是把pt转为 onnx_int8的情况。 MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation 目录…

【管理型文档】软件需求管理过程(原件)

软件需求管理规程应明确需求收集、分析、确认、变更控制及验证等流程&#xff0c;确保需求准确反映用户期望&#xff0c;支撑软件开发。该规程要求系统记录需求来源&#xff0c;通过评审确保需求完整、清晰、无歧义&#xff0c;实施变更控制以维护需求基线稳定&#xff0c;并持…

后端面试真题整理

面试问题整理 本人主要记录2024年秋招、春招过程中的疑难八股真题&#xff0c;参考来源&#xff1a;牛客网、知乎等。 八股 深拷贝与浅拷贝 浅拷贝&#xff1a; 浅拷贝会在堆上创建一个新的对象&#xff08;区别于引用拷贝的一点&#xff09;&#xff0c;不过&#xff0c;如果…

井盖丢失隐患大?智慧井盖监管系统帮你解决

在现代都市中&#xff0c;我们每天行走在钢筋水泥之间&#xff0c;却很少有人注意到脚下的小小井盖。这些不起眼的圆形铁盘不仅是城市地下管网的入口&#xff0c;更是维系城市生命线的重要组成部分。然而&#xff0c;当暴雨来袭&#xff0c;或是深夜无人之时&#xff0c;井盖的…

无线麦克风什么牌子的音质效果好?一文读懂麦克风哪个牌子的好

无线领夹麦克风哪款音质最好&#xff1f;在这个追求高质量音效的年代&#xff0c;选择一款合适的无线领夹麦克风&#xff08;简称领夹麦&#xff09;对于提升录音或直播的音质至关重要。随着市场的不断扩大&#xff0c;市面上充斥着大量信号不稳定、音质差的无线领夹麦克风&…

2024年汽车零部件企业CRM研究:服务商排名、案例分析、需求分析

最近媒体上频现各车企大佬发声&#xff0c;抗议某汽车企业“不要卷价格&#xff0c;要卷长期价值”&#xff0c;还有的直接批判其打破行业规则。图穷匕现&#xff0c;汽车行业的竞争愈发激烈了。 汽车产业作为我国国民经济的重要支柱产业、经济增长和转型的重要抓手&#xff0…

微软将持续多年的 Mono 项目移交给 Wine

今天&#xff0c;微软突然决定将 Mono 项目交由 Wine 开发社区管理。自Mono项目上一次作为开源.NET框架发布以来&#xff0c;已经过去了五年时间&#xff0c;此前Wine已经使用了Mono的代码&#xff0c;而在微软专注于开源.NET和其他工作的情况下&#xff0c;此举是合理的&#…

Python编程的终极十大工具(非常详细)零基础入门到精通,收藏这一篇就够了

&#x1f91f; 基于入门网络安全打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 Python一直以来都是程序员们的首选编程语言之一&#xff0c;其灵活性和功能强大的库使其成为解决各种问题的理想选择。在本文中&#xff0c;我们将介绍Python编程的终…

fdMemTable内存表进行SQL查询

fdLocalSql可以对fdMemTable内存表进行SQL查询&#xff08;可以对多个fdMemTable内存表进行联表查询哦&#xff09;&#xff0c;fdLocalSql使用SQLITE引擎&#xff0c;而FIREDAC驱动SQLITE&#xff0c;连SQLITE驱动DLL都不需要附带的。 所有设置用FormCreate里用代码 procedure…

【C#】Visual Studio2017 MSDN离线安装

1. 运行Visual Studio Installer 在Windows的开始菜单中直接搜索 2. 单击“修改”按钮 3. 依次点击&#xff0c;单个组件 - 代码工具 - Help Viewer - 修改&#xff0c;开始安装 4. 下载速度慢解决方法 修改IPv4 DNS 参考&#xff1a;visual studio下载慢解决方法&#xf…

unity脚本

Transform.Rotate 描述 使用 Transform.Rotate 以各种方式旋转 GameObjects。通常以欧拉角而不是四元数提供旋转。 可以在世界轴或本地轴中指定旋转。 世界轴旋转使用 Scene 的坐标系&#xff0c;因此在开始旋转 GameObject 时&#xff0c;它的 x、y 和 z 轴与 x、y 和 z 世…

Leetcode 131.分割回文串 回溯 C++实现

Leetcode 131. 分割回文串 问题&#xff1a;给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 算法&#xff1a; 创建二维返回数组 ans &#xff0c;和临时数组 path 。 进入 dfs 函数&#xff0c;当 …

初识linux(1)

linux背景 1991年10月5日&#xff0c;赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组 &#xff08;comp.os.minix&#xff09;中宣布他编制出了一种类似UNIX的小操作系统&#xff0c;叫Linux。新的操作系统是受到另 一个UNIX的小操作系统——Minix的启发…

今日arXiv最热大模型论文:港大微软发布AgentGen提高大模型规划能力,8B模型接近GPT-4水平

夕小瑶科技说 原创 作者 | Richard 在大语言模型&#xff08;LLM&#xff09;问世之后&#xff0c;基于 LLM 的 Agent 引起了广泛的关注并且变得越来越流行。规划能力无论对人类还是 Agent 都是一个重要的决策步骤&#xff0c;规划的本质是通过预先设定的行动过程&#xff0c…

软件设计师全套备考系列文章20 -- UML建模(重点,15分)

软考-- 软件设计师&#xff08;20&#xff09;-- UML建模(重点&#xff0c;15分) 文章目录 软考-- 软件设计师&#xff08;20&#xff09;-- UML建模(重点&#xff0c;15分)前言一、章节考点二、概述三、类图四、用例图五、顺序图六、活动图七、状态图八、通信图九、构建图 前言…

扫码点餐系统的前景如何?

扫码点餐系统作为一种餐饮业数字化转型的关键工具&#xff0c;其发展前景广阔。随着移动支付和智能手机的普及&#xff0c;该系统在餐厅、咖啡馆、快餐店等场所得到广泛应用&#xff0c;不仅简化了顾客点餐流程&#xff0c;减轻了服务员的工作负担&#xff0c;还提高了翻台率。…

沃尔玛停止在 3 个城市使用无人机送货,将重点转移到达拉斯

沃尔玛&#xff0c;作为全球领先的零售商&#xff0c;一直在探索创新的物流解决方案以提升顾客体验。近年来&#xff0c;该公司与无人机送货服务提供商DroneUp合作&#xff0c;尝试通过无人机技术实现快速配送服务。然而&#xff0c;经过一段时间的试点运营后&#xff0c;沃尔玛…

输电线路分布式故障诊断系统:分布式智慧网络的构建

输电线路分布式故障诊断系统&#xff1a;分布式智慧网络的构建 今天&#xff0c;就让深圳鼎信智慧科技陪大家一起走进输电线路分布式故障定位系统的世界&#xff1a; 1、系统架构&#xff1a;分布式智慧网络的构建 输电线路分布式故障定位系统主要由三大核心部分组成&#x…

微服务|一文带你了解无感知部署方案实战

目录 一、现有部署方案介绍 二、Nacos 介绍 三、影响时间的因素 四、方案目录结构 五、方案脚本实现 六、遇到的问题及优化 七、其他替代方案 一、现有部署方案介绍 在程序开发和运维过程中&#xff0c;会频繁地部署服务&#xff0c;并且每个服务的正常运行都依赖于其他服…

Springboot @RestControllerAdvice全局异常捕获处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、RestControllerAdvice二、案例1.自定义异常2.自定义相应常量3.自定义响应类4.核心逻辑5.测试 一、RestControllerAdvice RestControllerAdvice是Spring框架提供…