Starting a process from KernelMode

把 ABAP 采购订单增强做成一条可控流水线:BAdI ME_PROCESS_PO_CUST 全流程实战 摘要: SAP MM模块的ME_PROCESS_PO_CUST BAdI提供了采购订单全生命周期的增强点,覆盖从ME2*N事务到BAPI调用的各类场景。该接口通过INITIALIZE、OPEN、PROCESS_*系列方法、CHECK等组成完整处理流水线,支持字段控制、业务校验、数据派生等功能。关键注意事项包括:PROCESS_*方法仅在相关对象变更时触发、字段控制需区分参考键与动态规则、避免递归调用等。该BAdI采用面向对象设计,通过IF_PURCHASE_ORDER_*等接口操作采购单据对象,而非直接修改 阅读详情

By Stan Alex

How to start a Win32 process from within a driver 

Sample Image - KernelExec.jpg

Introduction

After many unsuccessful attempts trying to find a way to start a working Win32 process from KernelMode, I finally stumbled upon a promising piece of code that was both original and innovative (Note: the ideea belongs to Valerino).

Unfortunately that code didn't seem to work properly on my machine, and it always ended up crashing it, or just a process (in the most fortunate cases). So I've decided to reimplement Mighty Valerino's ideea in my own way (although the structure of the code is basically the same).

So let's get started. First, you must know of...

APC's

APC, standing for Asynchronous Procedure Call, represents a kernel procedure that that is queued to a particular thread for execution. In other words it's a code that is forcibly executed in a thread's context (This method is mostly employed by the I/O Manager). That is the SIMPLEST explanation I can give you, and that's all you need to know for now. There are three types of APC's:

Kernel APC's - They can be queued to any kernel thread and they will execute only if the specified thread isn't already executing a Kernel APC.

Special Kernel APC's - Basically the same as above. They run at IRQL APC_LEVEL and cannot be blocked except by running at a raised IRQL. They can always preempt normal Kernel APC's.

User APC's - These are APC's that can be queued to UserMode threads, but there's a catch: the thread must have previously called a wait service like WaitForSingleObject with the Alertable field set to TRUE. The APC will be invoked next time the thread returns from KernelMode. This is the kind of APCs that we will be dealing with from now on.

Enough talking. Let's get to the fun part :)

Running that process

A brief description of the ideea behind starting a Win32 process is the following:

1. We loop through the list of running processes until we find Explorer.exe. Why explorer.exe? Because it's desktop-interactive service (I tried popping up a message box from WinLogon.exe and I could only hear the sound of it). It also has many waiting threads (both alertable and non-alertable), so it works best with this code.

2. Once we've found Explorer.exe we iterate through it's threads searching for an alertable thread. If no such thread is found, we simply save a pointer to a non-alertable one and set its ApcState.UserApcPending to TRUE, thus making it alertable (notice: in this case it usually takes a few seconds for the thread to return to KernelMode)

3. Now we have the PEPROCESS of Explorer.exe and one of its PETHREADs. Next we queue our APC object (which will contain the code to be executed in UserMode) and when it completes, we just release the memory that we have previously allocated for it. That's all.

The Implementation

The main procedure is RunProcess(LPSTR lpProcess) where lpProcess must be the FULL PATH to the application that is to be run ('c:/RawWrite.exe' in our example)

 

void RunProcess(LPSTR lpProcess)
{

  PEPROCESS pTargetProcess = NULL;//self explanatory
  PKTHREAD pTargetThread = NULL;  //thread that can be either
                                  //alertable or not
  PKTHREAD pNotAlertableThread = NULL;//non-alertable thread
  PEPROCESS pSystemProcess = NULL; //May not necessarily be the
                                   //'System' process

  PETHREAD pTempThread = NULL;
  PLIST_ENTRY  pNextEntry, pListHead, pThNextEntry; 

//...
}

