Do All In One EXE File Under Win32

PE(dll、exe)文件内存加载(手动映射)小记 前言 PE文件即Windos操作系统下的可执行文件的文件结构名称,其中包含但不限于.dll .exe .sys .ocx等等。内存加载PE顾名思义就是通过内存,而非文件。这里的内存指代的是直接加载源。 这个技术其实很早之前就有了,网上也有很多开源可参考的代码,但是仅做一个伸手党那是绝对不行的,首先这些历史悠久的代码存在或多或少的bug,或莫名的崩溃咯,或32和64不兼容咯,各种问题皆是。当然,这些前辈先贤的代码一定是具有非常大的参考和开拓意义的。 技术用途 ... 阅读详情

文章提交: icelord (icelord_at_sohu.com)

希望题目没有语法错误。
    Exe可执行,可以使用系统提供的各种服务,do all in one exe看起来是句废话。仅作技术研究,各位不要为几个文字争论。
很早就看过高手写过的文章,<<脚本的故事>>、<<do all in smd shell>>,今天我也来班门弄斧一把。做后门、木马,现在的技术不知道是什么样的,但是个人认为将他们做到内核之中,将更有威力。当然,这也是把双刃剑。见过一些rootkit,通常做法是写驱动,然后将驱动包含在exe中,运行时释放驱动为一个独立文件,然后加载驱动,由驱动完成Rootkit的各种功能,这样就会生成两个文件。为什么不把它们在一个exe文件中实现呢?今天我们就试验一下,能不能在exe中实现驱动的功能。
其实这个想法来自一个程序。当时想试验一下arp攻击,还以为win32下有相关的系统调用,google了一把,不,baidu了一把,google看不懂,说win32下发包IpPacket到可以,Arp只能用IpHlpApi提供的SendARP()函数发送(可能孤陋寡闻),而且不能手动构造arp包,而且SP2下发送TCP SYN是不允许的。晕。借助工具的话就要使用WinPcap,或者自己写驱动。我当时想是否能像Fport那样,直接操作AFD(好像是TDI,还是/device/tcp udp?),会不会能成功。看了看网上流传的源码,好复杂。WinPcap导出的调用很简单,而且linux下可以平滑过渡。不过,我的初始想法是一个比较隐蔽的程序,这就要求它有很高的独立性。所以,很自然的落到了exe驱动上来。
第一个想法:在exe中导出DriverEntry,看了看sys文件,好像没有这个导出函数,那么程序入口就是DriverEntry,但是win32下exe的ImageBase是4MB,驱动好像是0x10000,不知道win32在加载时会不会对程序作重定位。将EXE的入口修改为DriverEntry…,然后在入口函数中作判断,是用户态还是ring0。好像VC的编译器会在入口加入xxx代码,这样很麻烦,而且相当麻烦。以上证明这个想法暂时不对。不过突然有个想法,程序里面包含main 和DriverEntry,入口为main,运行后修改入口为DriverEntry,然后加载驱动…,弊端很多…
第二个想法,在exe中执行ring0代码。这是老想法了,网上有无驱执行ring0的源码,我当初也装模作样的分析了一下。具体的实现方法是使用/Device/PhysicalMemory对象映射物理内存并修改(GDT,IDT,或者hook内核函数),对此有篇文章有精彩的解说(baidu关键字’/dev/kmem ring0’)。个人觉得hook内核函数比较简单快速,进入ring0后不需要作任何环境修改。如果使用中断门或者调用门,构造就很麻烦,而且好像在哪见过门的段地址要自己重新构造…。没试验过,仅是猜测。
具体思路:
(1)    使用ZwQuerySystemInformation获取ntoskrnl.exe的基址
(2)    用户态加载ntoskrnl.exe,获取内核api相对于它所在模块基址的偏移,加上内核镜像的基址获得真正的api的地址,计算需要使用的Kernel API的地址。
(3)    将api地址减去0x80000000(NT使用flat内存映射,前512Mb物理内存直接映射到2GB,不知道打开/3GB开关是什么情况,暂不考虑),获得api的物理内存地址
(4)    映射物理内存并写入hook代码
(5)    调用Kernel API对应的NaiveAPI,进入ring0
(6)    系统调用在当前进程的内存空间执行,所以可以使用整个进程空间,直接调用(2)计算的KernelAPI完成任务(注意Irql)
看到这里,问题似乎解决了。但是,以上方法只能执行ring0代码并不能实现驱动所实现的功能,功能还非常弱,对于一个简单的MemoryDump/ProcessList还可以,其它很多都受限制。由于代码运行于进程用户内存空间,使用内核栈,如果在别的进程空间调用将KeBugCheck之类的…。很自然,我们会想到把代码拷贝到内核空间去运行。这的确是解决方法。
第一种方案:由于KernelAPI大部分由ntoskrnl.exe和HAL.DLL导出,我们可以计算这些导出函数的地址,调用ExAllocatePool()分配空间(设pKeApiSet),拷贝。然后使用同样的方法来拷贝函数代码到内核,然后将pKeApiSet作为拷贝函数的参数,调用,这样代码就运行在内核空间了,但是还是只能在当前线程的时间片下运行。如果向其它驱动注册回调函数就麻烦了,因为这些函数都有固定的格式,而且调用时无法取得我们自己的参数。使用过下面的方法解决了这个问题:
//===========================================
//修改堆栈,对于_fastcall没试过 !!!!!
#define X_RELOC_CODE "/xFF/x34/x24"/
    "/xC7/x44/x24/x04/x00/x00/x00/x00"

