Windows X86 远线程注入问题解惑

news2024/9/23 18:00:27

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

问题描述

  Windows X86 远线程注入问题解惑
¥15
c++
windows
在之前提问的知道下 成功部署了 汇编器 ; 一会即将采纳。
新问题:(请通读全文 重点在于解惑)
下面这个是 X32dbg中 看到的一个功能call 作用是选中一个物体。

0057ADEB | 8B0D 90FB3801          | mov     ecx, dword ptr [138FB90]            |
0057ADF1 | 56                     | push    esi                                 |
0057ADF2 | E8 B9C14A00            | call    A26FB0                              |
0057ADF7 | 8BC8                   | mov     ecx, eax                            |
0057ADF9 | E8 D223FCFF            | call    53D1D0                              | 选中

这个是 我用来 翻译汇编为机器码的相关代码:
该汇编器 默认 地址为绝对地址(直接翻译)。

int QQSG::AsmToHex(ks_arch arch, int mode, const char* assembly, int syntax, QString& outStr, size_t* OutSize) {
    int status = 0;
    ks_engine* ks;
    ks_err err;
    size_t count;
    unsigned char* encode = nullptr;
    size_t size = 0;
 
    // Initialize Keystone engine
    err = ks_open(arch, mode, &ks);
    if (err != KS_ERR_OK) {
        printf("Failed to initialize Keystone engine: %d\n", ks_errno(ks));
        return -1;
    }
 
    // Set syntax option
    if (syntax)
        ks_option(ks, KS_OPT_SYNTAX, syntax);
 
    // Assemble instruction
    if (ks_asm(ks, assembly, 0, &encode, &size, &count)) {
        printf("ERROR: failed on ks_asm() with count = %zu, error code = %d\n", count, ks_errno(ks));
        ks_free(encode); // Free encoded data
        ks_close(ks);    // Close Keystone engine
        return 2;
    }
 
    // Check if the encoding was successful
    if (size > 0) {
        // Convert machine code to hexadecimal string
        for (size_t i = 0; i < size; i++) {
            char tmp[5];
            sprintf(tmp, "%02X", encode[i]);
            outStr += tmp;
        }
        outStr += "\r\n";
 
        // Print the machine code for debugging
        printf("Generated machine code: ");
        for (size_t i = 0; i < size; i++) {
            printf("%02X ", encode[i]);
        }
        printf("\n");
 
        // 调整 asmhex 的大小
        asmhex.resize(asmhex.size() + size);  // 调整 asmhex 的大小
        memcpy_s(asmhex.data() + asmhex.size() - size, size, encode, size);  // 复制数据到 asmhex
        *OutSize = size;
    }
    else {
        printf("No machine code generated for '%s'\n", assembly);
    }
 
    // Clean up resources
    ks_free(encode);
    ks_close(ks);
 
    return status;
}
 