We start off by retrieving a pointer to the 'System' process:

  pSystemProcess = PsGetCurrentProcess(); 
  //make sure you are running at IRQL PASSIVE_LEVEL
pSystemProcess->ActiveProcessLinks is a LIST_ENTRY field that contains links(pointers) to other processes ( PEPROCESS) running on the machine. Let's search for Explorer.exe and save a pointer to it and to one of its threads. (Note: you can queue an APC to ANY process, even CSRSS or SVCHOST, but the system will probably crash). Once we've got a pointer to Explorer.exe and one of its threads (i will not explain how to do that here) it's time to queue our APC to that thread:

 

if(!pTargetThread)
{
  //No alertable thread was found, so let's hope
  //we've at least got a non-alertable one
  pTargetThread = pNotAlertableThread;
}

if(pTargetThread)
{
  DbgPrint("KernelExec -> Targeted thread: 0x%p",
           pTargetThread);
  //We have a thread, now install the APC
  InstallUserModeApc(lpProcess, 
                     pTargetThread,
                     pTargetProcess);
}
InstallUserModeApc has the following prototype:

 

NTSTATUS 
InstallUserModeApc(
                   IN LPSTR lpProcess, 
                   IN PKTHREAD pTargetThread, 
                   IN PEPROCESS pTargetProcess);
where pTargetProcess points to the PEPROCESS of Explorer.exe and pTargetThread is the PKTHREAD which the APC will be queued to. Let's now allocate some memory for that APC and for an MDL (Memory Descriptor List) to map our UserMode code:

 

PRKAPC pApc = NULL;
PMDL pMdl = NULL;
ULONG dwSize = 0; //Size of code to be executed in Explorer's address space

pApc = ExAllocatePool (NonPagedPool,sizeof (KAPC)); 

dwSize = (unsigned char*)ApcCreateProcessEnd-
         (unsigned char*)ApcCreateProcess;
pMdl = IoAllocateMdl (ApcCreateProcess, dwSize, FALSE,FALSE,NULL);