//若想对齐,此代码后面可以加入 nop nop
//若想跳转,此处加入push addr;   ret即可,好像不能直接jmp abs_addr??(VC)
//vc编译使用相对地址
//    __asm push dword ptr [esp]
//    __asm mov dword [esp+4],lpParam

#define X_RELOC_HEADER_SIZE     11
#define X_RELOC_CODE_SIZE        11

//辅助结构,便于抽象理解,汗
typedef struct
{
    char b1[7];
    void *lpParam;
}X_RELOC_HEADER;

//=================================================

X_RELOC_HEADER *pCode=( X_RELOC_HEADER *)__KeApiSet.ExAllocatePool(NonPagedPool,UPALIGN(size+ X_RELOC_CODE_SIZE,4096));

Memcpy((char *)pCode, X_RELOC_CODE, X_RELOC_CODE_SIZE);
pCode->lpParam=(void *)&__KeApiSet;
//x_size>=MyCallback函数的大小
memcpy((void *)((ULONG)pCode+11),(void *)MyCallback,x_size);

//这里将pCode注册到其它驱动或者对象的回调函数去,对于新的回调函数添加一个参数(指向__KeApiSet)在最左边。
例如,原来的回调函数为
    OriginalCallback(Type1 Param1,Type2 Param2….)
新的回调函数如下
    MyCallback(void *lpParam, Type1 Param1,Type2 Param2…)
其实就是在调用函数时修改函数堆栈
----------------------------------------------------------------------------------------
NewCallback    |EIP    |         OriginalCallback |EIP    |                    |MyParam    |            |Param1    |                |Param1    |            |Param2    |                |Param2    |
                堆栈状态
----------------------------------------------------------------------------------------
CodeAddr&#61664;                NewCodeLayout&#61664;
|push ebp     |                |push dword ptr [esp]|
|mov ebp,esp    |                |movdword [esp+4],xParam    |
|sub esp,xxxx    |                |push ebp            |
|    ….    |                     |mov ebp,esp        |
                      代码状态
---------------------------------------------------------------------------------------

还有一种方法是使用EIP定位。Linux下的动态库有一种浮动代码的技术,其中就用到了使用EIP定位,原理如下
Call Nextaddr___        //&#61663;&#61664;push eip(=Nextaddr___)  +   jmp addr
Nextaddr___:        //
    Pop ebx        //ebx=EIP
