㈠ 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息.求高手幫助說明解決的詳細步驟
環衛女工三處骨折
在傷者面前,碧翠絲示意碧姬和張先生幫忙,她蹲下來用手扶著傷者的頭部,其他兩人抓著傷者的胳膊和腿,慢慢將其翻過身來。然後她又將傷者的衣服解開,查看傷勢,碧姬跪在地上為傷者查脈搏。
昨日16時許,記者聯繫到了張先生,並告訴他們傷者狀態良好,一家人聽到後都很開心。由於張先生懂的法語不多,惟一能當翻譯的女兒又出去了,張先生只好一把將女婿馬特拽來充當翻譯,可是馬特的中文、英文也不是很好。
得知傷者狀態良好都很開心
本報訊(記者周小宇) 昨日13時30分許,淘寶網,長春市衛星廣場附近,一輛黑色本田將一環衛女工撞倒。這時,正好兩位法國女士乘車路過,在120急救車趕到前,對受傷環衛工人作了急救處理,在傷者被120送走後,左旋肉鹼淘寶專賣店,她們才離開。
這時傷者睜開了眼睛,「我怎麼了?我這是在哪?」望著周圍人的注視,她虛弱地問道,隨後又閉上眼睛。碧翠絲趕緊晃了晃她,再次讓她睜開眼睛,然後示意張先生,「跟她說話,不要讓她睡著。」
經過一番簡單的檢查,碧翠絲鬆了口氣說:「不是很嚴重,代寫論文,可能有幾處骨折。」
在吉大一院的急診室,記者見到了56歲的傷者張鳳香,虛弱的她意識很清醒,「我在撿街上的垃圾,之後眼前一黑就什麼都不知道了。」對兩位國際友人的急救處理,張鳳香一點印象都沒有。急診大夫介紹,張鳳香的鎖骨、肋骨、脛骨3處骨折,目前沒有生命危險,但需要住院觀察。
車停下後,碧翠絲下了車,碧姬和張先生也跟著下了車。
馬特說,回到家後,媽媽和舅媽跟他們說了車禍的事情,傷者的臉上有擦傷,腹部被撞得淤青,但是情況不是很嚴重,應該不會有生命危險,只是在接下來的幾個小時里,她總是擔心傷者的病情。
肇事車車主劉先生表示配合張鳳香的治療。
「媽媽擔心女人(馬特對傷者的稱呼),希望她能好!」馬特說。
昨日13時許,喜宴結束後,碧翠絲和同來的親朋好友還有新娘的父親張先生乘坐大巴回家,行駛到人民大街上100多米遠時,唱著歌的碧翠絲望見路邊一名環衛女工趴在一輛黑色本田轎車前一動不動,車的風擋玻璃上全是碎裂的痕跡,周圍有幾個市民在旁邊圍觀。
過路法國女護士救助車禍傷者
「有人出事了,我有能力去救她,是很正常的事。」碧翠絲說。
10多分鍾後,120急救車趕到將傷者帶走,碧翠絲的腿早已經酸得站不起來,而碧姬穿著裙子,裸露著的膝蓋被地面的小石頭磨破了皮,出了血。兩人拿出創可貼簡單處理後就返回車上。
救人的兩名法國女士都是護士,一位叫碧翠絲,另一位叫碧姬。5日早晨,她們乘坐飛機來到長春參加碧翠絲兒子馬特和中國姑娘的婚禮,碧姬是馬特的舅媽。
情急之下,她趕緊沖到司機跟前,大聲地讓司機停車。
參加兒子喜宴路遇傷者
相關的主題文章:
[推薦]4999元看爽動作片 五款熱銷等離子推薦
[推薦]青年自稱雙性人在廣場上舉牌徵婚(組圖)
[推薦]5名工人申請離職久未獲批欲跳樓
㈡ 如何診斷並解決 Windows 內部堆棧溢出錯誤消息
win7堆棧溢出解決方法:打開常用的瀏覽器,這個方法適用於所有的瀏覽器。所以不用擔心會出現狀況。
找到菜單欄,在菜單欄上面存在一個"工具"選項,單擊工具這個按鈕。
在"工具"這個選項下面有個"Internet選項",點擊這個功能選項。就可進入"Internet選項"界面。
主要的操作就在"Internet選項"裡面,當點擊"Internet選項"的時候就會彈出一個窗口。
在"Internet選項"窗口上方有個"高級"按鈕,點擊這個按鈕,然後在"設置"下一級存在一個功能"禁用腳本調試",這個功能項在默認狀態下是勾選起的,現在我們要取消勾選這個功能項。
完成這最後一步就解決堆棧溢出的問題。
㈢ 求助怎麼從崩潰線程的堆棧信息中分析崩潰原因
最近在開發中要為部門的軟體產品加上crash report功能,研究了很多關於Windows平台下的debug技術。最終方案為minimp file + email匯報方式,對於debug的相關總結我會再寫一篇,這篇就先總結一下自動發送Email功能的實現方法。另外我還寫了一個demo程序,雖然 UI比較簡單,不過發送Email的基本功能已經有了,並且用了5種庫實現,一是為了比較庫的性能,二是通過比較庫的實現,我們可以學習一下代碼設計和實 現方面的技巧。
其實當今的軟體應用與網路結合越來越緊密,我們為軟體加上Email發送功能有很多好處。比如可以發送軟體錯誤報告信息,有利於軟體debug;可以在幫助中加入用戶意見和使用體驗等信息,通過郵件匯總升級;可以在用戶卸載軟體時請用戶選擇卸載原因,收集用戶使用習慣等。
發送郵件用到的協議是SMTP(Simple Mail Transfer Protocol,簡單郵件傳輸協議),是一種基於TCP/IP的上層應用協議,定義了郵件由源地址到目的地址的傳送規則。關於SMTP協議的具體內容,大家可以參考相關資料。我們要進行Email發送,需要兩個條件:
1、支持SMTP的庫
也就是完成SMTP功能的代碼,由於SMTP非常簡單,因此往往就是一個封裝類,或者一組API。當然也可以自己用socket實現SMTP,不過如果不是為了練手,還是直接用已有的開源代碼吧,畢竟簡單且穩定。
2、一個發送郵箱賬戶和一個接收郵箱賬戶
郵箱賬戶應該不是什麼難事,大家隨便去申請兩個免費郵箱就行了。需要說明的是,發送郵件時要先登錄郵件伺服器根據帳號和密碼進行認證,因此發送郵箱必須支 持SMTP訪問,比如126郵箱從07年開始便不再對新申請用戶支持SMTP訪問,因此126郵箱賬戶必須是07年以前申請的才行,否則會在認證時返回 550錯誤碼,提示用戶被鎖定。還有些郵箱如gmail需要SSL支持加密方式,對某些庫來說可能就不支持了。
我們先看一下demo程序界面,了解發送郵件需要哪些基本參數。
為程序添加自動發送Email功能
可知參數包括:發送端郵箱賬戶和密碼、接收端郵箱賬戶、郵件主題、內容、附件等信息,另外還要指定郵件 發送伺服器地址,在此我們認為是」smtp.host」形式,如按圖中設置發送伺服器地址即為smtp.126.com。一般庫還會支持指定發送者用戶 名、認證方式、多個接收地址、抄送地址、html格式正文、多個附件等。
下面介紹幾個比較不錯的SMTP庫,都是用C++開發的。
1、jwSMTP (http://sourceforge.net/projects/jwsmtp/)
jwSMTP是一個開源庫,支持跨平台,SMTP常用功能都支持的不錯,應用起來也非常方便。jwSMTP提供了一個封裝類,介面簡單易用。最難得的是它 自帶的文檔和示例都非常完善豐富,因此也是我最終選擇應用的庫。在應用過程中,該庫運行非常穩定,沒有發現什麼問題,建議大家使用jwSMTP。
以下是應用代碼:
jwsmtp::mailer mail( (LPCTSTR)m_strToUser, (LPCTSTR)m_strFormUser, (LPCTSTR)m_strSubject, (LPCTSTR)m_strContent, (LPCTSTR)m_strServer, jwsmtp::mailer::SMTP_PORT, false);
mail.username((LPCTSTR)m_strFormUser);
mail.password((LPCTSTR)m_strFromPassword);
mail.authtype(jwsmtp::mailer::PLAIN);
mail.attach((LPCTSTR)m_strAttachment);
mail.send();
std::string strCode = mail.response();
2、Windows MAPI
微軟已經為Windows系統開發者提供了SMTP協議的開發介面——MAPI(Messaging Application Progrmming Interface)。MAPI還是比較復雜的,我們如果只發送郵件的話,只用其中的Simple MAPI就足夠了,用起來十分簡單。Simple MAPI提供了一組API函數以及相關結構定義,只要在代碼中包含mapi.h頭文件即可。但是要想應用MAPI,必須要有Windows郵件系統支持,如安裝Outlook等應用軟體,還要在其中配置好profile。
開發步驟為:載入mapi32.dll庫 —> 通過GetProcAddress函數得到API函數地址 —> 設置MapiMessage等結構體參數 —> 調用MAPISendMail函數發送郵件。
由於MAPI開發中的諸多限制,我們應用起來不是很方便,有興趣的可以研究demo中的代碼。
3、free libsmtp (http://sourceforge.net/projects/freelibsmtp/)
free libsmtp也是一個開源C++庫,從封裝的結構看它提供了兩個類,比jwSMTP要復雜,面向對象的效果不是太理想。它最大的缺陷就是還沒有支持附件 功能,我懷疑可能是我沒找到更新的版本,但是sourcesforge上確實沒有。它的特色是提供了一個相應的異常類,支持異常使得代碼用起來更加安全。
以下是應用代碼:
try
{
mail::Smtp smtp((LPCTSTR)m_strServer, 25, strName, (LPCTSTR)m_strFromPassword);
mail::Mail email((LPCTSTR)m_strFormUser, (LPCTSTR)m_strToUser);
email.setSubject((LPCTSTR)m_strSubject);
email.setMessage((LPCTSTR)m_strContent);
smtp.sendMail(email);
}
catch (mail::Exception& e)
{
printf(e.why().c_str());
return ;
}
4、SMailer (http://morningspace.51.net/resource/SMailer.php)
這個是國內ITer寫的封裝類,用起來還不錯。但是跟free libsmtp一樣,封裝性做的不是太好,使用不太方便;也支持異常。
以下為應用代碼:
MUtils::WinSockHelper wshelper;
SMailer::MailInfo info;
info.setSenderName((LPCTSTR)m_strFormUser);
info.setSenderAddress((LPCTSTR)m_strFormUser);
info.addReceiver((LPCTSTR)m_strToUser, (LPCTSTR)m_strToUser);
info.setSubject((LPCTSTR)m_strSubject);
info.setPriority(SMailer::Priority::normal);
info.addMimeContent(&SMailer::TextPlainContent((LPCTSTR)m_strContent));
info.addMimeContent(&SMailer::AppOctStrmContent((LPCTSTR)m_strAttachment));
㈣ 怎樣根據堆棧信息查到DLL的出錯位置
現在是更深入地進行探討的時候了。在對託管代碼進行 P/INVOKE 調用時,DLLIMPORTATTRIBUTE 類型扮演著重要的角色。DLLIMPORTATTRIBUTE 的主要作用是給 CLR 指示哪個 DLL 導出您想要調用的函數。相關 DLL 的名稱被作為一個構造函數參數傳遞給 DLLIMPORTATTRIBUTE。
如果您無法肯定哪個 DLL 定義了您要使用的 WINDOWS API 函數,PLATFORM SDK 文檔將為您提供最好的幫助資源。在 WINDOWS API 函數主題文字臨近結尾的位置,SDK 文檔指定了 C 應用程序要使用該函數必須鏈接的 .LIB 文件。在幾乎所有的情況下,該 .LIB 文件具有與定義該函數的系統 DLL 文件相同的名稱。例如,如果該函數需要 C 應用程序鏈接到 KERNEL32.LIB,則該函數就定義在 KERNEL32.DLL 中。您可以在 MESSAGEBEEP 中找到有關 MESSAGEBEEP 的 PLATFORM SDK 文檔主題。在該主題結尾處,您會注意到它指出庫文件是 USER32.LIB;這表明 MESSAGEBEEP 是從 USER32.DLL 中導出的。
可選的 DLLIMPORTATTRIBUTE 屬性
除了指出宿主 DLL 外,DLLIMPORTATTRIBUTE 還包含了一些可選屬性,其中四個特別有趣:ENTRYPOINT、CHARSET、SETLASTERROR 和 CALLINGCONVENTION。
ENTRYPOINT 在不希望外部託管方法具有與 DLL 導出相同的名稱的情況下,可以設置該屬性來指示導出的 DLL 函數的入口點名稱。當您定義兩個調用相同非託管函數的外部方法時,這特別有用。另外,在 WINDOWS 中還可以通過它們的序號值綁定到導出的 DLL 函數。如果您需要這樣做,則諸如「#1」或「#129」的 ENTRYPOINT 值指示 DLL 中非託管函數的序號值而不是函數名。
CHARSET 對於字元集,並非所有版本的 WINDOWS 都是同樣創建的。WINDOWS 9X 系列產品缺少重要的 UNICODE 支持,而 WINDOWS NT 和 WINDOWS CE 系列則一開始就使用 UNICODE。在這些操作系統上運行的 CLR 將UNICODE 用於 STRING 和 CHAR 數據的內部表示。但也不必擔心 — 當調用 WINDOWS 9X API 函數時,CLR 會自動進行必要的轉換,將其從 UNICODE轉換為 ANSI。
如果 DLL 函數不以任何方式處理文本,則可以忽略 DLLIMPORTATTRIBUTE 的 CHARSET 屬性。然而,當 CHAR 或 STRING 數據是等式的一部分時,應該將 CHARSET 屬性設置為 CHARSET.AUTO。這樣可以使 CLR 根據宿主 OS 使用適當的字元集。如果沒有顯式地設置 CHARSET 屬性,則其默認值為 CHARSET.ANSI。這個默認值是有缺點的,因為對於在 WINDOWS 2000、WINDOWS XP 和 WINDOWS NT® 上進行的 INTEROP 調用,它會消極地影響文本參數封送處理的性能。
應該顯式地選擇 CHARSET.ANSI 或 CHARSET.UNICODE 的 CHARSET 值而不是使用 CHARSET.AUTO 的唯一情況是:您顯式地指定了一個導出函數,而該函數特定於這兩種 WIN32 OS 中的某一種。READDIRECTORYCHANGESW API 函數就是這樣的一個例子,它只存在於基於 WINDOWS NT 的操作系統中,並且只支持 UNICODE;在這種情況下,您應該顯式地使用 CHARSET.UNICODE。
有時,WINDOWS API 是否有字元集關系並不明顯。一種決不會有錯的確認方法是在 PLATFORM SDK 中檢查該函數的 C 語言頭文件。(如果您無法肯定要看哪個頭文件,則可以查看 PLATFORM SDK 文檔中列出的每個 API 函數的頭文件。)如果您發現該 API 函數確實定義為一個映射到以 A 或 W 結尾的函數名的宏,則字元集與您嘗試調用的函數有關系。WINDOWS API 函數的一個例子是在 WINUSER.H 中聲明的 GETMESSAGE API,您也許會驚訝地發現它有 A 和 W 兩種版本。
SETLASTERROR 錯誤處理非常重要,但在編程時經常被遺忘。當您進行 P/INVOKE 調用時,也會面臨其他的挑戰 — 處理託管代碼中 WINDOWS API 錯誤處理和異常之間的區別。 可以給您一點建議。
如果您正在使用 P/INVOKE 調用 WINDOWS API 函數,而對於該函數,您使用 GETLASTERROR 來查找擴展的錯誤信息,則應該在外部方法的 DLLIMPORTATTRIBUTE 中將 SETLASTERROR 屬性設置為 TRUE。這適用於大多數外部方法。
這會導致 CLR 在每次調用外部方法之後緩存由 API 函數設置的錯誤。然後,在包裝方法中,可以通過調用類庫的 SYSTEM.RUNTIME.INTEROPSERVICES.MARSHAL 類型中定義的 MARSHAL.GETLASTWIN32ERROR 方法來獲取緩存的錯誤值。 的建議是檢查這些期望來自 API 函數的錯誤值,並為這些值引發一個可感知的異常。對於其他所有失敗情況(包括根本就沒意料到的失敗情況),則引發在 SYSTEM.COMPONENTMODEL 命名空間中定義的 WIN32EXCEPTION,並將 MARSHAL.GETLASTWIN32ERROR 返回的值傳遞給它。如果您回頭看一下圖 1 中的代碼,您會看到 在 EXTERN MESSAGEBEEP 方法的公共包裝中就採用了這種方法。
CALLINGCONVENTION 將在此介紹的最後也可能是最不重要的一個 DLLIMPORTATTRIBUTE 屬性是 CALLINGCONVENTION。通過此屬性,可以給 CLR 指示應該將哪種函數調用約定用於堆棧中的參數。CALLINGCONVENTION.WINAPI 的默認值是最好的選擇,它在大多數情況下都可行。然而,如果該調用不起作用,則可以檢查 PLATFORM SDK 中的聲明頭文件,看看您調用的 API 函數是否是一個不符合調用約定標準的異常 API。
通常,本機函數(例如 WINDOWS API 函數或 C- 運行時 DLL 函數)的調用約定描述了如何將參數推入線程堆棧或從線程堆棧中清除。大多數 WINDOWS API 函數都是首先將函數的最後一個參數推入堆棧,然後由被調用的函數負責清理該堆棧。相反,許多 C-運行時 DLL 函數都被定義為按照方法參數在方法簽名中出現的順序將其推入堆棧,將堆棧清理工作交給調用者。
幸運的是,要讓 P/INVOKE 調用工作只需要讓外圍設備理解調用約定即可。通常,從默認值 CALLINGCONVENTION.WINAPI 開始是最好的選擇。然後,在 C 運行時 DLL 函數和少數函數中,可能需要將約定更改為 CALLINGCONVENTION.CDECL。
㈤ 打開電腦網頁會彈出「堆棧溢出」,這是什麼問題,怎麼解決求大神解答,謝了!
這就是溢出漏洞
本詞條缺少信息欄、名片圖,補充相關內容使詞條更完整,還能快速升級,趕緊來編輯吧!
溢出漏洞是一種計算機程序的可更正性缺陷。溢出漏洞的全名:緩沖區溢出漏洞 因為它是在程序執行的時候在緩沖區執行的錯誤代碼,所以叫緩沖區溢出漏洞。
目錄
1簡介
2何謂溢出漏洞
▪ 溢出原理
▪ 本地溢出
▪ 遠程溢出
3相關資料
▪ 在程序的地址空間里安排適當的代碼
▪ 控製程序轉移到攻擊代碼的形式
▪ 植入綜合代碼和流程式控制制
1簡介編輯
它一般是由於編程人員的疏忽造成的。
具體的講,溢出漏洞是由於程序中的某個或某些輸入函數(使用者輸入參數)對所接收數據的邊界驗證不嚴密而造成。
根據程序執行中堆棧調用原理,程序對超出邊界的部分如果沒有經過驗證自動去掉,那麼超出邊界的部分就會覆蓋後面的存放程序指針的數據,當執行完上面的代碼,程序會自動調用指針所指向地址的命令。
根據這個原理,惡意使用者就可以構造出溢出程序。
2何謂溢出漏洞編輯
溢出原理
其實溢出原理很簡單(我以前以為很難理解,太菜了,o(∩_∩)o…)。當然,這里為了讓大家容易理解,會引用一些程序實例(如果沒有編程基礎的,可以略過程序不看,影響不大,還是能理解的),而且說得會比較通俗和簡單,不會太深入。
從書上找來找去,終於找到一個適合的程序(汗!要找符合的程序簡單啊,但是要找特級菜鳥覺得特別簡單的程序就不多了,55~~)。大家看看下面這段程序:
#include 「stdafx.h」
#include 「string.h」
#include 「stdio.h」
char buf[255],pass[4]; /*聲明變數,讓計算機分配指定的內存*/
int main (int argc,char* argv[ ])
{
printf(「請輸入您的密碼:」); /*指定輸出的字元*/
scanf(%s,buf); /*輸入一個字元串,保存在變數buf中*/
strcpy(pass,buf); /*把字元串buf中的字元串復制到變數pass中*/
if (strcmp(pass,」wlqs」)= =0) /*比較輸入的字元串是否為密碼*/
printf (「輸入正確!」);
else printf(「輸入錯誤!);
return 0;
}
(註:「/*」中的中文是對程序的註解)
這是一段密碼驗證程序,與我們平時輸入密碼一樣,先讓用戶輸入密碼,然後在取得真正的密碼,與之對比,如果差異為0,則輸出密碼正確,否則輸出密碼錯誤。很多帳號登錄的程序都是這樣做的,看起來沒有非常合理,其實不然,它有一個致命缺陷!這個漏洞很容易就看出來了。那就是它給數據申請了4個位元組的儲存空間,但是萬一用戶輸入的數據不只4個位元組,那麼剩餘的位元組存放在哪裡?
先舉個例子,有一條一米長的木頭,有一張紅色紙條從尾巴往頭貼,上面寫有字,然後又有一張藍色紙條,上面也寫有字,要從木頭的頭往它的尾巴貼,但是貼了紅色紙條過後只剩4cm的長度,貼完後會有人讀出後面96cm的字,並且執行字條的命令,但是藍色紙條卻有10cm的長度,怎麼辦呢?只有把藍色紙條剩下的部分貼在紅色紙條上了。那麼紅色紙條的一些字就被覆蓋了。但是那個人還是會去讀那後面96cm的字,所以他就只有讀錯,前面讀的都是藍色字條的字。先前去執行的是藍色字條後面6cm的命令。
當然大家看了這個例子也不是很懂,下面來註解一下:
人——CPU
紅色字條上的字——CPU要執行的命令
4cm的長度——計算機為數據申請的內存空間
藍色字條上的字——要儲存的數據
可以看見藍色字條已經覆蓋了紅色字條上的字,然而那個人還是必須讀出後面96cm的字並執行。後面已經不是規定的命令了!他根本就不能執行,根本讀不懂!那麼他就不能執行了,並且報錯。
如圖系統只為我的密碼分配4個位元組的內存,那麼我輸入的密碼是「714718366」循環了6次的,不只4個位元組吧,其他剩下的字元將溢出!剩下的數字將佔用內存空間,那麼系統執行命令的時候將會執行佔用內存的數據,而不是執行原先寫好的命令了!這些數字系統根本就讀不懂,如何執行?那麼它只好報錯了!說此程序遇到問題需要關閉。那麼計算機上的程序將出錯而無法執行或關閉。
本地溢出
上面所說的本地計算機因數據溢出而關閉程序或無法執行就叫做本地溢出。輸入超長的數據已經把計算機要執行的代碼覆蓋掉了,可是,計算機不會管指令有沒有被更改,依舊取原先存放指令的空間里的數據來運行,取到「shujucuole!shujucuole!shujucuole!」這些不合法的溢出數據,它依舊會執行,可是在計算機里這樣的指令是非法指令,也就是不符合計算機邏輯的指令,用戶執行它的時候就會出錯,於是程序就被強行關閉了。
題外話:(想來想去,還是說一說o(∩_∩)o…我的愛好……損人利己的愛好)利用這樣的溢出漏洞可以關閉很多程序,比如各學校機房裡安裝的那些遠程教育系統,學生的計算機被教師的計算機所控制是因為學生機上安裝有一個學生端程序,教師機可以通過教師端來對學生端進行遠程式控制制,學生端沒有退出功能,學生所在的用戶組也沒有強行結束進程的許可權,當學生不想被老師控制的時候,可以打開學生端自帶的遠程消息功能,在消息里輸入很長的數據,比如幾百上千句「敢控制我!看我不宰了你!」,然後發送,就可以令學生端程序出錯而被系統強行關閉。這招對某些網吧的收費系統也有用的!^_^
遠程溢出
再舉個列子:
#include 「stdafx.h」
#include <winsock.h>
#pragma comment(lib,」ws2_32」)
int main(int argc,char* argv[ ])
{
char buf[255]=」 」,pass[4]=」 」; //聲明變數,讓計算機分配內存
//================================================================
//這節的代碼功能是初始化網路連接
//並偵聽1234埠等待連接
//沒有編程基礎的特級菜鳥可以略過不看
SOCKET sock1,sock2;
struct sockaddr_in addr1;
struct sockaddr_in addr2;
addr1 .sin_addr.s_addr=INADDR_ANY;
addr1 .sin_family=AF_INET;
addr1 .sin_port=htons(1234);
WSADATA * wsadatal=new WSADATA( );
WSAStartup(MAKEWORD(2,2),wsadatal1);
sock1=socket(AF_INET,SOCK_STREAM,0);
bind(sock1,(sockaddr *)&addr1,sizeof(struct sockaddr) );
listen(sock1,10);
int iSin=sizeof(struct sockaddr_in);
//=================================================================
if(sock2=accept(sock1,(sockaddr *)&addr2,&iSin)
{//有用戶連接進來
send(sock2,「請輸入密碼,密碼正確,則告訴你我的qq:」,36,0);
//發送提示用戶輸入密碼
if (recv(sock2,buf,255,0))
{//接受用戶發送過來的數據並保存在緩沖buf變數里
strcpy (pass,buf);//把緩沖buf變數里的數據復制到pass變數中
if(strcmp(pass,」wlqs」= =0)
//比較pass變數里的數據跟「wlqs」字元串之間的差異是否為0
{//差異為0,則說明兩者相等,密碼正確
send(sock2,」714718366」,9,0);//發送QQ號給用戶
}
else
{//否則就說明密碼錯誤
send (sock2,」密碼錯誤!」,10,0);
}
}
}
//=================[/ft]關閉網路連接並退出=======================
closesocket(sock2);
closesocket(sock1);
return 0;
}
這是一個伺服器程序,當有用戶連接的時候,它會先發送一句話,提示用戶輸入登錄密碼。其實它和前面說的本地溢出例子形似,問題也就處在把數據從緩存復制到內存的那句代碼里,如果遠程用戶輸入的密碼太長,那麼同樣出現溢出的現象。那麼程序就會出錯,服務端將被強行關閉。
比如騰訊公司的即時通訊軟體服務端程序就曾被黑客不停地攻擊導致服務端崩潰,不能正常提供服務,致使很多用戶都不能登陸,及時登陸成功也會在幾分鍾之內再次掉線,就是因為他們的服務端有這樣的漏洞存在,被別人利用了,這給他們以及他們的客戶造成了不可估計的損失。
3相關資料編輯
緩沖區溢出漏洞攻擊方式
緩沖區溢出漏洞可以使任何一個有黑客技術的人取得機器的控制權甚至是最高許可權。一般利用緩沖區溢出漏洞攻擊root程序,大都通過執行類似「exec(sh)」的執行代碼來獲得root 的shell。黑客要達到目的通常要完成兩個任務,就是在程序的地址空間里安排適當的代碼和通過適當的初始化寄存器和存儲器,讓程序跳轉到安排好的地址空間執行。
在程序的地址空間里安排適當的代碼
在程序的地址空間里安排適當的代碼往往是相對簡單的。如果要攻擊的代碼在所攻擊程序中已經存在了,那麼就簡單地對代碼傳遞一些參數,然後使程序跳轉到目標中就可以完成了。攻擊代碼要求執行「exec(『/bin/sh』)」,而在libc庫中的代碼執行「exec(arg)」,其中的「arg」是個指向字元串的指針參數,只要把傳入的參數指針修改指向「/bin/sh」,然後再跳轉到libc庫中的響應指令序列就可以了。當然,很多時候這個可能性是很小的,那麼就得用一種叫「植入法」的方式來完成了。當向要攻擊的程序里輸入一個字元串時,程序就會把這個字元串放到緩沖區里,這個字元串包含的數據是可以在這個所攻擊的目標的硬體平台上運行的指令序列。緩沖區可以設在:堆棧(自動變數)、堆(動態分配的)和靜態數據區(初始化或者未初始化的數據)等的任何地方。也可以不必為達到這個目的而溢出任何緩沖區,只要找到足夠的空間來放置這些攻擊代碼就夠了。
控製程序轉移到攻擊代碼的形式
緩沖區溢出漏洞攻擊都是在尋求改變程序的執行流程,使它跳轉到攻擊代碼,最為基本的就是溢出一個沒有檢查或者其他漏洞的緩沖區,這樣做就會擾亂程序的正常執行次序。通過溢出某緩沖區,可以改寫相近程序的空間而直接跳轉過系統對身份的驗證。原則上來講攻擊時所針對的緩沖區溢出的程序空間可為任意空間。但因不同地方的定位相異,所以也就帶出了多種轉移方式。
(1)Function Pointers(函數指針)
在程序中,「void (* foo) ( )」聲明了個返回值為「void」 Function Pointers的變數「foo」。Function Pointers可以用來定位任意地址空間,攻擊時只需要在任意空間里的Function Pointers鄰近處找到一個能夠溢出的緩沖區,然後用溢出來改變Function Pointers。當程序通過Function Pointers調用函數,程序的流程就會實現。
(2)Activation Records(激活記錄)
當一個函數調用發生時,堆棧中會留駐一個Activation Records,它包含了函數結束時返回的地址。執行溢出這些自動變數,使這個返回的地址指向攻擊代碼,再通過改變程序的返回地址。當函數調用結束時,程序就會跳轉到事先所設定的地址,而不是原來的地址。這樣的溢出方式也是較常見的。
(3)Longjmp buffers(長跳轉緩沖區)
在C語言中包含了一個簡單的檢驗/恢復系統,稱為「setjmp/longjmp」,意思是在檢驗點設定「setjmp(buffer)」,用longjmp(buffer)「來恢復檢驗點。如果攻擊時能夠進入緩沖區的空間,感覺「longjmp(buffer)」實際上是跳轉到攻擊的代碼。像Function Pointers一樣,longjmp緩沖區能夠指向任何地方,所以找到一個可供溢出的緩沖區是最先應該做的事情。
植入綜合代碼和流程式控制制
常見的溢出緩沖區攻擊類是在一個字元串里綜合了代碼植入和Activation Records。攻擊時定位在一個可供溢出的自動變數,然後向程序傳遞一個很大的字元串,在引發緩沖區溢出改變Activation Records的同時植入代碼(權因C在習慣上只為用戶和參數開辟很小的緩沖區)。植入代碼和緩沖區溢出不一定要一次性完成,可以在一個緩沖區內放置代碼(這個時候並不能溢出緩沖區),然後通過溢出另一個緩沖區來轉移程序的指針。這樣的方法一般是用於可供溢出的緩沖區不能放入全部代碼時的。如果想使用已經駐留的代碼不需要再外部植入的時候,通常必須先把代碼做為參數。在libc(熟悉C的朋友應該知道,現在幾乎所有的C程序連接都是利用它來連接的)中的一部分代碼段會執行「exec(something)」,當中的something就是參數,使用緩沖區溢出改變程序的參數,然後利用另一個緩沖區溢出使程序指針指向libc中的特定的代碼段。
程序編寫的錯誤造成網路的不安全性也應當受到重視,因為它的不安全性已被緩沖區溢出表現得淋漓盡致了。
㈥ 菜鳥請問Jboss的錯誤堆棧信息在哪裡
在Jboss下部署了公司的web app,使用時出現NullPointerException的錯誤:
JBWEB000065: HTTP Status 500 - java.lang.NullPointerException
--------------------------------------------------------------------------------
JBWEB000309: type JBWEB000067: Status report
JBWEB000068: message java.lang.NullPointerException
JBWEB000069: description JBWEB000145: The server encountered an internal error that prevented it from fulfilling this request.
㈦ 說明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以了解有關該錯誤以及代碼中導致錯
1.sqlServer用SQL身份驗證失敗的解決方法:
在開始菜單「運行」里執行
SQLServerManager.msc
打開配置管理器。
在「SQL Server 2005服務」節點看一看服務是否啟動。
在「SQL Server 2005的網路配置」節點,看一看是否啟用了TCP/IP,如果啟用了的話,雙擊TCP/IP,在「IP地址」里看一下127.0.0.1對應的「活動」值是否為「是」,如果不是「是」改成「是」之後重啟SQL Server 。 另外還要看一下是用的動態埠還是固定埠。如果安裝的不是默認實例,用得就是動態埠。
2.System.Data.SqlClient.SqlException: 在與 SQL Server 建立連接時出現與網路相關的或特定於實例的錯誤。未找到或無法訪問伺服器。請驗證實例名稱是否正確並且 SQL Server 已配置為允許遠程連接。 (provider: 命名管道提供程序, error: 40 - 無法打開到 SQL Server 的連接)技術參考 2010-01-23 14:45:46 閱讀253 評論0 字型大小:大中小 訂閱 .
在與 SQL Server 建立連接時出現與網路相關的或特定於實例的錯誤。未找到或無法訪問伺服器。請驗證實例名稱是否正確並且 SQL Server 已配置為允許遠程連接。 (provider: 命名管道提供程序, error: 40 - 無法打開到 SQL Server 的連接) 說明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以了解有關該錯誤以及代碼中導致錯誤的出處的詳細信息。 異常詳細信息: System.Data.SqlClient.SqlException: 在與 SQL Server 建立連接時出現與網路相關的或特定於實例的錯誤。未找到或無法訪問伺服器。請驗證實例名稱是否正確並且 SQL Server 已配置為允許遠程連接。 (provider: 命名管道提供程序, error: 40 - 無法打開到 SQL Server 的連接)源錯誤: de>de>行 34: using (OfficeChannelDataContext ocDc = new OfficeChannelDataContext(ConfigurationManager.ConnectionStrings["OfficeChannelConnectionString_Web"].ConnectionString)) 行 35: { 行 36: ocDc.SiteAccCount.First().AccessCount = jishu; 行 37: ocDc.SubmitChanges(); 行 38: } provider: 命名管道提供程序, error: 40 - 無法打開到SQL Server的連接
解決方法:開始->>SQLServer2005->>配置工具->>SQLServer外圍應用配置器->>服務和外圍連接的應用配置器->>點擊"遠程連接"->>本地連接和遠程連接->>同時使用TCP/IP和named Pipes->>點"確定"->>重啟SQLserver服務
㈧ 如何:查看堆棧跟蹤並定位到失敗點
在「測試結果」窗口中,右擊該測試並單擊 「查看測試結果詳細信息」。 將在主編輯窗口中打開「測試結果詳細信息」頁。「測試結果詳細信息」頁的「錯誤堆棧跟蹤」窗格將顯示堆棧跟蹤。堆棧跟蹤中的每一行也將顯示指向源代碼中的行的超鏈接。
㈨ 如何利用SAP報錯信息查找錯誤產生的原因
一般最上面main下面的為錯誤原因,可以在網上查找錯誤原因(一般常見都是許可權問題、空指針異常、Activity未定義等)。再往下找前面帶有你工程包名的那行提示,雙擊後顯示出現錯誤位置,一般雙擊看到的最上面的包名(看到多個包名提示信息時)
1、使用Eclipse的斷點,查看堆棧
2、最常用的就是LOG
log很簡單的,舉個簡單的例子:
LOGD("initHeapLocked: raw size= %d x %d", picture_width, picture_height);
LOGE("initHeapLocked: raw size= %d x %d", picture_width, picture_height);
D就是debug的意思,E就是error的意思~~
㈩ 如何在進程崩潰後列印堆棧並防止數據丟失
進程在運行過程中遇到邏輯錯誤, 比如除零, 空指針等等, 系統會觸發一個軟體中斷.
這個中斷會以信號的方式通知進程, 這些信號的默認處理方式是結束進程.
發生這種情況, 我們就認為進程崩潰了.
進程崩潰後, 我們會希望知道它是為何崩潰的, 是哪個函數, 哪行代碼引起的錯誤.
另外, 在進程退出前, 我們還希望做一些善後處理, 比如把某些數據存入資料庫, 等等.
下面, 我會介紹一些技術來達成這兩個目標.
1. 在core文件中查看堆棧信息
如果進程崩潰時, 我們能看到當時的堆棧信息, 就能很快定位到錯誤的代碼.
在 gcc 中加入 -g 選項, 可執行文件中便會包含調試信息. 進程崩潰後, 會生成一個 core 文件.
我們可以用 gdb 查看這個 core 文件, 從而知道進程崩潰時的環境.
在調試階段, core文件能給我們帶來很多便利. 但是在正式環境中, 它有很大的局限:
1. 包含調試信息的可執行文件會很大. 並且運行速度也會大幅降低.
2. 一個 core 文件常常很大, 如果進程頻繁崩潰, 硬碟資源會變得很緊張.
所以, 在正式環境中運行的程序, 不會包含調試信息.
它的core文件的大小, 我們會把它設為0, 也就是不會輸入core文件.
在這個前提下, 我們如何得到進程的堆棧信息呢?
2. 動態獲取線程的堆棧
c 語言提供了 backtrace 函數, 通過這個函數可以動態的獲取當前線程的堆棧.
要使用 backtrace 函數, 有兩點要求:
1. 程序使用的是 ELF 二進制格式.
2. 程序連接時使用了 -rdynamic 選項.
-rdynamic可用來通知鏈接器將所有符號添加到動態符號表中, 這些信息比 -g 選項的信息要少得多.
下面是將要用到的函數說明:
#include <execinfo.h>
int backtrace(void **buffer,int size);
用於獲取當前線程的調用堆棧, 獲取的信息將會被存放在buffer中, 它是一個指針列表。
參數 size 用來指定buffer中可以保存多少個void* 元素。
函數返回值是實際獲取的指針個數, 最大不超過size大小
注意: 某些編譯器的優化選項對獲取正確的調用堆棧有干擾,
另外內聯函數沒有堆棧框架; 刪除框架指針也會導致無法正確解析堆棧內容;
char ** backtrace_symbols (void *const *buffer, int size)
把從backtrace函數獲取的信息轉化為一個字元串數組.
參數buffer應該是從backtrace函數獲取的指針數組,
size是該數組中的元素個數(backtrace的返回值) ;
函數返回值是一個指向字元串數組的指針, 它的大小同buffer相同.
每個字元串包含了一個相對於buffer中對應元素的可列印信息.
它包括函數名,函數的偏移地址, 和實際的返回地址.
該函數的返回值是通過malloc函數申請的空間, 因此調用者必須使用free函數來釋放指針.
注意: 如果不能為字元串獲取足夠的空間, 函數的返回值將會為NULL.
void backtrace_symbols_fd (void *const *buffer, int size, int fd)
與backtrace_symbols 函數具有相同的功能,
不同的是它不會給調用者返回字元串數組, 而是將結果寫入文件描述符為fd的文件中,每個函數對應一行.
3. 捕捉信號
我們希望在進程崩潰時列印堆棧, 所以我們需要捕捉到相應的信號. 方法很簡單.
#include <signal.h>
void (*signal(int signum,void(* handler)(int)))(int);
或者: typedef void(*sig_t) ( int );
sig_t signal(int signum,sig_t handler);
參數說明:
第一個參數signum指明了所要處理的信號類型,它可以是除了SIGKILL和SIGSTOP外的任何一種信號。
第二個參數handler描述了與信號關聯的動作,它可以取以下三種值:
1. 一個返回值為正數的函數的地址, 也就是我們的信號處理函數.
這個函數應有如下形式的定義: int func(int sig); sig是傳遞給它的唯一參數。
執行了signal()調用後,進程只要接收到類型為sig的信號,不管其正在執行程序的哪一部分,就立即執行func()函數。
當func()函數執行結束後,控制權返回進程被中斷的那一點繼續執行。
2. SIGIGN, 忽略該信號.
3. SIGDFL, 恢復系統對信號的默認處理。
返回值: 返回先前的信號處理函數指針,如果有錯誤則返回SIG_ERR(-1)。
注意:
當一個信號的信號處理函數執行時,如果進程又接收到了該信號,該信號會自動被儲存而不會中斷信號處理函數的執行,
直到信號處理函數執行完畢再重新調用相應的處理函數。
如果在信號處理函數執行時進程收到了其它類型的信號,該函數的執行就會被中斷。
在信號發生跳轉到自定的handler處理函數執行後,系統會自動將此處理函數換回原來系統預設的處理方式,
如果要改變此操作請改用sigaction()。
4. 實例
下面我們實際編碼, 看看具體如何在捕捉到信號後, 列印進程堆棧, 然後結束進程.
#include <iostream>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <execinfo.h>
#include <fcntl.h>
#include <map>
using namespace std;
map<int, string> SIG_LIST;
#define SET_SIG(sig) SIG_LIST[sig] = #sig;
void SetSigList(){
SIG_LIST.clear();
SET_SIG(SIGILL)//非法指令
SET_SIG(SIGBUS)//匯流排錯誤
SET_SIG(SIGFPE)//浮點異常
SET_SIG(SIGABRT)//來自abort函數的終止信號
SET_SIG(SIGSEGV)//無效的存儲器引用(段錯誤)
SET_SIG(SIGPIPE)//向一個沒有讀用戶的管道做寫操作
SET_SIG(SIGTERM)//軟體終止信號
SET_SIG(SIGSTKFLT)//協處理器上的棧故障
SET_SIG(SIGXFSZ)//文件大小超出限制
SET_SIG(SIGTRAP)//跟蹤陷阱
}
string& GetSigName(int sig){
return SIG_LIST[sig];
}
void SaveBackTrace(int sig){
//打開文件
time_t tSetTime;
time(&tSetTime);
tm* ptm = localtime(&tSetTime);
char fname[256] = {0};
sprintf(fname, "core.%d-%d-%d_%d_%d_%d",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
FILE* f = fopen(fname, "a");
if (f == NULL){
exit(1);
}
int fd = fileno(f);
//鎖定文件
flock fl;
fl.l_type = F_WRLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_pid = getpid();
fcntl(fd, F_SETLKW, &fl);
//輸出程序的絕對路徑
char buffer[4096];
memset(buffer, 0, sizeof(buffer));
int count = readlink("/proc/self/exe", buffer, sizeof(buffer));
if(count > 0){
buffer[count] = '\n';
buffer[count + 1] = 0;
fwrite(buffer, 1, count+1, f);
}
//輸出信息的時間
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Dump Time: %d-%d-%d %d:%d:%d\n",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
fwrite(buffer, 1, strlen(buffer), f);
//線程和信號
sprintf(buffer, "Curr thread: %d, Catch signal:%s\n",
pthread_self(), GetSigName(sig).c_str());
fwrite(buffer, 1, strlen(buffer), f);
//堆棧
void* DumpArray[256];
int nSize = backtrace(DumpArray, 256);
sprintf(buffer, "backtrace rank = %d\n", nSize);
fwrite(buffer, 1, strlen(buffer), f);
if (nSize > 0){
char** symbols = backtrace_symbols(DumpArray, nSize);
if (symbols != NULL){
for (int i=0; i<nSize; i++){
fwrite(symbols[i], 1, strlen(symbols[i]), f);
fwrite("\n", 1, 1, f);
}
free(symbols);
}
}
//文件解鎖後關閉, 最後終止進程
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl);
fclose(f);
exit(1);
}
void SetSigCatchFun(){
map<int, string>::iterator it;
for (it=SIG_LIST.begin(); it!=SIG_LIST.end(); it++){
signal(it->first, SaveBackTrace);
}
}
void Fun(){
int a = 0;
int b = 1 / a;
}
static void* ThreadFun(void* arg){
Fun();
return NULL;
}
int main(){
SetSigList();
SetSigCatchFun();
printf("main thread id = %d\n", (pthread_t)pthread_self());
pthread_t pid;
if (pthread_create(&pid, NULL, ThreadFun, NULL)){
exit(1);
}
printf("fun thread id = %d\n", pid);
for(;;){
sleep(1);
}
return 0;
}
文件名為 bt.cpp
編譯: g++ bt.cpp -rdynamic -I /usr/local/include -L /usr/local/lib -pthread -o bt
主線程創建了 fun 線程, fun 線程有一個除零錯誤, 系統拋出 SIGFPE 信號.
該信號使 fun 線程中斷, 我們注冊的 SaveBackTrace 函數捕獲到這個信號, 列印相關信息, 然後終止進程.
在輸出的core文件中, 我們可以看到簡單的堆棧信息.
5. 善後處理
在上面的例子中, fun 線程被 SIGFPE 中斷, 轉而執行 SaveBackTrace 函數.
此時, main 線程仍然在正常運行.
如果我們把 SaveBackTrace 函數最後的 exit(1); 替換成 for(;;)sleep(1);
main 線程就可以一直正常的運行下去.
利用這個特點, 我們可以做很多其它事情.
游戲的伺服器進程常常有這些線程:
網路線程, 資料庫線程, 業務處理線程. 引發邏輯錯誤的代碼常常位於業務處理線程.
而資料庫線程由於功能穩定, 邏輯簡單, 是十分強壯的.
那麼, 如果業務處理線程有邏輯錯誤, 我們捕捉到信號後, 可以在信號處理函數的最後,
通知資料庫線程保存游戲數據.
直到資料庫線程把游戲信息全部存入資料庫, 信號處理函數才返回.
這樣, 伺服器宕機不會導致回檔, 損失被大大降低.
要實現這個機制, 要求資料庫模塊和業務處理模塊具有低耦合度.
當然, 實際應用的時候, 還有許多細節要考慮.
比如, 業務處理線程正在處理玩家的數據, 由於發生不可預知的錯誤, 玩家的數據被損壞了, 這些玩家的數據就不應該被存入資料庫.