WinNT&Win2K下實現程式的完全隱藏(轉)

RegisterForBlog發表於2007-09-19
WinNT&Win2K下實現程式的完全隱藏(轉)[@more@]

  關於程式的隱藏,98下的例子數不勝數。WinNT/Win2K下的隱藏方法,西祠的高手shotgun在去年的6月就已經在網上釋出出例項《揭開木馬的神秘面紗》 ,我也多次拜讀他的文章,對他的計算機水平及熱心幫助朋友的作風十分敬佩。這裡也可算是對shotgun的文章的補充與深入介紹吧,好了,閒話少說。

  在WinNT下"真正隱藏程式"這一說法,可以講是根本不可能實現,只要我們的程式是以程式核心的形式執行,都是不可能逃離CTRL+ALT+DEL的法眼。那麼奇怪了,這豈不是與我們的標題《WinNT & Win2K下實現程式的完全隱藏》相矛盾嗎?是的,實際上應該是:以非程式方式執行目的碼,而逃避程式檢視器的檢查,從而達到"程式隱藏"的目的。

  我們這裡用的,是在宿主程式中,以執行緒的方式執行我們的程式碼。實現起來非常簡單。

  首先,我們先建立一個不執行任何語句的執行緒

  DWORD stdcall ThreadProc(LPVOID *lpVoid){

  return 0;

  }

  然後,將執行緒程式碼拷備至宿主程式所能夠執行的任何地方(即頁面屬性為PAGGE_EXECUTE_READWRITE),如:共享記憶體影射區、宿主程式內。這裡我們選擇宿主程式,拷備的時侯,我們需要先在宿主程式中使用VirtualAllocEx函式申請一段記憶體,然後再使用WriteP rocessMemory將執行緒體寫入宿主程式中。

  以上工作完成後,我們便可CreateRemoteThread函式啟用其執行。下面給出一個完整的例子

  //遠端執行緒執行體

  DWORD __stdcall ThreadProc (void *lpPara){

  return 0;

  }

  int main(int argc, char* argv[]){

  const DWORD THREADSIZE=1024*4;//暫定執行緒體大小為4K,實際上沒這麼大,稍後我將會介紹

  DWORD byte_write;

  //獲得指定程式ID控制程式碼,並設其許可權為PROCESS_ALL_ACCESS,992是宿程式的ID號,獲取ID號的方法這裡我就不多講了

  HANDLE hWnd = :penProcess (PROCESS_ALL_ACCESS,FALSE,992);

  if(!hWnd)return 0;

  void *pRemoteThread =::VirtualAllocEx(hWnd,0,THREADSIZE,MEM_COMMIT| MEM_RESERVE,PAGE_EXECUTE_READWRITE);//申請

  if(!pRemoteThread)return 0;

  if(!::WriteProcessMemory(hWnd,pRemoteThread,&ThreadProc,THREADSIZE,0))//寫入程式

  return 0;

  //啟動執行緒

  HANDLE hThread = ::CreateRemoteThread (hWnd ,0,0,(DWORD (__stdcall *)(void*))pRemoteThread ,NULL,0,&byte_write);

  if(!hThread){ //還有記憶體分配未釋放

  return 0;

  }

  return 0;

  }

  到這裡,對於隱藏的方法就算告一段落,相信看過的朋友對這個思路有個非常明確的概念了吧。

  在理解隱藏的方法後,我們著重開始寫執行緒的執行部分了。如下:

  DWORD __stdcall ThreadProc(void *lpPara){

  MessageBox(NULL,"hello","hello",0);

  return 0;

  }

  編譯執行後,你會發現出現一個非法操作錯誤,為什麼呢?在我們以段頁式記憶體管理的win2K作業系統中,編譯時會把所有的常量編譯在PE檔案的.data節中,而程式碼段則在.text中,所以,我們拷備到宿主程式中的程式碼是在.text中的程式碼,MessageBox(NULL,(char *)指標,p,0);所指向的地址是本程式的記憶體虛擬地址。而在宿主程式中是無法訪問的。解決的方法很簡單,按舊照搬的將"hello"也拷備到目標程式中,然後再引用。同理,MessageBox函式地址編譯時,也是儲存在.Import中,寫過Win2k病毒的朋友都知道,所有常量與函式入口地址都需在程式碼段定義與得出,我們這裡也與他有點類似。言歸正傳,同樣情況我們也把函式的入口地址一起寫入目標程式中。//先定義引數結構typedef struct _RemotePara{//引數結構

  char pMessageBox[12];

  DWORD dwMessageBox;

  }RemotePara;

  //付值

  RemotePara myRemotePara;

  ::ZeroMemory(&myRemotePara,sizeof(RemotePara));

  HINSTANCE hUser32 = ::LoadLibrary ("user32.dll");

  myRemotePara.dwMessageBox =(DWORD) ::GetProcAddress (hUser32 , "MessageBoxA");

  strcat(myRemotePara.pMessageBox,"hello");

  //寫進目標程式

  RemotePara *pRemotePara =(RemotePara *) ::VirtualAllocEx (hWnd ,0,sizeof(RemotePara),MEM_COMMIT,PAGE_READWRITE);//注意申請空間時的頁面保護屬性

  if(!pRemotePara)return 0;

  if(!::WriteProcessMemory (hWnd ,pRemotePara,&myRemotePara,sizeof myRemotePara,0))return 0;

  //啟動進將引數傳遞進入

  HANDLE hThread = ::CreateRemoteThread (hWnd ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pRemotePara,0,&byte_write);

  if(!hThread){

  return 0;

  }好了,就這麼簡單,下在給出一個彈出一個MessageBox的例項:// RemoteThread.cpp: Defines the entry point for the console application.

  //

  #include "stdafx.h"

  typedef struct _RemotePara{//引數結構

  char pMessageBox[12];

  DWORD dwMessageBox;

  }RemotePara;

  //遠端執行緒

  DWORD __stdcall ThreadProc (RemotePara *lpPara){

  typedef int (__stdcall *MMessageBoxA)(HWND,LPCTSTR,LPCTSTR,DWORD);//定義MessageBox函式

  MMessageBoxA myMessageBoxA;

  myMessageBoxA =(MMessageBoxA) lpPara->dwMessageBox ;//得到函式入口地址

  myMessageBoxA(NULL,lpPara->pMessageBox ,lpPara->pMessageBox,0);//call return 0;

  }

  void EnableDebugPriv();//提升應用級除錯許可權

  int main(int argc, char* argv[]){

  const DWORD THREADSIZE=1024*4;

  DWORD byte_write;

  EnableDebugPriv();//提升許可權

  HANDLE hWnd = :penProcess (PROCESS_ALL_ACCESS,FALSE,992);

  if(!hWnd)return 0;

  void *pRemoteThread =::VirtualAllocEx(hWnd,0,THREADSIZE,MEM_COMMIT| MEM_RESERVE,PAGE_EXECUTE_READWRITE);

  if(!pRemoteThread)return 0;

  if(!::WriteProcessMemory(hWnd,pRemoteThread,&ThreadProc,THREADSIZE,0))

  return 0;

  //再付值

  RemotePara myRemotePara;

  ::ZeroMemory(&myRemotePara,sizeof(RemotePara));

  HINSTANCE hUser32 = ::LoadLibrary ("user32.dll");

  myRemotePara.dwMessageBox =(DWORD) ::GetProcAddress (hUser32 , "MessageBoxA");

  strcat(myRemotePara.pMessageBox,"hello");

  //寫進目標程式

  RemotePara *pRemotePara =(RemotePara *) ::VirtualAllocEx (hWnd ,0,sizeof(RemotePara),MEM_COMMIT,PAGE_READWRITE);//注意申請空間時的頁面屬性

  if(!pRemotePara)return 0;

  if(!::WriteProcessMemory (hWnd ,pRemotePara,&myRemotePara,sizeof myRemote

  Para,0))return 0;

  //啟動執行緒

  HANDLE hThread = ::CreateRemoteThread (hWnd ,0,0,(DWORD (__stdcall *)(voi

  d *))pRemoteThread ,pRemotePara,0,&byte_write);

  if(!hThread){

  return 0;

  }

  return 0;

  }

  //提升許可權

  void EnableDebugPriv( void )

  {

  HANDLE hToken;

  LUID sedebugnameValue;

  TOKEN_PRIVILEGES tkp;

  if ( ! OpenProcessToken( GetCurrentProcess(),

  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )

  return;

  if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ){

  CloseHandle( hToken );

  return;

  }

  tkp.PrivilegeCount = 1;

  tkp.Privileges[0].Luid = sedebugnameValue;

  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL )

  )

  CloseHandle( hToken );

  }

  好了,程式編譯執行後會在程式號為992的程式中建立一執行緒,彈出hello對話方塊。是不是非常簡單呢!

  這裡有幾個地方需要注意的:

  1、遠端執行緒在宿主程式中申請空間時,空間大小的確定了是我一直無法解決的問題。我曾使用兩個貼近一起的執行緒,以執行緒間的距離大小,並加上引數大小,作為申請空間時,仍然會出現非法操作,如下:

  static void StartThread (LPVOID *lpPara){

  return ;

  }

  static void EndThread(LPVOID *lpPara){

  return;

  }

  然後使用DWORD dwLenght = (DWORD)((char *)&StartThread - (char *)&EndThread);

  //得到StartThread執行緒程式碼長度,dwLenght += sizeof(ThreadPara); 仍會出現非法操作讓我很迷惑。在win2k中,執行緒的預設堆疊的頁大小是4KB,這裡我在為執行緒申請記憶體時,申請的大小暫時使用一個常數,始終為4KB的倍數,選取時儘量取大,線上程可成功執行後,再一點點改小。辦法是笨了點,如這裡的朋友有更好的方法,請不吝賜教。

  2、什麼時侯,什麼引數是需要從外部傳遞進來的呢?我這裡並沒有一個十分有力的答案,我的理解是:PE檔案中除了.text節以外的所有節,均需使用外部引數傳遞到執行緒中使用,如:.rsrc、.data、rdata等其他的15個節。在我們實際編寫的過程中,初學者並不知道我們的程式碼會編譯在什麼地方,這個時侯,我們可以在執行的時侯ALT + 8(VC中快捷鍵)反編譯過來,一般有lea eax p、push offset p等取地址語句,這個時侯,我們大都需要以

  

·上一篇:

·下一篇:
 
     最新更新
·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·


| | | | | | |

Copyright © 2004 - 2007 All Rights Reserved

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-970212/,如需轉載,請註明出處,否則將追究法律責任。

WinNT&Win2K下實現程式的完全隱藏(轉)
請登入後發表評論 登入
全部評論

相關文章