//Probe the pages for Write access and make them memory resident
MmProbeAndLockPages (pMdl,KernelMode,IoWriteAccess);
Our APC is now valid and pMdl is memory resident and maps our UserMode code ( ApcCreateProcess() that is. We'll get to that later). So what now? Should we deliver our APC to the thread and watch our Win32 process run? No no no.. not so fast! :)

How is Explorer.exe's thread supposed to invoke our APC routine if it doesn't have access to the Kernel memory? It cannot do that! Fine then, then let's map our APC code to UserMode memory:

 

KAPC_STATE ApcState;

//Attach to the Explorer's address space
KeStackAttachProcess(&(pTargetProcess->Pcb),&ApcState);

//Now map the physical pages (our code) described by pMdl
pMappedAddress = 
  MmMapLockedPagesSpecifyCache(pMdl,
                               UserMode,
                               MmCached,
                               NULL,FALSE,
                               NormalPagePriority);
To continue, first I must show you how ApcCreateProcess (the code mapped to UserMode memory, into Explorer's address space) works:

 

__declspec(naked)
void ApcCreateProcess(
  PVOID NormalContext,
  PVOID  SystemArgument1,
  PVOID SystemArgument2)
{
  __asm 
  {
    mov eax,0x7C86114D
    push 1
    nop
    push 0xabcd
    call eax
    jmp end       
    nop
    nop
    //...about 400 nop's here
end:
    nop
    ret 0x0c
  }
}

void ApcCreateProcessEnd(){} 
//Used only to calculate the size of the code above
We move the address of WinExec into eax (0x7C86114D is its address, on WinXP SP2), we push 1 on the stack (SW_SHOWNORMAL) and then we push... 0xabcd before calling WinExec. Why 0xabcd you might ask? Well, push 0xabcd is the first parameter of WinExec and it points to the path of the application to be executed. But that means 0xabcd cannot possibly point to the path all the times!

Why don't you simply push lpProcess from RunProcess(LPSTR lpProcess) then? Answer - Because WinExec will NOT be able to access it and it will throw an 'Access Violation' at you! You cannot access Kernel memory from UserMode, remember? Instead, right after we map our code to UserMode memory, we copy the path to the location right after the first nop instruction (that's why there are so many nop's in there) and we modify 0xabcd to point to it. Now here's the code:

 

ULONG *data_addr=0; //just a helper to change the address of the 'push' instruction
                    //in the ApcCreateProcess routine
ULONG dwMappedAddress = 0; //same as above

pMappedAddress = 
         MmMapLockedPagesSpecifyCache(pMdl,
                                      UserMode,
                                      MmCached,
                                      NULL,FALSE,
                                      NormalPagePriority);
dwMappedAddress = (ULONG)pMappedAddress;

//zero everything out except our assembler code
memset ((unsigned char*)pMappedAddress + 0x14, 0, 300);

//copy the path to the executable
memcpy ((unsigned char*)pMappedAddress + 0x14,
        lpProcess,
        strlen (lpProcess));

data_addr = (ULONG*)((char*)pMappedAddress+0x9);//address pushed on the stack
                                                //(originally 0xabcd)...
*data_addr = dwMappedAddress+0x14; //gets changed to point to our exe's path
    
//all done, detach now
KeUnstackDetachProcess (&ApcState);
What's left now is to initialize the APC and queue it to the thread. I will not explain how KeInitializeApc and KeInsertQueueApc works as Tim Deveaux as already done that here.

 

  //Initialize the APC...
  KeInitializeApc(pApc,
                  pTargetThread,
                  OriginalApcEnvironment,
                  &ApcKernelRoutine, //this will fire after 
                                     //the APC has returned
                  NULL,
                  pMappedAddress,
                  UserMode, 
                  NULL);
    
  //...and queue it
  KeInsertQueueApc(pApc,0,NULL,0);

  //is this a non-alertable thread?
  if(!pTargetThread->ApcState.UserApcPending)
  {
    //if yes then alert it
    pTargetThread->ApcState.UserApcPending = TRUE;
  }

  return STATUS_SUCCESS;
}

Compiling the code

This is simple - do a cd sys_path, where sys_path is the path to the driver project, then run build -ceZ. Or just press the F7 key in MS Visual Syudio 6 :)

Now copy KernelExec.sys to your C:/ directory, run Dbgview to see the output of the driver then double-click on Start_KE_Driver.exe to install and start the driver. Et voila! RawWrite.exe's window should be on your screen right now! :-)

P.S.: Make sure you first put an application called RawWrite.exe in your c:/ directory, because that is what the driver attempts to run.

Stan Alex

cesium 深度图(获取区域最高最低点位) 文章摘要: Cesium深度图技术可用于获取区域地形高程数据,核心实现步骤包括:1)通过离屏相机构建独立渲染环境,使用正交投影确保采样精度;2)采用离屏渲染技术获取均匀分布的地形点数据。关键技术点包含多边形外包矩形计算、后台相机配置(5km高度正交投影)、1024×1024像素离屏视图设置,以及深度数据解析(RGBA格式转换和三维坐标还原)。该方法避免了主视图干扰,可精准获取区域内地形高程信息,为填挖方分析等应用提供基础数据支持。 阅读详情

相关推荐

不同比例尺地质数据共享

包含20w、25w、100w、250w比例尺地质数据共享。

sinat_38828898的博客 2329

A problem occurred starting process 'command 'node''

ReactNative的热更新,微软提供了CodePush的解决方案,在Android集成时遇到了如下问题: Error:Execution failed for task ':app:recordFilesBeforeBundleCommandDebug'. > A problem occurred starting process 'command 'node'' node命令...

100斤的博客 6633

动力锂电池-二阶RC模型等效电路-RLS参数辨识-Simulink

1.锂电池二阶RC等效电路模型

QQ1978009424的博客 1万+

Android-Studio 运行报错

