南京大學計算機基礎(四)踩坑筆記

muyiGin發表於2024-08-11

第六週 緩衝區溢位章節

bang問題:

  • 每次輸入的id將影響getbuf中的堆疊位置,用-u 12的ebp和-u 123的ebp位置就不一樣。
  • 注意彙編程式碼中不能出現a0(代表換行符),如果地址有a0就將它隨便改改就行了(a0改為a8-0x8)。
    a0改為a8-0x8
  • 注意gdb如果不能重定向,可能是因為你修改了gdbinit:https://stackoverflow.com/questions/78832654/why-my-gdb-cant-read-the-file-by-stdin-very-weird?noredirect=1#comment138988527_78832654

rumble問題:
仔細分析彙編和棧的呼叫,這道題挺難的!【搞了我3個小時,真的別隻用gdb,用ida靜態結合gdb動態才是正解。】

  • 用ida標一標,其中的write_here是為了隨機地址防止你直接push的。write_here儲存的字串是你大寫的cookie值,比如我-u 1234的cookie是0x6eecf91d,那麼這裡就是"6EECF91D"。
  • 然後注意的是memcmp比較的是地址,所以你getbuf中應該push一個地址。
  • 緩衝區的輸入應該長成這樣,注意到我的"6EECF91D"的十六進位制是0x43454536 0x44313946【注意要顛倒過來】。
  • 然後push %esp表示當前地址。
  • 注意到棧幀中第一個引數是$ebp+8,所以你要壓入一個“返回地址”,我這裡壓的是0x11111111佔位。

Boom問題:
這個最簡單了,注意到舊ebp覆蓋便會自動返回正確ebp了。
如果你想試試別的方法,可以用push 舊ebp,然後將ebp指向當前esp,然後leave ret.
為什麼會有第二種方法呢?它能多考驗一下你對棧幀的理解【滑稽🤪】【好吧,其實一開始沒想到可以直接覆蓋ebp...】

KABOOM問題
首先要了解以下概念,csdn裡面有幾個csapp的講解好像都是錯的:

  • .text程式碼段不可編輯【所有有.plt】,所以返回地址一定是固定的。
  • 這個問題是“每次呼叫test時將棧隨機增長”,所以test棧幀和getbuf棧幀之間的距離仍然是固定的【試想一下如果改成每呼叫一個函式都隨機增長🤪】
  • getbuf棧幀的舊ebp會被覆蓋,但是esp和ebp位置也能被推匯出來:
    1. 當leave的時候,esp+4
    2. 當ret的時候,esp+4
    3. 所以如果我getbuf中ebp和舊ebp距離是48,那麼只需要esp+40就可以。
  • 因為getbufn走到ret的時候,我們修改過的返回地址並不確定,所以我們需要nop-sledge,也就是用nop一路滑一直滑倒我們的惡意程式碼:
  • 有些博主都講錯了,並不是跳轉到緩衝區開拓的最大起始地址,而是應該最大起始地址加一個數,保證能跳到nop雪橇裡面【比如我這裡0x556839e1是buf起始地址,我的buf陣列長度為735位元組】:

    最後來個nice job 獎勵自己凌晨三點還在學習我最喜歡的計算機~~~
    真好玩啊,我對逆向挺感興趣的~~~
    【明天有討厭的數學考試,但是我什麼都不會,因為我只有考試才去上課,其他時間都狠狠地翹了......所以明天一天肯定不能把剩下一點學完咯😭】

第七週 elf章節

不學了,數學沒意思,套公式算算算,太無聊了。、
開學!

phase1
跟著影片就能做,我這裡是0x79+0x60[data節位置].

phase2
phase2其實有點難,哪怕有影片跟著,因為容易出奇怪的小錯誤。
心在滴血,搞了整整兩個小時,踩坑的點在於:

  • put和strcmp都要的是char*,所以不能直接push字串(網上有教程居然直接跳到put執行,我不建議,這一章節本不應該破壞執行順序的)
  • 字串的順序問題,注意小端方式,但是在hexedit中是可以正序的(不懂的自己踩坑就知道了🤪)
  • 學號是字串,不要傳個$0x11111111
  • call的時候偏移地址是算的下一個地址,切記切記......

    如上圖,我的字串驗證是"yKSPHJa",A函式地址如果是x,call的下一條為2f,設a=x-2f那麼-a=~a+1.

    不想改了,應該是ebp,esp之類哪裡忘了還回去......

Phase3
這道題有點難,因為我對switch跳轉表不熟。
基礎知識:

  • 跳轉表在.rodata節中,然後跳轉表裡面存的是地址的偏移地址。
  • 在.o檔案中的跳轉表地址和可執行檔案連結後是不一樣的,但是相對偏移地址是一樣的。
    我儘量講清晰點:
    可以用ida的y鍵修改HexRays識別錯誤的char陣列範圍,我們可以發現這段程式碼其實相當好理解:

    然後彙編裡面發現跳轉表位於.rodata偏移0x4的地方:

    而.rodata節位於0x29c,所以跳轉表起始地址為:0x29c+0x4=0x2a0。

    現在我們就只修改第一個做個例子,本來Linkbomb輸出是:

    我們可以用gdb動態分析,發現經過-0x41過後,第一個是0x13,也就是19,那麼跳轉表中是四位元組地址,那麼19*4=76=0x4c,那麼跳轉表起始地址加上0x4c:0x2a0+0x4c=0x2e4,我們可以用hexedit發現0x2e4的地址是:0x000000a5

    說明要跳轉到這個偏移.text節的a5位置(我的.text節是0x34):

    那麼0x34+0xa5=0xd9,在hexedit的對應位置即可找到同樣的位元組碼:

    我將38修改為31,那麼再linkbomb應該是1開頭(和先前不一樣):

    成功(只看第一個)!:

Phase4:
我認為最難的一章,為什麼?因為你一開始不能用gdb動態除錯,在ida中也很難靜態分析。你必須對重定位表有所瞭解,然而,mooc南京大學的老師似乎並沒有怎麼介紹重定位表.....
我畫張圖幫助大家理解(應該沒人比我的這個更細了吧?):

所以從編譯到連結的整個流程是這樣的:

  1. 首先,編譯器將人能看懂的預處理.i檔案編譯成.s彙編檔案。當它看到一個變數(準確來說應該是符號,比如函式名也叫符號啊),他就把它丟到對應的節裡面,用symtab記錄位置【比如上文的0x0320+0x20】
  2. 然後呢,你光記錄了位置,但是以後怎麼知道哪裡需要它呢?於是就把具體位置丟到.rel節中。
  3. 接著,該後人“連結器”登場了。它先逐個掃描檔案的symtab,將所有在該檔案中未定義的符號都放入Undefined(未定義)中,將所有定義了的符號放入Defined中。
  4. 然後就是消消樂的時間,如果最終U集合還有剩下的,就會報錯!熟悉的ld開頭報錯!
  5. 如果全部符號都有定義,那就開始重定位吧!查閱.rel節,由於.text節也被整合在一起了,所以也要計算相關位置,最後把最終位置填在程式碼空缺的地方

我可講的真好🤪

於是,我沒做出來,我也不知道喵的哪裡錯了,搞了我一晚上了,心太累了。
不知道哪個填錯了,好煩,越做不出來越煩,根本不想分析程式碼.....
放個連結,未來我想做了再回來做......

強行完結!!!!撒花()

相關文章