在刚进入函数时获取EIP值,将参数拷贝到代码前面,eip减去一个数值就可以找到参数。不过这样好象有点麻烦。

    后来想起来VC编译器支持一种naked函数,用这个函数__declspec(naked)写就可以了,白白花费了这么长时间。

    应用:使用第一种方法(代码拷贝到内核空间,修改堆栈),在进入ring0后,可以注册一个回调函数到IPFilterDriver,实现一个简单的Ip过滤,美其名曰:“放火墙”。IoGetDevicePointer&#61664;IoBuildDeviceIoControlRequest&#61664;IofCallDriver。细节可以看网上的高手写的xxxWndows下防火墙。

    第三种方法,好像有篇文章说可以使用ZwSetSystemInformation(SysLoadAndCallImage),可以直接加载并运行,而且有种rootkit就使用了这种方法。具体没有看过,可以到网上看看。

    本来到这里基本算结束了,但是上面的方法只能实现简单的功能,而且代码有点复杂,对于第二种方法,特别是函数调用,必须使用额外参数来定位。这样还不如单独写一个sys文件快。这时我考虑到了代码重定位,于是baidu一下,找到了局部变量大哥写的《NT环境下进程的隐藏》,如获珍宝,自己按着方法把代码重写了一遍,学到不少。其实PE教程说的很明白,就是看不下去…。
    对EXE进行重定位方法我就不多说了。具体方法就是在内核空间中分配代内存,拷贝自身镜像到内核,然后对内核空间的镜像作重定位。由于进入ring0后,在win2k下还可以调用用户态API(printf()还可以使用,在当前进程空间),在xp下调用会导致进程退出,估计对调用前后状态或者地址作了限制。
    有了重定位,就可在函数中使用全局变量,这样对函数的限制大大减小。但还有个问题,就是对kernel API的调用还是使用的显式调用,非常麻烦,对每个函数都要GetProcAddress(),于是我将ntoskrnl.lib和hal.lib加入到程序中,原本以为这样就可以了,可是编译通过,程序根本运行不起来,运行便出错。不知道是机器上的VC有问题,还是…,估计是加载EXE时,回加载它所使用的所有库,估计在加载ntoskrnl.exe时出错了。我手动修改PE的导入表,去掉ntoskrnl.exe模块,程序便能正常运行。
卡到了这里,决定使用先编译,再用工具修改导入表,去掉ntoskrnl.exe的引用。方法就是将ntoskrnl.exe的描述符放到导入表的最后一项,然后将ntoskrnl.exe的IMAGE_IMPORT_DESCRIPTOR拷贝到程序的其他地方(就像病毒那样,将代码写入到PE的间隙处,VC默认对齐大小是4096,这样会有很多空隙),然后将这项置零。这样加载时就不会加载ntoskrnl.exe。说起来容易,实际根本不可行,也没试,因为我查到了VC编译器的延时加载功能(/DelayLoad:dll_name)。
    通常在调用dll导出函数时,编译器为所调用的函数生成导入地址表,将函数所在模块生成IMAGE_IMPORT_DESCRIPTOR,win32在加载程序时会自动加载指定的模块,并确定导入函数的实际地址。DelayLoad将所调用的导出函数生成一个stub,类似如下:
Pid=PsGetCurentProcessId();
Call 40E68E    //这里使用了Debug模式/增量编译,所以会有个跳转
        //release/static/GZ估计为call dword ptr[xxxxxxxx]
-------------------------------------------------------------------------------
0040E682    Push ecx
         Push edx
         Push 00429364        //压入IAT地址
         Jmp 40E66E
-------------------------------------------------------------------------------
0040E68E    jmp dword ptr [00429364]//&#61664;0040E682
-------------------------------------------------------------------------------
0040E66E     Push 00429000    //压入PCImgDelayDescr地址,类似导入表
         Call 00401087    //__delayLoadHelper(pImgDelayDesc,ppfnIATEntry)
         Pop edx        //__ delayLoadHelper计算API真正地址,填入IAT
         Pop ecx
         Jmp eax        //eax=Real Address==[IAT]
