20180425

day1

Win32 SDK运行流程及框架

  Win32 SDK编程即使用Win32 SDK来编写窗体应用程序,这种方式不使用任何框架,仅用操作系统提供的API来编写程序,虽然流程繁琐,编写复杂,但有助于理解Windows应用程序实 质的执行情况。

  Win32程序的入口点为WinMain函数,与控制台程序的main类似,它们都是由链接器来决定的。WinMain函数有4个参数,分别是hInstance,hPrevInstance,szCmdLine,iCmdShow。hInstance表示当前程序的实例句柄,它的实质为映像文件的基地址;hPrevInstance如今只起兼容作用,一般为NULL;szCmdLine是命令行指针,在启动函数调用WinMain函数前会使用GetCommandLine获取完整命令行,忽略文件名后将剩余部分传递给该参数,iCmdShow则是窗口显示的方式,比如最大化和最小化显示,用在ShowWindow函数中。

  程序运行的流程:1.注册窗口类  2.创建窗口  3.显示窗口  4.消息循环  5.消息处理

要创建一个窗口,我们首先得注册一个窗口类,WNDCLASS定义如下:

 1 typedef struct tagWNDCLASSA {
 2     UINT        style;
 3     WNDPROC     lpfnWndProc;
 4     int         cbClsExtra;
 5     int         cbWndExtra;
 6     HINSTANCE   hInstance;
 7     HICON       hIcon;
 8     HCURSOR     hCursor;
 9     HBRUSH      hbrBackground;
10     LPCSTR      lpszMenuName;
11     LPCSTR      lpszClassName;
12 } WNDCLASSA;

创建一个窗口类实例并进行初始化后,就可调用RegisterClass函数注册该窗口类。然后就可以调用CreateWindow函数来创建一个窗口,但这时仅仅表示某块内存保存了窗口的所有信息数据,并不会显示在屏幕上,CreateWindow返回一个窗口句柄,有了窗口句柄我们便能通过API来对该窗口进行一系列操作,于是我们就可调用ShowWindow函数使该窗口显示在屏幕上。

Win32程序是基于消息机制的,消息作为驱动来使程序运行。所以MSG这个消息结构是一个十分重要的结构,定义如下:

1 typedef struct{
2     HWND    hWnd;  //窗口句柄
3     UINT    message;//消息内容
4     WPARAM    wParam;
5     LPARAM    lParam;
6     DWORD    time;//产生时间
7     POINT    pt;//位置
8 } MSG;

操作系统维护了一个消息队列,当产生了消息后,便会将新产生的消息加入队列中,调用GetMessage函数可以获得队头消息,然后通过DispatchMessage函数将该消息传给操作系统,然后作为参数传给CALLBACK消息处理函数处理。所以消息循环通常由以下代码构成:

1 while (GetMessage(&msg, NULL, 0, 0))
2 {
3     TranslateMessage(&msg);
4     DispatchMessage(&msg);
5 }

通常把这种消息称为队列消息,然而还存在非队列消息,这些非队列消息一般是由函数调用引起的,如CreateWindow时会传递WM_CREATE消息,UpdateWindow会传递WM_PAINT消息等。

MFC框架执行流程

 MFC是微软提供的一个C++框架。当建立一个单文档工程时,vc便会自动为我们创建5个类,分别是CAboutDlg,CMainFrame,C$ProjectName$App,C$ProjectName$Doc,C$ProjectName$View。CMainFrame是框架窗口,即窗口的最外层,

执行流程:我们难以在MFC程序中找到WinMain函数,但程序实际运行时,依然会调用WinMain函数。首先创建了全局的C$ProjectName$App对象,C$ProjectName$App是CWinApp的子类,继承了其构造函数,调用其父类构造函数后,才进入WinMain函数,WinMain函数调用了AfxWinMain函数,在AfxWinMain函数中,获取了C$ProjectName$App全局对象的指针,然后调用其InitInstance方法,接着调用了run方法。在InitInstance中完成了窗口类的注册,窗口的显示和更新。在run方法中完成了消息循环。