QByteArray QQSG::assembleCode(const QByteArray& asmcode) {
    int all_size = 0;
    bool hasErrors = false;
 
    QString text = QString::fromUtf8(asmcode);
    printf("Original assembly code: %s\n", text.toLocal8Bit().constData());
    QStringList lines = text.split('\n');
 
    for (QString& asmstr : lines) {
        asmstr = asmstr.trimmed();
        printf("Processing assembly code: %s\n", asmstr.toLocal8Bit().constData());
        if (asmstr.isEmpty())
            continue;
 
        size_t hex_size = 0;
 
        // 调用 AsmToHex 并获取结果
        int status = this->AsmToHex(KS_ARCH_X86, KS_MODE_32, asmstr.toLocal8Bit().data(), 0, m_hexstr, &hex_size);
        printf("Assembly conversion result: %s\n", asmstr.toLocal8Bit().constData());
        if (status != 0) {
            printf("Assembly conversion failed: %s\n", asmstr.toLocal8Bit().constData());
            m_hexstr.append(" <= instruction format error!");
            hasErrors = true;
        }
        else {
            all_size += hex_size;
        }
    }
 
    // If errors occurred, return an empty QByteArray
    if (hasErrors) {
        printf("Errors occurred, returning an empty QByteArray\n");
        return QByteArray();
    }
 
    // Add a ret instruction at the end
 /*   asmhex.push_back(0xC3);*/
    all_size++;
 
    // 转换为 QByteArray 并返回
    QByteArray machineCode = QByteArray::fromRawData(reinterpret_cast<const char*>(asmhex.data()), asmhex.size());
 
    // 打印最终的机器码用于调试
    printf("Final machine code: %s\n", machineCode.toHex().constData());
    asmhex.clear();
    return machineCode;
}
void QQSG::on_pushButtonCodeInject_clicked()
{
    if (ui.lineEditCodeHwnd->text().isEmpty()) {
        QMessageBox::warning(this, tr("Warning"), tr("请输入目标窗口句柄!"));
        return;
    }
    // 尝试将文本转换为DWORD类型
    QString asmcode = ui.textEditShellCode->toPlainText();
    if (asmcode.isEmpty()) {
        QMessageBox::warning(this, tr("Warning"), tr("请输入汇编代码!"));
        return;
    }
    QString CodeHwndStr = "CodeHwnd:" + ui.lineEditCodeHwnd->text();
    for (int i = 0; i < m_clinetList.size(); ++i)
    {
        QTcpSocket* socket = m_clinetList.at(i);
        if (socket->state() == QTcpSocket::ConnectedState) {
            socket->write(CodeHwndStr.toUtf8());
        }
    }
}
void QQSG::recevieReadyRead()
{
    for (int i = 0; i < m_clinetList.size(); i++)
    {
        QTcpSocket* socket = m_clinetList.at(i);
        QByteArray data = socket->readAll()if (data.contains("StartShellcodeRemoteThread"))
        {
            QString asmcode = ui.textEditShellCode->toPlainText();
            QByteArray asmcodeBytes = asmcode.toUtf8();
            QByteArray machineCode = QQSG::assembleCode(asmcodeBytes);
 
            DWORD processId = 0;
            QString text = ui.tableWidget->item(0, UITYPE::WINWND)->text();
            bool ok;
            int m_hWnd = text.toInt(&ok);
 
            GetWindowThreadProcessId((HWND)m_hWnd, &processId);
            HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
           
            
            if (hProcess == NULL) {
                qDebug() << "Failed to open process:" << GetLastError();
                return;
            }
 
            PVOID pLibRemote = VirtualAllocEx(hProcess, NULL, machineCode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (pLibRemote == NULL) {
                qDebug() << "Failed to allocate memory in remote process:" << GetLastError();
                CloseHandle(hProcess);
                return;
            }
 
            SIZE_T bytesWritten;
            BOOL result = WriteProcessMemory(hProcess, pLibRemote, machineCode.data(), machineCode.size(), &bytesWritten);
            if (!result || bytesWritten != machineCode.size()) {
                qDebug() << "Failed to write memory to remote process:" << GetLastError();
                VirtualFreeEx(hProcess, pLibRemote, 0, MEM_RELEASE);
                CloseHandle(hProcess);
                return;
            }
           
            HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLibRemote, NULL, 0, NULL);
            if (hThread == NULL) {
                qDebug() << "Failed to create remote thread:" << GetLastError();
                VirtualFreeEx(hProcess, pLibRemote, 0, MEM_RELEASE);
                CloseHandle(hProcess);
                return;
            }
            QMessageBox::warning(this, tr("Warning"), tr("请输入汇编代码!"));
            DWORD result = WaitForSingleObject(hThread, INFINITE);
            if (result != WAIT_OBJECT_0) {
                qDebug() << "Failed to wait for remote thread:" << GetLastError();
                VirtualFreeEx(hProcess, pLibRemote, 0, MEM_RELEASE);
                CloseHandle(hThread);
                CloseHandle(hProcess);
                return;
            }
 
            VirtualFreeEx(hProcess, pLibRemote, 0, MEM_RELEASE);
            CloseHandle(hThread);
            CloseHandle(hProcess);
             return; 
        }   
    }
}

