当前位置:网站首页>Reading notes at night -- deep into virtual function
Reading notes at night -- deep into virtual function
2022-06-25 01:16:00 【ma_ de_ hao_ mei_ le】
Friend chain
First put the previous MyDriver Class to implement
extern "C" {
#include<ntifs.h>
}
class MyDriver
{
public:
MyDriver(PDRIVER_OBJECT driver);
virtual NTSTATUS OnDispatch(PDEVICE_OBJECT dev, PIRP irp) {
return STATUS_UNSUCCESSFUL;
};
static MyDriver *d_my_driver;
private:
static NTSTATUS sDispatch(PDEVICE_OBJECT dev, PIRP irp);
PDRIVER_OBJECT d_driver;
};
MyDriver::MyDriver(PDRIVER_OBJECT driver) : d_driver(driver)
{
size_t i;
for(i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) {
d_driver->MajorFunction[i] = sDispatch;
}
d_my_driver = this;
};
NTSTATUS MyDriver::sDispatch(PDEVICE_OBJECT dev, PIRP irp) {
return d_my_driver->OnDispatch(dev, irp);
}
MyDriver* MyDriver::d_my_driver = NULL;
void* __cdecl operator new(unsigned int size) {
void* pt = ExAllocatePool(NonPagedPool, size);
if(NULL != pt)
memset(pt, 0, size);
return pt;
}
class MySubDriver : public MyDriver
{
public:
MySubDriver(PDRIVER_OBJECT driver) : MyDriver(driver) {};
virtual NTSTATUS OnDispatch(PDEVICE_OBJECT dev, PIRP irp) {
DbgPrint("this is the dispatch function of MySubDriver\r\n");
return STATUS_UNSUCCESSFUL;
}
};
extern "C" NTSTATUS DriverEntry(
PDRIVER_OBJECT driver, PUNICODE_STRING reg
) {
MyDriver::d_my_driver = new MySubDriver(driver);
return STATUS_UNSUCCESSFUL;
}
build Then throw it to ida in
.text:00010486 ; int __stdcall MyDriver::sDispatch(_DEVICE_OBJECT *dev, _IRP *irp)
.text:00010486 [email protected]@@[email protected]@[email protected]@@Z proc near
.text:00010486 ; DATA XREF: MyDriver::MyDriver(_DRIVER_OBJECT *)+19o
.text:00010486
.text:00010486 dev = dword ptr 8
.text:00010486 irp = dword ptr 0Ch
.text:00010486
.text:00010486 mov edi, edi
.text:00010488 push ebp
.text:00010489 mov ebp, esp
.text:0001048B mov ecx, [email protected]@@[email protected] ; MyDriver * MyDriver::d_my_driver
.text:00010491 mov eax, [ecx]
.text:00010493 pop ebp
.text:00010494 jmp dword ptr [eax]
.text:00010494 [email protected]@@[email protected]@[email protected]@@Z endp
This is MyDriver Class sDispatch function , In our C++ In the code , Inside the function , Called OnDispatch function
NTSTATUS MyDriver::sDispatch(PDEVICE_OBJECT dev, PIRP irp) {
return d_my_driver->OnDispatch(dev, irp);
}
But in the assembly code above , I didn't see it call Instructions , only one jmp Jump instruction
According to the assembly code , You can see that the final program jumps to eax The address stored in the memory pointed to . and eax The value of comes from [ecx],ecx The value of comes from d_my_driver, That is to say this The pointer , According to us The introduction of the last article ,ecx Points to the virtual function table , that [ecx] This is the real content of the virtual function table , We can give c++ In the document mydriver Class and add a virtual function in sdispatch Call to see how many bytes a virtual function occupies in the table
Add a virtual function and call it :
extern "C" {
#include<ntifs.h>
}
class MyDriver
{
public:
MyDriver(PDRIVER_OBJECT driver);
virtual NTSTATUS OnDispatch(PDEVICE_OBJECT dev, PIRP irp) {
return STATUS_UNSUCCESSFUL;
};
virtual NTSTATUS test_virtual_fucn(PDEVICE_OBJECT dev, PIRP irp) {
return STATUS_UNSUCCESSFUL;
};
static MyDriver *d_my_driver;
private:
static NTSTATUS sDispatch(PDEVICE_OBJECT dev, PIRP irp);
PDRIVER_OBJECT d_driver;
};
MyDriver::MyDriver(PDRIVER_OBJECT driver) : d_driver(driver)
{
size_t i;
for(i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) {
d_driver->MajorFunction[i] = sDispatch;
}
d_my_driver = this;
};
NTSTATUS MyDriver::sDispatch(PDEVICE_OBJECT dev, PIRP irp) {
return d_my_driver->OnDispatch(dev, irp) + d_my_driver->test_virtual_fucn(dev, irp);
}
MyDriver* MyDriver::d_my_driver = NULL;
void* __cdecl operator new(unsigned int size) {
void* pt = ExAllocatePool(NonPagedPool, size);
if(NULL != pt)
memset(pt, 0, size);
return pt;
}
class MySubDriver : public MyDriver
{
public:
MySubDriver(PDRIVER_OBJECT driver) : MyDriver(driver) {
};
virtual NTSTATUS OnDispatch(PDEVICE_OBJECT dev, PIRP irp) {
DbgPrint("this is the dispatch function of MySubDriver\r\n");
return STATUS_UNSUCCESSFUL;
}
};
extern "C" NTSTATUS DriverEntry(
PDRIVER_OBJECT driver, PUNICODE_STRING reg
) {
MyDriver::d_my_driver = new MySubDriver(driver);
return STATUS_UNSUCCESSFUL;
}
sObDispatch Assembly code for
.text:00010486 ; int __stdcall MyDriver::sDispatch(_DEVICE_OBJECT *dev, _IRP *irp)
.text:00010486 [email protected]@@[email protected]@[email protected]@@Z proc near
.text:00010486 ; DATA XREF: MyDriver::MyDriver(_DRIVER_OBJECT *)+19o
.text:00010486
.text:00010486 dev = dword ptr 8
.text:00010486 irp = dword ptr 0Ch
.text:00010486
.text:00010486 mov edi, edi
.text:00010488 push ebp
.text:00010489 mov ebp, esp
.text:0001048B mov ecx, [email protected]@@[email protected] ; MyDriver * MyDriver::d_my_driver
.text:00010491 mov eax, [ecx]
.text:00010493 push esi
.text:00010494 push [ebp+irp]
.text:00010497 push [ebp+dev]
.text:0001049A call dword ptr [eax+4]
.text:0001049D push [ebp+irp]
.text:000104A0 mov ecx, [email protected]@@[email protected] ; MyDriver * MyDriver::d_my_driver
.text:000104A6 push [ebp+dev]
.text:000104A9 mov esi, eax
.text:000104AB mov eax, [ecx]
.text:000104AD call dword ptr [eax]
.text:000104AF add eax, esi
.text:000104B1 pop esi
.text:000104B2 pop ebp
.text:000104B3 retn 8
.text:000104B3 [email protected]@@[email protected]@[email protected]@@Z endp
You can see that there are two calls ,
···
.text:0001049A call dword ptr [eax+4]
.text:000104AD call dword ptr [eax]
···
therefore , We can determine the occupation of a virtual function table 4 Bytes , In fact, this can be inferred without testing , about x86 Applications for , The address is 32bit Of , A virtual function is just an address ( Function address ), That is to say 4bytes
Derived class mysubdriver Virtual function table and base class mydriver There must be some relation in the virtual function table of , Can be called mydriver The virtual function of can call mysubdriver Corresponding implementation function of
Take a look at mysubdriver How to initialize the virtual function table by the constructor of
mysubdriver Constructor for :
.text:00010534 ; void __thiscall MySubDriver::MySubDriver(MySubDriver *this, _DRIVER_OBJECT *driver)
.text:00010534 [email protected]@[email protected][email protected]@@Z proc near
.text:00010534 ; CODE XREF: DriverEntry(x,x)+16p
.text:00010534
.text:00010534 driver = dword ptr 8
.text:00010534
.text:00010534 this = ecx
.text:00010534 mov edi, edi
.text:00010536 push ebp
.text:00010537 mov ebp, esp
.text:00010539 push esi
.text:0001053A push [ebp+driver] ; driver
.text:0001053D mov esi, this
.text:0001053F call [email protected]@[email protected][email protected]@@Z ; MyDriver::MyDriver(_DRIVER_OBJECT *)
.text:00010544 mov dword ptr [esi], offset [email protected]@[email protected] ; const MySubDriver::`vftable'
.text:0001054A mov eax, esi
.text:0001054C pop esi
.text:0001054D pop ebp
.text:0001054E retn 4
.text:0001054E [email protected]@[email protected][email protected]@@Z endp
You can see mydriver The virtual function table of is actually mysubdriver The virtual function table of is replaced , Calling mydriver Before the constructor ecx Nothing has changed , Then incoming mydriver Constructor's this Pointers and mysubdriver Of this The pointer is the same , stay mydriver After the constructor call is completed ,this Will point to the virtual function table , But the next instruction
.text:00010544 mov dword ptr [esi], offset [email protected]@[email protected] ; const MySubDriver::`vftable'
bring this(esi stay mydriver The constructor is saved before calling this Value ) The content pointed to has changed , Turned into mysubdriver Virtual function table of