1、Execution failed for task ‘:react-native-update:compileDebugNdk’ 路径:android->app->build.gradlew android { sourceSets.main { jni.srcDirs = [] } } 路径:android->gradle.properti...

刘荣丹的日志 615

不只是烧录:深入理解英飞凌Aurix MCU的HSM安全模块与UDE Memtool解锁操作

本文深入探讨了英飞凌Aurix MCU的HSM安全模块设计与UDE Memtool解锁操作,揭示了硬件安全模块的架构、安全启动链机制及调试接口的安全特性。通过分析UDE Memtool的解锁逻辑和量产环境下的最佳实践,帮助工程师更好地应对MCU锁定问题,提升汽车电子和工业控制领域的安全烧录效率。

weixin_32770423的博客 301

从门禁到支付:Uniapp+NFC开发避坑指南(支持Mifare Classic)

本文详细介绍了Uniapp结合NFC技术开发门禁与支付系统的实战指南,特别针对Mifare Classic卡片进行深度优化。内容涵盖环境配置、设备兼容性处理、卡片安全机制解析以及高性能读写优化策略,帮助开发者快速实现跨平台的智能硬件交互解决方案。

t1u2v的博客 751

mac react native android 报错 A problem occurred starting process ‘command ‘node‘‘

一、通过错误信息找到文件的下载地址,复制到浏览器中下载(虽然下载速度依旧乌龟,但总能下载完)

u010537398的博客 429

量子计算入门指南:密度算符的核心概念与应用解析

本文深入解析了量子计算中密度算符的核心概念与应用。作为描述量子系统“状态的状态”的关键数学工具,密度算符能有效处理混合态与子系统描述,是理解量子噪声、量子纠错和开放系统演化的基石。文章通过对比纯态与混合态,阐释了密度矩阵的数学定义与物理意义,并结合代码示例演示了其在实际量子计算问题中的强大威力。

day7的博客 470

React Native遇见的几个坑

1. 环境变量配置解决办法:配置ANDROID_HOME,和JAVA_HOME。安装Android SDK,并安装Build Tool 23.0.1,最好把所有版本装上,因为将来使用的插件可能依赖的版本是不一样的。2. 执行cd android && ./gradlew assembleRelease任务错误* What went wrong:Execution failed for task '

清箫的专栏 1万+

【ACP】2025-最新-疑难题解析- 练习一汇总

他们对您的方案比较满意,作为一个特别看重用户体验的创业公司,他们有一个比较担心的问题:在后端云服务器 ECS 实例相对空闲时,可能会触发减少 ECS 实例的伸缩活动,这时候运行在即将移出伸缩组的 ECS 实例上的应用会被终止,那么发起这些应用的用户的体验会变差。:在使用阿里云的负载均衡 SLB 实例时,做了如下健康检查的配置:响应超时时间为 5 秒,健康检查间隔为 2 秒,不健康阈值为 3,健康阈值为 3,即对于确认一个后端服务器 ECS 实例是健康的,需要连续三次得到正常响应。以下说法哪一项是正确的?

jundao1997的专栏 327

FPGA实现PCIe接口

PCI Express(PCIe)是一种高速串行计算机扩展总线标准,在FPGA中实现PCIe接口可以实现与主机系统的高速数据通信。以下是FPGA实现PCIe接口的关键技术要点。

whm128的博客 1464

Android 开发 Gradle 相关问题

问题汇总

kiku 2136

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Starting a Process from KernelMode

IntroductionAfter many unsuccessful attempts trying to find a way to start a working Win32 process from KernelMode, I finally stumbled upon a promising piece of code that was both original and innov

zskof的专栏 1331

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

启动报错A problem occurred starting process ‘command ‘C:/Program Files/Java/jdk1.8.0_221/bin/java.exe‘‘

A problem occurred starting process ‘command ‘C:/Program Files/Java/jdk1.8.0_221/bin/java.exe’’ 可能原因:java启动命令行太长 Shorten command line :改为JAR manifest或其他可选项,进行调试; Shorten command line者一列可能不存在,需要点击Modify options选择; ...

