1. 内核同步对象(信号和互斥体)
1.1 信号
控制多线程等待数量问题
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, 安全控制,一般直接传入NULL。
LONG lInitialCount, 初始资源数量
LONG lMaximumCount, 最大并发数量
LPCTSTR lpName 信号量的名称,传入NULL表示匿名信号量
);
作用跨进程使用信号灯
HANDLE OpenSemaphore(
DWORD dwDesiredAccess, 访问权限,对一般传入SEMAPHORE_ALL_ACCESS。
BOOL bInheritHandle, 句柄继承性,一般传入TRUE即可。
LPCTSTR lpName 名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。
);
增加线程并发数量
BOOL ReleaseSemaphore(
HANDLE hSemaphore, 信号量的句柄。
LONG lReleaseCount, 增加个数,必须大于0且不超过最大资源数量。
LPLONG lpPreviousCount 可以用来传出先前的资源计数,设为NULL表示不需要传出
);
信号量:
WaitForSingleObject -- 等待成功,个数减一,
//等待可用的信号, 如果成功,则可用信号的个数减一
WaitForSingleObject(g_hSemphore, INFINITE);
信号量的个数为0,信号量处于no-signale状态
ReleaseSem释放信号 个数加一
//释放可用信号
ReleaseSemaphore(g_hSemphore, 1, NULL);
多用于处理多个线程共享多于一个资源的情况,常见于池技术
1.2 互斥体
互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex))。互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section)。
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针
BOOLbInitialOwner, // 初始化互斥对象的所有者
LPCTSTRlpName // 指向互斥对象名的指针
);
多个线程使用互斥体,只有一个线程拥有互斥体的权限,即只有一个线程能够执行
WaitForSingleObject(hMutex, INFINITE); -- 获取互斥体的使用权,并修改互斥体的状态为no-signal
ReleaseMutex(hMutex); --释放互斥体的使用权
1.3
三环(用户模式):原子操作, 关键段
内核同步对象:事件, 信号, 互斥体
三环的同步手段,效率明显高于内核同步对象
2. 远程线程注入
通过调用进程api函数传递参数到达调用函数实现自己的目的
注入 -- 别的进程执行自己的代码
如果让别的进程执行自己的dll代码?
获取进程句柄
HANDLE hProcess = GetProcessByName("Calc.exe");
Calc.exe 进程名
1) 获取LoadLiabrary的地址
HMODULE hModKer32 = GetModuleHandle("kernel32");
LPVOID pLoadLibrary = GetProcAddress(hModKer32, "LoadLibraryA");
LPTHREAD_START_ROUTINE addr = (LPTHREAD_START_ROUTINE)GetProcAddress(modHandle, "LoadLibraryA");
LoadLibraryA 调用函数
2) 在目标进程申请内存,写入dll的路径
目标进程中申请一块内存
LPVOID pDllPathOfDstProc =
VirtualAllocEx(
hProces,
NULL, //系统自动分配地址
0x1000, //申请内存大小
MEM_COMMIT, //物理映射
PAGE_READWRITE //可读可写
);
char szBuff[] = { "Dll.dll" };
DWORD dwBytestToWrite = 0;
BOOL bRet = WriteProcessMemory(
hProces,
pDllPathOfDstProc, 申请内存地址
szBuff, 写入的地址
sizeof(szBuff), 大小
&dwBytestToWrite);
Dll.dll 自己要注入dll的全路径
3) 创建远程线程
m_hRemoteThread = CreateRemoteThread(
hProces,
NULL,
0,
(LPTHREAD_START_ROUTINE)pLoadLibrary, //在目标进程中的回调函数的地址 远程调用这个函数
pDllPathOfDstProc, 将参数传进LoadLibrary函数
0,
NULL);
卸载:
1) 获取模块句柄
HANDLE hRemoteDll = NULL;
GetExitCodeThread(m_hRemoteThread, (DWORD*)&hRemoteDll);
2) 获取freelibrary的地址
HMODULE hModKer32 = GetModuleHandle("kernel32");
LPVOID pfnFreeLibrary = GetProcAddress(hModKer32, "FreeLibrary");
3) 创建远程线程
UINT dwProcId = GetDlgItemInt(EDT_PROCID);
HANDLE hProces = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwProcId);
m_hRemoteThread = CreateRemoteThread(
hProces,
NULL,
0,
(LPTHREAD_START_ROUTINE)pfnFreeLibrary, //在目标进程中的回调函数的地址
hRemoteDll,
0,
NULL);
对象 |
数据类型 |
描述 |
Event(事件) |
KEVENT |
阻塞一个线程直到其它线程检测到某事件发生 |
Semaphore(信号灯) |
KSEMAPHORE |
与事件对象相似,但可以满足任意数量的等待 |
Mutex(互斥) |
KMUTEX |
执行到关键代码段时,禁止其它线程执行该代码段 |
Timer(定时器) |
KTIMER |
推迟线程执行一段时期 |
Thread(线程) |
KTHREAD |
阻塞一个线程直到另一个线程结束 |