问题来了 在学习过程中,假如我想调用这个call 实现远线程,我写了 汇编语言:

//esi的值 是选中对象的相关参数 我们假设他是 0x12345678,

mov esi,0x12345678
mov ecx,0x138FB90
mov     ecx,[ecx]
push    esi
call   0xA26FB0
mov     ecx, eax
call    0x53D1D0

注入之后的结果如下:

Original assembly code: mov esi,0x12345678
mov ecx,0x138FB90
mov     ecx,[ecx]
push    esi
call   0xA26FB0
mov     ecx, eax
call    0x53D1D0
Processing assembly code: mov ecx,0x138FB90
Generated machine code: B9 90 FB 38 01
Assembly conversion result: mov ecx,0x138FB90
Processing assembly code: mov ecx,[ecx]
Generated machine code: 8B 09
Assembly conversion result: mov ecx,[ecx]
Processing assembly code: push esi
Generated machine code: 56
Assembly conversion result: push esi
Processing assembly code: call 0xA26FB0
Generated machine code: E8 AB 6F A2 00
Assembly conversion result: call 0xA26FB0
Processing assembly code: mov ecx,eax
Generated machine code: 89 C1
Assembly conversion result: mov ecx,eax
Processing assembly code: call 0x53D1D0
Generated machine code: E8 CB D1 53 00
Assembly conversion result: call 0x53D1D0
Processing assembly code: ret
Generated machine code: C3
Assembly conversion result: ret
Processing assembly code:
Final machine code: b990fb38018b0956e8ab6fa20089c1e8cbd15300c3
Received machineCode code: B9 90 FB 38 01 8B 09 56 E8 AB 6F A2 00 89 C1 E8 CB D1 53 00 
Received machineCode: B9 90 FB 38 01 8B 09 56 E8 AB 6F A2 00 89 C1 E8 CB D1 53 00 
 
// 原代码中的机器码(由于语言规范及传入数据,开头的机器码不同我可以理解,call后为什么不相同呢)
8B 0D 90 FB 38 01 56 E8 B9 C1 4A 00 8B C8 E8 D2 23 FC FF
此时:线程注入没有反应;
问题:
1.为什么 call 0xA26FB0 与 call 0x53D1D0翻译后的机器码 与 源代码中(文章开头)中的机器码不同呢
2.解释这种现象的原因,是因为call 后的 是偏移量?
3.为什么 注入后没有反应;
4. 综合上述问题 ,我需要如何修改 才能实现远线程注入
5.为什么我学习别人的文章,代码里也没有相关的处理 却可以调用成功;
6.为什么内联汇编却可以呢 ,比如下面:当然 内联汇编 需要修改一下,不能直接传值

DWORD 功能相关地址 =0x138FB90DWORD 选中目标 = 0x12345678;
DWORD call_1 =0xA26FB0;
DWORD call_2 =0xA26FB0;
_asm
{
mov esi,选中目标
mov ecx,功能相关地址
mov     ecx,[ecx]
push    esi
call   call_1 
mov     ecx, eax
call    call_2
}

解决方案

  如下是上述问题的解决方案,仅供参考:

  在你的问题中,你涉及到了远程线程注入和汇编代码的转换,特别是关于如何将汇编语言代码注入到远程进程中并使其执行。你遇到的主要问题是关于机器码转换的准确性以及在远程线程注入后代码没有执行的原因。让我们逐一解答这些问题。

