pwnable.kr_mistake

博客围绕pwnable.kr_mistake题目展开,指出要点是运算符优先级。连上服务器后查看题目文件夹下文件,依据提示找到代码关键点,因相关返回值和运算符优先级,代码实际等待用户输入而非读password文件,只需在fd赋值后输入密码和xor后的密码就能拿到flag。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pwnable.kr_mistake
题面:

We all make mistakes, let's move on.
(don't take this too seriously, no fancy hacking skill is required at all)

This task is based on real event
Thanks to dhmonkey

hint : operator priority

ssh mistake@pwnable.kr -p2222 (pw:guest)

提示这道题的要点是运算符的优先级

连上服务器后发现题目文件夹下有四个文件

mistake@ubuntu:~$ ls -l
total 24
-r-------- 1 mistake_pwn root      51 Jul 29  2014 flag
-r-sr-x--- 1 mistake_pwn mistake 8934 Aug  1  2014 mistake
-rw-r--r-- 1 root        root     792 Aug  1  2014 mistake.c
-r-------- 1 mistake_pwn root      10 Jul 29  2014 password

查看一下mistake.c

#include <stdio.h>                                               
#include <fcntl.h>                                               

#define PW_LEN 10                                                
#define XORKEY 1                                                 

void xor(char* s, int len){                                      
        int i;                                                   
        for(i=0; i<len; i++){                                    
                s[i] ^= XORKEY;                                  
        }                                                        
}                                                                

int main(int argc, char* argv[]){                                

        int fd;                                                  
        if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){ 
                printf("can't open password %d\n", fd);          
                return 0;                                        
        }                                                        

        printf("do not bruteforce...\n");                        
        sleep(time(0)%20);                                       

        char pw_buf[PW_LEN+1];                                   
        int len;                                                 
        if(!(len=read(fd,pw_buf,PW_LEN) > 0)){                   
                printf("read error\n");                          
                close(fd);                                       
                return 0;                                        
        }                                                        

        char pw_buf2[PW_LEN+1];                                  
        printf("input password : ");                             
        scanf("%10s", pw_buf2);                                  

        // xor your input                                        
        xor(pw_buf2, 10);                                        

        if(!strncmp(pw_buf, pw_buf2, PW_LEN)){                   
                printf("Password OK\n");                         
                system("/bin/cat flag\n");                       
        }                                                        
        else{                                                    
                printf("Wrong Password\n");                      
        }                                                        

        close(fd);                                               
        return 0;                                                
}                                                                

根据题目的提示运算符我找一些代码中的关键点

 if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){ 
                printf("can't open password %d\n", fd);          
                return 0;                                        
        }      

在这里由于open()的返回值不会小于0,且<的优先级比=高,所以这句语句的结果是open()的返回值!<0,所以open("/home/mistake/password",O_RDONLY,0400) < 0的值为false,因此赋值给fd的时候fd为0,此平台的第一题就是考察的File descriptor,当值为0时执行标准输入,因此实际上代码并不会读password文件,而是等待用户的输入,这就可以让我们来伪造password

        xor(pw_buf2, 10);                                        
        //对用户的输入xor                                                         
        if(!strncmp(pw_buf, pw_buf2, PW_LEN)){     //比较xor后的密码与“原”密码              
                printf("Password OK\n");                         
                system("/bin/cat flag\n");                       
        }   

因此我们只需要再fd赋值之后输入自己的10位密码,然后再输入xor后的密码,即可比对成功拿到flag

