驱动调用用户层代码

http://hi.baidu.com/%CE%F7%B7%E7%B9%AB%C9%E7/blog/item/0febbd355d0904bfd1a2d320.html

转贴一篇文章,原来找了好久的..... 驱动调用用户层代码

1、 KeUserModeCallBack

NTSTATUS
CallRing3()
{
PLIST_ENTRY Next;
PPEB Peb;
PLDR_DATA_TABLE_ENTRY Entry;
PVOID dll_addr, func_addr, pMem
= NULL, OutputBuffer, lpTextAddr;
UNICODE_STRING us;
NTSTATUS status;
ULONG OutputLength, dwSize
= PAGE_SIZE, KernelCallbackTable = 0, TableIndex, dwUserCodeSize;
MSGBOX_PARAMS StackParams;

Peb
= GetCurrentProcessPeb();
if (Peb) {
// 鸯妁屙桢 忮玟?钿桧嚓钼? 礤 耱嚯 忭铖栩?桤戾礤龛 br /> // ?铒桉囗桢 PEB 桤 msdn :)
KernelCallbackTable = *(ULONG*)((ULONG)Peb + 0x2C);
RtlInitUnicodeString(
&us, L"user32.dll");

Next
= Peb->Ldr->InMemoryOrderModuleList.Flink;
while (Next != &Peb->Ldr->InMemoryOrderModuleList) {
Entry
= CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, MemoryOrder);

if(!RtlCompareUnicodeString(&Entry->ModuleName, &us, TRUE)) {
dll_addr
= Entry->ModuleBaseAddress;
func_addr
= KernelGetProcAddress(dll_addr, "MessageBoxA");
DbgPrint(
"user32.dll found at %x", dll_addr);
DbgPrint(
"user32.dll->MessageBoxA found at %x", func_addr);

status
= ZwAllocateVirtualMemory((HANDLE)-1, &pMem, 0, &dwSize, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
if (NT_SUCCESS(status)) {
DbgPrint(
"Memory allocated at %x", pMem);
*(ULONG*)pMem = (ULONG)pMem + 4;
TableIndex
= ((ULONG)pMem - KernelCallbackTable) / sizeof(ULONG);
dwUserCodeSize
= (ULONG)Ring3Code_End - (ULONG)Ring3Code;
lpTextAddr
= (PVOID)((ULONG)pMem + 4 + dwUserCodeSize);

DbgPrint(
"KernelCallbackTable == %x", KernelCallbackTable);
DbgPrint(
"OurTableIndex == %x", TableIndex);

__try {

RtlCopyMemory((PVOID)((ULONG)pMem
+ 4), Ring3Code, dwUserCodeSize);
RtlCopyMemory(lpTextAddr, HELLOSTR, strlen(HELLOSTR));

RtlZeroMemory(
&StackParams, sizeof(MSGBOX_PARAMS));
StackParams.MessageBoxA
= func_addr;
StackParams.lpText
= lpTextAddr;

DbgPrint(
"Call user mode...");
status
= KeUserModeCallback( TableIndex,
&StackParams,
sizeof(MSGBOX_PARAMS),
&OutputBuffer,
&OutputLength );
DbgPrint(
"KeUserModeCallback return %x", status);

}
__except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint(
"Exception");
}

ZwFreeVirtualMemory((HANDLE)
-1, &pMem, &dwSize, MEM_DECOMMIT);
}
// if

break;
}
// if

Next
= Next->Flink;
}
// while
} // if Peb

return STATUS_DEVICE_CONFIGURATION_ERROR;
}

 

2、 apc