-------------------------------------------------------------------------------
由于PCImgDelayDescr被放置在单独的延时输入描述符目录中,而不是通常的输入表目录,所以win32在加载时,这些延时加载的模块不会被加载。第一次调用函数时IAT间接指向__delayLoadHelper函数,而__delayLoadHelper根据函数所在模块名和函数名计算函数地址,然后写会IAT,下次执行直接跳转到真正的函数地址上去。
    DelayLoad的这种特性正好解决了当前的问题。方法就是连接ntoskrnl.lib和hal.lib,然后将ntoskrnl.exe和hal.dll延时加载,自己重写__delayLoadHelper函数来取得KernelAPi的地址,这样问题迎刃而解了。VC6自己的__delayLoadHelper函数在文件DELAYHLP.CPP中实现,其中加入了对函数Hook的功能,就是导出两个函数指针,在__delayLoadHelper中先调用指针指向的函数,若为空怎使用默认的LoadLibrary()和GetProcAddress()。这样如果想hook函数只需要将模块延时加载然后自己实现__pfnDliNotifyHook即可。
    问题:
(1)    由于在内核之中,(同一进程空间)不能调用win32API (XP下不行,2K下可以,注意:非GUI API),如果还可能在其它进程空间使用,则根本不能使用UserAPI
(2)    经过重定位的镜像在获取API名称时有问题,镜像基址大于0x80000000,地址的最高位肯定为1,这在PE中与函数的INT冲突,信息会丢失。
解决方法:
(1)    其实使用的API就是LoadLibrary() 和GetProcAddress,重写LoadLibrary和GetProcAddress函数即可。对于LoadLibrary(),只需要调用ZwQuerySystemInformation获得模块的基址即可;对于GetProcAddress,根据模块镜像的基址找到IMAGE_NT_HEADERS->IMAGE_EXPORT_DIRECTORY逐个查找即可,注意函数使用序号(ordinal)的查找。
(2)    WIN32 PE文件的导入表和延时加载描述符表都有各自的INT和IAT(暂时这样理解),对于函数地址的确定都使用类似的机制。从INT获得函数名称或者函数ordinal,然后从模块里查找函数地址,填入IAT,只是确定函数地址时间有不同。对于函数名称,,PE使用IMAGE_THUNK_DATA来描述,它其实是一个DWORD指针,指向一个DWORD数组,对于数组中的每个DWORD,如果最高位为1(&IMAGE_ORDINAL_FLAG32),则此函数按序号引入,否则此DWORD指向一个IMAGE_IMPORT_BY_NAME结构,此结构包含函数名称字符串的RVA。普通Win32进程运行在0-2GB中,所以这没问题。但我们的镜像被拷贝到0xFExx xxxx ,重定位后IMAGE_THUNK_DATA的地址肯定>0x80000000,所以只能根据经验,全部按名称引入,理由是NT、95的函数序号并不一致(从书上看的,很简单,xp导出的函数比2K多,如果按序号肯定出问题)。就在这个地方,没有调试器,只有printf,浪费了两天的时间,晕。还以为是VC自带的代码决不会有问题,重写__delayLoadHelper后解决(__delayLoadHelper对函数Ordinal & IMAGE_ORDINAL_FLAG做了判断…)。

呵呵,终于到主题了,其实前面的要困难些。
当代运行在ring0时,它已经能实现多数功能了,但是如果要作个木马,后门之类的,还要解决与用户态通信的问题(其实并不是这样),所以想到了事件之类的,或者ring0 call ring0,apc…最后还是落到了文件设备上。通过文件设备,任何进程都可以与ring0通信,而且创建驱动的宿主可以安全撤退。如果使用ring0 代码(call gate,hook),则进程不能退出,因为线程的系统调用没有返回,所以即使强行中止也无济于事。如果通过ring0代码创建一个驱动,然后ring0返回到ring3,进程就可以安全退出。而这时的代码还驻留在内核的未分页区,以回调的方式响应请求。
    学过操作系统都知道,VFS的特性,就是所有设备都是用文件来表示,其实质就是分层的函数调用,使用注册机制来处理各种设备之间的差异。实际实现表现为一个文件对象对应一个设备对象,同时设备对象又对应一个驱动对象,不同的i/o请求通过文件对象分发到不同的设备,进而转发到设备对应的驱动对象,由驱动完成最终请求。这种分层的设计有何多优点,特别适合扩展和抽象,下面深略3000字。
    要创建驱动,无非就是创建一个驱动对象,创建一个设备对象,注册函数到设备对象,然后创建设备链接以使win32可以访问到设备。看win2K 源码(/private/ntos/io/internal.c),驱动加载的基本过程为

