DLL编程笔记

1 DLL基础

一、静态链接库(Static Link Library

程序员们把常用的代码集合放进独立的文件里,这样的文件就叫做库。在写程序的时候,把这个库文件加入编译器,就能够使用这个库包含的所有功能而不必自己再去写一大堆代码。但是这种方法会把库里所有的东西都包含进去,造成程序体积的增大。

 

制作静态链接库 StaticLibTest

StdAfx.h

// stdafx.h : include file for standard system include files,

//  or project specific  include files that are used frequently, but

//      are changed  infrequently

//

 

#if  !defined(AFX_STDAFX_H__796D49AA_9488_4F2F_AEB1_C8F28E516D92__INCLUDED_)

#define  AFX_STDAFX_H__796D49AA_9488_4F2F_AEB1_C8F28E516D92__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

#define WIN32_LEAN_AND_MEAN         //  Exclude rarely-used stuff from Windows headers

 

extern "C" void ShowInfo();

 

// TODO: reference additional headers your program requires here

 

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations  immediately before the previous line.

 

#endif //  !defined(AFX_STDAFX_H__796D49AA_9488_4F2F_AEB1_C8F28E516D92__INCLUDED_)

StdAfx.cpp

// stdafx.cpp : source file that includes just the standard  includes

//     01_001.pch will be  the pre-compiled header

//     stdafx.obj will  contain the pre-compiled type information

 

#include "stdafx.h"

#include<windows.h> //Message()

void ShowInfo()

{

       MessageBox(NULL,"ShowInfo()  test", "MQ", MB_OK);

}

调用静态链接库

ExecuteStaticLib.cpp

// ExecuteStaticLib.cpp : Defines the entry point for the  application.

//

 

#include "stdafx.h"

#pragma comment(lib, " StaticLibTest.lib")

extern "C" void ShowInfo();

 

int APIENTRY WinMain(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                      LPSTR     lpCmdLine,

                      int       nCmdShow)

{

      // TODO: Place code here.

       ShowInfo();

       return 0;

}

 

 

 

二、动态链接库Dynamic Link LibraryDLL

DLL的格式和EXE文件是一样的,但是不能直接执行。它把代码封装到自己的内部,只是提供函数接口让外面的EXE程序调用。在编译的时候不会将所包含的动态链接库编译到程序中。

 

制作静态链接库 DynamicLibTest

DynamicLibTest.cpp

// DynamicLibTest.cpp : Defines the entry point for the DLL  application.

//

 

#include "stdafx.h"

 

BOOL APIENTRY DllMain( HANDLE hModule,

                        DWORD  ul_reason_for_call,

                        LPVOID lpReserved

                                    )

{

    return TRUE;

}

 

__declspec(dllexport) void ShowInfo()

{

       MessageBox(NULL,"DynammicLib",  "MQ", MB_OK);

}

调用动态链接库

ExecuteDynamicLib.cpp

// ExecuteDynamicLib.cpp : Defines the entry point for the  console application.

//

#include    "stdafx.h"

#pragma comment(lib, "DynamicLibTest.lib")

 

void ShowInfo();

int main(int argc, char* argv[])

{

       ShowInfo();

       return 0;

}

 

编译的时候用.lib文件,执行的时候用.dll文件

 

 

 

2 DLL基础再讨论

一、动态链接库的模块定义文件(.def)

模块定义文件是一个有着.def文件扩展名的文本文件。它被用于导出DLL的函数。一个.def文件只有两个必需的部分,也就是“LIBRARY”“EXPORTS”

DynamicLibDefTest.cpp

// DynamicLibDefTest.cpp : Defines the entry point for the DLL  application.

//

 

#include "stdafx.h"

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                        LPVOID lpReserved

                                    )

{

    return TRUE;

}

 

__declspec(dllexport) void showInfo()

{

       MessageBox(NULL,  "DynamicLib", "MQ", MB_OK);

}

 

void UseDEFShowInfo()

{

       MessageBox(NULL,  "def show", "MQ", MB_OK);

}

EXPORTS.def

LIBRARY DynamicLibDefTest

 

EXPORTS UseDEFShowInfo @1

ExecuteDynamicDEFLib.cpp

// ExecuteDynamicDEFLib.cpp : Defines the entry point for the  console application.

//

 

#include "stdafx.h"

#pragma comment(lib, "DynamicLibDefTest.lib")

 

void showInfo();

void UseDEFShowInfo();

int main(int argc, char* argv[])

