1. EXE 恶意代码分析
2. DLL 恶意代码分析
3. OCX 恶意代码分析
4. SYS 恶意代码分析
5. COM 恶意代码分析
6. windows加载可执行文件流程
程序加载后,CreateProcess系列函数创建进程,在windows上,进程用EPROCESS结构表示,线程用ETHREAD结构表示
进程相关的工作准备就绪后,还需要单独创建一个参与内核调度的执行单元,也就是进程中的第一个线程:主线程。当然,这个工作也封装在了CreateProcess系列函数中了。
新进程的主线程创建完成后,便开始参与系统调度了。内核在创建时就明确进行了指定:nt!KiThreadStartup,这是一个内核函数,线程启动后就从这里开始执行。
线程从这里启动后,再通过Windows的异步过程调用APC机制执行提前插入的APC,进而将执行流程引入应用层,去执行Windows进程应用程序的初始化工作,比如一些核心DLL文件的加载(Kernel32.dll、ntdll.dll)等等。
随后,再次通过APC机制,再转向去执行可执行文件的入口点。
进行C/C++运行时库的初始化,这之后经过运行时函数的包装,才最终来到main函数
Windows上,从创建进程到main函数的完整流程
高清大图(https://bbs.pediy.com/upload/attach/201604/501306_qz5f5hi1n3107kt.png)
7. windows驱动分析
7.1 windows驱动
驱动程序是一个软件组件,可让操作系统和设备彼此通信。
7.1.1 驱动类型
- 设备函数驱动程序
- 设备筛选器驱动程序
- 软件驱动程序
- 文件系统筛选器驱动程序
- 文件系统驱动程序
7.2 驱动内部原理分析
驱动的三个重要概念DriverEntry、IRP Handler和IOCTL。
7.2.1 DriverEntry
驱动程序必须指定入口点DriverEntry。
DriverEntry要负责很多工作,例如创建设备对象、创建用于与驱动程序和核心函数(IRP Handler、卸载函数、回调例程等)进行通信的符号链接。
DriverEntry首先使用到IoCreateDevice()
或IoCreateDeviceSecure()
的调用来创建设备对象,后者通常用于将安全描述符应用于设备对象,以限制对本地管理员和NT AUTHORITYSYSTEM的访问。
接下来,DriveEntry
将IoCreateSymbolicLink()
与先前创建的设备对象一起使用,以建立符号链接,该链接将允许用户模式进程与驱动程序进行通信。
最后,DriverEntry
还定义了IRP Handler的函数。
7.2.2 IRP Handler
中断请求包(IRP)本质上只是驱动程序的一条指令。这些数据包允许驱动程序通过提供函数所需的相关信息来执行特定的主要函数。主要函数的代码较多,但其中最常见的是IRP_MJ_CREATE
、IRP_MJ_CLOSE
和IRP_MJ_DEVICE_CONTROL
。这些与用户模式函数相关:
IRP_MJ_CREATE → CreateFile
IRP_MJ_CLOSE → CloseFile
IRP_MJ_DEVICE_CONTROL → DeviceIoControl
在用户模式下执行以下代码时,驱动程序将收到具有主要函数代码IRP_MJ_CREATE
的IRP,并将执行MyCreateCloseFunction
函数:
hDevice = CreateFile(L”\\.\MyDevice”, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
在几乎所有情况下,对我们来说最重要的主要函数是IRP_MJ_DEVICE_CONTROL
,该函数用于发送请求,以从用户模式执行特定的内部函数。这些请求中包括一个IO控制代码,该代码负责通知驱动程序具体的操作,还包含一个向驱动程序发送数据和从驱动程序接收数据的缓冲区。
7.2.3 IOCTL
IO控制代码(IOCTL)是我们的主要搜寻目标,因为其中包含我们需要知道的很多重要细节。它是以DWORD表示,每一个32位都表示有关请求的详细信息,包括设备类型、需要的访问、函数代码和传输类型。微软提供了一个可视化的图表来分解这些字段:
1、传输类型:定义将数据传递到驱动程序地方式,具体的类型可以是METHOD_BUFFERED、METHOD_IN_DIRECT
、METHOD_OUT_DIRECT
或METHOD_NEITHER
。
2、函数代码:驱动程序要执行的内部函数。这部分应该是以0x800开始,但实际上我们会发现,很多都是从0x0开始的。其中的自定义位(Custom bit)用于定义厂商分配的值。
3、设备类型:在IoCreateDevice(Secure)()
指定的驱动程序设备对象类型。在Wdm.h和Ntddk.h中,定义了许多设备类型,但对于软件驱动程序而言,最常见的一种就是FILE_DEVICE_UNKNOWN (0x22)
。其中的通用位(Common bit)用于定义厂商分配的值。
驱动程序标头定义示例如下:
# MYDRIVER_IOCTL_DOSOMETHING CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
7.2.4 组合
类比于发送网络数据包的过程来对其进行分析。
我们可以使用所需的任何细节来构造数据包,然后将其发送到服务器进行处理,使用该数据包执行某些操作。而对于服务器端,要不然会忽略我们的数据包,要不然会返回一些结果。
总的来说:DriverEntry创建必要资源等,然后用户通过IRP将要办的事情(IOCTL)发送给驱动程序,驱动干完就返回些信息。
1、用户模式应用程序获取符号链接上的句柄。
2、用户模式应用程序使用DeviceIoControl()
将所需的IOCTL和输入/输出缓冲区发送到符号链接。
3、符号链接指向驱动程序的设备对象,并允许驱动程序接收用户模式应用程序的数据包(IRP)。
4、驱动程序看到该数据包来自DeviceIoControl(),因此将其传递给已定义的内部函数MyCtlFunction()
。
5、MyCtlFunction()
将函数代码0x800映射到内部函数SomeFunction()
。
6、SomeFunction()
执行。
7、IRP已经完成,其状态以及驱动程序在用户模式应用程序中提供的输出缓冲区中包含的为用户提供的所有内容都将传回给用户。
注意:在这里我们并不是说IRP已经完成,但需要关注的是,一旦SomeFunction()
执行,上述时间就可以发生,并且将得到函数返回的状态代码,这表明操作的结束。