190919 pwn-第五空间final_十生

本文介绍了如何利用SEH(Structured Exception Handling)在飞秋0day漏洞中进行缓冲区溢出攻击。通过找到溢出点偏移并构造ROP链,覆盖SEH handler来控制程序执行流程,最终执行shellcode获取shell。

说是题目,其实就是飞秋0day 233
之前虽然听说过各种windows的pwn
软件停止更新已久,保护都没开,是比较古老的玩意儿了
于是很容易搜到各种POC
例如0x49D03F处的整形溢出
在这里插入图片描述
在这里插入图片描述
v54是输入进来的字符串,因此可以提供4294967295=0xffffffff=-1从而使memcpy发生缓冲区溢出的异常,然后通过覆盖SEH的方式进行利用

通过cyclic生成字符串填入,可以测出溢出点的偏移7382+4
然后在7382的位置填入ROP的地址

SEH的利用方式

因为异常处理handler的第二个参数esp+8正好是异常结构的地址EstblisherFrame,即偏移7382的位置

因此地址可以填充pop+pop+retn的ROP,从而回到原栈
再在7382的位置填充jmp $+6即可跳过ROP地址,执行后面的shellcode
代码:

char 
<think>我们正在处理一个关于STM32的HAL_TIM_IC_CaptureCallback函数的问题。用户想要理解和优化这个函数中的定时器捕获逻辑。 首先,我们需要了解HAL_TIM_IC_CaptureCallback函数的作用:它是输入捕获模式下的回调函数,当发捕获事件(比如捕获到上升沿或下降沿)时,由HAL库调用。 通常,在这个回调函数中,我们会读取捕获到的值(比如CCRx寄存器的值),然后计算脉冲宽度或频率。 优化建议: 1. 减少回调函数中的处理时间:因为这是一个中断服务程序调用的回调函数,所以应该尽量快。避免在回调函数中做复杂的计算或调用耗时的函数(如printf)。 2. 使用DMA:对于高频率的捕获,可以考虑使用DMA来传输捕获值,避免频繁中断。 3. 双重缓冲:使用两个缓冲区交替存储捕获值,一个用于读取(处理),一个用于写入(捕获),这样可以避免数据竞争。 4. 状态机设计:如果捕获的信号需要多个边沿(比如同时捕获上升沿和下降沿),可以使用状态机来管理,避免在回调函数中做复杂的条件判断。 下面是一个简单的示例,展示如何捕获一个PWM信号的高电平宽度(使用两个边沿): 假设我们使用TIM2的通道1(CH1)进行输入捕获。 步骤: 1. 初始化时,设置捕获边沿为上升沿(等待第一个上升沿)。 2. 在回调函数中: 当捕获到上升沿时,记录当前捕获值,并设置下一次捕获为下降沿。 当捕获到下降沿时,记录当前捕获值,并计算高电平宽度(下降沿捕获值 - 上升沿捕获值),然后设置下一次捕获为上升沿。 注意:如果计数器溢出,需要考虑溢出次数。 优化后的代码结构: 在全局变量中定义: volatile uint32_t riseValue = 0; volatile uint32_t fallValue = 0; volatile uint32_t highPulse = 0; volatile uint8_t captureFlag = 0; // 用于通知主循环有新数据 在回调函数中: void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { // 检查当前的捕获边沿 if (__HAL_TIM_GET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1) == TIM_ICPOLARITY_RISING) { // 上升沿捕获 riseValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 改变捕获边沿为下降沿 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING); // 清除标志位,重新开始捕获 __HAL_TIM_SET_COUNTER(htim, 0); } else { // 下降沿捕获 fallValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 计算高电平宽度(注意:这里没有考虑计数器溢出) highPulse = fallValue - riseValue; captureFlag = 1; // 通知主循环 // 改变捕获边沿为上升沿 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING); } } } } 但是上述代码没有考虑计数器溢出的情况。如果脉冲宽度较长,计数器可能会溢出多次。因此,我们需要在每次捕获时考虑溢出次数。 优化建议:使用HAL库提供的输入捕获中断和溢出中断结合的方式。在溢出中断中记录溢出次数。 因此,我们需要: 1. 开启TIM2的更新中断(溢出中断)。 2. 在更新中断的回调函数中,对溢出次数计数。 在全局变量中: volatile uint32_t overflowCount = 0; 更新中断回调函数: void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { overflowCount++; } } 然后在捕获回调函数中,我们需要结合溢出次数来计算实际的捕获值。 但是注意:在捕获发时,读取溢出次数可能会被更新中断打断,因此需要采取一些保护措施(比如暂时关闭中断)。 另一种方法是使用定时器的从模式(复位模式),在每次捕获后复位计数器,这样就不会有溢出的问题(但这样只能测量相邻两个边沿的时间,不能测量超过一个周期的脉冲)。 根据用户需求,如果需要测量长脉冲,则必须处理溢出。下面给出一个处理溢出的例子: 在捕获回调函数中: if (htim->Instance == TIM2) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { uint32_t currentCapture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); uint32_t currentOverflow = overflowCount; // 读取当前的溢出次数 if (__HAL_TIM_GET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1) == TIM_ICPOLARITY_RISING) { // 上升沿捕获 // 记录当前的总计数值 = currentOverflow * (TIM2->ARR + 1) + currentCapture riseValue = currentOverflow * (TIM2->ARR + 1) + currentCapture; // 改变为下降沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING); } else { // 下降沿捕获 fallValue = currentOverflow * (TIM2->ARR + 1) + currentCapture; // 计算高电平宽度 highPulse = fallValue - riseValue; captureFlag = 1; // 改变为上升沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING); } } } 但是注意:在读取overflowCount和currentCapture之间,可能发更新中断,导致overflowCount增加而currentCapture是更新前的值。因此,我们需要在读取时暂时关闭更新中断,读取后再打开。 优化后的代码: uint32_t currentCapture; uint32_t currentOverflow; // 关闭更新中断 __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); currentCapture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); currentOverflow = overflowCount; // 重新开启更新中断 __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE); 这样,在读取过程中,更新中断被禁止,因此不会发更新中断,保证了数据的一致性。 总结:优化定时器捕获逻辑的关键在于减少中断处理时间、正确处理计数器溢出以及避免在中断中进行复杂操作。同时,使用标志位通知主循环,在主循环中处理数据(如计算、显示等)。 另外,如果用户需要测量高频率的信号,可以考虑使用定时器的从模式(复位模式)来避免溢出,或者使用更高频率的定时器。 根据用户的问题,我们提供上述优化思路。用户可以根据具体应用场景选择合适的方法。 成相关问题: 1. 在STM32中,如何配置定时器以进行输入捕获? 2. 如何处理定时器捕获中的溢出问题? 3. 使用DMA进行输入捕获有哪些步骤? 4. 如何降低输入捕获中断的处理时间? 5. 在测量PWM信号时,如何同时测量频率和占空比?</think>### 理解并优化 `HAL_TIM_IC_CaptureCallback` 函数逻辑 `HAL_TIM_IC_CaptureCallback` 是 STM32 HAL 库中用于处理输入捕获(Input Capture)事件的回调函数。当定时器捕获到特定边沿(上升沿/下降沿)时自动触发,常用于测量脉冲宽度、频率或编码器信号。 #### 基础逻辑流程 ```c void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { // 1. 检查触发捕获的定时器和通道 if (htim->Instance == TIMx) { switch (htim->Channel) { case HAL_TIM_ACTIVE_CHANNEL_1: // 2. 读取捕获值 uint32_t capture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 3. 边沿检测状态机 if (当前是上升沿模式) { // 记录上升沿时间 rise_time = capture; // 切换为下降沿检测 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); } else { // 记录下降沿时间 fall_time = capture; // 计算脉冲宽度 pulse_width = fall_time - rise_time; // 切换回上升沿检测 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); } break; // 其他通道处理... } } } ``` #### 关键优化策略 1. **减少中断处理时间** - 避免复杂计算:将数据处理移至主循环,仅用标志位通知 - 使用 DMA 传输捕获值(配置 `TIMx_DIER` 寄存器启用 DMA) - 示例优化: ```c volatile uint32_t g_capture_value; volatile bool g_new_capture = false; void HAL_TIM_IC_CaptureCallback(...) { g_capture_value = HAL_TIM_ReadCapturedValue(...); g_new_capture = true; // 主循环中处理数据 } ``` 2. **处理计数器溢出** ```c // 全局变量 volatile uint32_t g_overflow_count = 0; // 在TIM溢出中断中 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { g_overflow_count++; } // 计算实际时间(考虑溢出) uint32_t actual_time = capture_value + (g_overflow_count * (htim->Instance->ARR + 1)); ``` 3. **双缓冲机制** ```c #define BUF_SIZE 32 volatile uint32_t g_capture_buf[BUF_SIZE]; volatile uint8_t g_buf_index = 0; void HAL_TIM_IC_CaptureCallback(...) { if(g_buf_index < BUF_SIZE) { g_capture_buf[g_buf_index++] = HAL_TIM_ReadCapturedValue(...); } // 主循环定期处理缓冲区 } ``` 4. **动态调整捕获边沿** ```c // 根据信号特征自动切换极性 if (current_polarity == RISING) { if (capture_value < threshold) { __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, FALLING); } } ``` 5. **硬件优化** - 使用定时器级联(主从模式)扩展计数范围 - 启用输入滤波(配置 `TIMx_CCMR1` 寄存器) - 使用复位模式(`TIM_SLAVEMODE_RESET`)自动清零计数器 #### 完整优化示例 ```c // 全局变量 volatile struct { uint32_t rise_time; uint32_t fall_time; bool data_ready; } pulse_data; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance != TIM2) return; uint32_t capture = TIM2->CCR1; // 直接读取寄存器更快 if (TIM2->CCER & TIM_CCER_CC1P) { // 检查当前是下降沿模式 pulse_data.fall_time = capture; pulse_data.data_ready = true; TIM2->CCER &= ~TIM_CCER_CC1P; // 切回上升沿检测 } else { pulse_data.rise_time = capture; TIM2->CCER |= TIM_CCER_CC1P; // 切换为下降沿检测 } // 清除中断标志 __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); } ``` > 重要提示:在测量高频信号时,使能定时器预分频器(`TIMx_PSC`)可降低中断频率。对于超过 100kHz 的信号,建议结合 DMA 使用[^1]。 --- ### 相关问题 1. 如何配置 STM32 定时器实现 PWM 输入捕获模式? 2. 在输入捕获模式下如何处理信号抖动问题? 3. 如何通过 DMA 传输定时器捕获值以降低 CPU 负载? 4. STM32 中定时器级联有哪些应用场景? 5. 如何测量超过定时器最大计数值的长脉冲信号? [^1]: 移植 OpenHarmony 到 STM32F407ZG 开发板的工程配置参考
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值