同步对象和远程注入实现

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

阻塞一个线程直到另一个线程结束

 

posted @ 2020-09-04 18:19  特权E5  阅读(136)  评论(0编辑  收藏  举报