mistake@ubuntu:~$ ./mistake
do not bruteforce...
1111111111
input password : 0000000000
Password OK
Mommy, the operator priority always confuses me :(
import logging import time from functools import cached_property from typing import Any from lerobot.cameras.utils import make_cameras_from_configs from lerobot.errors import DeviceAlreadyConnectedError, DeviceNotConnectedError from lerobot.motors import Motor, MotorCalibration, MotorNormMode from lerobot.motors.dynamixel import ( DynamixelMotorsBus, OperatingMode, ) from ..robot import Robot from ..utils import ensure_safe_goal_position from .config_koch_follower import KochFollowerConfig logger = logging.getLogger(__name__) class KochFollower(Robot): """ - [Koch v1.0](https://github.com/AlexanderKoch-Koch/low_cost_robot), with and without the wrist-to-elbow expansion, developed by Alexander Koch from [Tau Robotics](https://tau-robotics.com) - [Koch v1.1](https://github.com/jess-moss/koch-v1-1) developed by Jess Moss """ config_class = KochFollowerConfig name = "koch_follower" def __init__(self, config: KochFollowerConfig): super().__init__(config) self.config = config norm_mode_body = MotorNormMode.DEGREES if config.use_degrees else MotorNormMode.RANGE_M100_100 self.bus = DynamixelMotorsBus( port=self.config.port, motors={ "shoulder_pan": Motor(1, "xl430-w250", norm_mode_body), "shoulder_lift": Motor(2, "xl430-w250", norm_mode_body), "elbow_flex": Motor(3, "xl330-m288", norm_mode_body), "wrist_flex": Motor(4, "xl330-m288", norm_mode_body), "wrist_roll": Motor(5, "xl330-m288", norm_mode_body), "gripper": Motor(6, "xl330-m288", MotorNormMode.RANGE_0_100), }, calibration=self.calibration, ) self.cameras = make_cameras_from_configs(config.cameras) @property def _motors_ft(self) -> dict[str, type]: return {f"{motor}.pos": float for motor in self.bus.motors} @property def _cameras_ft(self) -> dict[str, tuple]: return { cam: (self.config.cameras[cam].height, self.config.cameras[cam].width, 3) for cam in self.cameras } @cached_property def observation_features(self) -> dict[str, type | tuple]: return {**self._motors_ft, **self._cameras_ft} @cached_property def action_features(self) -> dict[str, type]: return self._motors_ft @property def is_connected(self) -> bool: return self.bus.is_connected and all(cam.is_connected for cam in self.cameras.values()) def connect(self, calibrate: bool = True) -> None: """ We assume that at connection time, arm is in a rest position, and torque can be safely disabled to run calibration. """ if self.is_connected: raise DeviceAlreadyConnectedError(f"{self} already connected") self.bus.connect() if not self.is_calibrated and calibrate: self.calibrate() for cam in self.cameras.values(): cam.connect() self.configure() logger.info(f"{self} connected.") @property def is_calibrated(self) -> bool: return self.bus.is_calibrated def calibrate(self) -> None: logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: self.bus.write("Operating_Mode", motor, OperatingMode.EXTENDED_POSITION.value) input(f"Move {self} to the middle of its range of motion and press ENTER....") homing_offsets = self.bus.set_half_turn_homings() full_turn_motors = ["shoulder_pan", "wrist_roll"] unknown_range_motors = [motor for motor in self.bus.motors if motor not in full_turn_motors] print( f"Move all joints except {full_turn_motors} sequentially through their entire " "ranges of motion.\nRecording positions. Press ENTER to stop..." ) range_mins, range_maxes = self.bus.record_ranges_of_motion(unknown_range_motors) for motor in full_turn_motors: range_mins[motor] = 0 range_maxes[motor] = 4095 self.calibration = {} for motor, m in self.bus.motors.items(): self.calibration[motor] = MotorCalibration( id=m.id, drive_mode=0, homing_offset=homing_offsets[motor], range_min=range_mins[motor], range_max=range_maxes[motor], ) self.bus.write_calibration(self.calibration) self._save_calibration() logger.info(f"Calibration saved to {self.calibration_fpath}") def configure(self) -> None: with self.bus.torque_disabled(): self.bus.configure_motors() # Use 'extended position mode' for all motors except gripper, because in joint mode the servos # can't rotate more than 360 degrees (from 0 to 4095) And some mistake can happen while assembling # the arm, you could end up with a servo with a position 0 or 4095 at a crucial point for motor in self.bus.motors: if motor != "gripper": self.bus.write("Operating_Mode", motor, OperatingMode.EXTENDED_POSITION.value) # Use 'position control current based' for gripper to be limited by the limit of the current. For # the follower gripper, it means it can grasp an object without forcing too much even tho, its # goal position is a complete grasp (both gripper fingers are ordered to join and reach a touch). # For the leader gripper, it means we can use it as a physical trigger, since we can force with # our finger to make it move, and it will move back to its original target position when we # release the force. self.bus.write("Operating_Mode", "gripper", OperatingMode.CURRENT_POSITION.value) # Set better PID values to close the gap between recorded states and actions # TODO(rcadene): Implement an automatic procedure to set optimal PID values for each motor self.bus.write("Position_P_Gain", "elbow_flex", 1500) self.bus.write("Position_I_Gain", "elbow_flex", 0) self.bus.write("Position_D_Gain", "elbow_flex", 600) def setup_motors(self) -> None: for motor in reversed(self.bus.motors): input(f"Connect the controller board to the '{motor}' motor only and press enter.") self.bus.setup_motor(motor) print(f"'{motor}' motor id set to {self.bus.motors[motor].id}") def get_observation(self) -> dict[str, Any]: if not self.is_connected: raise DeviceNotConnectedError(f"{self} is not connected.") # Read arm position start = time.perf_counter() obs_dict = self.bus.sync_read("Present_Position") obs_dict = {f"{motor}.pos": val for motor, val in obs_dict.items()} dt_ms = (time.perf_counter() - start) * 1e3 logger.debug(f"{self} read state: {dt_ms:.1f}ms") # Capture images from cameras for cam_key, cam in self.cameras.items(): start = time.perf_counter() obs_dict[cam_key] = cam.async_read() dt_ms = (time.perf_counter() - start) * 1e3 logger.debug(f"{self} read {cam_key}: {dt_ms:.1f}ms") return obs_dict def send_action(self, action: dict[str, float]) -> dict[str, float]: """Command arm to move to a target joint configuration. The relative action magnitude may be clipped depending on the configuration parameter `max_relative_target`. In this case, the action sent differs from original action. Thus, this function always returns the action actually sent. Args: action (dict[str, float]): The goal positions for the motors. Returns: dict[str, float]: The action sent to the motors, potentially clipped. """ if not self.is_connected: raise DeviceNotConnectedError(f"{self} is not connected.") goal_pos = {key.removesuffix(".pos"): val for key, val in action.items() if key.endswith(".pos")} # Cap goal position when too far away from present position. # /!\ Slower fps expected due to reading from the follower. if self.config.max_relative_target is not None: present_pos = self.bus.sync_read("Present_Position") goal_present_pos = {key: (g_pos, present_pos[key]) for key, g_pos in goal_pos.items()} goal_pos = ensure_safe_goal_position(goal_present_pos, self.config.max_relative_target) # Send goal position to the arm self.bus.sync_write("Goal_Position", goal_pos) return {f"{motor}.pos": val for motor, val in goal_pos.items()} def disconnect(self): if not self.is_connected: raise DeviceNotConnectedError(f"{self} is not connected.") self.bus.disconnect(self.config.disable_torque_on_disconnect) for cam in self.cameras.values(): cam.disconnect() logger.info(f"{self} disconnected.")
最新发布
07-26
<think>我们正在分析一个名为KochFollower的机器人手臂控制类,它使用Dynamixel电机和摄像头。这个类继承自Robot基类,实现了连接、校准、配置、获取观测、发送动作和断开连接等功能。我们将逐步解析关键部分。 ### 1. 初始化 ```python def __init__(self, config: KochFollowerConfig): super().__init__(config) self.config = config norm_mode_body = MotorNormMode.DEGREES if config.use_degrees else MotorNormMode.RANGE_M100_100 self.bus = DynamixelMotorsBus( port=self.config.port, motors={ "shoulder_pan": Motor(1, "xl430-w250", norm_mode_body), "shoulder_lift": Motor(2, "xl430-w250", norm_mode_body), "elbow_flex": Motor(3, "xl330-m288", norm_mode_body), "wrist_flex": Motor(4, "xl330-m288", norm_mode_body), "wrist_roll": Motor(5, "xl330-m288", norm_mode_body), "gripper": Motor(6, "xl330-m288", MotorNormMode.RANGE_0_100), }, calibration=self.calibration, ) self.cameras = make_cameras_from_configs(config.cameras) ``` - 根据配置选择电机位置归一化模式(角度或范围[-100,100]) - 创建Dynamixel总线,包含6个电机(5个关节和1个夹爪) - 夹爪使用特殊的归一化模式(范围[0,100]) - 根据配置创建摄像头 ### 2. 观测和动作特征 ```python @property def _motors_ft(self) -> dict[str, type]: return {f"{motor}.pos": float for motor in self.bus.motors} @property def _cameras_ft(self) -> dict[str, tuple]: return { cam: (self.config.cameras[cam].height, self.config.cameras[cam].width, 3) for cam in self.cameras } @cached_property def observation_features(self) -> dict[str, type | tuple]: return {**self._motors_ft, **self._cameras_ft} @cached_property def action_features(self) -> dict[str, type]: return self._motors_ft ``` - 观测特征包括电机位置(浮点数)和摄像头图像(高度、宽度、3通道) - 动作特征只包含电机位置 ### 3. 连接与校准 **连接流程**: 1. 检查是否已连接 2. 连接电机总线 3. 若未校准且`calibrate`为True,则执行校准 4. 连接所有摄像头 5. 配置电机 6. 记录日志 **校准流程**: ```python def calibrate(self) -> None: logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: self.bus.write("Operating_Mode", motor, OperatingMode.EXTENDED_POSITION.value) input(f"Move {self} to the middle of its range of motion and press ENTER....") homing_offsets = self.bus.set_half_turn_homings() full_turn_motors = ["shoulder_pan", "wrist_roll"] unknown_range_motors = [motor for motor in self.bus.motors if motor not in full_turn_motors] print( f"Move all joints except {full_turn_motors} sequentially through their entire " "ranges of motion.\nRecording positions. Press ENTER to stop..." ) range_mins, range_maxes = self.bus.record_ranges_of_motion(unknown_range_motors) for motor in full_turn_motors: range_mins[motor] = 0 range_maxes[motor] = 4095 self.calibration = {} for motor, m in self.bus.motors.items(): self.calibration[motor] = MotorCalibration( id=m.id, drive_mode=0, homing_offset=homing_offsets[motor], range_min=range_mins[motor], range_max=range_maxes[motor], ) self.bus.write_calibration(self.calibration) self._save_calibration() logger.info(f"Calibration saved to {self.calibration_fpath}") ``` - 设置电机为扩展位置模式(可多圈旋转) - 用户将机器人移动到中间位置,设置半圈归零 - 对于非全转电机(非肩部旋转和腕部旋转),用户移动关节记录运动范围 - 全转电机范围设为0到4095(对应多圈) - 保存校准参数 ### 4. 配置电机 ```python def configure(self) -> None: with self.bus.torque_disabled(): self.bus.configure_motors() for motor in self.bus.motors: if motor != "gripper": self.bus.write("Operating_Mode", motor, OperatingMode.EXTENDED_POSITION.value) self.bus.write("Operating_Mode", "gripper", OperatingMode.CURRENT_POSITION.value) self.bus.write("Position_P_Gain", "elbow_flex", 1500) self.bus.write("Position_I_Gain", "elbow_flex", 0) self.bus.write("Position_D_Gain", "elbow_flex", 600) ``` - 在力矩禁用状态下配置 - 非夹爪电机设为扩展位置模式 - 夹爪设为基于电流的位置模式(可柔顺控制) - 设置肘关节的PID参数(P=1500, I=0, D=600) ### 5. 获取观测 ```python def get_observation(self) -> dict[str, Any]: # 读取电机位置 obs_dict = self.bus.sync_read("Present_Position") obs_dict = {f"{motor}.pos": val for motor, val in obs_dict.items()} # 读取摄像头图像 for cam_key, cam in self.cameras.items(): obs_dict[cam_key] = cam.async_read() return obs_dict ``` - 同步读取所有电机的当前位置 - 异步读取摄像头图像(避免阻塞) ### 6. 发送动作 ```python def send_action(self, action: dict[str, float]) -> dict[str, float]: goal_pos = {key.removesuffix(".pos"): val for key, val in action.items() if key.endswith(".pos")} if self.config.max_relative_target is not None: present_pos = self.bus.sync_read("Present_Position") goal_present_pos = {key: (g_pos, present_pos[key]) for key, g_pos in goal_pos.items()} goal_pos = ensure_safe_goal_position(goal_present_pos, self.config.max_relative_target) self.bus.sync_write("Goal_Position", goal_pos) return {f"{motor}.pos": val for motor, val in goal_pos.items()} ``` - 从动作中提取目标位置 - 若配置了最大相对目标,则限制目标位置与当前位置的差值 - 同步写入目标位置 - 返回实际发送的动作 ### 7. 断开连接 ```python def disconnect(self): self.bus.disconnect(self.config.disable_torque_on_disconnect) for cam in self.cameras.values(): cam.disconnect() ``` - 断开电机总线(可选择是否禁用力矩) - 断开所有摄像头 ### 关键问题与优化建议 1. **实时性能**: - 电机控制频率受限于总线通信速度(尤其是同步读写) - 建议:使用更高波特率(如3000000)并优化数据包大小 2. **安全保护**: - 现有实现通过`ensure_safe_goal_position`限制位置变化 - 可增加电流监控和温度保护: ```python # 读取电流和温度 current = self.bus.read("Present_Current", motor_id) temperature = self.bus.read("Present_Temperature", motor_id) ``` 3. **摄像头同步**: - 当前使用异步读取,可能导致图像与电机位置时间戳不一致 - 建议:硬件触发摄像头(参考引用[1]和[5]) 4. **校准流程**: - 依赖用户手动移动关节,易出错 - 可考虑自动校准(如通过预设安全位置) 5. **夹爪控制**: - 使用基于电流的位置模式,适合抓取 - 但缺少力反馈控制,可增加压力传感器反馈 ### 示例应用:物体抓取 ```mermaid graph TD A[相机检测物体] --> B[计算物体3D位置] B --> C[逆运动学求解关节角度] C --> D[发送目标位置到电机] D --> E[夹爪闭合] E --> F[提升物体] ``` 1. 相机检测物体(使用OpenCV或Caffe模型,参考引用[1]) 2. 通过手眼标定转换坐标(参考引用[2]和[4]) 3. 逆运动学计算目标关节角 4. 控制机械臂运动到目标位置 5. 控制夹爪抓取物体 ### 相关问题 §§相关问题§§ 1. 如何优化Dynamixel总线通信以提高控制频率? 2. 如何实现机械臂和相机的精确时间同步? 3. 在夹爪控制中如何加入力反馈? 4. 自动校准机器人关节范围的方法有哪些? 5. 如何通过视觉伺服实现机械臂的实时跟踪?</think>以下是对 KochFollower 机器人手臂控制代码的解析与优化建议,结合 Dynamixel 电机特性和相机集成方案: ### 一、核心组件分析 #### 1. Dynamixel 电机控制 ```python self.bus = DynamixelMotorsBus( port=self.config.port, motors={ "shoulder_pan": Motor(1, "xl430-w250", norm_mode_body), "shoulder_lift": Motor(2, "xl430-w250", norm_mode_body), "elbow_flex": Motor(3, "xl330-m288", norm_mode_body), "wrist_flex": Motor(4, "xl330-m288", norm_mode_body), "wrist_roll": Motor(5, "xl330-m288", norm_mode_body), "gripper": Motor(6, "xl330-m288", MotorNormMode.RANGE_0_100), }, calibration=self.calibration, ) ``` - **电机选择**: - XL430-W250(肩部):高扭矩(1.0 N·m)适合承重关节 - XL330-M288(肘/腕):288° 旋转范围适合精细操作 - 夹爪使用特殊归一化模式 `RANGE_0_100` 简化控制 #### 2. 安全位置控制 ```python if self.config.max_relative_target is not None: present_pos = self.bus.sync_read("Present_Position") goal_present_pos = {key: (g_pos, present_pos[key]) for key, g_pos in goal_pos.items()} goal_pos = ensure_safe_goal_position(goal_present_pos, self.config.max_relative_target) ``` - 通过 `max_relative_target` 限制单步运动幅度,避免超调 - 实时读取当前位置实现闭环控制 #### 3. 相机集成优化 ```python self.cameras = make_cameras_from_configs(config.cameras) def get_observation(self): for cam_key, cam in self.cameras.items(): obs_dict[cam_key] = cam.async_read() # 异步读取减少延迟 ``` - 使用异步读取 (`async_read`) 避免阻塞电机控制循环 - 支持多相机配置,需在 `config.cameras` 定义分辨率/帧率 ### 二、关键问题优化方案 #### 1. 电机超调问题(PID 调节) ```python # 在 configure() 中优化 PID 参数 self.bus.write("Position_P_Gain", "elbow_flex", 1500) # 比例增益 self.bus.write("Position_I_Gain", "elbow_flex", 0) # 积分增益 self.bus.write("Position_D_Gain", "elbow_flex", 600) # 微分增益 ``` - **调参原则**: 1. 先增大 $P$ 直至出现轻微振荡 ($P=1500$) 2. 增加 $D$ 抑制振荡 ($D=600$) 3. 保持 $I=0$ 避免积分饱和 - 建议为每个关节单独调参,特别是负载差异大的肩/肘关节 #### 2. 手眼标定验证 ```python # 标定验证伪代码 H_cam_base = load_calibration_matrix() # 加载标定矩阵 # 选取特征点验证 for point in validation_points: cam_coord = camera.detect(point) base_coord = arm.forward_kinematics() projected_coord = H_cam_base @ base_coord error = np.linalg.norm(cam_coord - projected_coord) assert error < 3.0 # 像素误差阈值 ``` - 使用棋盘格标定板时,重投影误差应 $<0.5$ 像素[^2] - 动态验证:机械臂末端放置 LED,轨迹跟踪误差 $<5$ mm #### 3. 通信延迟优化 ```python # 在 DynamixelMotorsBus 中实现 def sync_write(self, register: str, values: dict): # 将电机按物理位置分组 group1 = ["shoulder_pan", "shoulder_lift"] # 近端电机 group2 = ["elbow_flex", "wrist_flex", "wrist_roll"] # 远端电机 # 分组写入减少单次数据量 self._write_group(group1, register, values) self._write_group(group2, register, values) ``` - **总线优化**: - 波特率提升至 `3000000`(XL330 支持) - 单次指令包含 $\leq4$ 个电机 - 使用 `GroupSyncWrite` 替代单电机写入 #### 4. 相机-机械臂协同 ```python # 曝光时间匹配模型 max_arm_speed = 100 # deg/s joint_resolution = 0.1 # deg min_exposure = 1e3 / (max_arm_speed / joint_resolution) # μs def capture_safe(): arm.pause_control() # 暂停控制 image = cam.capture(exposure=min_exposure) arm.resume_control() return image ``` - 运动模糊控制:曝光时间 $t_{exp} \leq \frac{\text{位置分辨率}}{\text{最大角速度}}$ - 硬件触发:通过 GPIO 同步相机曝光与电机采样时刻[^1] ### 三、系统级优化建议 1. **重力补偿实现**: ```python def gravity_compensation(self): torque_map = { "shoulder_lift": -15.0, # 单位:mA "elbow_flex": 8.0, } self.bus.sync_write("Goal_Current", torque_map) ``` - 基于关节角度查表法补偿重力矩 - 需预先测量各关节重力矩曲线 2. **热保护机制**: ```python def _check_temperature(self): temps = self.bus.sync_read("Present_Temperature") if any(t > 75 for t in temps.values()): # 75°C 阈值 self.bus.disable_torque() ``` 3. **视觉伺服集成**: ```python def visual_servoing(self, target_coord): while True: img = self.cameras["top"].read() curr_coord = detect_position(img) error = target_coord - curr_coord if np.linalg.norm(error) < 5.0: # 5px 阈值 break action = self.visual_servo_controller(error) self.send_action(action) ``` ### 四、相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值