&#61664;一堆注册表操作
&#61664;取得驱动文件名
&#61664;MmLoadSystemImage()加载驱动到内存
&#61664;ObCreateObject()创建驱动对象
&#61664;对驱动对象的各成员初始化
&#61664;ObInsertObject()
&#61664;ObReferenceObjectByHandle()    //取得对象指针
&#61664;NtClose()            //关闭ObInsertObject()创建的句柄
&#61664;驱动名称操作..
&#61664;status = driverObject->DriverInit( driverObject, &registryPath->Name );
                                    //调用驱动入口DriverEntry进行驱动初始化
&#61664;检查驱动对象的合法性(MajorFunction函数,驱动是否创建设备…)
&#61664;IopBootLog()
&#61664;MmFreeDriverInitialization()
&#61664;IopReadyDeviceObjects()            //VIP!!!!!

有了上面的过程,基本可以自己手动创建驱动并加载了,看了看搜索结果,发现ntoskrnl.exe导出了IoCreatDriver这个函数,其中实现了IopLoadDriver的大部分功能,事情变得简单起来。
NTKERNELAPI
NTSTATUS
IoCreateDriver (
    IN PUNICODE_STRING DriverName,   OPTIONAL
    IN PDRIVER_INITIALIZE InitializationFunction
    );
    具体方法就是:用exe中的DriverEntry做为参数,调用IoCreateDriver,即可实现驱动的加载。
    当在win2K下运行程序后,用WinObj居然打开失败。晕,再次看IoLoadDeiver,才发现漏掉了一个重要地方,创建驱动时,驱动对象的标志Flags和所创建设备的标志都有限制,使用IopReadyDeviceObjects()来添加驱动DRVO_INITIALIZED标志和,去掉驱动创建的所有设备的DO_DEVICE_INITIALIZING标志。IopReadyDeviceObjects()函数没有被ntoskrnl.exe导出?简单,自己写就行了。曾找不到问题原因时,还重写过IopfCompleteRquest和IopCompleteRequest,那才叫痛苦呢。
    Finally,搞定。为了方便,写了一个库,下次使用时就简单多了

#include “DrvHlpApi.h”
NTSTATUS Driverentry(void *pDriverObject,void *pRegPath)
{
//    ….IoCreateDevice()..
    Return STATUS_SUCCESS;
}

Int main(int argc.char **argv)
{
    x_InitRing0Utils();    
    x_StartDriver((ULONG)DriverEntry,0,0);
    return 0;
}
使用这个方法,完全可以实现驱动的所有功能,同时将它与win32程序结合在一起。在XP SP2和win2k SP4下测试通过(就试过IpFilter那个)。就这么简单。有兴趣的朋友可以mail来取得代码,头文件和库可以在 http://icelord.bokee.com下载到。

参考文章:
1.《NT环境下进程的隐藏》
2.Win2K Source Code
3.PE文件格式详解
4.Ring0Demo.c v1.0 by zzzEVAzzz
5.《开发Windows 2K/XP 下的防火墙》 
Win11安全设置阻止加载驱动的解决方案 当Win11系统提示“安全设置将阻止加载驱动程序”时,你可以尝试关闭内存完整性和Windows Defender防火墙来解决这一问题。关闭内存完整性可以通过Windows安全中心或修改注册表来实现;而关闭Windows Defender防火墙则可以通过控制面板进行设置。请注意,在采取这些措施之前要充分了解可能带来的安全风险,并谨慎操作。希望本文能帮助你解决这一问题,让你的设备恢复正常运行。 阅读详情

相关推荐