{

       showInfo();

       UseDEFShowInfo();

       return 0;

}

 

二、动态链接库的入口函数(DLLMain()函数)

每一个DLL必须有一个入口函数,DLLMain()函数是一个缺省的入口函数。DLLMain()函数负责初始化和结束工作。每当一个新的进程或该进程的新线程访问DLL时,或者访问DLL的每个进程或者线程不再使用DLL或者线程结束时,都会调用DLLMain()函数。

定义只在进入时调用DLLMain()函数

// DynamicLibDefTest.cpp : Defines the  entry point for the DLL application.

//

 

#include "stdafx.h"

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID  lpReserved

                                                )

{

         switch(ul_reason_for_call)

         {

                  case DLL_PROCESS_ATTACH:

                            {

                                     MessageBox(NULL,  "DLL first", "MQ", MB_OK);

                            }

                   default:

                            return  TRUE;

 

         }

    return TRUE;

}

 

__declspec(dllexport) void showInfo()

{

         MessageBox(NULL,  "DynamicLib", "MQ", MB_OK);

}

 

void UseDEFShowInfo()

{

         MessageBox(NULL, "def  show", "MQ", MB_OK);

}

 

 

 

 

3次课 进程权限的提升

一、OpenProcessToken函数

打开进程令牌环

二、LookupPrivilegeValue函数

获得进程本地唯一ID

三、AdjustTokenPrivileges函数

提升进程的权限

 

GetCurrentProcess() //获得当前进程句柄

ConRunDll.cpp

// ConRunDll.cpp : Defines the entry point for the console  application.

//

 

#include "stdafx.h"

#include<stdio.h>

#include<windows.h> //提升权限用

 

//提升权限函数

int EnableDebugPriv(const char* name)

{

       HANDLE hToken;

       if (!  OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,  &hToken))

       {

              printf("open  fail!\n");

              return -1;

       }

       LUID luid;

       if(!  LookupPrivilegeValue(NULL, name, &luid))

       {

              printf("look  up fail!\n");

              return -1;

       }

      

       TOKEN_PRIVILEGES tp;

       tp.PrivilegeCount =  1;

       tp.Privileges[0].Luid  = luid;

       tp.Privileges[0].Attributes  = SE_PRIVILEGE_ENABLED;

       if(!  AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL))

       {

              printf("privileges  fail!\n");

       }

       printf("success!\n");

       return 0;

}

 

int main(int argc, char* argv[])

{

       EnableDebugPriv(SE_DEBUG_NAME);

       return 0;

}

 

 

 

4次课 远程线程的创建

一、打开远程进程

OpenProcess函数

二、在远程进程的内存中分配空间

VirtualAllocEx函数

三、远程进程的内存的写入

WriteProcessMemory函数

四、找到LoadLibrary函数在Kernel32中的地址

GetProcAddress函数

五、在远程进程中线程(远程线程)

CreateRemoteThread函数

ConRunDll.cpp

// ConRunDll.cpp : Defines the entry point for the console  application.

//

 

#include "stdafx.h"

#include<stdio.h>

#include<windows.h> //提升权限用

 

//提升权限函数

int EnableDebugPriv(const char* name)

{

       HANDLE hToken;

       if (!  OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,  &hToken))

       {

              printf("open  fail!\n");

              return -1;

       }

       LUID luid;

       if(!  LookupPrivilegeValue(NULL, name, &luid))

       {

              printf("look  up fail!\n");

              return -1;

       }

      

       TOKEN_PRIVILEGES tp;

       tp.PrivilegeCount =  1;

       tp.Privileges[0].Luid  = luid;

       tp.Privileges[0].Attributes  = SE_PRIVILEGE_ENABLED;

       if(!  AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL))

       {

              printf("privileges  fail!\n");

       }

       printf("success!\n");

       return 0;

}

 

BOOL InjectDLL(const char* DLLFullPath, const DWORD  dwRemoteProcessId)