TLS,PEB,TEB结构

 TLS是线程局部存储,TLS是各线程的独立的数据存储空间,使用TLS技术可在线程内部独立使用或修改进程的全局数据或静态数据,在PE文件中有单独的数据目录表指向该结构,定义如下:

 1 typedef struct _IMAGE_TLS_DIRECTORY32 {
 2     DWORD   StartAddressOfRawData;
 3     DWORD   EndAddressOfRawData;
 4     DWORD   AddressOfIndex;             // PDWORD
 5     DWORD   AddressOfCallBacks;         // PIMAGE_TLS_CALLBACK *
 6     DWORD   SizeOfZeroFill;
 7     union {
 8         DWORD Characteristics;
 9         struct {
10             DWORD Reserved0 : 20;
11             DWORD Alignment : 4;
12             DWORD Reserved1 : 8;
13         } DUMMYSTRUCTNAME;
14     } DUMMYUNIONNAME;
15 } IMAGE_TLS_DIRECTORY32;

其中AddressCallBacks是回调函数起始地址,TLS回调函数常用于反调试。在调用main函数前都会先依次调用所有回调函数,结束时会再调用一次。

回调函数的声明方式void NTAPI TLS_CALLBACK(PVOID DllHandle, DWORD Reason, PVOID Reserved);

第一个参数是模块句柄(实质为加载地址),第二个参数是调用原因

有如下4中调用原因:  #define DLL_PROCESS_ATTACH   1

          #define DLL_THREAD_ATTACH      2

          #define DLL_THREAD_DETACH     3

          #define DLL_PROCESS_ATTACH   0

1表示主线程调用main函数前的回调函数

2表示子线程开始的回调函数

3表示子线程结束的回调函数

0表示主线程结束的回调函数

可通过如下代码向文件中添加TLS回调函数:

1 #pragma data_seg(".CRT$XLX")
2     //存储回调函数地址
3     PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK1/*func_name*/, TLS_CALLBACK2/*func_name*/, 0 };
4 #pragma data_seg()

PEB为进程控制块,是由操作系统为每个进程维护的一个数据结构。定义如下:

 1 typedef struct _PEB {
 2   BYTE                          Reserved1[2];
 3   BYTE                          BeingDebugged; //被调试状态
 4   BYTE                          Reserved2[1];
 5   PVOID                         Reserved3[2];
 6   PPEB_LDR_DATA                 Ldr;
 7   PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
 8   BYTE                          Reserved4[104];
 9   PVOID                         Reserved5[52];
10   PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
11   BYTE                          Reserved6[128];
12   PVOID                         Reserved7[1];
13   ULONG                         SessionId;
14 } PEB

有许多保留字段,我们忽略它。剩下的分别是BeingDebugged,Ldr,ProcessParameters,PostProcessInitRoutine和SessionId四个字段。

BeingDebugged标志表示程序的调试状态,IsDebuggerPresent()函数便是检查这个标志来返回一个布尔值的,常常用于反调试。

Ldr字段是指向关于进程加载模块的双向链表头的指针。

ProcessParameters指向了进程的参数信息结构,其中包含命令行参数等。

PostProcessInitRoutine不支持。

SessionId表示当前终端服务对话标识符。

TEB为线程环境块,我们通常通过该环境块来获得当前进程环境块。

Windows在创建线程前,会为该线程分配TEB,通常FS段寄存器指向该结构。TEB偏移0x00处是TIB(线程信息块),线程信息块偏移0x18处存在反身指针指向该TEB本身。

TEB偏移0x30处为PEB指针,由此可通过FS寄存器获取PEB。

明日:基本sql注入方式,floor报错注入,information_schema.tables。Win32 WM_PAINT消息和GDI简介

原文地址:https://www.cnblogs.com/amlkhlwd33/p/8935255.html