问题分析与解答

  1. 为什么 call 0xA26FB0call 0x53D1D0 翻译后的机器码与源代码中的机器码不同?

    汇编中的 call 指令需要使用相对于当前指令的偏移量,而不是绝对地址。因此,翻译成机器码时,call 指令后的地址是一个相对地址。

    • 在你的代码中,call 0xA26FB0call 0x53D1D0 在实际生成机器码时,需要计算这些地址相对于 call 指令本身的偏移量。
    • 原始机器码中的 call 指令实际上包含的是偏移量,不是绝对地址。比如,E8 AB 6F A2 00 表示 call 指令的偏移量是 0x00A26FAB(相对于 call 指令的地址)。

    在你的机器码生成中,call 后的地址可能是基于某个假设的位置计算的偏移量,而不是实际的绝对地址。确保你的汇编器或代码生成工具计算了正确的相对地址偏移量。

  2. 解释这种现象的原因,是因为 call 后的地址是偏移量?

    是的,call 指令使用的是相对偏移量,而不是绝对地址。call 指令后面跟的是相对于下一条指令的偏移量(即 call 指令的地址加上偏移量等于目标地址)。

    如果你将绝对地址直接放到 call 指令中,生成的机器码可能不会正确地跳转到目标地址,因为它们需要使用相对地址计算。

  3. 为什么注入后没有反应?

    可能有以下原因:

    • 偏移量计算错误:如前所述,call 指令需要相对地址。请确保你计算了正确的偏移量,并将其应用于机器码生成中。
    • 权限问题:检查注入的代码是否具有足够的权限执行,确保目标进程允许代码注入和执行。
    • 内存保护:确保分配的内存具有正确的保护属性(如 PAGE_EXECUTE_READWRITE)。
  4. 如何修改才能实现远程线程注入?

    你需要确保以下几点:

    • 计算相对地址:在生成机器码时,计算 call 指令的相对偏移量。你可以在汇编阶段计算 call 指令的偏移量,然后再将其转化为机器码。
    • 确保内存权限:分配的内存区域需要有正确的权限设置,确保可以执行写入的机器码。
    • 验证注入:确保远程线程的创建和代码注入过程无误。可以通过调试工具检查注入的机器码是否正确执行。
  5. 为什么我学习别人的文章,代码里也没有相关的处理却可以调用成功?

    可能是因为这些文章使用了不同的技术栈或工具,这些工具自动处理了相对地址的计算。例如,有些框架或库可能在注入代码前已经计算并调整了相对地址。你可以参考这些工具或库的文档,了解它们如何处理地址计算。

  6. 为什么内联汇编却可以?

    内联汇编通常会由编译器处理,并且编译器会自动管理相对地址和跳转目标的计算。编译器在生成目标代码时会将 call 指令的相对地址计算得很准确,因此你不需要手动处理这些偏移量。

总结

要解决你面临的问题,你需要:

  • 确保在汇编到机器码的过程中计算正确的相对地址。
  • 检查内存分配和权限设置是否正确。
  • 使用调试工具验证注入后的机器码是否按预期执行。

在生成机器码时,特别是涉及 call 指令时,确保理解相对地址和绝对地址的区别,以及如何正确计算和插入相对偏移量。

  希望如上措施及解决方案能够帮到有需要的你。

  PS:如若遇到采纳如下方案还是未解决的同学,希望不要抱怨&&急躁,毕竟影响因素众多,我写出来也是希望能够尽最大努力帮助到同类似问题的小伙伴,即把你未解决或者产生新Bug黏贴在评论区,我们大家一起来努力,一起帮你看看,可以不咯。

  若有对当前Bug有与如下提供的方法不一致,有个不情之请,希望你能把你的新思路或新方法分享到评论区,一起学习,目的就是帮助更多所需要的同学,正所谓「赠人玫瑰,手留余香」。

☀️写在最后

  如上问题有的来自我自身项目开发,有的收集网站,有的来自读者…如有侵权,立马删除。再者,针对此专栏中部分问题及其问题的解答思路或步骤等,存在少部分搜集于全网社区及人工智能问答等渠道,若最后实在是没能帮助到你,还望见谅!并非所有的解答都能解决每个人的问题,在此希望屏幕前的你能够给予宝贵的理解,而不是立刻指责或者抱怨!如果你有更优解,那建议你出教程写方案,一同学习!共同进步。

  ok,以上就是我这期的Bug修复内容啦,如果还想查找更多解决方案,你可以看看我专门收集Bug及提供解决方案的专栏《CSDN问答解惑-专业版》,都是实战中碰到的Bug,希望对你有所帮助。到此,咱们下期拜拜。

