第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 Library(DLL)
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; } |