边栏推荐
- 启动服务11111
- Heavyweight: the domestic ide was released, developed by Alibaba, and is completely open source! (high performance + high customization)
- 图书馆管理系统代码源码(php+css+js+mysql) 完整的代码源码
- How about compass stock trading software? Is it safe?
- Go language operators (under Lesson 8)
- php easywechat 和 小程序 实现 长久订阅消息推送
- 4年工作经验,多线程间的5种通信方式都说不出来,你敢信?
- VB 学习笔记
- Introduction to smart contract security audit delegatecall (2)
- 中金财富证券开户佣金多少呢?股票开户交易安全靠谱吗?
猜你喜欢

Text editor for QT project practice - Episode 10

15.线程同步的几种方法

Text editor of QT project practice ---------- episode 11

4年工作經驗,多線程間的5種通信方式都說不出來,你敢信?

重磅:国产IDE发布,由阿里研发,完全开源!(高性能+高定制性)

图书馆管理系统代码源码(php+css+js+mysql) 完整的代码源码

Cobalt Strike安装教程

JVM指令

2022 crane driver (limited to bridge crane) examination question bank simulated examination platform operation

Programmer: did you spend all your savings to buy a house in Shenzhen? Or return to Changsha to live a "surplus" life?
随机推荐
Basic knowledge of assembly language (2) -debug
生态护航 云服务商挥起“英特尔大旗”
Preliminary understanding of qtoolbutton
MySQL common basic statements (collation)
This national day! Tencent cloud wecity will accompany you to travel and light up the city landmark
Bi-sql index
bindservice方法实现音乐播放暂停
用手机在同花顺上开户靠谱吗?这样炒股有没有什么安全隐患
Bi SQL constraints
If the order has not been paid for 30 minutes, it will be automatically cancelled. How can I achieve this?
戴尔为何一直拒绝将商用本的超薄推向极致?
Library management system code source code (php+css+js+mysql) complete code source code
Default methods for Scala sample classes
丹麦技术大学首创将量子计算应用于能源系统潮流建模
Simulation questions and answers of the latest national fire facility operator (senior fire facility operator) in 2022
汇编语言(2)基础知识-debug
QT (36) -rapidjson parsing nested JSON
丹麥技術大學首創將量子計算應用於能源系統潮流建模
梦想CAD云图与GIS结合演示
Cloud development technology summit · public welfare programming challenge [hot registration]!