windows中的DLL注入

概念

  • 远程线程:另一个进程中的线程。
  • 注入:别的进程中执行自己的代码
  • 远程线程注入:指一个进程在另一个进程中创建线程的技术

设计思路

在DLL的dllmain里写自己的代码,利用系统共享库(系统dll是所有进程共享)的函数动态加载自己的DLL,来运行自己的代码,系统dll里面的LoadLiabrary函数地址在不同进程中的地址是相同的,把这个地址当做远程线程的函数回调,那线程执行的就是这个api,在给这个api传入自己的dll地址,那加载的就是自己的dll了,自然而然的就可以执行自己的代码

  1. DLL加载
    1. 获取LoadLiabrary的地址
    2. 在目标进程申请内存,写入dll的路径,
    3. 创建远程线程

DLL代码就是想要执行的代码,我的代码就是替换计算器的窗口处理函数

LONG g_oldProc = NULL;

LRESULT CALLBACK MyPro(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  if (Msg == WM_COMMAND)
  {
    //如果键盘输入的是7就弹框
    if (LOWORD(wParam) == 0x83)
    {
      MessageBox(hWnd, TEXT("按键hook"), TEXT("提示"), MB_OK);
    }
  }
  return CallWindowProc((WNDPROC)g_oldProc, hWnd, Msg, wParam, lParam);
}

void AddMyWinPro()
{
  //查找窗口句柄
  HWND hWnd = FindWindow(TEXT("SciCalc"), NULL);
  //替换消息窗口函数
  g_oldProc = SetWindowLong(hWnd, GWL_WNDPROC, (LONG)MyPro);

}

void OldWinPro()
{
  //查找窗口句柄
  HWND hWnd = FindWindow(TEXT("SciCalc"), NULL);
  //还原处理
  if (g_oldProc != NULL)
  {
    g_oldProc = SetWindowLong(hWnd, GWL_WNDPROC, (LONG)g_oldProc);
  }
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
    AddMyWinPro();
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
    OldWinPro();
		break;
	}
	return TRUE;
}

 

  //注入计算器
  //1. 查找窗口
  HWND hWnd = ::FindWindow(NULL, _T("计算器"));//通过窗口名获取该窗口的句柄
  if (hWnd == NULL)
  {
    AfxMessageBox(_T("计算器没有运行"));
    return;
  }
  //获取目标进程ID,
  DWORD dwProcessId;
  ::GetWindowThreadProcessId(hWnd, &dwProcessId);
  //获取目标进程ID
  //UINT dwProcId = GetDlgItemInt(IDC_PROCID);

  
  HANDLE hProces = OpenProcess(
    PROCESS_ALL_ACCESS,
    FALSE,
    dwProcessId);

  //1获取loadliabrary的地址
  
  //两个进程在kernel32.dll中的loadliabraryA地址映射是一样的,所以在自己进程中获取地址是一样获取到目标进程的loadliabraryA地址 
  
  HMODULE hModKer32 = GetModuleHandle(_T("kernel32"));
  LPVOID pLoadLibrary = GetProcAddress(hModKer32, "LoadLibraryA");
  if (pLoadLibrary == NULL)
  {
    AfxMessageBox(_T("获取LoadLibraryA地址失败"));
    return;
  }


  // 2) 在目标进程申请内存,写入dll的路径,
  //因为两个进程是独立地址空间,如果你传的参数是本进程的地址,目标进程运行时找的地址肯定是错误的
  LPVOID pDllPathOfDstProc =
    VirtualAllocEx(
    hProces,
    NULL, //系统自动分配地址
    0x1000, //申请内存大小
    MEM_COMMIT, //物理映射
    PAGE_READWRITE //可读可写
    );
  if (pDllPathOfDstProc == NULL)
  {
    AfxMessageBox(_T("申请内存失败"));
    return;
  }
  char szBuff[] = { "D:\\vs2013Code\\远程线程注入\\Debug\\dll.dll" };
  DWORD dwBytestToWrite = 0;
  BOOL bRet = WriteProcessMemory(
    hProces,
    pDllPathOfDstProc,//写入内存的首地址
    szBuff,
    sizeof(szBuff),
    &dwBytestToWrite);
  if (!bRet)
  {
    AfxMessageBox(_T("写入路径失败"));
    return;
  }
  // 3) 创建远程线程,目标进程创建了一个线程,执行目标线程的线程回调函数
  m_hRemoteThread = CreateRemoteThread(
    hProces,
    NULL,
    0,
    (LPTHREAD_START_ROUTINE)pLoadLibrary, //在目标进程中的回调函数的地址
    pDllPathOfDstProc,//此时内存存放的是dll,这时候调用pLoadLibrary线程回调函数就会把dll当做参数传进去,就把dll加载进去了,
    0,
    NULL);
  if (m_hRemoteThread == NULL)
  {
    AfxMessageBox(_T("远程线程创建失败"));
  }
  else
  {
    AfxMessageBox(_T("远程线程创建成功"));
  }

 

 

  1. DLL卸载
    1. 获取模块句柄
    2. 获取freelibrary的地址
    3. 创建远程线程
//   1) 获取模块句柄
HANDLE hRemoteDll = NULL;
GetExitCodeThread(m_hRemoteThread, (DWORD*)&hRemoteDll);//LoadLibraryA的退出码就是加载的DLL模块句柄

//   2) 获取freelibrary的地址
HMODULE hModKer32 = GetModuleHandle("kernel32");
LPVOID pfnFreeLibrary = GetProcAddress(hModKer32, "FreeLibrary");
if (pfnFreeLibrary == NULL)
{
    AfxMessageBox("获取LoadLibraryA地址失败");
    return;
}

//   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);
    
if (m_hRemoteThread == NULL)
{
AfxMessageBox("远程线程创建失败");
}
else
{
AfxMessageBox("远程线程创建成功");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值