【CTF】关于 .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 ,我佛了

posted @ 2022-04-20 22:16  Robinbin  阅读(205)  评论(0编辑  收藏  举报