{     HANDLE hRemoteProcess;

       hRemoteProcess =  OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,  FALSE, dwRemoteProcessId);

       if(hRemoteProcess ==  NULL)

       {

              printf("open  process fail!\n");

              return FALSE;

       }

       char  *pszLibFileRemote;

       pszLibFileRemote = (char*)VirtualAllocEx(hRemoteProcess,  NULL, lstrlen(DLLFullPath)+1, MEM_COMMIT, PAGE_READWRITE);

       if(pszLibFileRemote  == NULL)

       {

              printf("alloc  fail!\n");

              return FALSE;

       }

 

       if(!  WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (LPVOID)DLLFullPath,  lstrlen(DLLFullPath)+1, NULL))

       {

              printf("write  memory fail!\n");

              return FALSE;

       }

 

       PTHREAD_START_ROUTINE  pfnStartAddr =

       (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")),  "LoadLibraryA" );

       if(pfnStartAddr ==  NULL)

       {

              printf("get  proc addr fail!\n");

              return FALSE;

       }

      

       if(CreateRemoteThread(hRemoteProcess,  NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL) == NULL)

       {

              printf("create  remote thread fail!\n");

              return FALSE;

       }

      

       printf("good!\n");

}

int main(int argc, char* argv[])

{

       EnableDebugPriv(SE_DEBUG_NAME);

       InjectDLL("D:\\DynamicLibDefTest.dll",  4892);

       while(1);

       getchar();

       return TRUE;

       return 0;

}

 

 

 

5次课 进程ID的获取

一、系统进程快照

CreateToolhelp32Snapshot函数

二、在快照中搜索指定进程

Process32First函数

Processe32Next函数

ConRunDll.cpp

// ConRunDll.cpp : Defines the entry point for the console  application.

//

 

#include "stdafx.h"

#include<stdio.h>

#include<windows.h> //提升权限用

#include<TlHelp32.h>

 

//提升权限函数

int EnableDebugPriv(const char* name)

{

       HANDLE hToken;

       if (!  OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,  &hToken))

       {

              printf("open  fail!\n");

              return -1;

       }

       LUID luid;

       if(!  LookupPrivilegeValue(NULL, name, &luid))

       {

              printf("look  up fail!\n");

              return -1;

       }

      

       TOKEN_PRIVILEGES tp;

       tp.PrivilegeCount =  1;

       tp.Privileges[0].Luid  = luid;

       tp.Privileges[0].Attributes  = SE_PRIVILEGE_ENABLED;

       if(!  AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL))

       {

              printf("privileges  fail!\n");

       }

       printf("success!\n");

       return 0;

}

 

BOOL InjectDLL(const char* DLLFullPath, const DWORD  dwRemoteProcessId)

{     HANDLE  hRemoteProcess;

       hRemoteProcess =  OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,  FALSE, dwRemoteProcessId);

       if(hRemoteProcess ==  NULL)

       {

              printf("open  process fail!\n");

              return FALSE;

       }

       char  *pszLibFileRemote;

       pszLibFileRemote =  (char*)VirtualAllocEx(hRemoteProcess, NULL, lstrlen(DLLFullPath)+1,  MEM_COMMIT, PAGE_READWRITE);

       if(pszLibFileRemote  == NULL)

       {

              printf("alloc  fail!\n");

              return FALSE;

       }

 

       if(!  WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (LPVOID)DLLFullPath,  lstrlen(DLLFullPath)+1, NULL))

       {

              printf("write  memory fail!\n");

              return FALSE;

       }

 

       PTHREAD_START_ROUTINE  pfnStartAddr =

       (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")),  "LoadLibraryA" );

       if(pfnStartAddr ==  NULL)

       {

              printf("get  proc addr fail!\n");

              return FALSE;

       }

      

       if(CreateRemoteThread(hRemoteProcess,  NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL) == NULL)

       {

              printf("create  remote thread fail!\n");

              return FALSE;

       }

      

       printf("good!\n");

       return TRUE;

}

 

unsigned long getprocid(char *pn)

{

       HANDLE hnd;

       hnd =  CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

       if(hnd == NULL)

       {

              printf("snapshort  fail!\n");

              return 0;

       }

 

       PROCESSENTRY32 pe;

       pe.dwSize =  sizeof(PROCESSENTRY32);

       BOOL b;

       b =  Process32First(hnd, &pe);

       while(b)

       {

              if(strcmp(pe.szExeFile,  pn) == 0)

              {

                     return  pe.th32ProcessID;

                    

              }

                     b = Process32Next(hnd,  &pe);

       }

       return 0;

}

 

int main(int argc, char* argv[])

{

      

       EnableDebugPriv(SE_DEBUG_NAME);

       //InjectDLL("D:\\DynamicLibDefTest.dll",  4892);

       InjectDLL("D:\\DynamicLibDefTest.dll",getprocid("NOTEPAD.EXE"));

       while(1);

       getchar();

       return TRUE;

       return 0;

}

 

你可能感兴趣的:(DLL编程笔记)