如何在.NET里面调用win32 API

下面是示例在C#里面调用win32api中的 CreateFile 和 CloseHandle 这两个函数。using System;using System.IO;using System.Runtime.InteropServices;namespace copytest{ ///  /// FileAccess 的摘要说明。 ///  public class OpenFileApi

西井学习笔记 2899

[Windows驱动开发](四)内存管理

一、内存管理概念 1. 物理内存概念(Physical Memory Address)     PC上有三条总线,分别是数据总线、地址总线和控制总线。32位CPU的寻址能力为4GB(2的32次方)个字节。用户最多可以使用4GB的真实物理内存。PC中很多设备都提供了自己的设备内存。这部分内存会映射到PC的物理内存上,也就是读写这段物理地址,其实读写的是设备内存地址,而不是物理内存地址。

baggiowangyu的专栏 1万+

【webrtc】ImportError: No module named win32file

win32file

突围 1041

Do all in one exe file Under Win32

Do all in one exe file Under Win32icelord @ 2006    希望题目没有语法错误。    Exe可执行,可以使用系统提供的各种服务,do all in one exe看起来是句废话。很早就看过高手写过的文章,>、>,今天我也来班门弄斧一把。做后门、木马,现在的技术不知道是什么样的,但是个人认为将他们做到内核之中,将更有威力。当然,这也是把双刃剑。

天之流 6246

Electron常见问题 19 - 源码编译报错ImportError: No module named win32file