qq_45389465的博客 9890

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

react native 错误总结(不定时更新)

错误截图: 原因:lineHeight只能设置成整数  可以使用parseInt(23.7)进行取整操作

吴蕴强的博客 2793

Android Studio问题解决:A problem occurred starting process ‘command ‘,CreateProcess error=2, 系统找不到指定的文件。

一、遇到问题 二、解决问题 重新下载了22.0.7026061和22.1.7171670 ndk.dir中修改了路径 clean+Sync Project 哦了,大功告成

5209

从核心模式启动一个进程----怎样从内部的驱动程序启动一个Win32进程

从核心模式启动一个进程----怎样从内部的驱动程序启动一个Win32进程[Romania]Stan Alex著   [China]rxxi 译 文章原址:http://www.codeproject.com/useritems/KernelExec.aspDownload source files - 55 Kb Download demo project - 27 Kb

C/C++ World 5319

Execution failed for task ‘:app:bundleReleaseJsAndAssets‘

window电脑换Mac后,RN项目android端打包的时候出现如上报错!解决方案:打开app下的gradle文件:添加node路径。

weixin_41036707的博客 966

A problem occurred starting process 'command '

androidStudio运行出现:  A problem occurred starting process 'command 'E:\sdk\ndk-bundle\toolchains\mips64el-linux-android-4.9\prebuilt\windows-x86_64\bin\mips64el-linux-android-strip''解决方案: 在local.propert...

json_yi的博客 1万+

A problem occurred starting process 'command 'G:\Android\sdk\ndk-bundle\toolchains\mips64el-linux-an

如下图: 我这边出现这个是因为项目里面加入了模拟器的so库导致的,网上找到了一个简单的解决办法 方法一: 打开 local.properties,将ndk目录的目录加上后缀 .cmd, 例如 ndk.dir=G\:\\Android\\sdk\\ndk-bundle.cmd,  重新build就可以正常编译了 如上图:     方法二: 版本回退,  ndk版本在r17版,...

xiayiye5的博客 3158

grails3 A problem occurred starting process 'command 'C:\Program Files\Java\jdk1.8.0_101\bin\java.ex

A problem occurred starting process 'command 'C:\Program Files\Java\jdk1.8.0_101\bin\java.exe''

lvbaolin123的博客 1万+

React Native 学习中踩过的那些坑

1、react-native run-android时提示aapt权限被拒绝完整LOG如下: java.io.IOException: Cannot run program "/Users/name/AndroidSDKs/build-tools/23.0.2/aapt": error=13, Permission denied 解决办法:打开终端。进入SDK/build-tools/23.0

BaiSoo的博客 2003

ring0启动一个Win32进程 【译文】

ring0启动一个Win32进程 【译文】 文章原址:http://www.codeproject.com/useritems/KernelExec.asp Download source files - 55 Kb  Download demo project - 27 Kb  介绍 在许多不成功的尝试来试图找到一种方式来以核心模式(KernelMode)来启动可运行的Wi

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 705

用APC实现在内核模式运行用户程序

//=====================================================================================////Name: void RunUserModeProcess()                                                              ////        

2399

操作系统开发--什么是内核?

操作系统内核是你永远看不到的。它基本上允许任何其他程序执行。它处理硬件事件(称为中断)、软件事件(称为系统调用)和管理资源的访问。硬件事件处理(中断)会获取到你刚才按下的键,并将按键转化为对应的字符并存在缓冲区中,某些程序就可以在缓冲区里检索到该字符并判断出你按下的是哪个键。软件事件处理(系统调用)是由用户级的程序触发的,像打开文件,启动程序等。每一次的系统调用都需要判断传递的参数是否有效,然后执...

wenwushq的博客 8752
上一篇: Writing to the Internet Explorer Cache
下一篇: Hooking a DirectX/COM Interface
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值