//=====================================================================================//
//Name: void RunProcess() //
// //
//Descripion: This routine retrieves the list of all processes running on the machine, //
// searches for 'explorer.exe', gets one thread from it's PEPROCESS struct, //
// then it queues an APC to that thread //
//=====================================================================================//
void RunProcess(LPSTR lpProcess)
{
//全部定义为ULONG类型
ULONG pTargetProcess; //self explanatory
ULONG pTargetThread; //thread that can be either alerable or non-alertable
ULONG pNotAlertableThread; //non-alertable thread
ULONG pSystemProcess; //May not necessarily be the 'System' process
ULONG pTempThread;
ULONG pNextEntry, pListHead, pThNextEntry,pThListHead;


if(strlen(lpProcess)>300) return; //name not longer than 300 characters
//获得系统进程
pSystemProcess =(ULONG)PsGetCurrentProcess(); //make sure you are running at IRQL PASSIVE_LEVEL

if(!pSystemProcess)
{
DbgPrint(
"KernelExec -> Cannot find 'System' process!");
return;
}
//获取进程列表头(+0x088 ActiveProcessLinks : _LIST_ENTRY)
pListHead=pSystemProcess+0x88;
//得到下一个EPROCESS结构的ActiveProcessLinks偏移地址
pNextEntry=*(ULONG*)pListHead;
if(!pNextEntry)
DbgPrint(
"KernelExec -> No processes found!");
else
{

while(pNextEntry != pListHead) //start looping through the available processes
{ //得到EPROCESS的首地址
pSystemProcess =pNextEntry-0x88;
//进程名偏移
//+0x174 ImageFileName:[16] UChar
DbgPrint("ProcessName %s \n",(char*)pSystemProcess+0x174);
//Is this explorer.exe?
if(_strnicmp((char*)pSystemProcess+0x174,"explorer.exe",12)==0)
{
//得到进程的EPROCESS结构的地址
pTargetProcess = pSystemProcess; //Yes,we have found it!
DbgPrint("yes,we have found explorer.exe!");

pTargetThread
= pNotAlertableThread = 0;
//获取线程列表头
//+0x050 ThreadListHead : _LIST_ENTRY
//也就是_KPROCESS(PCB)中ThreadListHead的偏移地址
pThListHead = pSystemProcess+0x50;
//得到ETHREAD结构中_KTHREAD(Tcb)的+0x1b0 ThreadListEntry : _LIST_ENTRY地址
pThNextEntry=*(ULONG *)pThListHead;
//Now we loop through it's threads, seeking an alertable thread
while(pThNextEntry != pThListHead)
{
//所属ETHREAD的首地址
pTempThread =pThNextEntry-0x1b0;
DbgPrint(
"ethread address is:0x%x\n",(ULONG *)pTempThread);
//线程ID
//ETHREAD+0x1ec Cid : _CLIENT_ID为进程ID
//再向下+4为线程ID
DbgPrint("thread Id is %d\n",*(ULONG *)(pTempThread+0x1f0));
//是否警告状态
//+0x164 Alertable : UChar
DbgPrint("Alertable is:%x",*(char *)(pTempThread+0x164));
//tcb=*(PKTHREAD)pTempThread;
if(*(char *)(pTempThread+0x164)) //Tcb is the KTHREAD of this ETHREAD and stands for 'Thread Control Block'
{
//Good, an alertable thread was found.
//得到explorer.exe中符合条件的线程PKTHREAD(ETHREAD)结构的地址
pTargetThread =pTempThread;

DbgPrint(
"KernelExec -> Found alertable thread");
//We will be using this one, so break now
break;
}
else
{
//Didn't find an alertable thread yet, so we'll keep this one
//just in case we won't find ANY alertable threads
//至少需要一个非警告状态的线程
pNotAlertableThread =pTempThread;
}
//下一个线程块
pThNextEntry = *(ULONG *)pThNextEntry; //check next thread
}
break;
}
//下一个进程块
pNextEntry = *(ULONG *)pNextEntry; //get next process
}
}

if(!pTargetProcess)
{
DbgPrint(
"KernelExec -> Couldn't find Explorer.exe!");
return;
}
if(!pTargetThread)
{
//No alertable thread was found, so let's hope we've at least got a non-alertable one (we'll set its alertable flag ON)
//There's no problem with non-alertable threads, except for the fact that it takes
//a little longer for them to return from KernelMode. (that means our process execution will be delayed)
pTargetThread = pNotAlertableThread;
}

if(pTargetThread)
{
DbgPrint(
"KernelExec -> Targeted thread: 0x%p",pTargetThread);
//We have one thread (alertable or n/a), now install the APC
InstallUserModeApc(lpProcess,pTargetThread,pTargetProcess);
}
else
DbgPrint(
"KernelExec -> No thread found!"); //Explorer exe with NO threads (???)*/
}

 

3、ExRaiseHardError

01 typedef enum _HARDERROR_RESPONSE_OPTION {
02 OptionAbortRetryIgnore,
03 OptionOk,
04 OptionOkCancel,
05 OptionRetryCancel,
06 OptionYesNo,
07 OptionYesNoCancel,
08 OptionShutdownSystem,
09 OptionExplorerTrayBaloon,
10 OptionCancelTryAgainContinue
11 } HARDERROR_RESPONSE_OPTION, *PHARDERROR_RESPONSE_OPTION;
12
13 typedef enum _HARDERROR_RESPONSE {
14 ResponseReturnToCaller,
15 ResponseNotHandled,
16 ResponseAbort,
17 ResponseCancel,
18 ResponseIgnore,
19 ResponseNo,
20 ResponseOk,
21 ResponseRetry,
22 ResponseYes,
23 ResponseTryAgain,
24 ResponseContinue
25 } HARDERROR_RESPONSE, *PHARDERROR_RESPONSE;
26
27 NTSTATUS
28 NTAPI
29 ExRaiseHardError(
30 IN NTSTATUS ErrorStatus,
31 IN ULONG NumberOfParameters,
32 IN ULONG UnicodeStringParameterMask,
33 IN PVOID Parameters,
34 IN ULONG ResponseOption,
35 OUT PULONG Response );
36
37
38 ULONG
39 DisplayMessage (
40 PWSTR MessageString,
41 ULONG ResponseOption
42 )
43 {
44 NTSTATUS St;
45 UNICODE_STRING Message;
46 PVOID Parameters[] = {
47 &Message, //内容
48 0, //这是传说中的窗体标题...
49 0,
50 0
51 };
52 ULONG Response = 0;
53
54 RtlInitUnicodeString (&Message, MessageString);
55
56 St = ExRaiseHardError (
57 STATUS_FATAL_APP_EXIT,
58 1,
59 1,
60 &Parameters,
61 ResponseOption,
62 &Response
63 );
64
65 return Response;
66 }
67
68
69 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
70 {
71 ULONG r;
72 r = DisplayMessage (L"Do you want a girl?", OptionYesNo);
73 KdPrint(("The answer was %d \n", r));
74
75 return STATUS_UNSUCCESSFUL;
76 }