目录 问题 原因 解决 问题 下载Electron源码,编译过程中,遇到如下报错信息: G:\project\electron-gn\src>ninja -C out/Debug electron ninja: Entering directory `out/Debug' [1/1] Regenerating ninja files [368/17419] COPY ../../electron/node_modules/octicons/buil...s/default_app..

liuzhen007的专栏 1597

MmLoadDriver内存加载驱动.7z

64位环境下已签名驱动中实现加载未签名驱动,程序是源代码,可修改编译

DESKTOPBRIDGE UWP+WIN32混合打包出现THE FILE NAME “WIN32APP.EXE“ DECLARED FOR ELEMENT “*[LOCAL-NAME()=’APPL

DesktopBridge UWP+Win32混合打包出现The file name “win32app.exe” declared for element “*[local-name()=’Applications’]/*[local-name()=’Application’]/*[local-name()=’Extensions’]/*[local-name()=’Extension’ and @Category=’windows.fullTrustProcess’]” doesn’t exist in

282

无刷电机控制避坑指南:六步换向 vs FOC的5个关键差异

本文深入对比了无刷电机控制中六步换向与FOC(磁场定向控制)的五大核心差异。从控制逻辑、性能表现、效率能耗、硬件成本到应用场景,详细解析了FOC如何通过矢量合成实现平滑的正弦波控制与更高效率,而六步换向则以低成本实现简单开关驱动。旨在帮助工程师根据项目需求,在性能、成本与复杂度间做出最佳选择。

weixin_29216957的博客 506

EXE注入分析之傀儡进程

最近学习PE结构,顺便看到了一篇WIN32 EXE注入的文章,代码是04年的,比较古老了, 但是代码写的很好,受益匪浅,然后在百度很少找到翻译的比较清楚的文章,这篇我在代码中加了中文注释, 方便菜鸟理解,阅读这篇帖子需要熟悉PE结构,如果你不懂PE结构建议你先去学习下, 说错的地方请各位大神指正,板砖吐口水都可以。 --- 我是淫荡的分割线--- 提到傀儡进程,首先想到的

酷酷的鱼 - 网络编程,服务器安全专栏 3700

别再用Excel硬算传热了!用MATLAB/Octave复现国赛数学建模A题(附完整代码与避坑指南)

本文详细介绍了如何利用MATLAB/Octave高效解决数学建模中的传热问题,替代传统的Excel计算方法。通过复现2018年国赛A题的高温作业服传热模型,从理论推导到代码实现,提供了完整的有限差分法解决方案和参数拟合技巧,帮助读者提升数学建模效率和准确性。

weixin_30512965的博客 379

YOLOv8验证的命令以及计算coco指标

好久不看代码,都不知道怎么验证的了,来记录一下。1、计算coco指标。

毕竟是Shy哥 1481

Win32API调用

win32api简介

weixin_65589140的博客 1125

麒麟V10服务器多硬盘安装与分区实战:告别自动分区,手动分配/boot、swap和/根目录

本文详细介绍了麒麟V10服务器在多硬盘环境下的手动分区策略,包括/boot、swap和/根目录的优化分配方案。通过SSD与HDD混合存储架构的合理规划,提升系统性能和运维效率,适用于企业级定制化系统部署需求。

weixin_26976635的博客 406

Win32串行通信中文版(Serial Communications In Win32)

可到http://download.youkuaiyun.com/detail/zcube/5079651下载排版好的PDF版本。    原文链接:http://msdn.microsoft.com/en-us/library/ms810467.aspx           艾伦戴夫          微软Windows开发者支持中心           1995/12/11          应用

zcube的技术博客 1万+

从模态到颤振:深入解读Nastran的V-g/V-f图,判断你的机翼设计是否安全

本文深入解析Nastran中的V-g/V-f图在机翼颤振分析中的应用,帮助工程师准确判断设计安全性。通过模态分析到颤振边界的完整判读逻辑,结合气动弹性特性,指导优化机翼结构设计,确保飞行安全。

weixin_28732953的博客 470

(学习笔记)机器人自主导航从零开始第四步———Rviz、Gazebo、Meshlab的安装

一、Rviz的安装 Rviz是一个

qq_59475883的博客 5057

An In-Depth Look into the Win32 Portable Executable File Format, Part 2

https://msdn.microsoft.com/en-us/magazine/bb985994.aspxFrom the March 2002 issue of MSDN MagazineInside WindowsAn In-Depth Look into the Win32 Portable Executable File Format, Part 2Matt PietrekThis a...

738

【LangChain编程:从入门到实践】实现多模态代理

【LangChain编程:从入门到实践】实现多模态代理 关键词:LangChain, 多模态代理, 自然语言处理, 机器学习, 知识图谱, 对话系统, 代码生成, AI代理 1. 背景介绍 随着人工智

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 579

An In-Depth Look into the Win32 Portable Executable File Format

Matt Pietrek This article assumes youre familiar with C++ and Win32 L

zinocpp的专栏 1835

【OpenClaw从入门到精通】第41篇:2026年4月最新版——从零开始搭建你的第一个安全AI助理(保姆级实战教程)

2026年3月CNCERT联合发布《OpenClaw安全使用实践指南》后,安全部署成为OpenClaw使用的核心前提。本文针对新手及进阶用户,基于官方安全指引,提供三套实战部署方案:阿里云一键部署(新手首选)、Docker容器隔离部署(进阶推荐)、本地安全安装(测试专用),并详解阿里云百炼Coding Plan API接入流程。全文涵盖环境准备、分步实操、安全加固、问题排查等全流程,所有命令可直接复制执行,无需依赖外部代码库。通过本文,读者可零基础搭建安全隔离的OpenClaw AI助理,兼顾实用性与安全性

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2197

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

c++ win32调用exe,并等待其结束

调用exe 有诸如 ShellExecute(Ex) , System 之类的函数,本文以ShellExecuteEx为例子,调用exe,并等待其结束。         char ActiveCmd[200] ={0};        sprintf(ActiveCmd, "%s %s", argv[1]  , argv[2] );        printf( "%s\n", ActiveCm...

weixin_33682790的博客 951

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

win32动态库

(1)首先创建win32控制台应用程序 (2)在【应用程序设置】->【应用程序类型】选择“DLL(D)” (3)在建立的工程中添加lib.h及lib.cpp文件,源代码如下: #ifndef LIB_H   #define LIB_H   extern "C" int __declspec(dllexport)add(int x, int y);

softwarestudying的专栏 610

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: Linux Kernel do_mremap VMA本地权限提升漏洞
下一篇: 看nt下无驱执行ring0代码
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值