DLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "stdafx.h"
BOOL APIENTRY DllMain(

HMODULE hModule,
//DLL模块的句柄 handle Module
DWORD ul_reason_for_call
//DLLMain函数被调用的原因
LPVOID lpReserved
//Windows保留参数 必须为NULL
)
{
//DLLMain函数被调用的原因
switch(ul_reason_for_call)
{

case DLL_PROCESS_ATTACH:
//当DLL被进程加载时DLLMain被调用
case DLL_THREAD_ATTACH:
//有进程创建时DLLMain被调用
case DLL_THREAD_DETACH:
//有线程结束时DLLMain被调用
case DLL_PROCESS_DETACH:
//当DLL被进程卸载时DLLMain被调用
break;
}
return TRUE;
}

导出函数

1
2
3
4
5
6
7
8
//声明导出函数->将a函数导出
//加上 extern "c" 后 会指示编译器这部分代码按c语言的进行编译
//__declspec(dllexport):声明导出函数 若要使函数成为DLL接口的一部分 必须将其他模块钟函数的定义声明为dllexport
extern "c" __declspec(dllexport) void a();
void a()
{

}

应用程序与导出函数进行通讯

静态调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
调用静态库 格式#pragma comment(comment-type,["commentstring"])
comment-type 是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker之一。
compiler 放置编译器的版本或名字到一个对象文件,该选项是被linker忽略的。
exestr 以后的版本将会取消
lib 静态库,填写路径即可

linker:指定一个连接选项,这样就不用在命令行输入或者在开发环境中设置了。只有下面的linker选项能被传给Linker:
/DEFAULTLIB
/EXPORT
/INCLUDE
/MANIFESTDEPENDENCY
/MERGE
/SECTION

commentstring 是一个提供为comment-type提供附加信息的字符串。
*/
#include <Windows.h>
#pragma comment(lib,"LIB_PATH")
extern "C" void a ();
void main ()
{
a();
return 0;
}

动态调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <windows.h>
//定义一个函数指针类型
typedef void (*PMessage_Box)();

int main()
{
//将指定的模块加载到调用进程的地址空间中 获取句柄
HMODULE hModule = LoadLibrary("DLLPATH")

//判断句柄是否为空
if (hModule == NULL)
{
return -1;
}
/*
GetProcAddress 从dll中检索导出的函数或变量的地址
FARPROC GetProcAddress(HMODULE hModule,LPCSTR lpProcName);
参数hModule为包含函数或变量的DLL模块的句柄。
参数lpProcName为函数或变量名称,或函数的序数值。如果此参数是序数值,则必须使用低位字;高阶字必须为零。
执行成功 返回值为导出的函数或变量的地址 执行失败返回NULL
*/
PMessage_Box pMsg = (PMessage_Box)GetProcAddress(hModule,"function_name");

//调用
pMsg();

return 0;
}

DLL注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <Windows.h>

void Inject (int pID,char* Path)
{
/*
获取进程句柄
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
dwDesiredAccess 访问权限的设置。
bInheritHandle 如果此值为TRUE,则此进程创建的进程将继承该句柄。否则,进程将不会继承此句柄。
dwProcessId 要打开的本地进程的标识符。
*/

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);

/*
申请一块内存给传入的路径
LPVOID VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
hProcess 进程的句柄
lpAddress 该指针为要分配的页面区域指定所需的起始地址。如果为NULL,则该函数确定将区域分配到的位置。
dwSize 要分配的内存区域的大小,以字节为单位。
flAllocationType 内存分配的类型。
flProtect 对要分配的页面区域的内存保护。
如果函数成功,则返回值是页面分配区域的基地址。如果函数失败,则返回值为NULL。
*/
LPVOID pReturnAddress = VirtualAllocEx(hProcess,NULL,strlen(Path)+1,MEM_COMMIT,PAGE_READWRITE);
/*
将路径写入上面申请的内存
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
);
hProcess 要修改的过程存储器的句柄。
lpBaseAddress 指向要写入数据的指定进程中的基地址的指针。
lpBuffer 指向缓冲区的指针
nSize 要写入指定进程的字节数。
lpNumberOfBytesWritten 指向变量的指针,该变量接收传输到指定进程中的字节数。为NULL则忽略该参数。
如果函数执行成功,则返回值为非零。如果函数执行失败,则返回值为0(零)。
*/
WriteProcessMemory(hProcess,pReturnAddress,Path,strlen(Path)+1,NULL);

//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule,"LoadLibraryA");


