1. 程式人生 > 其它 >關於 .init .fini .init_array .fini_array 日誌 2019.7.16 pwn

關於 .init .fini .init_array .fini_array 日誌 2019.7.16 pwn

查詢資料的高效性

retn 返回到棧頂地址

關於 .init .fini .init_array .fini_array
其中存放著的是在main函式執行前執行的程式碼,由__libc_start_main呼叫,(__libc_start_main在libc.so上,所以先有start()呼叫__libc_start_main,再呼叫init段的程式碼)在這段程式碼中就有我們經常使用的libc_csu的gadget

.init段:

.text:0000000000400CB0 ; __unwind {
.text:0000000000400CB0                 push    r15
.text:0000000000400CB2                 mov     r15d, edi
.text:0000000000400CB5                 push    r14
.text:0000000000400CB7                 mov     r14, rsi
.text:0000000000400CBA                 push    r13
.text:0000000000400CBC                 mov     r13, rdx
.text:0000000000400CBF                 push    r12
.text:0000000000400CC1                 lea     r12, off_6011B0   //此處將init_array(0x6011B0)上的值給r12
.text:0000000000400CC8                 push    rbp
.text:0000000000400CC9                 lea     rbp, off_6011B8   //此處將fini_array(0x6011B8)上的值給rbp
.text:0000000000400CD0                 push    rbx
.text:0000000000400CD1                 sub     rbp, r12              //rbp為init_array和fini_array的差
.text:0000000000400CD4                 xor     ebx, ebx              //rbx清零
.text:0000000000400CD6                 sar     rbp, 3                //rbp算術右移3位(地址大小),即變成init_array中有多少個地址
.text:0000000000400CDA                 sub     rsp, 8
.text:0000000000400CDE                 call    _init_proc
.text:0000000000400CE3                 test    rbp, rbp
.text:0000000000400CE6                 jz      short loc_400D06
.text:0000000000400CE8                 nop     dword ptr [rax+rax+00000000h]
.text:0000000000400CF0
.text:0000000000400CF0 loc_400CF0:                             ; CODE XREF: init+54↓j
.text:0000000000400CF0                 mov     rdx, r13        //這裡到0x400D14就是我們常用的gadget
.text:0000000000400CF3                 mov     rsi, r14
.text:0000000000400CF6                 mov     edi, r15d
.text:0000000000400CF9                 call    qword ptr [r12+rbx*8]     //call r12+rbx*8,正常執行情況下是執行init_array 中的函式
.text:0000000000400CFD                 add     rbx, 1                    //rbx算是array中的偏移
.text:0000000000400D01                 cmp     rbx, rbp                  //直到array中的所用函式執行完,才能往下走
.text:0000000000400D04                 jnz     short loc_400CF0          //沒執行完所用函式返回0x400CF0繼續執行
.text:0000000000400D06
.text:0000000000400D06 loc_400D06:                             ; CODE XREF: init+36↑j
.text:0000000000400D06                 add     rsp, 8
.text:0000000000400D0A                 pop     rbx
.text:0000000000400D0B                 pop     rbp
.text:0000000000400D0C                 pop     r12
.text:0000000000400D0E                 pop     r13
.text:0000000000400D10                 pop     r14
.text:0000000000400D12                 pop     r15
.text:0000000000400D14                 retn
.text:0000000000400D14 ; } // starts at 400CB0
.text:0000000000400D14 init            endp

.init_array

.init_array:00000000006011B0 ; Segment type: Pure data
.init_array:00000000006011B0 ; Segment permissions: Read/Write
.init_array:00000000006011B0 ; Segment alignment 'qword' can not be represented in assembly
.init_array:00000000006011B0 _init_array     segment para public 'DATA' use64
.init_array:00000000006011B0                 assume cs:_init_array
.init_array:00000000006011B0                 ;org 6011B0h
.init_array:00000000006011B0 off_6011B0      dq offset sub_400850    ; DATA XREF: LOAD:00000000004000F8↑o
.init_array:00000000006011B0                                         ; init+11↑o
.init_array:00000000006011B0 _init_array     ends

關於.fini段
我的檔案中的.fini只有已經一句程式碼:retn

.text:0000000000400D20 ; void fini(void)
.text:0000000000400D20 fini            proc near               ; DATA XREF: start+F↑o
.text:0000000000400D20 ; __unwind {
.text:0000000000400D20                 rep retn    //返回到棧頂地址
.text:0000000000400D20 ; } // starts at 400D20
.text:0000000000400D20 fini            endp

而.fini_array中的有一個函式需要執行

.fini_array:00000000006011B8 ; Segment type: Pure data
.fini_array:00000000006011B8 ; Segment permissions: Read/Write
.fini_array:00000000006011B8 ; Segment alignment 'qword' can not be represented in assembly
.fini_array:00000000006011B8 _fini_array     segment para public 'DATA' use64
.fini_array:00000000006011B8                 assume cs:_fini_array
.fini_array:00000000006011B8                 ;org 6011B8h
.fini_array:00000000006011B8 qword_6011B8    dq 400830h              ; DATA XREF: init+19↑o  //0x400830需要執行
.fini_array:00000000006011B8 _fini_array     ends

所以我猜想:會不會在__libc_start_main()中,在呼叫.fini段前,.fini_array中的函式就已經入棧了?這個猜想也和前面題目在棧中一個情況(在棧上修改.fini_array push在棧上的地址為 main的地址,從而實現在程式main結束之後可以再執行一次的效果)相符合。
問題是:不知道怎麼找到這個.fini_array在棧上的值

彙編

LEA
LEA r16,m
8D /r 不影響標誌位
將源運算元的有效地址送 r16
LEA r32,m
將源運算元的有效地址送 r32

c語言

atol(): 把字串轉換成長整型數用 法: long atol(const char *nptr); 返回長整型
atoll(): 把字串轉換成長長整型數用 法: long long atol(const char *nptr); 返回長長整型
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ; 返回真實讀取的項數,count是最多讀取的項數

大多數題目的setbuf()/setvbuf()函式的作用是用來關閉I/O緩衝區,本題沒有關閉緩衝區,函式執行開始階段在fgets()函式以及printf()函式執行的時候,會malloc()兩塊記憶體區域。

震驚!

ida pro居然把我一個全域性變數識別成了區域性變數
然後在函式中將原本應該是全域性變數的s,寫成了 ::s ,我佛了