转载于:https://www.cnblogs.com/daxingxing/archive/2011/08/30/2159720.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的字符设备驱动程序的示例代码,实现了读取和写入设备数据的功能,以及处理ioctl接口: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/cdev.h> #include <linux/ioctl.h> #define DEVICE_NAME "my_device" struct my_device_data { char data[100]; int len; }; struct my_device { struct cdev cdev; struct my_device_data data; }; static int my_device_open(struct inode *inode, struct file *filp) { struct my_device *dev = container_of(inode->i_cdev, struct my_device, cdev); filp->private_data = dev; return 0; } static int my_device_release(struct inode *inode, struct file *filp) { return 0; } static ssize_t my_device_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct my_device *dev = filp->private_data; int len = min_t(int, count, dev->data.len - *f_pos); if (len <= 0) return 0; if (copy_to_user(buf, dev->data.data + *f_pos, len)) return -EFAULT; *f_pos += len; return len; } static ssize_t my_device_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct my_device *dev = filp->private_data; int len = min_t(int, count, sizeof(dev->data.data) - *f_pos); if (len <= 0) return 0; if (copy_from_user(dev->data.data + *f_pos, buf, len)) return -EFAULT; *f_pos += len; dev->data.len = *f_pos; return len; } static long my_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct my_device *dev = filp->private_data; int err = 0; switch (cmd) { case 0: // do something break; case 1: // do something else break; default: err = -EINVAL; break; } return err; } static const struct file_operations my_device_fops = { .owner = THIS_MODULE, .open = my_device_open, .release = my_device_release, .read = my_device_read, .write = my_device_write, .unlocked_ioctl = my_device_ioctl, }; static struct my_device my_device_data; static dev_t devno; static int __init my_device_init(void) { int err; err = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME); if (err < 0) return err; cdev_init(&my_device_data.cdev, &my_device_fops); my_device_data.cdev.owner = THIS_MODULE; err = cdev_add(&my_device_data.cdev, devno, 1); if (err < 0) { unregister_chrdev_region(devno, 1); return err; } return 0; } static void __exit my_device_exit(void) { cdev_del(&my_device_data.cdev); unregister_chrdev_region(devno, 1); } module_init(my_device_init); module_exit(my_device_exit); MODULE_LICENSE("GPL"); ``` 以下是一个简单的动态库的示例代码,用于测试与驱动程序的通信,其中包含了测试读取和写入设备数据的函数,以及测试ioctl接口的函数: ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #define DEVICE_NAME "/dev/my_device" struct my_device_data { char data[100]; int len; }; #define MY_DEVICE_IOCTL_CMD0 _IO('M', 0) #define MY_DEVICE_IOCTL_CMD1 _IO('M', 1) int my_device_read(struct my_device_data *data) { int fd = open(DEVICE_NAME, O_RDONLY); if (fd < 0) return fd; int ret = read(fd, data->data, sizeof(data->data)); if (ret >= 0) data->len = ret; close(fd); return ret; } int my_device_write(struct my_device_data *data) { int fd = open(DEVICE_NAME, O_WRONLY); if (fd < 0) return fd; int ret = write(fd, data->data, data->len); close(fd); return ret; } int my_device_ioctl(int cmd) { int fd = open(DEVICE_NAME, O_RDWR); if (fd < 0) return fd; int ret = ioctl(fd, cmd); close(fd); return ret; } ``` 最后,以下是一个简单的用户程序的示例代码,用于调用动态库中的测试函数,测试驱动程序的功能: ```c #include <stdio.h> #include "my_device.h" int main() { struct my_device_data data = {{0}, 0}; int ret; // test read and write strcpy(data.data, "hello, world!"); data.len = strlen(data.data) + 1; ret = my_device_write(&data); if (ret < 0) { fprintf(stderr, "my_device_write failed: %d\n", ret); return 1; } memset(&data, 0, sizeof(data)); ret = my_device_read(&data); if (ret < 0) { fprintf(stderr, "my_device_read failed: %d\n", ret); return 1; } printf("read data: %s\n", data.data); // test ioctl ret = my_device_ioctl(MY_DEVICE_IOCTL_CMD0); if (ret < 0) { fprintf(stderr, "my_device_ioctl failed: %d\n", ret); return 1; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值