/*
创建在另一个进程的虚拟地址空间中运行的线程
HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);

hProcess 进程句柄
lpThreadAttributes 指向SECURITY_ATTRIBUTES结构的指针
dwStackSize 堆栈的初始大小,以字节为单位。系统将此值舍入到最接近的页面。如果此参数为0(零),则新线程使用可执行文件的默认大小。
lpStartAddress 指向由线程执行的,类型为LPTHREAD_START_ROUTINE的应用程序定义的函数的指针,该指针表示远程进程中线程的起始地址。
lpParameter 指向要传递给线程函数的变量的指针。
dwCreationFlags 控制线程创建的标志。值0 线程在创建后立刻运行。
lpThreadId 指向接收线程标识符的变量的指针,如果此参数为NULL,则不返回线程标识符。
*/
//创建远程线程 并获取线程句柄
//CreateRemoteThread(进程句柄,NULL,0,lpStartAddress,指向要传递给线程函数的变量的指针,0,NULL);
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,lpStartAddress,pReturnAddress,0,NULL);

/*
等待线程事件 防止线程阻塞
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
hHandle 对象的句柄。
dwMilliseconds 超时时间间隔(以毫秒为单位)。
如果dwMilliseconds为INFINITE,则该函数仅在发出信号通知对象时(永久等待 线程执行完毕 获取到句柄)返回。
*/
WaitForSingleObject(hThread,2000);

//关闭打开对象句柄 防止内存泄漏
CloseHandle(hThread);
CloseHandle(hProcess);
}

int main()
{
const char* a ="DLL_PATH";
Inject (pID,(char*)a);
//不强转char* 新版vs会提示实参与形参不兼容
return 0;
}

卸载模块

1
2
3
4
5
6
7
/*
BOOL FreeLibrary(
HMODULE hLibModule
);
hLibModule加载的库模块的句柄。
*/
FreeLibrary();

获取进程ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<windows.h>
#include<stdio.h>
int GetProcessID()
{
//获取窗体句柄
/*
HWND FindWindowA(
LPCSTR lpClassName,
LPCSTR lpWindowName
);
//lpClassName
*/

HWND GetHandleID;
GetHandleID=FindWindowA("lpClassName", "lpWindowName");
if (GetHandleID != NULL)
{
printf("句柄为:%x",GetHandleID);
//获取进程id
DWORD _pid;
DWORD test;
BOOL flag = GetWindowThreadProcessId(GetHandleID, &_pid);
if (flag != 0)
{
printf("进程ID为:%d", _pid);
}
else
{
printf("获取ID失败");
}
getchar();
}

else
{
printf("获取句柄失败");
getchar();
}
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);
//获取自己的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId());

c语言调用Call

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//内联汇编
void Funcname()
{
__asm
{
push xxx
mov eax,xxx
call eax
add sep,0x6
}
}
void MyCall(DWORD pID,DWORD _CallAddress,LPVOID Funcname)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);

//有参数Call
if (_CallAddress == Null)
{

//申请一块内存给整个CAll
LPVOID CallAddress = VirtualAllocEx(hProcess,NULL,0x100,MEM_COMMIT,PAGE_READWRITE);

//将Call数据写入上面分配的内存
WriteProcessMemory(hProcess,CallAddress,Funcname,0x100,NULL);

//创建远程线程 并获取线程句柄
//CreateRemoteThread(进程句柄,NULL,0,lpStartAddress,指向要传递给线程函数的变量的指针,0,NULL);
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)CallAddress,NULL,0,NULL);

//等待线程事件 防止线程阻塞
WaitForSingleObject(hThread,2000);

//关闭打开对象句柄 防止内存泄漏
CloseHandle(hThread);
CloseHandle(hProcess);
}
else
{
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)_CallAddress,NULL,0,NULL);
WaitForSingleObject(hThread,2000);
CloseHandle(hThread);
CloseHandle(hProcess);
}

}

DLL调用Call

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Funcname()
{
__asm
{
push xxx
mov eax,xxx
call eax
add sep,0x6
}
}
BOOL APIENTRY DllMain(

HMODULE hModule,
//DLL模块的句柄 handle Module
DWORD ul_reason_for_call
//DLLMain函数被调用的原因
LPVOID lpReserved
//Windows保留参数 必须为NULL
)
{
//DLLMain函数被调用的原因
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Funcname();
break;
}
return TRUE;
}

使用多级指针读写值

1
2
3
4
5
6
7
8
9
10
11
12
DWORD ModuleBase = 0x0;
DWORD p1 = 0x0;
DWORD p2 = 0x0;
DWORD p3 = 0x0;
/*
DWORD add = *(DWORD*)ModuleBase;
DWORD add2 = *(DWORD*)(add + p1);
DWORD add3 = *(DWORD*)(add2 + p2);
DWORD address = add3 + p3;
*(DWORD*)address = xxx;
*/
*(DWORD*)((*(DWORD*)((*(DWORD*)((*(DWORD*)ModuleBase)+p1))+p2))+p3) = xxx;

