1 .text:0000000000400840 ; =============== S U B R O U T I N E ======================================= 2 .text:0000000000400840 3 .text:0000000000400840 4 .text:0000000000400840 public __libc_csu_init 5 .text:0000000000400840 __libc_csu_init proc near ; DATA XREF: _start+16o 6 .text:0000000000400840 push r15 7 .text:0000000000400842 mov r15d, edi 8 .text:0000000000400845 push r14 9 .text:0000000000400847 mov r14, rsi 10 .text:000000000040084A push r13 11 .text:000000000040084C mov r13, rdx 12 .text:000000000040084F push r12 13 .text:0000000000400851 lea r12, __frame_dummy_init_array_entry 14 .text:0000000000400858 push rbp 15 .text:0000000000400859 lea rbp, __do_global_dtors_aux_fini_array_entry 16 .text:0000000000400860 push rbx 17 .text:0000000000400861 sub rbp, r12 18 .text:0000000000400864 xor ebx, ebx 19 .text:0000000000400866 sar rbp, 3 20 .text:000000000040086A sub rsp, 8 21 .text:000000000040086E call _init_proc 22 .text:0000000000400873 test rbp, rbp 23 .text:0000000000400876 jz short loc_400896 24 .text:0000000000400878 nop dword ptr [rax+rax+00000000h] 25 .text:0000000000400880 26 .text:0000000000400880 loc_400880: ; CODE XREF: __libc_csu_init+54j 27 .text:0000000000400880 mov rdx, r13 28 .text:0000000000400883 mov rsi, r14 29 .text:0000000000400886 mov edi, r15d 30 .text:0000000000400889 call qword ptr [r12+rbx*8] 31 .text:000000000040088D add rbx, 1 32 .text:0000000000400891 cmp rbx, rbp 33 .text:0000000000400894 jnz short loc_400880 34 .text:0000000000400896 35 .text:0000000000400896 loc_400896: ; CODE XREF: __libc_csu_init+36j 36 .text:0000000000400896 add rsp, 8 37 .text:000000000040089A pop rbx 38 .text:000000000040089B pop rbp 39 .text:000000000040089C pop r12 40 .text:000000000040089E pop r13 41 .text:00000000004008A0 pop r14 42 .text:00000000004008A2 pop r15 43 .text:00000000004008A4 retn 44 .text:00000000004008A4 __libc_csu_init endp 45 .text:00000000004008A4 46 .text:00000000004008A4 ; ---------------------------------------------------------------------------
x64中的前六個參數依次保存在RDI, RSI, RDX, RCX, R8和 R9中
r13 =rdx=arg3
r14 =rsi=arg2
r15d=edi=arg1
r12= call address
這段gadgets用於在X64下進行rop,根本原因是X64使用寄存器傳參無法直接用棧進行rop。具體用法如下:
分為兩部分使用
1.執行gad1
.text:000000000040089A pop rbx 必須為0
.text:000000000040089B pop rbp 必須為1
.text:000000000040089C pop r12 call!!!!
.text:000000000040089E pop r13 arg3
.text:00000000004008A0 pop r14 arg2
.text:00000000004008A2 pop r15 arg1
.text:00000000004008A4 retn ——> to gad2
2.再執行gad2
.text:0000000000400880 mov rdx, r13
.text:0000000000400883 mov rsi, r14
.text:0000000000400886 mov edi, r15d
.text:0000000000400889 call qword ptr [r12+rbx*8] call!!!
.text:000000000040088D add rbx, 1
.text:0000000000400891 cmp rbx, rbp
.text:0000000000400894 jnz short loc_400880
.text:0000000000400896 add rsp, 8
.text:000000000040089A pop rbx
.text:000000000040089B pop rbp
.text:000000000040089C pop r12
.text:000000000040089E pop r13
.text:00000000004008A0 pop r14
.text:00000000004008A2 pop r15
.text:00000000004008A4 retn ——> 構造一些墊板(7*8=56byte)就返回了
此外還有一個老司機才知道的x64 gadgets,就是 pop rdi,ret的gadgets。這個gadgets還是在這里,但是是由opcode錯位產生的。
如上的例子中4008A2、4008A4兩句的字節碼如下
0x41 0x5f 0xc3
意思是pop r15,ret,但是恰好pop rdi,ret的opcode如下
0x5f 0xc3
因此如果我們指向0x4008A3就可以獲得pop rdi,ret的opcode,從而對於單參數函數可以直接獲得執行
與此類似的,還有0x4008A1處的 pop rsi,pop r15,ret
那么這個有什么用呢?我們知道x64傳參順序是rdi,rsi,rdx,rcx。
所以rsi是第二個參數,我們可以在rop中配合pop rdi,ret來使用pop rsi,pop r15,ret,這樣就可以輕松的調用2個參數的函數。
綜上,我們介紹了x64下利用通用gadgets調用一個參數、兩個參數、三個參數函數的方法。