zoukankan      html  css  js  c++  java
  • 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简介

  • 相关阅读:
    hdu 2014 青年歌手大奖赛_评委会打分
    java 图像灰度化与二值化
    hdu 2010
    如何搞定IE+google双内核的360浏览器表单自动回填兼容问题
    多预览小图焦点轮播插件lrtk
    多功能前台交互效果插件superSlide
    自适应标题延展线写法
    二级菜单延迟隐藏
    各种浏览器的Hack写法(chrome firefox ie等)
    jQuery treetable【表格多重折叠树功能及拖放表格子元素重新排列】
  • 原文地址:https://www.cnblogs.com/amlkhlwd33/p/8935255.html
Copyright © 2011-2022 走看看