创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);

lpThreadAttributes
指向SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承返回的句柄。如果 lpThreadAttributes为NULL,则不能继承该句柄。

dwStackSize
堆栈的初始大小,以字节为单位。系统将此值舍入到最接近的页面。如果此参数为零,则新线程将使用可执行文件的默认大小。

lpStartAddress
指向要由线程执行的应用程序定义的函数的指针。该指针表示线程的起始地址。

lpParameter
指向要传递给线程的变量的指针。

dwCreationFlags
控制线程创建的标志。
*/
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Funcname, NULL, 0, 0);
//reinterpret_cast<类型> C++的方式通过指针强转类型
CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>Funcname, NULL, 0, 0);

使用TabSheet操作MFC的Tab页控件

TabSheet.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#if !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_)  
#define AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TabSheet.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CTabSheet window
#define MAXPAGE 16

class CTabSheet : public CTabCtrl
{
// Construction
public:
CTabSheet();

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTabSheet)
//}}AFX_VIRTUAL

// Implementation
public:
int GetCurSel();
int SetCurSel(int nItem);
void Show();
void Free();

void SetRect();
BOOL AddPage(LPCTSTR title, CDialog *pDialog, UINT ID);
virtual ~CTabSheet();

// Generated message map functions
protected:
LPCTSTR m_Title[MAXPAGE];
UINT m_IDD[MAXPAGE];
CDialog* m_pPages[MAXPAGE];
int m_nNumOfPages;
int m_nCurrentPage;
//{{AFX_MSG(CTabSheet)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

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

#endif // !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_)

TabSheet.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// TabSheet.cpp : implementation file  
//

#include "stdafx.h"
#include "TabSheet.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTabSheet

CTabSheet::CTabSheet()
{
m_nNumOfPages = 0;
m_nCurrentPage = 0;
}

CTabSheet::~CTabSheet()
{
}


BEGIN_MESSAGE_MAP(CTabSheet, CTabCtrl)
//{{AFX_MSG_MAP(CTabSheet)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTabSheet message handlers

BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID)
{
if( MAXPAGE == m_nNumOfPages )
return FALSE;

m_nNumOfPages++;

m_pPages[m_nNumOfPages-1] = pDialog;
m_IDD[m_nNumOfPages-1] = ID;
m_Title[m_nNumOfPages-1] = title;

return TRUE;
}

void CTabSheet::SetRect()
{
CRect tabRect, itemRect;
int nX, nY, nXc, nYc;

GetClientRect(&tabRect);
GetItemRect(0, &itemRect);

nX=itemRect.left;
nY=itemRect.bottom+1;
nXc=tabRect.right-itemRect.left-2;
nYc=tabRect.bottom-nY-2;

m_pPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
for( int nCount=1; nCount < m_nNumOfPages; nCount++ )
m_pPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);

}

void CTabSheet::Show()
{
for( int i=0; i < m_nNumOfPages; i++ )
{
m_pPages[i]->Create( m_IDD[i], this );
InsertItem( i, m_Title[i] );
}

m_pPages[0]->ShowWindow(SW_SHOW);
for( int i=1; i < m_nNumOfPages; i++)
m_pPages[i]->ShowWindow(SW_HIDE);

SetRect();

}

void CTabSheet::OnLButtonDown(UINT nFlags, CPoint point)
{
CTabCtrl::OnLButtonDown(nFlags, point);

if(m_nCurrentPage != GetCurFocus())
{
m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE);
m_nCurrentPage=GetCurFocus();
m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);
// m_pPages[m_nCurrentPage]->SetFocus();
}
}

int CTabSheet::SetCurSel(int nItem)
{
if( nItem < 0 || nItem >= m_nNumOfPages)
return -1;

int ret = m_nCurrentPage;

if(m_nCurrentPage != nItem )
{
m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE);
m_nCurrentPage = nItem;
m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);
// m_pPages[m_nCurrentPage]->SetFocus();
CTabCtrl::SetCurSel(nItem);
}

return ret;
}

int CTabSheet::GetCurSel()
{
return CTabCtrl::GetCurSel();
}

//释放page资源
void CTabSheet::Free()
{

CTabCtrl::DeleteAllItems();
for( int i=0; i < m_nNumOfPages; i++ )
{
m_pPages[i]->DestroyWindow();
m_IDD[i] = NULL;
m_Title[i] = NULL;

}
m_nCurrentPage = 0;
m_nNumOfPages = 0;
//CTabCtrl::DestroyWindow(); //注意不要将this指针释放了
}