Chapter.10 掛科前夕?基礎(chǔ) shellcode 編寫!
翌日正午,筱懿明依然躺在床上呼呼大睡——而是因為當他被手機鈴聲吵醒準備慢悠悠地爬去上高數(shù)課時突然發(fā)現(xiàn)自己并沒有寫高數(shù)作業(yè),而高數(shù)老師又是習慣在正式開始講課前將作業(yè)清點完畢并在課堂上對沒交作業(yè)的人大肆批判一番的情緒喜怒無常的老古板——至少在筱懿明眼中是這樣,而在他醒來時距離高數(shù)課上課已經(jīng)只剩五分鐘,哪怕直接把洛青弦的作業(yè)拿過來抄一遍時間都不太來得及——當然,洛青弦早就先他一步前去教室了。
反正作業(yè)的問題似乎是沒法在上課前解決了,筱懿明索性決定睡個爽,反正在他看來少交一次作業(yè)不過就是少一點平時分而已,距離掛科似乎還有很遠的距離。而且對筱懿明來說確實也不是第一次翹課了,反正他的目標就是平平穩(wěn)穩(wěn)地本科畢業(yè)就行,和績點有關(guān)的保研出國一類的東西對他而言都沒有任何意義,課內(nèi)的東西索性就這樣爛下去也無所謂。
擺爛似乎就是這樣,剛開始翹課還有點戰(zhàn)戰(zhàn)兢兢生怕被老師發(fā)現(xiàn),擺到后面不去上課就和日常吃飯喝水一樣正常,偶爾有一天突發(fā)奇想要去上課反倒還感覺有點怪怪的。
但對于作為擺爛初學者的筱懿明而言,雖然他已經(jīng)充分地享受了課內(nèi)擺爛的爽感,但尚且未能掌握擺爛與完蛋之間的分界線,因此很容易擺著擺著就不知不覺把自己給擺死了——
“草,明哥你今早咋沒去上高數(shù)課,爺給你打電話也不接,這下真寄了,”
洛青弦猛地推開宿舍的大門沖了進來,只見筱懿明依舊躺在床上悠悠地打著呼嚕,仿佛沒有聽到洛青弦的呼喚。洛青弦只好走到他床邊用力地拍打著他的床板,試圖發(fā)出更大的噪音來將他喚醒。對于向來神經(jīng)衰弱的筱懿明而言效果顯著——
“哼,哼,啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊——”
筱懿明此前正在夢中與一位可愛的 JK少女共同探討著高中的理科課程,他雖然高考總分并不算低,且對于物理化學這樣的科目十分擅長,但若將這類更需要計算與邏輯思維的科目歸為“武”的話,那么那些更需要背誦大量內(nèi)容的“文”類科目對于他而言便是一場災難了——畢竟他終歸不是一個“能文能武”的全能人。在高中時期他一直沒有找到比較好的解決方案,心高氣傲的他也不愿向老師和其他同學請教學習,因此在“文”類科目上的痛點成了他高中生涯的一個遺憾。此時他終于有機會重新回到高中時期——雖然是在夢中,但總算有機會去重新學習自己所并不擅長的科目,他也愿意放下自己的身段向其他更為擅長這個方向的同學去虛心請教。而夢境的想象力終歸是要比現(xiàn)實生活大許多的,以前那些僅能以圖像與文字的形式印刷在書本上的知識終于能夠以超乎他想象的狀態(tài)進行深入的實踐學習,這又怎能不讓他感到心情舒暢無比?畢竟高中階段作為“做題家”的他,在現(xiàn)實生活當中想來是沒有這樣的機會去體會這種非凡的感受的。
但洛青弦這一拍便直接將筱懿明夢中的少女給拍得煙消云散,出現(xiàn)在他眼前的又變成了那熟悉的天花板,這叫他如何不心疼?于是乎筱懿明下意識地發(fā)出了野獸一般痛苦的哀嚎,為那曾經(jīng)短暫擁有過卻又被迫失去的美好而痛徹心扉。
“別tm叫了,明哥你這次翹課真翹出大禍了,”洛青弦扶額長嘆,正所謂“長太息以掩涕兮,哀民生之多艱”,雖然此刻他并沒有像當年的屈原那樣淚流滿面,卻也為筱懿明即將到來的悲慘命運感到悲哀,“高數(shù)老師今早發(fā)現(xiàn)你沒交作業(yè),點你名你也沒到,再加上前面有好幾次作業(yè)你也是后面才補交甚至干脆沒交的,他在課上一氣之下決定給你平時分直接清零了?!?p> “???”
這個突如其來的噩耗直接把筱懿明從尚未完全睡醒的大腦直接打入懵逼態(tài),雖然他印象中自己確乎翹的課也不少,也有那么幾次作業(yè)是沒交的,但確乎沒有想到已經(jīng)累積到了這個地步。
沒想到剛剛進入大學的第一個學期,自己就要面臨掛科的風險么?
“哼,哼,啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊——”筱懿明再一次發(fā)出了野獸一般痛苦的哀嚎,這一次倒是真正的感到痛苦了,此時的他比金木還痛,洛青弦若是沒有看過10遍東京喰種的話想來是無法理解他此刻的痛楚的,“間違っていたのは僕じゃない、この世界だ——”
“別擱這痛了,想想該咋整吧,”洛青弦無奈道,“雖然大家都知道著老師脾氣差,誰也沒想到他今天會這么生氣,今天除了你以外還有其他好幾個人也被‘宣判死刑’了,爺真無語了?!?p> 筱懿明直起身揉了揉太陽穴,現(xiàn)在的他感覺大腦一片混亂,不過他還是強行嘗試先讓自己的大腦冷靜下來,畢竟事情已經(jīng)發(fā)生了,現(xiàn)在唯有想想辦法看能否進行補救了。
但筱懿明非常明白自己的平時分估計是沒有辦法拿回來了,教他們高數(shù)的老教授雖然德高望重但性格古怪無比,課程與課堂要求幾乎比他高三時還要更加嚴格,而且決定了的事情基本上就不會更改,雖然在外人看來這似乎是對學生負責任的表現(xiàn),但對于身在局中的筱懿明而言可謂是苦不堪言——
關(guān)鍵是高中越鞭策高考分數(shù)越高,現(xiàn)在上這破高數(shù)課反而預期績點越上越低,一直都是負反饋又怎么能讓人提起心思學習呢?——當然這也只是筱懿明的偏見罷了,但對于他這樣不愿意被束縛的人而言一直被人推著前進可并不算是一件舒服的事情——但畢業(yè)證和學位證終究還是要拿的,他獨自一人又沒有任何辦法去改變現(xiàn)在的這個大局面,所以面對這令人痛苦的一切筱懿明也只好默默地忍受——雖然這本來就是他沒有好好完成作業(yè)所導致的結(jié)果,但在他看來至少懲罰不應(yīng)當那么嚴重。
不過似乎并非沒有解決方案——
“平時分 20分,期中 20分,期末 60分,現(xiàn)在高數(shù)的期中考試還沒開始,只要后面的兩場考試我都能考到 80分左右就不會掛科了”,筱懿明一邊翻身下床一邊嘆息道,“反正現(xiàn)在平時分都清零了,后面的高數(shù)課干脆都翹了算了?!?p> “上次隨堂小測你連50分都沒有,咋考 80分”洛青弦嘆息道,不同于筱懿明,洛青弦雖然編程技能還很一般,但是課內(nèi)課程還是學得不錯的,尤其是高數(shù)這門課可謂是大放異彩,被班上的同學譽為“King of Mathematics”,高數(shù)老師也讓他擔任了課代表,但查作業(yè)和簽到這種事情老教授一般都會選擇親自操刀,所以他想要利用職權(quán)幫助筱懿明也沒有辦法,“而且從下節(jié)課開始就要統(tǒng)計打卡了,總?cè)闭n數(shù)量超過一半的直接掛,考都不用考了?!?p> “md,醬紫整人?”對于筱懿明這樣的翹課專業(yè)戶而言這又是一個新的噩耗,尤其是高數(shù)課基本上都在早上的第一二節(jié)課,平常雖然作業(yè)查得嚴但不查到課率,所以筱懿明一般都是直接讓洛青弦?guī)兔Π炎鳂I(yè)給帶過去,自己則是在床上繼續(xù)呼呼大睡——畢竟他現(xiàn)在的生活作息按照時區(qū)換算基本上算是按照英國作息來的,再去上早八的話他的睡眠時間就要被干碎了——當然最簡單的做法自然是調(diào)整一下作息,可惜這對于筱懿明而言依然是一個遙不可及的目標,又或者說是不愿意去實現(xiàn)。
畢竟,只有在夜晚獨自一人的時候,他才有那種“活著”的感覺。
筱懿明坐到桌前,熟練地打開了自己的電腦,卻又盯著近乎空無一物的電腦桌面默默地看了好幾分鐘。良久,他決定還是先把高數(shù)的事情拋在腦后,畢竟既然平時分清零的結(jié)果已經(jīng)定了,現(xiàn)在再去把未完成的作業(yè)給補完也是無濟于事,不如在 GeekerCTF上繼續(xù)沖一沖。
熟練地點進平臺,這一次他點開了 Pwn方向的第二道題目,題目說明倒是比較簡短——
------
Do you know the shellcode?
------
“shellcode?啥意思,先百度一下好了?!碑吘篂g覽器不是真人,筱懿明沒有在它面前不懂裝懂的必要,既然自己確實“don't know”,那還是直接讓搜索引擎來回答更為實在。
在搜索結(jié)果頁面簡單翻了兩下之后,筱懿明很快便找到了他想要的答案——
「shellcode即一段被插入到目標進程中執(zhí)行以完成特定任務(wù)的匯編代碼,由于其任務(wù)通常是幫助黑客獲取目標主機的 shell,因此得名『shellcode』?!?p> “難道這一次這道題要我手寫一份 shellcode?還是先把題目拖到 IDA里看看是個啥情況好了。”
筱懿明將題目二進制文件拖進 IDA,這一次的題目依舊非常簡潔,在 main()函數(shù)當中便只調(diào)用了一個 vuln()函數(shù)——
------
__int64 vuln()
{
void *v0;// rsi
v0 = mmap(0LL, 0x1000uLL, 7, 34,-1, 0LL);
read(0, v0, 0x1000uLL);
return ((__int64 (*)(void))v0)();
}
------
“這代碼啥意思...”眼前的代碼比筱懿明想得更加難看懂,雖然僅僅有少量的幾行代碼,但無論是 mmap()還是 read()函數(shù)都是 POSIX標準中的系統(tǒng)調(diào)用,在 Windows操作系統(tǒng)上便沒有這一套 API,而在他以前打 OI時便僅用過標準庫的諸如 scanf、printf這樣多平臺通用的函數(shù),自然會感到非常懵逼,“先查一下...mmap好像是一個系統(tǒng)調(diào)用,和 malloc功能上似乎是一樣的?都是分配一塊動態(tài)內(nèi)存?后面這幾個參數(shù)又是什么意思...看來還是得百度...”
非常幸運的是在這個高度信息化的時代想要在互聯(lián)網(wǎng)上獲取基礎(chǔ)知識可謂是方便無比的,因此筱懿明很快便弄懂了 mmap()和 read()函數(shù)的作用,同時還明白了“文件描述符”這一概念——雖然只是知道 0、1、2分別對應(yīng)著 stdin、stdout、stderr的程度。
“mmap()參數(shù)中的 7對應(yīng) prot參數(shù),也就是‘屬性’(priority),意思就是說動態(tài)分配的這一塊內(nèi)存的屬性應(yīng)該是‘7’,而‘7’又是 4、2、1進行 OR運算的結(jié)果,也就是說這一塊內(nèi)存應(yīng)該同時具有可讀、可寫、可執(zhí)行的權(quán)限,”筱懿明一邊看著百度一邊對照著 IDA反編譯代碼思忖著,“read()函數(shù)的作用應(yīng)該就是從輸入中讀取最多 0x1000個字符到剛剛分配的那塊內(nèi)存上,最后一行代碼把這個指針轉(zhuǎn)成了一個函數(shù)指針并進行了調(diào)用,意思是將這塊內(nèi)存直接當作匯編代碼來執(zhí)行?”
隨著程序邏輯在筱懿明眼前變得清晰,他也逐漸弄明白了這道題究竟要做什么——
“看來這道題要我像一個真正的黑客那樣手寫一段 shellcode進行攻擊嗎?這種事情可真是...”
筱懿明的嘴角悄然浮現(xiàn)一絲弧度,在他的雙眸中閃爍著一絲詭異的光。
“帥得不得了呢!”
——當然耍帥除了浪費時間以外對于解題并沒有任何正面幫助,此時的筱懿明依然不知道該怎么去解這道題。
“先把 shellcode的匯編形式寫出來吧,等會再看看怎么去弄成機器碼...”
雖然筱懿明并不算是特別熟悉匯編,但是也并非毫無基礎(chǔ),初中的時候他曾經(jīng)跟著《匯編語言》一書做過幾個簡單的 x86匯編程序編寫實驗,現(xiàn)在要重新寫起匯編代碼或許需要一定時間的回憶以及額外的資料查詢,但也并非能夠稱得上是一件特別困難的事情。
“要拿到 shell其實就是要執(zhí)行‘system(“/bin/sh”)’,這個函數(shù)本質(zhì)上就是 execve(‘/bin/sh’, NULL, NULL),而 execve()其實是 Linux里的一個系統(tǒng)調(diào)用,只需要給 rax寄存器中放入對應(yīng)的系統(tǒng)調(diào)用號再執(zhí)行 syscall指令就好了,那先把‘/bin/sh’這個字符串給推到棧上吧...”
筱懿明很快便寫下了第一部分的匯編代碼:
------
xor rax, rax;
push rax;
mov rax, 0x68732f6e69622f;
push rax;
------
“還好之前看過大小端序相關(guān)的內(nèi)容,不然這往棧上寫字符串可能還得多浪費一點時間,”,筱懿明接著往下寫,“接下來要把這個字符串的地址給放到 execve()的第一個參數(shù)里...”
筱懿明突然停下了敲鍵盤的手,因為他突然意識到自己好像忽略了一件事情——
“怎么給一個函數(shù)傳遞參數(shù)呢?”
墨晚鳶
大家要認真學習不要掛科哦!筱懿明小朋友的行為可不值得大家參考呢!