码字不易,如果这篇文章对你有所帮助,帮忙给 bug菌 来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。

同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。


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

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

相关文章

ProtoBuf介绍及安装

文章目录 序列反序列化ProtoBuf特点安装ProtoBufwindowsUbuntuCentos 序列反序列化 在网络传输过程当中&#xff0c;可以理解为&#xff1a; 发送方接收方 它们彼此要通信&#xff0c;先要定好一个规则&#xff0c;也就是协议&#xff0c;双方都能认识的结构化数据&#xff…

Linux C——网络编程

本案例运行环境&#xff1a;Ubuntu 12.04.1 LTS 1、基本概念 网络的七层模型&#xff1a; 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 其中&#xff1a;1、2、3层主要面向通过网络端到端的数据流&#xff0c; 4、5、6、7层定义了程序的功能 …

静态链接和动态链接的Golang二进制文件

关注TechLead&#xff0c;复旦博士&#xff0c;分享云服务领域全维度开发技术。拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;复旦机器人智能实验室成员&#xff0c;国家级大学生赛事评审专家&#xff0c;发表多篇SCI核心期刊学术论文&#xff0c;阿里云认…

李沐 模型选择、过拟合和欠拟合相关代码【动手学深度学习v2】

多项式回归 生成数据集 给定x,我们将使用以下三阶多项式来生成训练和测试数据的标签: y=5+1.2x−3.4+5.6+ϵ where ϵ∼( ). 噪声项ϵ服从均值为0且标准差为0.1的正态分布。 在优化

GraphRAG与VectorRAG我都选:HybridRAG

从金融应用中产生的非结构化文本数据&#xff08;如财报电话会议记录&#xff09;提取和解释复杂信息&#xff0c;即使采用当前最佳实践使用检索增强生成&#xff08;RAG&#xff09;技术&#xff0c;对于大型语言模型&#xff08;LLMs&#xff09;来说仍存在重大挑战。这些挑战…

【游戏党必看】2024年最适合玩游戏的电脑系统推荐!

许多玩家都在问如果在电脑上玩游戏装什么系统好呢&#xff1f;以下系统之家小编给大家推荐两款专门为游戏玩家打造的操作系统&#xff0c;针对大型游戏进行了深度优化&#xff0c;显著提升了系统性能&#xff0c;确保游戏运行更为流畅无阻&#xff0c;能完美兼容各种类型的游戏…

三好夫人|最强“逼”婚神器,送完一次就领证

三好夫人&#xff5c;揭秘最强“逼”婚神器&#xff0c;让你的爱情甜蜜升级&#xff0c;速领见家长通行证&#xff01; 男人们请记住&#xff0c;如果一个女生给你送三好夫人&#xff0c;那么你赶快带她见家长把婚事定了。 在这个快节奏的时代&#xff0c;爱情似乎也被按下了快…

基于51单片机的电机控制和角度检测

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;采用滑动变阻器连接ADC0832数模转换器模拟角度传感器&#xff0c;然后通过LCD1602显示数值&#xff0c;然后按键按下不动&#xff0c;电机正转&#xff0c;松开停止。第二…

显示和隐藏图片【JavaScript】

使用 JavaScript 来实现显示和隐藏图片。下面是一个简单的示例&#xff0c;展示如何通过按钮点击来切换图片的可见性。 实现效果: 代码&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name&…

神奇的交互!Ethernet IP转Profinet网关与发那科机器人的数据交互

在当今的工业领域&#xff0c;随着自动化程度的不断提高&#xff0c;工业化升级已成为必然趋势。在这个过程中&#xff0c;对机器人的联网需求变得日益迫切。机器人作为工业生产中的重要组成部分&#xff0c;其高效运行和与其他设备的协同工作对于提高生产效率至关重要。然而&a…

EI-Bisynch协议

EI-Bisynch&#xff08;Extended Interface-Bisynchronous&#xff09;协议是一种早期用于设备通信的协议&#xff0c;主要用于工业控制系统中的串行通信。随着技术的发展&#xff0c;EI-Bisynch的使用已经大幅减少&#xff0c;逐渐被更现代化、灵活性更高的通信协议&#xff0…

【Linux】手把手教你制作一个简易shell——(进程创建fork进程替换wait与进程等待exec的应用)(自定义shell程序设计)

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

华为昇腾智算中心-智算中心测试方案与标准

本方案是企业内训课程《华为昇腾智算中心深度技术研修》的一部分授课课件的样例。方案内容中详细阐述了华为昇腾环境下智算中心的测试方案和标准&#xff0c;以确保硬件和软件系统在实际部署和运行中的高效性和稳定性。主要内容包括集群硬件清单、节点拓扑配置以及环境配置。硬…

企业微信oauth2的code换用户身份一直40029解决方案

序&#xff1a; 雪狼的微信表情包&#xff0c;欢迎下载【程序员雪狼】微信表情 - 来自微信表情商店&#xff0c;扫二维码下载表情 正文&#xff1a; 雪狼在用oauth2返回的code要去请求getuserinfo3rd接口的时候&#xff0c;报错如下40029 一样&#xff0c;肝了一天&#xff0c…

本地部署高颜值某抑云音乐播放器Splayer并实现无公网IP远程听歌

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

湖北建筑类初级职称申报的全方位解读

湖北建筑类初级职称申报的全方位解读 湖北工程行业助理工程师/初级职称申报评审 湖北建筑类助理工程师/初级职称正常申报目前都是电子版证书&#xff0c;湖北省政务服务网查询生成&#xff0c;省网查询&#xff0c;后期都会同步G网查询。 湖北建筑类助理工程师纸质版 1.之前申…

kubernetes网络(一)之calico详解

摘要 本文介绍Kubernetes最流行的网络解决方案calico。 kubernetes中不同宿主上的pod需要相互通信&#xff0c;如果按TCP/IP协议分层进行分类&#xff1a; 二层方案&#xff1a;flannel的udp和vxlan模式 三层方案&#xff1a;flannel的host-gw模式&#xff1b;calico的IPIP模…

ReduceLROnPlateau学习率衰减设置

学习率衰减有多种方式&#xff0c;本次采用optim.lr_scheduler.ReduceLROnPlateau&#xff0c;这种方式代表在发现loss不再降低或者acc不再提高之后&#xff0c;降低学习率。 model GRU().to(device) criterion nn.CrossEntropyLoss().to(device) optimizer optim.AdamW(m…

YOLOv10独家改进:红外场景严重遮挡和重叠目标解决方案 | 一种新的自适应算法轻量级通道分割和变换(ALSS)模块,自适应特征提取优化策略

💡💡💡本文解决什么问题:红外检测场景存在严重遮挡和重叠目标时的局限性的问题点。 💡💡💡提出了一种新的自适应算法轻量级通道分割和变换(ALSS)模块。该模块采用自适应信道分裂策略优化特征提取,并集成信道变换机制增强信道间的信息交换。这改善了模糊特征的提…

简单多状态dp第一弹 leetcode -面试题17.16.按摩师 -213.打家劫舍II

a​​​​​​​面试题 17.16. 按摩师 按摩师 题目: 分析: 使用动态规划解决 状态表示: dp[i] 表示&#xff1a;选择到 i 位置时&#xff0c;此时的最长预约时长。 但是我们这个题在 i 位置的时候&#xff0c;会面临 选择 或者 不选择 两种抉择&#xff0c;所依赖的状态需要…